+ = $this->Text->autoParagraph(h(${{ singularVar }}->{{ field }})); ?> ++
diff --git a/.gitignore b/.gitignore index c6597e4ea..f4178924c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,52 @@ +# CakePHP 4 +# User specific & automatically generated files # +################################################# +/build +/dist +/tags +/composer.lock +/phpunit.xml +/vendor +/vendors +/composer.phar +*.mo +debug.log +error.log +.phpunit.result.cache + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +Thumbs.db + +# Tool specific files # +####################### +# vim +*~ +*.swp +*.swo +# sublime text & textmate +*.sublime-* +*.stTheme.cache +*.tmlanguage.cache +*.tmPreferences.cache +# Eclipse +.settings/* +/.project +/.buildpath +# JetBrains, aka PHPStorm, IntelliJ IDEA +.idea/* +# NetBeans +nbproject/* +# Visual Studio Code +.vscode + # CakePHP 3 /vendor/* diff --git a/app/composer.json b/app/composer.json index 97b9d5208..4f2ec1d9b 100644 --- a/app/composer.json +++ b/app/composer.json @@ -5,19 +5,21 @@ "type": "project", "license": "MIT", "require": { - "php": ">=5.6", + "php": ">=7.2", "adodb/adodb-php": "^5.20", - "cakephp/cakephp": "3.10.*", - "cakephp/migrations": "^1.0", + "cakephp/cakephp": "4.0.*", + "cakephp/migrations": "^3.0.0", "cakephp/plugin-installer": "^1.0", "doctrine/dbal": "^2.9", "josegonzalez/dotenv": "2.*", "mobiledetect/mobiledetectlib": "2.*" }, "require-dev": { - "cakephp/bake": "^1.1", + "cakephp/bake": "^2.0.10", "cakephp/cakephp-codesniffer": "^3.0", - "cakephp/debug_kit": "^3.6", + "cakephp/debug_kit": "^4.0.6", + "phpstan/phpstan": "^0.12.18", + "phpunit/phpunit": "^8.0", "psy/psysh": "@stable" }, "suggest": { @@ -40,7 +42,6 @@ "scripts": { "post-install-cmd": "App\\Console\\Installer::postInstall", "post-create-project-cmd": "App\\Console\\Installer::postInstall", - "post-autoload-dump": "Cake\\Composer\\Installer\\PluginInstaller::postAutoloadDump", "check": [ "@test", "@cs-check" diff --git a/app/composer.lock b/app/composer.lock index a107ccd9f..891a7509e 100644 --- a/app/composer.lock +++ b/app/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "18bc2276e368023a5a640a707d6102dc", + "content-hash": "fd5988586d5d9d91062852addfcc0c0d", "packages": [ { "name": "adodb/adodb-php", @@ -119,41 +119,45 @@ }, { "name": "cakephp/cakephp", - "version": "3.10.0", + "version": "4.0.10", "source": { "type": "git", "url": "https://github.com/cakephp/cakephp.git", - "reference": "084963bd27984e50174fadcbdee91048112231a0" + "reference": "5c6d72bc9bb1be6eec1b00b3930f9e5054ee6d76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/cakephp/zipball/084963bd27984e50174fadcbdee91048112231a0", - "reference": "084963bd27984e50174fadcbdee91048112231a0", + "url": "https://api.github.com/repos/cakephp/cakephp/zipball/5c6d72bc9bb1be6eec1b00b3930f9e5054ee6d76", + "reference": "5c6d72bc9bb1be6eec1b00b3930f9e5054ee6d76", "shasum": "" }, "require": { "aura/intl": "^3.0.0", - "cakephp/chronos": "^1.0.1", + "cakephp/chronos": "^2.0", + "composer/ca-bundle": "^1.2", "ext-intl": "*", + "ext-json": "*", "ext-mbstring": "*", - "laminas/laminas-diactoros": "^1.4.0", - "paragonie/random_compat": "^1.4|^2.0|9.99.99", - "php": ">=5.6.0,<8.0.0", + "laminas/laminas-diactoros": "^2.2.2", + "laminas/laminas-httphandlerrunner": "^1.1", + "php": ">=7.2.0", + "psr/http-client": "^1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", "psr/log": "^1.0.0", "psr/simple-cache": "^1.0.0" }, - "conflict": { - "phpunit/phpunit": "<5.7" - }, "replace": { "cakephp/cache": "self.version", "cakephp/collection": "self.version", + "cakephp/console": "self.version", "cakephp/core": "self.version", "cakephp/database": "self.version", "cakephp/datasource": "self.version", "cakephp/event": "self.version", "cakephp/filesystem": "self.version", "cakephp/form": "self.version", + "cakephp/http": "self.version", "cakephp/i18n": "self.version", "cakephp/log": "self.version", "cakephp/orm": "self.version", @@ -161,10 +165,10 @@ "cakephp/validation": "self.version" }, "require-dev": { - "cakephp/cakephp-codesniffer": "^3.0", - "cakephp/chronos": "^1.2.1", - "paragonie/csp-builder": "^1.4|^2.3", - "phpunit/phpunit": "^5.7.14|^6.0" + "cakephp/cakephp-codesniffer": "^4.0", + "mikey179/vfsstream": "^1.6", + "paragonie/csp-builder": "^2.3", + "phpunit/phpunit": "~8.5.0" }, "suggest": { "ext-curl": "To enable more efficient network calls in Http\\Client.", @@ -213,30 +217,28 @@ "issues": "https://github.com/cakephp/cakephp/issues", "source": "https://github.com/cakephp/cakephp" }, - "time": "2021-06-20T01:14:53+00:00" + "time": "2020-12-08T03:04:12+00:00" }, { "name": "cakephp/chronos", - "version": "1.3.0", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/cakephp/chronos.git", - "reference": "ba2bab98849e7bf29b02dd634ada49ab36472959" + "reference": "556e14da67307ffc2e68beeb7df0694dc8d1207d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/chronos/zipball/ba2bab98849e7bf29b02dd634ada49ab36472959", - "reference": "ba2bab98849e7bf29b02dd634ada49ab36472959", + "url": "https://api.github.com/repos/cakephp/chronos/zipball/556e14da67307ffc2e68beeb7df0694dc8d1207d", + "reference": "556e14da67307ffc2e68beeb7df0694dc8d1207d", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.2" }, "require-dev": { - "athletic/athletic": "~0.1", - "cakephp/cakephp-codesniffer": "^3.0", - "phpbench/phpbench": "@dev", - "phpunit/phpunit": "<6.0 || ^7.0" + "cakephp/cakephp-codesniffer": "^4.5", + "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", "autoload": { @@ -274,41 +276,42 @@ "issues": "https://github.com/cakephp/chronos/issues", "source": "https://github.com/cakephp/chronos" }, - "time": "2019-11-30T02:33:19+00:00" + "time": "2021-06-17T13:49:10+00:00" }, { "name": "cakephp/migrations", - "version": "1.8.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/cakephp/migrations.git", - "reference": "cd65daa9fae933bc0ccc69d5b5d92460375da9e2" + "reference": "d22737c31243db89774abfe6a077d254c0eae75a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/migrations/zipball/cd65daa9fae933bc0ccc69d5b5d92460375da9e2", - "reference": "cd65daa9fae933bc0ccc69d5b5d92460375da9e2", + "url": "https://api.github.com/repos/cakephp/migrations/zipball/d22737c31243db89774abfe6a077d254c0eae75a", + "reference": "d22737c31243db89774abfe6a077d254c0eae75a", "shasum": "" }, "require": { - "cakephp/cache": "^3.6.0", - "cakephp/orm": "^3.6.0", - "php": ">=5.6.0", - "robmorgan/phinx": "0.8.1" + "cakephp/cache": "^4.0.5", + "cakephp/orm": "^4.0.5", + "php": ">=7.2.0", + "robmorgan/phinx": "^0.12" }, "require-dev": { - "cakephp/bake": "^1.7.0", - "cakephp/cakephp": "^3.6.0", - "cakephp/cakephp-codesniffer": "^3.0", - "phpunit/phpunit": "^5.7.14" + "cakephp/bake": "^2.1.0", + "cakephp/cakephp": "^4.0.5", + "cakephp/cakephp-codesniffer": "~4.1.0", + "phpunit/phpunit": "~8.5.0" }, "suggest": { - "cakephp/bake": "Required if you want to generate migrations." + "cakephp/bake": "If you want to generate migrations.", + "dereuromark/cakephp-ide-helper": "If you want to have IDE suggest/autocomplete when creating migrations." }, "type": "cakephp-plugin", "autoload": { "psr-4": { - "Migrations\\": "src" + "Migrations\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -321,19 +324,19 @@ "homepage": "https://github.com/cakephp/migrations/graphs/contributors" } ], - "description": "Database Migration plugin for CakePHP 3.0 based on Phinx", + "description": "Database Migration plugin for CakePHP based on Phinx", "homepage": "https://github.com/cakephp/migrations", "keywords": [ "cakephp", "migrations" ], "support": { - "forum": "http://stackoverflow.com/tags/cakephp", + "forum": "https://stackoverflow.com/tags/cakephp", "irc": "irc://irc.freenode.org/cakephp", "issues": "https://github.com/cakephp/migrations/issues", "source": "https://github.com/cakephp/migrations" }, - "time": "2018-04-16T01:35:59+00:00" + "time": "2021-05-20T13:57:37+00:00" }, { "name": "cakephp/plugin-installer", @@ -384,6 +387,82 @@ }, "time": "2020-10-29T04:00:42+00:00" }, + { + "name": "composer/ca-bundle", + "version": "1.2.10", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8", + "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.2 || ^5", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/ca-bundle/issues", + "source": "https://github.com/composer/ca-bundle/tree/1.2.10" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-06-07T13:58:28+00:00" + }, { "name": "doctrine/cache", "version": "2.1.1", @@ -787,40 +866,49 @@ }, { "name": "laminas/laminas-diactoros", - "version": "1.8.7p2", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-diactoros.git", - "reference": "6991c1af7c8d2c8efee81b22ba97024781824aaa" + "reference": "8b5792b7c81465efb14780c2d4787f158bd96183" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/6991c1af7c8d2c8efee81b22ba97024781824aaa", - "reference": "6991c1af7c8d2c8efee81b22ba97024781824aaa", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/8b5792b7c81465efb14780c2d4787f158bd96183", + "reference": "8b5792b7c81465efb14780c2d4787f158bd96183", "shasum": "" }, "require": { - "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^5.6 || ^7.0", + "php": "^7.3 || ~8.0.0 || ~8.1.0", + "psr/http-factory": "^1.0", "psr/http-message": "^1.0" }, + "conflict": { + "phpspec/prophecy": "<1.9.0", + "zendframework/zend-diactoros": "*" + }, "provide": { + "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, - "replace": { - "zendframework/zend-diactoros": "~1.8.7.0" - }, "require-dev": { + "ext-curl": "*", "ext-dom": "*", + "ext-gd": "*", "ext-libxml": "*", - "laminas/laminas-coding-standard": "~1.0", - "php-http/psr7-integration-tests": "dev-master", - "phpunit/phpunit": "^5.7.16 || ^6.0.8 || ^7.2.7" + "http-interop/http-factory-tests": "^0.8.0", + "laminas/laminas-coding-standard": "~1.0.0", + "php-http/psr7-integration-tests": "^1.1", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.1", + "psalm/plugin-phpunit": "^0.14.0", + "vimeo/psalm": "^4.3" }, "type": "library", "extra": { - "branch-alias": { - "dev-release-1.8": "1.8.x-dev" + "laminas": { + "config-provider": "Laminas\\Diactoros\\ConfigProvider", + "module": "Laminas\\Diactoros" } }, "autoload": { @@ -856,6 +944,7 @@ "http", "laminas", "psr", + "psr-17", "psr-7" ], "support": { @@ -866,7 +955,84 @@ "rss": "https://github.com/laminas/laminas-diactoros/releases.atom", "source": "https://github.com/laminas/laminas-diactoros" }, - "time": "2020-03-23T15:28:28+00:00" + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2021-09-15T08:41:12+00:00" + }, + { + "name": "laminas/laminas-httphandlerrunner", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-httphandlerrunner.git", + "reference": "6a2dd33e4166469ade07ad1283b45924383b224b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-httphandlerrunner/zipball/6a2dd33e4166469ade07ad1283b45924383b224b", + "reference": "6a2dd33e4166469ade07ad1283b45924383b224b", + "shasum": "" + }, + "require": { + "laminas/laminas-zendframework-bridge": "^1.0", + "php": "^7.3 || ~8.0.0", + "psr/http-message": "^1.0", + "psr/http-message-implementation": "^1.0", + "psr/http-server-handler": "^1.0" + }, + "replace": { + "zendframework/zend-httphandlerrunner": "^1.1.0" + }, + "require-dev": { + "laminas/laminas-coding-standard": "~1.0.0", + "laminas/laminas-diactoros": "^2.1.1", + "phpunit/phpunit": "^9.3", + "psalm/plugin-phpunit": "^0.15.1", + "vimeo/psalm": "^4.6" + }, + "type": "library", + "extra": { + "laminas": { + "config-provider": "Laminas\\HttpHandlerRunner\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Laminas\\HttpHandlerRunner\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Execute PSR-15 RequestHandlerInterface instances and emit responses they generate.", + "homepage": "https://laminas.dev", + "keywords": [ + "components", + "laminas", + "mezzio", + "psr-15", + "psr-7" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-httphandlerrunner/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-httphandlerrunner/issues", + "rss": "https://github.com/laminas/laminas-httphandlerrunner/releases.atom", + "source": "https://github.com/laminas/laminas-httphandlerrunner" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2021-04-08T13:52:56+00:00" }, { "name": "laminas/laminas-zendframework-bridge", @@ -1055,71 +1221,75 @@ "time": "2021-02-19T21:22:57+00:00" }, { - "name": "paragonie/random_compat", - "version": "v9.99.99", + "name": "psr/container", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + "url": "https://github.com/php-fig/container.git", + "reference": "2ae37329ee82f91efadc282cc2d527fd6065a5ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "url": "https://api.github.com/repos/php-fig/container/zipball/2ae37329ee82f91efadc282cc2d527fd6065a5ef", + "reference": "2ae37329ee82f91efadc282cc2d527fd6065a5ef", "shasum": "" }, "require": { - "php": "^7" + "php": ">=7.2.0" }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } }, - "type": "library", "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.1" }, - "time": "2018-07-02T15:55:56+00:00" + "time": "2021-03-24T13:40:57+00:00" }, { - "name": "psr/http-message", + "name": "psr/http-client", "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" }, "type": "library", "extra": { @@ -1129,7 +1299,7 @@ }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1142,47 +1312,46 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", "keywords": [ "http", - "http-message", + "http-client", "psr", - "psr-7", - "request", - "response" + "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "source": "https://github.com/php-fig/http-client/tree/master" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2020-06-29T06:28:15+00:00" }, { - "name": "psr/log", - "version": "1.1.4", + "name": "psr/http-factory", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.0.0", + "psr/http-message": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1192,33 +1361,37 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Common interfaces for PSR-7 HTTP message factories", "keywords": [ - "log", + "factory", + "http", + "message", "psr", - "psr-3" + "psr-17", + "psr-7", + "request", + "response" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/http-factory/tree/master" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2019-04-30T12:38:16+00:00" }, { - "name": "psr/simple-cache", + "name": "psr/http-message", "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { @@ -1232,7 +1405,7 @@ }, "autoload": { "psr-4": { - "Psr\\SimpleCache\\": "src/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1245,49 +1418,48 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common interfaces for simple caching", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "cache", - "caching", + "http", + "http-message", "psr", - "psr-16", - "simple-cache" + "psr-7", + "request", + "response" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/master" + "source": "https://github.com/php-fig/http-message/tree/master" }, - "time": "2017-10-23T01:57:42+00:00" + "time": "2016-08-06T14:39:51+00:00" }, { - "name": "robmorgan/phinx", - "version": "v0.8.1", + "name": "psr/http-server-handler", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/cakephp/phinx.git", - "reference": "7a19de5bebc59321edd9613bc2a667e7f96224ec" + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/phinx/zipball/7a19de5bebc59321edd9613bc2a667e7f96224ec", - "reference": "7a19de5bebc59321edd9613bc2a667e7f96224ec", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/aff2f80e33b7f026ec96bb42f63242dc50ffcae7", + "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7", "shasum": "" }, "require": { - "php": ">=5.4", - "symfony/config": "~2.8|~3.0", - "symfony/console": "~2.8|~3.0", - "symfony/yaml": "~2.8|~3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.26|^5.0" + "php": ">=7.0", + "psr/http-message": "^1.0" }, - "bin": [ - "bin/phinx" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "Phinx\\": "src/Phinx" + "Psr\\Http\\Server\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1296,21 +1468,255 @@ ], "authors": [ { - "name": "Woody Gilk", - "email": "woody.gilk@gmail.com", - "homepage": "http://shadowhand.me", - "role": "Developer" - }, - { - "name": "Rob Morgan", - "email": "robbym@gmail.com", - "homepage": "https://robmorgan.id.au", - "role": "Lead Developer" - }, - { - "name": "Richard Quadling", - "email": "rquadling@gmail.com", - "role": "Developer" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ], + "support": { + "issues": "https://github.com/php-fig/http-server-handler/issues", + "source": "https://github.com/php-fig/http-server-handler/tree/master" + }, + "time": "2018-10-30T16:46:14+00:00" + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/2296f45510945530b9dceb8bcedb5cb84d40c5f5", + "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0", + "psr/http-server-handler": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-server-middleware/issues", + "source": "https://github.com/php-fig/http-server-middleware/tree/master" + }, + "time": "2018-10-30T17:12:04+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "robmorgan/phinx", + "version": "0.12.8", + "source": { + "type": "git", + "url": "https://github.com/cakephp/phinx.git", + "reference": "d2ed1b452cc90f4cae4ea6b5976b94fb9e5ed2a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/phinx/zipball/d2ed1b452cc90f4cae4ea6b5976b94fb9e5ed2a2", + "reference": "d2ed1b452cc90f4cae4ea6b5976b94fb9e5ed2a2", + "shasum": "" + }, + "require": { + "cakephp/database": "^4.0", + "php": ">=7.2", + "psr/container": "^1.0 || ^2.0", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/console": "^3.4|^4.0|^5.0" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "^4.0", + "ext-json": "*", + "ext-pdo": "*", + "phpunit/phpunit": "^8.5|^9.3", + "sebastian/comparator": ">=1.2.3", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "ext-json": "Install if using JSON configuration format", + "ext-pdo": "PDO extension is needed", + "symfony/yaml": "Install if using YAML configuration format" + }, + "bin": [ + "bin/phinx" + ], + "type": "library", + "autoload": { + "psr-4": { + "Phinx\\": "src/Phinx/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Morgan", + "email": "robbym@gmail.com", + "homepage": "https://robmorgan.id.au", + "role": "Lead Developer" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com", + "homepage": "https://shadowhand.me", + "role": "Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Developer" + }, + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/phinx/graphs/contributors", + "role": "Developer" } ], "description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.", @@ -1324,38 +1730,41 @@ ], "support": { "issues": "https://github.com/cakephp/phinx/issues", - "source": "https://github.com/cakephp/phinx/tree/v0.8.1" + "source": "https://github.com/cakephp/phinx/tree/0.12.8" }, - "time": "2017-06-05T13:30:19+00:00" + "time": "2021-07-28T15:31:39+00:00" }, { "name": "symfony/config", - "version": "v3.4.47", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "bc6b3fd3930d4b53a60b42fe2ed6fc466b75f03f" + "reference": "4268f3059c904c61636275182707f81645517a37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/bc6b3fd3930d4b53a60b42fe2ed6fc466b75f03f", - "reference": "bc6b3fd3930d4b53a60b42fe2ed6fc466b75f03f", + "url": "https://api.github.com/repos/symfony/config/zipball/4268f3059c904c61636275182707f81645517a37", + "reference": "4268f3059c904c61636275182707f81645517a37", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/filesystem": "~2.8|~3.0|~4.0", - "symfony/polyfill-ctype": "~1.8" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22" }, "conflict": { - "symfony/dependency-injection": "<3.3", - "symfony/finder": "<3.3" + "symfony/finder": "<4.4" }, "require-dev": { - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/event-dispatcher": "~3.3|~4.0", - "symfony/finder": "~3.3|~4.0", - "symfony/yaml": "~3.0|~4.0" + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" }, "suggest": { "symfony/yaml": "To use the yaml reference dumper" @@ -1383,10 +1792,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Config Component", + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v3.4.47" + "source": "https://github.com/symfony/config/tree/v5.3.4" }, "funding": [ { @@ -1402,41 +1811,50 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2021-07-21T12:40:44+00:00" }, { "name": "symfony/console", - "version": "v3.4.47", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81" + "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81", - "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81", + "url": "https://api.github.com/repos/symfony/console/zipball/8b1008344647462ae6ec57559da166c2bfa5e16a", + "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2", + "symfony/string": "^5.1" }, "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" }, "provide": { - "psr/log-implementation": "1.0" + "psr/log-implementation": "1.0|2.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0" + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" }, "suggest": { "psr/log": "For using the console logger", @@ -1467,10 +1885,16 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Console Component", + "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], "support": { - "source": "https://github.com/symfony/console/tree/v3.4.47" + "source": "https://github.com/symfony/console/tree/v5.3.7" }, "funding": [ { @@ -1486,39 +1910,38 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2021-08-25T20:02:16+00:00" }, { - "name": "symfony/debug", - "version": "v4.4.27", + "name": "symfony/deprecation-contracts", + "version": "v2.4.0", "source": { "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "2f9160e92eb64c95da7368c867b663a8e34e980c" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/2f9160e92eb64c95da7368c867b663a8e34e980c", - "reference": "2f9160e92eb64c95da7368c867b663a8e34e980c", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", "shasum": "" }, "require": { - "php": ">=7.1.3", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "symfony/http-kernel": "<3.4" - }, - "require-dev": { - "symfony/http-kernel": "^3.4|^4.0|^5.0" + "php": ">=7.1" }, "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" }, - "exclude-from-classmap": [ - "/Tests/" + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1527,18 +1950,18 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides tools to ease debugging PHP code", + "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug/tree/v4.4.27" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" }, "funding": [ { @@ -1554,24 +1977,24 @@ "type": "tidelift" } ], - "time": "2021-07-22T07:21:39+00:00" + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/filesystem", - "version": "v4.4.27", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "517fb795794faf29086a77d99eb8f35e457837a7" + "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/517fb795794faf29086a77d99eb8f35e457837a7", - "reference": "517fb795794faf29086a77d99eb8f35e457837a7", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/343f4fe324383ca46792cae728a3b6e2f708fb32", + "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-php80": "^1.16" }, @@ -1601,7 +2024,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v4.4.27" + "source": "https://github.com/symfony/filesystem/tree/v5.3.4" }, "funding": [ { @@ -1617,7 +2040,7 @@ "type": "tidelift" } ], - "time": "2021-07-21T12:19:41+00:00" + "time": "2021-07-21T12:40:44+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1699,24 +2122,24 @@ "time": "2021-02-19T12:13:01+00:00" }, { - "name": "symfony/polyfill-mbstring", + "name": "symfony/polyfill-intl-grapheme", "version": "v1.23.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "16880ba9c5ebe3642d1995ab866db29270b36535" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6", - "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535", + "reference": "16880ba9c5ebe3642d1995ab866db29270b36535", "shasum": "" }, "require": { "php": ">=7.1" }, "suggest": { - "ext-mbstring": "For best performance" + "ext-intl": "For best performance" }, "type": "library", "extra": { @@ -1730,7 +2153,7 @@ }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" }, "files": [ "bootstrap.php" @@ -1750,17 +2173,18 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", + "grapheme", + "intl", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1" }, "funding": [ { @@ -1779,22 +2203,25 @@ "time": "2021-05-27T12:26:48+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.23.1", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be", - "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "shasum": "" }, "require": { "php": ">=7.1" }, + "suggest": { + "ext-intl": "For best performance" + }, "type": "library", "extra": { "branch-alias": { @@ -1807,7 +2234,7 @@ }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, "files": [ "bootstrap.php" @@ -1821,10 +2248,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -1834,16 +2257,18 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "intl", + "normalizer", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0" }, "funding": [ { @@ -1859,42 +2284,44 @@ "type": "tidelift" } ], - "time": "2021-07-28T13:41:28+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { - "name": "symfony/yaml", - "version": "v3.4.47", + "name": "symfony/polyfill-mbstring", + "version": "v1.23.1", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "88289caa3c166321883f67fe5130188ebbb47094" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094", - "reference": "88289caa3c166321883f67fe5130188ebbb47094", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6", + "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" + "php": ">=7.1" }, "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "ext-mbstring": "For best performance" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, "autoload": { "psr-4": { - "Symfony\\Component\\Yaml\\": "" + "Symfony\\Polyfill\\Mbstring\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1903,18 +2330,25 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Yaml Component", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], "support": { - "source": "https://github.com/symfony/yaml/tree/v3.4.47" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1" }, "funding": [ { @@ -1930,49 +2364,45 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" - } - ], - "packages-dev": [ + "time": "2021-05-27T12:26:48+00:00" + }, { - "name": "ajgl/breakpoint-twig-extension", - "version": "0.3.5", + "name": "symfony/polyfill-php73", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/ajgarlag/AjglBreakpointTwigExtension.git", - "reference": "9875feea0ac4bc3c9f308c62bae4727669d6052a" + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ajgarlag/AjglBreakpointTwigExtension/zipball/9875feea0ac4bc3c9f308c62bae4727669d6052a", - "reference": "9875feea0ac4bc3c9f308c62bae4727669d6052a", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010", + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010", "shasum": "" }, "require": { - "php": ">=5.6", - "twig/twig": "^1.34|^2.0|^3.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.18", - "symfony/framework-bundle": "^2.7|^3.4|^4.4|^5.2", - "symfony/phpunit-bridge": "^4.4|^5.2", - "symfony/twig-bundle": "^2.7|^3.4|^4.4|^5.2" - }, - "suggest": { - "ext-xdebug": "The Xdebug extension is required for the breakpoint to work", - "symfony/framework-bundle": "The framework bundle to integrate the extension into Symfony", - "symfony/twig-bundle": "The twig bundle to integrate the extension into Symfony" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.3.x-dev" + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { - "Ajgl\\Twig\\Extension\\": "src/" - } + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1980,121 +2410,161 @@ ], "authors": [ { - "name": "Antonio J. García Lagar", - "email": "aj@garcialagar.es", - "homepage": "http://aj.garcialagar.es", - "role": "developer" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Twig extension to set breakpoints", - "homepage": "https://github.com/ajgarlag/AjglBreakpointTwigExtension", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", "keywords": [ - "Xdebug", - "breakpoint", - "twig" + "compatibility", + "polyfill", + "portable", + "shim" ], "support": { - "issues": "https://github.com/ajgarlag/AjglBreakpointTwigExtension/issues", - "source": "https://github.com/ajgarlag/AjglBreakpointTwigExtension/tree/0.3.5" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0" }, - "time": "2021-02-08T10:48:05+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" }, { - "name": "aptoma/twig-markdown", - "version": "2.0.0", + "name": "symfony/polyfill-php80", + "version": "v1.23.1", "source": { "type": "git", - "url": "https://github.com/aptoma/twig-markdown.git", - "reference": "64a9c5c7418c08faf91c4410b34bdb65fb25c23d" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aptoma/twig-markdown/zipball/64a9c5c7418c08faf91c4410b34bdb65fb25c23d", - "reference": "64a9c5c7418c08faf91c4410b34bdb65fb25c23d", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be", + "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be", "shasum": "" }, "require": { - "twig/twig": "~1.12" - }, - "require-dev": { - "codeclimate/php-test-reporter": "dev-master", - "erusev/parsedown": "^1.6", - "knplabs/github-api": "~1.2", - "league/commonmark": "~0.5", - "michelf/php-markdown": "~1", - "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "~0.6" - }, - "suggest": { - "knplabs/github-api": "Needed for using GitHub's Markdown engine provided through their API.", - "michelf/php-markdown": "Original Markdown engine with MarkdownExtra." + "php": ">=7.1" }, "type": "library", - "autoload": { - "psr-0": { - "Aptoma": "src/" + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Joris Berthelot", - "email": "joris@berthelot.tel" + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Gunnar Lium", - "email": "gunnar@aptoma.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Twig extension to work with Markdown content", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", "keywords": [ - "markdown", - "twig" + "compatibility", + "polyfill", + "portable", + "shim" ], "support": { - "issues": "https://github.com/aptoma/twig-markdown/issues", - "source": "https://github.com/aptoma/twig-markdown/tree/master" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1" }, - "time": "2015-10-23T20:27:08+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-07-28T13:41:28+00:00" }, { - "name": "asm89/twig-cache-extension", - "version": "1.4.0", + "name": "symfony/polyfill-php81", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/asm89/twig-cache-extension.git", - "reference": "13787226956ec766f4770722082288097aebaaf3" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "e66119f3de95efc359483f810c4c3e6436279436" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/asm89/twig-cache-extension/zipball/13787226956ec766f4770722082288097aebaaf3", - "reference": "13787226956ec766f4770722082288097aebaaf3", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436", + "reference": "e66119f3de95efc359483f810c4c3e6436279436", "shasum": "" }, "require": { - "php": ">=5.3.2", - "twig/twig": "^1.0|^2.0" - }, - "require-dev": { - "doctrine/cache": "~1.0", - "phpunit/phpunit": "^5.0 || ^4.8.10" - }, - "suggest": { - "psr/cache-implementation": "To make use of PSR-6 cache implementation via PsrCacheAdapter." + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { - "": "lib/" - } + "Symfony\\Polyfill\\Php81\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2102,52 +2572,71 @@ ], "authors": [ { - "name": "Alexander", - "email": "iam.asm89@gmail.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Cache fragments of templates directly within Twig.", - "homepage": "https://github.com/asm89/twig-cache-extension", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", "keywords": [ - "cache", - "extension", - "twig" + "compatibility", + "polyfill", + "portable", + "shim" ], "support": { - "issues": "https://github.com/asm89/twig-cache-extension/issues", - "source": "https://github.com/asm89/twig-cache-extension/tree/1.4.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.23.0" }, - "abandoned": "twig/cache-extension", - "time": "2020-01-01T20:47:37+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-21T13:25:03+00:00" }, { - "name": "cakephp/bake", - "version": "1.12.0", + "name": "symfony/service-contracts", + "version": "v1.1.2", "source": { "type": "git", - "url": "https://github.com/cakephp/bake.git", - "reference": "33e8ee8419ba36c13fa4074c208c93352b5530cf" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/bake/zipball/33e8ee8419ba36c13fa4074c208c93352b5530cf", - "reference": "33e8ee8419ba36c13fa4074c208c93352b5530cf", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0", + "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0", "shasum": "" }, "require": { - "cakephp/cakephp": "^3.8.0", - "cakephp/plugin-installer": "^1.0", - "php": ">=5.6.0", - "wyrihaximus/twig-view": "^4.3.7" + "php": "^7.1.3" }, - "require-dev": { - "cakephp/cakephp-codesniffer": "^3.0", - "phpunit/phpunit": "^5.7.14|^6.0" + "suggest": { + "psr/container": "", + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } }, - "type": "cakephp-plugin", "autoload": { "psr-4": { - "Bake\\": "src/" + "Symfony\\Contracts\\Service\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -2156,50 +2645,194 @@ ], "authors": [ { - "name": "CakePHP Community", - "homepage": "https://github.com/cakephp/bake/graphs/contributors" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Bake plugin for CakePHP 3", - "homepage": "https://github.com/cakephp/bake", + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", "keywords": [ - "bake", - "cakephp" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" ], "support": { - "forum": "https://stackoverflow.com/tags/cakephp", - "irc": "irc://irc.freenode.org/cakephp", - "issues": "https://github.com/cakephp/bake/issues", - "source": "https://github.com/cakephp/bake" + "source": "https://github.com/symfony/service-contracts/tree/v1.1.2" }, - "time": "2019-12-07T20:34:43+00:00" + "time": "2019-05-28T07:50:59+00:00" }, { - "name": "cakephp/cakephp-codesniffer", - "version": "3.3.0", + "name": "symfony/string", + "version": "v5.3.7", "source": { "type": "git", - "url": "https://github.com/cakephp/cakephp-codesniffer.git", - "reference": "7998a191e787fd5b68cb635d7050cb0d7b55e1a1" + "url": "https://github.com/symfony/string.git", + "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/cakephp-codesniffer/zipball/7998a191e787fd5b68cb635d7050cb0d7b55e1a1", - "reference": "7998a191e787fd5b68cb635d7050cb0d7b55e1a1", + "url": "https://api.github.com/repos/symfony/string/zipball/8d224396e28d30f81969f083a58763b8b9ceb0a5", + "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5", "shasum": "" }, "require": { - "php": ">=5.6", - "squizlabs/php_codesniffer": "^3.0.0" + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" }, "require-dev": { - "phpunit/phpunit": "<6.0" + "symfony/error-handler": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" }, - "type": "phpcodesniffer-standard", + "type": "library", "autoload": { "psr-4": { - "CakePHP\\": "CakePHP/" - } + "Symfony\\Component\\String\\": "" + }, + "files": [ + "Resources/functions.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.3.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-08-26T08:00:08+00:00" + } + ], + "packages-dev": [ + { + "name": "cakephp/bake", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/cakephp/bake.git", + "reference": "f1c297c4e903a15188389011b93ce46119849d01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/bake/zipball/f1c297c4e903a15188389011b93ce46119849d01", + "reference": "f1c297c4e903a15188389011b93ce46119849d01", + "shasum": "" + }, + "require": { + "cakephp/cakephp": "^4.0", + "cakephp/twig-view": "^1.0", + "php": ">=7.2" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "^4.0", + "cakephp/debug_kit": "^4.1", + "phpunit/phpunit": "~8.5.0" + }, + "type": "cakephp-plugin", + "autoload": { + "psr-4": { + "Bake\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/bake/graphs/contributors" + } + ], + "description": "Bake plugin for CakePHP", + "homepage": "https://github.com/cakephp/bake", + "keywords": [ + "bake", + "cakephp" + ], + "support": { + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/bake/issues", + "source": "https://github.com/cakephp/bake" + }, + "time": "2020-10-23T01:17:19+00:00" + }, + { + "name": "cakephp/cakephp-codesniffer", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/cakephp/cakephp-codesniffer.git", + "reference": "7998a191e787fd5b68cb635d7050cb0d7b55e1a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/cakephp-codesniffer/zipball/7998a191e787fd5b68cb635d7050cb0d7b55e1a1", + "reference": "7998a191e787fd5b68cb635d7050cb0d7b55e1a1", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "squizlabs/php_codesniffer": "^3.0.0" + }, + "require-dev": { + "phpunit/phpunit": "<6.0" + }, + "type": "phpcodesniffer-standard", + "autoload": { + "psr-4": { + "CakePHP\\": "CakePHP/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2227,30 +2860,29 @@ }, { "name": "cakephp/debug_kit", - "version": "3.23.0", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/cakephp/debug_kit.git", - "reference": "49506b55d0b7becf4803e895b07a8cd8599ab1e4" + "reference": "940a0214947e85bbaa0724acfda852f64831f04f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/debug_kit/zipball/49506b55d0b7becf4803e895b07a8cd8599ab1e4", - "reference": "49506b55d0b7becf4803e895b07a8cd8599ab1e4", + "url": "https://api.github.com/repos/cakephp/debug_kit/zipball/940a0214947e85bbaa0724acfda852f64831f04f", + "reference": "940a0214947e85bbaa0724acfda852f64831f04f", "shasum": "" }, "require": { - "cakephp/cakephp": "^3.7.0", - "cakephp/chronos": "^1.0.0", - "composer/composer": "^1.3 | ^2.0", - "jdorn/sql-formatter": "^1.2.0", - "php": ">=5.6.0" + "cakephp/cakephp": "^4.0", + "cakephp/chronos": "^2.0", + "composer/composer": "^1.3", + "jdorn/sql-formatter": "^1.2", + "php": ">=7.2" }, "require-dev": { - "cakephp/authorization": "^1.3.2", - "cakephp/cakephp-codesniffer": "^3.0", - "cakephp/plugin-installer": "^1.3", - "phpunit/phpunit": "^5.7.14|^6.0" + "cakephp/authorization": "^2.0", + "cakephp/cakephp-codesniffer": "^4.0", + "phpunit/phpunit": "^8.0" }, "suggest": { "ext-pdo_sqlite": "DebugKit needs to store panel data in a database. SQLite is simple and easy to use." @@ -2290,42 +2922,44 @@ "issues": "https://github.com/cakephp/debug_kit/issues", "source": "https://github.com/cakephp/debug_kit" }, - "time": "2021-05-16T04:58:57+00:00" + "time": "2020-06-10T01:37:18+00:00" }, { - "name": "composer/ca-bundle", - "version": "1.2.10", + "name": "cakephp/twig-view", + "version": "1.2.0", "source": { "type": "git", - "url": "https://github.com/composer/ca-bundle.git", - "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8" + "url": "https://github.com/cakephp/twig-view.git", + "reference": "668dd6aee43dd616b1e83cb9ba166f094c10fbce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8", - "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8", + "url": "https://api.github.com/repos/cakephp/twig-view/zipball/668dd6aee43dd616b1e83cb9ba166f094c10fbce", + "reference": "668dd6aee43dd616b1e83cb9ba166f094c10fbce", "shasum": "" }, "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^5.3.2 || ^7.0 || ^8.0" + "cakephp/cakephp": "^4.0", + "jasny/twig-extensions": "^1.3", + "php": ">=7.2", + "twig/markdown-extra": "^3.0", + "twig/twig": "^3.0" }, - "require-dev": { - "phpstan/phpstan": "^0.12.55", - "psr/log": "^1.0", - "symfony/phpunit-bridge": "^4.2 || ^5", - "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" + "conflict": { + "wyrihaximus/twig-view": "*" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } + "require-dev": { + "cakephp/cakephp-codesniffer": "^4.0", + "cakephp/debug_kit": "^4.0", + "cakephp/plugin-installer": "^1.3", + "michelf/php-markdown": "^1.9", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^8.5 || ^9.3" }, + "type": "cakephp-plugin", "autoload": { "psr-4": { - "Composer\\CaBundle\\": "src" + "Cake\\TwigView\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2334,74 +2968,60 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/cakephp/graphs/contributors" } ], - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "description": "Twig powered View for CakePHP", "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" + "cakephp", + "template", + "twig", + "view" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.2.10" + "forum": "https://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "issues": "https://github.com/cakephp/twig-view/issues", + "source": "https://github.com/cakephp/twig-view" }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-06-07T13:58:28+00:00" + "time": "2020-12-13T19:57:31+00:00" }, { "name": "composer/composer", - "version": "2.1.8", + "version": "1.10.22", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "24d38e9686092de05214cafa187dc282a5d89497" + "reference": "28c9dfbe2351635961f670773e8d7b17bc5eda25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/24d38e9686092de05214cafa187dc282a5d89497", - "reference": "24d38e9686092de05214cafa187dc282a5d89497", + "url": "https://api.github.com/repos/composer/composer/zipball/28c9dfbe2351635961f670773e8d7b17bc5eda25", + "reference": "28c9dfbe2351635961f670773e8d7b17bc5eda25", "shasum": "" }, "require": { "composer/ca-bundle": "^1.0", - "composer/metadata-minifier": "^1.0", - "composer/semver": "^3.0", + "composer/semver": "^1.0", "composer/spdx-licenses": "^1.2", - "composer/xdebug-handler": "^2.0", - "justinrainbow/json-schema": "^5.2.11", + "composer/xdebug-handler": "^1.1", + "justinrainbow/json-schema": "^5.2.10", "php": "^5.3.2 || ^7.0 || ^8.0", "psr/log": "^1.0", - "react/promise": "^1.2 || ^2.7", "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.0", - "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0" + "symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0" + }, + "conflict": { + "symfony/console": "2.8.38" }, "require-dev": { "phpspec/prophecy": "^1.10", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + "symfony/phpunit-bridge": "^4.2" }, "suggest": { "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", @@ -2414,7 +3034,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "1.10-dev" } }, "autoload": { @@ -2430,12 +3050,12 @@ { "name": "Nils Adermann", "email": "naderman@naderman.de", - "homepage": "https://www.naderman.de" + "homepage": "http://www.naderman.de" }, { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "https://seld.be" + "homepage": "http://seld.be" } ], "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", @@ -2446,78 +3066,9 @@ "package" ], "support": { - "irc": "ircs://irc.libera.chat:6697/composer", + "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/composer/issues", - "source": "https://github.com/composer/composer/tree/2.1.8" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-09-15T11:55:15+00:00" - }, - { - "name": "composer/metadata-minifier", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/metadata-minifier.git", - "reference": "c549d23829536f0d0e984aaabbf02af91f443207" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207", - "reference": "c549d23829536f0d0e984aaabbf02af91f443207", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "composer/composer": "^2", - "phpstan/phpstan": "^0.12.55", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\MetadataMinifier\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Small utility library that handles metadata minification and expansion.", - "keywords": [ - "composer", - "compression" - ], - "support": { - "issues": "https://github.com/composer/metadata-minifier/issues", - "source": "https://github.com/composer/metadata-minifier/tree/1.0.0" + "source": "https://github.com/composer/composer/tree/1.10.22" }, "funding": [ { @@ -2533,33 +3084,32 @@ "type": "tidelift" } ], - "time": "2021-04-07T13:37:33+00:00" + "time": "2021-04-27T11:10:45+00:00" }, { "name": "composer/semver", - "version": "3.2.5", + "version": "1.7.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9" + "reference": "647490bbcaf7fc4891c58f47b825eb99d19c377a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9", - "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9", + "url": "https://api.github.com/repos/composer/semver/zipball/647490bbcaf7fc4891c58f47b825eb99d19c377a", + "reference": "647490bbcaf7fc4891c58f47b825eb99d19c377a", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.54", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpunit/phpunit": "^4.5 || ^5.0.5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { @@ -2598,7 +3148,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.5" + "source": "https://github.com/composer/semver/tree/1.7.2" }, "funding": [ { @@ -2614,7 +3164,7 @@ "type": "tidelift" } ], - "time": "2021-05-24T12:41:47+00:00" + "time": "2020-12-03T15:47:16+00:00" }, { "name": "composer/spdx-licenses", @@ -2697,21 +3247,21 @@ }, { "name": "composer/xdebug-handler", - "version": "2.0.2", + "version": "1.4.6", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339" + "reference": "f27e06cd9675801df441b3656569b328e04aa37c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339", - "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f27e06cd9675801df441b3656569b328e04aa37c", + "reference": "f27e06cd9675801df441b3656569b328e04aa37c", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1 || ^2 || ^3" + "psr/log": "^1.0" }, "require-dev": { "phpstan/phpstan": "^0.12.55", @@ -2741,7 +3291,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.2" + "source": "https://github.com/composer/xdebug-handler/tree/1.4.6" }, "funding": [ { @@ -2757,40 +3307,38 @@ "type": "tidelift" } ], - "time": "2021-07-31T17:03:58+00:00" + "time": "2021-03-25T17:01:18+00:00" }, { - "name": "jasny/twig-extensions", - "version": "v1.2.0", + "name": "doctrine/instantiator", + "version": "1.4.0", "source": { "type": "git", - "url": "https://github.com/jasny/twig-extensions.git", - "reference": "30bdf3a3903c021544f36332c9d5d4d563527da4" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jasny/twig-extensions/zipball/30bdf3a3903c021544f36332c9d5d4d563527da4", - "reference": "30bdf3a3903c021544f36332c9d5d4d563527da4", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", "shasum": "" }, "require": { - "php": ">=7.0.0 | >=5.6.0", - "twig/twig": "^2.0 | ^1.12" + "php": "^7.1 || ^8.0" }, "require-dev": { - "ext-intl": "*", - "ext-pcre": "*", - "jasny/php-code-quality": "^2.1", - "phpunit/phpunit": "^5.0" - }, - "suggest": { - "ext-intl": "Required for the use of the LocalDate Twig extension", - "ext-pcre": "Required for the use of the PCRE Twig extension" + "doctrine/coding-standard": "^8.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", "autoload": { "psr-4": { - "Jasny\\Twig\\": "src/" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2799,12 +3347,83 @@ ], "authors": [ { - "name": "Arnold Daniels", - "email": "arnold@jasny.net", - "homepage": "http://www.jasny.net" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" } ], - "description": "A set of useful Twig filters", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-11-10T18:47:58+00:00" + }, + { + "name": "jasny/twig-extensions", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/jasny/twig-extensions.git", + "reference": "a694eb02f6fc14ff8e2fceb8b80882c0c926102b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jasny/twig-extensions/zipball/a694eb02f6fc14ff8e2fceb8b80882c0c926102b", + "reference": "a694eb02f6fc14ff8e2fceb8b80882c0c926102b", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "twig/twig": "^2.0 | ^3.0" + }, + "require-dev": { + "ext-intl": "*", + "ext-pcre": "*", + "jasny/php-code-quality": "^2.5", + "php": ">=7.2.0" + }, + "suggest": { + "ext-intl": "Required for the use of the LocalDate Twig extension", + "ext-pcre": "Required for the use of the PCRE Twig extension" + }, + "type": "library", + "autoload": { + "psr-4": { + "Jasny\\Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Arnold Daniels", + "email": "arnold@jasny.net", + "homepage": "http://www.jasny.net" + } + ], + "description": "A set of useful Twig filters", "homepage": "http://github.com/jasny/twig-extensions#README", "keywords": [ "PCRE", @@ -2821,7 +3440,7 @@ "issues": "https://github.com/jasny/twig-extensions/issues", "source": "https://github.com/jasny/twig-extensions" }, - "time": "2017-09-13T07:38:01+00:00" + "time": "2019-12-10T16:04:23+00:00" }, { "name": "jdorn/sql-formatter", @@ -2947,6 +3566,64 @@ }, "time": "2021-07-22T09:24:00+00:00" }, + { + "name": "myclabs/deep-copy", + "version": "1.10.2", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2020-11-13T09:40:50+00:00" + }, { "name": "nikic/php-parser", "version": "v4.12.0", @@ -3004,129 +3681,1603 @@ "time": "2021-07-21T10:44:31+00:00" }, { - "name": "psy/psysh", - "version": "v0.10.8", + "name": "phar-io/manifest", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/bobthecow/psysh.git", - "reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3" + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e4573f47750dd6c92dca5aee543fa77513cbd8d3", - "reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "bae7c545bef187884426f042434e561ab1ddb182" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", + "reference": "bae7c545bef187884426f042434e561ab1ddb182", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.1.0" + }, + "time": "2021-02-23T14:00:09+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.2.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + }, + "time": "2020-09-03T19:13:55+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "30f38bffc6f24293dadd1823936372dfa9e86e2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/30f38bffc6f24293dadd1823936372dfa9e86e2f", + "reference": "30f38bffc6f24293dadd1823936372dfa9e86e2f", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.0" + }, + "time": "2021-09-17T15:28:14+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.14.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", + "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.2", + "php": "^7.2 || ~8.0, <8.2", + "phpdocumentor/reflection-docblock": "^5.2", + "sebastian/comparator": "^3.0 || ^4.0", + "sebastian/recursion-context": "^3.0 || ^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^6.0 || ^7.0", + "phpunit/phpunit": "^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/1.14.0" + }, + "time": "2021-09-10T09:02:12+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "0.12.99", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b4d40f1d759942f523be267a1bab6884f46ca3f7", + "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.12-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/0.12.99" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpstan", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2021-09-12T20:09:55+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "7.0.15", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "819f92bba8b001d4363065928088de22f25a3a48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/819f92bba8b001d4363065928088de22f25a3a48", + "reference": "819f92bba8b001d4363065928088de22f25a3a48", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": ">=7.2", + "phpunit/php-file-iterator": "^2.0.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.1.3 || ^4.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^4.2.2", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.2.2" + }, + "suggest": { + "ext-xdebug": "^2.7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.15" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-07-26T12:20:09+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "28af674ff175d0768a5a978e6de83f697d4a7f05" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/28af674ff175d0768a5a978e6de83f697d4a7f05", + "reference": "28af674ff175d0768a5a978e6de83f697d4a7f05", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-07-19T06:46:01+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + }, + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "2.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662", + "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:20:02+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/a853a0e183b9db7eed023d7933a858fa1c8d25a3", + "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "abandoned": true, + "time": "2020-08-04T08:28:15+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "8.5.20", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "9deefba183198398a09b927a6ac6bc1feb0b7b70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9deefba183198398a09b927a6ac6bc1feb0b7b70", + "reference": "9deefba183198398a09b927a6ac6bc1feb0b7b70", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.0", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.2", + "phpspec/prophecy": "^1.10.3", + "phpunit/php-code-coverage": "^7.0.12", + "phpunit/php-file-iterator": "^2.0.4", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.1.2", + "sebastian/comparator": "^3.0.2", + "sebastian/diff": "^3.0.2", + "sebastian/environment": "^4.2.3", + "sebastian/exporter": "^3.1.2", + "sebastian/global-state": "^3.0.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0.1", + "sebastian/type": "^1.1.3", + "sebastian/version": "^2.0.1" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.20" + }, + "funding": [ + { + "url": "https://phpunit.de/donate.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-08-31T06:44:38+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.10.8", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e4573f47750dd6c92dca5aee543fa77513cbd8d3", + "reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3", + "php": "^8.0 || ^7.0 || ^5.5.9", + "symfony/console": "~5.0|~4.0|~3.0|^2.4.2|~2.3.10", + "symfony/var-dumper": "~5.0|~4.0|~3.0|~2.7" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "hoa/console": "3.17.*" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.", + "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.10.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.10.8" + }, + "time": "2021-04-10T16:23:39+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:15:22+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "1071dfcef776a57013124ff35e1fc41ccd294758" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1071dfcef776a57013124ff35e1fc41ccd294758", + "reference": "1071dfcef776a57013124ff35e1fc41ccd294758", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:04:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/14f72dd46eaf2f2293cbe79c93cc0bc43161a211", + "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:59:04+00:00" + }, + { + "name": "sebastian/environment", + "version": "4.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", + "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/4.2.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:53:42+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/6b853149eab67d4da22291d36f5b0631c0fd856e", + "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:47:53+00:00" + }, + { + "name": "sebastian/global-state", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "474fb9edb7ab891665d3bfc6317f42a0a150454b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/474fb9edb7ab891665d3bfc6317f42a0a150454b", + "reference": "474fb9edb7ab891665d3bfc6317f42a0a150454b", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^8.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:43:24+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:40:27+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:37:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:34:24+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3", + "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:30:19+00:00" + }, + { + "name": "sebastian/type", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0150cfbc4495ed2df3872fb31b26781e4e077eb4", + "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4", "shasum": "" }, "require": { - "ext-json": "*", - "ext-tokenizer": "*", - "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3", - "php": "^8.0 || ^7.0 || ^5.5.9", - "symfony/console": "~5.0|~4.0|~3.0|^2.4.2|~2.3.10", - "symfony/var-dumper": "~5.0|~4.0|~3.0|~2.7" + "php": ">=7.2" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "hoa/console": "3.17.*" - }, - "suggest": { - "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", - "ext-pdo-sqlite": "The doc command requires SQLite to work.", - "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", - "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.", - "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." + "phpunit/phpunit": "^8.2" }, - "bin": [ - "bin/psysh" - ], "type": "library", "extra": { "branch-alias": { - "dev-main": "0.10.x-dev" + "dev-master": "1.1-dev" } }, "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Psy\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "An interactive shell for modern PHP.", - "homepage": "http://psysh.org", - "keywords": [ - "REPL", - "console", - "interactive", - "shell" - ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.10.8" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/1.1.4" }, - "time": "2021-04-10T16:23:39+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:25:11+00:00" }, { - "name": "react/promise", - "version": "v2.8.0", + "name": "sebastian/version", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4", - "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36" + "php": ">=5.6" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { - "psr-4": { - "React\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "keywords": [ - "promise", - "promises" - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v2.8.0" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/master" }, - "time": "2020-05-12T15:16:56+00:00" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "seld/jsonlint", @@ -3357,82 +5508,6 @@ ], "time": "2021-08-04T21:20:46+00:00" }, - { - "name": "symfony/polyfill-php72", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-05-27T09:17:38+00:00" - }, { "name": "symfony/process", "version": "v5.3.7", @@ -3497,33 +5572,32 @@ }, { "name": "symfony/var-dumper", - "version": "v4.4.30", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7f65c44c2ce80d3a0fcdb6385ee0ad535e45660c" + "reference": "3ad5af4aed07d0a0201bbcfc42658fe6c5b2fb8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7f65c44c2ce80d3a0fcdb6385ee0ad535e45660c", - "reference": "7f65c44c2ce80d3a0fcdb6385ee0ad535e45660c", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3ad5af4aed07d0a0201bbcfc42658fe6c5b2fb8f", + "reference": "3ad5af4aed07d0a0201bbcfc42658fe6c5b2fb8f", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php72": "~1.5", "symfony/polyfill-php80": "^1.16" }, "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/console": "<3.4" + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^3.4|^4.0|^5.0", + "symfony/console": "^4.4|^5.0", "symfony/process": "^4.4|^5.0", - "twig/twig": "^1.43|^2.13|^3.0.4" + "twig/twig": "^2.13|^3.0.4" }, "suggest": { "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", @@ -3566,7 +5640,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v4.4.30" + "source": "https://github.com/symfony/var-dumper/tree/v5.3.7" }, "funding": [ { @@ -3582,47 +5656,100 @@ "type": "tidelift" } ], - "time": "2021-08-04T20:31:23+00:00" + "time": "2021-08-04T23:19:25+00:00" }, { - "name": "twig/twig", - "version": "v1.44.5", + "name": "theseer/tokenizer", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "dd4353357c5a116322e92a00d16043a31881a81e" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/dd4353357c5a116322e92a00d16043a31881a81e", - "reference": "dd4353357c5a116322e92a00d16043a31881a81e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "^1.8" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + }, + { + "name": "twig/markdown-extra", + "version": "v3.3.3", + "source": { + "type": "git", + "url": "https://github.com/twigphp/markdown-extra.git", + "reference": "725a4ef89d93bb80fc63c67cf261bf7512649290" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/markdown-extra/zipball/725a4ef89d93bb80fc63c67cf261bf7512649290", + "reference": "725a4ef89d93bb80fc63c67cf261bf7512649290", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "twig/twig": "^2.4|^3.0" }, "require-dev": { - "psr/container": "^1.0", - "symfony/phpunit-bridge": "^4.4.9|^5.0.9" + "erusev/parsedown": "^1.7", + "league/commonmark": "^1.0", + "league/html-to-markdown": "^4.8|^5.0", + "michelf/php-markdown": "^1.8", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.44-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "psr-0": { - "Twig_": "lib/" - }, "psr-4": { - "Twig\\": "src/" - } + "Twig\\Extra\\Markdown\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { @@ -3630,25 +5757,17 @@ "email": "fabien@symfony.com", "homepage": "http://fabien.potencier.org", "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" } ], - "description": "Twig, the flexible, fast, and secure template language for PHP", + "description": "A Twig extension for Markdown", "homepage": "https://twig.symfony.com", "keywords": [ - "templating" + "html", + "markdown", + "twig" ], "support": { - "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v1.44.5" + "source": "https://github.com/twigphp/markdown-extra/tree/v3.3.3" }, "funding": [ { @@ -3660,89 +5779,118 @@ "type": "tidelift" } ], - "time": "2021-09-17T08:35:19+00:00" + "time": "2021-07-07T07:08:18+00:00" }, { - "name": "umpirsky/twig-php-function", - "version": "v0.1", + "name": "twig/twig", + "version": "v3.3.3", "source": { "type": "git", - "url": "https://github.com/umpirsky/twig-php-function.git", - "reference": "53b4b1eb0c5eacbd7d66c504b7d809c79b4bedbc" + "url": "https://github.com/twigphp/Twig.git", + "reference": "a27fa056df8a6384316288ca8b0fa3a35fdeb569" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/umpirsky/twig-php-function/zipball/53b4b1eb0c5eacbd7d66c504b7d809c79b4bedbc", - "reference": "53b4b1eb0c5eacbd7d66c504b7d809c79b4bedbc", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a27fa056df8a6384316288ca8b0fa3a35fdeb569", + "reference": "a27fa056df8a6384316288ca8b0fa3a35fdeb569", "shasum": "" }, "require": { - "php": ">=5.3.3", - "twig/twig": "~1.12" + "php": ">=7.2.5", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { - "phpspec/phpspec": "~2.0", - "phpunit/phpunit": "~4.4" + "psr/container": "^1.0", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, "autoload": { - "psr-0": { - "Umpirsky\\": "src/" + "psr-4": { + "Twig\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Saša Stamenković", - "email": "umpirsky@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" } ], - "description": "Call (almost) any PHP function from your Twig templates.", + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], "support": { - "issues": "https://github.com/umpirsky/twig-php-function/issues", - "source": "https://github.com/umpirsky/twig-php-function/tree/master" + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v3.3.3" }, - "time": "2016-03-12T16:36:32+00:00" + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2021-09-17T08:44:23+00:00" }, { - "name": "wyrihaximus/twig-view", - "version": "4.4.0", + "name": "webmozart/assert", + "version": "1.10.0", "source": { "type": "git", - "url": "https://github.com/cakephp/legacy-twig-view.git", - "reference": "463e1a6ed493d4fe99eaeaaf39d80172b51fc0fb" + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/legacy-twig-view/zipball/463e1a6ed493d4fe99eaeaaf39d80172b51fc0fb", - "reference": "463e1a6ed493d4fe99eaeaaf39d80172b51fc0fb", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", "shasum": "" }, "require": { - "ajgl/breakpoint-twig-extension": "^0.3.0", - "aptoma/twig-markdown": "^2.0", - "asm89/twig-cache-extension": "^1.0", - "cakephp/cakephp": "^3.7", - "jasny/twig-extensions": "^1.0", - "php": "^5.6 || ^7.0", - "twig/twig": "^1.27", - "umpirsky/twig-php-function": "0.1" + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "require-dev": { - "cakephp/bake": "^1.5", - "cakephp/debug_kit": "^3.0", - "phake/phake": "^2.3.2", - "phpunit/phpunit": "^5.7.14", - "squizlabs/php_codesniffer": "^3.4.0", - "wyrihaximus/phpunit-class-reflection-helpers": "dev-master" + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } }, - "type": "cakephp-plugin", "autoload": { "psr-4": { - "WyriHaximus\\TwigView\\": "src/" + "Webmozart\\Assert\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3751,23 +5899,21 @@ ], "authors": [ { - "name": "Cees-Jan Kiewiet", - "email": "ceesjank@gmail.com", - "homepage": "http://wyrihaximus.net/" + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "Twig powered View for CakePHP3", + "description": "Assertions to validate method input/output with nice error messages.", "keywords": [ - "cakephp", - "cakephp3", - "twig", - "view" + "assert", + "check", + "validate" ], "support": { - "issues": "https://github.com/cakephp/legacy-twig-view/issues", - "source": "https://github.com/cakephp/legacy-twig-view/tree/4.4.0" + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" }, - "time": "2021-04-06T15:42:50+00:00" + "time": "2021-03-09T10:59:23+00:00" } ], "aliases": [], @@ -3778,7 +5924,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=5.6" + "php": ">=7.2" }, "platform-dev": [], "plugin-api-version": "2.1.0" diff --git a/app/config/app.php b/app/config/app.php index 6b7c82a1a..9f35ce8bd 100644 --- a/app/config/app.php +++ b/app/config/app.php @@ -25,6 +25,13 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ +use Cake\Cache\Engine\FileEngine; +use Cake\Database\Connection; +use Cake\Database\Driver\Mysql; +use Cake\Error\ExceptionRenderer; +use Cake\Log\Engine\FileLog; +use Cake\Mailer\Transport\MailTransport; + return [ /** * Debug Level: @@ -37,7 +44,7 @@ */ 'debug' => filter_var(env('DEBUG', false), FILTER_VALIDATE_BOOLEAN), - /** + /* * Configure basic information about the application. * * - namespace - The namespace to find app classes under. @@ -54,7 +61,10 @@ * /.htaccess * /webroot/.htaccess * And uncomment the baseUrl key below. - * - fullBaseUrl - A base URL to use for absolute links. + * - fullBaseUrl - A base URL to use for absolute links. When set to false (default) + * CakePHP generates required value based on `HTTP_HOST` environment variable. + * However, you can define it manually to optimize performance or if you + * are concerned about people manipulating the `Host` header. * - imageBaseUrl - Web path to the public images directory under webroot. * - cssBaseUrl - Web path to the public css directory under webroot. * - jsBaseUrl - Web path to the public js directory under webroot. @@ -66,36 +76,36 @@ 'namespace' => 'App', 'encoding' => env('APP_ENCODING', 'UTF-8'), 'defaultLocale' => env('APP_DEFAULT_LOCALE', 'en_US'), + 'defaultTimezone' => env('APP_DEFAULT_TIMEZONE', 'UTC'), 'base' => false, 'dir' => 'src', 'webroot' => 'webroot', 'wwwRoot' => WWW_ROOT, - // 'baseUrl' => env('SCRIPT_NAME'), + //'baseUrl' => env('SCRIPT_NAME'), 'fullBaseUrl' => false, 'imageBaseUrl' => 'img/', 'cssBaseUrl' => 'css/', 'jsBaseUrl' => 'js/', 'paths' => [ 'plugins' => [ROOT . DS . 'plugins' . DS], - 'templates' => [APP . 'Template' . DS], - 'locales' => [APP . 'Locale' . DS], + 'templates' => [ROOT . DS . 'templates' . DS], + 'locales' => [RESOURCES . 'locales' . DS], ], ], - /** + /* * Security and encryption configuration * * - salt - A random string used in security hashing methods. * The salt value is also used as the encryption key. * You should treat it as extremely sensitive data. */ - 'Security' => [ // Note that we (COmanage) override this in bootstrap.php 'salt' => env('SECURITY_SALT', '22a0feb8115478995505ee6275de27f42ff79e9876794c6762cb75ea853986af'), ], - /** + /* * Apply timestamps with the last modified time to static assets (js, css, images). * Will append a querystring parameter containing the time the file was modified. * This is useful for busting browser caches. @@ -104,51 +114,66 @@ * enable timestamping regardless of debug value. */ 'Asset' => [ - 'timestamp' => true, + 'timestamp' => true, + // 'cacheTime' => '+1 year' ], - /** + /* * Configure the cache adapters. */ 'Cache' => [ 'default' => [ - 'className' => 'File', + 'className' => FileEngine::class, 'path' => CACHE, 'url' => env('CACHE_DEFAULT_URL', null), ], - /** + /* * Configure the cache used for general framework caching. * Translation cache files are stored with this configuration. * Duration will be set to '+2 minutes' in bootstrap.php when debug = true * If you set 'className' => 'Null' core cache will be disabled. */ '_cake_core_' => [ - 'className' => 'Null', // 'File', + 'className' => 'Null', // FileEngine::class 'prefix' => 'myapp_cake_core_', - 'path' => CACHE . 'persistent/', + 'path' => CACHE . 'persistent' . DS, 'serialize' => true, 'duration' => '+1 years', 'url' => env('CACHE_CAKECORE_URL', null), ], - /** + /* * Configure the cache for model and datasource caches. This cache * configuration is used to store schema descriptions, and table listings * in connections. * Duration will be set to '+2 minutes' in bootstrap.php when debug = true */ '_cake_model_' => [ - 'className' => 'Null', //'File', + 'className' => 'Null', // FileEngine::class 'prefix' => 'myapp_cake_model_', - 'path' => CACHE . 'models/', + 'path' => CACHE . 'models' . DS, 'serialize' => true, 'duration' => '+1 years', 'url' => env('CACHE_CAKEMODEL_URL', null), ], + + /* + * Configure the cache for routes. The cached routes collection is built the + * first time the routes are processed through `config/routes.php`. + * Duration will be set to '+2 seconds' in bootstrap.php when debug = true + */ + '_cake_routes_' => [ + 'className' => 'Null', // FileEngine::class + 'prefix' => 'myapp_cake_routes_', + 'path' => CACHE, + 'serialize' => true, + 'duration' => '+1 years', + 'url' => env('CACHE_CAKEROUTES_URL', null), + ], ], - /** + /* * Configure the Error and Exception handlers used by your application. * * By default errors are displayed using Debugger, when debug is true and logged @@ -172,20 +197,40 @@ * - `skipLog` - array - List of exceptions to skip for logging. Exceptions that * extend one of the listed exceptions will also be skipped for logging. * E.g.: - * `'skipLog' => ['Cake\Network\Exception\NotFoundException', 'Cake\Network\Exception\UnauthorizedException']` + * `'skipLog' => ['Cake\Http\Exception\NotFoundException', 'Cake\Http\Exception\UnauthorizedException']` * - `extraFatalErrorMemory` - int - The number of megabytes to increase * the memory limit by when a fatal error is encountered. This allows * breathing room to complete logging or error handling. + * - `ignoredDeprecationPaths` - array - A list of glob compatible file paths that deprecations + * should be ignored in. Use this to ignore deprecations for plugins or parts of + * your application that still emit deprecations. */ 'Error' => [ 'errorLevel' => E_ALL, - 'exceptionRenderer' => 'Cake\Error\ExceptionRenderer', + 'exceptionRenderer' => ExceptionRenderer::class, 'skipLog' => [], 'log' => true, 'trace' => true, + 'ignoredDeprecationPaths' => [], ], - /** + /* + * Debugger configuration + * + * Define development error values for Cake\Error\Debugger + * + * - `editor` Set the editor URL format you want to use. + * By default atom, emacs, macvim, phpstorm, sublime, textmate, and vscode are + * available. You can add additional editor link formats using + * `Debugger::addEditor()` during your application bootstrap. + * - `outputMask` A mapping of `key` to `replacement` values that + * `Debugger` should replace in dumped data and logs generated by `Debugger`. + */ + 'Debugger' => [ + 'editor' => 'phpstorm', + ], + + /* * Email configuration. * * By defining transports separately from delivery profiles you can easily @@ -208,20 +253,23 @@ * 'EmailTransport' => [ 'default' => [ - 'className' => 'Mail', - // The following keys are used in SMTP transports + 'className' => MailTransport::class, + * The keys host, port, timeout, username, password, client and tls + * are used in SMTP transports 'host' => 'localhost', 'port' => 25, 'timeout' => 30, - 'username' => null, - 'password' => null, + * It is recommended to set these options through your environment or app_local.php + //'username' => null, + //'password' => null, 'client' => null, - 'tls' => null, + 'tls' => false, 'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null), ], ], + */ - /** + /* * Email delivery profiles * * Delivery profiles allow you to predefine various properties about email @@ -234,44 +282,46 @@ 'default' => [ 'transport' => 'default', 'from' => 'you@localhost', + * Will by default be set to config value of App.encoding, if that exists otherwise to UTF-8. //'charset' => 'utf-8', //'headerCharset' => 'utf-8', ], ], */ - /** + /* * Connection information used by the ORM to connect * to your application's datastores. - * Do not use periods in database name - it may lead to error. - * See https://github.com/cakephp/cakephp/issues/6471 for details. - * Drivers include Mysql Postgres Sqlite Sqlserver - * See vendor\cakephp\cakephp\src\Database\Driver for complete list * + * ### Notes + * - Drivers include Mysql Postgres Sqlite Sqlserver + * See vendor\cakephp\cakephp\src\Database\Driver for complete list + * - Do not use periods in database name - it may lead to error. + * See https://github.com/cakephp/cakephp/issues/6471 for details. + * - 'encoding' is recommended to be set to full UTF-8 4-Byte support. + * E.g set it to 'utf8mb4' in MariaDB and MySQL and 'utf8' for any + * other RDBMS. * Note for COmanage we read in local/Config/database.php instead * 'Datasources' => [ 'default' => [ - 'className' => 'Cake\Database\Connection', - 'driver' => 'Cake\Database\Driver\Postgres', + 'className' => Connection::class, + 'driver' => Mysql::class, 'persistent' => false, - 'host' => 'localhost', - /** - * CakePHP will use the default DB port based on the driver selected - * MySQL on MAMP uses port 8889, MAMP users will want to uncomment - * the following line and set the port accordingly - * - //'port' => 'non_standard_port_number', - 'username' => 'comatch', - 'password' => '', - 'database' => 'matchtest', - 'encoding' => 'utf8', 'timezone' => 'UTC', + + * For MariaDB/MySQL the internal default changed from utf8 to utf8mb4, aka full utf-8 support, in CakePHP 3.6 + //'encoding' => 'utf8mb4', + + * If your MySQL server is configured with `skip-character-set-client-handshake` + * then you MUST use the `flags` config to set your charset encoding. + * For e.g. `'flags' => [\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4']` + 'flags' => [], 'cacheMetadata' => true, 'log' => true, //false, - /** + /* * Set identifier quoting to true if you are using reserved words or * special characters in your table or column names. Enabling this * setting will result in queries built using the Query Builder having @@ -292,36 +342,32 @@ 'url' => env('DATABASE_URL', null), ], + */ - /** + /* * The test connection is used during the test suite. * 'test' => [ - 'className' => 'Cake\Database\Connection', - 'driver' => 'Cake\Database\Driver\Postgres', + 'className' => Connection::class, + 'driver' => Mysql::class, 'persistent' => false, - 'host' => 'localhost', - //'port' => 'non_standard_port_number', - 'username' => 'my_app', - 'password' => 'secret', - 'database' => 'test_myapp', - 'encoding' => 'utf8', 'timezone' => 'UTC', + //'encoding' => 'utf8mb4', + 'flags' => [], 'cacheMetadata' => true, 'quoteIdentifiers' => false, 'log' => false, //'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'], - 'url' => env('DATABASE_TEST_URL', null), ], ], */ - /** + /* * Configures logging options */ 'Log' => [ 'debug' => [ - 'className' => 'Cake\Log\Engine\FileLog', + 'className' => FileLog::class, 'path' => LOGS, 'file' => 'debug', 'url' => env('LOG_DEBUG_URL', null), @@ -329,7 +375,7 @@ 'levels' => ['notice', 'info', 'debug'], ], 'error' => [ - 'className' => 'Cake\Log\Engine\FileLog', + 'className' => FileLog::class, 'path' => LOGS, 'file' => 'error', 'url' => env('LOG_ERROR_URL', null), @@ -338,7 +384,7 @@ ], // To enable this dedicated query log, you need set your datasource's log flag to true 'queries' => [ - 'className' => 'Cake\Log\Engine\FileLog', + 'className' => FileLog::class, 'path' => LOGS, 'file' => 'queries', 'url' => env('LOG_QUERIES_URL', null), @@ -346,7 +392,7 @@ ], ], - /** + /* * Session configuration. * * Contains an array of settings to use for session configuration. The @@ -355,8 +401,8 @@ * * ## Options * - * - `cookie` - The name of the cookie to use. Defaults to 'CAKEPHP'. Avoid using `.` in cookie names, - * as PHP will drop sessions from cookies with `.` in the name. + * - `cookie` - The name of the cookie to use. Defaults to value set for `session.name` php.ini config. + * Avoid using `.` in cookie names, as PHP will drop sessions from cookies with `.` in the name. * - `cookiePath` - The url path for which session cookie is set. Maps to the * `session.cookie_path` php.ini config. Defaults to base path of app. * - `timeout` - The time in minutes the session should be valid for. diff --git a/app/config/bootstrap.php b/app/config/bootstrap.php index 667287a40..b47318334 100644 --- a/app/config/bootstrap.php +++ b/app/config/bootstrap.php @@ -1,4 +1,6 @@ parse() @@ -78,14 +89,12 @@ } /* - * Load an environment local configuration file. - * You can use a file like app_local.php to provide local overrides to your - * shared configuration. + * Load an environment local configuration file to provide overrides to your configuration. + * Notice: For security reasons app_local.php **should not** be included in your git repo. */ -//Configure::load('app_local', 'default'); - -// This is set in app.php -//Configure::write('debug', false); +if (file_exists(CONFIG . 'app_local.php')) { + Configure::load('app_local', 'default'); +} /* * When debug = true the metadata cache should only last @@ -95,14 +104,14 @@ Cache::disable(); // Configure::write('Cache._cake_model_.duration', '+2 minutes'); // Configure::write('Cache._cake_core_.duration', '+2 minutes'); +// Configure::write('Cache._cake_routes_.duration', '+2 seconds'); } /* - * Set server timezone to UTC. You can change it to another timezone of your - * choice but using UTC makes time calculations / conversions easier. + * Set the default server timezone. Using UTC makes time calculations / conversions easier. * Check http://php.net/manual/en/timezones.php for list of valid timezone strings. */ -date_default_timezone_set('UTC'); +date_default_timezone_set(Configure::read('App.defaultTimezone')); /* * Configure the mbstring extension to use the correct encoding. @@ -129,16 +138,15 @@ * Include the CLI bootstrap overrides. */ if ($isCli) { - require __DIR__ . '/bootstrap_cli.php'; + require CONFIG . 'bootstrap_cli.php'; } /* * Set the full base URL. * This URL is used as the base of all absolute links. - * - * If you define fullBaseUrl in your config file you can remove this. */ -if (!Configure::read('App.fullBaseUrl')) { +$fullBaseUrl = Configure::read('App.fullBaseUrl'); +if (!$fullBaseUrl) { $s = null; if (env('HTTPS')) { $s = 's'; @@ -146,15 +154,19 @@ $httpHost = env('HTTP_HOST'); if (isset($httpHost)) { - Configure::write('App.fullBaseUrl', 'http' . $s . '://' . $httpHost); + $fullBaseUrl = 'http' . $s . '://' . $httpHost; } unset($httpHost, $s); } +if ($fullBaseUrl) { + Router::fullBaseUrl($fullBaseUrl); +} +unset($fullBaseUrl); Cache::setConfig(Configure::consume('Cache')); ConnectionManager::setConfig(Configure::consume('Datasources')); TransportFactory::setConfig(Configure::consume('EmailTransport')); -Email::setConfig(Configure::consume('Email')); +Mailer::setConfig(Configure::consume('Email')); Log::setConfig(Configure::consume('Log')); // Set the salt based on our local configuration $securitySaltFile = LOCAL . DS . "Config" . DS . "security.salt"; @@ -187,21 +199,34 @@ }); /* - * Enable immutable time objects in the ORM. + * You can set whether the ORM uses immutable or mutable Time types. + * The default changed in 4.0 to immutable types. You can uncomment + * below to switch back to mutable types. * * You can enable default locale format parsing by adding calls * to `useLocaleParser()`. This enables the automatic conversion of * locale specific date formats. For details see - * @link https://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html#parsing-localized-datetime-data - */ -Type::build('time') - ->useImmutable(); -Type::build('date') - ->useImmutable(); -Type::build('datetime') - ->useImmutable(); -Type::build('timestamp') - ->useImmutable(); + * @link https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html#parsing-localized-datetime-data + */ + \Cake\Database\TypeFactory::build('time') + ->useMutable(); + \Cake\Database\TypeFactory::build('date') + ->useMutable(); + \Cake\Database\TypeFactory::build('datetime') + ->useMutable(); + \Cake\Database\TypeFactory::build('timestamp') + ->useMutable(); +// \Cake\Database\TypeFactory::build('datetimefractional') +// ->useMutable(); +// \Cake\Database\TypeFactory::build('timestampfractional') +// ->useMutable(); +// \Cake\Database\TypeFactory::build('datetimetimezone') +// ->useMutable(); +// \Cake\Database\TypeFactory::build('timestamptimezone') +// ->useMutable(); + +// There is no time-specific type in Cake +TypeFactory::map('time', StringType::class); /* * Custom Inflector rules, can be set to correctly pluralize or singularize diff --git a/app/config/bootstrap_cli.php b/app/config/bootstrap_cli.php index 8f67c453f..fc0dc30bb 100644 --- a/app/config/bootstrap_cli.php +++ b/app/config/bootstrap_cli.php @@ -1,4 +1,6 @@ = 50.1 is needed to use CakePHP. Please update the `libicu` package of your system.' . PHP_EOL, E_USER_ERROR); } /* * You can remove this if you are confident you have mbstring installed. */ if (!extension_loaded('mbstring')) { - trigger_error('You must enable the mbstring extension to use CakePHP.' . PHP_EOL, E_USER_ERROR); + trigger_error('You must enable the mbstring extension to use CakePHP.', E_USER_ERROR); } diff --git a/app/config/routes.php b/app/config/routes.php index 31198f027..ae555ec0c 100644 --- a/app/config/routes.php +++ b/app/config/routes.php @@ -1,11 +1,14 @@ setRouteClass(DashedRoute::class); -Router::scope('/', function (RouteBuilder $routes) { - /** +$routes->scope('/', function (RouteBuilder $builder) { + /* * Here, we are connecting '/' (base path) to a controller called 'Pages', * its action called 'display', and we pass a param to select the view file - * to use (in this case, src/Template/Pages/home.ctp)... + * to use (in this case, templates/Pages/home.php)... */ - $routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']); + $builder->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']); - /** + /* * ...and connect the rest of 'Pages' controller's URLs. */ - $routes->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']); + $builder->connect('/pages/*', 'Pages::display'); /** * TIER ID Match API Routes */ // Match Request - $routes->get('/api/:matchgrid_id/v1/matchRequests/:id', ['controller' => 'TierApi', 'action' => 'viewMatchRequest']); - $routes->get('/api/:matchgrid_id/v1/matchRequests', ['controller' => 'TierApi', 'action' => 'viewMatchRequests']); - $routes->put('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'match']); - $routes->post('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'search']); + $builder->get('/api/:matchgrid_id/v1/matchRequests/:id', ['controller' => 'TierApi', 'action' => 'viewMatchRequest']); + $builder->get('/api/:matchgrid_id/v1/matchRequests', ['controller' => 'TierApi', 'action' => 'viewMatchRequests']); + $builder->put('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'match']); + $builder->post('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'search']); // This doesn't match and we end up in current(), so we just check there // Also, as of API v1.0.0, search over GET has been removed -// $routes->get('/api/:matchgrid_id/v1/people/:sor/:sorid?*', ['controller' => 'TierApi', 'action' => 'search']); - $routes->delete('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'remove']); - $routes->get('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'current']); - $routes->get('/api/:matchgrid_id/v1/people/:sor', ['controller' => 'TierApi', 'action' => 'inventory']); - $routes->put('/api/:matchgrid_id/v1/referenceIds/:id', ['controller' => 'TierApi', 'action' => 'merge']); +// $builder->get('/api/:matchgrid_id/v1/people/:sor/:sorid?*', ['controller' => 'TierApi', 'action' => 'search']); + $builder->delete('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'remove']); + $builder->get('/api/:matchgrid_id/v1/people/:sor/:sorid', ['controller' => 'TierApi', 'action' => 'current']); + $builder->get('/api/:matchgrid_id/v1/people/:sor', ['controller' => 'TierApi', 'action' => 'inventory']); + $builder->put('/api/:matchgrid_id/v1/referenceIds/:id', ['controller' => 'TierApi', 'action' => 'merge']); /** * Connect catchall routes for all controllers. * - * Using the argument `DashedRoute`, the `fallbacks` method is a shortcut for - * `$routes->connect('/:controller', ['action' => 'index'], ['routeClass' => 'DashedRoute']);` - * `$routes->connect('/:controller/:action/*', [], ['routeClass' => 'DashedRoute']);` + * The `fallbacks` method is a shortcut for * - * Any route class can be used with this method, such as: - * - DashedRoute - * - InflectedRoute - * - Route - * - Or your own route class + * ``` + * $builder->connect('/{controller}', ['action' => 'index']); + * $builder->connect('/{controller}/{action}/*', []); + * ``` * * You can remove these routes once you've connected the * routes you want in your application. */ - $routes->fallbacks(DashedRoute::class); + $builder->fallbacks(); }); -/** - * Load all plugin routes. See the Plugin documentation on - * how to customize the loading of plugin routes. +/* + * If you need a different set of middleware or none at all, + * open new scope and define routes there. + * + * ``` + * $routes->scope('/api', function (RouteBuilder $builder) { + * // No $builder->applyMiddleware() here. + * + * // Parse specified extensions from URLs + * // $builder->setExtensions(['json', 'xml']); * - * As of Cake v3.6 it is no longer necessary to call this - * Plugin::routes(); + * // Connect API actions here. + * }); + * ``` */ diff --git a/app/src/Locale/en_US/default.po b/app/resources/locales/en_US/default.po similarity index 100% rename from app/src/Locale/en_US/default.po rename to app/resources/locales/en_US/default.po diff --git a/app/src/Application.php b/app/src/Application.php index dd259775b..987dc7754 100644 --- a/app/src/Application.php +++ b/app/src/Application.php @@ -37,7 +37,22 @@ class Application extends BaseApplication { * @return \Cake\Http\MiddlewareQueue The updated middleware queue. */ - public function middleware($middlewareQueue) { + public function middleware($middlewareQueue): \Cake\Http\MiddlewareQueue { + // loading csrf Middleware + $csrf = new CsrfProtectionMiddleware(['cookieName' => 'matchCsrfToken']); + $csrf->whitelistCallback(function (ServerRequestInterface $request) { + // skip controllers + $skipedControllers = ['TierApi']; // Controllers list + if(in_array($request->getParam('controller'), $skipedControllers, true)) { + return true; + } + // skip debugkit + if($request->getParam('plugin') == 'DebugKit') { + return true; + } + return $request; + }); + $middlewareQueue // Catch any exceptions in the lower layers, // and make an error page/response @@ -57,19 +72,7 @@ public function middleware($middlewareQueue) { // https://stackoverflow.com/questions/47714940/cakephp-3-5-6-disable-csrf-middleware-for-controller // https://stackoverflow.com/questions/51931406/post-requests-for-cakephp-3-api-are-not-working - ->add(function(ServerRequestInterface $request, - ResponseInterface $response, - callable $next) { - $params = $request->getAttribute('params'); - - if($params['controller'] == 'TierApi') { - // Do not enable CsrfProtectionMiddleware - return $next($request, $response); - } else { - $csrf = new CsrfProtectionMiddleware(['cookieName' => 'matchCsrfToken']); - return $csrf($request, $response, $next); - } - }); + ->add($csrf); return $middlewareQueue; } diff --git a/app/src/Command/BulkLoadCommand.php b/app/src/Command/BulkLoadCommand.php index 7fa2912ff..ec29df1b3 100644 --- a/app/src/Command/BulkLoadCommand.php +++ b/app/src/Command/BulkLoadCommand.php @@ -52,7 +52,7 @@ class BulkLoadCommand extends Command { * @return ConsoleOptionParser Console Option Parser */ - public function buildOptionParser(ConsoleOptionParser $parser) { + public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser { $parser->addOption('matchgrid-id', [ 'help' => __('match.fd.matchgrid_id') ]) diff --git a/app/src/Command/SetupCommand.php b/app/src/Command/SetupCommand.php index f631308e7..e40d3dfc9 100644 --- a/app/src/Command/SetupCommand.php +++ b/app/src/Command/SetupCommand.php @@ -48,7 +48,7 @@ class SetupCommand extends Command { * @return ConsoleOptionParser Console Option Parser */ - public function buildOptionParser(ConsoleOptionParser $parser) { + public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser { $parser->addOption('admin-username', [ 'help' => __('match.cmd.opt.admin-username') ])->addOption('force', [ @@ -106,7 +106,7 @@ public function execute(Arguments $args, ConsoleIo $io) { $io->out(__('match.cmd.se.admin')); $permissionsTable = TableRegistry::get('Permissions'); - $permission = $permissionsTable->newEntity(); + $permission = $permissionsTable->newEmptyEntity(); $permission->username = $user; $permission->matchgrid_id = null; diff --git a/app/src/Controller/ApiUsersController.php b/app/src/Controller/ApiUsersController.php index 906565d81..af685adea 100644 --- a/app/src/Controller/ApiUsersController.php +++ b/app/src/Controller/ApiUsersController.php @@ -30,6 +30,7 @@ namespace App\Controller; use Cake\Routing\Router; +use Cake\Event\EventInterface; class ApiUsersController extends StandardController { public $pagination = [ @@ -42,10 +43,10 @@ class ApiUsersController extends StandardController { * Callback run prior to the view rendering. * * @since COmanage Match v1.0.0 - * @param Event $event Cake Event + * @param \Cake\Event\EventInterface $event Cake Event */ - public function beforeRender(\Cake\Event\Event $event) { + public function beforeRender(EventInterface $event) { parent::beforeRender($event); // Populate a pointer to the REST API for configuration purposes diff --git a/app/src/Controller/AppController.php b/app/src/Controller/AppController.php index a412c0d22..9520a197a 100644 --- a/app/src/Controller/AppController.php +++ b/app/src/Controller/AppController.php @@ -32,7 +32,7 @@ use Cake\Controller\Controller; use Cake\Datasource\Exception; use Cake\Datasource\Exception\RecordNotFoundException; -use Cake\Event\Event; +use Cake\Event\EventInterface; use Cake\ORM\TableRegistry; use InvalidArgumentException; @@ -50,7 +50,7 @@ class AppController extends Controller { * @since COmanage Match v1.0.0 */ - public function initialize() { + public function initialize(): void { parent::initialize(); // Load Components used by most or all controllers @@ -92,10 +92,10 @@ public function initialize() { * Callback run prior to the request action. * * @since COmanage Match v1.0.0 - * @param Event $event Cake Event + * @param \Cake\Event\EventInterface $event Cake Event */ - public function beforeFilter(\Cake\Event\Event $event) { + public function beforeFilter(EventInterface $event) { parent::beforeFilter($event); // Determine the timezone @@ -109,10 +109,10 @@ public function beforeFilter(\Cake\Event\Event $event) { * Callback run prior to the view rendering. * * @since COmanage Match v1.0.0 - * @param Event $event Cake Event + * @param \Cake\Event\EventInterface $event Cake Event */ - public function beforeRender(\Cake\Event\Event $event) { + public function beforeRender(EventInterface $event) { parent::beforeRender($event); // The current user, if authenticated diff --git a/app/src/Controller/Component/AuthorizationComponent.php b/app/src/Controller/Component/AuthorizationComponent.php index 59852cc6e..21e915b0c 100644 --- a/app/src/Controller/Component/AuthorizationComponent.php +++ b/app/src/Controller/Component/AuthorizationComponent.php @@ -43,7 +43,7 @@ class AuthorizationComponent extends Component { * @since COmanage Match v1.0.0 */ - public function initialize(array $config) { + public function initialize(array $config): void { parent::initialize($config); $this->Permissions = TableRegistry::get('Permissions'); @@ -188,6 +188,7 @@ public function menuPermissions($username, $matchgridId=null) { 'attribute_groups' => $platformAdmin || $mgAdmin, 'attribute_maps' => $platformAdmin || $mgAdmin, 'attributes' => $platformAdmin || $mgAdmin, + 'display' => $platformAdmin || $mgAdmin, // || $recMgr, this isn't yet implemented in the controller 'matchgrid_settings' => $platformAdmin || $mgAdmin, 'rules' => $platformAdmin || $mgAdmin, 'systems_of_record' => $platformAdmin || $mgAdmin, diff --git a/app/src/Controller/ErrorController.php b/app/src/Controller/ErrorController.php index b7d4231bd..c0778d91d 100644 --- a/app/src/Controller/ErrorController.php +++ b/app/src/Controller/ErrorController.php @@ -14,7 +14,7 @@ */ namespace App\Controller; -use Cake\Event\Event; +use Cake\Event\EventInterface; /** * Error Handling Controller @@ -28,7 +28,7 @@ class ErrorController extends AppController * * @return void */ - public function initialize() + public function initialize(): void { $this->loadComponent('RequestHandler'); } @@ -36,20 +36,20 @@ public function initialize() /** * beforeFilter callback. * - * @param \Cake\Event\Event $event Event. + * @param \Cake\Event\EventInterface $event Event. * @return \Cake\Http\Response|null|void */ - public function beforeFilter(Event $event) + public function beforeFilter(EventInterface $event) { } /** * beforeRender callback. * - * @param \Cake\Event\Event $event Event. + * @param \Cake\Event\EventInterface $event Event. * @return \Cake\Http\Response|null|void */ - public function beforeRender(Event $event) + public function beforeRender(EventInterface $event) { parent::beforeRender($event); @@ -59,7 +59,7 @@ public function beforeRender(Event $event) /** * afterFilter callback. * - * @param \Cake\Event\Event $event Event. + * @param \Cake\Event\EventInterface $event Event. * @return \Cake\Http\Response|null|void */ public function afterFilter(Event $event) diff --git a/app/src/Controller/MatchgridRecordsController.php b/app/src/Controller/MatchgridRecordsController.php index ab0c72b9b..28db151d4 100644 --- a/app/src/Controller/MatchgridRecordsController.php +++ b/app/src/Controller/MatchgridRecordsController.php @@ -32,6 +32,7 @@ use Cake\Log\Log; use Cake\ORM\TableRegistry; use Cake\Utility\Hash; +use Cake\Event\EventInterface; use \App\Lib\Enum\ConfidenceModeEnum; use \App\Lib\Match\AttributeManager; @@ -51,7 +52,7 @@ class MatchgridRecordsController extends StandardController { * @since COmanage Match v1.0.0 */ - public function initialize() { + public function initialize(): void { parent::initialize(); // In order to configure MatchgridRecords with the correct table name, we @@ -131,7 +132,7 @@ public function add() { // We could coerce validation errors into a newEntity, but we probably don't have them // $this->set('vv_obj', $this->MatchgridRecords->newEntity($this->request->getData())); // Create an empty entity for FormHelper - $this->set('vv_obj', $this->MatchgridRecords->newEntity()); + $this->set('vv_obj', $this->MatchgridRecords->newEmptyEntity()); // We can't call parent::add, since it will try to reprocess the save, so we have // to manually make some calls. @@ -156,10 +157,10 @@ public function add() { * Callback run prior to the view rendering. * * @since COmanage Match v1.0.0 - * @param Event $event Cake Event + * @param \Cake\Event\EventInterface $event Cake Event */ - public function beforeRender(\Cake\Event\Event $event) { + public function beforeRender(EventInterface $event) { parent::beforeRender($event); // Pull the Matchgrid configuration in order to pass the attribute configuration. @@ -304,7 +305,7 @@ public function edit($id) { return $this->redirect([ 'action' => 'edit', $id, - 'matchgrid_id' => $this->cur_mg->id + '?' => ['matchgrid_id' => $this->cur_mg->id] ]); } catch(\Exception $e) { @@ -412,7 +413,7 @@ protected function performMatch(MatchService $MatchService, string $sor, string 'controller' => 'matchgrids', 'action' => 'reconcile', $this->cur_mg->id, - 'rowid' => $matchRequest + '?' => ['rowid' => $matchRequest] ]); } @@ -421,7 +422,7 @@ protected function performMatch(MatchService $MatchService, string $sor, string return $this->redirect([ 'action' => 'edit', $id, - 'matchgrid_id' => $this->cur_mg->id + '?' => ['matchgrid_id' => $this->cur_mg->id] ]); } } \ No newline at end of file diff --git a/app/src/Controller/MatchgridSettingsController.php b/app/src/Controller/MatchgridSettingsController.php index c1fadc118..cfc94fa5d 100644 --- a/app/src/Controller/MatchgridSettingsController.php +++ b/app/src/Controller/MatchgridSettingsController.php @@ -29,6 +29,8 @@ namespace App\Controller; +use Cake\Event\EventInterface; + class MatchgridSettingsController extends StandardController { public $pagination = [ 'order' => [ @@ -40,10 +42,10 @@ class MatchgridSettingsController extends StandardController { * Callback run prior to the view rendering. * * @since COmanage Match v1.0.0 - * @param Event $event Cake Event + * @param \Cake\Event\EventInterface $event Cake Event */ - public function beforeRender(\Cake\Event\Event $event) { + public function beforeRender(EventInterface $event) { parent::beforeRender($event); // Override page title diff --git a/app/src/Controller/MatchgridsController.php b/app/src/Controller/MatchgridsController.php index 5577c4582..03c097ce8 100644 --- a/app/src/Controller/MatchgridsController.php +++ b/app/src/Controller/MatchgridsController.php @@ -31,6 +31,7 @@ use Cake\Log\Log; use \App\Lib\Enum\PermissionEnum; +use Cake\Event\EventInterface; class MatchgridsController extends StandardController { public $pagination = [ @@ -43,10 +44,10 @@ class MatchgridsController extends StandardController { * Callback run prior to the request action. * * @since COmanage Match v1.0.0 - * @param Event $event Cake Event + * @param \Cake\Event\EventInterface $event Cake Event */ - public function beforeFilter(\Cake\Event\Event $event) { + public function beforeFilter(EventInterface $event) { // Only certain actions require a matchgrid ID if(in_array($this->request->getParam('action'), ['build', 'manage', 'pending', 'reconcile'])) { @@ -206,7 +207,7 @@ public function reconcile(string $id) { ]); } else { // is get // Find and render the candidates for the pending record - + $rowId = (int)$this->request->getQuery('rowid'); if(!$rowId) { diff --git a/app/src/Controller/PagesController.php b/app/src/Controller/PagesController.php index 58f120679..5d9970d46 100644 --- a/app/src/Controller/PagesController.php +++ b/app/src/Controller/PagesController.php @@ -15,6 +15,7 @@ namespace App\Controller; use Cake\Core\Configure; +use Cake\Event\EventInterface; use Cake\Network\Exception\ForbiddenException; use Cake\Network\Exception\NotFoundException; use Cake\View\Exception\MissingTemplateException; @@ -32,10 +33,10 @@ class PagesController extends AppController * Callback run prior to the request action. * * @since COmanage Match v1.0.0 - * @param Event $event Cake Event + * @param \Cake\Event\EventInterface $event Cake Event */ - public function beforeFilter(\Cake\Event\Event $event) { + public function beforeFilter(EventInterface $event) { parent::beforeFilter($event); $param = $this->request->getParam('pass.0'); diff --git a/app/src/Controller/StandardController.php b/app/src/Controller/StandardController.php index b4f2a550d..0a10a6a35 100644 --- a/app/src/Controller/StandardController.php +++ b/app/src/Controller/StandardController.php @@ -64,7 +64,7 @@ public function add() { } else { // Create an empty entity for FormHelper - $this->set('vv_obj', $this->$modelsName->newEntity()); + $this->set('vv_obj', $this->$modelsName->newEmptyEntity()); } // PrimaryLinkTrait diff --git a/app/src/Controller/TierApiController.php b/app/src/Controller/TierApiController.php index 4e42cb50c..1d1b80f36 100644 --- a/app/src/Controller/TierApiController.php +++ b/app/src/Controller/TierApiController.php @@ -49,7 +49,7 @@ class TierApiController extends AppController { * @since COmanage Match v1.0.0 */ - public function initialize() { + public function initialize(): void { // We have substantial differences from AppController::initialize(), so we // completely override here. diff --git a/app/src/Lib/Match/MatchService.php b/app/src/Lib/Match/MatchService.php index 14689870f..c64433b43 100644 --- a/app/src/Lib/Match/MatchService.php +++ b/app/src/Lib/Match/MatchService.php @@ -29,18 +29,15 @@ namespace App\Lib\Match; -use Cake\Datasource\ConnectionInterface; -use Cake\Datasource\ConnectionManager; use Cake\Log\Log; use Cake\ORM\TableRegistry; -use Cake\Utility\Xml; use \App\Lib\Enum\ConfidenceModeEnum; use \App\Lib\Enum\ReferenceIdEnum; use \App\Lib\Enum\SearchTypeEnum; use \App\Lib\Enum\StatusEnum; -require(ROOT . DS . "vendor" . DS . "adodb" . DS . "adodb-php" . DS . "adodb-xmlschema03.inc.php"); +require_once ROOT . DS . "vendor" . DS . "adodb" . DS . "adodb-php" . DS . "adodb-xmlschema03.inc.php"; class MatchService extends PostgresService { protected $mgConfig = null; diff --git a/app/src/Lib/Match/MatchgridBuilder.php b/app/src/Lib/Match/MatchgridBuilder.php index 3fad3c87e..956fc5bb4 100644 --- a/app/src/Lib/Match/MatchgridBuilder.php +++ b/app/src/Lib/Match/MatchgridBuilder.php @@ -105,7 +105,6 @@ protected function configToSchema($dbc, \Cake\Datasource\EntityInterface $Matchg // Track which attributes need case insensitive indexes $ciAttrs = []; - if($indexes) { // Since index names need to be unique across the schema, we'll use the // matchgrid ID to make the names unique. @@ -128,9 +127,9 @@ protected function configToSchema($dbc, \Cake\Datasource\EntityInterface $Matchg foreach($attributes as $attr) { // We use the Entity ID to provide some level of reproducibility $indexName = 'matchgrid_' . $Matchgrid->id . '_attr_id' . $attr->id; - + $table->addIndex([$attr->name], $indexName, $flags, $options); - + if(!$attr->case_sensitive) { $ciAttrs[$indexName] = $attr->name; } @@ -167,12 +166,10 @@ protected function configToSchema($dbc, \Cake\Datasource\EntityInterface $Matchg $sql = rtrim($sql, ")") . " NULLS FIRST)"; } elseif(preg_match("/^CREATE INDEX (\w+) ON .*/", $sql, $matches)) { $attr = $ciAttrs[ $matches[1] ]; - // Not ideal to hardcode SQL, but this should be pretty portable. // Note the validation rule for table_name and attr is pretty restrictive, // so we don't need to SQL escape them. Similarly, we create the index // name above. - // We use IF NOT EXISTS to avoid errors on rebuilding the matchgrid, // however a better long term solution would be to add native support to // DBAL for expression in index creation (CO-2217). diff --git a/app/src/Model/Table/ApiUsersTable.php b/app/src/Model/Table/ApiUsersTable.php index 44d7f3f5a..aa43a16aa 100644 --- a/app/src/Model/Table/ApiUsersTable.php +++ b/app/src/Model/Table/ApiUsersTable.php @@ -48,7 +48,7 @@ class ApiUsersTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -83,7 +83,7 @@ public function initialize(array $config) { * @return RulesChecker Cake RulesChecker */ - public function buildRules(RulesChecker $rules) { + public function buildRules(RulesChecker $rules): RulesChecker { $rules->add( [$this, 'checkUsername'], 'checkUsername', @@ -164,24 +164,24 @@ public function findAuthorization(\Cake\ORM\Query $query, array $options) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'username', 'length', [ 'rule' => [ 'maxLength', 128 ] ] ); // notEmpty is old style, use notBlank - $validator->notBlank('username'); + $validator->notEmptyString('username'); $validator->add( 'password', 'length', [ 'rule' => [ 'maxLength', 80 ] ] ); - $validator->notBlank('password'); + $validator->notEmptyString('password'); $validator->add( 'matchgrid_id', diff --git a/app/src/Model/Table/AttributeGroupsTable.php b/app/src/Model/Table/AttributeGroupsTable.php index f54bd1ed1..b1c4b86a2 100644 --- a/app/src/Model/Table/AttributeGroupsTable.php +++ b/app/src/Model/Table/AttributeGroupsTable.php @@ -43,7 +43,7 @@ class AttributeGroupsTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -60,10 +60,10 @@ public function initialize(array $config) { * Set validation rules. * * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'name', 'length', diff --git a/app/src/Model/Table/AttributeMappingsTable.php b/app/src/Model/Table/AttributeMappingsTable.php index 7c2a81173..26c85f8fb 100644 --- a/app/src/Model/Table/AttributeMappingsTable.php +++ b/app/src/Model/Table/AttributeMappingsTable.php @@ -44,7 +44,7 @@ class AttributeMappingsTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -105,7 +105,7 @@ public function install(int $attributeMapId, string $mapping) { foreach($namemap as $q => $vs) { foreach($vs as $v => $status) { if(!isset($curmap[$q][$v])) { - $mapping = $this->newEntity(); + $mapping = $this->newEmptyEntity(); $mapping->attribute_map_id = $attributeMapId; $mapping->query = $q; @@ -126,10 +126,10 @@ public function install(int $attributeMapId, string $mapping) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'query', 'length', diff --git a/app/src/Model/Table/AttributeMapsTable.php b/app/src/Model/Table/AttributeMapsTable.php index 1b7aca330..983e1da90 100644 --- a/app/src/Model/Table/AttributeMapsTable.php +++ b/app/src/Model/Table/AttributeMapsTable.php @@ -44,7 +44,7 @@ class AttributeMapsTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -66,10 +66,10 @@ public function initialize(array $config) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'name', 'length', diff --git a/app/src/Model/Table/AttributesTable.php b/app/src/Model/Table/AttributesTable.php index 15d0d4b24..ae0751732 100644 --- a/app/src/Model/Table/AttributesTable.php +++ b/app/src/Model/Table/AttributesTable.php @@ -45,7 +45,7 @@ class AttributesTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -81,10 +81,10 @@ public function initialize(array $config) { * Set validation rules. * * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'name', 'length', diff --git a/app/src/Model/Table/MatchgridRecordsTable.php b/app/src/Model/Table/MatchgridRecordsTable.php index 52150ba12..871b9a432 100644 --- a/app/src/Model/Table/MatchgridRecordsTable.php +++ b/app/src/Model/Table/MatchgridRecordsTable.php @@ -45,7 +45,7 @@ class MatchgridRecordsTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->setPrimaryLink('matchgrid_id'); $this->setRequiresMatchgrid(true); // We allow unkeyed primary link here because a record ID is not by itself @@ -86,10 +86,10 @@ public function initialize(array $config) { * Set validation rules. * * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator * - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { // We don't do validation here since MatchService should handle that }*/ } \ No newline at end of file diff --git a/app/src/Model/Table/MatchgridSettingsTable.php b/app/src/Model/Table/MatchgridSettingsTable.php index b3c8e87b1..e91355f12 100644 --- a/app/src/Model/Table/MatchgridSettingsTable.php +++ b/app/src/Model/Table/MatchgridSettingsTable.php @@ -56,7 +56,7 @@ class MatchgridSettingsTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { // Timestamp behavior handles created/modified updates $this->addBehavior('Timestamp'); @@ -175,10 +175,10 @@ protected function lookupValue(int $matchgridId, string $field) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'matchgrid_id', 'content', diff --git a/app/src/Model/Table/MatchgridsTable.php b/app/src/Model/Table/MatchgridsTable.php index 99003e239..c4968bd2f 100644 --- a/app/src/Model/Table/MatchgridsTable.php +++ b/app/src/Model/Table/MatchgridsTable.php @@ -50,7 +50,7 @@ class MatchgridsTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { // Timestamp behavior handles created/modified updates $this->addBehavior('Timestamp'); @@ -164,10 +164,10 @@ public function getMatchgridConfig($id) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'table_name', 'length', diff --git a/app/src/Model/Table/MetaTable.php b/app/src/Model/Table/MetaTable.php index 512c67810..afdcf3ab8 100644 --- a/app/src/Model/Table/MetaTable.php +++ b/app/src/Model/Table/MetaTable.php @@ -46,7 +46,7 @@ class MetaTable extends Table { public function setUpgradeVersion($version) { // XXX log this? print "Setting version to " . $version . "\n"; - $meta = $this->newEntity(); + $meta = $this->newEmptyEntity(); $meta->id = 1; $meta->upgrade_version = $version; @@ -62,10 +62,10 @@ public function setUpgradeVersion($version) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'upgrade_version', 'length', diff --git a/app/src/Model/Table/PermissionsTable.php b/app/src/Model/Table/PermissionsTable.php index 0132d35f3..285e95b2c 100644 --- a/app/src/Model/Table/PermissionsTable.php +++ b/app/src/Model/Table/PermissionsTable.php @@ -45,7 +45,7 @@ class PermissionsTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -88,10 +88,10 @@ public function findForUser(string $username) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'username', 'length', diff --git a/app/src/Model/Table/RuleAttributesTable.php b/app/src/Model/Table/RuleAttributesTable.php index 3bf702c0f..444f8299f 100644 --- a/app/src/Model/Table/RuleAttributesTable.php +++ b/app/src/Model/Table/RuleAttributesTable.php @@ -47,7 +47,7 @@ class RuleAttributesTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -89,10 +89,10 @@ public function initialize(array $config) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'rule_id', 'content', diff --git a/app/src/Model/Table/RulesTable.php b/app/src/Model/Table/RulesTable.php index 9d34caaba..6cd173f32 100644 --- a/app/src/Model/Table/RulesTable.php +++ b/app/src/Model/Table/RulesTable.php @@ -47,7 +47,7 @@ class RulesTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -76,10 +76,10 @@ public function initialize(array $config) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'name', 'length', diff --git a/app/src/Model/Table/SystemsOfRecordTable.php b/app/src/Model/Table/SystemsOfRecordTable.php index 864c8658f..53ff8d5ed 100644 --- a/app/src/Model/Table/SystemsOfRecordTable.php +++ b/app/src/Model/Table/SystemsOfRecordTable.php @@ -46,7 +46,7 @@ class SystemsOfRecordTable extends Table { * @param array $config Configuration options passed to constructor */ - public function initialize(array $config) { + public function initialize(array $config): void { $this->addBehavior('Timestamp'); // Define associations @@ -72,10 +72,10 @@ public function initialize(array $config) { * * @since COmanage Match v1.0.0 * @param Validator $validator Validator - * @return $validator Validator + * @return \Cake\Validation\Validator Validator */ - public function validationDefault(Validator $validator) { + public function validationDefault(Validator $validator): Validator { $validator->add( 'label', 'length', diff --git a/app/src/Shell/ConsoleShell.php b/app/src/Shell/ConsoleShell.php index 2eb9395e3..020970934 100644 --- a/app/src/Shell/ConsoleShell.php +++ b/app/src/Shell/ConsoleShell.php @@ -64,7 +64,7 @@ public function main() * * @return \Cake\Console\ConsoleOptionParser */ - public function getOptionParser() + public function getOptionParser(): ConsoleOptionParser { $parser = new ConsoleOptionParser('console'); $parser->setDescription( diff --git a/app/src/Template/Element/breadcrumbs.ctp b/app/src/Template/Element/breadcrumbs.ctp deleted file mode 100644 index a3aa92700..000000000 --- a/app/src/Template/Element/breadcrumbs.ctp +++ /dev/null @@ -1,127 +0,0 @@ -request->getRequestTarget(false) != '/') { - // Don't bother rendering breadcrumbs if we're already at the top page - - $action = $this->template; - // $this->name = Models - $modelsName = $this->name; - - $this->Breadcrumbs->setTemplates([ - 'wrapper' => '{{content}}', - 'item' => '{{title}}{{separator}}', - 'itemWithoutLink' => '{{title}}{{separator}}', - 'separator' => '{{separator}}' - ]); - - $this->Breadcrumbs->prepend( - __('match.meta.match'), - ['controller' => 'matchgrids', - 'action' => 'select'] - ); - - if(!empty($vv_cur_mg) - && ($modelsName != 'Matchgrids' || $action != 'manage')) { - // Link to matchgrid if set - $this->Breadcrumbs->add( - $vv_cur_mg->table_name, - ['controller' => 'matchgrids', - 'action' => 'manage', - $vv_cur_mg->id ] - ); - } - - if(!empty($vv_primary_link_obj) - && !empty($vv_primary_link_model) - && $vv_primary_link_model != 'Matchgrids') { - // If the primary link is not matchgrid, render a link to it (and the parent index). - // We'll need to calculate the controller name. - - if(!empty($vv_cur_mg->id)) { - // We currently assume the parent of a primary link is matchgrid, which - // might or might not always be true in the future. - $this->Breadcrumbs->add( - __('match.ct.'.$vv_primary_link_model, [99]), - ['controller' => \Cake\Utility\Inflector::dasherize($vv_primary_link_model), - 'action' => 'index', - 'matchgrid_id' => $vv_cur_mg->id] - ); - } - - $this->Breadcrumbs->add( - $vv_primary_link_obj->name, - ['controller' => \Cake\Utility\Inflector::dasherize($vv_primary_link_model), - 'action' => 'edit', - $vv_primary_link_obj->id] - ); - } - - if($action != 'index' && $action != 'manage' - && !($modelsName == 'Matchgrids' && $action == 'pending')) { - - // Default parent is index, to which we might need to append the Primary Link ID - $crumbLinkText = 'match.ct.'.$modelsName; - - $target = [ - 'controller' => Inflector::dasherize($modelsName), - 'action' => 'index' - ]; - - if(!empty($vv_primary_link) && !empty($vv_primary_link_obj->id)) { - $target[$vv_primary_link] = $vv_primary_link_obj->id; - } - - // Non-index special cases - if ($modelsName == 'Matchgrids' && $action == 'reconcile') { - $crumbLinkText = 'match.ac.PendingRequests'; - $target = [ - 'controller' => Inflector::dasherize($modelsName), - 'action' => 'pending', - $vv_cur_mg->id // will always be set for reconcile - ]; - } - - $this->Breadcrumbs->add( - __($crumbLinkText, [99]), - $target - ); - } - - if(!empty($vv_title)) { - $this->Breadcrumbs->add( - $vv_title - ); - } - - print $this->Breadcrumbs->render( - [], - ['separator' => ' > '] - ); -} \ No newline at end of file diff --git a/app/src/Template/Element/menuMain.ctp b/app/src/Template/Element/menuMain.ctp deleted file mode 100644 index 2eb32feb0..000000000 --- a/app/src/Template/Element/menuMain.ctp +++ /dev/null @@ -1,69 +0,0 @@ - -
diff --git a/app/src/Template/Element/menuTop.ctp b/app/src/Template/Element/menuTop.ctp deleted file mode 100644 index ab4251581..000000000 --- a/app/src/Template/Element/menuTop.ctp +++ /dev/null @@ -1,108 +0,0 @@ - - -| = __('match.fd.sor'); ?> | -= __('match.fd.sorid'); ?> | -= __('match.fd.request_time'); ?> | -
|---|---|---|
| - = $p['sor']; ?> - | -- = $this->Html->link( - $p['sorid'], - ['action' => 'reconcile', $vv_matchgrid_id, 'rowid' => $p['id']], - ['class' => 'row-link'] - ); ?> - | -- = $p['request_time']; ?> - | -
| Paginator->sort($cfg['sortable'], $label); - } else { - print $this->Paginator->sort($col, $label); - } - } else { - print $label; - } - ?> | - -= __($product.'.fd.action'); ?> | -
|---|---|
| - $col) && $entity->$col) { - print __($product.'.en.'.$cfg['class'].'.1'); - } else { - print __($product.'.en.'.$cfg['class'].'.0'); - } - break; - case 'datetime': - // XXX dates can also be rendered as eg $entity->created->format(DATE_RFC850); - print $this->Time->nice($entity->$col, $vv_tz); - break; - case 'enum': - if($entity->$col) { - print __($product.'.en.'.$cfg['class'].'.'.$entity->$col); - } - break; - case 'fk': - // Assuming $col is of the form foo_id, look to see if the corresponding - // AutoViewVar $foos is set, and if so render the lookup value instead - $f = null; - if(preg_match('/^(.*?)_id$/', $col, $f)) { - $avv = Inflector::variable(Inflector::pluralize($f[1])); - - if(!empty(${$avv}[$entity->$col])) { - // We found the viewvar (eg: $foos), and it has a corresponding value - // (eg: $foos[3]), so render it - print ${$avv}[$entity->$col]; // XXX filter_var? - } else { - // No match, just render the value - print $entity->$col; - } - } else { - // Just print the value - print $entity->$col; - } - break; - case 'link': - case 'echo': - default: - // By default our label is the column value, but it might be overridden - $label = $entity->$col; - - if(!empty($cfg['model']) && !empty($cfg['field'])) { - $m = $cfg['model']; - $f = $cfg['field']; - - if(!empty($entity->$m->$f)) { - $label = $entity->$m->$f; - } - } - - $linked = false; - - if($cfg['type'] == 'link') { - foreach($linkActions as $a) { - // Does this user have permission for this action? - if($vv_permissions[$a]) { - print $this->Html->link($label, ['action' => $a, $entity->id]); - $linked = true; - break 2; - } - } - } - - if(!$linked) { - // Just echo the value - print $label; - } - break; - // XXX dates can be rendered as eg $entity->created->format(DATE_RFC850); - } - ?> - | - -- Html->link( - __($product.'.op.edit'), - array_merge(['action' => 'edit'], $linkArgs), - ['class' => 'editbutton'] - ); - } - - if(isset($vv_permissions['duplicate']) && $vv_permissions['duplicate']) { - print $this->Html->link( - __($product.'.op.duplicate'), - array_merge(['action' => 'duplicate'], $linkArgs), - ['class' => 'copybutton'] - ); - } - - if($vv_permissions['delete']) { - // XXX this is throwing CSRF error even though delete button on edit-record page is working? - // probably because this is using Form helper, but we're outside of a form? - print $this->Form->postLink( - __($product.'.op.delete'), - array_merge(['action' => 'delete'], $linkArgs), - // XXX should be configurable which field we put in, maybe displayField? - ['confirm' => __($product.'.op.delete.confirm', [$entity->id]), - 'class' => 'deletebutton'] - ); - } - - if(!empty($indexActions)) { - // Insert additional actions as per the .inc file - - if(!isset($entity->status) || $entity->status == StatusEnum::Active) { - foreach($indexActions as $a) { - if($vv_permissions[ $a['action'] ]) { - // If we have a .confirm text, use postLink instead - - $confirmKey = $product.'.op.'.$a['action'].'.confirm'; - $confirmTxt = __($confirmKey); - - if($confirmTxt != $confirmKey) { - // We found the localized string - - print $this->Form->postLink( - __($product.'.op.' . $a['action']), - array_merge(['action' => $a['action']], $linkArgs), - // XXX should be configurable which field we put in, maybe displayField? - ['confirm' => __($confirmKey, [$entity->id]), - 'class' => $a['class']] - ); - } elseif(!empty($a['controller'])) { - // We're linking into a related controller - print $this->Html->link( - __('match.ct.' . Inflector::camelize(Inflector::pluralize($a['controller'])), [99]), - ['controller' => $a['controller'], - 'action' => $a['action'], - $tableFK => $entity->id], - ['class' => $a['class']] - ); - } else { - print $this->Html->link( - __($product.'.op.' . $a['action']), - array_merge(['action' => $a['action']], $linkArgs), - ['class' => $a['class']] - ); - } - } - } - } - } - ?> - | -
| = __('match.fd.sor'); ?> | += __('match.fd.sorid'); ?> | += __('match.fd.request_time'); ?> | +
|---|---|---|
| + = $p['sor']; ?> + | ++ = $this->Html->link( + $p['sorid'], + ['action' => 'reconcile', + $vv_matchgrid_id, + '?' => [ 'rowid' => $p['id'] ] ], + ['class' => 'row-link'] + ); ?> + | ++ = $p['request_time']; ?> + | +
| Paginator->sort($cfg['sortable'], $label); + } else { + print $this->Paginator->sort($col, $label); + } + } else { + print $label; + } + ?> | + += __($product.'.fd.action'); ?> | +
|---|---|
| + $col) && $entity->$col) { + print __($product.'.en.'.$cfg['class'].'.1'); + } else { + print __($product.'.en.'.$cfg['class'].'.0'); + } + break; + case 'datetime': + // XXX dates can also be rendered as eg $entity->created->format(DATE_RFC850); + print $this->Time->nice($entity->$col, $vv_tz); + break; + case 'enum': + if($entity->$col) { + print __($product.'.en.'.$cfg['class'].'.'.$entity->$col); + } + break; + case 'fk': + // Assuming $col is of the form foo_id, look to see if the corresponding + // AutoViewVar $foos is set, and if so render the lookup value instead + $f = null; + if(preg_match('/^(.*?)_id$/', $col, $f)) { + $avv = Inflector::variable(Inflector::pluralize($f[1])); + + if(!empty(${$avv}[$entity->$col])) { + // We found the viewvar (eg: $foos), and it has a corresponding value + // (eg: $foos[3]), so render it + print ${$avv}[$entity->$col]; // XXX filter_var? + } else { + // No match, just render the value + print $entity->$col; + } + } else { + // Just print the value + print $entity->$col; + } + break; + case 'link': + case 'echo': + default: + // By default our label is the column value, but it might be overridden + $label = $entity->$col; + + if(!empty($cfg['model']) && !empty($cfg['field'])) { + $m = $cfg['model']; + $f = $cfg['field']; + + if(!empty($entity->$m->$f)) { + $label = $entity->$m->$f; + } + } + + $linked = false; + + if($cfg['type'] == 'link') { + foreach($linkActions as $a) { + // Does this user have permission for this action? + if($vv_permissions[$a]) { + print $this->Html->link($label, ['action' => $a, $entity->id]); + $linked = true; + break 2; + } + } + } + + if(!$linked) { + // Just echo the value + print $label; + } + break; + // XXX dates can be rendered as eg $entity->created->format(DATE_RFC850); + } + ?> + | + ++ Html->link( + __($product.'.op.edit'), + array_merge_recursive(['action' => 'edit'], $linkArgs), + ['class' => 'editbutton'] + ); + } + + if(isset($vv_permissions['duplicate']) && $vv_permissions['duplicate']) { + print $this->Html->link( + __($product.'.op.duplicate'), + array_merge_recursive(['action' => 'duplicate'], $linkArgs), + ['class' => 'copybutton'] + ); + } + + if($vv_permissions['delete']) { + // XXX this is throwing CSRF error even though delete button on edit-record page is working? + // probably because this is using Form helper, but we're outside of a form? + print $this->Form->postLink( + __($product.'.op.delete'), + array_merge_recursive(['action' => 'delete'], $linkArgs), + // XXX should be configurable which field we put in, maybe displayField? + ['confirm' => __($product.'.op.delete.confirm', [$entity->id]), + 'class' => 'deletebutton'] + ); + } + + if(!empty($indexActions)) { + // Insert additional actions as per the .inc file + + if(!isset($entity->status) || $entity->status == StatusEnum::Active) { + foreach($indexActions as $a) { + if($vv_permissions[ $a['action'] ]) { + // If we have a .confirm text, use postLink instead + + $confirmKey = $product.'.op.'.$a['action'].'.confirm'; + $confirmTxt = __($confirmKey); + + if($confirmTxt != $confirmKey) { + // We found the localized string + + print $this->Form->postLink( + __($product.'.op.' . $a['action']), + array_merge_recursive(['action' => $a['action']], $linkArgs), + // XXX should be configurable which field we put in, maybe displayField? + ['confirm' => __($confirmKey, [$entity->id]), + 'class' => $a['class']] + ); + } elseif(!empty($a['controller'])) { + // We're linking into a related controller + print $this->Html->link( + __('match.ct.' . Inflector::camelize(Inflector::pluralize($a['controller'])), [99]), + ['controller' => $a['controller'], + 'action' => $a['action'], + '?' => [ $tableFK => $entity->id] ], + ['class' => $a['class']] + ); + } else { + print $this->Html->link( + __($product.'.op.' . $a['action']), + array_merge_recursive(['action' => $a['action']], $linkArgs), + ['class' => $a['class']] + ); + } + } + } + } + } + ?> + | +
paragraph
\n\ncode\n\n";
- $this->assertEquals($expectedOutput, $this->getEngine()->transform($content));
- }
-
- /**
- * Test that the generated code looks as expected
- *
- * @dataProvider getTests
- */
- public function testCompile($node, $source, $environment = null)
- {
- parent::testCompile($node, $source, $environment);
- }
-
- protected function getEngine()
- {
- return new MichelfMarkdownEngine();
- }
-
- public function getTests()
- {
- $tests = array();
-
- $body = new \Twig_Node(array(new \Twig_Node_Text("#Title\n\nparagraph\n", 1)));
- $node = new MarkdownNode($body, 1);
-
- $tests['simple text'] = array($node, <<new Filesystem()
+ findRecursive
+ new Filesystem()
+ find
+ | = $this->Paginator->sort('{{ field }}') ?> | -{% endfor %} -= __('Actions') ?> | -||
|---|---|---|---|
| = ${{ singularVar }}->has('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?> | -{% endfor %} -{% endif %} -{% if isKey is not same as(true) %} -{% set columnData = Bake.columnData(field, schema) %} -{% if columnData.type not in ['integer', 'float', 'decimal', 'biginteger', 'smallinteger', 'tinyinteger'] %} -= h(${{ singularVar }}->{{ field }}) ?> | -{% else %} -= $this->Number->format(${{ singularVar }}->{{ field }}) ?> | -{% endif %} -{% endif %} -{% endfor %} -{% set pk = '$' ~ singularVar ~ '->' ~ primaryKey[0] %} -- = $this->Html->link(__('View'), ['action' => 'view', {{ pk|raw }}]) ?> - = $this->Html->link(__('Edit'), ['action' => 'edit', {{ pk|raw }}]) ?> - = $this->Form->postLink(__('Delete'), ['action' => 'delete', {{ pk|raw }}], ['confirm' => __('Are you sure you want to delete # {0}?', {{ pk|raw }})]) ?> - | -
= $this->Paginator->counter(['format' => __('Page {{ '{{' }}page{{ '}}' }} of {{ '{{' }}pages{{ '}}' }}, showing {{ '{{' }}current{{ '}}' }} record(s) out of {{ '{{' }}count{{ '}}' }} total')]) ?>
-| = __('{{ details.property|humanize }}') ?> | -= ${{ singularVar }}->has('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?> | -
|---|---|
| = __('{{ field|humanize }}') ?> | -= h(${{ singularVar }}->{{ field }}) ?> | -
| = __('{{ alias|underscore|singularize|humanize }}') ?> | -= ${{ singularVar }}->has('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?> | -
| = __('{{ field|humanize }}') ?> | -= $this->Number->format(${{ singularVar }}->{{ field }}) ?> | -
| = __('{{ field|humanize }}') ?> | -= h(${{ singularVar }}->{{ field }}) ?> | -
| = __('{{ field|humanize }}') ?> | -= ${{ singularVar }}->{{ field }} ? __('Yes') : __('No'); ?> | -
| = $this->Paginator->sort('{{ field }}') ?> | +{% endfor %} += __('Actions') ?> | +||
|---|---|---|---|
| = ${{ singularVar }}->has('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?> | +{% endif %} +{% endfor %} +{% endif %} +{% if isKey is not same as(true) %} +{% set columnData = Bake.columnData(field, schema) %} +{% if columnData.type not in ['integer', 'float', 'decimal', 'biginteger', 'smallinteger', 'tinyinteger'] %} += h(${{ singularVar }}->{{ field }}) ?> | +{% else %} += $this->Number->format(${{ singularVar }}->{{ field }}) ?> | +{% endif %} +{% endif %} +{% endfor %} +{% set pk = '$' ~ singularVar ~ '->' ~ primaryKey[0] %} ++ = $this->Html->link(__('View'), ['action' => 'view', {{ pk|raw }}]) ?> + = $this->Html->link(__('Edit'), ['action' => 'edit', {{ pk|raw }}]) ?> + = $this->Form->postLink(__('Delete'), ['action' => 'delete', {{ pk|raw }}], ['confirm' => __('Are you sure you want to delete # {0}?', {{ pk|raw }})]) ?> + | +
= $this->Paginator->counter(__('Page {{ '{{' }}page{{ '}}' }} of {{ '{{' }}pages{{ '}}' }}, showing {{ '{{' }}current{{ '}}' }} record(s) out of {{ '{{' }}count{{ '}}' }} total')) ?>
+| = __('{{ details.property|humanize }}') ?> | += ${{ singularVar }}->has('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?> | +
|---|---|
| = __('{{ field|humanize }}') ?> | += h(${{ singularVar }}->{{ field }}) ?> | +
| = __('{{ alias|underscore|singularize|humanize }}') ?> | += ${{ singularVar }}->has('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?> | +
| = __('{{ field|humanize }}') ?> | += $this->Number->format(${{ singularVar }}->{{ field }}) ?> | +
| = __('{{ field|humanize }}') ?> | += h(${{ singularVar }}->{{ field }}) ?> | +
| = __('{{ field|humanize }}') ?> | += ${{ singularVar }}->{{ field }} ? __('Yes') : __('No'); ?> | +
+ = $this->Text->autoParagraph(h(${{ singularVar }}->{{ field }})); ?> ++
` tags around the output of given variable. Similar to debug().
+ * print_r() will also wrap tags around the output of given variable. Similar to debug().
*
* This function returns the same variable that was passed.
*
* @param mixed $var Variable to print out.
* @return mixed the same $var that was passed to this function
- * @link https://book.cakephp.org/3/en/core-libraries/global-constants-and-functions.html#pr
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#pr
* @see debug()
*/
function pr($var)
@@ -150,7 +144,7 @@ function pr($var)
return $var;
}
- $template = (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') ? '%s
' : "\n%s\n\n";
+ $template = PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' ? '%s
' : "\n%s\n\n";
printf($template, trim(print_r($var, true)));
return $var;
@@ -163,14 +157,14 @@ function pr($var)
* json pretty print convenience function.
*
* In terminals this will act similar to using json_encode() with JSON_PRETTY_PRINT directly, when not run on cli
- * will also wrap `` tags around the output of given variable. Similar to pr().
+ * will also wrap tags around the output of given variable. Similar to pr().
*
* This function returns the same variable that was passed.
*
* @param mixed $var Variable to print out.
* @return mixed the same $var that was passed to this function
* @see pr()
- * @link https://book.cakephp.org/3/en/core-libraries/global-constants-and-functions.html#pj
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#pj
*/
function pj($var)
{
@@ -178,8 +172,8 @@ function pj($var)
return $var;
}
- $template = (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') ? '%s
' : "\n%s\n\n";
- printf($template, trim(json_encode($var, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)));
+ $template = PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' ? '%s
' : "\n%s\n\n";
+ printf($template, trim(json_encode($var, JSON_PRETTY_PRINT)));
return $var;
}
@@ -196,16 +190,16 @@ function pj($var)
* @param string $key Environment variable name.
* @param string|bool|null $default Specify a default value in case the environment variable is not defined.
* @return string|bool|null Environment variable setting.
- * @link https://book.cakephp.org/3/en/core-libraries/global-constants-and-functions.html#env
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#env
*/
- function env($key, $default = null)
+ function env(string $key, $default = null)
{
if ($key === 'HTTPS') {
if (isset($_SERVER['HTTPS'])) {
- return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
+ return !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
}
- return (strpos((string)env('SCRIPT_URI'), 'https://') === 0);
+ return strpos((string)env('SCRIPT_URI'), 'https://') === 0;
}
if ($key === 'SCRIPT_NAME' && env('CGI_MODE') && isset($_ENV['SCRIPT_URL'])) {
@@ -234,8 +228,8 @@ function env($key, $default = null)
switch ($key) {
case 'DOCUMENT_ROOT':
- $name = env('SCRIPT_NAME');
- $filename = env('SCRIPT_FILENAME');
+ $name = (string)env('SCRIPT_NAME');
+ $filename = (string)env('SCRIPT_FILENAME');
$offset = 0;
if (!strpos($name, '.php')) {
$offset = 4;
@@ -243,9 +237,9 @@ function env($key, $default = null)
return substr($filename, 0, -(strlen($name) + $offset));
case 'PHP_SELF':
- return str_replace(env('DOCUMENT_ROOT'), '', env('SCRIPT_FILENAME'));
+ return str_replace((string)env('DOCUMENT_ROOT'), '', (string)env('SCRIPT_FILENAME'));
case 'CGI_MODE':
- return (PHP_SAPI === 'cgi');
+ return PHP_SAPI === 'cgi';
}
return $default;
@@ -260,7 +254,7 @@ function env($key, $default = null)
* @param string $message The warning message.
* @return void
*/
- function triggerWarning($message)
+ function triggerWarning(string $message): void
{
$stackFrame = 1;
$trace = debug_backtrace();
@@ -287,7 +281,7 @@ function triggerWarning($message)
* as that should point to application/plugin code.
* @return void
*/
- function deprecationWarning($message, $stackFrame = 1)
+ function deprecationWarning(string $message, int $stackFrame = 1): void
{
if (!(error_reporting() & E_USER_DEPRECATED)) {
return;
@@ -319,7 +313,7 @@ function deprecationWarning($message, $stackFrame = 1)
* @param mixed $var Variable to check
* @return string Returns the class name or variable type
*/
- function getTypeName($var)
+ function getTypeName($var): string
{
return is_object($var) ? get_class($var) : gettype($var);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Connection.php b/app/vendor/cakephp/cakephp/src/Database/Connection.php
index cd06f05d5..e5c597d92 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Connection.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Connection.php
@@ -1,4 +1,6 @@
_config = $config;
@@ -128,7 +142,7 @@ public function __construct($config)
$this->setDriver($driver, $config);
if (!empty($config['log'])) {
- $this->enableQueryLogging($config['log']);
+ $this->enableQueryLogging((bool)$config['log']);
}
}
@@ -139,23 +153,23 @@ public function __construct($config)
*/
public function __destruct()
{
- if ($this->_transactionStarted && class_exists('Cake\Log\Log')) {
+ if ($this->_transactionStarted && class_exists(Log::class)) {
Log::warning('The connection is going to be closed but there is an active transaction.');
}
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function config()
+ public function config(): array
{
return $this->_config;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function configName()
+ public function configName(): string
{
if (empty($this->_config['name'])) {
return '';
@@ -168,7 +182,7 @@ public function configName()
* Sets the driver instance. If a string is passed it will be treated
* as a class name and will be instantiated.
*
- * @param \Cake\Database\Driver|string $driver The driver instance to use.
+ * @param \Cake\Database\DriverInterface|string $driver The driver instance to use.
* @param array $config Config for a new driver.
* @throws \Cake\Database\Exception\MissingDriverException When a driver class is missing.
* @throws \Cake\Database\Exception\MissingExtensionException When a driver's PHP extension is missing.
@@ -177,8 +191,9 @@ public function configName()
public function setDriver($driver, $config = [])
{
if (is_string($driver)) {
+ /** @psalm-var class-string<\Cake\Database\DriverInterface>|null $className */
$className = App::className($driver, 'Database/Driver');
- if (!$className || !class_exists($className)) {
+ if ($className === null) {
throw new MissingDriverException(['driver' => $driver]);
}
$driver = new $className($config);
@@ -198,7 +213,7 @@ public function setDriver($driver, $config = [])
*
* @return \Cake\Core\Retry\CommandRetry The retry wrapper
*/
- public function getDisconnectRetry()
+ public function getDisconnectRetry(): CommandRetry
{
return new CommandRetry(new ReconnectStrategy($this));
}
@@ -206,48 +221,34 @@ public function getDisconnectRetry()
/**
* Gets the driver instance.
*
- * @return \Cake\Database\Driver
+ * @return \Cake\Database\DriverInterface
*/
- public function getDriver()
+ public function getDriver(): DriverInterface
{
return $this->_driver;
}
- /**
- * Sets the driver instance. If a string is passed it will be treated
- * as a class name and will be instantiated.
- *
- * If no params are passed it will return the current driver instance.
- *
- * @deprecated 3.4.0 Use setDriver()/getDriver() instead.
- * @param \Cake\Database\Driver|string|null $driver The driver instance to use.
- * @param array $config Either config for a new driver or null.
- * @throws \Cake\Database\Exception\MissingDriverException When a driver class is missing.
- * @throws \Cake\Database\Exception\MissingExtensionException When a driver's PHP extension is missing.
- * @return \Cake\Database\Driver
- */
- public function driver($driver = null, $config = [])
- {
- deprecationWarning('Connection::driver() is deprecated. Use Connection::setDriver()/getDriver() instead.');
- if ($driver !== null) {
- $this->setDriver($driver, $config);
- }
-
- return $this->getDriver();
- }
-
/**
* Connects to the configured database.
*
- * @throws \Cake\Database\Exception\MissingConnectionException if credentials are invalid.
+ * @throws \Cake\Database\Exception\MissingConnectionException If database connection could not be established.
* @return bool true, if the connection was already established or the attempt was successful.
*/
- public function connect()
+ public function connect(): bool
{
try {
return $this->_driver->connect();
- } catch (Exception $e) {
- throw new MissingConnectionException(['reason' => $e->getMessage()], null, $e);
+ } catch (MissingConnectionException $e) {
+ throw $e;
+ } catch (Throwable $e) {
+ throw new MissingConnectionException(
+ [
+ 'driver' => App::shortName(get_class($this->_driver), 'Database/Driver'),
+ 'reason' => $e->getMessage(),
+ ],
+ null,
+ $e
+ );
}
}
@@ -256,7 +257,7 @@ public function connect()
*
* @return void
*/
- public function disconnect()
+ public function disconnect(): void
{
$this->_driver->disconnect();
}
@@ -266,7 +267,7 @@ public function disconnect()
*
* @return bool
*/
- public function isConnected()
+ public function isConnected(): bool
{
return $this->_driver->isConnected();
}
@@ -277,7 +278,7 @@ public function isConnected()
* @param string|\Cake\Database\Query $sql The SQL to convert into a prepared statement.
* @return \Cake\Database\StatementInterface
*/
- public function prepare($sql)
+ public function prepare($sql): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($sql) {
$statement = $this->_driver->prepare($sql);
@@ -299,7 +300,7 @@ public function prepare($sql)
* @param array $types list or associative array of types to be used for casting values in query
* @return \Cake\Database\StatementInterface executed statement
*/
- public function execute($query, array $params = [], array $types = [])
+ public function execute(string $query, array $params = [], array $types = []): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($query, $params, $types) {
if (!empty($params)) {
@@ -322,7 +323,7 @@ public function execute($query, array $params = [], array $types = [])
* @param \Cake\Database\ValueBinder $generator The placeholder generator to use
* @return string
*/
- public function compileQuery(Query $query, ValueBinder $generator)
+ public function compileQuery(Query $query, ValueBinder $generator): string
{
return $this->getDriver()->compileQuery($query, $generator)[1];
}
@@ -334,7 +335,7 @@ public function compileQuery(Query $query, ValueBinder $generator)
* @param \Cake\Database\Query $query The query to be executed
* @return \Cake\Database\StatementInterface executed statement
*/
- public function run(Query $query)
+ public function run(Query $query): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($query) {
$statement = $this->prepare($query);
@@ -351,7 +352,7 @@ public function run(Query $query)
* @param string $sql The SQL query to execute.
* @return \Cake\Database\StatementInterface
*/
- public function query($sql)
+ public function query(string $sql): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($sql) {
$statement = $this->prepare($sql);
@@ -366,7 +367,7 @@ public function query($sql)
*
* @return \Cake\Database\Query
*/
- public function newQuery()
+ public function newQuery(): Query
{
return new Query($this);
}
@@ -374,10 +375,10 @@ public function newQuery()
/**
* Sets a Schema\Collection object for this connection.
*
- * @param \Cake\Database\Schema\Collection $collection The schema collection object
+ * @param \Cake\Database\Schema\CollectionInterface $collection The schema collection object
* @return $this
*/
- public function setSchemaCollection(SchemaCollection $collection)
+ public function setSchemaCollection(SchemaCollectionInterface $collection)
{
$this->_schemaCollection = $collection;
@@ -387,41 +388,25 @@ public function setSchemaCollection(SchemaCollection $collection)
/**
* Gets a Schema\Collection object for this connection.
*
- * @return \Cake\Database\Schema\Collection
+ * @return \Cake\Database\Schema\CollectionInterface
*/
- public function getSchemaCollection()
+ public function getSchemaCollection(): SchemaCollectionInterface
{
if ($this->_schemaCollection !== null) {
return $this->_schemaCollection;
}
if (!empty($this->_config['cacheMetadata'])) {
- return $this->_schemaCollection = new CachedCollection($this, $this->_config['cacheMetadata']);
+ return $this->_schemaCollection = new CachedCollection(
+ new SchemaCollection($this),
+ empty($this->_config['cacheKeyPrefix']) ? $this->configName() : $this->_config['cacheKeyPrefix'],
+ $this->getCacher()
+ );
}
return $this->_schemaCollection = new SchemaCollection($this);
}
- /**
- * Gets or sets a Schema\Collection object for this connection.
- *
- * @deprecated 3.4.0 Use setSchemaCollection()/getSchemaCollection()
- * @param \Cake\Database\Schema\Collection|null $collection The schema collection object
- * @return \Cake\Database\Schema\Collection
- */
- public function schemaCollection(SchemaCollection $collection = null)
- {
- deprecationWarning(
- 'Connection::schemaCollection() is deprecated. ' .
- 'Use Connection::setSchemaCollection()/getSchemaCollection() instead.'
- );
- if ($collection !== null) {
- $this->setSchemaCollection($collection);
- }
-
- return $this->getSchemaCollection();
- }
-
/**
* Executes an INSERT query on the specified table.
*
@@ -430,7 +415,7 @@ public function schemaCollection(SchemaCollection $collection = null)
* @param array $types list of associative array containing the types to be used for casting
* @return \Cake\Database\StatementInterface
*/
- public function insert($table, array $data, array $types = [])
+ public function insert(string $table, array $data, array $types = []): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($table, $data, $types) {
$columns = array_keys($data);
@@ -451,7 +436,7 @@ public function insert($table, array $data, array $types = [])
* @param array $types list of associative array containing the types to be used for casting
* @return \Cake\Database\StatementInterface
*/
- public function update($table, array $data, array $conditions = [], $types = [])
+ public function update(string $table, array $data, array $conditions = [], array $types = []): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($table, $data, $conditions, $types) {
return $this->newQuery()->update($table)
@@ -469,7 +454,7 @@ public function update($table, array $data, array $conditions = [], $types = [])
* @param array $types list of associative array containing the types to be used for casting
* @return \Cake\Database\StatementInterface
*/
- public function delete($table, $conditions = [], $types = [])
+ public function delete(string $table, array $conditions = [], array $types = []): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($table, $conditions, $types) {
return $this->newQuery()->delete($table)
@@ -483,14 +468,14 @@ public function delete($table, $conditions = [], $types = [])
*
* @return void
*/
- public function begin()
+ public function begin(): void
{
if (!$this->_transactionStarted) {
if ($this->_logQueries) {
$this->log('BEGIN');
}
- $this->getDisconnectRetry()->run(function () {
+ $this->getDisconnectRetry()->run(function (): void {
$this->_driver->beginTransaction();
});
@@ -512,7 +497,7 @@ public function begin()
*
* @return bool true on success, false otherwise
*/
- public function commit()
+ public function commit(): bool
{
if (!$this->_transactionStarted) {
return false;
@@ -520,6 +505,7 @@ public function commit()
if ($this->_transactionLevel === 0) {
if ($this->wasNestedTransactionRolledback()) {
+ /** @var \Cake\Database\Exception\NestedTransactionRollbackException $e */
$e = $this->nestedTransactionRollbackException;
$this->nestedTransactionRollbackException = null;
throw $e;
@@ -549,7 +535,7 @@ public function commit()
* beginning of it. Defaults to false if using savepoints, or true if not.
* @return bool
*/
- public function rollback($toBeginning = null)
+ public function rollback(?bool $toBeginning = null): bool
{
if (!$this->_transactionStarted) {
return false;
@@ -584,13 +570,18 @@ public function rollback($toBeginning = null)
/**
* Enables/disables the usage of savepoints, enables only if driver the allows it.
*
- * If you are trying to enable this feature, make sure you check
- * `isSavePointsEnabled()` to verify that savepoints were enabled successfully.
+ * If you are trying to enable this feature, make sure you check the return value of this
+ * function to verify it was enabled successfully.
+ *
+ * ### Example:
+ *
+ * `$connection->enableSavePoints(true)` Returns true if drivers supports save points, false otherwise
+ * `$connection->enableSavePoints(false)` Disables usage of savepoints and returns false
*
* @param bool $enable Whether or not save points should be used.
* @return $this
*/
- public function enableSavePoints($enable)
+ public function enableSavePoints(bool $enable = true)
{
if ($enable === false) {
$this->_useSavePoints = false;
@@ -618,49 +609,18 @@ public function disableSavePoints()
*
* @return bool true if enabled, false otherwise
*/
- public function isSavePointsEnabled()
+ public function isSavePointsEnabled(): bool
{
return $this->_useSavePoints;
}
- /**
- * Returns whether this connection is using savepoints for nested transactions
- * If a boolean is passed as argument it will enable/disable the usage of savepoints
- * only if driver the allows it.
- *
- * If you are trying to enable this feature, make sure you check the return value of this
- * function to verify it was enabled successfully.
- *
- * ### Example:
- *
- * `$connection->useSavePoints(true)` Returns true if drivers supports save points, false otherwise
- * `$connection->useSavePoints(false)` Disables usage of savepoints and returns false
- * `$connection->useSavePoints()` Returns current status
- *
- * @deprecated 3.4.0 Use enableSavePoints()/isSavePointsEnabled() instead.
- * @param bool|null $enable Whether or not save points should be used.
- * @return bool true if enabled, false otherwise
- */
- public function useSavePoints($enable = null)
- {
- deprecationWarning(
- 'Connection::useSavePoints() is deprecated. ' .
- 'Use Connection::enableSavePoints()/isSavePointsEnabled() instead.'
- );
- if ($enable !== null) {
- $this->enableSavePoints($enable);
- }
-
- return $this->isSavePointsEnabled();
- }
-
/**
* Creates a new save point for nested transactions.
*
* @param string|int $name The save point name.
* @return void
*/
- public function createSavePoint($name)
+ public function createSavePoint($name): void
{
$this->execute($this->_driver->savePointSQL($name))->closeCursor();
}
@@ -671,7 +631,7 @@ public function createSavePoint($name)
* @param string|int $name The save point name.
* @return void
*/
- public function releaseSavePoint($name)
+ public function releaseSavePoint($name): void
{
$this->execute($this->_driver->releaseSavePointSQL($name))->closeCursor();
}
@@ -682,7 +642,7 @@ public function releaseSavePoint($name)
* @param string|int $name The save point name.
* @return void
*/
- public function rollbackSavepoint($name)
+ public function rollbackSavepoint($name): void
{
$this->execute($this->_driver->rollbackSavePointSQL($name))->closeCursor();
}
@@ -692,9 +652,9 @@ public function rollbackSavepoint($name)
*
* @return void
*/
- public function disableForeignKeys()
+ public function disableForeignKeys(): void
{
- $this->getDisconnectRetry()->run(function () {
+ $this->getDisconnectRetry()->run(function (): void {
$this->execute($this->_driver->disableForeignKeySQL())->closeCursor();
});
}
@@ -704,9 +664,9 @@ public function disableForeignKeys()
*
* @return void
*/
- public function enableForeignKeys()
+ public function enableForeignKeys(): void
{
- $this->getDisconnectRetry()->run(function () {
+ $this->getDisconnectRetry()->run(function (): void {
$this->execute($this->_driver->enableForeignKeySQL())->closeCursor();
});
}
@@ -717,21 +677,13 @@ public function enableForeignKeys()
*
* @return bool true if driver supports dynamic constraints
*/
- public function supportsDynamicConstraints()
+ public function supportsDynamicConstraints(): bool
{
return $this->_driver->supportsDynamicConstraints();
}
/**
- * {@inheritDoc}
- *
- * ### Example:
- *
- * ```
- * $connection->transactional(function ($connection) {
- * $connection->newQuery()->delete('users')->execute();
- * });
- * ```
+ * @inheritDoc
*/
public function transactional(callable $transaction)
{
@@ -742,9 +694,6 @@ public function transactional(callable $transaction)
} catch (Throwable $e) {
$this->rollback(false);
throw $e;
- } catch (Exception $e) {
- $this->rollback(false);
- throw $e;
}
if ($result === false) {
@@ -768,21 +717,13 @@ public function transactional(callable $transaction)
*
* @return bool
*/
- protected function wasNestedTransactionRolledback()
+ protected function wasNestedTransactionRolledback(): bool
{
return $this->nestedTransactionRollbackException instanceof NestedTransactionRollbackException;
}
/**
- * {@inheritDoc}
- *
- * ### Example:
- *
- * ```
- * $connection->disableConstraints(function ($connection) {
- * $connection->newQuery()->delete('users')->execute();
- * });
- * ```
+ * @inheritDoc
*/
public function disableConstraints(callable $operation)
{
@@ -791,13 +732,10 @@ public function disableConstraints(callable $operation)
try {
$result = $operation($this);
- } catch (Exception $e) {
+ } finally {
$this->enableForeignKeys();
- throw $e;
}
- $this->enableForeignKeys();
-
return $result;
});
}
@@ -807,7 +745,7 @@ public function disableConstraints(callable $operation)
*
* @return bool True if a transaction is running else false.
*/
- public function inTransaction()
+ public function inTransaction(): bool
{
return $this->_transactionStarted;
}
@@ -816,12 +754,12 @@ public function inTransaction()
* Quotes value to be used safely in database query.
*
* @param mixed $value The value to quote.
- * @param string|null $type Type to be used for determining kind of quoting to perform
+ * @param string|int|\Cake\Database\TypeInterface $type Type to be used for determining kind of quoting to perform
* @return string Quoted value
*/
- public function quote($value, $type = null)
+ public function quote($value, $type = 'string'): string
{
- list($value, $type) = $this->cast($value, $type);
+ [$value, $type] = $this->cast($value, $type);
return $this->_driver->quote($value, $type);
}
@@ -831,7 +769,7 @@ public function quote($value, $type = null)
*
* @return bool
*/
- public function supportsQuoting()
+ public function supportsQuoting(): bool
{
return $this->_driver->supportsQuoting();
}
@@ -843,7 +781,7 @@ public function supportsQuoting()
* @param string $identifier The identifier to quote.
* @return string
*/
- public function quoteIdentifier($identifier)
+ public function quoteIdentifier(string $identifier): string
{
return $this->_driver->quoteIdentifier($identifier);
}
@@ -857,27 +795,47 @@ public function quoteIdentifier($identifier)
* true to use `_cake_model_` or the name of the cache config to use.
* @return void
*/
- public function cacheMetadata($cache)
+ public function cacheMetadata($cache): void
{
$this->_schemaCollection = null;
$this->_config['cacheMetadata'] = $cache;
+ if (is_string($cache)) {
+ $this->cacher = null;
+ }
}
/**
- * {@inheritDoc}
- *
- * @deprecated 3.7.0 Use enableQueryLogging() and isQueryLoggingEnabled() instead.
+ * @inheritDoc
+ */
+ public function setCacher(CacheInterface $cacher)
+ {
+ $this->cacher = $cacher;
+
+ return $this;
+ }
+
+ /**
+ * @inheritDoc
*/
- public function logQueries($enable = null)
+ public function getCacher(): CacheInterface
{
- deprecationWarning(
- 'Connection::logQueries() is deprecated. ' .
- 'Use enableQueryLogging() and isQueryLoggingEnabled() instead.'
- );
- if ($enable === null) {
- return $this->_logQueries;
+ if ($this->cacher !== null) {
+ return $this->cacher;
}
- $this->_logQueries = $enable;
+
+ $configName = $this->_config['cacheMetadata'] ?? '_cake_model_';
+ if (!is_string($configName)) {
+ $configName = '_cake_model_';
+ }
+
+ if (!class_exists(Cache::class)) {
+ throw new RuntimeException(
+ 'To use caching you must either set a cacher using Connection::setCacher()' .
+ ' or require the cakephp/cache package in your composer config.'
+ );
+ }
+
+ return $this->cacher = Cache::pool($configName);
}
/**
@@ -886,9 +844,9 @@ public function logQueries($enable = null)
* @param bool $value Enable/disable query logging
* @return $this
*/
- public function enableQueryLogging($value)
+ public function enableQueryLogging(bool $value = true)
{
- $this->_logQueries = (bool)$value;
+ $this->_logQueries = $value;
return $this;
}
@@ -910,36 +868,19 @@ public function disableQueryLogging()
*
* @return bool
*/
- public function isQueryLoggingEnabled()
+ public function isQueryLoggingEnabled(): bool
{
return $this->_logQueries;
}
- /**
- * {@inheritDoc}
- *
- * @deprecated 3.5.0 Use getLogger() and setLogger() instead.
- */
- public function logger($instance = null)
- {
- deprecationWarning(
- 'Connection::logger() is deprecated. ' .
- 'Use Connection::setLogger()/getLogger() instead.'
- );
- if ($instance === null) {
- return $this->getLogger();
- }
-
- $this->setLogger($instance);
- }
-
/**
* Sets a logger
*
- * @param \Cake\Database\Log\QueryLogger $logger Logger object
+ * @param \Psr\Log\LoggerInterface $logger Logger object
* @return $this
+ * @psalm-suppress ImplementedReturnTypeMismatch
*/
- public function setLogger($logger)
+ public function setLogger(LoggerInterface $logger)
{
$this->_logger = $logger;
@@ -949,15 +890,22 @@ public function setLogger($logger)
/**
* Gets the logger object
*
- * @return \Cake\Database\Log\QueryLogger logger instance
+ * @return \Psr\Log\LoggerInterface logger instance
*/
- public function getLogger()
+ public function getLogger(): LoggerInterface
{
- if ($this->_logger === null) {
- $this->_logger = new QueryLogger();
+ if ($this->_logger !== null) {
+ return $this->_logger;
+ }
+
+ if (!class_exists(QueryLogger::class)) {
+ throw new RuntimeException(
+ 'For logging you must either set a logger using Connection::setLogger()' .
+ ' or require the cakephp/log package in your composer config.'
+ );
}
- return $this->_logger;
+ return $this->_logger = new QueryLogger();
}
/**
@@ -966,11 +914,11 @@ public function getLogger()
* @param string $sql string to be logged
* @return void
*/
- public function log($sql)
+ public function log(string $sql): void
{
$query = new LoggedQuery();
$query->query = $sql;
- $this->getLogger()->log($query);
+ $this->getLogger()->debug((string)$query, ['query' => $query]);
}
/**
@@ -980,7 +928,7 @@ public function log($sql)
* @param \Cake\Database\StatementInterface $statement the instance to be decorated
* @return \Cake\Database\Log\LoggingStatement
*/
- protected function _newLogger(StatementInterface $statement)
+ protected function _newLogger(StatementInterface $statement): LoggingStatement
{
$log = new LoggingStatement($statement, $this->_driver);
$log->setLogger($this->getLogger());
@@ -994,7 +942,7 @@ protected function _newLogger(StatementInterface $statement)
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$secrets = [
'password' => '*****',
diff --git a/app/vendor/cakephp/cakephp/src/Database/ConstraintsInterface.php b/app/vendor/cakephp/cakephp/src/Database/ConstraintsInterface.php
new file mode 100644
index 000000000..dafd045d0
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/ConstraintsInterface.php
@@ -0,0 +1,49 @@
+_schemaDialect) {
+ if ($this->_schemaDialect === null) {
$this->_schemaDialect = new MysqlSchema($this);
}
@@ -66,17 +69,17 @@ public function schemaDialect()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function disableForeignKeySQL()
+ public function disableForeignKeySQL(): string
{
return 'SET foreign_key_checks = 0';
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function enableForeignKeySQL()
+ public function enableForeignKeySQL(): string
{
return 'SET foreign_key_checks = 1';
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Dialect/PostgresDialectTrait.php b/app/vendor/cakephp/cakephp/src/Database/Dialect/PostgresDialectTrait.php
index 89d874fb9..6064e0d44 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Dialect/PostgresDialectTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Dialect/PostgresDialectTrait.php
@@ -1,4 +1,6 @@
clause('epilog')) {
$query->epilog('RETURNING *');
@@ -82,7 +86,7 @@ protected function _insertQueryTranslator($query)
*
* @return array
*/
- protected function _expressionTranslators()
+ protected function _expressionTranslators(): array
{
$namespace = 'Cake\Database\Expression';
@@ -99,7 +103,7 @@ protected function _expressionTranslators()
* to postgres SQL.
* @return void
*/
- protected function _transformFunctionExpression(FunctionExpression $expression)
+ protected function _transformFunctionExpression(FunctionExpression $expression): void
{
switch ($expression->getName()) {
case 'CONCAT':
@@ -162,11 +166,11 @@ protected function _transformFunctionExpression(FunctionExpression $expression)
* Used by Cake\Database\Schema package to reflect schema and
* generate schema.
*
- * @return \Cake\Database\Schema\PostgresSchema
+ * @return \Cake\Database\Schema\BaseSchema
*/
- public function schemaDialect()
+ public function schemaDialect(): BaseSchema
{
- if (!$this->_schemaDialect) {
+ if ($this->_schemaDialect === null) {
$this->_schemaDialect = new PostgresSchema($this);
}
@@ -174,17 +178,17 @@ public function schemaDialect()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function disableForeignKeySQL()
+ public function disableForeignKeySQL(): string
{
return 'SET CONSTRAINTS ALL DEFERRED';
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function enableForeignKeySQL()
+ public function enableForeignKeySQL(): string
{
return 'SET CONSTRAINTS ALL IMMEDIATE';
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Dialect/SqliteDialectTrait.php b/app/vendor/cakephp/cakephp/src/Database/Dialect/SqliteDialectTrait.php
index c129c4893..6d3127642 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Dialect/SqliteDialectTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Dialect/SqliteDialectTrait.php
@@ -1,4 +1,6 @@
getName()) {
case 'CONCAT':
@@ -110,7 +114,7 @@ protected function _transformFunctionExpression(FunctionExpression $expression)
case 'RAND':
$expression
->setName('ABS')
- ->add(["RANDOM() % 1" => 'literal'], [], true);
+ ->add(['RANDOM() % 1' => 'literal'], [], true);
break;
case 'CURRENT_DATE':
$expression->setName('DATE')->add(["'now'" => 'literal']);
@@ -161,11 +165,11 @@ protected function _transformFunctionExpression(FunctionExpression $expression)
* Used by Cake\Database\Schema package to reflect schema and
* generate schema.
*
- * @return \Cake\Database\Schema\SqliteSchema
+ * @return \Cake\Database\Schema\BaseSchema
*/
- public function schemaDialect()
+ public function schemaDialect(): BaseSchema
{
- if (!$this->_schemaDialect) {
+ if ($this->_schemaDialect === null) {
$this->_schemaDialect = new SqliteSchema($this);
}
@@ -173,17 +177,17 @@ public function schemaDialect()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function disableForeignKeySQL()
+ public function disableForeignKeySQL(): string
{
return 'PRAGMA foreign_keys = OFF';
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function enableForeignKeySQL()
+ public function enableForeignKeySQL(): string
{
return 'PRAGMA foreign_keys = ON';
}
@@ -193,7 +197,7 @@ public function enableForeignKeySQL()
*
* @return \Cake\Database\SqliteCompiler
*/
- public function newCompiler()
+ public function newCompiler(): QueryCompiler
{
return new SqliteCompiler();
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Dialect/SqlserverDialectTrait.php b/app/vendor/cakephp/cakephp/src/Database/Dialect/SqlserverDialectTrait.php
index 54300fa39..d125f9d4d 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Dialect/SqlserverDialectTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Dialect/SqlserverDialectTrait.php
@@ -1,4 +1,6 @@
clause('limit');
$offset = $query->clause('offset');
@@ -69,7 +73,7 @@ protected function _selectQueryTranslator($query)
$query->order($query->newExpr()->add('(SELECT NULL)'));
}
- if ($this->_version() < 11 && $offset !== null) {
+ if ($this->version() < 11 && $offset !== null) {
return $this->_pagingSubquery($query, $limit, $offset);
}
@@ -79,10 +83,9 @@ protected function _selectQueryTranslator($query)
/**
* Get the version of SQLserver we are connected to.
*
- * @return int
+ * @return string
*/
- // @codingStandardsIgnoreLine
- public function _version()
+ protected function version(): string
{
$this->connect();
@@ -96,11 +99,11 @@ public function _version()
* be used.
*
* @param \Cake\Database\Query $original The query to wrap in a subquery.
- * @param int $limit The number of rows to fetch.
- * @param int $offset The number of rows to offset.
+ * @param int|null $limit The number of rows to fetch.
+ * @param int|null $offset The number of rows to offset.
* @return \Cake\Database\Query Modified query object.
*/
- protected function _pagingSubquery($original, $limit, $offset)
+ protected function _pagingSubquery(Query $original, ?int $limit, ?int $offset): Query
{
$field = '_cake_paging_._cake_page_rownum_';
@@ -119,10 +122,9 @@ protected function _pagingSubquery($original, $limit, $offset)
isset($select[$orderBy]) &&
$select[$orderBy] instanceof ExpressionInterface
) {
- $order->add(new OrderClauseExpression($select[$orderBy], $direction));
- } else {
- $order->add([$key => $direction]);
+ $key = $select[$orderBy]->sql(new ValueBinder());
}
+ $order->add([$key => $direction]);
// Leave original order clause unchanged.
return $orderBy;
@@ -170,7 +172,7 @@ protected function _pagingSubquery($original, $limit, $offset)
* @param \Cake\Database\Query $original The query to be transformed
* @return \Cake\Database\Query
*/
- protected function _transformDistinct($original)
+ protected function _transformDistinct(Query $original): Query
{
if (!is_array($original->clause('distinct'))) {
return $original;
@@ -222,7 +224,7 @@ protected function _transformDistinct($original)
*
* @return array
*/
- protected function _expressionTranslators()
+ protected function _expressionTranslators(): array
{
$namespace = 'Cake\Database\Expression';
@@ -239,7 +241,7 @@ protected function _expressionTranslators()
* @param \Cake\Database\Expression\FunctionExpression $expression The function expression to convert to TSQL.
* @return void
*/
- protected function _transformFunctionExpression(FunctionExpression $expression)
+ protected function _transformFunctionExpression(FunctionExpression $expression): void
{
switch ($expression->getName()) {
case 'CONCAT':
@@ -247,6 +249,7 @@ protected function _transformFunctionExpression(FunctionExpression $expression)
$expression->setName('')->setConjunction(' +');
break;
case 'DATEDIFF':
+ /** @var bool $hasDay */
$hasDay = false;
$visitor = function ($value) use (&$hasDay) {
if ($value === 'day') {
@@ -326,9 +329,9 @@ protected function _transformFunctionExpression(FunctionExpression $expression)
* Used by Cake\Schema package to reflect schema and
* generate schema.
*
- * @return \Cake\Database\Schema\SqlserverSchema
+ * @return \Cake\Database\Schema\BaseSchema
*/
- public function schemaDialect()
+ public function schemaDialect(): BaseSchema
{
return new SqlserverSchema($this);
}
@@ -336,10 +339,10 @@ public function schemaDialect()
/**
* Returns a SQL snippet for creating a new transaction savepoint
*
- * @param string $name save point name
+ * @param string|int $name save point name
* @return string
*/
- public function savePointSQL($name)
+ public function savePointSQL($name): string
{
return 'SAVE TRANSACTION t' . $name;
}
@@ -347,10 +350,10 @@ public function savePointSQL($name)
/**
* Returns a SQL snippet for releasing a previously created save point
*
- * @param string $name save point name
+ * @param string|int $name save point name
* @return string
*/
- public function releaseSavePointSQL($name)
+ public function releaseSavePointSQL($name): string
{
return 'COMMIT TRANSACTION t' . $name;
}
@@ -358,10 +361,10 @@ public function releaseSavePointSQL($name)
/**
* Returns a SQL snippet for rollbacking a previously created save point
*
- * @param string $name save point name
+ * @param string|int $name save point name
* @return string
*/
- public function rollbackSavePointSQL($name)
+ public function rollbackSavePointSQL($name): string
{
return 'ROLLBACK TRANSACTION t' . $name;
}
@@ -371,23 +374,23 @@ public function rollbackSavePointSQL($name)
*
* @return \Cake\Database\SqlserverCompiler
*/
- public function newCompiler()
+ public function newCompiler(): QueryCompiler
{
return new SqlserverCompiler();
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function disableForeignKeySQL()
+ public function disableForeignKeySQL(): string
{
return 'EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"';
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function enableForeignKeySQL()
+ public function enableForeignKeySQL(): string
{
return 'EXEC sp_MSforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"';
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Dialect/TupleComparisonTranslatorTrait.php b/app/vendor/cakephp/cakephp/src/Database/Dialect/TupleComparisonTranslatorTrait.php
index 39c3013de..728319058 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Dialect/TupleComparisonTranslatorTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Dialect/TupleComparisonTranslatorTrait.php
@@ -1,4 +1,6 @@
getField();
@@ -69,13 +71,6 @@ protected function _transformTupleComparison(TupleComparison $expression, $query
return;
}
- $type = $expression->getType();
- if ($type) {
- $typeMap = array_combine($fields, $type);
- } else {
- $typeMap = [];
- }
-
$surrogate = $query->getConnection()
->newQuery()
->select($true);
@@ -87,12 +82,12 @@ protected function _transformTupleComparison(TupleComparison $expression, $query
$conditions = ['OR' => []];
foreach ($value as $tuple) {
$item = [];
- foreach (array_values($tuple) as $i => $value) {
- $item[] = [$fields[$i] => $value];
+ foreach (array_values($tuple) as $i => $value2) {
+ $item[] = [$fields[$i] => $value2];
}
$conditions['OR'][] = $item;
}
- $surrogate->where($conditions, $typeMap);
+ $surrogate->where($conditions);
$expression->setField($true);
$expression->setValue($surrogate);
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver.php b/app/vendor/cakephp/cakephp/src/Database/Driver.php
index a7c517b06..9ca0cec8c 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver.php
@@ -1,4 +1,6 @@
App::shortName(static::class, 'Database/Driver'),
+ 'reason' => $e->getMessage(),
+ ],
+ null,
+ $e
+ );
+ }
$this->setConnection($connection);
return true;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function connect();
+ abstract public function connect(): bool;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function disconnect()
+ public function disconnect(): void
{
+ /** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$this->_connection = null;
}
- /**
- * Returns correct connection resource or object that is internally used
- * If first argument is passed, it will set internal connection object or
- * result to the value passed.
- *
- * @param mixed $connection The PDO connection instance.
- * @return mixed Connection object used internally.
- * @deprecated 3.6.0 Use getConnection()/setConnection() instead.
- */
- public function connection($connection = null)
- {
- deprecationWarning(
- get_called_class() . '::connection() is deprecated. ' .
- 'Use setConnection()/getConnection() instead.'
- );
- if ($connection !== null) {
- $this->_connection = $connection;
- }
-
- return $this->_connection;
- }
-
/**
* Get the internal PDO connection instance.
*
@@ -139,6 +139,13 @@ public function connection($connection = null)
*/
public function getConnection()
{
+ if ($this->_connection === null) {
+ throw new MissingConnectionException([
+ 'driver' => App::shortName(static::class, 'Database/Driver'),
+ 'reason' => 'Unknown',
+ ]);
+ }
+
return $this->_connection;
}
@@ -147,6 +154,7 @@ public function getConnection()
*
* @param \PDO $connection PDO instance.
* @return $this
+ * @psalm-suppress MoreSpecificImplementedParamType
*/
public function setConnection($connection)
{
@@ -156,26 +164,25 @@ public function setConnection($connection)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function enabled();
+ abstract public function enabled(): bool;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function prepare($query)
+ public function prepare($query): StatementInterface
{
$this->connect();
- $isObject = $query instanceof Query;
- $statement = $this->_connection->prepare($isObject ? $query->sql() : $query);
+ $statement = $this->_connection->prepare($query instanceof Query ? $query->sql() : $query);
return new PDOStatement($statement, $this);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function beginTransaction()
+ public function beginTransaction(): bool
{
$this->connect();
if ($this->_connection->inTransaction()) {
@@ -186,9 +193,9 @@ public function beginTransaction()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function commitTransaction()
+ public function commitTransaction(): bool
{
$this->connect();
if (!$this->_connection->inTransaction()) {
@@ -199,9 +206,9 @@ public function commitTransaction()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function rollbackTransaction()
+ public function rollbackTransaction(): bool
{
$this->connect();
if (!$this->_connection->inTransaction()) {
@@ -212,47 +219,51 @@ public function rollbackTransaction()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function releaseSavePointSQL($name);
+ abstract public function releaseSavePointSQL($name): string;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function savePointSQL($name);
+ abstract public function savePointSQL($name): string;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function rollbackSavePointSQL($name);
+ abstract public function rollbackSavePointSQL($name): string;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function disableForeignKeySQL();
+ abstract public function disableForeignKeySQL(): string;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function enableForeignKeySQL();
+ abstract public function enableForeignKeySQL(): string;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function supportsDynamicConstraints();
+ abstract public function supportsDynamicConstraints(): bool;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function supportsSavePoints()
+ public function supportsSavePoints(): bool
{
return true;
}
/**
* {@inheritDoc}
+ *
+ * @param mixed $value The value to quote.
+ * @param int $type Type to be used for determining kind of quoting to perform.
+ * @return string
*/
- public function quote($value, $type)
+ public function quote($value, $type = PDO::PARAM_STR): string
{
$this->connect();
@@ -264,7 +275,7 @@ public function quote($value, $type)
*
* @return bool
*/
- public function supportsQuoting()
+ public function supportsQuoting(): bool
{
$this->connect();
@@ -272,24 +283,24 @@ public function supportsQuoting()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function queryTranslator($type);
+ abstract public function queryTranslator(string $type): Closure;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function schemaDialect();
+ abstract public function schemaDialect(): BaseSchema;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- abstract public function quoteIdentifier($identifier);
+ abstract public function quoteIdentifier(string $identifier): string;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function schemaValue($value)
+ public function schemaValue($value): string
{
if ($value === null) {
return 'NULL';
@@ -303,10 +314,18 @@ public function schemaValue($value)
if (is_float($value)) {
return str_replace(',', '.', (string)$value);
}
+ /** @psalm-suppress InvalidArgument */
if (
- (is_int($value) || $value === '0') || (
- is_numeric($value) && strpos($value, ',') === false &&
- $value[0] !== '0' && strpos($value, 'e') === false)
+ (
+ is_int($value) ||
+ $value === '0'
+ ) ||
+ (
+ is_numeric($value) &&
+ strpos($value, ',') === false &&
+ substr($value, 0, 1) !== '0' &&
+ strpos($value, 'e') === false
+ )
) {
return (string)$value;
}
@@ -315,17 +334,17 @@ public function schemaValue($value)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function schema()
+ public function schema(): string
{
return $this->_config['schema'];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function lastInsertId($table = null, $column = null)
+ public function lastInsertId(?string $table = null, ?string $column = null)
{
$this->connect();
@@ -337,37 +356,35 @@ public function lastInsertId($table = null, $column = null)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function isConnected()
+ public function isConnected(): bool
{
if ($this->_connection === null) {
$connected = false;
} else {
try {
- $connected = $this->_connection->query('SELECT 1');
+ $connected = (bool)$this->_connection->query('SELECT 1');
} catch (PDOException $e) {
$connected = false;
}
}
- return (bool)$connected;
+ return $connected;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function enableAutoQuoting($enable = true)
+ public function enableAutoQuoting(bool $enable = true)
{
- $this->_autoQuoting = (bool)$enable;
+ $this->_autoQuoting = $enable;
return $this;
}
/**
- * Disable auto quoting of identifiers in queries.
- *
- * @return $this
+ * @inheritDoc
*/
public function disableAutoQuoting()
{
@@ -377,41 +394,17 @@ public function disableAutoQuoting()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function isAutoQuotingEnabled()
+ public function isAutoQuotingEnabled(): bool
{
return $this->_autoQuoting;
}
/**
- * Returns whether or not this driver should automatically quote identifiers
- * in queries
- *
- * If called with a boolean argument, it will toggle the auto quoting setting
- * to the passed value
- *
- * @deprecated 3.4.0 use enableAutoQuoting()/isAutoQuotingEnabled() instead.
- * @param bool|null $enable Whether to enable auto quoting
- * @return bool
- */
- public function autoQuoting($enable = null)
- {
- deprecationWarning(
- 'Driver::autoQuoting() is deprecated. ' .
- 'Use Driver::enableAutoQuoting()/isAutoQuotingEnabled() instead.'
- );
- if ($enable !== null) {
- $this->enableAutoQuoting($enable);
- }
-
- return $this->isAutoQuotingEnabled();
- }
-
- /**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function compileQuery(Query $query, ValueBinder $generator)
+ public function compileQuery(Query $query, ValueBinder $generator): array
{
$processor = $this->newCompiler();
$translator = $this->queryTranslator($query->type());
@@ -421,35 +414,44 @@ public function compileQuery(Query $query, ValueBinder $generator)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function newCompiler()
+ public function newCompiler(): QueryCompiler
{
return new QueryCompiler();
}
/**
- * Constructs new TableSchema.
- *
- * @param string $table The table name.
- * @param array $columns The list of columns for the schema.
- * @return \Cake\Database\Schema\TableSchemaInterface
+ * @inheritDoc
*/
- public function newTableSchema($table, array $columns = [])
+ public function newTableSchema(string $table, array $columns = []): TableSchema
{
$className = TableSchema::class;
if (isset($this->_config['tableSchema'])) {
+ /** @var class-string<\Cake\Database\Schema\TableSchema> $className */
$className = $this->_config['tableSchema'];
}
return new $className($table, $columns);
}
+ /**
+ * Returns the maximum alias length allowed.
+ * This can be different than the maximum identifier length for columns.
+ *
+ * @return int|null Maximum alias length or null if no limit
+ */
+ public function getMaxAliasLength(): ?int
+ {
+ return static::MAX_ALIAS_LENGTH;
+ }
+
/**
* Destructor
*/
public function __destruct()
{
+ /** @psalm-suppress PossiblyNullPropertyAssignmentValue */
$this->_connection = null;
}
@@ -459,7 +461,7 @@ public function __destruct()
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
return [
'connected' => $this->_connection !== null,
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php b/app/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php
index 154079b4d..c7dcacde6 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php
@@ -1,4 +1,6 @@
_connection) {
return true;
@@ -78,9 +86,6 @@ public function connect()
if (!empty($config['timezone'])) {
$config['init'][] = sprintf("SET time_zone = '%s'", $config['timezone']);
}
- if (!empty($config['encoding'])) {
- $config['init'][] = sprintf('SET NAMES %s', $config['encoding']);
- }
$config['flags'] += [
PDO::ATTR_PERSISTENT => $config['persistent'],
@@ -97,11 +102,15 @@ public function connect()
}
if (empty($config['unix_socket'])) {
- $dsn = "mysql:host={$config['host']};port={$config['port']};dbname={$config['database']};charset={$config['encoding']}";
+ $dsn = "mysql:host={$config['host']};port={$config['port']};dbname={$config['database']}";
} else {
$dsn = "mysql:unix_socket={$config['unix_socket']};dbname={$config['database']}";
}
+ if (!empty($config['encoding'])) {
+ $dsn .= ";charset={$config['encoding']}";
+ }
+
$this->_connect($dsn, $config);
if (!empty($config['init'])) {
@@ -119,7 +128,7 @@ public function connect()
*
* @return bool true if it is valid to use this driver
*/
- public function enabled()
+ public function enabled(): bool
{
return in_array('mysql', PDO::getAvailableDrivers(), true);
}
@@ -130,12 +139,17 @@ public function enabled()
* @param string|\Cake\Database\Query $query The query to prepare.
* @return \Cake\Database\StatementInterface
*/
- public function prepare($query)
+ public function prepare($query): StatementInterface
{
$this->connect();
$isObject = $query instanceof Query;
+ /**
+ * @psalm-suppress PossiblyInvalidMethodCall
+ * @psalm-suppress PossiblyInvalidArgument
+ */
$statement = $this->_connection->prepare($isObject ? $query->sql() : $query);
$result = new MysqlStatement($statement, $this);
+ /** @psalm-suppress PossiblyInvalidMethodCall */
if ($isObject && $query->isBufferedResultsEnabled() === false) {
$result->bufferResults(false);
}
@@ -144,17 +158,17 @@ public function prepare($query)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function schema()
+ public function schema(): string
{
return $this->_config['database'];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function supportsDynamicConstraints()
+ public function supportsDynamicConstraints(): bool
{
return true;
}
@@ -164,14 +178,14 @@ public function supportsDynamicConstraints()
*
* @return bool
*/
- public function supportsNativeJson()
+ public function supportsNativeJson(): bool
{
if ($this->_supportsNativeJson !== null) {
return $this->_supportsNativeJson;
}
if ($this->_version === null) {
- $this->_version = $this->_connection->getAttribute(PDO::ATTR_SERVER_VERSION);
+ $this->_version = (string)$this->_connection->getAttribute(PDO::ATTR_SERVER_VERSION);
}
return $this->_supportsNativeJson = version_compare($this->_version, '5.7.0', '>=');
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/PDODriverTrait.php b/app/vendor/cakephp/cakephp/src/Database/Driver/PDODriverTrait.php
deleted file mode 100644
index 033dd71cb..000000000
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/PDODriverTrait.php
+++ /dev/null
@@ -1,202 +0,0 @@
-connection($connection);
-
- return true;
- }
-
- /**
- * Returns correct connection resource or object that is internally used
- * If first argument is passed, it will set internal connection object or
- * result to the value passed
- *
- * @param \PDO|null $connection The PDO connection instance.
- * @return \PDO connection object used internally
- */
- public function connection($connection = null)
- {
- if ($connection !== null) {
- $this->_connection = $connection;
- }
-
- return $this->_connection;
- }
-
- /**
- * Disconnects from database server
- *
- * @return void
- */
- public function disconnect()
- {
- $this->_connection = null;
- }
-
- /**
- * Checks whether or not the driver is connected.
- *
- * @return bool
- */
- public function isConnected()
- {
- if ($this->_connection === null) {
- $connected = false;
- } else {
- try {
- $connected = $this->_connection->query('SELECT 1');
- } catch (PDOException $e) {
- $connected = false;
- }
- }
-
- return (bool)$connected;
- }
-
- /**
- * Prepares a sql statement to be executed
- *
- * @param string|\Cake\Database\Query $query The query to turn into a prepared statement.
- * @return \Cake\Database\StatementInterface
- */
- public function prepare($query)
- {
- $this->connect();
- $isObject = $query instanceof Query;
- $statement = $this->_connection->prepare($isObject ? $query->sql() : $query);
-
- return new PDOStatement($statement, $this);
- }
-
- /**
- * Starts a transaction
- *
- * @return bool true on success, false otherwise
- */
- public function beginTransaction()
- {
- $this->connect();
- if ($this->_connection->inTransaction()) {
- return true;
- }
-
- return $this->_connection->beginTransaction();
- }
-
- /**
- * Commits a transaction
- *
- * @return bool true on success, false otherwise
- */
- public function commitTransaction()
- {
- $this->connect();
- if (!$this->_connection->inTransaction()) {
- return false;
- }
-
- return $this->_connection->commit();
- }
-
- /**
- * Rollback a transaction
- *
- * @return bool true on success, false otherwise
- */
- public function rollbackTransaction()
- {
- $this->connect();
- if (!$this->_connection->inTransaction()) {
- return false;
- }
-
- return $this->_connection->rollBack();
- }
-
- /**
- * Returns a value in a safe representation to be used in a query string
- *
- * @param mixed $value The value to quote.
- * @param string $type Type to be used for determining kind of quoting to perform
- * @return string
- */
- public function quote($value, $type)
- {
- $this->connect();
-
- return $this->_connection->quote($value, $type);
- }
-
- /**
- * Returns last id generated for a table or sequence in database
- *
- * @param string|null $table table name or sequence to get last insert value from
- * @param string|null $column the name of the column representing the primary key
- * @return string|int
- */
- public function lastInsertId($table = null, $column = null)
- {
- $this->connect();
-
- return $this->_connection->lastInsertId($table);
- }
-
- /**
- * Checks if the driver supports quoting, as PDO_ODBC does not support it.
- *
- * @return bool
- */
- public function supportsQuoting()
- {
- $this->connect();
-
- return $this->_connection->getAttribute(PDO::ATTR_DRIVER_NAME) !== 'odbc';
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/Postgres.php b/app/vendor/cakephp/cakephp/src/Database/Driver/Postgres.php
index 52786bbdd..abbdd65d8 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/Postgres.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver/Postgres.php
@@ -1,4 +1,6 @@
_connection) {
return true;
@@ -92,7 +101,7 @@ public function connect()
*
* @return bool true if it is valid to use this driver
*/
- public function enabled()
+ public function enabled(): bool
{
return in_array('pgsql', PDO::getAvailableDrivers(), true);
}
@@ -103,7 +112,7 @@ public function enabled()
* @param string $encoding The encoding to use.
* @return void
*/
- public function setEncoding($encoding)
+ public function setEncoding(string $encoding): void
{
$this->connect();
$this->_connection->exec('SET NAMES ' . $this->_connection->quote($encoding));
@@ -116,17 +125,27 @@ public function setEncoding($encoding)
* @param string $schema The schema names to set `search_path` to.
* @return void
*/
- public function setSchema($schema)
+ public function setSchema(string $schema): void
{
$this->connect();
$this->_connection->exec('SET search_path TO ' . $this->_connection->quote($schema));
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function supportsDynamicConstraints()
+ public function supportsDynamicConstraints(): bool
{
return true;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return \Cake\Database\PostgresCompiler
+ */
+ public function newCompiler(): QueryCompiler
+ {
+ return new PostgresCompiler();
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlite.php b/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlite.php
index 48367ba4a..385b4e4bf 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlite.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlite.php
@@ -1,4 +1,6 @@
_connection) {
return true;
@@ -62,16 +66,22 @@ public function connect()
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
];
+ if (!is_string($config['database']) || !strlen($config['database'])) {
+ $name = $config['name'] ?? 'unknown';
+ throw new InvalidArgumentException(
+ "The `database` key for the `{$name}` SQLite connection needs to be a non-empty string."
+ );
+ }
$databaseExists = file_exists($config['database']);
$dsn = "sqlite:{$config['database']}";
$this->_connect($dsn, $config);
- if (!$databaseExists && $config['database'] != ':memory:') {
- //@codingStandardsIgnoreStart
+ if (!$databaseExists && $config['database'] !== ':memory:') {
+ // phpcs:disable
@chmod($config['database'], $config['mask']);
- //@codingStandardsIgnoreEnd
+ // phpcs:enable
}
if (!empty($config['init'])) {
@@ -88,7 +98,7 @@ public function connect()
*
* @return bool true if it is valid to use this driver
*/
- public function enabled()
+ public function enabled(): bool
{
return in_array('sqlite', PDO::getAvailableDrivers(), true);
}
@@ -99,12 +109,17 @@ public function enabled()
* @param string|\Cake\Database\Query $query The query to prepare.
* @return \Cake\Database\StatementInterface
*/
- public function prepare($query)
+ public function prepare($query): StatementInterface
{
$this->connect();
$isObject = $query instanceof Query;
+ /**
+ * @psalm-suppress PossiblyInvalidMethodCall
+ * @psalm-suppress PossiblyInvalidArgument
+ */
$statement = $this->_connection->prepare($isObject ? $query->sql() : $query);
$result = new SqliteStatement(new PDOStatement($statement, $this), $this);
+ /** @psalm-suppress PossiblyInvalidMethodCall */
if ($isObject && $query->isBufferedResultsEnabled() === false) {
$result->bufferResults(false);
}
@@ -113,9 +128,9 @@ public function prepare($query)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function supportsDynamicConstraints()
+ public function supportsDynamicConstraints(): bool
{
return false;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlserver.php b/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlserver.php
index f9f40d65d..76adab63c 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlserver.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlserver.php
@@ -1,4 +1,6 @@
_connection) {
return true;
@@ -70,18 +79,23 @@ public function connect()
$config = $this->_config;
if (isset($config['persistent']) && $config['persistent']) {
- throw new \InvalidArgumentException('Config setting "persistent" cannot be set to true, as the Sqlserver PDO driver does not support PDO::ATTR_PERSISTENT');
+ throw new InvalidArgumentException(
+ 'Config setting "persistent" cannot be set to true, '
+ . 'as the Sqlserver PDO driver does not support PDO::ATTR_PERSISTENT'
+ );
}
$config['flags'] += [
+ PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
];
if (!empty($config['encoding'])) {
+ /** @psalm-suppress UndefinedConstant */
$config['flags'][PDO::SQLSRV_ATTR_ENCODING] = $config['encoding'];
}
$port = '';
- if (strlen($config['port'])) {
+ if ($config['port']) {
$port = ',' . $config['port'];
}
@@ -128,7 +142,7 @@ public function connect()
*
* @return bool true if it is valid to use this driver
*/
- public function enabled()
+ public function enabled(): bool
{
return in_array('sqlsrv', PDO::getAvailableDrivers(), true);
}
@@ -139,23 +153,28 @@ public function enabled()
* @param string|\Cake\Database\Query $query The query to prepare.
* @return \Cake\Database\StatementInterface
*/
- public function prepare($query)
+ public function prepare($query): StatementInterface
{
$this->connect();
$options = [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL];
$isObject = $query instanceof Query;
+ /** @psalm-suppress PossiblyInvalidMethodCall */
if ($isObject && $query->isBufferedResultsEnabled() === false) {
$options = [];
}
+ /**
+ * @psalm-suppress PossiblyInvalidMethodCall
+ * @psalm-suppress PossiblyInvalidArgument
+ */
$statement = $this->_connection->prepare($isObject ? $query->sql() : $query, $options);
return new SqlserverStatement($statement, $this);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function supportsDynamicConstraints()
+ public function supportsDynamicConstraints(): bool
{
return true;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/DriverInterface.php b/app/vendor/cakephp/cakephp/src/Database/DriverInterface.php
index 476a0593a..e04b043f0 100644
--- a/app/vendor/cakephp/cakephp/src/Database/DriverInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/DriverInterface.php
@@ -1,4 +1,6 @@
$this->_from,
'to' => $this->_to,
];
+ /** @var string|\Cake\Database\ExpressionInterface $field */
$field = $this->_field;
if ($field instanceof ExpressionInterface) {
$field = $field->sql($generator);
@@ -98,15 +102,17 @@ public function sql(ValueBinder $generator)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
foreach ([$this->_field, $this->_from, $this->_to] as $part) {
if ($part instanceof ExpressionInterface) {
$visitor($part);
}
}
+
+ return $this;
}
/**
@@ -117,7 +123,7 @@ public function traverse(callable $visitor)
* @param string $type The type of $value
* @return string generated placeholder
*/
- protected function _bindValue($value, $generator, $type)
+ protected function _bindValue($value, $generator, $type): string
{
$placeholder = $generator->placeholder('c');
$generator->bind($placeholder, $value, $type);
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/CaseExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/CaseExpression.php
index 8e36d2b6f..90a5f1218 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/CaseExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/CaseExpression.php
@@ -1,4 +1,6 @@
count($conditions)) {
end($values);
$key = key($values);
- $this->elseValue($values[$key], isset($types[$key]) ? $types[$key] : null);
+ $this->elseValue($values[$key], $types[$key] ?? null);
}
}
@@ -76,7 +80,8 @@ public function __construct($conditions = [], $values = [], $types = [])
* Conditions must be a one dimensional array or a QueryExpression.
* The trueValues must be a similar structure, but may contain a string value.
*
- * @param array|\Cake\Database\ExpressionInterface $conditions Must be a ExpressionInterface instance, or an array of ExpressionInterface instances.
+ * @param array|\Cake\Database\ExpressionInterface $conditions Must be a ExpressionInterface instance,
+ * or an array of ExpressionInterface instances.
* @param array|\Cake\Database\ExpressionInterface $values associative array of values of each condition
* @param array $types associative array of types to be associated with the values
* @return $this
@@ -102,12 +107,12 @@ public function add($conditions = [], $values = [], $types = [])
* Iterates over the passed in conditions and ensures that there is a matching true value for each.
* If no matching true value, then it is defaulted to '1'.
*
- * @param array|\Cake\Database\ExpressionInterface $conditions Must be a ExpressionInterface instance, or an array of ExpressionInterface instances.
- * @param array|\Cake\Database\ExpressionInterface $values associative array of values of each condition
+ * @param array $conditions Array of ExpressionInterface instances.
+ * @param array $values associative array of values of each condition
* @param array $types associative array of types to be associated with the values
* @return void
*/
- protected function _addExpressions($conditions, $values, $types)
+ protected function _addExpressions(array $conditions, array $values, array $types): void
{
$rawValues = array_values($values);
$keyValues = array_keys($values);
@@ -124,7 +129,7 @@ protected function _addExpressions($conditions, $values, $types)
}
$this->_conditions[] = $c;
- $value = isset($rawValues[$k]) ? $rawValues[$k] : 1;
+ $value = $rawValues[$k] ?? 1;
if ($value === 'literal') {
$value = $keyValues[$k];
@@ -138,7 +143,7 @@ protected function _addExpressions($conditions, $values, $types)
continue;
}
- $type = isset($types[$k]) ? $types[$k] : null;
+ $type = $types[$k] ?? null;
if ($type !== null && !$value instanceof ExpressionInterface) {
$value = $this->_castToExpression($value, $type);
@@ -160,7 +165,7 @@ protected function _addExpressions($conditions, $values, $types)
* @param string|null $type Type of value
* @return void
*/
- public function elseValue($value = null, $type = null)
+ public function elseValue($value = null, ?string $type = null): void
{
if (is_array($value)) {
end($value);
@@ -185,7 +190,7 @@ public function elseValue($value = null, $type = null)
* @param \Cake\Database\ValueBinder $generator Sql generator
* @return string
*/
- protected function _compile($part, ValueBinder $generator)
+ protected function _compile($part, ValueBinder $generator): string
{
if ($part instanceof ExpressionInterface) {
$part = $part->sql($generator);
@@ -204,7 +209,7 @@ protected function _compile($part, ValueBinder $generator)
* @param \Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
- public function sql(ValueBinder $generator)
+ public function sql(ValueBinder $generator): string
{
$parts = [];
$parts[] = 'CASE';
@@ -222,9 +227,9 @@ public function sql(ValueBinder $generator)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
foreach (['_conditions', '_values'] as $part) {
foreach ($this->{$part} as $c) {
@@ -238,5 +243,7 @@ public function traverse(callable $visitor)
$visitor($this->_elseValue);
$this->_elseValue->traverse($visitor);
}
+
+ return $this;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/Comparison.php b/app/vendor/cakephp/cakephp/src/Database/Expression/Comparison.php
index de0ad76c3..544805e87 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/Comparison.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/Comparison.php
@@ -1,4 +1,6 @@
_type = $type;
- }
-
+ $this->_type = $type;
$this->setField($field);
$this->setValue($value);
$this->_operator = $operator;
@@ -90,17 +90,13 @@ public function __construct($field, $value, $type, $operator)
* @param mixed $value The value to compare
* @return void
*/
- public function setValue($value)
+ public function setValue($value): void
{
- $hasType = isset($this->_type) && is_string($this->_type);
- $isMultiple = $hasType && strpos($this->_type, '[]') !== false;
-
- if ($hasType) {
- $value = $this->_castToExpression($value, $this->_type);
- }
+ $value = $this->_castToExpression($value, $this->_type);
+ $isMultiple = $this->_type && strpos($this->_type, '[]') !== false;
if ($isMultiple) {
- list($value, $this->_valueExpressions) = $this->_collectExpressions($value);
+ [$value, $this->_valueExpressions] = $this->_collectExpressions($value);
}
$this->_isMultiple = $isMultiple;
@@ -123,7 +119,7 @@ public function getValue()
* @param string $operator The operator to be used for the comparison.
* @return void
*/
- public function setOperator($operator)
+ public function setOperator(string $operator): void
{
$this->_operator = $operator;
}
@@ -133,7 +129,7 @@ public function setOperator($operator)
*
* @return string
*/
- public function getOperator()
+ public function getOperator(): string
{
return $this->_operator;
}
@@ -144,8 +140,9 @@ public function getOperator()
* @param \Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
- public function sql(ValueBinder $generator)
+ public function sql(ValueBinder $generator): string
{
+ /** @var string|\Cake\Database\ExpressionInterface $field */
$field = $this->_field;
if ($field instanceof ExpressionInterface) {
@@ -156,16 +153,16 @@ public function sql(ValueBinder $generator)
$template = '%s %s (%s)';
$value = $this->_value->sql($generator);
} else {
- list($template, $value) = $this->_stringExpression($generator);
+ [$template, $value] = $this->_stringExpression($generator);
}
return sprintf($template, $field, $this->_operator, $value);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
if ($this->_field instanceof ExpressionInterface) {
$visitor($this->_field);
@@ -181,6 +178,8 @@ public function traverse(callable $visitor)
$visitor($v);
$v->traverse($visitor);
}
+
+ return $this;
}
/**
@@ -206,7 +205,7 @@ public function __clone()
* @param \Cake\Database\ValueBinder $generator The value binder to use.
* @return array First position containing the template and the second a placeholder
*/
- protected function _stringExpression($generator)
+ protected function _stringExpression(ValueBinder $generator): array
{
$template = '%s ';
@@ -216,13 +215,17 @@ protected function _stringExpression($generator)
if ($this->_isMultiple) {
$template .= '%s (%s)';
- $type = str_replace('[]', '', $this->_type);
+ $type = $this->_type;
+ if ($type !== null) {
+ $type = str_replace('[]', '', $type);
+ }
$value = $this->_flattenValue($this->_value, $generator, $type);
// To avoid SQL errors when comparing a field to a list of empty values,
// better just throw an exception here
if ($value === '') {
$field = $this->_field instanceof ExpressionInterface ? $this->_field->sql($generator) : $this->_field;
+ /** @psalm-suppress PossiblyInvalidCast */
throw new DatabaseException(
"Impossible to generate condition with empty list of values for field ($field)"
);
@@ -240,10 +243,10 @@ protected function _stringExpression($generator)
*
* @param mixed $value The value to bind
* @param \Cake\Database\ValueBinder $generator The value binder to use
- * @param string $type The type of $value
+ * @param string|null $type The type of $value
* @return string generated placeholder
*/
- protected function _bindValue($value, $generator, $type)
+ protected function _bindValue($value, ValueBinder $generator, ?string $type = null): string
{
$placeholder = $generator->placeholder('c');
$generator->bind($placeholder, $value, $type);
@@ -255,17 +258,19 @@ protected function _bindValue($value, $generator, $type)
* Converts a traversable value into a set of placeholders generated by
* $generator and separated by `,`
*
- * @param array|\Traversable $value the value to flatten
+ * @param iterable $value the value to flatten
* @param \Cake\Database\ValueBinder $generator The value binder to use
- * @param string|array|null $type the type to cast values to
+ * @param string|null $type the type to cast values to
* @return string
*/
- protected function _flattenValue($value, $generator, $type = 'string')
+ protected function _flattenValue(iterable $value, ValueBinder $generator, ?string $type = null): string
{
$parts = [];
- foreach ($this->_valueExpressions as $k => $v) {
- $parts[$k] = $v->sql($generator);
- unset($value[$k]);
+ if (is_array($value)) {
+ foreach ($this->_valueExpressions as $k => $v) {
+ $parts[$k] = $v->sql($generator);
+ unset($value[$k]);
+ }
}
if (!empty($value)) {
@@ -280,10 +285,10 @@ protected function _flattenValue($value, $generator, $type = 'string')
* and all ExpressionInterface objects that could be found in the second
* position.
*
- * @param array|\Traversable $values The rows to insert
+ * @param iterable|\Cake\Database\ExpressionInterface $values The rows to insert
* @return array
*/
- protected function _collectExpressions($values)
+ protected function _collectExpressions($values): array
{
if ($values instanceof ExpressionInterface) {
return [$values, []];
@@ -293,6 +298,7 @@ protected function _collectExpressions($values)
$isArray = is_array($values);
if ($isArray) {
+ /** @var array $result */
$result = $values;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/FieldInterface.php b/app/vendor/cakephp/cakephp/src/Database/Expression/FieldInterface.php
index 35b2a588a..24b7204f1 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/FieldInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/FieldInterface.php
@@ -1,4 +1,6 @@
_field = $field;
}
@@ -40,7 +42,7 @@ public function setField($field)
/**
* Returns the field name
*
- * @return string|\Cake\Database\ExpressionInterface
+ * @return string|array|\Cake\Database\ExpressionInterface
*/
public function getField()
{
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/FunctionExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/FunctionExpression.php
index 7cbe43954..81ab886bb 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/FunctionExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/FunctionExpression.php
@@ -1,4 +1,6 @@
_name = $name;
$this->_returnType = $returnType;
@@ -77,7 +79,7 @@ public function __construct($name, $params = [], $types = [], $returnType = 'str
* @param string $name The name of the function
* @return $this
*/
- public function setName($name)
+ public function setName(string $name)
{
$this->_name = $name;
@@ -89,32 +91,11 @@ public function setName($name)
*
* @return string
*/
- public function getName()
+ public function getName(): string
{
return $this->_name;
}
- /**
- * Sets the name of the SQL function to be invoke in this expression,
- * if no value is passed it will return current name
- *
- * @deprecated 3.4.0 Use setName()/getName() instead.
- * @param string|null $name The name of the function
- * @return string|$this
- */
- public function name($name = null)
- {
- deprecationWarning(
- 'FunctionExpression::name() is deprecated. ' .
- 'Use FunctionExpression::setName()/getName() instead.'
- );
- if ($name !== null) {
- return $this->setName($name);
- }
-
- return $this->getName();
- }
-
/**
* Adds one or more arguments for the function call.
*
@@ -125,8 +106,9 @@ public function name($name = null)
* @param bool $prepend Whether to prepend or append to the list of arguments
* @see \Cake\Database\Expression\FunctionExpression::__construct() for more details.
* @return $this
+ * @psalm-suppress MoreSpecificImplementedParamType
*/
- public function add($params, $types = [], $prepend = false)
+ public function add($params, array $types = [], bool $prepend = false)
{
$put = $prepend ? 'array_unshift' : 'array_push';
$typeMap = $this->getTypeMap()->setTypes($types);
@@ -167,7 +149,7 @@ public function add($params, $types = [], $prepend = false)
* @param \Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
- public function sql(ValueBinder $generator)
+ public function sql(ValueBinder $generator): string
{
$parts = [];
foreach ($this->_conditions as $condition) {
@@ -195,7 +177,7 @@ public function sql(ValueBinder $generator)
*
* @return int
*/
- public function count()
+ public function count(): int
{
return 1 + count($this->_conditions);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/IdentifierExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/IdentifierExpression.php
index 52fde3349..9b97879ca 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/IdentifierExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/IdentifierExpression.php
@@ -1,4 +1,6 @@
_identifier = $identifier;
}
@@ -50,7 +53,7 @@ public function __construct($identifier)
* @param string $identifier The identifier
* @return void
*/
- public function setIdentifier($identifier)
+ public function setIdentifier(string $identifier): void
{
$this->_identifier = $identifier;
}
@@ -60,7 +63,7 @@ public function setIdentifier($identifier)
*
* @return string
*/
- public function getIdentifier()
+ public function getIdentifier(): string
{
return $this->_identifier;
}
@@ -71,7 +74,7 @@ public function getIdentifier()
* @param \Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
- public function sql(ValueBinder $generator)
+ public function sql(ValueBinder $generator): string
{
return $this->_identifier;
}
@@ -79,7 +82,8 @@ public function sql(ValueBinder $generator)
/**
* @inheritDoc
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
+ return $this;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/OrderByExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/OrderByExpression.php
index 98f16a76e..2aaa6a10f 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/OrderByExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/OrderByExpression.php
@@ -1,4 +1,6 @@
_conditions as $k => $direction) {
@@ -63,16 +66,22 @@ public function sql(ValueBinder $generator)
* @param array $types list of types associated on fields referenced in $conditions
* @return void
*/
- protected function _addConditions(array $orders, array $types)
+ protected function _addConditions(array $orders, array $types): void
{
foreach ($orders as $key => $val) {
- if (is_string($key) && is_string($val) && !in_array(strtoupper($val), ['ASC', 'DESC'], true)) {
- deprecationWarning(
- 'Passing extra sort expressions by associative array is deprecated. ' .
+ if (
+ is_string($key) &&
+ is_string($val) &&
+ !in_array(strtoupper($val), ['ASC', 'DESC'], true)
+ ) {
+ throw new RuntimeException(
+ 'Passing extra expressions by associative array is not ' .
+ 'allowed to avoid potential SQL injection. ' .
'Use QueryExpression or numeric array instead.'
);
}
}
+
$this->_conditions = array_merge($this->_conditions, $orders);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/OrderClauseExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/OrderClauseExpression.php
index 8fc1c2c5b..5a6aec266 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/OrderClauseExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/OrderClauseExpression.php
@@ -1,4 +1,6 @@
_field;
- if ($field instanceof Query) {
- $field = sprintf('(%s)', $field->sql($generator));
- } elseif ($field instanceof ExpressionInterface) {
+ if ($field instanceof ExpressionInterface) {
$field = $field->sql($generator);
}
@@ -60,14 +61,16 @@ public function sql(ValueBinder $generator)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
if ($this->_field instanceof ExpressionInterface) {
$visitor($this->_field);
$this->_field->traverse($visitor);
}
+
+ return $this;
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/QueryExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/QueryExpression.php
index 4ea417799..0bf3d08ef 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/QueryExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/QueryExpression.php
@@ -1,4 +1,6 @@
_conjunction = strtoupper($conjunction);
@@ -91,51 +91,11 @@ public function setConjunction($conjunction)
*
* @return string
*/
- public function getConjunction()
+ public function getConjunction(): string
{
return $this->_conjunction;
}
- /**
- * Changes the conjunction for the conditions at this level of the expression tree.
- * If called with no arguments it will return the currently configured value.
- *
- * @deprecated 3.4.0 Use setConjunction()/getConjunction() instead.
- * @param string|null $conjunction value to be used for joining conditions. If null it
- * will not set any value, but return the currently stored one
- * @return string|$this
- */
- public function tieWith($conjunction = null)
- {
- deprecationWarning(
- 'QueryExpression::tieWith() is deprecated. ' .
- 'Use QueryExpression::setConjunction()/getConjunction() instead.'
- );
- if ($conjunction !== null) {
- return $this->setConjunction($conjunction);
- }
-
- return $this->getConjunction();
- }
-
- /**
- * Backwards compatible wrapper for tieWith()
- *
- * @param string|null $conjunction value to be used for joining conditions. If null it
- * will not set any value, but return the currently stored one
- * @return string|$this
- * @deprecated 3.2.0 Use setConjunction()/getConjunction() instead
- */
- public function type($conjunction = null)
- {
- deprecationWarning(
- 'QueryExpression::type() is deprecated. ' .
- 'Use QueryExpression::setConjunction()/getConjunction() instead.'
- );
-
- return $this->tieWith($conjunction);
- }
-
/**
* Adds one or more conditions to this expression object. Conditions can be
* expressed in a one dimensional array, that will cause all conditions to
@@ -156,7 +116,7 @@ public function type($conjunction = null)
* @see \Cake\Database\Query::where() for examples on conditions
* @return $this
*/
- public function add($conditions, $types = [])
+ public function add($conditions, array $types = [])
{
if (is_string($conditions)) {
$this->_conditions[] = $conditions;
@@ -185,7 +145,7 @@ public function add($conditions, $types = [])
* will be created, one per each value in the array.
* @return $this
*/
- public function eq($field, $value, $type = null)
+ public function eq($field, $value, ?string $type = null)
{
if ($type === null) {
$type = $this->_calculateType($field);
@@ -352,7 +312,7 @@ public function notLike($field, $value, $type = null)
* "field IN (value1, value2)".
*
* @param string|\Cake\Database\ExpressionInterface $field Database field to be compared against value
- * @param string|array $values the value to be bound to $field for comparison
+ * @param string|array|\Cake\Database\ExpressionInterface $values the value to be bound to $field for comparison
* @param string|null $type the type name for $value as configured using the Type map.
* @return $this
*/
@@ -373,8 +333,9 @@ public function in($field, $values, $type = null)
*
* @param array|\Cake\Database\ExpressionInterface $conditions The conditions to test. Must be a ExpressionInterface
* instance, or an array of ExpressionInterface instances.
- * @param array|\Cake\Database\ExpressionInterface $values associative array of values to be associated with the conditions
- * passed in $conditions. If there are more $values than $conditions, the last $value is used as the `ELSE` value
+ * @param array|\Cake\Database\ExpressionInterface $values associative array of values to be associated with the
+ * conditions passed in $conditions. If there are more $values than $conditions,
+ * the last $value is used as the `ELSE` value.
* @param array $types associative array of types to be associated with the values
* passed in $values
* @return $this
@@ -389,7 +350,7 @@ public function addCase($conditions, $values = [], $types = [])
* "field NOT IN (value1, value2)".
*
* @param string|\Cake\Database\ExpressionInterface $field Database field to be compared against value
- * @param array $values the value to be bound to $field for comparison
+ * @param array|\Cake\Database\ExpressionInterface $values the value to be bound to $field for comparison
* @param string|null $type the type name for $value as configured using the Type map.
* @return $this
*/
@@ -431,7 +392,7 @@ public function notExists(ExpressionInterface $query)
* Adds a new condition to the expression object in the form
* "field BETWEEN from AND to".
*
- * @param string|\Cake\Database\ExpressionInterface $field The field name to compare for values in between the range.
+ * @param string|\Cake\Database\ExpressionInterface $field The field name to compare for values inbetween the range.
* @param mixed $from The initial value of the range.
* @param mixed $to The ending value in the comparison range.
* @param string|null $type the type name for $value as configured using the Type map.
@@ -446,19 +407,18 @@ public function between($field, $from, $to, $type = null)
return $this->add(new BetweenExpression($field, $from, $to, $type));
}
-// @codingStandardsIgnoreStart
/**
* Returns a new QueryExpression object containing all the conditions passed
* and set up the conjunction to be "AND"
*
- * @param callable|string|array|\Cake\Database\ExpressionInterface $conditions to be joined with AND
+ * @param \Closure|string|array|\Cake\Database\ExpressionInterface $conditions to be joined with AND
* @param array $types associative array of fields pointing to the type of the
* values that are being passed. Used for correctly binding values to statements.
* @return \Cake\Database\Expression\QueryExpression
*/
- public function and_($conditions, $types = [])
+ public function and($conditions, $types = [])
{
- if ($this->isCallable($conditions)) {
+ if ($conditions instanceof Closure) {
return $conditions(new static([], $this->getTypeMap()->setTypes($types)));
}
@@ -469,20 +429,51 @@ public function and_($conditions, $types = [])
* Returns a new QueryExpression object containing all the conditions passed
* and set up the conjunction to be "OR"
*
- * @param callable|string|array|\Cake\Database\ExpressionInterface $conditions to be joined with OR
+ * @param \Closure|string|array|\Cake\Database\ExpressionInterface $conditions to be joined with OR
* @param array $types associative array of fields pointing to the type of the
* values that are being passed. Used for correctly binding values to statements.
* @return \Cake\Database\Expression\QueryExpression
*/
- public function or_($conditions, $types = [])
+ public function or($conditions, $types = [])
{
- if ($this->isCallable($conditions)) {
+ if ($conditions instanceof Closure) {
return $conditions(new static([], $this->getTypeMap()->setTypes($types), 'OR'));
}
return new static($conditions, $this->getTypeMap()->setTypes($types), 'OR');
}
-// @codingStandardsIgnoreEnd
+
+// phpcs:disable
+ /**
+ * Returns a new QueryExpression object containing all the conditions passed
+ * and set up the conjunction to be "AND"
+ *
+ * @param \Closure|string|array|\Cake\Database\ExpressionInterface $conditions to be joined with AND
+ * @param array $types associative array of fields pointing to the type of the
+ * values that are being passed. Used for correctly binding values to statements.
+ * @return \Cake\Database\Expression\QueryExpression
+ * @deprecated 4.0.0 Use {@link and()} instead.
+ */
+ public function and_($conditions, $types = [])
+ {
+ return $this->and($conditions, $types);
+ }
+
+ /**
+ * Returns a new QueryExpression object containing all the conditions passed
+ * and set up the conjunction to be "OR"
+ *
+ * @param \Closure|string|array|\Cake\Database\ExpressionInterface $conditions to be joined with OR
+ * @param array $types associative array of fields pointing to the type of the
+ * values that are being passed. Used for correctly binding values to statements.
+ * @return \Cake\Database\Expression\QueryExpression
+ * @deprecated 4.0.0 Use {@link or()} instead.
+ */
+ public function or_($conditions, $types = [])
+ {
+ return $this->or($conditions, $types);
+ }
+// phpcs:enable
/**
* Adds a new set of conditions to this level of the tree and negates
@@ -507,7 +498,7 @@ public function not($conditions, $types = [])
*
* @return int
*/
- public function count()
+ public function count(): int
{
return count($this->_conditions);
}
@@ -519,7 +510,7 @@ public function count()
* @param string $right Right join condition field name.
* @return $this
*/
- public function equalFields($left, $right)
+ public function equalFields(string $left, string $right)
{
$wrapIdentifier = function ($field) {
if ($field instanceof ExpressionInterface) {
@@ -541,14 +532,14 @@ public function equalFields($left, $right)
* @param \Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
- public function sql(ValueBinder $generator)
+ public function sql(ValueBinder $generator): string
{
$len = $this->count();
if ($len === 0) {
return '';
}
$conjunction = $this->_conjunction;
- $template = ($len === 1) ? '%s' : '(%s)';
+ $template = $len === 1 ? '%s' : '(%s)';
$parts = [];
foreach ($this->_conditions as $part) {
if ($part instanceof Query) {
@@ -572,10 +563,10 @@ public function sql(ValueBinder $generator)
*
* Callback function receives as only argument an instance of ExpressionInterface
*
- * @param callable $visitor The callable to apply to all sub-expressions.
- * @return void
+ * @param \Closure $visitor The callable to apply to all sub-expressions.
+ * @return $this
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
foreach ($this->_conditions as $c) {
if ($c instanceof ExpressionInterface) {
@@ -583,6 +574,8 @@ public function traverse(callable $visitor)
$c->traverse($visitor);
}
}
+
+ return $this;
}
/**
@@ -597,15 +590,15 @@ public function traverse(callable $visitor)
* passed by reference, this will enable you to change the key under which the
* modified part is stored.
*
- * @param callable $callable The callable to apply to each part.
+ * @param callable $visitor The callable to apply to each part.
* @return $this
*/
- public function iterateParts(callable $callable)
+ public function iterateParts(callable $visitor)
{
$parts = [];
foreach ($this->_conditions as $k => $c) {
- $key =& $k;
- $part = $callable($c, $key);
+ $key = &$k;
+ $part = $visitor($c, $key);
if ($part !== null) {
$parts[$key] = $part;
}
@@ -615,22 +608,6 @@ public function iterateParts(callable $callable)
return $this;
}
- /**
- * Helps calling the `and()` and `or()` methods transparently.
- *
- * @param string $method The method name.
- * @param array $args The arguments to pass to the method.
- * @return \Cake\Database\Expression\QueryExpression
- * @throws \BadMethodCallException
- */
- public function __call($method, $args)
- {
- if (in_array($method, ['and', 'or'])) {
- return call_user_func_array([$this, $method . '_'], $args);
- }
- throw new BadMethodCallException(sprintf('Method %s does not exist', $method));
- }
-
/**
* Check whether or not a callable is acceptable.
*
@@ -638,10 +615,10 @@ public function __call($method, $args)
* as they often contain user input and arrays of strings
* are easy to sneak in.
*
- * @param callable $c The callable to check.
+ * @param callable|string|array|\Cake\Database\ExpressionInterface $c The callable to check.
* @return bool Valid callable.
*/
- public function isCallable($c)
+ public function isCallable($c): bool
{
if (is_string($c)) {
return false;
@@ -659,7 +636,7 @@ public function isCallable($c)
*
* @return bool
*/
- public function hasNestedExpression()
+ public function hasNestedExpression(): bool
{
foreach ($this->_conditions as $c) {
if ($c instanceof ExpressionInterface) {
@@ -680,7 +657,7 @@ public function hasNestedExpression()
* @param array $types list of types associated on fields referenced in $conditions
* @return void
*/
- protected function _addConditions(array $conditions, array $types)
+ protected function _addConditions(array $conditions, array $types): void
{
$operators = ['and', 'or', 'xor'];
@@ -689,7 +666,7 @@ protected function _addConditions(array $conditions, array $types)
foreach ($conditions as $k => $c) {
$numericKey = is_numeric($k);
- if ($this->isCallable($c)) {
+ if ($c instanceof Closure) {
$expr = new static([], $typeMap);
$c = $c($expr, $this);
}
@@ -699,8 +676,12 @@ protected function _addConditions(array $conditions, array $types)
}
$isArray = is_array($c);
- $isOperator = in_array(strtolower($k), $operators);
- $isNot = strtolower($k) === 'not';
+ $isOperator = $isNot = false;
+ if (!$numericKey) {
+ $normalizedKey = strtolower($k);
+ $isOperator = in_array($normalizedKey, $operators);
+ $isNot = $normalizedKey === 'not';
+ }
if (($isOperator || $isNot) && ($isArray || $c instanceof Countable) && count($c) === 0) {
continue;
@@ -743,24 +724,27 @@ protected function _addConditions(array $conditions, array $types)
* be extracted.
* @param mixed $value The value to be bound to a placeholder for the field
* @return string|\Cake\Database\ExpressionInterface
+ * @throws \InvalidArgumentException If operator is invalid or missing on NULL usage.
*/
- protected function _parseCondition($field, $value)
+ protected function _parseCondition(string $field, $value)
{
$operator = '=';
$expression = $field;
$parts = explode(' ', trim($field), 2);
if (count($parts) > 1) {
- list($expression, $operator) = $parts;
+ [$expression, $operator] = $parts;
}
$type = $this->getTypeMap()->type($expression);
$operator = strtolower(trim($operator));
- $typeMultiple = strpos($type, '[]') !== false;
+ $typeMultiple = (is_string($type) && strpos($type, '[]') !== false);
if (in_array($operator, ['in', 'not in']) || $typeMultiple) {
$type = $type ?: 'string';
- $type .= $typeMultiple ? null : '[]';
+ if (!$typeMultiple) {
+ $type .= '[]';
+ }
$operator = $operator === '=' ? 'IN' : $operator;
$operator = $operator === '!=' ? 'NOT IN' : $operator;
$typeMultiple = true;
@@ -794,16 +778,20 @@ protected function _parseCondition($field, $value)
$operator = '!=';
}
+ if ($value === null && $this->_conjunction !== ',') {
+ throw new InvalidArgumentException('Expression is missing operator (IS, IS NOT) with `null` value.');
+ }
+
return new Comparison($expression, $value, $type, $operator);
}
/**
* Returns the type name for the passed field if it was stored in the typeMap
*
- * @param string|\Cake\Database\Expression\IdentifierExpression $field The field name to get a type for.
+ * @param string|\Cake\Database\ExpressionInterface $field The field name to get a type for.
* @return string|null The computed type or null, if the type is unknown.
*/
- protected function _calculateType($field)
+ protected function _calculateType($field): ?string
{
$field = $field instanceof IdentifierExpression ? $field->getIdentifier() : $field;
if (is_string($field)) {
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/TupleComparison.php b/app/vendor/cakephp/cakephp/src/Database/Expression/TupleComparison.php
index 101d8a680..322e01fd7 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/TupleComparison.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/TupleComparison.php
@@ -1,4 +1,6 @@
_type = (array)$types;
+ $this->_type = $types;
+ $this->setField($fields);
+ $this->setValue($values);
+ $this->_operator = $conjunction;
}
/**
- * Returns the type to be used for casting the value to a database representation
+ * Sets the value
*
- * @return array
+ * @param mixed $value The value to compare
+ * @return void
*/
- public function getType()
+ public function setValue($value): void
{
- return $this->_type;
+ $this->_value = $value;
}
/**
@@ -61,7 +67,7 @@ public function getType()
* @param \Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
- public function sql(ValueBinder $generator)
+ public function sql(ValueBinder $generator): string
{
$template = '(%s) %s (%s)';
$fields = [];
@@ -89,7 +95,7 @@ public function sql(ValueBinder $generator)
* @param \Cake\Database\ValueBinder $generator The value binder to convert expressions with.
* @return string
*/
- protected function _stringifyValues($generator)
+ protected function _stringifyValues(ValueBinder $generator): string
{
$values = [];
$parts = $this->getValue();
@@ -105,39 +111,35 @@ protected function _stringifyValues($generator)
}
$type = $this->_type;
- $multiType = is_array($type);
- $isMulti = $this->isMulti();
- $type = $multiType ? $type : str_replace('[]', '', $type);
- $type = $type ?: null;
+ $isMultiOperation = $this->isMulti();
+ if (empty($type)) {
+ $type = null;
+ }
- if ($isMulti) {
+ if ($isMultiOperation) {
$bound = [];
foreach ($value as $k => $val) {
- $valType = $multiType && isset($type[$k]) ? $type[$k] : $type;
- $bound[] = $this->_bindValue($generator, $val, $valType);
+ /** @var string $valType */
+ $valType = $type && isset($type[$k]) ? $type[$k] : $type;
+ $bound[] = $this->_bindValue($val, $generator, $valType);
}
$values[] = sprintf('(%s)', implode(',', $bound));
continue;
}
- $valType = $multiType && isset($type[$i]) ? $type[$i] : $type;
- $values[] = $this->_bindValue($generator, $value, $valType);
+ /** @var string $valType */
+ $valType = $type && isset($type[$i]) ? $type[$i] : $type;
+ $values[] = $this->_bindValue($value, $generator, $valType);
}
return implode(', ', $values);
}
/**
- * Registers a value in the placeholder generator and returns the generated
- * placeholder
- *
- * @param \Cake\Database\ValueBinder $generator The value binder
- * @param mixed $value The value to bind
- * @param string $type The type to use
- * @return string generated placeholder
+ * @inheritDoc
*/
- protected function _bindValue($generator, $value, $type)
+ protected function _bindValue($value, ValueBinder $generator, ?string $type = null): string
{
$placeholder = $generator->placeholder('tuple');
$generator->bind($placeholder, $value, $type);
@@ -151,12 +153,14 @@ protected function _bindValue($generator, $value, $type)
*
* Callback function receives as its only argument an instance of an ExpressionInterface
*
- * @param callable $visitor The callable to apply to sub-expressions
- * @return void
+ * @param \Closure $visitor The callable to apply to sub-expressions
+ * @return $this
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
- foreach ($this->getField() as $field) {
+ /** @var string[] $fields */
+ $fields = $this->getField();
+ foreach ($fields as $field) {
$this->_traverseValue($field, $visitor);
}
@@ -165,10 +169,10 @@ public function traverse(callable $visitor)
$visitor($value);
$value->traverse($visitor);
- return;
+ return $this;
}
- foreach ($value as $i => $val) {
+ foreach ($value as $val) {
if ($this->isMulti()) {
foreach ($val as $v) {
$this->_traverseValue($v, $visitor);
@@ -177,6 +181,8 @@ public function traverse(callable $visitor)
$this->_traverseValue($val, $visitor);
}
}
+
+ return $this;
}
/**
@@ -184,10 +190,10 @@ public function traverse(callable $visitor)
* it is an ExpressionInterface
*
* @param mixed $value The value to traverse
- * @param callable $callable The callable to use when traversing
+ * @param \Closure $callable The callable to use when traversing
* @return void
*/
- protected function _traverseValue($value, $callable)
+ protected function _traverseValue($value, Closure $callable): void
{
if ($value instanceof ExpressionInterface) {
$callable($value);
@@ -201,7 +207,7 @@ protected function _traverseValue($value, $callable)
*
* @return bool
*/
- public function isMulti()
+ public function isMulti(): bool
{
return in_array(strtolower($this->_operator), ['in', 'not in']);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/UnaryExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/UnaryExpression.php
index 554e9a527..dc42cff5b 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/UnaryExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/UnaryExpression.php
@@ -1,4 +1,6 @@
_operator = $operator;
$this->_value = $value;
@@ -77,7 +80,7 @@ public function __construct($operator, $value, $mode = self::PREFIX)
* @param \Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
- public function sql(ValueBinder $generator)
+ public function sql(ValueBinder $generator): string
{
$operand = $this->_value;
if ($operand instanceof ExpressionInterface) {
@@ -92,14 +95,16 @@ public function sql(ValueBinder $generator)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
if ($this->_value instanceof ExpressionInterface) {
$visitor($this->_value);
$this->_value->traverse($visitor);
}
+
+ return $this;
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/ValuesExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/ValuesExpression.php
index 389caa438..57113ed83 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/ValuesExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/ValuesExpression.php
@@ -1,4 +1,6 @@
type names
*/
- public function __construct(array $columns, $typeMap)
+ public function __construct(array $columns, TypeMap $typeMap)
{
$this->_columns = $columns;
$this->setTypeMap($typeMap);
@@ -81,11 +85,17 @@ public function __construct(array $columns, $typeMap)
* @return void
* @throws \Cake\Database\Exception When mixing array + Query data types.
*/
- public function add($data)
+ public function add($data): void
{
if (
- (count($this->_values) && $data instanceof Query) ||
- ($this->_query && is_array($data))
+ (
+ count($this->_values) &&
+ $data instanceof Query
+ ) ||
+ (
+ $this->_query &&
+ is_array($data)
+ )
) {
throw new Exception(
'You cannot mix subqueries and array data in inserts.'
@@ -106,7 +116,7 @@ public function add($data)
* @param array $cols Array with columns to be inserted.
* @return $this
*/
- public function setColumns($cols)
+ public function setColumns(array $cols)
{
$this->_columns = $cols;
$this->_castedExpressions = false;
@@ -119,32 +129,11 @@ public function setColumns($cols)
*
* @return array
*/
- public function getColumns()
+ public function getColumns(): array
{
return $this->_columns;
}
- /**
- * Sets the columns to be inserted. If no params are passed, then it returns
- * the currently stored columns.
- *
- * @deprecated 3.4.0 Use setColumns()/getColumns() instead.
- * @param array|null $cols Array with columns to be inserted.
- * @return array|$this
- */
- public function columns($cols = null)
- {
- deprecationWarning(
- 'ValuesExpression::columns() is deprecated. ' .
- 'Use ValuesExpression::setColumns()/getColumns() instead.'
- );
- if ($cols !== null) {
- return $this->setColumns($cols);
- }
-
- return $this->getColumns();
- }
-
/**
* Get the bare column names.
*
@@ -153,7 +142,7 @@ public function columns($cols = null)
*
* @return array
*/
- protected function _columnNames()
+ protected function _columnNames(): array
{
$columns = [];
foreach ($this->_columns as $col) {
@@ -172,7 +161,7 @@ protected function _columnNames()
* @param array $values Array with values to be inserted.
* @return $this
*/
- public function setValues($values)
+ public function setValues(array $values)
{
$this->_values = $values;
$this->_castedExpressions = false;
@@ -185,7 +174,7 @@ public function setValues($values)
*
* @return array
*/
- public function getValues()
+ public function getValues(): array
{
if (!$this->_castedExpressions) {
$this->_processExpressions();
@@ -194,27 +183,6 @@ public function getValues()
return $this->_values;
}
- /**
- * Sets the values to be inserted. If no params are passed, then it returns
- * the currently stored values
- *
- * @deprecated 3.4.0 Use setValues()/getValues() instead.
- * @param array|null $values Array with values to be inserted.
- * @return array|$this
- */
- public function values($values = null)
- {
- deprecationWarning(
- 'ValuesExpression::values() is deprecated. ' .
- 'Use ValuesExpression::setValues()/getValues() instead.'
- );
- if ($values !== null) {
- return $this->setValues($values);
- }
-
- return $this->getValues();
- }
-
/**
* Sets the query object to be used as the values expression to be evaluated
* to insert records in the table.
@@ -235,40 +203,18 @@ public function setQuery(Query $query)
*
* @return \Cake\Database\Query|null
*/
- public function getQuery()
+ public function getQuery(): ?Query
{
return $this->_query;
}
- /**
- * Sets the query object to be used as the values expression to be evaluated
- * to insert records in the table. If no params are passed, then it returns
- * the currently stored query
- *
- * @deprecated 3.4.0 Use setQuery()/getQuery() instead.
- * @param \Cake\Database\Query|null $query The query to set
- * @return \Cake\Database\Query|null|$this
- */
- public function query(Query $query = null)
- {
- deprecationWarning(
- 'ValuesExpression::query() is deprecated. ' .
- 'Use ValuesExpression::setQuery()/getQuery() instead.'
- );
- if ($query !== null) {
- return $this->setQuery($query);
- }
-
- return $this->getQuery();
- }
-
/**
* Convert the values into a SQL string with placeholders.
*
* @param \Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
- public function sql(ValueBinder $generator)
+ public function sql(ValueBinder $generator): string
{
if (empty($this->_values) && empty($this->_query)) {
return '';
@@ -308,8 +254,9 @@ public function sql(ValueBinder $generator)
$placeholders[] = implode(', ', $rowPlaceholders);
}
- if ($this->getQuery()) {
- return ' ' . $this->getQuery()->sql($generator);
+ $query = $this->getQuery();
+ if ($query) {
+ return ' ' . $query->sql($generator);
}
return sprintf(' VALUES (%s)', implode('), (', $placeholders));
@@ -321,13 +268,13 @@ public function sql(ValueBinder $generator)
* This method will also traverse any queries that are to be used in the INSERT
* values.
*
- * @param callable $visitor The visitor to traverse the expression with.
- * @return void
+ * @param \Closure $visitor The visitor to traverse the expression with.
+ * @return $this
*/
- public function traverse(callable $visitor)
+ public function traverse(Closure $visitor)
{
if ($this->_query) {
- return;
+ return $this;
}
if (!$this->_castedExpressions) {
@@ -341,13 +288,15 @@ public function traverse(callable $visitor)
if (!is_array($v)) {
continue;
}
- foreach ($v as $column => $field) {
+ foreach ($v as $field) {
if ($field instanceof ExpressionInterface) {
$visitor($field);
$field->traverse($visitor);
}
}
}
+
+ return $this;
}
/**
@@ -355,14 +304,14 @@ public function traverse(callable $visitor)
*
* @return void
*/
- protected function _processExpressions()
+ protected function _processExpressions(): void
{
$types = [];
$typeMap = $this->getTypeMap();
$columns = $this->_columnNames();
foreach ($columns as $c) {
- if (!is_scalar($c)) {
+ if (!is_string($c) && !is_int($c)) {
continue;
}
$types[$c] = $typeMap->type($c);
diff --git a/app/vendor/cakephp/cakephp/src/Database/ExpressionInterface.php b/app/vendor/cakephp/cakephp/src/Database/ExpressionInterface.php
index 1091fcaa3..3304b29ac 100644
--- a/app/vendor/cakephp/cakephp/src/Database/ExpressionInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/ExpressionInterface.php
@@ -1,4 +1,6 @@
_driver = $driver;
$map = $typeMap->toArray();
- $types = Type::buildAll();
+ $types = TypeFactory::buildAll();
$simpleMap = $batchingMap = [];
$simpleResult = $batchingResult = [];
@@ -76,15 +77,7 @@ public function __construct(TypeMap $typeMap, Driver $driver)
continue;
}
- // Because of backwards compatibility reasons, we won't allow classes
- // inheriting Type in userland code to be batchable, even if they implement
- // the interface. Users can implement the TypeInterface instead to have
- // access to this feature.
- $batchingType = $type instanceof BatchCastingInterface &&
- !($type instanceof Type &&
- strpos(get_class($type), 'Cake\Database\Type') === false);
-
- if ($batchingType) {
+ if ($type instanceof BatchCastingInterface) {
$batchingMap[$k] = $type;
continue;
}
@@ -127,7 +120,7 @@ public function __construct(TypeMap $typeMap, Driver $driver)
* @param array $row The array with the fields to be casted
* @return array
*/
- public function __invoke($row)
+ public function __invoke(array $row): array
{
if (!empty($this->_typeMap)) {
foreach ($this->_typeMap as $field => $type) {
@@ -137,6 +130,7 @@ public function __invoke($row)
if (!empty($this->batchingTypeMap)) {
foreach ($this->batchingTypeMap as $t => $fields) {
+ /** @psalm-suppress PossiblyUndefinedMethod */
$row = $this->types[$t]->manyToPHP($row, $fields, $this->_driver);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/FunctionsBuilder.php b/app/vendor/cakephp/cakephp/src/Database/FunctionsBuilder.php
index 09fe941df..f803a8ad8 100644
--- a/app/vendor/cakephp/cakephp/src/Database/FunctionsBuilder.php
+++ b/app/vendor/cakephp/cakephp/src/Database/FunctionsBuilder.php
@@ -1,4 +1,6 @@
_build('RAND', [], [], 'float');
}
@@ -76,7 +87,7 @@ public function rand()
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function sum($expression, $types = [])
+ public function sum($expression, $types = []): FunctionExpression
{
$returnType = 'float';
if (current($types) === 'integer') {
@@ -93,7 +104,7 @@ public function sum($expression, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function avg($expression, $types = [])
+ public function avg($expression, $types = []): FunctionExpression
{
return $this->_literalArgumentFunction('AVG', $expression, $types, 'float');
}
@@ -105,7 +116,7 @@ public function avg($expression, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function max($expression, $types = [])
+ public function max($expression, $types = []): FunctionExpression
{
return $this->_literalArgumentFunction('MAX', $expression, $types, current($types) ?: 'string');
}
@@ -117,7 +128,7 @@ public function max($expression, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function min($expression, $types = [])
+ public function min($expression, $types = []): FunctionExpression
{
return $this->_literalArgumentFunction('MIN', $expression, $types, current($types) ?: 'string');
}
@@ -129,7 +140,7 @@ public function min($expression, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function count($expression, $types = [])
+ public function count($expression, $types = []): FunctionExpression
{
return $this->_literalArgumentFunction('COUNT', $expression, $types, 'integer');
}
@@ -141,7 +152,7 @@ public function count($expression, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function concat($args, $types = [])
+ public function concat(array $args, array $types = []): FunctionExpression
{
return $this->_build('CONCAT', $args, $types, 'string');
}
@@ -153,35 +164,11 @@ public function concat($args, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function coalesce($args, $types = [])
+ public function coalesce(array $args, array $types = []): FunctionExpression
{
return $this->_build('COALESCE', $args, $types, current($types) ?: 'string');
}
- /**
- * Returns a FunctionExpression representing a call to SQL CAST function.
- *
- * @param string|\Cake\Database\ExpressionInterface $field Field or expression to cast.
- * @param string $type The target data type
- * @return \Cake\Database\Expression\FunctionExpression
- */
- public function cast($field, $type = '')
- {
- if (is_array($field)) {
- deprecationWarning(
- 'Build cast function by FunctionsBuilder::cast(array $args) is deprecated. ' .
- 'Use FunctionsBuilder::cast($field, string $type) instead.'
- );
-
- return $this->_build('CAST', $field);
- }
-
- $expression = $this->_literalArgumentFunction('CAST', $field);
- $expression->setConjunction(' AS')->add([$type => 'literal']);
-
- return $expression;
- }
-
/**
* Returns a FunctionExpression representing the difference in days between
* two dates.
@@ -190,7 +177,7 @@ public function cast($field, $type = '')
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function dateDiff($args, $types = [])
+ public function dateDiff(array $args, array $types = []): FunctionExpression
{
return $this->_build('DATEDIFF', $args, $types, 'integer');
}
@@ -203,7 +190,7 @@ public function dateDiff($args, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function datePart($part, $expression, $types = [])
+ public function datePart(string $part, $expression, array $types = []): FunctionExpression
{
return $this->extract($part, $expression, $types);
}
@@ -216,7 +203,7 @@ public function datePart($part, $expression, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function extract($part, $expression, $types = [])
+ public function extract(string $part, $expression, array $types = []): FunctionExpression
{
$expression = $this->_literalArgumentFunction('EXTRACT', $expression, $types, 'integer');
$expression->setConjunction(' FROM')->add([$part => 'literal'], [], true);
@@ -233,7 +220,7 @@ public function extract($part, $expression, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function dateAdd($expression, $value, $unit, $types = [])
+ public function dateAdd($expression, $value, string $unit, array $types = []): FunctionExpression
{
if (!is_numeric($value)) {
$value = 0;
@@ -253,7 +240,7 @@ public function dateAdd($expression, $value, $unit, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function dayOfWeek($expression, $types = [])
+ public function dayOfWeek($expression, $types = []): FunctionExpression
{
return $this->_literalArgumentFunction('DAYOFWEEK', $expression, $types, 'integer');
}
@@ -266,7 +253,7 @@ public function dayOfWeek($expression, $types = [])
* @param array $types list of types to bind to the arguments
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function weekday($expression, $types = [])
+ public function weekday($expression, $types = []): FunctionExpression
{
return $this->dayOfWeek($expression, $types);
}
@@ -279,7 +266,7 @@ public function weekday($expression, $types = [])
* @param string $type (datetime|date|time)
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function now($type = 'datetime')
+ public function now(string $type = 'datetime'): FunctionExpression
{
if ($type === 'datetime') {
return $this->_build('NOW')->setReturnType('datetime');
@@ -290,6 +277,8 @@ public function now($type = 'datetime')
if ($type === 'time') {
return $this->_build('CURRENT_TIME')->setReturnType('time');
}
+
+ throw new InvalidArgumentException('Invalid argument for FunctionsBuilder::now(): ' . $type);
}
/**
@@ -301,7 +290,7 @@ public function now($type = 'datetime')
* params, and the third one the return type of the function
* @return \Cake\Database\Expression\FunctionExpression
*/
- public function __call($name, $args)
+ public function __call(string $name, array $args): FunctionExpression
{
switch (count($args)) {
case 0:
diff --git a/app/vendor/cakephp/cakephp/src/Database/IdentifierQuoter.php b/app/vendor/cakephp/cakephp/src/Database/IdentifierQuoter.php
index e82695b22..c05718aa2 100644
--- a/app/vendor/cakephp/cakephp/src/Database/IdentifierQuoter.php
+++ b/app/vendor/cakephp/cakephp/src/Database/IdentifierQuoter.php
@@ -1,4 +1,6 @@
getValueBinder();
- $query->setValueBinder(false);
+ $query->setValueBinder(null);
if ($query->type() === 'insert') {
$this->_quoteInsert($query);
@@ -74,7 +76,7 @@ public function quote(Query $query)
* @param \Cake\Database\ExpressionInterface $expression The expression object to walk and quote.
* @return void
*/
- public function quoteExpression($expression)
+ public function quoteExpression(ExpressionInterface $expression): void
{
if ($expression instanceof FieldInterface) {
$this->_quoteComparison($expression);
@@ -101,7 +103,7 @@ public function quoteExpression($expression)
* @param \Cake\Database\Query $query The query to quote.
* @return void
*/
- protected function _quoteParts($query)
+ protected function _quoteParts(Query $query): void
{
foreach (['distinct', 'select', 'from', 'group'] as $part) {
$contents = $query->clause($part);
@@ -129,7 +131,7 @@ protected function _quoteParts($query)
* @param array $part the part of the query to quote
* @return array
*/
- protected function _basicQuoter($part)
+ protected function _basicQuoter(array $part): array
{
$result = [];
foreach ((array)$part as $alias => $value) {
@@ -148,11 +150,11 @@ protected function _basicQuoter($part)
* @param array $joins The joins to quote.
* @return array
*/
- protected function _quoteJoins($joins)
+ protected function _quoteJoins(array $joins): array
{
$result = [];
foreach ($joins as $value) {
- $alias = null;
+ $alias = '';
if (!empty($value['alias'])) {
$alias = $this->_driver->quoteIdentifier($value['alias']);
$value['alias'] = $alias;
@@ -174,13 +176,13 @@ protected function _quoteJoins($joins)
* @param \Cake\Database\Query $query The insert query to quote.
* @return void
*/
- protected function _quoteInsert($query)
+ protected function _quoteInsert(Query $query): void
{
- list($table, $columns) = $query->clause('insert');
+ [$table, $columns] = $query->clause('insert');
$table = $this->_driver->quoteIdentifier($table);
foreach ($columns as &$column) {
if (is_scalar($column)) {
- $column = $this->_driver->quoteIdentifier($column);
+ $column = $this->_driver->quoteIdentifier((string)$column);
}
}
$query->insert($columns)->into($table);
@@ -192,7 +194,7 @@ protected function _quoteInsert($query)
* @param \Cake\Database\Query $query The update query to quote.
* @return void
*/
- protected function _quoteUpdate($query)
+ protected function _quoteUpdate(Query $query): void
{
$table = $query->clause('update')[0];
@@ -207,7 +209,7 @@ protected function _quoteUpdate($query)
* @param \Cake\Database\Expression\FieldInterface $expression The expression to quote.
* @return void
*/
- protected function _quoteComparison(FieldInterface $expression)
+ protected function _quoteComparison(FieldInterface $expression): void
{
$field = $expression->getField();
if (is_string($field)) {
@@ -232,7 +234,7 @@ protected function _quoteComparison(FieldInterface $expression)
* @param \Cake\Database\Expression\OrderByExpression $expression The expression to quote.
* @return void
*/
- protected function _quoteOrderBy(OrderByExpression $expression)
+ protected function _quoteOrderBy(OrderByExpression $expression): void
{
$expression->iterateParts(function ($part, &$field) {
if (is_string($field)) {
@@ -254,7 +256,7 @@ protected function _quoteOrderBy(OrderByExpression $expression)
* @param \Cake\Database\Expression\IdentifierExpression $expression The identifiers to quote.
* @return void
*/
- protected function _quoteIdentifierExpression(IdentifierExpression $expression)
+ protected function _quoteIdentifierExpression(IdentifierExpression $expression): void
{
$expression->setIdentifier(
$this->_driver->quoteIdentifier($expression->getIdentifier())
diff --git a/app/vendor/cakephp/cakephp/src/Database/LICENSE.txt b/app/vendor/cakephp/cakephp/src/Database/LICENSE.txt
index 0c4b7932c..0b3b94303 100644
--- a/app/vendor/cakephp/cakephp/src/Database/LICENSE.txt
+++ b/app/vendor/cakephp/cakephp/src/Database/LICENSE.txt
@@ -1,7 +1,7 @@
The MIT License (MIT)
CakePHP(tm) : The Rapid Development PHP Framework (https://cakephp.org)
-Copyright (c) 2005-2016, Cake Software Foundation, Inc. (https://cakefoundation.org)
+Copyright (c) 2005-2019, Cake Software Foundation, Inc. (https://cakefoundation.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/vendor/cakephp/cakephp/src/Database/Log/LoggedQuery.php b/app/vendor/cakephp/cakephp/src/Database/Log/LoggedQuery.php
index b66328dd4..96a3ac199 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Log/LoggedQuery.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Log/LoggedQuery.php
@@ -1,4 +1,6 @@
'\\$',
+ '\\' => '\\\\\\\\',
+ "'" => "''",
+ ];
+
+ $p = strtr($p, $replacements);
+
+ return "'$p'";
+ }
+
+ return $p;
+ }, $this->params);
+
+ $keys = [];
+ $limit = is_int(key($params)) ? 1 : -1;
+ foreach ($params as $key => $param) {
+ $keys[] = is_string($key) ? "/:$key\b/" : '/[?]/';
+ }
+
+ return preg_replace($keys, $params, $this->query, $limit);
+ }
+
+ /**
+ * Returns data that will be serialized as JSON
+ *
+ * @return array
+ */
+ public function jsonSerialize(): array
+ {
+ $error = $this->error;
+ if ($error !== null) {
+ $error = [
+ 'class' => get_class($error),
+ 'message' => $error->getMessage(),
+ 'code' => $error->getCode(),
+ ];
+ }
+
+ return [
+ 'query' => $this->query,
+ 'numRows' => $this->numRows,
+ 'params' => $this->params,
+ 'took' => $this->took,
+ 'error' => $error,
+ ];
+ }
+
/**
* Returns the string representation of this logged query
*
* @return string
*/
- public function __toString()
+ public function __toString(): string
{
- return "duration={$this->took} rows={$this->numRows} {$this->query}";
+ $sql = $this->query;
+ if (!empty($this->params)) {
+ $sql = $this->interpolate();
+ }
+
+ return "duration={$this->took} rows={$this->numRows} {$sql}";
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Log/LoggingStatement.php b/app/vendor/cakephp/cakephp/src/Database/Log/LoggingStatement.php
index d38c0a622..674cf6bb3 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Log/LoggingStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Log/LoggingStatement.php
@@ -1,4 +1,6 @@
queryString = $this->queryString;
$query->error = $e;
$this->_log($query, $params, $t);
@@ -71,16 +75,16 @@ public function execute($params = null)
* to the logging system.
*
* @param \Cake\Database\Log\LoggedQuery $query The query to log.
- * @param array $params List of values to be bound to query.
+ * @param array|null $params List of values to be bound to query.
* @param float $startTime The microtime when the query was executed.
* @return void
*/
- protected function _log($query, $params, $startTime)
+ protected function _log(LoggedQuery $query, ?array $params, float $startTime): void
{
$query->took = (int)round((microtime(true) - $startTime) * 1000, 0);
$query->params = $params ?: $this->_compiledParams;
$query->query = $this->queryString;
- $this->getLogger()->log($query);
+ $this->getLogger()->debug((string)$query, ['query' => $query]);
}
/**
@@ -92,9 +96,10 @@ protected function _log($query, $params, $startTime)
* @param string|int|null $type PDO type or name of configured Type class
* @return void
*/
- public function bindValue($column, $value, $type = 'string')
+ public function bindValue($column, $value, $type = 'string'): void
{
parent::bindValue($column, $value, $type);
+
if ($type === null) {
$type = 'string';
}
@@ -104,34 +109,13 @@ public function bindValue($column, $value, $type = 'string')
$this->_compiledParams[$column] = $value;
}
- /**
- * Sets the logger object instance. When called with no arguments
- * it returns the currently setup logger instance
- *
- * @deprecated 3.5.0 Use getLogger() and setLogger() instead.
- * @param \Cake\Database\Log\QueryLogger|null $instance Logger object instance.
- * @return \Cake\Database\Log\QueryLogger|null Logger instance
- */
- public function logger($instance = null)
- {
- deprecationWarning(
- 'LoggingStatement::logger() is deprecated. ' .
- 'Use LoggingStatement::setLogger()/getLogger() instead.'
- );
- if ($instance === null) {
- return $this->getLogger();
- }
-
- return $this->_logger = $instance;
- }
-
/**
* Sets a logger
*
- * @param \Cake\Database\Log\QueryLogger $logger Logger object
+ * @param \Psr\Log\LoggerInterface $logger Logger object
* @return void
*/
- public function setLogger($logger)
+ public function setLogger(LoggerInterface $logger): void
{
$this->_logger = $logger;
}
@@ -139,9 +123,9 @@ public function setLogger($logger)
/**
* Gets the logger object
*
- * @return \Cake\Database\Log\QueryLogger logger instance
+ * @return \Psr\Log\LoggerInterface logger instance
*/
- public function getLogger()
+ public function getLogger(): LoggerInterface
{
return $this->_logger;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Log/QueryLogger.php b/app/vendor/cakephp/cakephp/src/Database/Log/QueryLogger.php
index 198f2300b..a3a229655 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Log/QueryLogger.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Log/QueryLogger.php
@@ -1,4 +1,6 @@
params)) {
- $query->query = $this->_interpolate($query);
- }
- $this->_log($query);
- }
+ $this->_defaultConfig['scopes'] = ['queriesLog'];
- /**
- * Wrapper function for the logger object, useful for unit testing
- * or for overriding in subclasses.
- *
- * @param \Cake\Database\Log\LoggedQuery $query to be written in log
- * @return void
- */
- protected function _log($query)
- {
- Log::write('debug', $query, ['queriesLog']);
+ parent::__construct($config);
}
/**
- * Helper function used to replace query placeholders by the real
- * params used to execute the query
- *
- * @param \Cake\Database\Log\LoggedQuery $query The query to log
- * @return string
+ * @inheritDoc
*/
- protected function _interpolate($query)
+ public function log($level, $message, array $context = [])
{
- $params = array_map(function ($p) {
- if ($p === null) {
- return 'NULL';
- }
- if (is_bool($p)) {
- return $p ? '1' : '0';
- }
-
- if (is_string($p)) {
- $replacements = [
- '$' => '\\$',
- '\\' => '\\\\\\\\',
- "'" => "''",
- ];
-
- $p = strtr($p, $replacements);
-
- return "'$p'";
- }
-
- return $p;
- }, $query->params);
-
- $keys = [];
- $limit = is_int(key($params)) ? 1 : -1;
- foreach ($params as $key => $param) {
- $keys[] = is_string($key) ? "/:$key\b/" : '/[?]/';
- }
-
- return preg_replace($keys, $params, $query->query, $limit);
+ Log::write(
+ 'debug',
+ (string)$context['query'],
+ ['scope' => $this->scopes() ?: ['queriesLog']]
+ );
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/PostgresCompiler.php b/app/vendor/cakephp/cakephp/src/Database/PostgresCompiler.php
new file mode 100644
index 000000000..e4bc8951c
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/PostgresCompiler.php
@@ -0,0 +1,35 @@
+ null,
];
+ /**
+ * The list of query clauses to traverse for generating a SELECT statement
+ *
+ * @var string[]
+ */
+ protected $_selectParts = [
+ 'select', 'from', 'join', 'where', 'group', 'having', 'order', 'limit',
+ 'offset', 'union', 'epilog',
+ ];
+
+ /**
+ * The list of query clauses to traverse for generating an UPDATE statement
+ *
+ * @var string[]
+ */
+ protected $_updateParts = ['update', 'set', 'where', 'epilog'];
+
+ /**
+ * The list of query clauses to traverse for generating a DELETE statement
+ *
+ * @var string[]
+ */
+ protected $_deleteParts = ['delete', 'modifier', 'from', 'where', 'epilog'];
+
+ /**
+ * The list of query clauses to traverse for generating an INSERT statement
+ *
+ * @var string[]
+ */
+ protected $_insertParts = ['insert', 'values', 'epilog'];
+
/**
* Indicates whether internal state of this query was changed, this is used to
* discard internal cached objects such as the transformed query or the reference
@@ -89,7 +137,7 @@ class Query implements ExpressionInterface, IteratorAggregate
* statement upon retrieval. Each one of the callback function will receive
* the row array as first argument.
*
- * @var array
+ * @var callable[]
*/
protected $_resultDecorators = [];
@@ -143,7 +191,7 @@ class Query implements ExpressionInterface, IteratorAggregate
* @param \Cake\Database\Connection $connection The connection
* object to be used for transforming and executing this query
*/
- public function __construct($connection)
+ public function __construct(Connection $connection)
{
$this->setConnection($connection);
}
@@ -154,7 +202,7 @@ public function __construct($connection)
* @param \Cake\Database\Connection $connection Connection instance
* @return $this
*/
- public function setConnection($connection)
+ public function setConnection(Connection $connection)
{
$this->_dirty();
$this->_connection = $connection;
@@ -167,32 +215,11 @@ public function setConnection($connection)
*
* @return \Cake\Database\Connection
*/
- public function getConnection()
+ public function getConnection(): Connection
{
return $this->_connection;
}
- /**
- * Sets the connection instance to be used for executing and transforming this query
- * When called with a null argument, it will return the current connection instance.
- *
- * @deprecated 3.4.0 Use setConnection()/getConnection() instead.
- * @param \Cake\Database\Connection|null $connection Connection instance
- * @return $this|\Cake\Database\Connection
- */
- public function connection($connection = null)
- {
- deprecationWarning(
- 'Query::connection() is deprecated. ' .
- 'Use Query::setConnection()/getConnection() instead.'
- );
- if ($connection !== null) {
- return $this->setConnection($connection);
- }
-
- return $this->getConnection();
- }
-
/**
* Compiles the SQL representation of this query and executes it using the
* configured connection object. Returns the resulting statement object.
@@ -213,7 +240,7 @@ public function connection($connection = null)
*
* @return \Cake\Database\StatementInterface
*/
- public function execute()
+ public function execute(): StatementInterface
{
$statement = $this->_connection->run($this);
$this->_iterator = $this->_decorateStatement($statement);
@@ -243,7 +270,7 @@ public function execute()
*
* @return int
*/
- public function rowCountAndClose()
+ public function rowCountAndClose(): int
{
$statement = $this->execute();
try {
@@ -269,7 +296,7 @@ public function rowCountAndClose()
* associated values for expressions
* @return string
*/
- public function sql(ValueBinder $generator = null)
+ public function sql(?ValueBinder $generator = null): string
{
if (!$generator) {
$generator = $this->getValueBinder();
@@ -288,7 +315,39 @@ public function sql(ValueBinder $generator = null)
* The callback will receive 2 parameters, the first one is the value of the query
* part that is being iterated and the second the name of such part.
*
- * ### Example:
+ * ### Example
+ * ```
+ * $query->select(['title'])->from('articles')->traverse(function ($value, $clause) {
+ * if ($clause === 'select') {
+ * var_dump($value);
+ * }
+ * });
+ * ```
+ *
+ * @param callable $visitor A function or callable to be executed for each part
+ * @return $this
+ */
+ public function traverse($visitor)
+ {
+ foreach ($this->_parts as $name => $part) {
+ $visitor($part, $name);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Will iterate over the provided parts.
+ *
+ * Traversing functions can aggregate results using variables in the closure
+ * or instance variables. This method can be used to traverse a subset of
+ * query parts in order to render a SQL query.
+ *
+ * The callback will receive 2 parameters, the first one is the value of the query
+ * part that is being iterated and the second the name of such part.
+ *
+ * ### Example
+ *
* ```
* $query->select(['title'])->from('articles')->traverse(function ($value, $clause) {
* if ($clause === 'select') {
@@ -298,12 +357,11 @@ public function sql(ValueBinder $generator = null)
* ```
*
* @param callable $visitor A function or callable to be executed for each part
- * @param string[] $parts The query clauses to traverse
+ * @param string[] $parts The list of query parts to traverse
* @return $this
*/
- public function traverse(callable $visitor, array $parts = [])
+ public function traverseParts(callable $visitor, array $parts)
{
- $parts = $parts ?: array_keys($this->_parts);
foreach ($parts as $name) {
$visitor($this->_parts[$name], $name);
}
@@ -346,7 +404,7 @@ public function traverse(callable $visitor, array $parts = [])
* @param bool $overwrite whether to reset fields with passed list or not
* @return $this
*/
- public function select($fields = [], $overwrite = false)
+ public function select($fields = [], bool $overwrite = false)
{
if (!is_string($fields) && is_callable($fields)) {
$fields = $fields($this);
@@ -478,16 +536,10 @@ public function modifier($modifiers, $overwrite = false)
* passed as an array of strings, array of expression objects, or a single string. See
* the examples above for the valid call types.
* @param bool $overwrite whether to reset tables with passed list or not
- * @return $this|array
+ * @return $this
*/
public function from($tables = [], $overwrite = false)
{
- if (empty($tables)) {
- deprecationWarning('Using Query::from() to read state is deprecated. Use clause("from") instead.');
-
- return $this->_parts['from'];
- }
-
$tables = (array)$tables;
if ($overwrite) {
@@ -581,20 +633,14 @@ public function from($tables = [], $overwrite = false)
* $query->join(['something' => 'different_table'], [], true); // resets joins list
* ```
*
- * @param array|string|null $tables list of tables to be joined in the query
+ * @param array|string $tables list of tables to be joined in the query
* @param array $types associative array of type names used to bind values to query
* @param bool $overwrite whether to reset joins with passed list or not
- * @see \Cake\Database\Type
- * @return $this|array
+ * @see \Cake\Database\TypeFactory
+ * @return $this
*/
- public function join($tables = null, $types = [], $overwrite = false)
+ public function join($tables, $types = [], $overwrite = false)
{
- if ($tables === null) {
- deprecationWarning('Using Query::join() to read state is deprecated. Use Query::clause("join") instead.');
-
- return $this->_parts['join'];
- }
-
if (is_string($tables) || isset($tables['table'])) {
$tables = [$tables];
}
@@ -614,7 +660,7 @@ public function join($tables = null, $types = [], $overwrite = false)
$t['conditions'] = $this->newExpr()->add($t['conditions'], $types);
}
$alias = is_string($alias) ? $alias : null;
- $joins[$alias ?: $i++] = $t + ['type' => QueryInterface::JOIN_TYPE_INNER, 'alias' => $alias];
+ $joins[$alias ?: $i++] = $t + ['type' => static::JOIN_TYPE_INNER, 'alias' => $alias];
}
if ($overwrite) {
@@ -637,7 +683,7 @@ public function join($tables = null, $types = [], $overwrite = false)
* @param string $name The alias/name of the join to remove.
* @return $this
*/
- public function removeJoin($name)
+ public function removeJoin(string $name)
{
unset($this->_parts['join'][$name]);
$this->_dirty();
@@ -675,7 +721,7 @@ public function removeJoin($name)
*
* See `join()` for further details on conditions and types.
*
- * @param string|string[]|\Cake\Database\ExpressionInterface[] $table The table to join with
+ * @param string|string[] $table The table to join with
* @param string|array|\Cake\Database\ExpressionInterface $conditions The conditions
* to use for joining.
* @param array $types a list of types associated to the conditions used for converting
@@ -684,7 +730,9 @@ public function removeJoin($name)
*/
public function leftJoin($table, $conditions = [], $types = [])
{
- return $this->join($this->_makeJoin($table, $conditions, QueryInterface::JOIN_TYPE_LEFT), $types);
+ $this->join($this->_makeJoin($table, $conditions, static::JOIN_TYPE_LEFT), $types);
+
+ return $this;
}
/**
@@ -695,7 +743,7 @@ public function leftJoin($table, $conditions = [], $types = [])
* The arguments of this method are identical to the `leftJoin()` shorthand, please refer
* to that methods description for further details.
*
- * @param string|string[]|\Cake\Database\ExpressionInterface[] $table The table to join with
+ * @param string|string[] $table The table to join with
* @param string|array|\Cake\Database\ExpressionInterface $conditions The conditions
* to use for joining.
* @param array $types a list of types associated to the conditions used for converting
@@ -704,7 +752,9 @@ public function leftJoin($table, $conditions = [], $types = [])
*/
public function rightJoin($table, $conditions = [], $types = [])
{
- return $this->join($this->_makeJoin($table, $conditions, QueryInterface::JOIN_TYPE_RIGHT), $types);
+ $this->join($this->_makeJoin($table, $conditions, static::JOIN_TYPE_RIGHT), $types);
+
+ return $this;
}
/**
@@ -715,7 +765,7 @@ public function rightJoin($table, $conditions = [], $types = [])
* The arguments of this method are identical to the `leftJoin()` shorthand, please refer
* to that methods description for further details.
*
- * @param string|string[]|\Cake\Database\ExpressionInterface[] $table The table to join with
+ * @param string|array $table The table to join with
* @param string|array|\Cake\Database\ExpressionInterface $conditions The conditions
* to use for joining.
* @param array $types a list of types associated to the conditions used for converting
@@ -724,19 +774,22 @@ public function rightJoin($table, $conditions = [], $types = [])
*/
public function innerJoin($table, $conditions = [], $types = [])
{
- return $this->join($this->_makeJoin($table, $conditions, QueryInterface::JOIN_TYPE_INNER), $types);
+ $this->join($this->_makeJoin($table, $conditions, static::JOIN_TYPE_INNER), $types);
+
+ return $this;
}
/**
* Returns an array that can be passed to the join method describing a single join clause
*
- * @param string|string[]|\Cake\Database\ExpressionInterface[] $table The table to join with
+ * @param string|string[] $table The table to join with
* @param string|array|\Cake\Database\ExpressionInterface $conditions The conditions
* to use for joining.
* @param string $type the join type to use
* @return array
+ * @psalm-suppress InvalidReturnType
*/
- protected function _makeJoin($table, $conditions, $type)
+ protected function _makeJoin($table, $conditions, $type): array
{
$alias = $table;
@@ -745,6 +798,7 @@ protected function _makeJoin($table, $conditions, $type)
$table = current($table);
}
+ /** @psalm-suppress InvalidReturnStatement */
return [
$alias => [
'table' => $table,
@@ -867,14 +921,14 @@ protected function _makeJoin($table, $conditions, $type)
* If you use string conditions make sure that your values are correctly quoted.
* The safest thing you can do is to never use string conditions.
*
- * @param string|array|\Cake\Database\ExpressionInterface|callable|null $conditions The conditions to filter on.
+ * @param string|array|\Cake\Database\ExpressionInterface|\Closure|null $conditions The conditions to filter on.
* @param array $types associative array of type names used to bind values to query
* @param bool $overwrite whether to reset conditions with passed list or not
- * @see \Cake\Database\Type
+ * @see \Cake\Database\TypeFactory
* @see \Cake\Database\Expression\QueryExpression
* @return $this
*/
- public function where($conditions = null, $types = [], $overwrite = false)
+ public function where($conditions = null, array $types = [], bool $overwrite = false)
{
if ($overwrite) {
$this->_parts['where'] = $this->newExpr();
@@ -887,7 +941,8 @@ public function where($conditions = null, $types = [], $overwrite = false)
/**
* Convenience method that adds a NOT NULL condition to the query
*
- * @param array|string|\Cake\Database\ExpressionInterface $fields A single field or expressions or a list of them that should be not null
+ * @param array|string|\Cake\Database\ExpressionInterface $fields A single field or expressions or a list of them
+ * that should be not null.
* @return $this
*/
public function whereNotNull($fields)
@@ -908,7 +963,8 @@ public function whereNotNull($fields)
/**
* Convenience method that adds a IS NULL condition to the query
*
- * @param array|string|\Cake\Database\ExpressionInterface $fields A single field or expressions or a list of them that should be null
+ * @param array|string|\Cake\Database\ExpressionInterface $fields A single field or expressions or a list of them
+ * that should be null.
* @return $this
*/
public function whereNull($fields)
@@ -935,6 +991,7 @@ public function whereNull($fields)
* Be careful about using it without proper sanity checks.
*
* Options:
+ *
* - `types` - Associative array of type names used to bind values to query
* - `allowEmpty` - Allow empty array.
*
@@ -943,7 +1000,7 @@ public function whereNull($fields)
* @param array $options Options
* @return $this
*/
- public function whereInList($field, array $values, array $options = [])
+ public function whereInList(string $field, array $values, array $options = [])
{
$options += [
'types' => [],
@@ -970,7 +1027,7 @@ public function whereInList($field, array $values, array $options = [])
* @param array $options Options
* @return $this
*/
- public function whereNotInList($field, array $values, array $options = [])
+ public function whereNotInList(string $field, array $values, array $options = [])
{
$options += [
'types' => [],
@@ -1034,88 +1091,19 @@ public function whereNotInList($field, array $values, array $options = [])
*
* `WHERE (title = 'Foo') AND (author_id = 1 OR author_id = 2)`
*
- * @param string|array|\Cake\Database\ExpressionInterface|callable $conditions The conditions to add with AND.
+ * @param string|array|\Cake\Database\ExpressionInterface|\Closure $conditions The conditions to add with AND.
* @param array $types associative array of type names used to bind values to query
* @see \Cake\Database\Query::where()
- * @see \Cake\Database\Type
+ * @see \Cake\Database\TypeFactory
* @return $this
*/
- public function andWhere($conditions, $types = [])
+ public function andWhere($conditions, array $types = [])
{
$this->_conjugate('where', $conditions, 'AND', $types);
return $this;
}
- /**
- * Connects any previously defined set of conditions to the provided list
- * using the OR operator. This function accepts the conditions list in the same
- * format as the method `where` does, hence you can use arrays, expression objects
- * callback functions or strings.
- *
- * It is important to notice that when calling this function, any previous set
- * of conditions defined for this query will be treated as a single argument for
- * the OR operator. This function will not only operate the most recently defined
- * condition, but all the conditions as a whole.
- *
- * When using an array for defining conditions, creating constraints form each
- * array entry will use the same logic as with the `where()` function. This means
- * that each array entry will be joined to the other using the OR operator, unless
- * you nest the conditions in the array using other operator.
- *
- * ### Examples:
- *
- * ```
- * $query->where(['title' => 'Hello World')->orWhere(['title' => 'Foo']);
- * ```
- *
- * Will produce:
- *
- * `WHERE title = 'Hello World' OR title = 'Foo'`
- *
- * ```
- * $query
- * ->where(['OR' => ['published' => false, 'published is NULL']])
- * ->orWhere(['author_id' => 1, 'comments_count >' => 10])
- * ```
- *
- * Produces:
- *
- * `WHERE (published = 0 OR published IS NULL) OR (author_id = 1 AND comments_count > 10)`
- *
- * ```
- * $query
- * ->where(['title' => 'Foo'])
- * ->orWhere(function ($exp, $query) {
- * return $exp
- * ->or(['author_id' => 1])
- * ->add(['author_id' => 2]);
- * });
- * ```
- *
- * Generates the following conditions:
- *
- * `WHERE (title = 'Foo') OR (author_id = 1 OR author_id = 2)`
- *
- * @param string|array|\Cake\Database\ExpressionInterface|callable $conditions The conditions to add with OR.
- * @param array $types associative array of type names used to bind values to query
- * @see \Cake\Database\Query::where()
- * @see \Cake\Database\Type
- * @return $this
- * @deprecated 3.5.0 This method creates hard to predict SQL based on the current query state.
- * Use `Query::where()` instead as it has more predicatable and easier to understand behavior.
- */
- public function orWhere($conditions, $types = [])
- {
- deprecationWarning(
- 'Query::orWhere() is deprecated as it creates hard to predict SQL based on the ' .
- 'current query state. Use `Query::where()` instead.'
- );
- $this->_conjugate('where', $conditions, 'OR', $types);
-
- return $this;
- }
-
/**
* Adds a single or multiple fields to be used in the ORDER clause for this query.
* Fields can be passed as an array of strings, array of expression
@@ -1140,9 +1128,7 @@ public function orWhere($conditions, $types = [])
* `ORDER BY title DESC, author_id ASC`
*
* ```
- * $query
- * ->order(['title' => $query->newExpr('DESC NULLS FIRST')])
- * ->order('author_id');
+ * $query->order(['title' => 'DESC NULLS FIRST'])->order('author_id');
* ```
*
* Will generate:
@@ -1173,7 +1159,7 @@ public function orWhere($conditions, $types = [])
* If you need to set complex expressions as order conditions, you
* should use `orderAsc()` or `orderDesc()`.
*
- * @param array|\Cake\Database\ExpressionInterface|callable|string $fields fields to be added to the list
+ * @param array|\Cake\Database\ExpressionInterface|\Closure|string $fields fields to be added to the list
* @param bool $overwrite whether to reset order with field list or not
* @return $this
*/
@@ -1204,7 +1190,7 @@ public function order($fields, $overwrite = false)
* Order fields are not suitable for use with user supplied data as they are
* not sanitized by the query builder.
*
- * @param string|\Cake\Database\Expression\QueryExpression|callable $field The field to order on.
+ * @param string|\Cake\Database\Expression\QueryExpression $field The field to order on.
* @param bool $overwrite Whether or not to reset the order clauses.
* @return $this
*/
@@ -1220,11 +1206,6 @@ public function orderAsc($field, $overwrite = false)
if (!$this->_parts['order']) {
$this->_parts['order'] = new OrderByExpression();
}
-
- if ($this->_parts['order']->isCallable($field)) {
- $field = $field($this->newExpr(), $this);
- }
-
$this->_parts['order']->add(new OrderClauseExpression($field, 'ASC'));
return $this;
@@ -1239,7 +1220,7 @@ public function orderAsc($field, $overwrite = false)
* Order fields are not suitable for use with user supplied data as they are
* not sanitized by the query builder.
*
- * @param string|\Cake\Database\Expression\QueryExpression|callable $field The field to order on.
+ * @param string|\Cake\Database\Expression\QueryExpression $field The field to order on.
* @param bool $overwrite Whether or not to reset the order clauses.
* @return $this
*/
@@ -1255,11 +1236,6 @@ public function orderDesc($field, $overwrite = false)
if (!$this->_parts['order']) {
$this->_parts['order'] = new OrderByExpression();
}
-
- if ($this->_parts['order']->isCallable($field)) {
- $field = $field($this->newExpr(), $this);
- }
-
$this->_parts['order']->add(new OrderClauseExpression($field, 'DESC'));
return $this;
@@ -1315,7 +1291,7 @@ public function group($fields, $overwrite = false)
* Having fields are not suitable for use with user supplied data as they are
* not sanitized by the query builder.
*
- * @param string|array|\Cake\Database\ExpressionInterface|callable|null $conditions The having conditions.
+ * @param string|array|\Cake\Database\ExpressionInterface|\Closure|null $conditions The having conditions.
* @param array $types associative array of type names used to bind values to query
* @param bool $overwrite whether to reset conditions with passed list or not
* @see \Cake\Database\Query::where()
@@ -1340,7 +1316,7 @@ public function having($conditions = null, $types = [], $overwrite = false)
* Having fields are not suitable for use with user supplied data as they are
* not sanitized by the query builder.
*
- * @param string|array|\Cake\Database\ExpressionInterface|callable $conditions The AND conditions for HAVING.
+ * @param string|array|\Cake\Database\ExpressionInterface|\Closure $conditions The AND conditions for HAVING.
* @param array $types associative array of type names used to bind values to query
* @see \Cake\Database\Query::andWhere()
* @return $this
@@ -1352,30 +1328,6 @@ public function andHaving($conditions, $types = [])
return $this;
}
- /**
- * Connects any previously defined set of conditions to the provided list
- * using the OR operator in the HAVING clause. This method operates in exactly
- * the same way as the method `orWhere()` does. Please refer to its
- * documentation for an insight on how to using each parameter.
- *
- * Having fields are not suitable for use with user supplied data as they are
- * not sanitized by the query builder.
- *
- * @param string|array|\Cake\Database\ExpressionInterface|callable $conditions The OR conditions for HAVING.
- * @param array $types associative array of type names used to bind values to query.
- * @see \Cake\Database\Query::orWhere()
- * @return $this
- * @deprecated 3.5.0 This method creates hard to predict SQL based on the current query state.
- * Use `Query::having()` instead as it has more predicatable and easier to understand behavior.
- */
- public function orHaving($conditions, $types = [])
- {
- deprecationWarning('Query::orHaving() is deprecated. Use Query::having() instead.');
- $this->_conjugate('having', $conditions, 'OR', $types);
-
- return $this;
- }
-
/**
* Set the page of results you want.
*
@@ -1391,7 +1343,7 @@ public function orHaving($conditions, $types = [])
* @return $this
* @throws \InvalidArgumentException If page number < 1.
*/
- public function page($num, $limit = null)
+ public function page(int $num, ?int $limit = null)
{
if ($num < 1) {
throw new InvalidArgumentException('Pages must start at 1.');
@@ -1576,7 +1528,7 @@ public function insert(array $columns, array $types = [])
* @param string $table The table name to insert into.
* @return $this
*/
- public function into($table)
+ public function into(string $table)
{
$this->_dirty();
$this->_type = 'insert';
@@ -1601,7 +1553,7 @@ public function into($table)
* @param string $identifier The identifier for an expression
* @return \Cake\Database\ExpressionInterface
*/
- public function identifier($identifier)
+ public function identifier(string $identifier): ExpressionInterface
{
return new IdentifierExpression($identifier);
}
@@ -1613,7 +1565,7 @@ public function identifier($identifier)
* or by providing an array of value sets. Additionally $data can be a Query
* instance to insert data from another SELECT statement.
*
- * @param array|\Cake\Database\Query $data The data to insert.
+ * @param array|\Cake\Database\Query|\Cake\Database\Expression\ValuesExpression $data The data to insert.
* @return $this
* @throws \Cake\Database\Exception if you try to set values before declaring columns.
* Or if you try to set values on non-insert queries.
@@ -1691,9 +1643,9 @@ public function update($table)
* });
* ```
*
- * @param string|array|callable|\Cake\Database\Expression\QueryExpression $key The column name or array of keys
+ * @param string|array|\Closure|\Cake\Database\Expression\QueryExpression $key The column name or array of keys
* + values to set. This can also be a QueryExpression containing a SQL fragment.
- * It can also be a callable, that is required to return an expression object.
+ * It can also be a Closure, that is required to return an expression object.
* @param mixed $value The value to update $key to. Can be null if $key is an
* array or QueryExpression. When $key is an array, this parameter will be
* used as $types instead.
@@ -1706,7 +1658,7 @@ public function set($key, $value = null, $types = [])
$this->_parts['set'] = $this->newExpr()->setConjunction(',');
}
- if ($this->_parts['set']->isCallable($key)) {
+ if ($key instanceof Closure) {
$exp = $this->newExpr()->setConjunction(',');
$this->_parts['set']->add($key($exp));
@@ -1720,8 +1672,8 @@ public function set($key, $value = null, $types = [])
return $this;
}
- if (is_string($types) && is_string($key)) {
- $types = [$key => $types];
+ if (!is_string($types)) {
+ $types = null;
}
$this->_parts['set']->eq($key, $value, $types);
@@ -1737,7 +1689,7 @@ public function set($key, $value = null, $types = [])
* @param string|null $table The table to use when deleting.
* @return $this
*/
- public function delete($table = null)
+ public function delete(?string $table = null)
{
$this->_dirty();
$this->_type = 'delete';
@@ -1762,7 +1714,7 @@ public function delete($table = null)
*
* Epliog content is raw SQL and not suitable for use with user supplied data.
*
- * @param string|\Cake\Database\ExpressionInterface|null $expression The expression to be appended
+ * @param string|\Cake\Database\Expression\QueryExpression|null $expression The expression to be appended
* @return $this
*/
public function epilog($expression = null)
@@ -1778,7 +1730,7 @@ public function epilog($expression = null)
*
* @return string
*/
- public function type()
+ public function type(): string
{
return $this->_type;
}
@@ -1797,10 +1749,10 @@ public function type()
* $expression = $query->newExpr('Table.column = Table2.column'); // Return a raw SQL expression
* ```
*
- * @param mixed $rawExpression A string, array or anything you want wrapped in an expression object
+ * @param string|array|\Cake\Database\ExpressionInterface|null $rawExpression A string, array or anything you want wrapped in an expression object
* @return \Cake\Database\Expression\QueryExpression
*/
- public function newExpr($rawExpression = null)
+ public function newExpr($rawExpression = null): QueryExpression
{
$expression = new QueryExpression([], $this->getTypeMap());
@@ -1824,7 +1776,7 @@ public function newExpr($rawExpression = null)
*
* @return \Cake\Database\FunctionsBuilder
*/
- public function func()
+ public function func(): FunctionsBuilder
{
if ($this->_functionsBuilder === null) {
$this->_functionsBuilder = new FunctionsBuilder();
@@ -1839,7 +1791,8 @@ public function func()
* iterated without having to call execute() manually, thus making it look like
* a result set instead of the query itself.
*
- * @return \Cake\Database\StatementInterface|null
+ * @return \Cake\Database\StatementInterface
+ * @psalm-suppress ImplementedReturnTypeMismatch
*/
public function getIterator()
{
@@ -1882,7 +1835,7 @@ public function getIterator()
* @return mixed
* @throws \InvalidArgumentException When the named clause does not exist.
*/
- public function clause($name)
+ public function clause(string $name)
{
if (!array_key_exists($name, $this->_parts)) {
$clauses = implode(', ', array_keys($this->_parts));
@@ -1920,7 +1873,7 @@ public function clause($name)
* @param bool $overwrite Whether or not this should append or replace all existing decorators.
* @return $this
*/
- public function decorateResults($callback, $overwrite = false)
+ public function decorateResults(?callable $callback, bool $overwrite = false)
{
if ($overwrite) {
$this->_resultDecorators = [];
@@ -1943,29 +1896,49 @@ public function decorateResults($callback, $overwrite = false)
*
* @param callable $callback the function to be executed for each ExpressionInterface
* found inside this query.
- * @return $this|null
+ * @return $this
*/
public function traverseExpressions(callable $callback)
{
- $visitor = function ($expression) use (&$visitor, $callback) {
- if (is_array($expression)) {
- foreach ($expression as $e) {
- $visitor($e);
- }
+ if (!$callback instanceof Closure) {
+ $callback = Closure::fromCallable($callback);
+ }
- return null;
- }
+ foreach ($this->_parts as $part) {
+ $this->_expressionsVisitor($part, $callback);
+ }
- if ($expression instanceof ExpressionInterface) {
- $expression->traverse($visitor);
+ return $this;
+ }
- if (!($expression instanceof self)) {
- $callback($expression);
- }
+ /**
+ * Query parts traversal method used by traverseExpressions()
+ *
+ * @param \Cake\Database\ExpressionInterface|\Cake\Database\ExpressionInterface[] $expression Query expression or
+ * array of expressions.
+ * @param \Closure $callback The callback to be executed for each ExpressionInterface
+ * found inside this query.
+ * @return void
+ */
+ protected function _expressionsVisitor($expression, Closure $callback): void
+ {
+ if (is_array($expression)) {
+ foreach ($expression as $e) {
+ $this->_expressionsVisitor($e, $callback);
}
- };
- return $this->traverse($visitor);
+ return;
+ }
+
+ if ($expression instanceof ExpressionInterface) {
+ $expression->traverse(function ($exp) use ($callback) {
+ $this->_expressionsVisitor($exp, $callback);
+ });
+
+ if (!$expression instanceof self) {
+ $callback($expression);
+ }
+ }
}
/**
@@ -1978,11 +1951,11 @@ public function traverseExpressions(callable $callback)
* @param string|int $param placeholder to be replaced with quoted version
* of $value
* @param mixed $value The value to be bound
- * @param string|int $type the mapped type name, used for casting when sending
+ * @param string|int|null $type the mapped type name, used for casting when sending
* to database
* @return $this
*/
- public function bind($param, $value, $type = 'string')
+ public function bind($param, $value, $type = null)
{
$this->getValueBinder()->bind($param, $value, $type);
@@ -1998,7 +1971,7 @@ public function bind($param, $value, $type = 'string')
*
* @return \Cake\Database\ValueBinder
*/
- public function getValueBinder()
+ public function getValueBinder(): ValueBinder
{
if ($this->_valueBinder === null) {
$this->_valueBinder = new ValueBinder();
@@ -2014,44 +1987,16 @@ public function getValueBinder()
* associate values to those placeholders so that they can be passed correctly
* to the statement object.
*
- * @param \Cake\Database\ValueBinder|false $binder The binder or false to disable binding.
+ * @param \Cake\Database\ValueBinder|null $binder The binder or null to disable binding.
* @return $this
*/
- public function setValueBinder($binder)
+ public function setValueBinder(?ValueBinder $binder)
{
$this->_valueBinder = $binder;
return $this;
}
- /**
- * Returns the currently used ValueBinder instance. If a value is passed,
- * it will be set as the new instance to be used.
- *
- * A ValueBinder is responsible for generating query placeholders and temporarily
- * associate values to those placeholders so that they can be passed correctly
- * to the statement object.
- *
- * @deprecated 3.5.0 Use setValueBinder()/getValueBinder() instead.
- * @param \Cake\Database\ValueBinder|false|null $binder new instance to be set. If no value is passed the
- * default one will be returned
- * @return $this|\Cake\Database\ValueBinder
- */
- public function valueBinder($binder = null)
- {
- deprecationWarning('Query::valueBinder() is deprecated. Use Query::getValueBinder()/setValueBinder() instead.');
- if ($binder === null) {
- if ($this->_valueBinder === null) {
- $this->_valueBinder = new ValueBinder();
- }
-
- return $this->_valueBinder;
- }
- $this->_valueBinder = $binder;
-
- return $this;
- }
-
/**
* Enables/Disables buffered results.
*
@@ -2065,7 +2010,7 @@ public function valueBinder($binder = null)
* @param bool $enable Whether or not to enable buffering
* @return $this
*/
- public function enableBufferedResults($enable = true)
+ public function enableBufferedResults(bool $enable = true)
{
$this->_dirty();
$this->_useBufferedResults = (bool)$enable;
@@ -2101,41 +2046,11 @@ public function disableBufferedResults()
*
* @return bool
*/
- public function isBufferedResultsEnabled()
+ public function isBufferedResultsEnabled(): bool
{
return $this->_useBufferedResults;
}
- /**
- * Enable/Disable buffered results.
- *
- * When enabled the results returned by this Query will be
- * buffered. This enables you to iterate a result set multiple times, or
- * both cache and iterate it.
- *
- * When disabled it will consume less memory as fetched results are not
- * remembered for future iterations.
- *
- * If called with no arguments, it will return whether or not buffering is
- * enabled.
- *
- * @deprecated 3.4.0 Use enableBufferedResults()/isBufferedResultsEnabled() instead.
- * @param bool|null $enable Whether or not to enable buffering
- * @return bool|$this
- */
- public function bufferResults($enable = null)
- {
- deprecationWarning(
- 'Query::bufferResults() is deprecated. ' .
- 'Use Query::enableBufferedResults()/isBufferedResultsEnabled() instead.'
- );
- if ($enable !== null) {
- return $this->enableBufferedResults($enable);
- }
-
- return $this->isBufferedResultsEnabled();
- }
-
/**
* Sets the TypeMap class where the types for each of the fields in the
* select clause are stored.
@@ -2157,7 +2072,7 @@ public function setSelectTypeMap(TypeMap $typeMap)
*
* @return \Cake\Database\TypeMap
*/
- public function getSelectTypeMap()
+ public function getSelectTypeMap(): TypeMap
{
if ($this->_selectTypeMap === null) {
$this->_selectTypeMap = new TypeMap();
@@ -2190,37 +2105,14 @@ public function enableResultsCasting()
return $this;
}
- /**
- * Sets the TypeMap class where the types for each of the fields in the
- * select clause are stored.
- *
- * When called with no arguments, the current TypeMap object is returned.
- *
- * @deprecated 3.4.0 Use setSelectTypeMap()/getSelectTypeMap() instead.
- * @param \Cake\Database\TypeMap|null $typeMap The map object to use
- * @return $this|\Cake\Database\TypeMap
- */
- public function selectTypeMap(TypeMap $typeMap = null)
- {
- deprecationWarning(
- 'Query::selectTypeMap() is deprecated. ' .
- 'Use Query::setSelectTypeMap()/getSelectTypeMap() instead.'
- );
- if ($typeMap !== null) {
- return $this->setSelectTypeMap($typeMap);
- }
-
- return $this->getSelectTypeMap();
- }
-
/**
* Auxiliary function used to wrap the original statement from the driver with
* any registered callbacks.
*
* @param \Cake\Database\StatementInterface $statement to be decorated
- * @return \Cake\Database\Statement\CallbackStatement
+ * @return \Cake\Database\Statement\CallbackStatement|\Cake\Database\StatementInterface
*/
- protected function _decorateStatement($statement)
+ protected function _decorateStatement(StatementInterface $statement)
{
$typeMap = $this->getSelectTypeMap();
$driver = $this->getConnection()->getDriver();
@@ -2240,12 +2132,13 @@ protected function _decorateStatement($statement)
* Helper function used to build conditions by composing QueryExpression objects.
*
* @param string $part Name of the query part to append the new part to
- * @param string|array|\Cake\Database\ExpressionInterface|callable|null $append Expression or builder function to append.
+ * @param string|array|\Cake\Database\ExpressionInterface|\Closure|null $append Expression or builder function to append.
+ * to append.
* @param string $conjunction type of conjunction to be used to operate part
* @param array $types associative array of type names used to bind values to query
* @return void
*/
- protected function _conjugate($part, $append, $conjunction, $types)
+ protected function _conjugate(string $part, $append, $conjunction, array $types): void
{
$expression = $this->_parts[$part] ?: $this->newExpr();
if (empty($append)) {
@@ -2254,7 +2147,7 @@ protected function _conjugate($part, $append, $conjunction, $types)
return;
}
- if ($expression->isCallable($append)) {
+ if ($append instanceof Closure) {
$append = $append($this->newExpr(), $this);
}
@@ -2276,7 +2169,7 @@ protected function _conjugate($part, $append, $conjunction, $types)
*
* @return void
*/
- protected function _dirty()
+ protected function _dirty(): void
{
$this->_dirty = true;
@@ -2309,6 +2202,7 @@ public function __clone()
if (is_array($part)) {
foreach ($part as $i => $piece) {
if ($piece instanceof ExpressionInterface) {
+ /** @psalm-suppress PossiblyUndefinedMethod */
$this->_parts[$name][$i] = clone $piece;
}
}
@@ -2324,7 +2218,7 @@ public function __clone()
*
* @return string
*/
- public function __toString()
+ public function __toString(): string
{
return $this->sql();
}
@@ -2335,7 +2229,7 @@ public function __toString()
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
try {
set_error_handler(function ($errno, $errstr) {
diff --git a/app/vendor/cakephp/cakephp/src/Database/QueryCompiler.php b/app/vendor/cakephp/cakephp/src/Database/QueryCompiler.php
index d28ecefd7..b0d08d134 100644
--- a/app/vendor/cakephp/cakephp/src/Database/QueryCompiler.php
+++ b/app/vendor/cakephp/cakephp/src/Database/QueryCompiler.php
@@ -1,4 +1,6 @@
type();
- $query->traverse(
+ $query->traverseParts(
$this->_sqlCompiler($sql, $query, $generator),
- $this->{'_' . $type . 'Parts'}
+ $this->{"_{$type}Parts"}
);
// Propagate bound parameters from sub-queries if the
@@ -121,25 +132,28 @@ public function compile(Query $query, ValueBinder $generator)
* @param \Cake\Database\ValueBinder $generator The placeholder and value binder object
* @return \Closure
*/
- protected function _sqlCompiler(&$sql, $query, $generator)
+ protected function _sqlCompiler(string &$sql, Query $query, ValueBinder $generator): Closure
{
- return function ($parts, $name) use (&$sql, $query, $generator) {
+ return function ($part, $partName) use (&$sql, $query, $generator) {
if (
- !isset($parts) ||
- ((is_array($parts) || $parts instanceof \Countable) && !count($parts))
+ $part === null ||
+ (is_array($part) && empty($part)) ||
+ ($part instanceof Countable && count($part) === 0)
) {
return;
}
- if ($parts instanceof ExpressionInterface) {
- $parts = [$parts->sql($generator)];
+
+ if ($part instanceof ExpressionInterface) {
+ $part = [$part->sql($generator)];
}
- if (isset($this->_templates[$name])) {
- $parts = $this->_stringifyExpressions((array)$parts, $generator);
+ if (isset($this->_templates[$partName])) {
+ $part = $this->_stringifyExpressions((array)$part, $generator);
+ $sql .= sprintf($this->_templates[$partName], implode(', ', $part));
- return $sql .= sprintf($this->_templates[$name], implode(', ', $parts));
+ return;
}
- return $sql .= $this->{'_build' . ucfirst($name) . 'Part'}($parts, $query, $generator);
+ $sql .= $this->{'_build' . $partName . 'Part'}($part, $query, $generator);
};
}
@@ -154,9 +168,8 @@ protected function _sqlCompiler(&$sql, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string
*/
- protected function _buildSelectPart($parts, $query, $generator)
+ protected function _buildSelectPart(array $parts, Query $query, ValueBinder $generator): string
{
- $driver = $query->getConnection()->getDriver();
$select = 'SELECT%s %s%s';
if ($this->_orderedUnion && $query->clause('union')) {
$select = '(SELECT%s %s%s';
@@ -164,11 +177,18 @@ protected function _buildSelectPart($parts, $query, $generator)
$distinct = $query->clause('distinct');
$modifiers = $this->_buildModifierPart($query->clause('modifier'), $query, $generator);
+ $driver = $query->getConnection()->getDriver();
+ $quoteIdentifiers = $driver->isAutoQuotingEnabled() || $this->_quotedSelectAliases;
$normalized = [];
$parts = $this->_stringifyExpressions($parts, $generator);
foreach ($parts as $k => $p) {
if (!is_numeric($k)) {
- $p = $p . ' AS ' . $driver->quoteIdentifier($k);
+ $p = $p . ' AS ';
+ if ($quoteIdentifiers) {
+ $p .= $driver->quoteIdentifier($k);
+ } else {
+ $p .= $k;
+ }
}
$normalized[] = $p;
}
@@ -195,7 +215,7 @@ protected function _buildSelectPart($parts, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string
*/
- protected function _buildFromPart($parts, $query, $generator)
+ protected function _buildFromPart(array $parts, Query $query, ValueBinder $generator): string
{
$select = ' FROM %s';
$normalized = [];
@@ -221,7 +241,7 @@ protected function _buildFromPart($parts, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string
*/
- protected function _buildJoinPart($parts, $query, $generator)
+ protected function _buildJoinPart(array $parts, Query $query, ValueBinder $generator): string
{
$joins = '';
foreach ($parts as $join) {
@@ -258,7 +278,7 @@ protected function _buildJoinPart($parts, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string
*/
- protected function _buildSetPart($parts, $query, $generator)
+ protected function _buildSetPart(array $parts, Query $query, ValueBinder $generator): string
{
$set = [];
foreach ($parts as $part) {
@@ -284,7 +304,7 @@ protected function _buildSetPart($parts, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string
*/
- protected function _buildUnionPart($parts, $query, $generator)
+ protected function _buildUnionPart(array $parts, Query $query, ValueBinder $generator): string
{
$parts = array_map(function ($p) use ($generator) {
$p['query'] = $p['query']->sql($generator);
@@ -312,7 +332,7 @@ protected function _buildUnionPart($parts, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string SQL fragment.
*/
- protected function _buildInsertPart($parts, $query, $generator)
+ protected function _buildInsertPart(array $parts, Query $query, ValueBinder $generator): string
{
$table = $parts[0];
$columns = $this->_stringifyExpressions($parts[1], $generator);
@@ -329,7 +349,7 @@ protected function _buildInsertPart($parts, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string SQL fragment.
*/
- protected function _buildValuesPart($parts, $query, $generator)
+ protected function _buildValuesPart(array $parts, Query $query, ValueBinder $generator): string
{
return implode('', $this->_stringifyExpressions($parts, $generator));
}
@@ -342,7 +362,7 @@ protected function _buildValuesPart($parts, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string SQL fragment.
*/
- protected function _buildUpdatePart($parts, $query, $generator)
+ protected function _buildUpdatePart(array $parts, Query $query, ValueBinder $generator): string
{
$table = $this->_stringifyExpressions($parts, $generator);
$modifiers = $this->_buildModifierPart($query->clause('modifier'), $query, $generator);
@@ -358,7 +378,7 @@ protected function _buildUpdatePart($parts, $query, $generator)
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string SQL fragment.
*/
- protected function _buildModifierPart($parts, $query, $generator)
+ protected function _buildModifierPart(array $parts, Query $query, ValueBinder $generator): string
{
if ($parts === []) {
return '';
@@ -376,7 +396,7 @@ protected function _buildModifierPart($parts, $query, $generator)
* @param bool $wrap Whether to wrap each expression object with parenthesis
* @return array
*/
- protected function _stringifyExpressions($expressions, $generator, $wrap = true)
+ protected function _stringifyExpressions(array $expressions, ValueBinder $generator, bool $wrap = true): array
{
$result = [];
foreach ($expressions as $k => $expression) {
diff --git a/app/vendor/cakephp/cakephp/src/Database/README.md b/app/vendor/cakephp/cakephp/src/Database/README.md
index e0add0b26..e4c513ba8 100644
--- a/app/vendor/cakephp/cakephp/src/Database/README.md
+++ b/app/vendor/cakephp/cakephp/src/Database/README.md
@@ -55,7 +55,7 @@ directly in the options array:
use Cake\Database\Connection;
$connection = new Connection([
- 'driver' => 'Cake\Database\Driver\Sqlite',
+ 'driver' => Cake\Database\Driver\Sqlite::class,
'database' => '/path/to/file.db'
]);
```
diff --git a/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php b/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
index 37eb364d5..4bc549f44 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
@@ -1,4 +1,6 @@
getMessage();
@@ -95,7 +97,7 @@ public function shouldRetry(Exception $exception, $retryCount)
*
* @return bool Whether or not the connection was re-established
*/
- protected function reconnect()
+ protected function reconnect(): bool
{
if ($this->connection->inTransaction()) {
// It is not safe to blindly reconnect in the middle of a transaction
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/BaseSchema.php b/app/vendor/cakephp/cakephp/src/Database/Schema/BaseSchema.php
index 24098011b..bb1939118 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/BaseSchema.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/BaseSchema.php
@@ -1,4 +1,6 @@
connect();
$this->_driver = $driver;
@@ -48,10 +51,10 @@ public function __construct(Driver $driver)
/**
* Generate an ON clause for a foreign key.
*
- * @param string|null $on The on clause
+ * @param string $on The on clause
* @return string
*/
- protected function _foreignOnClause($on)
+ protected function _foreignOnClause(string $on): string
{
if ($on === TableSchema::ACTION_SET_NULL) {
return 'SET NULL';
@@ -68,15 +71,17 @@ protected function _foreignOnClause($on)
if ($on === TableSchema::ACTION_NO_ACTION) {
return 'NO ACTION';
}
+
+ throw new InvalidArgumentException('Invalid value for "on": ' . $on);
}
/**
* Convert string on clauses to the abstract ones.
*
* @param string $clause The on clause to convert.
- * @return string|null
+ * @return string
*/
- protected function _convertOnClause($clause)
+ protected function _convertOnClause(string $clause): string
{
if ($clause === 'CASCADE' || $clause === 'RESTRICT') {
return strtolower($clause);
@@ -95,7 +100,7 @@ protected function _convertOnClause($clause)
* @param string|array $references The referenced columns of a foreign key constraint statement
* @return string
*/
- protected function _convertConstraintColumns($references)
+ protected function _convertConstraintColumns($references): string
{
if (is_string($references)) {
return $this->_driver->quoteIdentifier($references);
@@ -113,7 +118,7 @@ protected function _convertConstraintColumns($references)
* @param \Cake\Database\Schema\TableSchema $schema Schema instance
* @return array SQL statements to drop a table.
*/
- public function dropTableSql(TableSchema $schema)
+ public function dropTableSql(TableSchema $schema): array
{
$sql = sprintf(
'DROP TABLE %s',
@@ -130,7 +135,7 @@ public function dropTableSql(TableSchema $schema)
* getting tables from.
* @return array An array of (sql, params) to execute.
*/
- abstract public function listTablesSql($config);
+ abstract public function listTablesSql(array $config): array;
/**
* Generate the SQL to describe a table.
@@ -139,7 +144,7 @@ abstract public function listTablesSql($config);
* @param array $config The connection configuration.
* @return array An array of (sql, params) to execute.
*/
- abstract public function describeColumnSql($tableName, $config);
+ abstract public function describeColumnSql(string $tableName, array $config): array;
/**
* Generate the SQL to describe the indexes in a table.
@@ -148,7 +153,7 @@ abstract public function describeColumnSql($tableName, $config);
* @param array $config The connection configuration.
* @return array An array of (sql, params) to execute.
*/
- abstract public function describeIndexSql($tableName, $config);
+ abstract public function describeIndexSql(string $tableName, array $config): array;
/**
* Generate the SQL to describe the foreign keys in a table.
@@ -157,7 +162,7 @@ abstract public function describeIndexSql($tableName, $config);
* @param array $config The connection configuration.
* @return array An array of (sql, params) to execute.
*/
- abstract public function describeForeignKeySql($tableName, $config);
+ abstract public function describeForeignKeySql(string $tableName, array $config): array;
/**
* Generate the SQL to describe table options
@@ -166,7 +171,7 @@ abstract public function describeForeignKeySql($tableName, $config);
* @param array $config The connection configuration.
* @return array SQL statements to get options for a table.
*/
- public function describeOptionsSql($tableName, $config)
+ public function describeOptionsSql(string $tableName, array $config): array
{
return ['', ''];
}
@@ -178,7 +183,7 @@ public function describeOptionsSql($tableName, $config)
* @param array $row The row data from `describeColumnSql`.
* @return void
*/
- abstract public function convertColumnDescription(TableSchema $schema, $row);
+ abstract public function convertColumnDescription(TableSchema $schema, array $row): void;
/**
* Convert an index description results into abstract schema indexes or constraints.
@@ -188,7 +193,7 @@ abstract public function convertColumnDescription(TableSchema $schema, $row);
* @param array $row The row data from `describeIndexSql`.
* @return void
*/
- abstract public function convertIndexDescription(TableSchema $schema, $row);
+ abstract public function convertIndexDescription(TableSchema $schema, array $row): void;
/**
* Convert a foreign key description into constraints on the Table object.
@@ -198,7 +203,7 @@ abstract public function convertIndexDescription(TableSchema $schema, $row);
* @param array $row The row data from `describeForeignKeySql`.
* @return void
*/
- abstract public function convertForeignKeyDescription(TableSchema $schema, $row);
+ abstract public function convertForeignKeyDescription(TableSchema $schema, array $row): void;
/**
* Convert options data into table options.
@@ -207,7 +212,7 @@ abstract public function convertForeignKeyDescription(TableSchema $schema, $row)
* @param array $row The row of data.
* @return void
*/
- public function convertOptionsDescription(TableSchema $schema, $row)
+ public function convertOptionsDescription(TableSchema $schema, array $row): void
{
}
@@ -220,7 +225,12 @@ public function convertOptionsDescription(TableSchema $schema, $row)
* @param string[] $indexes The indexes for the table.
* @return string[] SQL statements to create a table.
*/
- abstract public function createTableSql(TableSchema $schema, $columns, $constraints, $indexes);
+ abstract public function createTableSql(
+ TableSchema $schema,
+ array $columns,
+ array $constraints,
+ array $indexes
+ ): array;
/**
* Generate the SQL fragment for a single column in a table.
@@ -229,7 +239,7 @@ abstract public function createTableSql(TableSchema $schema, $columns, $constrai
* @param string $name The name of the column.
* @return string SQL fragment.
*/
- abstract public function columnSql(TableSchema $schema, $name);
+ abstract public function columnSql(TableSchema $schema, string $name): string;
/**
* Generate the SQL queries needed to add foreign key constraints to the table
@@ -237,7 +247,7 @@ abstract public function columnSql(TableSchema $schema, $name);
* @param \Cake\Database\Schema\TableSchema $schema The table instance the foreign key constraints are.
* @return array SQL fragment.
*/
- abstract public function addConstraintSql(TableSchema $schema);
+ abstract public function addConstraintSql(TableSchema $schema): array;
/**
* Generate the SQL queries needed to drop foreign key constraints from the table
@@ -245,7 +255,7 @@ abstract public function addConstraintSql(TableSchema $schema);
* @param \Cake\Database\Schema\TableSchema $schema The table instance the foreign key constraints are.
* @return array SQL fragment.
*/
- abstract public function dropConstraintSql(TableSchema $schema);
+ abstract public function dropConstraintSql(TableSchema $schema): array;
/**
* Generate the SQL fragments for defining table constraints.
@@ -254,7 +264,7 @@ abstract public function dropConstraintSql(TableSchema $schema);
* @param string $name The name of the column.
* @return string SQL fragment.
*/
- abstract public function constraintSql(TableSchema $schema, $name);
+ abstract public function constraintSql(TableSchema $schema, string $name): string;
/**
* Generate the SQL fragment for a single index in a table.
@@ -263,7 +273,7 @@ abstract public function constraintSql(TableSchema $schema, $name);
* @param string $name The name of the column.
* @return string SQL fragment.
*/
- abstract public function indexSql(TableSchema $schema, $name);
+ abstract public function indexSql(TableSchema $schema, string $name): string;
/**
* Generate the SQL to truncate a table.
@@ -271,5 +281,5 @@ abstract public function indexSql(TableSchema $schema, $name);
* @param \Cake\Database\Schema\TableSchema $schema Table instance.
* @return array SQL statements to truncate a table.
*/
- abstract public function truncateTableSql(TableSchema $schema);
+ abstract public function truncateTableSql(TableSchema $schema): array;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/CachedCollection.php b/app/vendor/cakephp/cakephp/src/Database/Schema/CachedCollection.php
index 1137167ea..7e7aac559 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/CachedCollection.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/CachedCollection.php
@@ -1,4 +1,6 @@
collection = $collection;
+ $this->prefix = $prefix;
+ $this->cacher = $cacher;
+ }
+
+ /**
+ * @inheritDoc
*/
- public function __construct(ConnectionInterface $connection, $cacheKey = true)
+ public function listTables(): array
{
- parent::__construct($connection);
- $this->setCacheMetadata($cacheKey);
+ return $this->collection->listTables();
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describe($name, array $options = [])
+ public function describe(string $name, array $options = []): TableSchemaInterface
{
$options += ['forceRefresh' => false];
- $cacheConfig = $this->getCacheMetadata();
$cacheKey = $this->cacheKey($name);
- if (!empty($cacheConfig) && !$options['forceRefresh']) {
- $cached = Cache::read($cacheKey, $cacheConfig);
- if ($cached !== false) {
+ if (!$options['forceRefresh']) {
+ $cached = $this->cacher->get($cacheKey);
+ if ($cached !== null) {
return $cached;
}
}
- $table = parent::describe($name, $options);
-
- if (!empty($cacheConfig)) {
- Cache::write($cacheKey, $table, $cacheConfig);
- }
+ $table = $this->collection->describe($name, $options);
+ $this->cacher->set($cacheKey, $table);
return $table;
}
@@ -73,64 +93,31 @@ public function describe($name, array $options = [])
* @param string $name The name to get a cache key for.
* @return string The cache key.
*/
- public function cacheKey($name)
+ public function cacheKey(string $name): string
{
- $cachePrefix = $this->_connection->configName();
- $config = $this->_connection->config();
- if (isset($config['cacheKeyPrefix'])) {
- $cachePrefix = $config['cacheKeyPrefix'];
- }
-
- return $cachePrefix . '_' . $name;
+ return $this->prefix . '_' . $name;
}
/**
- * Sets the cache config name to use for caching table metadata, or
- * disables it if false is passed.
+ * Set a cacher.
*
- * @param bool $enable Whether or not to enable caching
+ * @param \Psr\SimpleCache\CacheInterface $cacher Cacher object
* @return $this
*/
- public function setCacheMetadata($enable)
+ public function setCacher(CacheInterface $cacher)
{
- if ($enable === true) {
- $enable = '_cake_model_';
- }
-
- $this->_cache = $enable;
+ $this->cacher = $cacher;
return $this;
}
/**
- * Gets the cache config name to use for caching table metadata, false means disabled.
- *
- * @return string|bool
- */
- public function getCacheMetadata()
- {
- return $this->_cache;
- }
-
- /**
- * Sets the cache config name to use for caching table metadata, or
- * disables it if false is passed.
- * If called with no arguments it returns the current configuration name.
+ * Get a cacher.
*
- * @deprecated 3.4.0 Use setCacheMetadata()/getCacheMetadata()
- * @param bool|null $enable Whether or not to enable caching
- * @return string|bool
+ * @return \Psr\SimpleCache\CacheInterface $cacher Cacher object
*/
- public function cacheMetadata($enable = null)
+ public function getCacher(): CacheInterface
{
- deprecationWarning(
- 'CachedCollection::cacheMetadata() is deprecated. ' .
- 'Use CachedCollection::setCacheMetadata()/getCacheMetadata() instead.'
- );
- if ($enable !== null) {
- $this->setCacheMetadata($enable);
- }
-
- return $this->getCacheMetadata();
+ return $this->cacher;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/Collection.php b/app/vendor/cakephp/cakephp/src/Database/Schema/Collection.php
index 65bccaf04..b214bdc08 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/Collection.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/Collection.php
@@ -1,4 +1,6 @@
_dialect->listTablesSql($this->_connection->config());
+ [$sql, $params] = $this->_dialect->listTablesSql($this->_connection->config());
$result = [];
$statement = $this->_connection->execute($sql, $params);
while ($row = $statement->fetch()) {
@@ -87,11 +89,11 @@ public function listTables()
* @return \Cake\Database\Schema\TableSchema Object with column metadata.
* @throws \Cake\Database\Exception when table cannot be described.
*/
- public function describe($name, array $options = [])
+ public function describe(string $name, array $options = []): TableSchemaInterface
{
$config = $this->_connection->config();
if (strpos($name, '.')) {
- list($config['schema'], $name) = explode('.', $name);
+ [$config['schema'], $name] = explode('.', $name);
}
$table = $this->_connection->getDriver()->newTableSchema($name);
@@ -113,16 +115,24 @@ public function describe($name, array $options = [])
* @param string $stage The stage name.
* @param string $name The table name.
* @param array $config The config data.
- * @param \Cake\Database\Schema\TableSchemaInterface $schema The table schema instance.
+ * @param \Cake\Database\Schema\TableSchema $schema The table schema instance.
* @return void
* @throws \Cake\Database\Exception on query failure.
+ * @uses \Cake\Database\Schema\BaseSchema::describeColumnSql
+ * @uses \Cake\Database\Schema\BaseSchema::describeIndexSql
+ * @uses \Cake\Database\Schema\BaseSchema::describeForeignKeySql
+ * @uses \Cake\Database\Schema\BaseSchema::describeOptionsSql
+ * @uses \Cake\Database\Schema\BaseSchema::convertColumnDescription
+ * @uses \Cake\Database\Schema\BaseSchema::convertIndexDescription
+ * @uses \Cake\Database\Schema\BaseSchema::convertForeignKeyDescription
+ * @uses \Cake\Database\Schema\BaseSchema::convertOptionsDescription
*/
- protected function _reflect($stage, $name, $config, $schema)
+ protected function _reflect(string $stage, string $name, array $config, TableSchema $schema): void
{
$describeMethod = "describe{$stage}Sql";
$convertMethod = "convert{$stage}Description";
- list($sql, $params) = $this->_dialect->{$describeMethod}($name, $config);
+ [$sql, $params] = $this->_dialect->{$describeMethod}($name, $config);
if (empty($sql)) {
return;
}
@@ -131,6 +141,7 @@ protected function _reflect($stage, $name, $config, $schema)
} catch (PDOException $e) {
throw new Exception($e->getMessage(), 500, $e);
}
+ /** @psalm-suppress PossiblyFalseIterator */
foreach ($statement->fetchAll('assoc') as $row) {
$this->_dialect->{$convertMethod}($schema, $row);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/CollectionInterface.php b/app/vendor/cakephp/cakephp/src/Database/Schema/CollectionInterface.php
new file mode 100644
index 000000000..9bd58cac3
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/CollectionInterface.php
@@ -0,0 +1,51 @@
+_driver->quoteIdentifier($config['database']), []];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeColumnSql($tableName, $config)
+ public function describeColumnSql(string $tableName, array $config): array
{
return ['SHOW FULL COLUMNS FROM ' . $this->_driver->quoteIdentifier($tableName), []];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeIndexSql($tableName, $config)
+ public function describeIndexSql(string $tableName, array $config): array
{
return ['SHOW INDEXES FROM ' . $this->_driver->quoteIdentifier($tableName), []];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeOptionsSql($tableName, $config)
+ public function describeOptionsSql(string $tableName, array $config): array
{
return ['SHOW TABLE STATUS WHERE Name = ?', [$tableName]];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertOptionsDescription(TableSchema $schema, $row)
+ public function convertOptionsDescription(TableSchema $schema, array $row): void
{
$schema->setOptions([
'engine' => $row['Engine'],
@@ -75,13 +76,13 @@ public function convertOptionsDescription(TableSchema $schema, $row)
/**
* Convert a MySQL column type into an abstract type.
*
- * The returned type will be a type that Cake\Database\Type can handle.
+ * The returned type will be a type that Cake\Database\TypeFactory can handle.
*
* @param string $column The column type + length
* @return array Array of column information.
* @throws \Cake\Database\Exception When column type cannot be parsed.
*/
- protected function _convertColumn($column)
+ protected function _convertColumn(string $column): array
{
preg_match('/([a-z]+)(?:\(([0-9,]+)\))?\s*([a-z]+)?/i', $column, $matches);
if (empty($matches)) {
@@ -93,15 +94,24 @@ protected function _convertColumn($column)
if (isset($matches[2]) && strlen($matches[2])) {
$length = $matches[2];
if (strpos($matches[2], ',') !== false) {
- list($length, $precision) = explode(',', $length);
+ [$length, $precision] = explode(',', $length);
}
$length = (int)$length;
$precision = (int)$precision;
}
- if (in_array($col, ['date', 'time', 'datetime', 'timestamp'])) {
+ if (in_array($col, ['date', 'time'])) {
return ['type' => $col, 'length' => null];
}
+ if (in_array($col, ['datetime', 'timestamp'])) {
+ $typeName = $col;
+ if ($length > 0) {
+ $typeName = $col . 'fractional';
+ }
+
+ return ['type' => $typeName, 'length' => null, 'precision' => $length];
+ }
+
if (($col === 'tinyint' && $length === 1) || $col === 'boolean') {
return ['type' => TableSchema::TYPE_BOOLEAN, 'length' => null];
}
@@ -123,14 +133,14 @@ protected function _convertColumn($column)
return ['type' => TableSchema::TYPE_UUID, 'length' => null];
}
if ($col === 'char') {
- return ['type' => TableSchema::TYPE_STRING, 'length' => $length, 'fixed' => true];
+ return ['type' => TableSchema::TYPE_CHAR, 'length' => $length];
}
if (strpos($col, 'char') !== false) {
return ['type' => TableSchema::TYPE_STRING, 'length' => $length];
}
if (strpos($col, 'text') !== false) {
$lengthName = substr($col, 0, -4);
- $length = isset(TableSchema::$columnLengths[$lengthName]) ? TableSchema::$columnLengths[$lengthName] : null;
+ $length = TableSchema::$columnLengths[$lengthName] ?? null;
return ['type' => TableSchema::TYPE_TEXT, 'length' => $length];
}
@@ -139,7 +149,7 @@ protected function _convertColumn($column)
}
if (strpos($col, 'blob') !== false || in_array($col, ['binary', 'varbinary'])) {
$lengthName = substr($col, 0, -4);
- $length = isset(TableSchema::$columnLengths[$lengthName]) ? TableSchema::$columnLengths[$lengthName] : $length;
+ $length = TableSchema::$columnLengths[$lengthName] ?? $length;
return ['type' => TableSchema::TYPE_BINARY, 'length' => $length];
}
@@ -168,9 +178,9 @@ protected function _convertColumn($column)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertColumnDescription(TableSchema $schema, $row)
+ public function convertColumnDescription(TableSchema $schema, array $row): void
{
$field = $this->_convertColumn($row['Type']);
$field += [
@@ -186,9 +196,9 @@ public function convertColumnDescription(TableSchema $schema, $row)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertIndexDescription(TableSchema $schema, $row)
+ public function convertIndexDescription(TableSchema $schema, array $row): void
{
$type = null;
$columns = $length = [];
@@ -202,7 +212,7 @@ public function convertIndexDescription(TableSchema $schema, $row)
if ($row['Index_type'] === 'FULLTEXT') {
$type = TableSchema::INDEX_FULLTEXT;
- } elseif ($row['Non_unique'] == 0 && $type !== 'primary') {
+ } elseif ((int)$row['Non_unique'] === 0 && $type !== 'primary') {
$type = TableSchema::CONSTRAINT_UNIQUE;
} elseif ($type !== 'primary') {
$type = TableSchema::INDEX_INDEX;
@@ -242,9 +252,9 @@ public function convertIndexDescription(TableSchema $schema, $row)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeForeignKeySql($tableName, $config)
+ public function describeForeignKeySql(string $tableName, array $config): array
{
$sql = 'SELECT * FROM information_schema.key_column_usage AS kcu
INNER JOIN information_schema.referential_constraints AS rc
@@ -258,9 +268,9 @@ public function describeForeignKeySql($tableName, $config)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertForeignKeyDescription(TableSchema $schema, $row)
+ public function convertForeignKeyDescription(TableSchema $schema, array $row): void
{
$data = [
'type' => TableSchema::CONSTRAINT_FOREIGN,
@@ -274,17 +284,17 @@ public function convertForeignKeyDescription(TableSchema $schema, $row)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function truncateTableSql(TableSchema $schema)
+ public function truncateTableSql(TableSchema $schema): array
{
return [sprintf('TRUNCATE TABLE `%s`', $schema->name())];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function createTableSql(TableSchema $schema, $columns, $constraints, $indexes)
+ public function createTableSql(TableSchema $schema, array $columns, array $constraints, array $indexes): array
{
$content = implode(",\n", array_merge($columns, $constraints, $indexes));
$temporary = $schema->isTemporary() ? ' TEMPORARY ' : ' ';
@@ -304,10 +314,11 @@ public function createTableSql(TableSchema $schema, $columns, $constraints, $ind
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function columnSql(TableSchema $schema, $name)
+ public function columnSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getColumn($name);
$out = $this->_driver->quoteIdentifier($name);
$nativeJson = $this->_driver->supportsNativeJson();
@@ -324,13 +335,18 @@ public function columnSql(TableSchema $schema, $name)
TableSchema::TYPE_DATE => ' DATE',
TableSchema::TYPE_TIME => ' TIME',
TableSchema::TYPE_DATETIME => ' DATETIME',
+ TableSchema::TYPE_DATETIME_FRACTIONAL => ' DATETIME',
TableSchema::TYPE_TIMESTAMP => ' TIMESTAMP',
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL => ' TIMESTAMP',
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE => ' TIMESTAMP',
+ TableSchema::TYPE_CHAR => ' CHAR',
TableSchema::TYPE_UUID => ' CHAR(36)',
TableSchema::TYPE_JSON => $nativeJson ? ' JSON' : ' LONGTEXT',
];
$specialMap = [
'string' => true,
'text' => true,
+ 'char' => true,
'binary' => true,
];
if (isset($typeMap[$data['type']])) {
@@ -339,7 +355,7 @@ public function columnSql(TableSchema $schema, $name)
if (isset($specialMap[$data['type']])) {
switch ($data['type']) {
case TableSchema::TYPE_STRING:
- $out .= !empty($data['fixed']) ? ' CHAR' : ' VARCHAR';
+ $out .= ' VARCHAR';
if (!isset($data['length'])) {
$data['length'] = 255;
}
@@ -351,15 +367,15 @@ public function columnSql(TableSchema $schema, $name)
break;
}
- if ($isKnownLength) {
- $length = array_search($data['length'], TableSchema::$columnLengths);
- $out .= ' ' . strtoupper($length) . 'TEXT';
- }
+ /** @var string $length */
+ $length = array_search($data['length'], TableSchema::$columnLengths);
+ $out .= ' ' . strtoupper($length) . 'TEXT';
break;
case TableSchema::TYPE_BINARY:
$isKnownLength = in_array($data['length'], TableSchema::$columnLengths);
if ($isKnownLength) {
+ /** @var string $length */
$length = array_search($data['length'], TableSchema::$columnLengths);
$out .= ' ' . strtoupper($length) . 'BLOB';
break;
@@ -380,16 +396,17 @@ public function columnSql(TableSchema $schema, $name)
}
$hasLength = [
TableSchema::TYPE_INTEGER,
+ TableSchema::TYPE_CHAR,
TableSchema::TYPE_SMALLINTEGER,
TableSchema::TYPE_TINYINTEGER,
TableSchema::TYPE_STRING,
];
if (in_array($data['type'], $hasLength, true) && isset($data['length'])) {
- $out .= '(' . (int)$data['length'] . ')';
+ $out .= '(' . $data['length'] . ')';
}
- $hasPrecision = [TableSchema::TYPE_FLOAT, TableSchema::TYPE_DECIMAL];
- if (in_array($data['type'], $hasPrecision, true) && isset($data['length'])) {
+ $lengthAndPrecisionTypes = [TableSchema::TYPE_FLOAT, TableSchema::TYPE_DECIMAL];
+ if (in_array($data['type'], $lengthAndPrecisionTypes, true) && isset($data['length'])) {
if (isset($data['precision'])) {
$out .= '(' . (int)$data['length'] . ',' . (int)$data['precision'] . ')';
} else {
@@ -397,6 +414,11 @@ public function columnSql(TableSchema $schema, $name)
}
}
+ $precisionTypes = [TableSchema::TYPE_DATETIME_FRACTIONAL, TableSchema::TYPE_TIMESTAMP_FRACTIONAL];
+ if (in_array($data['type'], $precisionTypes, true) && isset($data['precision'])) {
+ $out .= '(' . (int)$data['precision'] . ')';
+ }
+
$hasUnsigned = [
TableSchema::TYPE_TINYINTEGER,
TableSchema::TYPE_SMALLINTEGER,
@@ -407,13 +429,15 @@ public function columnSql(TableSchema $schema, $name)
];
if (
in_array($data['type'], $hasUnsigned, true) &&
- isset($data['unsigned']) && $data['unsigned'] === true
+ isset($data['unsigned']) &&
+ $data['unsigned'] === true
) {
$out .= ' UNSIGNED';
}
$hasCollate = [
TableSchema::TYPE_TEXT,
+ TableSchema::TYPE_CHAR,
TableSchema::TYPE_STRING,
];
if (in_array($data['type'], $hasCollate, true) && isset($data['collate']) && $data['collate'] !== '') {
@@ -424,26 +448,46 @@ public function columnSql(TableSchema $schema, $name)
$out .= ' NOT NULL';
}
$addAutoIncrement = (
- [$name] == (array)$schema->primaryKey() &&
+ (array)$schema->getPrimaryKey() === [$name] &&
!$schema->hasAutoincrement() &&
!isset($data['autoIncrement'])
);
if (
in_array($data['type'], [TableSchema::TYPE_INTEGER, TableSchema::TYPE_BIGINTEGER]) &&
- ($data['autoIncrement'] === true || $addAutoIncrement)
+ (
+ $data['autoIncrement'] === true ||
+ $addAutoIncrement
+ )
) {
$out .= ' AUTO_INCREMENT';
}
- if (isset($data['null']) && $data['null'] === true && $data['type'] === TableSchema::TYPE_TIMESTAMP) {
+
+ $timestampTypes = [
+ TableSchema::TYPE_TIMESTAMP,
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE,
+ ];
+ if (isset($data['null']) && $data['null'] === true && in_array($data['type'], $timestampTypes, true)) {
$out .= ' NULL';
unset($data['default']);
}
+
+ $dateTimeTypes = [
+ TableSchema::TYPE_DATETIME,
+ TableSchema::TYPE_DATETIME_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP,
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE,
+ ];
if (
isset($data['default']) &&
- in_array($data['type'], [TableSchema::TYPE_TIMESTAMP, TableSchema::TYPE_DATETIME]) &&
- in_array(strtolower($data['default']), ['current_timestamp', 'current_timestamp()'])
+ in_array($data['type'], $dateTimeTypes) &&
+ strpos(strtolower($data['default']), 'current_timestamp') !== false
) {
$out .= ' DEFAULT CURRENT_TIMESTAMP';
+ if (isset($data['precision'])) {
+ $out .= '(' . $data['precision'] . ')';
+ }
unset($data['default']);
}
if (isset($data['default'])) {
@@ -458,10 +502,11 @@ public function columnSql(TableSchema $schema, $name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function constraintSql(TableSchema $schema, $name)
+ public function constraintSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getConstraint($name);
if ($data['type'] === TableSchema::CONSTRAINT_PRIMARY) {
$columns = array_map(
@@ -485,14 +530,15 @@ public function constraintSql(TableSchema $schema, $name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function addConstraintSql(TableSchema $schema)
+ public function addConstraintSql(TableSchema $schema): array
{
$sqlPattern = 'ALTER TABLE %s ADD %s;';
$sql = [];
foreach ($schema->constraints() as $name) {
+ /** @var array $constraint */
$constraint = $schema->getConstraint($name);
if ($constraint['type'] === TableSchema::CONSTRAINT_FOREIGN) {
$tableName = $this->_driver->quoteIdentifier($schema->name());
@@ -504,14 +550,15 @@ public function addConstraintSql(TableSchema $schema)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function dropConstraintSql(TableSchema $schema)
+ public function dropConstraintSql(TableSchema $schema): array
{
$sqlPattern = 'ALTER TABLE %s DROP FOREIGN KEY %s;';
$sql = [];
foreach ($schema->constraints() as $name) {
+ /** @var array $constraint */
$constraint = $schema->getConstraint($name);
if ($constraint['type'] === TableSchema::CONSTRAINT_FOREIGN) {
$tableName = $this->_driver->quoteIdentifier($schema->name());
@@ -524,10 +571,11 @@ public function dropConstraintSql(TableSchema $schema)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function indexSql(TableSchema $schema, $name)
+ public function indexSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getIndex($name);
$out = '';
if ($data['type'] === TableSchema::INDEX_INDEX) {
@@ -548,7 +596,7 @@ public function indexSql(TableSchema $schema, $name)
* @param array $data Key data.
* @return string
*/
- protected function _keySql($prefix, $data)
+ protected function _keySql(string $prefix, array $data): string
{
$columns = array_map(
[$this->_driver, 'quoteIdentifier'],
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/PostgresSchema.php b/app/vendor/cakephp/cakephp/src/Database/Schema/PostgresSchema.php
index cb0da6dca..1e4ab2a88 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/PostgresSchema.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/PostgresSchema.php
@@ -1,4 +1,6 @@
$col, 'length' => null];
}
+ if (in_array($col, ['timestamptz', 'timestamp with time zone'], true)) {
+ return ['type' => TableSchema::TYPE_TIMESTAMP_TIMEZONE, 'length' => null];
+ }
if (strpos($col, 'timestamp') !== false) {
- return ['type' => TableSchema::TYPE_TIMESTAMP, 'length' => null];
+ return ['type' => TableSchema::TYPE_TIMESTAMP_FRACTIONAL, 'length' => null];
}
if (strpos($col, 'time') !== false) {
return ['type' => TableSchema::TYPE_TIME, 'length' => null];
@@ -110,15 +115,15 @@ protected function _convertColumn($column)
if ($col === 'uuid') {
return ['type' => TableSchema::TYPE_UUID, 'length' => null];
}
- if ($col === 'char' || $col === 'character') {
- return ['type' => TableSchema::TYPE_STRING, 'fixed' => true, 'length' => $length];
+ if ($col === 'char') {
+ return ['type' => TableSchema::TYPE_CHAR, 'length' => $length];
+ }
+ if (strpos($col, 'character') !== false) {
+ return ['type' => TableSchema::TYPE_STRING, 'length' => $length];
}
// money is 'string' as it includes arbitrary text content
// before the number value.
- if (
- strpos($col, 'char') !== false ||
- strpos($col, 'money') !== false
- ) {
+ if (strpos($col, 'money') !== false || $col === 'string') {
return ['type' => TableSchema::TYPE_STRING, 'length' => $length];
}
if (strpos($col, 'text') !== false) {
@@ -141,13 +146,15 @@ protected function _convertColumn($column)
return ['type' => TableSchema::TYPE_JSON, 'length' => null];
}
- return ['type' => TableSchema::TYPE_STRING, 'length' => null];
+ $length = is_numeric($length) ? $length : null;
+
+ return ['type' => TableSchema::TYPE_STRING, 'length' => $length];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertColumnDescription(TableSchema $schema, $row)
+ public function convertColumnDescription(TableSchema $schema, array $row): void
{
$field = $this->_convertColumn($row['type']);
@@ -175,6 +182,18 @@ public function convertColumnDescription(TableSchema $schema, $row)
$field['length'] = $row['column_precision'];
$field['precision'] = $row['column_scale'] ?: null;
}
+
+ if ($field['type'] === TableSchema::TYPE_TIMESTAMP_FRACTIONAL) {
+ $field['precision'] = $row['datetime_precision'];
+ if ($field['precision'] === 0) {
+ $field['type'] = TableSchema::TYPE_TIMESTAMP;
+ }
+ }
+
+ if ($field['type'] === TableSchema::TYPE_TIMESTAMP_TIMEZONE) {
+ $field['precision'] = $row['datetime_precision'];
+ }
+
$schema->addColumn($row['name'], $field);
}
@@ -184,8 +203,8 @@ public function convertColumnDescription(TableSchema $schema, $row)
* Postgres includes sequence data and casting information in default values.
* We need to remove those.
*
- * @param string|null $default The default value.
- * @return string|null
+ * @param string|int|null $default The default value.
+ * @return string|int|null
*/
protected function _defaultValue($default)
{
@@ -210,9 +229,9 @@ protected function _defaultValue($default)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeIndexSql($tableName, $config)
+ public function describeIndexSql(string $tableName, array $config): array
{
$sql = 'SELECT
c2.relname,
@@ -238,9 +257,9 @@ public function describeIndexSql($tableName, $config)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertIndexDescription(TableSchema $schema, $row)
+ public function convertIndexDescription(TableSchema $schema, array $row): void
{
$type = TableSchema::INDEX_INDEX;
$name = $row['relname'];
@@ -275,7 +294,7 @@ public function convertIndexDescription(TableSchema $schema, $row)
* @param array $row The metadata record to update with.
* @return void
*/
- protected function _convertConstraint($schema, $name, $type, $row)
+ protected function _convertConstraint(TableSchema $schema, string $name, string $type, array $row): void
{
$constraint = $schema->getConstraint($name);
if (!$constraint) {
@@ -289,10 +308,11 @@ protected function _convertConstraint($schema, $name, $type, $row)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeForeignKeySql($tableName, $config)
+ public function describeForeignKeySql(string $tableName, array $config): array
{
+ // phpcs:disable Generic.Files.LineLength
$sql = 'SELECT
c.conname AS name,
c.contype AS type,
@@ -310,6 +330,7 @@ public function describeForeignKeySql($tableName, $config)
WHERE n.nspname = ?
AND cl.relname = ?
ORDER BY name, a.attnum, ab.attnum DESC';
+ // phpcs:enable Generic.Files.LineLength
$schema = empty($config['schema']) ? 'public' : $config['schema'];
@@ -317,9 +338,9 @@ public function describeForeignKeySql($tableName, $config)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertForeignKeyDescription(TableSchema $schema, $row)
+ public function convertForeignKeyDescription(TableSchema $schema, array $row): void
{
$data = [
'type' => TableSchema::CONSTRAINT_FOREIGN,
@@ -332,9 +353,9 @@ public function convertForeignKeyDescription(TableSchema $schema, $row)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- protected function _convertOnClause($clause)
+ protected function _convertOnClause(string $clause): string
{
if ($clause === 'r') {
return TableSchema::ACTION_RESTRICT;
@@ -350,10 +371,11 @@ protected function _convertOnClause($clause)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function columnSql(TableSchema $schema, $name)
+ public function columnSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getColumn($name);
$out = $this->_driver->quoteIdentifier($name);
$typeMap = [
@@ -366,8 +388,12 @@ public function columnSql(TableSchema $schema, $name)
TableSchema::TYPE_DATE => ' DATE',
TableSchema::TYPE_TIME => ' TIME',
TableSchema::TYPE_DATETIME => ' TIMESTAMP',
+ TableSchema::TYPE_DATETIME_FRACTIONAL => ' TIMESTAMP',
TableSchema::TYPE_TIMESTAMP => ' TIMESTAMP',
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL => ' TIMESTAMP',
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE => ' TIMESTAMPTZ',
TableSchema::TYPE_UUID => ' UUID',
+ TableSchema::TYPE_CHAR => ' CHAR',
TableSchema::TYPE_JSON => ' JSONB',
];
@@ -377,7 +403,7 @@ public function columnSql(TableSchema $schema, $name)
if ($data['type'] === TableSchema::TYPE_INTEGER || $data['type'] === TableSchema::TYPE_BIGINTEGER) {
$type = $data['type'] === TableSchema::TYPE_INTEGER ? ' INTEGER' : ' BIGINT';
- if ([$name] === $schema->primaryKey() || $data['autoIncrement'] === true) {
+ if ($schema->getPrimaryKey() === [$name] || $data['autoIncrement'] === true) {
$type = $data['type'] === TableSchema::TYPE_INTEGER ? ' SERIAL' : ' BIGSERIAL';
unset($data['null'], $data['default']);
}
@@ -391,44 +417,64 @@ public function columnSql(TableSchema $schema, $name)
$out .= ' BYTEA';
}
+ if ($data['type'] === TableSchema::TYPE_CHAR) {
+ $out .= '(' . $data['length'] . ')';
+ }
+
if (
$data['type'] === TableSchema::TYPE_STRING ||
- ($data['type'] === TableSchema::TYPE_TEXT && $data['length'] === TableSchema::LENGTH_TINY)
+ (
+ $data['type'] === TableSchema::TYPE_TEXT &&
+ $data['length'] === TableSchema::LENGTH_TINY
+ )
) {
- $isFixed = !empty($data['fixed']);
- $type = ' VARCHAR';
- if ($isFixed) {
- $type = ' CHAR';
- }
- $out .= $type;
- if (isset($data['length'])) {
- $out .= '(' . (int)$data['length'] . ')';
+ $out .= ' VARCHAR';
+ if (isset($data['length']) && $data['length'] !== '') {
+ $out .= '(' . $data['length'] . ')';
}
}
- $hasCollate = [TableSchema::TYPE_TEXT, TableSchema::TYPE_STRING];
+ $hasCollate = [TableSchema::TYPE_TEXT, TableSchema::TYPE_STRING, TableSchema::TYPE_CHAR];
if (in_array($data['type'], $hasCollate, true) && isset($data['collate']) && $data['collate'] !== '') {
$out .= ' COLLATE "' . $data['collate'] . '"';
}
- if ($data['type'] === TableSchema::TYPE_FLOAT && isset($data['precision'])) {
- $out .= '(' . (int)$data['precision'] . ')';
+ $hasPrecision = [
+ TableSchema::TYPE_FLOAT,
+ TableSchema::TYPE_DATETIME,
+ TableSchema::TYPE_DATETIME_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP,
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE,
+ ];
+ if (in_array($data['type'], $hasPrecision) && isset($data['precision'])) {
+ $out .= '(' . $data['precision'] . ')';
}
if (
$data['type'] === TableSchema::TYPE_DECIMAL &&
- (isset($data['length']) || isset($data['precision']))
+ (
+ isset($data['length']) ||
+ isset($data['precision'])
+ )
) {
- $out .= '(' . (int)$data['length'] . ',' . (int)$data['precision'] . ')';
+ $out .= '(' . $data['length'] . ',' . (int)$data['precision'] . ')';
}
if (isset($data['null']) && $data['null'] === false) {
$out .= ' NOT NULL';
}
+ $datetimeTypes = [
+ TableSchema::TYPE_DATETIME,
+ TableSchema::TYPE_DATETIME_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP,
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE,
+ ];
if (
isset($data['default']) &&
- in_array($data['type'], [TableSchema::TYPE_TIMESTAMP, TableSchema::TYPE_DATETIME]) &&
+ in_array($data['type'], $datetimeTypes) &&
strtolower($data['default']) === 'current_timestamp'
) {
$out .= ' DEFAULT CURRENT_TIMESTAMP';
@@ -446,14 +492,15 @@ public function columnSql(TableSchema $schema, $name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function addConstraintSql(TableSchema $schema)
+ public function addConstraintSql(TableSchema $schema): array
{
$sqlPattern = 'ALTER TABLE %s ADD %s;';
$sql = [];
foreach ($schema->constraints() as $name) {
+ /** @var array $constraint */
$constraint = $schema->getConstraint($name);
if ($constraint['type'] === TableSchema::CONSTRAINT_FOREIGN) {
$tableName = $this->_driver->quoteIdentifier($schema->name());
@@ -465,14 +512,15 @@ public function addConstraintSql(TableSchema $schema)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function dropConstraintSql(TableSchema $schema)
+ public function dropConstraintSql(TableSchema $schema): array
{
$sqlPattern = 'ALTER TABLE %s DROP CONSTRAINT %s;';
$sql = [];
foreach ($schema->constraints() as $name) {
+ /** @var array $constraint */
$constraint = $schema->getConstraint($name);
if ($constraint['type'] === TableSchema::CONSTRAINT_FOREIGN) {
$tableName = $this->_driver->quoteIdentifier($schema->name());
@@ -485,10 +533,11 @@ public function dropConstraintSql(TableSchema $schema)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function indexSql(TableSchema $schema, $name)
+ public function indexSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getIndex($name);
$columns = array_map(
[$this->_driver, 'quoteIdentifier'],
@@ -504,10 +553,11 @@ public function indexSql(TableSchema $schema, $name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function constraintSql(TableSchema $schema, $name)
+ public function constraintSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getConstraint($name);
$out = 'CONSTRAINT ' . $this->_driver->quoteIdentifier($name);
if ($data['type'] === TableSchema::CONSTRAINT_PRIMARY) {
@@ -527,7 +577,7 @@ public function constraintSql(TableSchema $schema, $name)
* @param array $data Key data.
* @return string
*/
- protected function _keySql($prefix, $data)
+ protected function _keySql(string $prefix, array $data): string
{
$columns = array_map(
[$this->_driver, 'quoteIdentifier'],
@@ -548,9 +598,9 @@ protected function _keySql($prefix, $data)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function createTableSql(TableSchema $schema, $columns, $constraints, $indexes)
+ public function createTableSql(TableSchema $schema, array $columns, array $constraints, array $indexes): array
{
$content = array_merge($columns, $constraints);
$content = implode(",\n", array_filter($content));
@@ -577,9 +627,9 @@ public function createTableSql(TableSchema $schema, $columns, $constraints, $ind
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function truncateTableSql(TableSchema $schema)
+ public function truncateTableSql(TableSchema $schema): array
{
$name = $this->_driver->quoteIdentifier($schema->name());
@@ -594,7 +644,7 @@ public function truncateTableSql(TableSchema $schema)
* @param \Cake\Database\Schema\TableSchema $schema Table instance
* @return array SQL statements to drop a table.
*/
- public function dropTableSql(TableSchema $schema)
+ public function dropTableSql(TableSchema $schema): array
{
$sql = sprintf(
'DROP TABLE %s CASCADE',
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/SqlGeneratorInterface.php b/app/vendor/cakephp/cakephp/src/Database/Schema/SqlGeneratorInterface.php
index 847f7d822..3acaf27b9 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/SqlGeneratorInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/SqlGeneratorInterface.php
@@ -1,4 +1,6 @@
TableSchema::TYPE_BIGINTEGER, 'length' => $length, 'unsigned' => $unsigned];
}
- if ($col == 'smallint') {
+ if ($col === 'smallint') {
return ['type' => TableSchema::TYPE_SMALLINTEGER, 'length' => $length, 'unsigned' => $unsigned];
}
- if ($col == 'tinyint') {
+ if ($col === 'tinyint') {
return ['type' => TableSchema::TYPE_TINYINTEGER, 'length' => $length, 'unsigned' => $unsigned];
}
if (strpos($col, 'int') !== false) {
return ['type' => TableSchema::TYPE_INTEGER, 'length' => $length, 'unsigned' => $unsigned];
}
if (strpos($col, 'decimal') !== false) {
- return ['type' => TableSchema::TYPE_DECIMAL, 'length' => $length, 'precision' => $precision, 'unsigned' => $unsigned];
+ return [
+ 'type' => TableSchema::TYPE_DECIMAL,
+ 'length' => $length,
+ 'precision' => $precision,
+ 'unsigned' => $unsigned,
+ ];
}
if (in_array($col, ['float', 'real', 'double'])) {
- return ['type' => TableSchema::TYPE_FLOAT, 'length' => $length, 'precision' => $precision, 'unsigned' => $unsigned];
+ return [
+ 'type' => TableSchema::TYPE_FLOAT,
+ 'length' => $length,
+ 'precision' => $precision,
+ 'unsigned' => $unsigned,
+ ];
}
if (strpos($col, 'boolean') !== false) {
@@ -97,7 +108,7 @@ protected function _convertColumn($column)
return ['type' => TableSchema::TYPE_UUID, 'length' => null];
}
if ($col === 'char') {
- return ['type' => TableSchema::TYPE_STRING, 'fixed' => true, 'length' => $length];
+ return ['type' => TableSchema::TYPE_CHAR, 'length' => $length];
}
if (strpos($col, 'char') !== false) {
return ['type' => TableSchema::TYPE_STRING, 'length' => $length];
@@ -109,7 +120,17 @@ protected function _convertColumn($column)
if (in_array($col, ['blob', 'clob', 'binary', 'varbinary'])) {
return ['type' => TableSchema::TYPE_BINARY, 'length' => $length];
}
- if (in_array($col, ['date', 'time', 'timestamp', 'datetime'])) {
+
+ $datetimeTypes = [
+ 'date',
+ 'time',
+ 'timestamp',
+ 'timestampfractional',
+ 'timestamptimezone',
+ 'datetime',
+ 'datetimefractional',
+ ];
+ if (in_array($col, $datetimeTypes)) {
return ['type' => $col, 'length' => null];
}
@@ -117,9 +138,9 @@ protected function _convertColumn($column)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function listTablesSql($config)
+ public function listTablesSql(array $config): array
{
return [
'SELECT name FROM sqlite_master WHERE type="table" ' .
@@ -129,9 +150,9 @@ public function listTablesSql($config)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeColumnSql($tableName, $config)
+ public function describeColumnSql(string $tableName, array $config): array
{
$sql = sprintf(
'PRAGMA table_info(%s)',
@@ -142,9 +163,9 @@ public function describeColumnSql($tableName, $config)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertColumnDescription(TableSchema $schema, $row)
+ public function convertColumnDescription(TableSchema $schema, array $row): void
{
$field = $this->_convertColumn($row['type']);
$field += [
@@ -161,6 +182,7 @@ public function convertColumnDescription(TableSchema $schema, $row)
// SQLite does not support autoincrement on composite keys.
if ($row['pk'] && !empty($primary)) {
$existingColumn = $primary['columns'][0];
+ /** @psalm-suppress PossiblyNullOperand */
$schema->addColumn($existingColumn, ['autoIncrement' => null] + $schema->getColumn($existingColumn));
}
@@ -181,17 +203,17 @@ public function convertColumnDescription(TableSchema $schema, $row)
* Sqlite includes quotes and bared NULLs in default values.
* We need to remove those.
*
- * @param string|null $default The default value.
- * @return string|null
+ * @param string|int|null $default The default value.
+ * @return string|int|null
*/
protected function _defaultValue($default)
{
- if ($default === 'NULL') {
+ if ($default === 'NULL' || $default === null) {
return null;
}
// Remove quotes
- if (preg_match("/^'(.*)'$/", $default, $matches)) {
+ if (is_string($default) && preg_match("/^'(.*)'$/", $default, $matches)) {
return str_replace("''", "'", $matches[1]);
}
@@ -199,9 +221,9 @@ protected function _defaultValue($default)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeIndexSql($tableName, $config)
+ public function describeIndexSql(string $tableName, array $config): array
{
$sql = sprintf(
'PRAGMA index_list(%s)',
@@ -218,8 +240,13 @@ public function describeIndexSql($tableName, $config)
* additional queries are done here. Sqlite constraint names are not
* stable, and the names for constraints will not match those used to create
* the table. This is a limitation in Sqlite's metadata features.
+ *
+ * @param \Cake\Database\Schema\TableSchema $schema The table object to append
+ * an index or constraint to.
+ * @param array $row The row data from `describeIndexSql`.
+ * @return void
*/
- public function convertIndexDescription(TableSchema $schema, $row)
+ public function convertIndexDescription(TableSchema $schema, array $row): void
{
$sql = sprintf(
'PRAGMA index_info(%s)',
@@ -228,6 +255,7 @@ public function convertIndexDescription(TableSchema $schema, $row)
$statement = $this->_driver->prepare($sql);
$statement->execute();
$columns = [];
+ /** @psalm-suppress PossiblyFalseIterator */
foreach ($statement->fetchAll('assoc') as $column) {
$columns[] = $column['name'];
}
@@ -246,9 +274,9 @@ public function convertIndexDescription(TableSchema $schema, $row)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeForeignKeySql($tableName, $config)
+ public function describeForeignKeySql(string $tableName, array $config): array
{
$sql = sprintf('PRAGMA foreign_key_list(%s)', $this->_driver->quoteIdentifier($tableName));
@@ -256,14 +284,14 @@ public function describeForeignKeySql($tableName, $config)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertForeignKeyDescription(TableSchema $schema, $row)
+ public function convertForeignKeyDescription(TableSchema $schema, array $row): void
{
$name = $row['from'] . '_fk';
- $update = isset($row['on_update']) ? $row['on_update'] : '';
- $delete = isset($row['on_delete']) ? $row['on_delete'] : '';
+ $update = $row['on_update'] ?? '';
+ $delete = $row['on_delete'] ?? '';
$data = [
'type' => TableSchema::CONSTRAINT_FOREIGN,
'columns' => [$row['from']],
@@ -284,14 +312,19 @@ public function convertForeignKeyDescription(TableSchema $schema, $row)
/**
* {@inheritDoc}
*
+ * @param \Cake\Database\Schema\TableSchema $schema The table instance the column is in.
+ * @param string $name The name of the column.
+ * @return string SQL fragment.
* @throws \Cake\Database\Exception when the column type is unknown
*/
- public function columnSql(TableSchema $schema, $name)
+ public function columnSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getColumn($name);
$typeMap = [
TableSchema::TYPE_BINARY_UUID => ' BINARY(16)',
TableSchema::TYPE_UUID => ' CHAR(36)',
+ TableSchema::TYPE_CHAR => ' CHAR',
TableSchema::TYPE_TINYINTEGER => ' TINYINT',
TableSchema::TYPE_SMALLINTEGER => ' SMALLINT',
TableSchema::TYPE_INTEGER => ' INTEGER',
@@ -302,7 +335,10 @@ public function columnSql(TableSchema $schema, $name)
TableSchema::TYPE_DATE => ' DATE',
TableSchema::TYPE_TIME => ' TIME',
TableSchema::TYPE_DATETIME => ' DATETIME',
+ TableSchema::TYPE_DATETIME_FRACTIONAL => ' DATETIMEFRACTIONAL',
TableSchema::TYPE_TIMESTAMP => ' TIMESTAMP',
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL => ' TIMESTAMPFRACTIONAL',
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE => ' TIMESTAMPTIMEZONE',
TableSchema::TYPE_JSON => ' TEXT',
];
@@ -318,9 +354,10 @@ public function columnSql(TableSchema $schema, $name)
if (
in_array($data['type'], $hasUnsigned, true) &&
- isset($data['unsigned']) && $data['unsigned'] === true
+ isset($data['unsigned']) &&
+ $data['unsigned'] === true
) {
- if ($data['type'] !== TableSchema::TYPE_INTEGER || [$name] !== (array)$schema->primaryKey()) {
+ if ($data['type'] !== TableSchema::TYPE_INTEGER || (array)$schema->getPrimaryKey() !== [$name]) {
$out .= ' UNSIGNED';
}
}
@@ -333,20 +370,27 @@ public function columnSql(TableSchema $schema, $name)
$out .= ' TEXT';
}
+ if ($data['type'] === TableSchema::TYPE_CHAR) {
+ $out .= '(' . $data['length'] . ')';
+ }
+
if (
$data['type'] === TableSchema::TYPE_STRING ||
- ($data['type'] === TableSchema::TYPE_TEXT && $data['length'] === TableSchema::LENGTH_TINY)
+ (
+ $data['type'] === TableSchema::TYPE_TEXT &&
+ $data['length'] === TableSchema::LENGTH_TINY
+ )
) {
$out .= ' VARCHAR';
if (isset($data['length'])) {
- $out .= '(' . (int)$data['length'] . ')';
+ $out .= '(' . $data['length'] . ')';
}
}
if ($data['type'] === TableSchema::TYPE_BINARY) {
if (isset($data['length'])) {
- $out .= ' BLOB(' . (int)$data['length'] . ')';
+ $out .= ' BLOB(' . $data['length'] . ')';
} else {
$out .= ' BLOB';
}
@@ -359,15 +403,19 @@ public function columnSql(TableSchema $schema, $name)
];
if (
in_array($data['type'], $integerTypes, true) &&
- isset($data['length']) && [$name] !== (array)$schema->primaryKey()
+ isset($data['length']) &&
+ (array)$schema->getPrimaryKey() !== [$name]
) {
- $out .= '(' . (int)$data['length'] . ')';
+ $out .= '(' . (int)$data['length'] . ')';
}
$hasPrecision = [TableSchema::TYPE_FLOAT, TableSchema::TYPE_DECIMAL];
if (
in_array($data['type'], $hasPrecision, true) &&
- (isset($data['length']) || isset($data['precision']))
+ (
+ isset($data['length']) ||
+ isset($data['precision'])
+ )
) {
$out .= '(' . (int)$data['length'] . ',' . (int)$data['precision'] . ')';
}
@@ -376,11 +424,18 @@ public function columnSql(TableSchema $schema, $name)
$out .= ' NOT NULL';
}
- if ($data['type'] === TableSchema::TYPE_INTEGER && [$name] === (array)$schema->primaryKey()) {
+ if ($data['type'] === TableSchema::TYPE_INTEGER && (array)$schema->getPrimaryKey() === [$name]) {
$out .= ' PRIMARY KEY AUTOINCREMENT';
}
- if (isset($data['null']) && $data['null'] === true && $data['type'] === TableSchema::TYPE_TIMESTAMP) {
+ $timestampTypes = [
+ TableSchema::TYPE_DATETIME,
+ TableSchema::TYPE_DATETIME_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP,
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE,
+ ];
+ if (isset($data['null']) && $data['null'] === true && in_array($data['type'], $timestampTypes, true)) {
$out .= ' DEFAULT NULL';
}
if (isset($data['default'])) {
@@ -395,10 +450,16 @@ public function columnSql(TableSchema $schema, $name)
*
* Note integer primary keys will return ''. This is intentional as Sqlite requires
* that integer primary keys be defined in the column definition.
+ *
+ * @param \Cake\Database\Schema\TableSchema $schema The table instance the column is in.
+ * @param string $name The name of the column.
+ * @return string SQL fragment.
*/
- public function constraintSql(TableSchema $schema, $name)
+ public function constraintSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getConstraint($name);
+ /** @psalm-suppress PossiblyNullArrayAccess */
if (
$data['type'] === TableSchema::CONSTRAINT_PRIMARY &&
count($data['columns']) === 1 &&
@@ -444,8 +505,11 @@ public function constraintSql(TableSchema $schema, $name)
*
* SQLite can not properly handle adding a constraint to an existing table.
* This method is no-op
+ *
+ * @param \Cake\Database\Schema\TableSchema $schema The table instance the foreign key constraints are.
+ * @return array SQL fragment.
*/
- public function addConstraintSql(TableSchema $schema)
+ public function addConstraintSql(TableSchema $schema): array
{
return [];
}
@@ -455,17 +519,21 @@ public function addConstraintSql(TableSchema $schema)
*
* SQLite can not properly handle dropping a constraint to an existing table.
* This method is no-op
+ *
+ * @param \Cake\Database\Schema\TableSchema $schema The table instance the foreign key constraints are.
+ * @return array SQL fragment.
*/
- public function dropConstraintSql(TableSchema $schema)
+ public function dropConstraintSql(TableSchema $schema): array
{
return [];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function indexSql(TableSchema $schema, $name)
+ public function indexSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getIndex($name);
$columns = array_map(
[$this->_driver, 'quoteIdentifier'],
@@ -481,9 +549,9 @@ public function indexSql(TableSchema $schema, $name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function createTableSql(TableSchema $schema, $columns, $constraints, $indexes)
+ public function createTableSql(TableSchema $schema, array $columns, array $constraints, array $indexes): array
{
$lines = array_merge($columns, $constraints);
$content = implode(",\n", array_filter($lines));
@@ -498,9 +566,9 @@ public function createTableSql(TableSchema $schema, $columns, $constraints, $ind
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function truncateTableSql(TableSchema $schema)
+ public function truncateTableSql(TableSchema $schema): array
{
$name = $schema->name();
$sql = [];
@@ -519,7 +587,7 @@ public function truncateTableSql(TableSchema $schema)
*
* @return bool
*/
- public function hasSequences()
+ public function hasSequences(): bool
{
$result = $this->_driver->prepare(
'SELECT 1 FROM sqlite_master WHERE name = "sqlite_sequence"'
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/SqlserverSchema.php b/app/vendor/cakephp/cakephp/src/Database/Schema/SqlserverSchema.php
index 12f84d055..b69d4a5de 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/SqlserverSchema.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/SqlserverSchema.php
@@ -1,4 +1,6 @@
$col, 'length' => null];
}
+
+ if ($col === 'datetime') {
+ // datetime cannot parse more than 3 digits of precision and isn't accurate
+ return ['type' => TableSchema::TYPE_DATETIME, 'length' => null];
+ }
if (strpos($col, 'datetime') !== false) {
- return ['type' => TableSchema::TYPE_TIMESTAMP, 'length' => null];
+ $typeName = TableSchema::TYPE_DATETIME;
+ if ($scale > 0) {
+ $typeName = TableSchema::TYPE_DATETIME_FRACTIONAL;
+ }
+
+ return ['type' => $typeName, 'length' => null, 'precision' => $scale];
+ }
+
+ if ($col === 'char') {
+ return ['type' => TableSchema::TYPE_CHAR, 'length' => $length];
}
if ($col === 'tinyint') {
@@ -134,7 +151,7 @@ protected function _convertColumn($col, $length = null, $precision = null, $scal
}
if (strpos($col, 'char') !== false) {
- return ['type' => TableSchema::TYPE_STRING, 'fixed' => true, 'length' => $length];
+ return ['type' => TableSchema::TYPE_CHAR, 'length' => $length];
}
if (strpos($col, 'text') !== false) {
@@ -158,29 +175,24 @@ protected function _convertColumn($col, $length = null, $precision = null, $scal
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertColumnDescription(TableSchema $schema, $row)
+ public function convertColumnDescription(TableSchema $schema, array $row): void
{
$field = $this->_convertColumn(
$row['type'],
- $row['char_length'],
- $row['precision'],
- $row['scale']
+ $row['char_length'] !== null ? (int)$row['char_length'] : null,
+ $row['precision'] !== null ? (int)$row['precision'] : null,
+ $row['scale'] !== null ? (int)$row['scale'] : null
);
- if (!empty($row['default'])) {
- $row['default'] = trim($row['default'], '()');
- }
+
if (!empty($row['autoincrement'])) {
$field['autoIncrement'] = true;
}
- if ($field['type'] === TableSchema::TYPE_BOOLEAN) {
- $row['default'] = (int)$row['default'];
- }
$field += [
'null' => $row['null'] === '1',
- 'default' => $this->_defaultValue($row['default']),
+ 'default' => $this->_defaultValue($field['type'], $row['default']),
'collate' => $row['collation_name'],
];
$schema->addColumn($row['name'], $field);
@@ -189,20 +201,35 @@ public function convertColumnDescription(TableSchema $schema, $row)
/**
* Manipulate the default value.
*
- * Sqlite includes quotes and bared NULLs in default values.
- * We need to remove those.
+ * Removes () wrapping default values, extracts strings from
+ * N'' wrappers and collation text and converts NULL strings.
*
+ * @param string $type The schema type
* @param string|null $default The default value.
- * @return string|null
+ * @return string|int|null
*/
- protected function _defaultValue($default)
+ protected function _defaultValue($type, $default)
{
+ if ($default === null) {
+ return $default;
+ }
+
+ // remove () surrounding value (NULL) but leave () at the end of functions
+ // integers might have two ((0)) wrapping value
+ if (preg_match('/^\(+(.*?(\(\))?)\)+$/', $default, $matches)) {
+ $default = $matches[1];
+ }
+
if ($default === 'NULL') {
return null;
}
+ if ($type === TableSchema::TYPE_BOOLEAN) {
+ return (int)$default;
+ }
+
// Remove quotes
- if (preg_match("/^N?'(.*)'/", $default, $matches)) {
+ if (preg_match("/^\(?N?'(.*)'\)?/", $default, $matches)) {
return str_replace("''", "'", $matches[1]);
}
@@ -210,9 +237,9 @@ protected function _defaultValue($default)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeIndexSql($tableName, $config)
+ public function describeIndexSql(string $tableName, array $config): array
{
$sql = "SELECT
I.[name] AS [index_name],
@@ -234,9 +261,9 @@ public function describeIndexSql($tableName, $config)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertIndexDescription(TableSchema $schema, $row)
+ public function convertIndexDescription(TableSchema $schema, array $row): void
{
$type = TableSchema::INDEX_INDEX;
$name = $row['index_name'];
@@ -273,10 +300,11 @@ public function convertIndexDescription(TableSchema $schema, $row)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function describeForeignKeySql($tableName, $config)
+ public function describeForeignKeySql(string $tableName, array $config): array
{
+ // phpcs:disable Generic.Files.LineLength
$sql = 'SELECT FK.[name] AS [foreign_key_name], FK.[delete_referential_action_desc] AS [delete_type],
FK.[update_referential_action_desc] AS [update_type], C.name AS [column], RT.name AS [reference_table],
RC.name AS [reference_column]
@@ -288,6 +316,7 @@ public function describeForeignKeySql($tableName, $config)
INNER JOIN sys.columns C ON C.column_id = FKC.parent_column_id AND C.object_id = FKC.parent_object_id
INNER JOIN sys.columns RC ON RC.column_id = FKC.referenced_column_id AND RC.object_id = FKC.referenced_object_id
WHERE FK.is_ms_shipped = 0 AND T.name = ? AND S.name = ?';
+ // phpcs:enable Generic.Files.LineLength
$schema = empty($config['schema']) ? static::DEFAULT_SCHEMA_NAME : $config['schema'];
@@ -295,9 +324,9 @@ public function describeForeignKeySql($tableName, $config)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function convertForeignKeyDescription(TableSchema $schema, $row)
+ public function convertForeignKeyDescription(TableSchema $schema, array $row): void
{
$data = [
'type' => TableSchema::CONSTRAINT_FOREIGN,
@@ -311,9 +340,9 @@ public function convertForeignKeyDescription(TableSchema $schema, $row)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- protected function _foreignOnClause($on)
+ protected function _foreignOnClause(string $on): string
{
$parent = parent::_foreignOnClause($on);
@@ -321,9 +350,9 @@ protected function _foreignOnClause($on)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- protected function _convertOnClause($clause)
+ protected function _convertOnClause(string $clause): string
{
switch ($clause) {
case 'NO_ACTION':
@@ -340,10 +369,11 @@ protected function _convertOnClause($clause)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function columnSql(TableSchema $schema, $name)
+ public function columnSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getColumn($name);
$out = $this->_driver->quoteIdentifier($name);
$typeMap = [
@@ -353,12 +383,16 @@ public function columnSql(TableSchema $schema, $name)
TableSchema::TYPE_BIGINTEGER => ' BIGINT',
TableSchema::TYPE_BINARY_UUID => ' UNIQUEIDENTIFIER',
TableSchema::TYPE_BOOLEAN => ' BIT',
+ TableSchema::TYPE_CHAR => ' NCHAR',
TableSchema::TYPE_FLOAT => ' FLOAT',
TableSchema::TYPE_DECIMAL => ' DECIMAL',
TableSchema::TYPE_DATE => ' DATE',
TableSchema::TYPE_TIME => ' TIME',
- TableSchema::TYPE_DATETIME => ' DATETIME',
- TableSchema::TYPE_TIMESTAMP => ' DATETIME',
+ TableSchema::TYPE_DATETIME => ' DATETIME2',
+ TableSchema::TYPE_DATETIME_FRACTIONAL => ' DATETIME2',
+ TableSchema::TYPE_TIMESTAMP => ' DATETIME2',
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL => ' DATETIME2',
+ TableSchema::TYPE_TIMESTAMP_TIMEZONE => ' DATETIME2',
TableSchema::TYPE_UUID => ' UNIQUEIDENTIFIER',
TableSchema::TYPE_JSON => ' NVARCHAR(MAX)',
];
@@ -368,7 +402,7 @@ public function columnSql(TableSchema $schema, $name)
}
if ($data['type'] === TableSchema::TYPE_INTEGER || $data['type'] === TableSchema::TYPE_BIGINTEGER) {
- if ([$name] === $schema->primaryKey() || $data['autoIncrement'] === true) {
+ if ($schema->getPrimaryKey() === [$name] || $data['autoIncrement'] === true) {
unset($data['null'], $data['default']);
$out .= ' IDENTITY(1, 1)';
}
@@ -378,6 +412,10 @@ public function columnSql(TableSchema $schema, $name)
$out .= ' NVARCHAR(MAX)';
}
+ if ($data['type'] === TableSchema::TYPE_CHAR) {
+ $out .= '(' . $data['length'] . ')';
+ }
+
if ($data['type'] === TableSchema::TYPE_BINARY) {
if (
!isset($data['length'])
@@ -397,33 +435,38 @@ public function columnSql(TableSchema $schema, $name)
if (
$data['type'] === TableSchema::TYPE_STRING ||
- ($data['type'] === TableSchema::TYPE_TEXT && $data['length'] === TableSchema::LENGTH_TINY)
+ (
+ $data['type'] === TableSchema::TYPE_TEXT &&
+ $data['length'] === TableSchema::LENGTH_TINY
+ )
) {
$type = ' NVARCHAR';
-
- if (!empty($data['fixed'])) {
- $type = ' NCHAR';
- }
-
- if (!isset($data['length'])) {
- $data['length'] = 255;
- }
-
- $out .= sprintf('%s(%d)', $type, $data['length']);
+ $length = $data['length'] ?? TableSchema::LENGTH_TINY;
+ $out .= sprintf('%s(%d)', $type, $length);
}
- $hasCollate = [TableSchema::TYPE_TEXT, TableSchema::TYPE_STRING];
+ $hasCollate = [TableSchema::TYPE_TEXT, TableSchema::TYPE_STRING, TableSchema::TYPE_CHAR];
if (in_array($data['type'], $hasCollate, true) && isset($data['collate']) && $data['collate'] !== '') {
$out .= ' COLLATE ' . $data['collate'];
}
- if ($data['type'] === TableSchema::TYPE_FLOAT && isset($data['precision'])) {
+ $precisionTypes = [
+ TableSchema::TYPE_FLOAT,
+ TableSchema::TYPE_DATETIME,
+ TableSchema::TYPE_DATETIME_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP,
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL,
+ ];
+ if (in_array($data['type'], $precisionTypes, true) && isset($data['precision'])) {
$out .= '(' . (int)$data['precision'] . ')';
}
if (
$data['type'] === TableSchema::TYPE_DECIMAL &&
- (isset($data['length']) || isset($data['precision']))
+ (
+ isset($data['length']) ||
+ isset($data['precision'])
+ )
) {
$out .= '(' . (int)$data['length'] . ',' . (int)$data['precision'] . ')';
}
@@ -432,14 +475,30 @@ public function columnSql(TableSchema $schema, $name)
$out .= ' NOT NULL';
}
+ $dateTimeTypes = [
+ TableSchema::TYPE_DATETIME,
+ TableSchema::TYPE_DATETIME_FRACTIONAL,
+ TableSchema::TYPE_TIMESTAMP,
+ TableSchema::TYPE_TIMESTAMP_FRACTIONAL,
+ ];
+ $dateTimeDefaults = [
+ 'current_timestamp',
+ 'getdate()',
+ 'getutcdate()',
+ 'sysdatetime()',
+ 'sysutcdatetime()',
+ 'sysdatetimeoffset()',
+ ];
if (
isset($data['default']) &&
- in_array($data['type'], [TableSchema::TYPE_TIMESTAMP, TableSchema::TYPE_DATETIME]) &&
- strtolower($data['default']) === 'current_timestamp'
+ in_array($data['type'], $dateTimeTypes, true) &&
+ in_array(strtolower($data['default']), $dateTimeDefaults, true)
) {
- $out .= ' DEFAULT CURRENT_TIMESTAMP';
+ $out .= ' DEFAULT ' . strtoupper($data['default']);
} elseif (isset($data['default'])) {
- $default = is_bool($data['default']) ? (int)$data['default'] : $this->_driver->schemaValue($data['default']);
+ $default = is_bool($data['default'])
+ ? (int)$data['default']
+ : $this->_driver->schemaValue($data['default']);
$out .= ' DEFAULT ' . $default;
} elseif (isset($data['null']) && $data['null'] !== false) {
$out .= ' DEFAULT NULL';
@@ -449,14 +508,15 @@ public function columnSql(TableSchema $schema, $name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function addConstraintSql(TableSchema $schema)
+ public function addConstraintSql(TableSchema $schema): array
{
$sqlPattern = 'ALTER TABLE %s ADD %s;';
$sql = [];
foreach ($schema->constraints() as $name) {
+ /** @var array $constraint */
$constraint = $schema->getConstraint($name);
if ($constraint['type'] === TableSchema::CONSTRAINT_FOREIGN) {
$tableName = $this->_driver->quoteIdentifier($schema->name());
@@ -468,14 +528,15 @@ public function addConstraintSql(TableSchema $schema)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function dropConstraintSql(TableSchema $schema)
+ public function dropConstraintSql(TableSchema $schema): array
{
$sqlPattern = 'ALTER TABLE %s DROP CONSTRAINT %s;';
$sql = [];
foreach ($schema->constraints() as $name) {
+ /** @var array $constraint */
$constraint = $schema->getConstraint($name);
if ($constraint['type'] === TableSchema::CONSTRAINT_FOREIGN) {
$tableName = $this->_driver->quoteIdentifier($schema->name());
@@ -488,10 +549,11 @@ public function dropConstraintSql(TableSchema $schema)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function indexSql(TableSchema $schema, $name)
+ public function indexSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getIndex($name);
$columns = array_map(
[$this->_driver, 'quoteIdentifier'],
@@ -507,10 +569,11 @@ public function indexSql(TableSchema $schema, $name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function constraintSql(TableSchema $schema, $name)
+ public function constraintSql(TableSchema $schema, string $name): string
{
+ /** @var array $data */
$data = $schema->getConstraint($name);
$out = 'CONSTRAINT ' . $this->_driver->quoteIdentifier($name);
if ($data['type'] === TableSchema::CONSTRAINT_PRIMARY) {
@@ -530,7 +593,7 @@ public function constraintSql(TableSchema $schema, $name)
* @param array $data Key data.
* @return string
*/
- protected function _keySql($prefix, $data)
+ protected function _keySql(string $prefix, array $data): string
{
$columns = array_map(
[$this->_driver, 'quoteIdentifier'],
@@ -551,9 +614,9 @@ protected function _keySql($prefix, $data)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function createTableSql(TableSchema $schema, $columns, $constraints, $indexes)
+ public function createTableSql(TableSchema $schema, array $columns, array $constraints, array $indexes): array
{
$content = array_merge($columns, $constraints);
$content = implode(",\n", array_filter($content));
@@ -568,9 +631,9 @@ public function createTableSql(TableSchema $schema, $columns, $constraints, $ind
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function truncateTableSql(TableSchema $schema)
+ public function truncateTableSql(TableSchema $schema): array
{
$name = $this->_driver->quoteIdentifier($schema->name());
$queries = [
@@ -578,8 +641,9 @@ public function truncateTableSql(TableSchema $schema)
];
// Restart identity sequences
- $pk = $schema->primaryKey();
+ $pk = $schema->getPrimaryKey();
if (count($pk) === 1) {
+ /** @var array $column */
$column = $schema->getColumn($pk[0]);
if (in_array($column['type'], ['integer', 'biginteger'])) {
$queries[] = sprintf(
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/Table.php b/app/vendor/cakephp/cakephp/src/Database/Schema/Table.php
deleted file mode 100644
index 8304e75fc..000000000
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/Table.php
+++ /dev/null
@@ -1,4 +0,0 @@
- [
- 'fixed' => null,
+ 'collate' => null,
+ ],
+ 'char' => [
'collate' => null,
],
'text' => [
@@ -217,70 +221,70 @@ class TableSchema implements TableSchemaInterface, SqlGeneratorInterface
*
* @var string
*/
- const CONSTRAINT_PRIMARY = 'primary';
+ public const CONSTRAINT_PRIMARY = 'primary';
/**
* Unique constraint type
*
* @var string
*/
- const CONSTRAINT_UNIQUE = 'unique';
+ public const CONSTRAINT_UNIQUE = 'unique';
/**
* Foreign constraint type
*
* @var string
*/
- const CONSTRAINT_FOREIGN = 'foreign';
+ public const CONSTRAINT_FOREIGN = 'foreign';
/**
* Index - index type
*
* @var string
*/
- const INDEX_INDEX = 'index';
+ public const INDEX_INDEX = 'index';
/**
* Fulltext index type
*
* @var string
*/
- const INDEX_FULLTEXT = 'fulltext';
+ public const INDEX_FULLTEXT = 'fulltext';
/**
* Foreign key cascade action
*
* @var string
*/
- const ACTION_CASCADE = 'cascade';
+ public const ACTION_CASCADE = 'cascade';
/**
* Foreign key set null action
*
* @var string
*/
- const ACTION_SET_NULL = 'setNull';
+ public const ACTION_SET_NULL = 'setNull';
/**
* Foreign key no action
*
* @var string
*/
- const ACTION_NO_ACTION = 'noAction';
+ public const ACTION_NO_ACTION = 'noAction';
/**
* Foreign key restrict action
*
* @var string
*/
- const ACTION_RESTRICT = 'restrict';
+ public const ACTION_RESTRICT = 'restrict';
/**
* Foreign key restrict default
*
* @var string
*/
- const ACTION_SET_DEFAULT = 'setDefault';
+ public const ACTION_SET_DEFAULT = 'setDefault';
/**
* Constructor.
@@ -288,7 +292,7 @@ class TableSchema implements TableSchemaInterface, SqlGeneratorInterface
* @param string $table The table name.
* @param array $columns The list of columns for the schema.
*/
- public function __construct($table, array $columns = [])
+ public function __construct(string $table, array $columns = [])
{
$this->_table = $table;
foreach ($columns as $field => $definition) {
@@ -297,17 +301,17 @@ public function __construct($table, array $columns = [])
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function name()
+ public function name(): string
{
return $this->_table;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function addColumn($name, $attrs)
+ public function addColumn(string $name, $attrs)
{
if (is_string($attrs)) {
$attrs = ['type' => $attrs];
@@ -324,9 +328,9 @@ public function addColumn($name, $attrs)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function removeColumn($name)
+ public function removeColumn(string $name)
{
unset($this->_columns[$name], $this->_typeMap[$name]);
@@ -334,31 +338,17 @@ public function removeColumn($name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function columns()
+ public function columns(): array
{
return array_keys($this->_columns);
}
/**
- * Get column data in the table.
- *
- * @param string $name The column name.
- * @return array|null Column data or null.
- * @deprecated 3.5.0 Use getColumn() instead.
+ * @inheritDoc
*/
- public function column($name)
- {
- deprecationWarning('TableSchema::column() is deprecated. Use TableSchema::getColumn() instead.');
-
- return $this->getColumn($name);
- }
-
- /**
- * {@inheritDoc}
- */
- public function getColumn($name)
+ public function getColumn(string $name): ?array
{
if (!isset($this->_columns[$name])) {
return null;
@@ -370,29 +360,9 @@ public function getColumn($name)
}
/**
- * Sets the type of a column, or returns its current type
- * if none is passed.
- *
- * @param string $name The column to get the type of.
- * @param string|null $type The type to set the column to.
- * @return string|null Either the column type or null.
- * @deprecated 3.5.0 Use setColumnType()/getColumnType() instead.
+ * @inheritDoc
*/
- public function columnType($name, $type = null)
- {
- deprecationWarning('TableSchema::columnType() is deprecated. Use TableSchema::setColumnType() or TableSchema::getColumnType() instead.');
-
- if ($type !== null) {
- $this->setColumnType($name, $type);
- }
-
- return $this->getColumnType($name);
- }
-
- /**
- * {@inheritDoc}
- */
- public function getColumnType($name)
+ public function getColumnType(string $name): ?string
{
if (!isset($this->_columns[$name])) {
return null;
@@ -402,9 +372,9 @@ public function getColumnType($name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function setColumnType($name, $type)
+ public function setColumnType(string $name, string $type)
{
if (!isset($this->_columns[$name])) {
return $this;
@@ -417,17 +387,17 @@ public function setColumnType($name, $type)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function hasColumn($name)
+ public function hasColumn(string $name): bool
{
return isset($this->_columns[$name]);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function baseColumnType($column)
+ public function baseColumnType(string $column): ?string
{
if (isset($this->_columns[$column]['baseType'])) {
return $this->_columns[$column]['baseType'];
@@ -439,37 +409,37 @@ public function baseColumnType($column)
return null;
}
- if (Type::getMap($type)) {
- $type = Type::build($type)->getBaseType();
+ if (TypeFactory::getMap($type)) {
+ $type = TypeFactory::build($type)->getBaseType();
}
return $this->_columns[$column]['baseType'] = $type;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function typeMap()
+ public function typeMap(): array
{
return $this->_typeMap;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function isNullable($name)
+ public function isNullable(string $name): bool
{
if (!isset($this->_columns[$name])) {
return true;
}
- return ($this->_columns[$name]['null'] === true);
+ return $this->_columns[$name]['null'] === true;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function defaultValues()
+ public function defaultValues(): array
{
$defaults = [];
foreach ($this->_columns as $name => $data) {
@@ -486,11 +456,9 @@ public function defaultValues()
}
/**
- * {@inheritDoc}
- *
- * @throws \Cake\Database\Exception
+ * @inheritDoc
*/
- public function addIndex($name, $attrs)
+ public function addIndex(string $name, $attrs)
{
if (is_string($attrs)) {
$attrs = ['type' => $attrs];
@@ -500,10 +468,19 @@ public function addIndex($name, $attrs)
unset($attrs['references'], $attrs['update'], $attrs['delete']);
if (!in_array($attrs['type'], static::$_validIndexTypes, true)) {
- throw new Exception(sprintf('Invalid index type "%s" in index "%s" in table "%s".', $attrs['type'], $name, $this->_table));
+ throw new Exception(sprintf(
+ 'Invalid index type "%s" in index "%s" in table "%s".',
+ $attrs['type'],
+ $name,
+ $this->_table
+ ));
}
if (empty($attrs['columns'])) {
- throw new Exception(sprintf('Index "%s" in table "%s" must have at least one column.', $name, $this->_table));
+ throw new Exception(sprintf(
+ 'Index "%s" in table "%s" must have at least one column.',
+ $name,
+ $this->_table
+ ));
}
$attrs['columns'] = (array)$attrs['columns'];
foreach ($attrs['columns'] as $field) {
@@ -524,45 +501,43 @@ public function addIndex($name, $attrs)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function indexes()
+ public function indexes(): array
{
return array_keys($this->_indexes);
}
/**
- * Read information about an index based on name.
- *
- * @param string $name The name of the index.
- * @return array|null Array of index data, or null
- * @deprecated 3.5.0 Use getIndex() instead.
+ * @inheritDoc
*/
- public function index($name)
+ public function getIndex(string $name): ?array
{
- deprecationWarning('TableSchema::index() is deprecated. Use TableSchema::getIndex() instead.');
+ if (!isset($this->_indexes[$name])) {
+ return null;
+ }
- return $this->getIndex($name);
+ return $this->_indexes[$name];
}
/**
- * {@inheritDoc}
+ * Get the column(s) used for the primary key.
+ *
+ * @return array Column name(s) for the primary key. An
+ * empty list will be returned when the table has no primary key.
+ * @deprecated 4.0.0 Renamed to {@link getPrimaryKey()}.
*/
- public function getIndex($name)
+ public function primaryKey(): array
{
- if (!isset($this->_indexes[$name])) {
- return null;
- }
-
- return $this->_indexes[$name];
+ return $this->getPrimarykey();
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function primaryKey()
+ public function getPrimaryKey(): array
{
- foreach ($this->_constraints as $name => $data) {
+ foreach ($this->_constraints as $data) {
if ($data['type'] === static::CONSTRAINT_PRIMARY) {
return $data['columns'];
}
@@ -572,11 +547,9 @@ public function primaryKey()
}
/**
- * {@inheritDoc}
- *
- * @throws \Cake\Database\Exception
+ * @inheritDoc
*/
- public function addConstraint($name, $attrs)
+ public function addConstraint(string $name, $attrs)
{
if (is_string($attrs)) {
$attrs = ['type' => $attrs];
@@ -630,9 +603,9 @@ public function addConstraint($name, $attrs)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function dropConstraint($name)
+ public function dropConstraint(string $name)
{
if (isset($this->_constraints[$name])) {
unset($this->_constraints[$name]);
@@ -646,7 +619,7 @@ public function dropConstraint($name)
*
* @return bool
*/
- public function hasAutoincrement()
+ public function hasAutoincrement(): bool
{
foreach ($this->_columns as $column) {
if (isset($column['autoIncrement']) && $column['autoIncrement']) {
@@ -664,47 +637,39 @@ public function hasAutoincrement()
* @return array
* @throws \Cake\Database\Exception When foreign key definition is not valid.
*/
- protected function _checkForeignKey($attrs)
+ protected function _checkForeignKey(array $attrs): array
{
if (count($attrs['references']) < 2) {
throw new Exception('References must contain a table and column.');
}
if (!in_array($attrs['update'], static::$_validForeignKeyActions)) {
- throw new Exception(sprintf('Update action is invalid. Must be one of %s', implode(',', static::$_validForeignKeyActions)));
+ throw new Exception(sprintf(
+ 'Update action is invalid. Must be one of %s',
+ implode(',', static::$_validForeignKeyActions)
+ ));
}
if (!in_array($attrs['delete'], static::$_validForeignKeyActions)) {
- throw new Exception(sprintf('Delete action is invalid. Must be one of %s', implode(',', static::$_validForeignKeyActions)));
+ throw new Exception(sprintf(
+ 'Delete action is invalid. Must be one of %s',
+ implode(',', static::$_validForeignKeyActions)
+ ));
}
return $attrs;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function constraints()
+ public function constraints(): array
{
return array_keys($this->_constraints);
}
/**
- * Read information about a constraint based on name.
- *
- * @param string $name The name of the constraint.
- * @return array|null Array of constraint data, or null
- * @deprecated 3.5.0 Use getConstraint() instead.
+ * @inheritDoc
*/
- public function constraint($name)
- {
- deprecationWarning('TableSchema::constraint() is deprecated. Use TableSchema::getConstraint() instead.');
-
- return $this->getConstraint($name);
- }
-
- /**
- * {@inheritDoc}
- */
- public function getConstraint($name)
+ public function getConstraint(string $name): ?array
{
if (!isset($this->_constraints[$name])) {
return null;
@@ -714,9 +679,9 @@ public function getConstraint($name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function setOptions($options)
+ public function setOptions(array $options)
{
$this->_options = array_merge($this->_options, $options);
@@ -724,38 +689,17 @@ public function setOptions($options)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getOptions()
+ public function getOptions(): array
{
return $this->_options;
}
/**
- * Get/set the options for a table.
- *
- * Table options allow you to set platform specific table level options.
- * For example the engine type in MySQL.
- *
- * @deprecated 3.4.0 Use setOptions()/getOptions() instead.
- * @param array|null $options The options to set, or null to read options.
- * @return $this|array Either the TableSchema instance, or an array of options when reading.
+ * @inheritDoc
*/
- public function options($options = null)
- {
- deprecationWarning('TableSchema::options() is deprecated. Use TableSchema::setOptions() or TableSchema::getOptions() instead.');
-
- if ($options !== null) {
- return $this->setOptions($options);
- }
-
- return $this->getOptions();
- }
-
- /**
- * {@inheritDoc}
- */
- public function setTemporary($temporary)
+ public function setTemporary(bool $temporary)
{
$this->_temporary = (bool)$temporary;
@@ -763,37 +707,17 @@ public function setTemporary($temporary)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function isTemporary()
+ public function isTemporary(): bool
{
return $this->_temporary;
}
/**
- * Get/Set whether the table is temporary in the database
- *
- * @deprecated 3.4.0 Use setTemporary()/isTemporary() instead.
- * @param bool|null $temporary whether or not the table is to be temporary
- * @return $this|bool Either the TableSchema instance, the current temporary setting
- */
- public function temporary($temporary = null)
- {
- deprecationWarning(
- 'TableSchema::temporary() is deprecated. ' .
- 'Use TableSchema::setTemporary()/isTemporary() instead.'
- );
- if ($temporary !== null) {
- return $this->setTemporary($temporary);
- }
-
- return $this->isTemporary();
- }
-
- /**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function createSql(Connection $connection)
+ public function createSql(Connection $connection): array
{
$dialect = $connection->getDriver()->schemaDialect();
$columns = $constraints = $indexes = [];
@@ -811,9 +735,9 @@ public function createSql(Connection $connection)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function dropSql(Connection $connection)
+ public function dropSql(Connection $connection): array
{
$dialect = $connection->getDriver()->schemaDialect();
@@ -821,9 +745,9 @@ public function dropSql(Connection $connection)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function truncateSql(Connection $connection)
+ public function truncateSql(Connection $connection): array
{
$dialect = $connection->getDriver()->schemaDialect();
@@ -831,9 +755,9 @@ public function truncateSql(Connection $connection)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function addConstraintSql(Connection $connection)
+ public function addConstraintSql(Connection $connection): array
{
$dialect = $connection->getDriver()->schemaDialect();
@@ -841,9 +765,9 @@ public function addConstraintSql(Connection $connection)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function dropConstraintSql(Connection $connection)
+ public function dropConstraintSql(Connection $connection): array
{
$dialect = $connection->getDriver()->schemaDialect();
@@ -855,7 +779,7 @@ public function dropConstraintSql(Connection $connection)
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
return [
'table' => $this->_table,
@@ -868,6 +792,3 @@ public function __debugInfo()
];
}
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Database\Schema\TableSchema', 'Cake\Database\Schema\Table');
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/TableSchemaAwareInterface.php b/app/vendor/cakephp/cakephp/src/Database/Schema/TableSchemaAwareInterface.php
index e5f5ff806..f08e363ba 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/TableSchemaAwareInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/TableSchemaAwareInterface.php
@@ -1,4 +1,6 @@
_schema = $this->getSchema($connection);
}
@@ -54,7 +53,7 @@ public function __construct($connection)
* @param string|null $name The name of the table to build cache data for.
* @return array Returns a list build table caches
*/
- public function build($name = null)
+ public function build(?string $name = null): array
{
$tables = [$name];
if (empty($name)) {
@@ -62,6 +61,7 @@ public function build($name = null)
}
foreach ($tables as $table) {
+ /** @psalm-suppress PossiblyNullArgument */
$this->_schema->describe($table, ['forceRefresh' => true]);
}
@@ -74,17 +74,19 @@ public function build($name = null)
* @param string|null $name The name of the table to clear cache data for.
* @return array Returns a list of cleared table caches
*/
- public function clear($name = null)
+ public function clear(?string $name = null): array
{
$tables = [$name];
if (empty($name)) {
$tables = $this->_schema->listTables();
}
- $configName = $this->_schema->getCacheMetadata();
+
+ $cacher = $this->_schema->getCacher();
foreach ($tables as $table) {
+ /** @psalm-suppress PossiblyNullArgument */
$key = $this->_schema->cacheKey($table);
- Cache::delete($key, $configName);
+ $cacher->delete($key);
}
return $tables;
@@ -94,21 +96,19 @@ public function clear($name = null)
* Helper method to get the schema collection.
*
* @param \Cake\Database\Connection $connection Connection object
- * @return \Cake\Database\Schema\Collection|\Cake\Database\Schema\CachedCollection
+ * @return \Cake\Database\Schema\CachedCollection
* @throws \RuntimeException If given connection object is not compatible with schema caching
*/
- public function getSchema(Connection $connection)
+ public function getSchema(Connection $connection): CachedCollection
{
- if (!method_exists($connection, 'schemaCollection')) {
- throw new RuntimeException('The given connection object is not compatible with schema caching, as it does not implement a "schemaCollection()" method.');
- }
-
$config = $connection->config();
if (empty($config['cacheMetadata'])) {
- Log::info(sprintf('Metadata cache was disabled in config for `%s`. Enabling to clear cache.', $connection->configName()));
$connection->cacheMetadata(true);
}
- return $connection->getSchemaCollection();
+ /** @var \Cake\Database\Schema\CachedCollection $schemaCollection */
+ $schemaCollection = $connection->getSchemaCollection();
+
+ return $schemaCollection;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/SqlDialectTrait.php b/app/vendor/cakephp/cakephp/src/Database/SqlDialectTrait.php
index c0eda4f9d..f5800a667 100644
--- a/app/vendor/cakephp/cakephp/src/Database/SqlDialectTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/SqlDialectTrait.php
@@ -1,4 +1,6 @@
isAutoQuotingEnabled()) {
@@ -102,7 +106,7 @@ public function queryTranslator($type)
return $query;
}
- $query->traverseExpressions(function ($expression) use ($translators, $query) {
+ $query->traverseExpressions(function ($expression) use ($translators, $query): void {
foreach ($translators as $class => $method) {
if ($expression instanceof $class) {
$this->{$method}($expression, $query);
@@ -121,7 +125,7 @@ public function queryTranslator($type)
*
* @return array
*/
- protected function _expressionTranslators()
+ protected function _expressionTranslators(): array
{
return [];
}
@@ -132,7 +136,7 @@ protected function _expressionTranslators()
* @param \Cake\Database\Query $query The query to translate
* @return \Cake\Database\Query The modified query
*/
- protected function _selectQueryTranslator($query)
+ protected function _selectQueryTranslator(Query $query): Query
{
return $this->_transformDistinct($query);
}
@@ -144,7 +148,7 @@ protected function _selectQueryTranslator($query)
* @param \Cake\Database\Query $query The query to be transformed
* @return \Cake\Database\Query
*/
- protected function _transformDistinct($query)
+ protected function _transformDistinct(Query $query): Query
{
if (is_array($query->clause('distinct'))) {
$query->group($query->clause('distinct'), true);
@@ -166,7 +170,7 @@ protected function _transformDistinct($query)
* @param \Cake\Database\Query $query The query to translate
* @return \Cake\Database\Query The modified query
*/
- protected function _deleteQueryTranslator($query)
+ protected function _deleteQueryTranslator(Query $query): Query
{
$hadAlias = false;
$tables = [];
@@ -198,7 +202,7 @@ protected function _deleteQueryTranslator($query)
* @param \Cake\Database\Query $query The query to translate
* @return \Cake\Database\Query The modified query
*/
- protected function _updateQueryTranslator($query)
+ protected function _updateQueryTranslator(Query $query): Query
{
return $this->_removeAliasesFromConditions($query);
}
@@ -211,10 +215,10 @@ protected function _updateQueryTranslator($query)
* @throws \RuntimeException In case the processed query contains any joins, as removing
* aliases from the conditions can break references to the joined tables.
*/
- protected function _removeAliasesFromConditions($query)
+ protected function _removeAliasesFromConditions(Query $query): Query
{
if ($query->clause('join')) {
- throw new \RuntimeException(
+ throw new RuntimeException(
'Aliases are being removed from conditions for UPDATE/DELETE queries, ' .
'this can break references to joined tables.'
);
@@ -229,7 +233,7 @@ protected function _removeAliasesFromConditions($query)
is_string($field) &&
strpos($field, '.') !== false
) {
- list(, $unaliasedField) = explode('.', $field, 2);
+ [, $unaliasedField] = explode('.', $field, 2);
$expression->setField($unaliasedField);
}
@@ -239,7 +243,7 @@ protected function _removeAliasesFromConditions($query)
if ($expression instanceof IdentifierExpression) {
$identifier = $expression->getIdentifier();
if (strpos($identifier, '.') !== false) {
- list(, $unaliasedIdentifier) = explode('.', $identifier, 2);
+ [, $unaliasedIdentifier] = explode('.', $identifier, 2);
$expression->setIdentifier($unaliasedIdentifier);
}
@@ -259,7 +263,7 @@ protected function _removeAliasesFromConditions($query)
* @param \Cake\Database\Query $query The query to translate
* @return \Cake\Database\Query The modified query
*/
- protected function _insertQueryTranslator($query)
+ protected function _insertQueryTranslator(Query $query): Query
{
return $query;
}
@@ -267,10 +271,10 @@ protected function _insertQueryTranslator($query)
/**
* Returns a SQL snippet for creating a new transaction savepoint
*
- * @param string $name save point name
+ * @param string|int $name save point name
* @return string
*/
- public function savePointSQL($name)
+ public function savePointSQL($name): string
{
return 'SAVEPOINT LEVEL' . $name;
}
@@ -278,10 +282,10 @@ public function savePointSQL($name)
/**
* Returns a SQL snippet for releasing a previously created save point
*
- * @param string $name save point name
+ * @param string|int $name save point name
* @return string
*/
- public function releaseSavePointSQL($name)
+ public function releaseSavePointSQL($name): string
{
return 'RELEASE SAVEPOINT LEVEL' . $name;
}
@@ -289,10 +293,10 @@ public function releaseSavePointSQL($name)
/**
* Returns a SQL snippet for rollbacking a previously created save point
*
- * @param string $name save point name
+ * @param string|int $name save point name
* @return string
*/
- public function rollbackSavePointSQL($name)
+ public function rollbackSavePointSQL($name): string
{
return 'ROLLBACK TO SAVEPOINT LEVEL' . $name;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/SqliteCompiler.php b/app/vendor/cakephp/cakephp/src/Database/SqliteCompiler.php
index 1c7fa949c..290fa27af 100644
--- a/app/vendor/cakephp/cakephp/src/Database/SqliteCompiler.php
+++ b/app/vendor/cakephp/cakephp/src/Database/SqliteCompiler.php
@@ -1,4 +1,6 @@
'DELETE',
@@ -43,7 +45,7 @@ class SqlserverCompiler extends QueryCompiler
];
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
protected $_selectParts = [
'select', 'from', 'join', 'where', 'group', 'having', 'order', 'offset',
@@ -62,7 +64,7 @@ class SqlserverCompiler extends QueryCompiler
* @param \Cake\Database\ValueBinder $generator the placeholder generator to be used in expressions
* @return string
*/
- protected function _buildInsertPart($parts, $query, $generator)
+ protected function _buildInsertPart(array $parts, Query $query, ValueBinder $generator): string
{
$table = $parts[0];
$columns = $this->_stringifyExpressions($parts[1], $generator);
@@ -83,9 +85,9 @@ protected function _buildInsertPart($parts, $query, $generator)
* @param \Cake\Database\Query $query The query that is being compiled
* @return string
*/
- protected function _buildLimitPart($limit, $query)
+ protected function _buildLimitPart(int $limit, Query $query): string
{
- if ($limit === null || $query->clause('offset') === null) {
+ if ($query->clause('offset') === null) {
return '';
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/BufferResultsTrait.php b/app/vendor/cakephp/cakephp/src/Database/Statement/BufferResultsTrait.php
index c0c8fc2ff..aa8554ff5 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/BufferResultsTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/BufferResultsTrait.php
@@ -1,4 +1,6 @@
_bufferResults = (bool)$buffer;
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/BufferedStatement.php b/app/vendor/cakephp/cakephp/src/Database/Statement/BufferedStatement.php
index 55b054e6e..d4a009094 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/BufferedStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/BufferedStatement.php
@@ -1,4 +1,6 @@
statement = $statement;
$this->_driver = $driver;
@@ -88,39 +91,40 @@ public function __construct(StatementInterface $statement, $driver)
* @param string $property internal property to get
* @return mixed
*/
- public function __get($property)
+ public function __get(string $property)
{
if ($property === 'queryString') {
+ /** @psalm-suppress NoInterfaceProperties */
return $this->statement->queryString;
}
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function bindValue($column, $value, $type = 'string')
+ public function bindValue($column, $value, $type = 'string'): void
{
$this->statement->bindValue($column, $value, $type);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function closeCursor()
+ public function closeCursor(): void
{
$this->statement->closeCursor();
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function columnCount()
+ public function columnCount(): int
{
return $this->statement->columnCount();
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function errorCode()
{
@@ -128,17 +132,17 @@ public function errorCode()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function errorInfo()
+ public function errorInfo(): array
{
return $this->statement->errorInfo();
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function execute($params = null)
+ public function execute(?array $params = null): bool
{
$this->_reset();
$this->_hasExecuted = true;
@@ -147,15 +151,12 @@ public function execute($params = null)
}
/**
- * Returns the value of the result at position.
- *
- * @param int $position The numeric position of the column to retrieve in the result
- * @return mixed Returns the specific value of the column designated at $position
+ * @inheritDoc
*/
- public function fetchColumn($position)
+ public function fetchColumn(int $position)
{
$result = $this->fetch(static::FETCH_TYPE_NUM);
- if (isset($result[$position])) {
+ if ($result !== false && isset($result[$position])) {
return $result[$position];
}
@@ -168,23 +169,23 @@ public function fetchColumn($position)
*
* @return int
*/
- public function count()
+ public function count(): int
{
return $this->rowCount();
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function bind($params, $types)
+ public function bind(array $params, array $types): void
{
$this->statement->bind($params, $types);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function lastInsertId($table = null, $column = null)
+ public function lastInsertId(?string $table = null, ?string $column = null)
{
return $this->statement->lastInsertId($table, $column);
}
@@ -224,9 +225,9 @@ public function fetch($type = self::FETCH_TYPE_NUM)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
- public function fetchAssoc()
+ public function fetchAssoc(): array
{
$result = $this->fetch(static::FETCH_TYPE_ASSOC);
@@ -234,10 +235,7 @@ public function fetchAssoc()
}
/**
- * {@inheritDoc}
- *
- * @param string $type The type to fetch.
- * @return array
+ * @inheritDoc
*/
public function fetchAll($type = self::FETCH_TYPE_NUM)
{
@@ -255,9 +253,9 @@ public function fetchAll($type = self::FETCH_TYPE_NUM)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function rowCount()
+ public function rowCount(): int
{
if (!$this->_allFetched) {
$this->fetchAll(static::FETCH_TYPE_ASSOC);
@@ -271,7 +269,7 @@ public function rowCount()
*
* @return void
*/
- protected function _reset()
+ protected function _reset(): void
{
$this->buffer = [];
$this->_allFetched = false;
@@ -303,7 +301,7 @@ public function current()
*
* @return void
*/
- public function rewind()
+ public function rewind(): void
{
$this->index = 0;
}
@@ -313,7 +311,7 @@ public function rewind()
*
* @return bool
*/
- public function valid()
+ public function valid(): bool
{
$old = $this->index;
$row = $this->fetch(self::FETCH_TYPE_ASSOC);
@@ -330,7 +328,7 @@ public function valid()
*
* @return void
*/
- public function next()
+ public function next(): void
{
$this->index += 1;
}
@@ -340,7 +338,7 @@ public function next()
*
* @return \Cake\Database\StatementInterface
*/
- public function getInnerStatement()
+ public function getInnerStatement(): StatementInterface
{
return $this->statement;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/CallbackStatement.php b/app/vendor/cakephp/cakephp/src/Database/Statement/CallbackStatement.php
index 714f05604..692a2aa26 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/CallbackStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/CallbackStatement.php
@@ -1,4 +1,6 @@
_callback = $callback;
@@ -66,8 +71,9 @@ public function fetch($type = parent::FETCH_TYPE_NUM)
* @param string|int $type Either 'num' or 'assoc' to indicate the result format you would like.
* @return array
*/
- public function fetchAll($type = parent::FETCH_TYPE_NUM)
+ public function fetchAll($type = parent::FETCH_TYPE_NUM): array
{
+ /** @psalm-suppress PossiblyFalseArgument */
return array_map($this->_callback, $this->_statement->fetchAll($type));
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/MysqlStatement.php b/app/vendor/cakephp/cakephp/src/Database/Statement/MysqlStatement.php
index dc3fcbbed..3efa15e8f 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/MysqlStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/MysqlStatement.php
@@ -1,4 +1,6 @@
_driver->getConnection();
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/PDOStatement.php b/app/vendor/cakephp/cakephp/src/Database/Statement/PDOStatement.php
index 83e25ac16..75e9abd7a 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/PDOStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/PDOStatement.php
@@ -1,4 +1,6 @@
_statement = $statement;
+ $this->_driver = $driver;
}
/**
@@ -56,16 +68,16 @@ public function __construct(Statement $statement = null, $driver = null)
*
* @param string|int $column name or param position to be bound
* @param mixed $value The value to bind to variable in query
- * @param string|int $type PDO type or name of configured Type class
+ * @param string|int|null $type PDO type or name of configured Type class
* @return void
*/
- public function bindValue($column, $value, $type = 'string')
+ public function bindValue($column, $value, $type = 'string'): void
{
if ($type === null) {
$type = 'string';
}
- if (!ctype_digit($type)) {
- list($value, $type) = $this->cast($value, $type);
+ if (!is_int($type)) {
+ [$value, $type] = $this->cast($value, $type);
}
$this->_statement->bindValue($column, $value, $type);
}
@@ -83,8 +95,8 @@ public function bindValue($column, $value, $type = 'string')
* print_r($statement->fetch('assoc')); // will show ['id' => 1, 'title' => 'a title']
* ```
*
- * @param string $type 'num' for positional columns, assoc for named columns
- * @return array|false Result array containing columns and values or false if no results
+ * @param string|int $type 'num' for positional columns, assoc for named columns
+ * @return mixed Result array containing columns and values or false if no results
* are left
*/
public function fetch($type = parent::FETCH_TYPE_NUM)
@@ -99,6 +111,13 @@ public function fetch($type = parent::FETCH_TYPE_NUM)
return $this->_statement->fetch(PDO::FETCH_OBJ);
}
+ if (!is_int($type)) {
+ throw new Exception(sprintf(
+ 'Fetch type for PDOStatement must be an integer, found `%s` instead',
+ getTypeName($type)
+ ));
+ }
+
return $this->_statement->fetch($type);
}
@@ -113,8 +132,9 @@ public function fetch($type = parent::FETCH_TYPE_NUM)
* print_r($statement->fetchAll('assoc')); // will show [0 => ['id' => 1, 'title' => 'a title']]
* ```
*
- * @param string $type num for fetching columns as positional keys or assoc for column names as keys
- * @return array list of all results from database for this statement
+ * @param string|int $type num for fetching columns as positional keys or assoc for column names as keys
+ * @return array|false list of all results from database for this statement, false on failure
+ * @psalm-assert string $type
*/
public function fetchAll($type = parent::FETCH_TYPE_NUM)
{
@@ -128,6 +148,13 @@ public function fetchAll($type = parent::FETCH_TYPE_NUM)
return $this->_statement->fetchAll(PDO::FETCH_OBJ);
}
+ if (!is_int($type)) {
+ throw new Exception(sprintf(
+ 'Fetch type for PDOStatement must be an integer, found `%s` instead',
+ getTypeName($type)
+ ));
+ }
+
return $this->_statement->fetchAll($type);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/SqliteStatement.php b/app/vendor/cakephp/cakephp/src/Database/Statement/SqliteStatement.php
index 8b9da2e7f..cc965a812 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/SqliteStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/SqliteStatement.php
@@ -1,4 +1,6 @@
_statement instanceof BufferedStatement) {
$this->_statement = $this->_statement->getInnerStatement();
@@ -44,15 +46,23 @@ public function execute($params = null)
*
* @return int
*/
- public function rowCount()
+ public function rowCount(): int
{
- if (preg_match('/^(?:DELETE|UPDATE|INSERT)/i', $this->_statement->queryString)) {
+ /** @psalm-suppress NoInterfaceProperties */
+ if (
+ $this->_statement->queryString &&
+ preg_match('/^(?:DELETE|UPDATE|INSERT)/i', $this->_statement->queryString)
+ ) {
$changes = $this->_driver->prepare('SELECT CHANGES()');
$changes->execute();
- $count = $changes->fetch()[0];
+ $row = $changes->fetch();
$changes->closeCursor();
- return (int)$count;
+ if (!$row) {
+ return 0;
+ }
+
+ return (int)$row[0];
}
return parent::rowCount();
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/SqlserverStatement.php b/app/vendor/cakephp/cakephp/src/Database/Statement/SqlserverStatement.php
index c18694edc..efd3b6a2c 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/SqlserverStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/SqlserverStatement.php
@@ -1,4 +1,6 @@
cast($value, $type);
+ if (!is_int($type)) {
+ [$value, $type] = $this->cast($value, $type);
}
- if ($type == PDO::PARAM_LOB) {
+ if ($type === PDO::PARAM_LOB) {
+ /** @psalm-suppress UndefinedConstant */
$this->_statement->bindParam($column, $value, $type, 0, PDO::SQLSRV_ENCODING_BINARY);
} else {
$this->_statement->bindValue($column, $value, $type);
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/StatementDecorator.php b/app/vendor/cakephp/cakephp/src/Database/Statement/StatementDecorator.php
index 9ae35c481..723034b62 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/StatementDecorator.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/StatementDecorator.php
@@ -1,4 +1,6 @@
_statement = $statement;
$this->_driver = $driver;
@@ -74,9 +78,10 @@ public function __construct($statement = null, $driver = null)
* @param string $property internal property to get
* @return mixed
*/
- public function __get($property)
+ public function __get(string $property)
{
if ($property === 'queryString') {
+ /** @psalm-suppress NoInterfaceProperties */
return $this->_statement->queryString;
}
}
@@ -98,10 +103,10 @@ public function __get($property)
*
* @param string|int $column name or param position to be bound
* @param mixed $value The value to bind to variable in query
- * @param string $type name of configured Type class
+ * @param string|int|null $type name of configured Type class
* @return void
*/
- public function bindValue($column, $value, $type = 'string')
+ public function bindValue($column, $value, $type = 'string'): void
{
$this->_statement->bindValue($column, $value, $type);
}
@@ -113,7 +118,7 @@ public function bindValue($column, $value, $type = 'string')
*
* @return void
*/
- public function closeCursor()
+ public function closeCursor(): void
{
$this->_statement->closeCursor();
}
@@ -131,7 +136,7 @@ public function closeCursor()
*
* @return int
*/
- public function columnCount()
+ public function columnCount(): int
{
return $this->_statement->columnCount();
}
@@ -152,7 +157,7 @@ public function errorCode()
*
* @return array
*/
- public function errorInfo()
+ public function errorInfo(): array
{
return $this->_statement->errorInfo();
}
@@ -166,7 +171,7 @@ public function errorInfo()
* @param array|null $params list of values to be bound to query
* @return bool true on success, false otherwise
*/
- public function execute($params = null)
+ public function execute(?array $params = null): bool
{
$this->_hasExecuted = true;
@@ -186,8 +191,8 @@ public function execute($params = null)
* print_r($statement->fetch('assoc')); // will show ['id' => 1, 'title' => 'a title']
* ```
*
- * @param string $type 'num' for positional columns, assoc for named columns
- * @return array|false Result array containing columns and values or false if no results
+ * @param string|int $type 'num' for positional columns, assoc for named columns
+ * @return mixed Result array containing columns and values or false if no results
* are left
*/
public function fetch($type = self::FETCH_TYPE_NUM)
@@ -201,7 +206,7 @@ public function fetch($type = self::FETCH_TYPE_NUM)
*
* @return array Result array containing columns and values an an associative array or an empty array if no results
*/
- public function fetchAssoc()
+ public function fetchAssoc(): array
{
$result = $this->fetch(static::FETCH_TYPE_ASSOC);
@@ -214,10 +219,10 @@ public function fetchAssoc()
* @param int $position The numeric position of the column to retrieve in the result
* @return mixed Returns the specific value of the column designated at $position
*/
- public function fetchColumn($position)
+ public function fetchColumn(int $position)
{
$result = $this->fetch(static::FETCH_TYPE_NUM);
- if (isset($result[$position])) {
+ if ($result && isset($result[$position])) {
return $result[$position];
}
@@ -235,8 +240,8 @@ public function fetchColumn($position)
* print_r($statement->fetchAll('assoc')); // will show [0 => ['id' => 1, 'title' => 'a title']]
* ```
*
- * @param string $type num for fetching columns as positional keys or assoc for column names as keys
- * @return array List of all results from database for this statement
+ * @param string|int $type num for fetching columns as positional keys or assoc for column names as keys
+ * @return array|false List of all results from database for this statement. False on failure.
*/
public function fetchAll($type = self::FETCH_TYPE_NUM)
{
@@ -256,7 +261,7 @@ public function fetchAll($type = self::FETCH_TYPE_NUM)
*
* @return int
*/
- public function rowCount()
+ public function rowCount(): int
{
return $this->_statement->rowCount();
}
@@ -274,7 +279,8 @@ public function rowCount()
* }
* ```
*
- * @return \Cake\Database\StatementInterface|\PDOStatement
+ * @return \Cake\Database\StatementInterface
+ * @psalm-suppress ImplementedReturnTypeMismatch
*/
public function getIterator()
{
@@ -291,7 +297,7 @@ public function getIterator()
*
* @return int
*/
- public function count()
+ public function count(): int
{
return $this->rowCount();
}
@@ -303,7 +309,7 @@ public function count()
* @param array $types list of types to be used, keys should match those in $params
* @return void
*/
- public function bind($params, $types)
+ public function bind(array $params, array $types): void
{
if (empty($params)) {
return;
@@ -317,6 +323,7 @@ public function bind($params, $types)
$type = $types[$index];
}
if ($anonymousParams) {
+ /** @psalm-suppress InvalidOperand */
$index += $offset;
}
$this->bindValue($index, $value, $type);
@@ -330,14 +337,14 @@ public function bind($params, $types)
* @param string|null $column the name of the column representing the primary key
* @return string|int
*/
- public function lastInsertId($table = null, $column = null)
+ public function lastInsertId(?string $table = null, ?string $column = null)
{
- $row = null;
if ($column && $this->columnCount()) {
$row = $this->fetch(static::FETCH_TYPE_ASSOC);
- }
- if (isset($row[$column])) {
- return $row[$column];
+
+ if ($row && isset($row[$column])) {
+ return $row[$column];
+ }
}
return $this->_driver->lastInsertId($table, $column);
@@ -346,7 +353,7 @@ public function lastInsertId($table = null, $column = null)
/**
* Returns the statement object that was decorated by this class.
*
- * @return \Cake\Database\StatementInterface|\PDOStatement
+ * @return \Cake\Database\StatementInterface
*/
public function getInnerStatement()
{
diff --git a/app/vendor/cakephp/cakephp/src/Database/StatementInterface.php b/app/vendor/cakephp/cakephp/src/Database/StatementInterface.php
index eddb3a6c2..0c0dc5f86 100644
--- a/app/vendor/cakephp/cakephp/src/Database/StatementInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/StatementInterface.php
@@ -1,4 +1,6 @@
fetch('assoc')); // will show ['id' => 1, 'title' => 'a title']
* ```
*
- * @param string $type 'num' for positional columns, assoc for named columns
- * @return array|false Result array containing columns and values or false if no results
+ * @param string|int $type 'num' for positional columns, assoc for named columns, or PDO fetch mode constants.
+ * @return mixed Result array containing columns and values or false if no results
* are left
*/
public function fetch($type = 'num');
@@ -145,11 +147,19 @@ public function fetch($type = 'num');
* print_r($statement->fetchAll('assoc')); // will show [0 => ['id' => 1, 'title' => 'a title']]
* ```
*
- * @param string $type num for fetching columns as positional keys or assoc for column names as keys
- * @return array list of all results from database for this statement
+ * @param string|int $type num for fetching columns as positional keys or assoc for column names as keys
+ * @return array|false list of all results from database for this statement or false on failure.
*/
public function fetchAll($type = 'num');
+ /**
+ * Returns the value of the result at position.
+ *
+ * @param int $position The numeric position of the column to retrieve in the result
+ * @return mixed Returns the specific value of the column designated at $position
+ */
+ public function fetchColumn(int $position);
+
/**
* Returns the number of rows affected by this SQL statement
*
@@ -163,7 +173,7 @@ public function fetchAll($type = 'num');
*
* @return int
*/
- public function rowCount();
+ public function rowCount(): int;
/**
* Statements can be passed as argument for count()
@@ -171,7 +181,7 @@ public function rowCount();
*
* @return int
*/
- public function count();
+ public function count(): int;
/**
* Binds a set of values to statement object with corresponding type
@@ -180,14 +190,14 @@ public function count();
* @param array $types list of types to be used, keys should match those in $params
* @return void
*/
- public function bind($params, $types);
+ public function bind(array $params, array $types): void;
/**
* Returns the latest primary inserted using this statement
*
* @param string|null $table table name or sequence to get last insert value from
* @param string|null $column the name of the column representing the primary key
- * @return string
+ * @return string|int
*/
- public function lastInsertId($table = null, $column = null);
+ public function lastInsertId(?string $table = null, ?string $column = null);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type.php b/app/vendor/cakephp/cakephp/src/Database/Type.php
index 7bfbb4ba5..466b8d597 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type.php
@@ -1,381 +1,5 @@
'Cake\Database\Type\IntegerType',
- 'smallinteger' => 'Cake\Database\Type\IntegerType',
- 'integer' => 'Cake\Database\Type\IntegerType',
- 'biginteger' => 'Cake\Database\Type\IntegerType',
- 'binary' => 'Cake\Database\Type\BinaryType',
- 'binaryuuid' => 'Cake\Database\Type\BinaryUuidType',
- 'boolean' => 'Cake\Database\Type\BoolType',
- 'date' => 'Cake\Database\Type\DateType',
- 'datetime' => 'Cake\Database\Type\DateTimeType',
- 'decimal' => 'Cake\Database\Type\DecimalType',
- 'float' => 'Cake\Database\Type\FloatType',
- 'json' => 'Cake\Database\Type\JsonType',
- 'string' => 'Cake\Database\Type\StringType',
- 'text' => 'Cake\Database\Type\StringType',
- 'time' => 'Cake\Database\Type\TimeType',
- 'timestamp' => 'Cake\Database\Type\DateTimeType',
- 'uuid' => 'Cake\Database\Type\UuidType',
- ];
-
- /**
- * List of basic type mappings, used to avoid having to instantiate a class
- * for doing conversion on these.
- *
- * @var array
- * @deprecated 3.1 All types will now use a specific class
- */
- protected static $_basicTypes = [
- 'string' => ['callback' => [Type::class, 'strval']],
- 'text' => ['callback' => [Type::class, 'strval']],
- 'boolean' => [
- 'callback' => [Type::class, 'boolval'],
- 'pdo' => PDO::PARAM_BOOL,
- ],
- ];
-
- /**
- * Contains a map of type object instances to be reused if needed.
- *
- * @var \Cake\Database\Type[]
- */
- protected static $_builtTypes = [];
-
- /**
- * Identifier name for this type
- *
- * @var string|null
- */
- protected $_name;
-
- /**
- * Constructor
- *
- * @param string|null $name The name identifying this type
- */
- public function __construct($name = null)
- {
- $this->_name = $name;
- }
-
- /**
- * Returns a Type object capable of converting a type identified by name.
- *
- * @param string $name type identifier
- * @throws \InvalidArgumentException If type identifier is unknown
- * @return \Cake\Database\Type
- */
- public static function build($name)
- {
- if (isset(static::$_builtTypes[$name])) {
- return static::$_builtTypes[$name];
- }
- if (!isset(static::$_types[$name])) {
- throw new InvalidArgumentException(sprintf('Unknown type "%s"', $name));
- }
- if (is_string(static::$_types[$name])) {
- return static::$_builtTypes[$name] = new static::$_types[$name]($name);
- }
-
- return static::$_builtTypes[$name] = static::$_types[$name];
- }
-
- /**
- * Returns an arrays with all the mapped type objects, indexed by name.
- *
- * @return array
- */
- public static function buildAll()
- {
- $result = [];
- foreach (static::$_types as $name => $type) {
- $result[$name] = isset(static::$_builtTypes[$name]) ? static::$_builtTypes[$name] : static::build($name);
- }
-
- return $result;
- }
-
- /**
- * Returns a Type object capable of converting a type identified by $name
- *
- * @param string $name The type identifier you want to set.
- * @param \Cake\Database\Type $instance The type instance you want to set.
- * @return void
- */
- public static function set($name, Type $instance)
- {
- static::$_builtTypes[$name] = $instance;
- static::$_types[$name] = get_class($instance);
- }
-
- /**
- * Registers a new type identifier and maps it to a fully namespaced classname,
- * If called with no arguments it will return current types map array
- * If $className is omitted it will return mapped class for $type
- *
- * Deprecated 3.6.2:
- * - The usage of $type as string[]|\Cake\Database\Type[] is deprecated.
- * Use Type::setMap() with string[] instead.
- * - Passing $className as \Cake\Database\Type instance is deprecated, use
- * class name string only.
- * - Using this method as getter is deprecated. Use Type::getMap() instead.
- *
- * @param string|string[]|\Cake\Database\Type[]|null $type If string name of type to map, if array list of arrays to be mapped
- * @param string|\Cake\Database\Type|null $className The classname or object instance of it to register.
- * @return array|string|null If $type is null then array with current map, if $className is null string
- * configured class name for give $type, null otherwise
- */
- public static function map($type = null, $className = null)
- {
- if ($type === null) {
- deprecationWarning(
- 'Using `Type::map()` as getter is deprecated. ' .
- 'Use `Type::getMap()` instead.'
- );
-
- return static::$_types;
- }
- if (is_array($type)) {
- deprecationWarning(
- 'Using `Type::map()` to set complete types map is deprecated. ' .
- 'Use `Type::setMap()` instead.'
- );
-
- static::$_types = $type;
-
- return null;
- }
- if ($className === null) {
- deprecationWarning(
- 'Using `Type::map()` as getter is deprecated. ' .
- 'Use `Type::getMap()` instead.'
- );
-
- return isset(static::$_types[$type]) ? static::$_types[$type] : null;
- }
-
- if (!is_string($className)) {
- deprecationWarning(
- 'Passing $className as object to Type::map() is deprecated. ' .
- 'Use Type::set() instead.'
- );
- }
-
- static::$_types[$type] = $className;
- unset(static::$_builtTypes[$type]);
- }
-
- /**
- * Set type to classname mapping.
- *
- * @param string[] $map List of types to be mapped.
- * @return void
- * @since 3.6.2
- */
- public static function setMap(array $map)
- {
- static::$_types = $map;
- static::$_builtTypes = [];
- }
-
- /**
- * Get mapped class name or instance for type(s).
- *
- * @param string|null $type Type name to get mapped class for or null to get map array.
- * @return array|string|\Cake\Database\TypeInterface|null Configured class name or instance for give $type or map array.
- * @since 3.6.2
- */
- public static function getMap($type = null)
- {
- if ($type === null) {
- return static::$_types;
- }
-
- return isset(static::$_types[$type]) ? static::$_types[$type] : null;
- }
-
- /**
- * Clears out all created instances and mapped types classes, useful for testing
- *
- * @return void
- */
- public static function clear()
- {
- static::$_types = [];
- static::$_builtTypes = [];
- }
-
- /**
- * {@inheritDoc}
- */
- public function getName()
- {
- return $this->_name;
- }
-
- /**
- * {@inheritDoc}
- */
- public function getBaseType()
- {
- return $this->_name;
- }
-
- /**
- * {@inheritDoc}
- */
- public function toDatabase($value, Driver $driver)
- {
- return $this->_basicTypeCast($value);
- }
-
- /**
- * Casts given value from a database type to PHP equivalent
- *
- * @param mixed $value Value to be converted to PHP equivalent
- * @param \Cake\Database\Driver $driver Object from which database preferences and configuration will be extracted
- * @return mixed
- */
- public function toPHP($value, Driver $driver)
- {
- return $this->_basicTypeCast($value);
- }
-
- /**
- * Checks whether this type is a basic one and can be converted using a callback
- * If it is, returns converted value
- *
- * @param mixed $value Value to be converted to PHP equivalent
- * @return mixed
- * @deprecated 3.1 All types should now be a specific class
- */
- protected function _basicTypeCast($value)
- {
- deprecationWarning(
- 'Using Type::_basicTypeCast() is deprecated. ' .
- "The '{$this->_name}' type needs to be updated to implement `TypeInterface`."
- );
- if ($value === null) {
- return null;
- }
- if (!empty(static::$_basicTypes[$this->_name])) {
- $typeInfo = static::$_basicTypes[$this->_name];
- if (isset($typeInfo['callback'])) {
- return $typeInfo['callback']($value);
- }
- }
-
- return $value;
- }
-
- /**
- * {@inheritDoc}
- */
- public function toStatement($value, Driver $driver)
- {
- if ($value === null) {
- return PDO::PARAM_NULL;
- }
-
- return PDO::PARAM_STR;
- }
-
- /**
- * Type converter for boolean values.
- *
- * Will convert string true/false into booleans.
- *
- * @param mixed $value The value to convert to a boolean.
- * @return bool
- * @deprecated 3.1.8 This method is now unused.
- */
- public static function boolval($value)
- {
- deprecationWarning('Type::boolval() is deprecated.');
- if (is_string($value) && !is_numeric($value)) {
- return strtolower($value) === 'true';
- }
-
- return !empty($value);
- }
-
- /**
- * Type converter for string values.
- *
- * Will convert values into strings
- *
- * @param mixed $value The value to convert to a string.
- * @return string
- * @deprecated 3.1.8 This method is now unused.
- */
- public static function strval($value)
- {
- deprecationWarning('Type::strval() is deprecated.');
- if (is_array($value)) {
- $value = '';
- }
-
- return (string)$value;
- }
-
- /**
- * {@inheritDoc}
- */
- public function newId()
- {
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- public function marshal($value)
- {
- return $this->_basicTypeCast($value);
- }
-
- /**
- * Returns an array that can be used to describe the internal state of this
- * object.
- *
- * @return array
- */
- public function __debugInfo()
- {
- return [
- 'name' => $this->_name,
- ];
- }
-}
+// @deprecated Backwards compatibility alias. Will be removed in 5.0
+class_alias('Cake\Database\TypeFactory', 'Cake\Database\Type');
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/BaseType.php b/app/vendor/cakephp/cakephp/src/Database/Type/BaseType.php
new file mode 100644
index 000000000..6909771b6
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/BaseType.php
@@ -0,0 +1,80 @@
+_name = $name;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getName(): ?string
+ {
+ return $this->_name;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getBaseType(): ?string
+ {
+ return $this->_name;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function toStatement($value, DriverInterface $driver)
+ {
+ if ($value === null) {
+ return PDO::PARAM_NULL;
+ }
+
+ return PDO::PARAM_STR;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function newId()
+ {
+ return null;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/BatchCastingInterface.php b/app/vendor/cakephp/cakephp/src/Database/Type/BatchCastingInterface.php
index 36d938094..04b74c722 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/BatchCastingInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/BatchCastingInterface.php
@@ -1,4 +1,6 @@
_name = $name;
- }
-
/**
* Convert binary data into the database format.
*
* Binary data is not altered before being inserted into the database.
* As PDO will handle reading file handles.
*
- * @param string|resource $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param mixed $value The value to convert.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return string|resource
*/
- public function toDatabase($value, Driver $driver)
+ public function toDatabase($value, DriverInterface $driver)
{
return $value;
}
@@ -69,23 +45,16 @@ public function toDatabase($value, Driver $driver)
/**
* Convert binary into resource handles
*
- * @param resource|string|null $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param mixed $value The value to convert.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return resource|null
* @throws \Cake\Core\Exception\Exception
*/
- public function toPHP($value, Driver $driver)
+ public function toPHP($value, DriverInterface $driver)
{
if ($value === null) {
return null;
}
- if (
- is_string($value)
- && $driver instanceof Sqlserver
- && version_compare(PHP_VERSION, '7.0', '<')
- ) {
- $value = pack('H*', $value);
- }
if (is_string($value)) {
return fopen('data:text/plain;base64,' . base64_encode($value), 'rb');
}
@@ -99,10 +68,10 @@ public function toPHP($value, Driver $driver)
* Get the correct PDO binding type for Binary data.
*
* @param mixed $value The value being bound.
- * @param \Cake\Database\Driver $driver The driver.
+ * @param \Cake\Database\DriverInterface $driver The driver.
* @return int
*/
- public function toStatement($value, Driver $driver)
+ public function toStatement($value, DriverInterface $driver): int
{
return PDO::PARAM_LOB;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/BinaryUuidType.php b/app/vendor/cakephp/cakephp/src/Database/Type/BinaryUuidType.php
index b6a553352..090297461 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/BinaryUuidType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/BinaryUuidType.php
@@ -1,4 +1,6 @@
_name = $name;
- }
-
/**
* Convert binary uuid data into the database format.
*
* Binary data is not altered before being inserted into the database.
* As PDO will handle reading file handles.
*
- * @param string|resource $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param mixed $value The value to convert.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return string|resource
*/
- public function toDatabase($value, Driver $driver)
+ public function toDatabase($value, DriverInterface $driver)
{
if (is_string($value)) {
return $this->convertStringToBinaryUuid($value);
@@ -75,7 +52,7 @@ public function toDatabase($value, Driver $driver)
*
* @return string A new primary key value.
*/
- public function newId()
+ public function newId(): string
{
return Text::uuid();
}
@@ -83,12 +60,12 @@ public function newId()
/**
* Convert binary uuid into resource handles
*
- * @param resource|string|null $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param mixed $value The value to convert.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return resource|string|null
* @throws \Cake\Core\Exception\Exception
*/
- public function toPHP($value, Driver $driver)
+ public function toPHP($value, DriverInterface $driver)
{
if ($value === null) {
return null;
@@ -107,10 +84,10 @@ public function toPHP($value, Driver $driver)
* Get the correct PDO binding type for Binary data.
*
* @param mixed $value The value being bound.
- * @param \Cake\Database\Driver $driver The driver.
+ * @param \Cake\Database\DriverInterface $driver The driver.
* @return int
*/
- public function toStatement($value, Driver $driver)
+ public function toStatement($value, DriverInterface $driver): int
{
return PDO::PARAM_LOB;
}
@@ -135,13 +112,13 @@ public function marshal($value)
* @param mixed $binary The value to convert.
* @return string Converted value.
*/
- protected function convertBinaryUuidToString($binary)
+ protected function convertBinaryUuidToString($binary): string
{
- $string = unpack("H*", $binary);
+ $string = unpack('H*', $binary);
$string = preg_replace(
- "/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/",
- "$1-$2-$3-$4-$5",
+ '/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/',
+ '$1-$2-$3-$4-$5',
$string
);
@@ -154,10 +131,10 @@ protected function convertBinaryUuidToString($binary)
* @param string $string The value to convert.
* @return string Converted value.
*/
- protected function convertStringToBinaryUuid($string)
+ protected function convertStringToBinaryUuid($string): string
{
$string = str_replace('-', '', $string);
- return pack("H*", $string);
+ return pack('H*', $string);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/BoolType.php b/app/vendor/cakephp/cakephp/src/Database/Type/BoolType.php
index 65e529eb9..eeb1c8854 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/BoolType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/BoolType.php
@@ -1,4 +1,6 @@
_name = $name;
- }
-
/**
* Convert bool data into the database format.
*
* @param mixed $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return bool|null
*/
- public function toDatabase($value, Driver $driver)
+ public function toDatabase($value, DriverInterface $driver): ?bool
{
if ($value === true || $value === false || $value === null) {
return $value;
@@ -78,10 +54,10 @@ public function toDatabase($value, Driver $driver)
* Convert bool values to PHP booleans
*
* @param mixed $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return bool|null
*/
- public function toPHP($value, Driver $driver)
+ public function toPHP($value, DriverInterface $driver): ?bool
{
if ($value === null || $value === true || $value === false) {
return $value;
@@ -95,11 +71,9 @@ public function toPHP($value, Driver $driver)
}
/**
- * {@inheritDoc}
- *
- * @return array
+ * @inheritDoc
*/
- public function manyToPHP(array $values, array $fields, Driver $driver)
+ public function manyToPHP(array $values, array $fields, DriverInterface $driver): array
{
foreach ($fields as $field) {
if (!isset($values[$field]) || $values[$field] === true || $values[$field] === false) {
@@ -132,10 +106,10 @@ public function manyToPHP(array $values, array $fields, Driver $driver)
* Get the correct PDO binding type for bool data.
*
* @param mixed $value The value being bound.
- * @param \Cake\Database\Driver $driver The driver.
+ * @param \Cake\Database\DriverInterface $driver The driver.
* @return int
*/
- public function toStatement($value, Driver $driver)
+ public function toStatement($value, DriverInterface $driver): int
{
if ($value === null) {
return PDO::PARAM_NULL;
@@ -150,21 +124,12 @@ public function toStatement($value, Driver $driver)
* @param mixed $value The value to convert.
* @return bool|null Converted value.
*/
- public function marshal($value)
+ public function marshal($value): ?bool
{
- if ($value === null) {
- return null;
- }
- if ($value === 'true') {
- return true;
- }
- if ($value === 'false') {
- return false;
- }
- if (!is_scalar($value)) {
+ if ($value === null || $value === '') {
return null;
}
- return !empty($value);
+ return filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/DateTimeFractionalType.php b/app/vendor/cakephp/cakephp/src/Database/Type/DateTimeFractionalType.php
new file mode 100644
index 000000000..3cc149d91
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/DateTimeFractionalType.php
@@ -0,0 +1,42 @@
+|class-string<\DateTimeImmutable>
*/
protected $_className;
/**
- * Timezone instance.
+ * Database time zone.
*
* @var \DateTimeZone|null
*/
protected $dbTimezone;
+ /**
+ * Default time zone.
+ *
+ * @var \DateTimeZone
+ */
+ protected $defaultTimezone;
+
+ /**
+ * Whether database time zone is kept when converting
+ *
+ * @var bool
+ */
+ protected $keepDatabaseTimezone = false;
+
/**
* {@inheritDoc}
+ *
+ * @param string|null $name The name identifying this type
*/
- public function __construct($name = null)
+ public function __construct(?string $name = null)
{
- $this->_name = $name;
+ parent::__construct($name);
- $this->_setClassName(static::$dateTimeClass, 'DateTime');
+ $this->defaultTimezone = new DateTimeZone(date_default_timezone_get());
+ $this->useImmutable();
}
/**
* Convert DateTime instance into strings.
*
- * @param string|int|\DateTime|\DateTimeImmutable $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param mixed $value The value to convert.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return string|null
*/
- public function toDatabase($value, Driver $driver)
+ public function toDatabase($value, DriverInterface $driver): ?string
{
if ($value === null || is_string($value)) {
return $value;
@@ -137,8 +141,6 @@ public function toDatabase($value, Driver $driver)
$value = new $class('@' . $value);
}
- $format = (array)$this->_format;
-
if (
$this->dbTimezone !== null
&& $this->dbTimezone->getName() !== $value->getTimezone()->getName()
@@ -149,20 +151,31 @@ public function toDatabase($value, Driver $driver)
$value = $value->setTimezone($this->dbTimezone);
}
- return $value->format(array_shift($format));
+ return $value->format($this->_format);
+ }
+
+ /**
+ * Alias for `setDatabaseTimezone()`.
+ *
+ * @param string|\DateTimeZone|null $timezone Database timezone.
+ * @return $this
+ */
+ public function setTimezone($timezone)
+ {
+ return $this->setDatabaseTimezone($timezone);
}
/**
* Set database timezone.
*
- * Specified timezone will be set for DateTime objects before generating
- * datetime string for saving to database. If `null` no timezone conversion
- * will be done.
+ * This is the time zone used when converting database strings to DateTime
+ * instances and converting DateTime instances to database strings.
*
+ * @see DateTimeType::setKeepDatabaseTimezone
* @param string|\DateTimeZone|null $timezone Database timezone.
* @return $this
*/
- public function setTimezone($timezone)
+ public function setDatabaseTimezone($timezone)
{
if (is_string($timezone)) {
$timezone = new DateTimeZone($timezone);
@@ -173,20 +186,34 @@ public function setTimezone($timezone)
}
/**
- * Convert strings into DateTime instances.
+ * {@inheritDoc}
*
- * @param string $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
- * @return \Cake\I18n\Time|\DateTime|null
+ * @param mixed $value Value to be converted to PHP equivalent
+ * @param \Cake\Database\DriverInterface $driver Object from which database preferences and configuration will be extracted
+ * @return \DateTimeInterface|null
*/
- public function toPHP($value, Driver $driver)
+ public function toPHP($value, DriverInterface $driver)
{
- if ($value === null || strpos($value, '0000-00-00') === 0) {
+ if ($value === null) {
return null;
}
- $instance = clone $this->_datetimeInstance;
- $instance = $instance->modify($value);
+ $class = $this->_className;
+ if (is_int($value)) {
+ $instance = new $class('@' . $value);
+ } else {
+ if (strpos($value, '0000-00-00') === 0) {
+ return null;
+ }
+ $instance = new $class($value, $this->dbTimezone);
+ }
+
+ if (
+ !$this->keepDatabaseTimezone &&
+ $instance->getTimezone()->getName() !== $this->defaultTimezone->getName()
+ ) {
+ $instance = $instance->setTimezone($this->defaultTimezone);
+ }
if ($this->setToDateStart) {
$instance = $instance->setTime(0, 0, 0);
@@ -196,24 +223,55 @@ public function toPHP($value, Driver $driver)
}
/**
- * {@inheritDoc}
+ * Set whether DateTime object created from database string is converted
+ * to default time zone.
+ *
+ * If your database date times are in a specific time zone that you want
+ * to keep in the DateTime instance then set this to true.
+ *
+ * When false, datetime timezones are converted to default time zone.
+ * This is default behavior.
*
- * @return array
+ * @param bool $keep If true, database time zone is kept when converting
+ * to DateTime instances.
+ * @return $this
*/
- public function manyToPHP(array $values, array $fields, Driver $driver)
+ public function setKeepDatabaseTimezone(bool $keep)
+ {
+ $this->keepDatabaseTimezone = $keep;
+
+ return $this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function manyToPHP(array $values, array $fields, DriverInterface $driver): array
{
foreach ($fields as $field) {
if (!isset($values[$field])) {
continue;
}
- if (strpos($values[$field], '0000-00-00') === 0) {
+ $value = $values[$field];
+ if (strpos($value, '0000-00-00') === 0) {
$values[$field] = null;
continue;
}
- $instance = clone $this->_datetimeInstance;
- $instance = $instance->modify($values[$field]);
+ $class = $this->_className;
+ if (is_int($value)) {
+ $instance = new $class('@' . $value);
+ } else {
+ $instance = new $class($value, $this->dbTimezone);
+ }
+
+ if (
+ !$this->keepDatabaseTimezone &&
+ $instance->getTimezone()->getName() !== $this->defaultTimezone->getName()
+ ) {
+ $instance = $instance->setTimezone($this->defaultTimezone);
+ }
if ($this->setToDateStart) {
$instance = $instance->setTime(0, 0, 0);
@@ -231,46 +289,43 @@ public function manyToPHP(array $values, array $fields, Driver $driver)
* @param mixed $value Request data
* @return \DateTimeInterface|null
*/
- public function marshal($value)
+ public function marshal($value): ?DateTimeInterface
{
if ($value instanceof DateTimeInterface) {
return $value;
}
+ /** @var class-string<\DatetimeInterface> $class */
$class = $this->_className;
try {
- $compare = $date = false;
- if ($value === '' || $value === null || $value === false || $value === true) {
+ if ($value === '' || $value === null || is_bool($value)) {
return null;
}
$isString = is_string($value);
if (ctype_digit($value)) {
- $date = new $class('@' . $value);
- } elseif ($isString && $this->_useLocaleParser) {
- return $this->_parseValue($value);
+ return new $class('@' . $value);
+ } elseif ($isString && $this->_useLocaleMarshal) {
+ return $this->_parseLocaleValue($value);
} elseif ($isString) {
- $date = new $class($value);
- $compare = true;
- }
- if ($compare && $date && !$this->_compare($date, $value)) {
- return $value;
- }
- if ($date) {
- return $date;
+ return $this->_parseValue($value);
}
} catch (Exception $e) {
- return $value;
+ return null;
}
if (is_array($value) && implode('', $value) === '') {
return null;
}
- $value += ['hour' => 0, 'minute' => 0, 'second' => 0];
+ $value += ['hour' => 0, 'minute' => 0, 'second' => 0, 'microsecond' => 0];
$format = '';
if (
isset($value['year'], $value['month'], $value['day']) &&
- (is_numeric($value['year']) && is_numeric($value['month']) && is_numeric($value['day']))
+ (
+ is_numeric($value['year']) &&
+ is_numeric($value['month']) &&
+ is_numeric($value['day'])
+ )
) {
$format .= sprintf('%d-%02d-%02d', $value['year'], $value['month'], $value['day']);
}
@@ -282,49 +337,34 @@ public function marshal($value)
$value['hour'] = strtolower($value['meridian']) === 'am' ? $value['hour'] : $value['hour'] + 12;
}
$format .= sprintf(
- '%s%02d:%02d:%02d',
+ '%s%02d:%02d:%02d.%06d',
empty($format) ? '' : ' ',
$value['hour'],
$value['minute'],
- $value['second']
+ $value['second'],
+ $value['microsecond']
);
- $tz = isset($value['timezone']) ? $value['timezone'] : null;
+ $tz = $value['timezone'] ?? null;
return new $class($format, $tz);
}
/**
- * @param \Cake\I18n\Time|\DateTime $date DateTime object
- * @param mixed $value Request data
- * @return bool
- */
- protected function _compare($date, $value)
- {
- foreach ((array)$this->_format as $format) {
- if ($date->format($format) === $value) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Sets whether or not to parse dates passed to the marshal() function
- * by using a locale aware parser.
+ * Sets whether or not to parse strings passed to `marshal()` using
+ * the locale-aware format set by `setLocaleFormat()`.
*
* @param bool $enable Whether or not to enable
* @return $this
*/
- public function useLocaleParser($enable = true)
+ public function useLocaleParser(bool $enable = true)
{
if ($enable === false) {
- $this->_useLocaleParser = $enable;
+ $this->_useLocaleMarshal = $enable;
return $this;
}
- if (method_exists($this->_className, 'parseDateTime')) {
- $this->_useLocaleParser = $enable;
+ if (is_subclass_of($this->_className, I18nDateTimeInterface::class)) {
+ $this->_useLocaleMarshal = $enable;
return $this;
}
@@ -334,17 +374,17 @@ public function useLocaleParser($enable = true)
}
/**
- * Sets the format string to use for parsing dates in this class. The formats
- * that are accepted are documented in the `Cake\I18n\Time::parseDateTime()`
- * function.
+ * Sets the locale-aware format used by `marshal()` when parsing strings.
*
- * @param string|array $format The format in which the string are passed.
+ * See `Cake\I18n\Time::parseDateTime()` for accepted formats.
+ *
+ * @param string|array $format The locale-aware format
* @see \Cake\I18n\Time::parseDateTime()
* @return $this
*/
public function setLocaleFormat($format)
{
- $this->_localeFormat = $format;
+ $this->_localeMarshalFormat = $format;
return $this;
}
@@ -356,7 +396,7 @@ public function setLocaleFormat($format)
*/
public function useImmutable()
{
- $this->_setClassName('Cake\I18n\FrozenTime', 'DateTimeImmutable');
+ $this->_setClassName(FrozenTime::class, DateTimeImmutable::class);
return $this;
}
@@ -367,22 +407,24 @@ public function useImmutable()
* @param string $class The classname to use.
* @param string $fallback The classname to use when the preferred class does not exist.
* @return void
+ * @psalm-param class-string<\DateTime>|class-string<\DateTimeImmutable> $class
+ * @psalm-param class-string<\DateTime>|class-string<\DateTimeImmutable> $fallback
*/
- protected function _setClassName($class, $fallback)
+ protected function _setClassName(string $class, string $fallback): void
{
if (!class_exists($class)) {
$class = $fallback;
}
$this->_className = $class;
- $this->_datetimeInstance = new $this->_className();
}
/**
* Get the classname used for building objects.
*
* @return string
+ * @psalm-return class-string<\DateTime>|class-string<\DateTimeImmutable>
*/
- public function getDateTimeClassName()
+ public function getDateTimeClassName(): string
{
return $this->_className;
}
@@ -394,34 +436,63 @@ public function getDateTimeClassName()
*/
public function useMutable()
{
- $this->_setClassName('Cake\I18n\Time', 'DateTime');
+ $this->_setClassName(Time::class, DateTime::class);
return $this;
}
/**
* Converts a string into a DateTime object after parsing it using the locale
- * aware parser with the specified format.
+ * aware parser with the format set by `setLocaleFormat()`.
+ *
+ * @param string $value The value to parse and convert to an object.
+ * @return \Cake\I18n\I18nDateTimeInterface|null
+ */
+ protected function _parseLocaleValue(string $value)
+ {
+ /** @var \Cake\I18n\I18nDateTimeInterface $class */
+ $class = $this->_className;
+
+ return $class::parseDateTime($value, $this->_localeMarshalFormat);
+ }
+
+ /**
+ * Converts a string into a DateTime object after parsing it using the
+ * formats in `_marshalFormats`.
*
* @param string $value The value to parse and convert to an object.
- * @return \Cake\I18n\Time|null
+ * @return \DateTimeInterface|null
*/
- protected function _parseValue($value)
+ protected function _parseValue(string $value)
{
- /** @var \Cake\I18n\Time $class */
+ /** @var \DateTime|\DateTimeImmutable $class */
$class = $this->_className;
- return $class::parseDateTime($value, $this->_localeFormat);
+ foreach ($this->_marshalFormats as $format) {
+ try {
+ $dateTime = $class::createFromFormat($format, $value);
+ // Check for false in case DateTime is used directly
+ if ($dateTime !== false) {
+ return $dateTime;
+ }
+ } catch (InvalidArgumentException $e) {
+ // Chronos wraps DateTime::createFromFormat and throws
+ // exception if parse fails.
+ continue;
+ }
+ }
+
+ return null;
}
/**
* Casts given value to Statement equivalent
*
* @param mixed $value value to be converted to PDO statement
- * @param \Cake\Database\Driver $driver object from which database preferences and configuration will be extracted
+ * @param \Cake\Database\DriverInterface $driver object from which database preferences and configuration will be extracted
* @return mixed
*/
- public function toStatement($value, Driver $driver)
+ public function toStatement($value, DriverInterface $driver)
{
return PDO::PARAM_STR;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/DateType.php b/app/vendor/cakephp/cakephp/src/Database/Type/DateType.php
index 5aa30b042..7bbc02184 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/DateType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/DateType.php
@@ -1,4 +1,6 @@
_setClassName('Cake\I18n\FrozenDate', 'DateTimeImmutable');
+ $this->_setClassName(FrozenDate::class, DateTimeImmutable::class);
return $this;
}
@@ -66,7 +66,7 @@ public function useImmutable()
*/
public function useMutable()
{
- $this->_setClassName('Cake\I18n\Date', 'DateTime');
+ $this->_setClassName(Date::class, DateTime::class);
return $this;
}
@@ -75,9 +75,9 @@ public function useMutable()
* Convert request data into a datetime object.
*
* @param mixed $value Request data
- * @return \DateTimeInterface
+ * @return \DateTimeInterface|null
*/
- public function marshal($value)
+ public function marshal($value): ?DateTimeInterface
{
$date = parent::marshal($value);
if ($date instanceof DateTime) {
@@ -88,13 +88,13 @@ public function marshal($value)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- protected function _parseValue($value)
+ protected function _parseLocaleValue(string $value)
{
- /** @var \Cake\I18n\Time $class */
+ /** @var \Cake\I18n\I18nDateTimeInterface $class */
$class = $this->_className;
- return $class::parseDate($value, $this->_localeFormat);
+ return $class::parseDate($value, $this->_localeMarshalFormat);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/DecimalType.php b/app/vendor/cakephp/cakephp/src/Database/Type/DecimalType.php
index 15b377f0d..9359ca1d3 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/DecimalType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/DecimalType.php
@@ -1,4 +1,6 @@
_name = $name;
- }
-
/**
* The class to use for representing number objects
*
* @var string
*/
- public static $numberClass = 'Cake\I18n\Number';
+ public static $numberClass = Number::class;
/**
* Whether numbers should be parsed using a locale aware parser
@@ -68,84 +45,88 @@ public function __construct($name = null)
protected $_useLocaleParser = false;
/**
- * Convert integer data into the database format.
+ * Convert decimal strings into the database format.
*
* @param mixed $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
- * @return string|null
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
+ * @return string|float|int|null
* @throws \InvalidArgumentException
*/
- public function toDatabase($value, Driver $driver)
+ public function toDatabase($value, DriverInterface $driver)
{
if ($value === null || $value === '') {
return null;
}
- if (!is_scalar($value)) {
- throw new InvalidArgumentException(sprintf(
- 'Cannot convert value of type `%s` to a decimal',
- getTypeName($value)
- ));
- }
- if (is_string($value) && is_numeric($value)) {
+
+ if (is_numeric($value)) {
return $value;
}
- return sprintf('%F', $value);
+ if (
+ is_object($value)
+ && method_exists($value, '__toString')
+ && is_numeric(strval($value))
+ ) {
+ return strval($value);
+ }
+
+ throw new InvalidArgumentException(sprintf(
+ 'Cannot convert value of type `%s` to a decimal',
+ getTypeName($value)
+ ));
}
/**
- * Convert float values to PHP floats
+ * {@inheritDoc}
*
* @param mixed $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
- * @return float|null
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
+ * @return string|null
*/
- public function toPHP($value, Driver $driver)
+ public function toPHP($value, DriverInterface $driver): ?string
{
if ($value === null) {
- return $value;
+ return null;
}
- return (float)$value;
+ return (string)$value;
}
/**
- * {@inheritDoc}
- *
- * @return float[]
+ * @inheritDoc
*/
- public function manyToPHP(array $values, array $fields, Driver $driver)
+ public function manyToPHP(array $values, array $fields, DriverInterface $driver): array
{
foreach ($fields as $field) {
if (!isset($values[$field])) {
continue;
}
- $values[$field] = (float)$values[$field];
+ $values[$field] = (string)$values[$field];
}
return $values;
}
/**
- * Get the correct PDO binding type for integer data.
+ * Get the correct PDO binding type for decimal data.
*
* @param mixed $value The value being bound.
- * @param \Cake\Database\Driver $driver The driver.
+ * @param \Cake\Database\DriverInterface $driver The driver.
* @return int
*/
- public function toStatement($value, Driver $driver)
+ public function toStatement($value, DriverInterface $driver): int
{
return PDO::PARAM_STR;
}
/**
- * Marshals request data into PHP floats.
+ * Marshalls request data into decimal strings.
*
* @param mixed $value The value to convert.
- * @return float|string|null Converted value.
+ * @return string|null Converted value.
*/
- public function marshal($value)
+ public function marshal($value): ?string
{
if ($value === null || $value === '') {
return null;
@@ -154,7 +135,7 @@ public function marshal($value)
return $this->_parseValue($value);
}
if (is_numeric($value)) {
- return (float)$value;
+ return (string)$value;
}
if (is_string($value) && preg_match('/^[0-9,. ]+$/', $value)) {
return $value;
@@ -171,7 +152,7 @@ public function marshal($value)
* @return $this
* @throws \RuntimeException
*/
- public function useLocaleParser($enable = true)
+ public function useLocaleParser(bool $enable = true)
{
if ($enable === false) {
$this->_useLocaleParser = $enable;
@@ -179,8 +160,8 @@ public function useLocaleParser($enable = true)
return $this;
}
if (
- static::$numberClass === 'Cake\I18n\Number' ||
- is_subclass_of(static::$numberClass, 'Cake\I18n\Number')
+ static::$numberClass === Number::class ||
+ is_subclass_of(static::$numberClass, Number::class)
) {
$this->_useLocaleParser = $enable;
@@ -192,17 +173,17 @@ public function useLocaleParser($enable = true)
}
/**
- * Converts a string into a float point after parsing it using the locale
- * aware parser.
+ * Converts localized string into a decimal string after parsing it using
+ * the locale aware parser.
*
* @param string $value The value to parse and convert to an float.
- * @return float
+ * @return string
*/
- protected function _parseValue($value)
+ protected function _parseValue(string $value): string
{
/** @var \Cake\I18n\Number $class */
$class = static::$numberClass;
- return $class::parseFloat($value);
+ return (string)$class::parseFloat($value);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/ExpressionTypeCasterTrait.php b/app/vendor/cakephp/cakephp/src/Database/Type/ExpressionTypeCasterTrait.php
index 0976220a7..2743b42f8 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/ExpressionTypeCasterTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/ExpressionTypeCasterTrait.php
@@ -1,4 +1,6 @@
$type) {
- $object = Type::build($type);
+ $object = TypeFactory::build($type);
if ($object instanceof ExpressionTypeInterface) {
$result[$k] = $object;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/ExpressionTypeInterface.php b/app/vendor/cakephp/cakephp/src/Database/Type/ExpressionTypeInterface.php
index 0210e3123..7615cf9e0 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/ExpressionTypeInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/ExpressionTypeInterface.php
@@ -1,4 +1,6 @@
_name = $name;
- }
-
/**
* The class to use for representing number objects
*
* @var string
*/
- public static $numberClass = 'Cake\I18n\Number';
+ public static $numberClass = Number::class;
/**
* Whether numbers should be parsed using a locale aware parser
@@ -69,11 +46,11 @@ public function __construct($name = null)
/**
* Convert integer data into the database format.
*
- * @param string|resource $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param mixed $value The value to convert.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return float|null
*/
- public function toDatabase($value, Driver $driver)
+ public function toDatabase($value, DriverInterface $driver): ?float
{
if ($value === null || $value === '') {
return null;
@@ -83,14 +60,14 @@ public function toDatabase($value, Driver $driver)
}
/**
- * Convert float values to PHP integers
+ * {@inheritDoc}
*
- * @param resource|string|null $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param mixed $value The value to convert.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return float|null
* @throws \Cake\Core\Exception\Exception
*/
- public function toPHP($value, Driver $driver)
+ public function toPHP($value, DriverInterface $driver): ?float
{
if ($value === null) {
return null;
@@ -100,11 +77,9 @@ public function toPHP($value, Driver $driver)
}
/**
- * {@inheritDoc}
- *
- * @return float[]
+ * @inheritDoc
*/
- public function manyToPHP(array $values, array $fields, Driver $driver)
+ public function manyToPHP(array $values, array $fields, DriverInterface $driver): array
{
foreach ($fields as $field) {
if (!isset($values[$field])) {
@@ -121,10 +96,10 @@ public function manyToPHP(array $values, array $fields, Driver $driver)
* Get the correct PDO binding type for integer data.
*
* @param mixed $value The value being bound.
- * @param \Cake\Database\Driver $driver The driver.
+ * @param \Cake\Database\DriverInterface $driver The driver.
* @return int
*/
- public function toStatement($value, Driver $driver)
+ public function toStatement($value, DriverInterface $driver): int
{
return PDO::PARAM_STR;
}
@@ -133,7 +108,7 @@ public function toStatement($value, Driver $driver)
* Marshals request data into PHP floats.
*
* @param mixed $value The value to convert.
- * @return float|string|null Converted value.
+ * @return string|float|null Converted value.
*/
public function marshal($value)
{
@@ -160,7 +135,7 @@ public function marshal($value)
* @param bool $enable Whether or not to enable
* @return $this
*/
- public function useLocaleParser($enable = true)
+ public function useLocaleParser(bool $enable = true)
{
if ($enable === false) {
$this->_useLocaleParser = $enable;
@@ -168,8 +143,8 @@ public function useLocaleParser($enable = true)
return $this;
}
if (
- static::$numberClass === 'Cake\I18n\Number' ||
- is_subclass_of(static::$numberClass, 'Cake\I18n\Number')
+ static::$numberClass === Number::class ||
+ is_subclass_of(static::$numberClass, Number::class)
) {
$this->_useLocaleParser = $enable;
@@ -187,7 +162,7 @@ public function useLocaleParser($enable = true)
* @param string $value The value to parse and convert to an float.
* @return float
*/
- protected function _parseValue($value)
+ protected function _parseValue(string $value): float
{
$class = static::$numberClass;
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/IntegerType.php b/app/vendor/cakephp/cakephp/src/Database/Type/IntegerType.php
index 106e6380e..8352e4f11 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/IntegerType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/IntegerType.php
@@ -1,4 +1,6 @@
_name = $name;
- }
-
/**
* Checks if the value is not a numeric value
*
@@ -58,7 +34,7 @@ public function __construct($name = null)
* @param mixed $value Value to check
* @return void
*/
- protected function checkNumeric($value)
+ protected function checkNumeric($value): void
{
if (!is_numeric($value)) {
throw new InvalidArgumentException(sprintf(
@@ -72,10 +48,10 @@ protected function checkNumeric($value)
* Convert integer data into the database format.
*
* @param mixed $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return int|null
*/
- public function toDatabase($value, Driver $driver)
+ public function toDatabase($value, DriverInterface $driver): ?int
{
if ($value === null || $value === '') {
return null;
@@ -87,13 +63,13 @@ public function toDatabase($value, Driver $driver)
}
/**
- * Convert integer values to PHP integers
+ * {@inheritDoc}
*
* @param mixed $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return int|null
*/
- public function toPHP($value, Driver $driver)
+ public function toPHP($value, DriverInterface $driver): ?int
{
if ($value === null) {
return $value;
@@ -103,11 +79,9 @@ public function toPHP($value, Driver $driver)
}
/**
- * {@inheritDoc}
- *
- * @return int[]
+ * @inheritDoc
*/
- public function manyToPHP(array $values, array $fields, Driver $driver)
+ public function manyToPHP(array $values, array $fields, DriverInterface $driver): array
{
foreach ($fields as $field) {
if (!isset($values[$field])) {
@@ -126,10 +100,10 @@ public function manyToPHP(array $values, array $fields, Driver $driver)
* Get the correct PDO binding type for integer data.
*
* @param mixed $value The value being bound.
- * @param \Cake\Database\Driver $driver The driver.
+ * @param \Cake\Database\DriverInterface $driver The driver.
* @return int
*/
- public function toStatement($value, Driver $driver)
+ public function toStatement($value, DriverInterface $driver): int
{
return PDO::PARAM_INT;
}
@@ -140,7 +114,7 @@ public function toStatement($value, Driver $driver)
* @param mixed $value The value to convert.
* @return int|null Converted value.
*/
- public function marshal($value)
+ public function marshal($value): ?int
{
if ($value === null || $value === '') {
return null;
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/JsonType.php b/app/vendor/cakephp/cakephp/src/Database/Type/JsonType.php
index ed9bb8046..0969c5cfb 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/JsonType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/JsonType.php
@@ -1,4 +1,6 @@
_name = $name;
- }
-
/**
* Convert a value data into a JSON string
*
* @param mixed $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return string|null
+ * @throws \InvalidArgumentException
*/
- public function toDatabase($value, Driver $driver)
+ public function toDatabase($value, DriverInterface $driver): ?string
{
if (is_resource($value)) {
throw new InvalidArgumentException('Cannot convert a resource value to JSON');
}
+ if ($value === null) {
+ return null;
+ }
+
return json_encode($value);
}
/**
- * Convert string values to PHP arrays.
+ * {@inheritDoc}
*
* @param mixed $value The value to convert.
- * @param \Cake\Database\Driver $driver The driver instance to convert with.
+ * @param \Cake\Database\DriverInterface $driver The driver instance to convert with.
* @return string|array|null
*/
- public function toPHP($value, Driver $driver)
+ public function toPHP($value, DriverInterface $driver)
{
+ if (!is_string($value)) {
+ return null;
+ }
+
return json_decode($value, true);
}
/**
- * {@inheritDoc}
- *
- * @return array
+ * @inheritDoc
*/
- public function manyToPHP(array $values, array $fields, Driver $driver)
+ public function manyToPHP(array $values, array $fields, DriverInterface $driver): array
{
foreach ($fields as $field) {
if (!isset($values[$field])) {
@@ -101,10 +84,10 @@ public function manyToPHP(array $values, array $fields, Driver $driver)
* Get the correct PDO binding type for string data.
*
* @param mixed $value The value being bound.
- * @param \Cake\Database\Driver $driver The driver.
+ * @param \Cake\Database\DriverInterface $driver The driver.
* @return int
*/
- public function toStatement($value, Driver $driver)
+ public function toStatement($value, DriverInterface $driver): int
{
return PDO::PARAM_STR;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/OptionalConvertInterface.php b/app/vendor/cakephp/cakephp/src/Database/Type/OptionalConvertInterface.php
index d43fd606f..512683bb6 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/OptionalConvertInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/OptionalConvertInterface.php
@@ -1,4 +1,6 @@
_className;
- return $class::parseTime($value, $this->_localeFormat);
+ /** @psalm-suppress PossiblyInvalidArgument */
+ return $class::parseTime($value, $this->_localeMarshalFormat);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/UuidType.php b/app/vendor/cakephp/cakephp/src/Database/Type/UuidType.php
index 492da50fc..ce7f754fb 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/UuidType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/UuidType.php
@@ -1,4 +1,6 @@
toDatabase($value, $this->_driver);
@@ -50,7 +53,7 @@ public function cast($value, $type)
* @param array $types list or associative array of types
* @return array
*/
- public function matchTypes($columns, $types)
+ public function matchTypes(array $columns, array $types): array
{
if (!is_int(key($types))) {
$positions = array_intersect_key(array_flip($columns), $types);
diff --git a/app/vendor/cakephp/cakephp/src/Database/TypeFactory.php b/app/vendor/cakephp/cakephp/src/Database/TypeFactory.php
new file mode 100644
index 000000000..361dfc9a7
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/TypeFactory.php
@@ -0,0 +1,164 @@
+
+ * @psalm-var array>
+ */
+ protected static $_types = [
+ 'tinyinteger' => Type\IntegerType::class,
+ 'smallinteger' => Type\IntegerType::class,
+ 'integer' => Type\IntegerType::class,
+ 'biginteger' => Type\IntegerType::class,
+ 'binary' => Type\BinaryType::class,
+ 'binaryuuid' => Type\BinaryUuidType::class,
+ 'boolean' => Type\BoolType::class,
+ 'date' => Type\DateType::class,
+ 'datetime' => Type\DateTimeType::class,
+ 'datetimefractional' => Type\DateTimeFractionalType::class,
+ 'decimal' => Type\DecimalType::class,
+ 'float' => Type\FloatType::class,
+ 'json' => Type\JsonType::class,
+ 'string' => Type\StringType::class,
+ 'char' => Type\StringType::class,
+ 'text' => Type\StringType::class,
+ 'time' => Type\TimeType::class,
+ 'timestamp' => Type\DateTimeType::class,
+ 'timestampfractional' => Type\DateTimeFractionalType::class,
+ 'timestamptimezone' => Type\DateTimeTimezoneType::class,
+ 'uuid' => Type\UuidType::class,
+ ];
+
+ /**
+ * Contains a map of type object instances to be reused if needed.
+ *
+ * @var \Cake\Database\TypeInterface[]
+ */
+ protected static $_builtTypes = [];
+
+ /**
+ * Returns a Type object capable of converting a type identified by name.
+ *
+ * @param string $name type identifier
+ * @throws \InvalidArgumentException If type identifier is unknown
+ * @return \Cake\Database\TypeInterface
+ */
+ public static function build(string $name): TypeInterface
+ {
+ if (isset(static::$_builtTypes[$name])) {
+ return static::$_builtTypes[$name];
+ }
+ if (!isset(static::$_types[$name])) {
+ throw new InvalidArgumentException(sprintf('Unknown type "%s"', $name));
+ }
+
+ return static::$_builtTypes[$name] = new static::$_types[$name]($name);
+ }
+
+ /**
+ * Returns an arrays with all the mapped type objects, indexed by name.
+ *
+ * @return \Cake\Database\TypeInterface[]
+ */
+ public static function buildAll(): array
+ {
+ $result = [];
+ foreach (static::$_types as $name => $type) {
+ $result[$name] = static::$_builtTypes[$name] ?? static::build($name);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Set TypeInterface instance capable of converting a type identified by $name
+ *
+ * @param string $name The type identifier you want to set.
+ * @param \Cake\Database\TypeInterface $instance The type instance you want to set.
+ * @return void
+ */
+ public static function set(string $name, TypeInterface $instance): void
+ {
+ static::$_builtTypes[$name] = $instance;
+ static::$_types[$name] = get_class($instance);
+ }
+
+ /**
+ * Registers a new type identifier and maps it to a fully namespaced classname.
+ *
+ * @param string $type Name of type to map.
+ * @param string $className The classname to register.
+ * @return void
+ * @psalm-param class-string<\Cake\Database\TypeInterface> $className
+ */
+ public static function map(string $type, string $className): void
+ {
+ static::$_types[$type] = $className;
+ unset(static::$_builtTypes[$type]);
+ }
+
+ /**
+ * Set type to classname mapping.
+ *
+ * @param string[] $map List of types to be mapped.
+ * @return void
+ * @psalm-param array> $map
+ */
+ public static function setMap(array $map): void
+ {
+ static::$_types = $map;
+ static::$_builtTypes = [];
+ }
+
+ /**
+ * Get mapped class name for given type or map array.
+ *
+ * @param string|null $type Type name to get mapped class for or null to get map array.
+ * @return string[]|string|null Configured class name for given $type or map array.
+ */
+ public static function getMap(?string $type = null)
+ {
+ if ($type === null) {
+ return static::$_types;
+ }
+
+ return static::$_types[$type] ?? null;
+ }
+
+ /**
+ * Clears out all created instances and mapped types classes, useful for testing
+ *
+ * @return void
+ */
+ public static function clear(): void
+ {
+ static::$_types = [];
+ static::$_builtTypes = [];
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Database/TypeInterface.php b/app/vendor/cakephp/cakephp/src/Database/TypeInterface.php
index 1068abdef..fca0fdbe8 100644
--- a/app/vendor/cakephp/cakephp/src/Database/TypeInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/TypeInterface.php
@@ -1,4 +1,6 @@
_defaults;
}
- /**
- * Configures a map of default fields and their associated types to be
- * used as the default list of types for every function in this class
- * with a $types param. Useful to avoid repetition when calling the same
- * functions using the same fields and types.
- *
- * If called with no arguments it will return the currently configured types.
- *
- * ### Example
- *
- * ```
- * $query->defaults(['created' => 'datetime', 'is_visible' => 'boolean']);
- * ```
- *
- * This method will replace all the existing default mappings with the ones provided.
- * To add into the mappings use addDefaults()
- *
- * @deprecated 3.4.0 Use setDefaults()/getDefaults() instead.
- * @param array|null $defaults associative array where keys are field names and values
- * are the correspondent type.
- * @return $this|array
- */
- public function defaults(array $defaults = null)
- {
- deprecationWarning(
- 'TypeMap::defaults() is deprecated. ' .
- 'Use TypeMap::setDefaults()/getDefaults() instead.'
- );
- if ($defaults !== null) {
- return $this->setDefaults($defaults);
- }
-
- return $this->getDefaults();
- }
-
/**
* Add additional default types into the type map.
*
@@ -131,7 +98,7 @@ public function defaults(array $defaults = null)
* @param string[] $types The additional types to add.
* @return void
*/
- public function addDefaults(array $types)
+ public function addDefaults(array $types): void
{
$this->_defaults += $types;
}
@@ -163,42 +130,11 @@ public function setTypes(array $types)
*
* @return string[]
*/
- public function getTypes()
+ public function getTypes(): array
{
return $this->_types;
}
- /**
- * Sets a map of fields and their associated types for single-use.
- *
- * If called with no arguments it will return the currently configured types.
- *
- * ### Example
- *
- * ```
- * $query->types(['created' => 'time']);
- * ```
- *
- * This method will replace all the existing type maps with the ones provided.
- *
- * @deprecated 3.4.0 Use setTypes()/getTypes() instead.
- * @param array|null $types associative array where keys are field names and values
- * are the correspondent type.
- * @return $this|array
- */
- public function types(array $types = null)
- {
- deprecationWarning(
- 'TypeMap::types() is deprecated. ' .
- 'Use TypeMap::setTypes()/getTypes() instead.'
- );
- if ($types !== null) {
- return $this->setTypes($types);
- }
-
- return $this->getTypes();
- }
-
/**
* Returns the type of the given column. If there is no single use type is configured,
* the column type will be looked for inside the default mapping. If neither exist,
@@ -207,7 +143,7 @@ public function types(array $types = null)
* @param string|int $column The type for a given column
* @return string|null
*/
- public function type($column)
+ public function type($column): ?string
{
if (isset($this->_types[$column])) {
return $this->_types[$column];
@@ -224,7 +160,7 @@ public function type($column)
*
* @return string[]
*/
- public function toArray()
+ public function toArray(): array
{
return $this->_types + $this->_defaults;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/TypeMapTrait.php b/app/vendor/cakephp/cakephp/src/Database/TypeMapTrait.php
index c041af19c..7e9829e2e 100644
--- a/app/vendor/cakephp/cakephp/src/Database/TypeMapTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/TypeMapTrait.php
@@ -1,4 +1,6 @@
_typeMap === null) {
$this->_typeMap = new TypeMap();
@@ -54,27 +56,6 @@ public function getTypeMap()
return $this->_typeMap;
}
- /**
- * Creates a new TypeMap if $typeMap is an array, otherwise returns the existing type map
- * or exchanges it for the given one.
- *
- * @deprecated 3.4.0 Use setTypeMap()/getTypeMap() instead.
- * @param array|\Cake\Database\TypeMap|null $typeMap Creates a TypeMap if array, otherwise sets the given TypeMap
- * @return $this|\Cake\Database\TypeMap
- */
- public function typeMap($typeMap = null)
- {
- deprecationWarning(
- 'TypeMapTrait::typeMap() is deprecated. ' .
- 'Use TypeMapTrait::setTypeMap()/getTypeMap() instead.'
- );
- if ($typeMap !== null) {
- return $this->setTypeMap($typeMap);
- }
-
- return $this->getTypeMap();
- }
-
/**
* Overwrite the default type mappings for fields
* in the implementing object.
@@ -101,28 +82,8 @@ public function setDefaultTypes(array $types)
*
* @return array
*/
- public function getDefaultTypes()
+ public function getDefaultTypes(): array
{
return $this->getTypeMap()->getDefaults();
}
-
- /**
- * Allows setting default types when chaining query
- *
- * @deprecated 3.4.0 Use setDefaultTypes()/getDefaultTypes() instead.
- * @param array|null $types The array of types to set.
- * @return $this|array
- */
- public function defaultTypes(array $types = null)
- {
- deprecationWarning(
- 'TypeMapTrait::defaultTypes() is deprecated. ' .
- 'Use TypeMapTrait::setDefaultTypes()/getDefaultTypes() instead.'
- );
- if ($types !== null) {
- return $this->setDefaultTypes($types);
- }
-
- return $this->getDefaultTypes();
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/TypedResultInterface.php b/app/vendor/cakephp/cakephp/src/Database/TypedResultInterface.php
index 48e8de0ae..434ff08ca 100644
--- a/app/vendor/cakephp/cakephp/src/Database/TypedResultInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/TypedResultInterface.php
@@ -1,4 +1,6 @@
_returnType;
}
@@ -42,33 +44,10 @@ public function getReturnType()
* @param string $type The name of the type that is to be returned
* @return $this
*/
- public function setReturnType($type)
+ public function setReturnType(string $type)
{
$this->_returnType = $type;
return $this;
}
-
- /**
- * Sets the type of the value this object will generate.
- * If called without arguments, returns the current known type
- *
- * @deprecated 3.5.0 Use getReturnType()/setReturnType() instead.
- * @param string|null $type The name of the type that is to be returned
- * @return string|$this
- */
- public function returnType($type = null)
- {
- deprecationWarning(
- 'TypedResultTrait::returnType() is deprecated. ' .
- 'Use TypedResultTrait::setReturnType()/getReturnType() instead.'
- );
- if ($type !== null) {
- $this->_returnType = $type;
-
- return $this;
- }
-
- return $this->_returnType;
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/ValueBinder.php b/app/vendor/cakephp/cakephp/src/Database/ValueBinder.php
index c18edf7b5..1a63a57d9 100644
--- a/app/vendor/cakephp/cakephp/src/Database/ValueBinder.php
+++ b/app/vendor/cakephp/cakephp/src/Database/ValueBinder.php
@@ -1,4 +1,6 @@
_bindings[$param] = compact('value', 'type') + [
'placeholder' => is_int($param) ? $param : substr($param, 1),
@@ -63,7 +65,7 @@ public function bind($param, $value, $type = 'string')
* if it starts with a colon, then the same string is returned
* @return string to be used as a placeholder in a query expression
*/
- public function placeholder($token)
+ public function placeholder(string $token): string
{
$number = $this->_bindingsCount++;
if ($token[0] !== ':' && $token !== '?') {
@@ -77,11 +79,11 @@ public function placeholder($token)
* Creates unique named placeholders for each of the passed values
* and binds them with the specified type.
*
- * @param array|\Traversable $values The list of values to be bound
- * @param string $type The type with which all values will be bound
+ * @param iterable $values The list of values to be bound
+ * @param string|int|null $type The type with which all values will be bound
* @return array with the placeholders to insert in the query
*/
- public function generateManyNamed($values, $type = 'string')
+ public function generateManyNamed(iterable $values, $type = null): array
{
$placeholders = [];
foreach ($values as $k => $value) {
@@ -103,7 +105,7 @@ public function generateManyNamed($values, $type = 'string')
*
* @return array
*/
- public function bindings()
+ public function bindings(): array
{
return $this->_bindings;
}
@@ -113,7 +115,7 @@ public function bindings()
*
* @return void
*/
- public function reset()
+ public function reset(): void
{
$this->_bindings = [];
$this->_bindingsCount = 0;
@@ -124,7 +126,7 @@ public function reset()
*
* @return void
*/
- public function resetCount()
+ public function resetCount(): void
{
$this->_bindingsCount = 0;
}
@@ -135,7 +137,7 @@ public function resetCount()
* @param \Cake\Database\StatementInterface $statement The statement to add parameters to.
* @return void
*/
- public function attachTo($statement)
+ public function attachTo(StatementInterface $statement): void
{
$bindings = $this->bindings();
if (empty($bindings)) {
diff --git a/app/vendor/cakephp/cakephp/src/Database/composer.json b/app/vendor/cakephp/cakephp/src/Database/composer.json
index 839ffbfee..93251172c 100644
--- a/app/vendor/cakephp/cakephp/src/Database/composer.json
+++ b/app/vendor/cakephp/cakephp/src/Database/composer.json
@@ -24,11 +24,12 @@
"source": "https://github.com/cakephp/database"
},
"require": {
- "php": ">=5.6.0,<8.0.0",
- "cakephp/cache": "^3.6.0",
- "cakephp/core": "^3.6.0",
- "cakephp/datasource": "^3.6.0",
- "cakephp/log": "^3.6.0"
+ "php": ">=7.2.0",
+ "cakephp/core": "^4.0",
+ "cakephp/datasource": "^4.0"
+ },
+ "suggest": {
+ "cakephp/i18n": "If you are using locale-aware datetime formats or Chronos types."
},
"autoload": {
"psr-4": {
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionInterface.php
index e9eb3d3cf..9b9ba8eaa 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionInterface.php
@@ -1,4 +1,6 @@
transactional(function ($connection) {
+ * $connection->newQuery()->delete('users')->execute();
+ * });
+ * ```
+ *
* @param callable $transaction The callback to execute within a transaction.
* @return mixed The return value of the callback.
* @throws \Exception Will re-throw any exception raised in $callback after
@@ -70,6 +107,14 @@ public function transactional(callable $transaction);
*
* Constraints should be re-enabled after the callback succeeds/fails.
*
+ * ### Example:
+ *
+ * ```
+ * $connection->disableConstraints(function ($connection) {
+ * $connection->newQuery()->delete('users')->execute();
+ * });
+ * ```
+ *
* @param callable $operation The callback to execute within a transaction.
* @return mixed The return value of the callback.
* @throws \Exception Will re-throw any exception raised in $callback after
@@ -78,21 +123,24 @@ public function transactional(callable $transaction);
public function disableConstraints(callable $operation);
/**
- * Enables or disables query logging for this connection.
+ * Enable/disable query logging
*
- * @param bool|null $enable whether to turn logging on or disable it.
- * Use null to read current value.
- * @return bool
+ * @param bool $value Enable/disable query logging
+ * @return $this
+ */
+ public function enableQueryLogging(bool $value = true);
+
+ /**
+ * Disable query logging
+ *
+ * @return $this
*/
- public function logQueries($enable = null);
+ public function disableQueryLogging();
/**
- * Sets the logger object instance. When called with no arguments
- * it returns the currently setup logger instance.
+ * Check if query logging is enabled.
*
- * @param object|null $instance logger object instance
- * @return object logger instance
- * @deprecated 3.5.0 Will be replaced by getLogger()/setLogger()
+ * @return bool
*/
- public function logger($instance = null);
+ public function isQueryLoggingEnabled(): bool;
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionManager.php b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionManager.php
index 6ad676b31..eb908be51 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionManager.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionManager.php
@@ -1,4 +1,6 @@
*/
protected static $_dsnClassMap = [
- 'mysql' => 'Cake\Database\Driver\Mysql',
- 'postgres' => 'Cake\Database\Driver\Postgres',
- 'sqlite' => 'Cake\Database\Driver\Sqlite',
- 'sqlserver' => 'Cake\Database\Driver\Sqlserver',
+ 'mysql' => Mysql::class,
+ 'postgres' => Postgres::class,
+ 'sqlite' => Sqlite::class,
+ 'sqlserver' => Sqlserver::class,
];
/**
@@ -70,7 +78,7 @@ class ConnectionManager
* @throws \Cake\Core\Exception\Exception When trying to modify an existing config.
* @see \Cake\Core\StaticConfigTrait::config()
*/
- public static function setConfig($key, $config = null)
+ public static function setConfig($key, $config = null): void
{
if (is_array($config)) {
$config['name'] = $key;
@@ -101,10 +109,10 @@ public static function setConfig($key, $config = null)
*
* Note that query-string arguments are also parsed and set as values in the returned configuration.
*
- * @param string|null $config The DSN string to convert to a configuration array
+ * @param string $config The DSN string to convert to a configuration array
* @return array The configuration array to be stored after parsing the DSN
*/
- public static function parseDsn($config = null)
+ public static function parseDsn(string $config): array
{
$config = static::_parseDsn($config);
@@ -114,7 +122,7 @@ public static function parseDsn($config = null)
if (empty($config['driver'])) {
$config['driver'] = $config['className'];
- $config['className'] = 'Cake\Database\Connection';
+ $config['className'] = Connection::class;
}
unset($config['path']);
@@ -148,7 +156,7 @@ public static function parseDsn($config = null)
* @throws \Cake\Datasource\Exception\MissingDatasourceConfigException When aliasing a
* connection that does not exist.
*/
- public static function alias($alias, $source)
+ public static function alias(string $alias, string $source): void
{
if (empty(static::$_config[$source]) && empty(static::$_config[$alias])) {
throw new MissingDatasourceConfigException(
@@ -167,7 +175,7 @@ public static function alias($alias, $source)
* @param string $name The connection name to remove aliases for.
* @return void
*/
- public static function dropAlias($name)
+ public static function dropAlias(string $name): void
{
unset(static::$_aliasMap[$name]);
}
@@ -186,7 +194,7 @@ public static function dropAlias($name)
* @throws \Cake\Datasource\Exception\MissingDatasourceConfigException When config
* data is missing.
*/
- public static function get($name, $useAliases = true)
+ public static function get(string $name, bool $useAliases = true)
{
if ($useAliases && isset(static::$_aliasMap[$name])) {
$name = static::$_aliasMap[$name];
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionRegistry.php b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionRegistry.php
index a02b0c76a..01b7b5c56 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionRegistry.php
@@ -1,4 +1,6 @@
*/
class ConnectionRegistry extends ObjectRegistry
{
@@ -31,14 +34,11 @@ class ConnectionRegistry extends ObjectRegistry
* Part of the template method for Cake\Core\ObjectRegistry::load()
*
* @param string $class Partial classname to resolve.
- * @return string|false Either the correct classname or false.
+ * @return string|null Either the correct class name or null.
+ * @psalm-return class-string|null
*/
- protected function _resolveClassName($class)
+ protected function _resolveClassName(string $class): ?string
{
- if (is_object($class)) {
- return $class;
- }
-
return App::className($class, 'Datasource');
}
@@ -52,7 +52,7 @@ protected function _resolveClassName($class)
* @return void
* @throws \Cake\Datasource\Exception\MissingDatasourceException
*/
- protected function _throwMissingClassError($class, $plugin)
+ protected function _throwMissingClassError(string $class, ?string $plugin): void
{
throw new MissingDatasourceException([
'class' => $class,
@@ -68,12 +68,12 @@ protected function _throwMissingClassError($class, $plugin)
* If a callable is passed as first argument, The returned value of this
* function will be the result of the callable.
*
- * @param string|object|callable $class The classname or object to make.
+ * @param string|\Cake\Datasource\ConnectionInterface|callable $class The classname or object to make.
* @param string $alias The alias of the object.
* @param array $settings An array of settings to use for the datasource.
- * @return object A connection with the correct settings.
+ * @return \Cake\Datasource\ConnectionInterface A connection with the correct settings.
*/
- protected function _create($class, $alias, $settings)
+ protected function _create($class, string $alias, array $settings)
{
if (is_callable($class)) {
return $class($alias);
@@ -85,6 +85,8 @@ protected function _create($class, $alias, $settings)
unset($settings['className']);
+ // phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.InvalidFormat
+ /** @var \Cake\Datasource\ConnectionInterface */
return new $class($settings);
}
@@ -94,7 +96,7 @@ protected function _create($class, $alias, $settings)
* @param string $name The adapter name.
* @return $this
*/
- public function unload($name)
+ public function unload(string $name)
{
unset($this->_loaded[$name]);
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/EntityInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/EntityInterface.php
index fb4074e88..53bca0618 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/EntityInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/EntityInterface.php
@@ -1,4 +1,6 @@
accessible('*', true)` means that any property not specified already
- * will be accessible by default.
+ * Returns whether or not this entity has already been persisted.
*
- * @deprecated 3.4.0 Use setAccess() and isAccessible() instead.
- * @param string|array $property Either a single or list of properties to change its accessibility.
- * @param bool|null $set true marks the property as accessible, false will
- * mark it as protected.
- * @return \Cake\Datasource\EntityInterface|bool
+ * @return bool Whether or not the entity has been persisted.
*/
- public function accessible($property, $set = null);
+ public function isNew(): bool;
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/EntityTrait.php b/app/vendor/cakephp/cakephp/src/Datasource/EntityTrait.php
index e8a756e8f..08802956f 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/EntityTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/EntityTrait.php
@@ -1,4 +1,6 @@
true`
- * means that any property not defined in the map will be accessible by default
+ * means that any field not defined in the map will be accessible by default
*
* @var array
*/
@@ -121,57 +116,57 @@ trait EntityTrait
*
* @var string
*/
- protected $_registryAlias;
+ protected $_registryAlias = '';
/**
- * Magic getter to access properties that have been set in this entity
+ * Magic getter to access fields that have been set in this entity
*
- * @param string $property Name of the property to access
+ * @param string $field Name of the field to access
* @return mixed
*/
- public function &__get($property)
+ public function &__get(string $field)
{
- return $this->get($property);
+ return $this->get($field);
}
/**
- * Magic setter to add or edit a property in this entity
+ * Magic setter to add or edit a field in this entity
*
- * @param string $property The name of the property to set
- * @param mixed $value The value to set to the property
+ * @param string $field The name of the field to set
+ * @param mixed $value The value to set to the field
* @return void
*/
- public function __set($property, $value)
+ public function __set(string $field, $value): void
{
- $this->set($property, $value);
+ $this->set($field, $value);
}
/**
- * Returns whether this entity contains a property named $property
+ * Returns whether this entity contains a field named $field
* regardless of if it is empty.
*
- * @param string $property The property to check.
+ * @param string $field The field to check.
* @return bool
* @see \Cake\ORM\Entity::has()
*/
- public function __isset($property)
+ public function __isset(string $field): bool
{
- return $this->has($property);
+ return $this->has($field);
}
/**
- * Removes a property from this entity
+ * Removes a field from this entity
*
- * @param string $property The property to unset
+ * @param string $field The field to unset
* @return void
*/
- public function __unset($property)
+ public function __unset(string $field): void
{
- $this->unsetProperty($property);
+ $this->unset($field);
}
/**
- * Sets a single property inside this entity.
+ * Sets a single field inside this entity.
*
* ### Example:
*
@@ -179,9 +174,9 @@ public function __unset($property)
* $entity->set('name', 'Andrew');
* ```
*
- * It is also possible to mass-assign multiple properties to this entity
- * with one call by passing a hashed array as properties in the form of
- * property => value pairs
+ * It is also possible to mass-assign multiple fields to this entity
+ * with one call by passing a hashed array as fields in the form of
+ * field => value pairs
*
* ### Example:
*
@@ -192,7 +187,7 @@ public function __unset($property)
* ```
*
* Some times it is handy to bypass setter functions in this entity when assigning
- * properties. You can achieve this by disabling the `setter` option using the
+ * fields. You can achieve this by disabling the `setter` option using the
* `$options` parameter:
*
* ```
@@ -201,92 +196,92 @@ public function __unset($property)
* ```
*
* Mass assignment should be treated carefully when accepting user input, by default
- * entities will guard all fields when properties are assigned in bulk. You can disable
+ * entities will guard all fields when fields are assigned in bulk. You can disable
* the guarding for a single set call with the `guard` option:
*
* ```
- * $entity->set(['name' => 'Andrew', 'id' => 1], ['guard' => true]);
+ * $entity->set(['name' => 'Andrew', 'id' => 1], ['guard' => false]);
* ```
*
- * You do not need to use the guard option when assigning properties individually:
+ * You do not need to use the guard option when assigning fields individually:
*
* ```
* // No need to use the guard option.
* $entity->set('name', 'Andrew');
* ```
*
- * @param string|array $property the name of property to set or a list of
- * properties with their respective values
- * @param mixed $value The value to set to the property or an array if the
+ * @param string|array $field the name of field to set or a list of
+ * fields with their respective values
+ * @param mixed $value The value to set to the field or an array if the
* first argument is also an array, in which case will be treated as $options
- * @param array $options options to be used for setting the property. Allowed option
+ * @param array $options options to be used for setting the field. Allowed option
* keys are `setter` and `guard`
* @return $this
* @throws \InvalidArgumentException
*/
- public function set($property, $value = null, array $options = [])
+ public function set($field, $value = null, array $options = [])
{
- if (is_string($property) && $property !== '') {
+ if (is_string($field) && $field !== '') {
$guard = false;
- $property = [$property => $value];
+ $field = [$field => $value];
} else {
$guard = true;
$options = (array)$value;
}
- if (!is_array($property)) {
- throw new InvalidArgumentException('Cannot set an empty property');
+ if (!is_array($field)) {
+ throw new InvalidArgumentException('Cannot set an empty field');
}
$options += ['setter' => true, 'guard' => $guard];
- foreach ($property as $p => $value) {
- if ($options['guard'] === true && !$this->isAccessible($p)) {
+ foreach ($field as $name => $value) {
+ if ($options['guard'] === true && !$this->isAccessible($name)) {
continue;
}
- $this->setDirty($p, true);
+ $this->setDirty($name, true);
if (
- !array_key_exists($p, $this->_original) &&
- array_key_exists($p, $this->_properties) &&
- $this->_properties[$p] !== $value
+ !array_key_exists($name, $this->_original) &&
+ array_key_exists($name, $this->_fields) &&
+ $this->_fields[$name] !== $value
) {
- $this->_original[$p] = $this->_properties[$p];
+ $this->_original[$name] = $this->_fields[$name];
}
if (!$options['setter']) {
- $this->_properties[$p] = $value;
+ $this->_fields[$name] = $value;
continue;
}
- $setter = static::_accessor($p, 'set');
+ $setter = static::_accessor($name, 'set');
if ($setter) {
$value = $this->{$setter}($value);
}
- $this->_properties[$p] = $value;
+ $this->_fields[$name] = $value;
}
return $this;
}
/**
- * Returns the value of a property by name
+ * Returns the value of a field by name
*
- * @param string $property the name of the property to retrieve
+ * @param string $field the name of the field to retrieve
* @return mixed
- * @throws \InvalidArgumentException if an empty property name is passed
+ * @throws \InvalidArgumentException if an empty field name is passed
*/
- public function &get($property)
+ public function &get(string $field)
{
- if (!strlen((string)$property)) {
- throw new InvalidArgumentException('Cannot get an empty property');
+ if ($field === '') {
+ throw new InvalidArgumentException('Cannot get an empty field');
}
$value = null;
- $method = static::_accessor($property, 'get');
+ $method = static::_accessor($field, 'get');
- if (isset($this->_properties[$property])) {
- $value =& $this->_properties[$property];
+ if (isset($this->_fields[$field])) {
+ $value = &$this->_fields[$field];
}
if ($method) {
@@ -299,22 +294,22 @@ public function &get($property)
}
/**
- * Returns the value of an original property by name
+ * Returns the value of an original field by name
*
- * @param string $property the name of the property for which original value is retrieved.
+ * @param string $field the name of the field for which original value is retrieved.
* @return mixed
- * @throws \InvalidArgumentException if an empty property name is passed.
+ * @throws \InvalidArgumentException if an empty field name is passed.
*/
- public function getOriginal($property)
+ public function getOriginal(string $field)
{
- if (!strlen((string)$property)) {
- throw new InvalidArgumentException('Cannot get an empty property');
+ if (!strlen($field)) {
+ throw new InvalidArgumentException('Cannot get an empty field');
}
- if (array_key_exists($property, $this->_original)) {
- return $this->_original[$property];
+ if (array_key_exists($field, $this->_original)) {
+ return $this->_original[$field];
}
- return $this->get($property);
+ return $this->get($field);
}
/**
@@ -322,12 +317,12 @@ public function getOriginal($property)
*
* @return array
*/
- public function getOriginalValues()
+ public function getOriginalValues(): array
{
$originals = $this->_original;
$originalKeys = array_keys($originals);
- foreach ($this->_properties as $key => $value) {
- if (!in_array($key, $originalKeys)) {
+ foreach ($this->_fields as $key => $value) {
+ if (!in_array($key, $originalKeys, true)) {
$originals[$key] = $value;
}
}
@@ -336,7 +331,7 @@ public function getOriginalValues()
}
/**
- * Returns whether this entity contains a property named $property
+ * Returns whether this entity contains a field named $field
* that contains a non-null value.
*
* ### Example:
@@ -348,23 +343,23 @@ public function getOriginalValues()
* $entity->has('last_name'); // false
* ```
*
- * You can check multiple properties by passing an array:
+ * You can check multiple fields by passing an array:
*
* ```
* $entity->has(['name', 'last_name']);
* ```
*
- * All properties must not be null to get a truthy result.
+ * All fields must not be null to get a truthy result.
*
- * When checking multiple properties. All properties must not be null
+ * When checking multiple fields. All fields must not be null
* in order for true to be returned.
*
- * @param string|string[] $property The property or properties to check.
+ * @param string|string[] $field The field or fields to check.
* @return bool
*/
- public function has($property)
+ public function has($field): bool
{
- foreach ((array)$property as $prop) {
+ foreach ((array)$field as $prop) {
if ($this->get($prop) === null) {
return false;
}
@@ -374,7 +369,7 @@ public function has($property)
}
/**
- * Checks that a property is empty
+ * Checks that a field is empty
*
* This is not working like the PHP `empty()` function. The method will
* return true for:
@@ -385,12 +380,12 @@ public function has($property)
*
* and false in all other cases.
*
- * @param string $property The property to check.
+ * @param string $field The field to check.
* @return bool
*/
- public function isEmpty($property)
+ public function isEmpty(string $field): bool
{
- $value = $this->get($property);
+ $value = $this->get($field);
if (
$value === null ||
(
@@ -398,7 +393,7 @@ public function isEmpty($property)
empty($value) ||
(
is_string($value) &&
- $value === ''
+ empty($value)
)
)
) {
@@ -409,7 +404,7 @@ public function isEmpty($property)
}
/**
- * Checks tha a property has a value.
+ * Checks tha a field has a value.
*
* This method will return true for
*
@@ -421,210 +416,155 @@ public function isEmpty($property)
*
* and false in all other cases.
*
- * @param string $property The property to check.
+ * @param string $field The field to check.
* @return bool
*/
- public function hasValue($property)
+ public function hasValue(string $field): bool
{
- return !$this->isEmpty($property);
+ return !$this->isEmpty($field);
}
/**
- * Removes a property or list of properties from this entity
+ * Removes a field or list of fields from this entity
*
* ### Examples:
*
* ```
- * $entity->unsetProperty('name');
- * $entity->unsetProperty(['name', 'last_name']);
+ * $entity->unset('name');
+ * $entity->unset(['name', 'last_name']);
* ```
*
- * @param string|string[] $property The property to unset.
+ * @param string|string[] $field The field to unset.
* @return $this
*/
- public function unsetProperty($property)
+ public function unset($field)
{
- $property = (array)$property;
- foreach ($property as $p) {
- unset($this->_properties[$p], $this->_dirty[$p]);
+ $field = (array)$field;
+ foreach ($field as $p) {
+ unset($this->_fields[$p], $this->_original[$p], $this->_dirty[$p]);
}
return $this;
}
/**
- * Get/Set the hidden properties on this entity.
- *
- * If the properties argument is null, the currently hidden properties
- * will be returned. Otherwise the hidden properties will be set.
+ * Removes a field or list of fields from this entity
*
- * @deprecated 3.4.0 Use EntityTrait::setHidden() and EntityTrait::getHidden()
- * @param string[]|null $properties Either an array of properties to hide or null to get properties
- * @return string[]|$this
+ * @deprecated 4.0.0 Use {@link unset()} instead. Will be removed in 5.0.
+ * @param string|string[] $field The field to unset.
+ * @return $this
*/
- public function hiddenProperties($properties = null)
+ public function unsetProperty($field)
{
- deprecationWarning(
- get_called_class() . '::hiddenProperties() is deprecated. ' .
- 'Use setHidden()/getHidden() instead.'
- );
- if ($properties === null) {
- return $this->_hidden;
- }
- $this->_hidden = $properties;
-
- return $this;
+ return $this->unset($field);
}
/**
- * Sets hidden properties.
+ * Sets hidden fields.
*
- * @param string[] $properties An array of properties to hide from array exports.
- * @param bool $merge Merge the new properties with the existing. By default false.
+ * @param string[] $fields An array of fields to hide from array exports.
+ * @param bool $merge Merge the new fields with the existing. By default false.
* @return $this
*/
- public function setHidden(array $properties, $merge = false)
+ public function setHidden(array $fields, bool $merge = false)
{
if ($merge === false) {
- $this->_hidden = $properties;
+ $this->_hidden = $fields;
return $this;
}
- $properties = array_merge($this->_hidden, $properties);
- $this->_hidden = array_unique($properties);
+ $fields = array_merge($this->_hidden, $fields);
+ $this->_hidden = array_unique($fields);
return $this;
}
/**
- * Gets the hidden properties.
+ * Gets the hidden fields.
*
* @return string[]
*/
- public function getHidden()
+ public function getHidden(): array
{
return $this->_hidden;
}
/**
- * Get/Set the virtual properties on this entity.
- *
- * If the properties argument is null, the currently virtual properties
- * will be returned. Otherwise the virtual properties will be set.
- *
- * @deprecated 3.4.0 Use EntityTrait::getVirtual() and EntityTrait::setVirtual()
- * @param string[]|null $properties Either an array of properties to treat as virtual or null to get properties
- * @return string[]|$this
- */
- public function virtualProperties($properties = null)
- {
- deprecationWarning(
- get_called_class() . '::virtualProperties() is deprecated. ' .
- 'Use setVirtual()/getVirtual() instead.'
- );
- if ($properties === null) {
- return $this->getVirtual();
- }
-
- return $this->setVirtual($properties);
- }
-
- /**
- * Sets the virtual properties on this entity.
+ * Sets the virtual fields on this entity.
*
- * @param string[] $properties An array of properties to treat as virtual.
- * @param bool $merge Merge the new properties with the existing. By default false.
+ * @param string[] $fields An array of fields to treat as virtual.
+ * @param bool $merge Merge the new fields with the existing. By default false.
* @return $this
*/
- public function setVirtual(array $properties, $merge = false)
+ public function setVirtual(array $fields, bool $merge = false)
{
if ($merge === false) {
- $this->_virtual = $properties;
+ $this->_virtual = $fields;
return $this;
}
- $properties = array_merge($this->_virtual, $properties);
- $this->_virtual = array_unique($properties);
+ $fields = array_merge($this->_virtual, $fields);
+ $this->_virtual = array_unique($fields);
return $this;
}
/**
- * Gets the virtual properties on this entity.
+ * Gets the virtual fields on this entity.
*
* @return string[]
*/
- public function getVirtual()
+ public function getVirtual(): array
{
return $this->_virtual;
}
/**
- * Gets the list of visible properties.
- *
- * The list of visible properties is all standard properties
- * plus virtual properties minus hidden properties.
- *
- * @return string[] A list of properties that are 'visible' in all
- * representations.
- */
- public function getVisible()
- {
- $properties = array_keys($this->_properties);
- $properties = array_merge($properties, $this->_virtual);
-
- return array_diff($properties, $this->_hidden);
- }
-
- /**
- * Gets the list of visible properties.
+ * Gets the list of visible fields.
*
- * The list of visible properties is all standard properties
- * plus virtual properties minus hidden properties.
+ * The list of visible fields is all standard fields
+ * plus virtual fields minus hidden fields.
*
- * @return string[] A list of properties that are 'visible' in all
+ * @return string[] A list of fields that are 'visible' in all
* representations.
- * @deprecated 3.8.0 Use getVisible() instead.
*/
- public function visibleProperties()
+ public function getVisible(): array
{
- deprecationWarning(
- get_called_class() . '::visibleProperties() is deprecated. ' .
- 'Use getVisible() instead.'
- );
+ $fields = array_keys($this->_fields);
+ $fields = array_merge($fields, $this->_virtual);
- return $this->getVisible();
+ return array_diff($fields, $this->_hidden);
}
/**
- * Returns an array with all the properties that have been set
+ * Returns an array with all the fields that have been set
* to this entity
*
- * This method will recursively transform entities assigned to properties
+ * This method will recursively transform entities assigned to fields
* into arrays as well.
*
* @return array
*/
- public function toArray()
+ public function toArray(): array
{
$result = [];
- foreach ($this->getVisible() as $property) {
- $value = $this->get($property);
+ foreach ($this->getVisible() as $field) {
+ $value = $this->get($field);
if (is_array($value)) {
- $result[$property] = [];
+ $result[$field] = [];
foreach ($value as $k => $entity) {
if ($entity instanceof EntityInterface) {
- $result[$property][$k] = $entity->toArray();
+ $result[$field][$k] = $entity->toArray();
} else {
- $result[$property][$k] = $entity;
+ $result[$field][$k] = $entity;
}
}
} elseif ($value instanceof EntityInterface) {
- $result[$property] = $value->toArray();
+ $result[$field] = $value->toArray();
} else {
- $result[$property] = $value;
+ $result[$field] = $value;
}
}
@@ -632,11 +572,11 @@ public function toArray()
}
/**
- * Returns the properties that will be serialized as JSON
+ * Returns the fields that will be serialized as JSON
*
* @return array
*/
- public function jsonSerialize()
+ public function jsonSerialize(): array
{
return $this->extract($this->getVisible());
}
@@ -644,10 +584,10 @@ public function jsonSerialize()
/**
* Implements isset($entity);
*
- * @param mixed $offset The offset to check.
+ * @param string $offset The offset to check.
* @return bool Success
*/
- public function offsetExists($offset)
+ public function offsetExists($offset): bool
{
return $this->has($offset);
}
@@ -655,7 +595,7 @@ public function offsetExists($offset)
/**
* Implements $entity[$offset];
*
- * @param mixed $offset The offset to get.
+ * @param string $offset The offset to get.
* @return mixed
*/
public function &offsetGet($offset)
@@ -666,11 +606,11 @@ public function &offsetGet($offset)
/**
* Implements $entity[$offset] = $value;
*
- * @param mixed $offset The offset to set.
+ * @param string $offset The offset to set.
* @param mixed $value The value to set.
* @return void
*/
- public function offsetSet($offset, $value)
+ public function offsetSet($offset, $value): void
{
$this->set($offset, $value);
}
@@ -678,12 +618,12 @@ public function offsetSet($offset, $value)
/**
* Implements unset($result[$offset]);
*
- * @param mixed $offset The offset to remove.
+ * @param string $offset The offset to remove.
* @return void
*/
- public function offsetUnset($offset)
+ public function offsetUnset($offset): void
{
- $this->unsetProperty($offset);
+ $this->unset($offset);
}
/**
@@ -694,7 +634,7 @@ public function offsetUnset($offset)
* @param string $type the accessor type ('get' or 'set')
* @return string method name or empty string (no method available)
*/
- protected static function _accessor($property, $type)
+ protected static function _accessor(string $property, string $type): string
{
$class = static::class;
@@ -706,7 +646,7 @@ protected static function _accessor($property, $type)
return static::$_accessors[$class][$type][$property] = '';
}
- if ($class === 'Cake\ORM\Entity') {
+ if (static::class === Entity::class) {
return '';
}
@@ -731,19 +671,19 @@ protected static function _accessor($property, $type)
}
/**
- * Returns an array with the requested properties
- * stored in this entity, indexed by property name
+ * Returns an array with the requested fields
+ * stored in this entity, indexed by field name
*
- * @param string[] $properties list of properties to be returned
- * @param bool $onlyDirty Return the requested property only if it is dirty
+ * @param string[] $fields list of fields to be returned
+ * @param bool $onlyDirty Return the requested field only if it is dirty
* @return array
*/
- public function extract(array $properties, $onlyDirty = false)
+ public function extract(array $fields, bool $onlyDirty = false): array
{
$result = [];
- foreach ($properties as $property) {
- if (!$onlyDirty || $this->isDirty($property)) {
- $result[$property] = $this->get($property);
+ foreach ($fields as $field) {
+ if (!$onlyDirty || $this->isDirty($field)) {
+ $result[$field] = $this->get($field);
}
}
@@ -751,42 +691,42 @@ public function extract(array $properties, $onlyDirty = false)
}
/**
- * Returns an array with the requested original properties
- * stored in this entity, indexed by property name.
+ * Returns an array with the requested original fields
+ * stored in this entity, indexed by field name.
*
- * Properties that are unchanged from their original value will be included in the
+ * Fields that are unchanged from their original value will be included in the
* return of this method.
*
- * @param string[] $properties List of properties to be returned
+ * @param string[] $fields List of fields to be returned
* @return array
*/
- public function extractOriginal(array $properties)
+ public function extractOriginal(array $fields): array
{
$result = [];
- foreach ($properties as $property) {
- $result[$property] = $this->getOriginal($property);
+ foreach ($fields as $field) {
+ $result[$field] = $this->getOriginal($field);
}
return $result;
}
/**
- * Returns an array with only the original properties
- * stored in this entity, indexed by property name.
+ * Returns an array with only the original fields
+ * stored in this entity, indexed by field name.
*
- * This method will only return properties that have been modified since
- * the entity was built. Unchanged properties will be omitted.
+ * This method will only return fields that have been modified since
+ * the entity was built. Unchanged fields will be omitted.
*
- * @param string[] $properties List of properties to be returned
+ * @param string[] $fields List of fields to be returned
* @return array
*/
- public function extractOriginalChanged(array $properties)
+ public function extractOriginalChanged(array $fields): array
{
$result = [];
- foreach ($properties as $property) {
- $original = $this->getOriginal($property);
- if ($original !== $this->get($property)) {
- $result[$property] = $original;
+ foreach ($fields as $field) {
+ $original = $this->getOriginal($field);
+ if ($original !== $this->get($field)) {
+ $result[$field] = $original;
}
}
@@ -794,94 +734,60 @@ public function extractOriginalChanged(array $properties)
}
/**
- * Sets the dirty status of a single property. If called with no second
- * argument, it will return whether the property was modified or not
- * after the object creation.
- *
- * When called with no arguments it will return whether or not there are any
- * dirty property in the entity
- *
- * @deprecated 3.4.0 Use EntityTrait::setDirty() and EntityTrait::isDirty()
- * @param string|null $property the field to set or check status for
- * @param bool|null $isDirty true means the property was changed, false means
- * it was not changed and null will make the function return current state
- * for that property
- * @return bool Whether the property was changed or not
- */
- public function dirty($property = null, $isDirty = null)
- {
- deprecationWarning(
- get_called_class() . '::dirty() is deprecated. ' .
- 'Use setDirty()/isDirty() instead.'
- );
- if ($property === null) {
- return $this->isDirty();
- }
-
- if ($isDirty === null) {
- return $this->isDirty($property);
- }
-
- $this->setDirty($property, $isDirty);
-
- return true;
- }
-
- /**
- * Sets the dirty status of a single property.
+ * Sets the dirty status of a single field.
*
- * @param string $property the field to set or check status for
- * @param bool $isDirty true means the property was changed, false means
+ * @param string $field the field to set or check status for
+ * @param bool $isDirty true means the field was changed, false means
* it was not changed. Defaults to true.
* @return $this
*/
- public function setDirty($property, $isDirty = true)
+ public function setDirty(string $field, bool $isDirty = true)
{
if ($isDirty === false) {
- unset($this->_dirty[$property]);
+ unset($this->_dirty[$field]);
return $this;
}
- $this->_dirty[$property] = true;
- unset($this->_errors[$property], $this->_invalid[$property]);
+ $this->_dirty[$field] = true;
+ unset($this->_errors[$field], $this->_invalid[$field]);
return $this;
}
/**
- * Checks if the entity is dirty or if a single property of it is dirty.
+ * Checks if the entity is dirty or if a single field of it is dirty.
*
- * @param string|null $property The field to check the status for. Null for the whole entity.
- * @return bool Whether the property was changed or not
+ * @param string|null $field The field to check the status for. Null for the whole entity.
+ * @return bool Whether the field was changed or not
*/
- public function isDirty($property = null)
+ public function isDirty(?string $field = null): bool
{
- if ($property === null) {
+ if ($field === null) {
return !empty($this->_dirty);
}
- return isset($this->_dirty[$property]);
+ return isset($this->_dirty[$field]);
}
/**
- * Gets the dirty properties.
+ * Gets the dirty fields.
*
* @return string[]
*/
- public function getDirty()
+ public function getDirty(): array
{
return array_keys($this->_dirty);
}
/**
* Sets the entire entity as clean, which means that it will appear as
- * no properties being modified or added at all. This is an useful call
+ * no fields being modified or added at all. This is an useful call
* for an initial object hydration
*
* @return void
*/
- public function clean()
+ public function clean(): void
{
$this->_dirty = [];
$this->_errors = [];
@@ -898,10 +804,10 @@ public function clean()
* @param bool $new Indicate whether or not this entity has been persisted.
* @return $this
*/
- public function setNew($new)
+ public function setNew(bool $new)
{
if ($new) {
- foreach ($this->_properties as $k => $p) {
+ foreach ($this->_fields as $k => $p) {
$this->_dirty[$k] = true;
}
}
@@ -914,14 +820,14 @@ public function setNew($new)
/**
* Returns whether or not this entity has already been persisted.
*
- * @param bool|null $new true if it is known this instance was not yet persisted.
- * This will be deprecated in 4.0, use `setNew()` instead.
* @return bool Whether or not the entity has been persisted.
*/
- public function isNew($new = null)
+ public function isNew(): bool
{
- if ($new !== null) {
- $this->setNew($new);
+ if (func_num_args()) {
+ deprecationWarning('Using isNew() as setter is deprecated. Use setNew() instead.');
+
+ $this->setNew(func_get_arg(0));
}
return $this->_new;
@@ -933,7 +839,7 @@ public function isNew($new = null)
* @param bool $includeNested true will check nested entities for hasErrors()
* @return bool
*/
- public function hasErrors($includeNested = true)
+ public function hasErrors(bool $includeNested = true): bool
{
if (Hash::filter($this->_errors)) {
return true;
@@ -943,8 +849,8 @@ public function hasErrors($includeNested = true)
return false;
}
- foreach ($this->_properties as $property) {
- if ($this->_readHasErrors($property)) {
+ foreach ($this->_fields as $field) {
+ if ($this->_readHasErrors($field)) {
return true;
}
}
@@ -957,9 +863,9 @@ public function hasErrors($includeNested = true)
*
* @return array
*/
- public function getErrors()
+ public function getErrors(): array
{
- $diff = array_diff_key($this->_properties, $this->_errors);
+ $diff = array_diff_key($this->_fields, $this->_errors);
return $this->_errors + (new Collection($diff))
->filter(function ($value) {
@@ -978,9 +884,9 @@ public function getErrors()
* @param string $field Field name to get the errors from
* @return array
*/
- public function getError($field)
+ public function getError(string $field): array
{
- $errors = isset($this->_errors[$field]) ? $this->_errors[$field] : [];
+ $errors = $this->_errors[$field] ?? [];
if ($errors) {
return $errors;
}
@@ -1002,7 +908,7 @@ public function getError($field)
* @param bool $overwrite Whether or not to overwrite pre-existing errors for $fields
* @return $this
*/
- public function setErrors(array $errors, $overwrite = false)
+ public function setErrors(array $errors, bool $overwrite = false)
{
if ($overwrite) {
foreach ($errors as $f => $error) {
@@ -1045,7 +951,7 @@ public function setErrors(array $errors, $overwrite = false)
* @param bool $overwrite Whether or not to overwrite pre-existing errors for $field
* @return $this
*/
- public function setError($field, $errors, $overwrite = false)
+ public function setError(string $field, $errors, bool $overwrite = false)
{
if (is_string($errors)) {
$errors = [$errors];
@@ -1054,66 +960,13 @@ public function setError($field, $errors, $overwrite = false)
return $this->setErrors([$field => $errors], $overwrite);
}
- /**
- * Sets the error messages for a field or a list of fields. When called
- * without the second argument it returns the validation
- * errors for the specified fields. If called with no arguments it returns
- * all the validation error messages stored in this entity and any other nested
- * entity.
- *
- * ### Example
- *
- * ```
- * // Sets the error messages for a single field
- * $entity->errors('salary', ['must be numeric', 'must be a positive number']);
- *
- * // Returns the error messages for a single field
- * $entity->getErrors('salary');
- *
- * // Returns all error messages indexed by field name
- * $entity->getErrors();
- *
- * // Sets the error messages for multiple fields at once
- * $entity->getErrors(['salary' => ['message'], 'name' => ['another message']);
- * ```
- *
- * When used as a setter, this method will return this entity instance for method
- * chaining.
- *
- * @deprecated 3.4.0 Use EntityTrait::setError(), EntityTrait::setErrors(), EntityTrait::getError() and EntityTrait::getErrors()
- * @param string|array|null $field The field to get errors for, or the array of errors to set.
- * @param string|array|null $errors The errors to be set for $field
- * @param bool $overwrite Whether or not to overwrite pre-existing errors for $field
- * @return array|$this
- */
- public function errors($field = null, $errors = null, $overwrite = false)
- {
- deprecationWarning(
- get_called_class() . '::errors() is deprecated. ' .
- 'Use setError()/getError() or setErrors()/getErrors() instead.'
- );
- if ($field === null) {
- return $this->getErrors();
- }
-
- if (is_string($field) && $errors === null) {
- return $this->getError($field);
- }
-
- if (!is_array($field)) {
- $field = [$field => $errors];
- }
-
- return $this->setErrors($field, $overwrite);
- }
-
/**
* Auxiliary method for getting errors in nested entities
*
* @param string $field the field in this entity to check for errors
* @return array errors in nested entity if any
*/
- protected function _nestedErrors($field)
+ protected function _nestedErrors(string $field): array
{
// Only one path element, check for nested entity with error.
if (strpos($field, '.') === false) {
@@ -1137,7 +990,7 @@ protected function _nestedErrors($field)
if ($entity instanceof EntityInterface) {
$val = $entity->get($part);
} elseif (is_array($entity)) {
- $val = isset($entity[$part]) ? $entity[$part] : false;
+ $val = $entity[$part] ?? false;
}
if (
@@ -1161,10 +1014,10 @@ protected function _nestedErrors($field)
/**
* Reads if there are errors for one or many objects.
*
- * @param mixed $object The object to read errors from.
+ * @param array|\Cake\Datasource\EntityInterface $object The object to read errors from.
* @return bool
*/
- protected function _readHasErrors($object)
+ protected function _readHasErrors($object): bool
{
if ($object instanceof EntityInterface && $object->hasErrors()) {
return true;
@@ -1184,11 +1037,11 @@ protected function _readHasErrors($object)
/**
* Read the error(s) from one or many objects.
*
- * @param array|\Cake\Datasource\EntityInterface $object The object to read errors from.
+ * @param iterable|\Cake\Datasource\EntityInterface $object The object to read errors from.
* @param string|null $path The field name for errors.
* @return array
*/
- protected function _readError($object, $path = null)
+ protected function _readError($object, $path = null): array
{
if ($path !== null && $object instanceof EntityInterface) {
return $object->getError($path);
@@ -1196,12 +1049,12 @@ protected function _readError($object, $path = null)
if ($object instanceof EntityInterface) {
return $object->getErrors();
}
- if (is_array($object)) {
+ if (is_iterable($object)) {
$array = array_map(function ($val) {
if ($val instanceof EntityInterface) {
return $val->getErrors();
}
- }, $object);
+ }, (array)$object);
return array_filter($array);
}
@@ -1214,7 +1067,7 @@ protected function _readError($object, $path = null)
*
* @return array
*/
- public function getInvalid()
+ public function getInvalid(): array
{
return $this->_invalid;
}
@@ -1225,25 +1078,23 @@ public function getInvalid()
* @param string $field The name of the field.
* @return mixed|null
*/
- public function getInvalidField($field)
+ public function getInvalidField(string $field)
{
- $value = isset($this->_invalid[$field]) ? $this->_invalid[$field] : null;
-
- return $value;
+ return $this->_invalid[$field] ?? null;
}
/**
* Set fields as invalid and not patchable into the entity.
*
* This is useful for batch operations when one needs to get the original value for an error message after patching.
- * This value could not be patched into the entity and is simply copied into the _invalid property for debugging purposes
- * or to be able to log it away.
+ * This value could not be patched into the entity and is simply copied into the _invalid property for debugging
+ * purposes or to be able to log it away.
*
* @param array $fields The values to set.
* @param bool $overwrite Whether or not to overwrite pre-existing values for $field.
* @return $this
*/
- public function setInvalid(array $fields, $overwrite = false)
+ public function setInvalid(array $fields, bool $overwrite = false)
{
foreach ($fields as $field => $value) {
if ($overwrite === true) {
@@ -1263,7 +1114,7 @@ public function setInvalid(array $fields, $overwrite = false)
* @param mixed $value The invalid value to be set for $field.
* @return $this
*/
- public function setInvalidField($field, $value)
+ public function setInvalidField(string $field, $value)
{
$this->_invalid[$field] = $value;
@@ -1271,104 +1122,13 @@ public function setInvalidField($field, $value)
}
/**
- * Sets a field as invalid and not patchable into the entity.
- *
- * This is useful for batch operations when one needs to get the original value for an error message after patching.
- * This value could not be patched into the entity and is simply copied into the _invalid property for debugging purposes
- * or to be able to log it away.
- *
- * @deprecated 3.5 Use getInvalid()/getInvalidField()/setInvalid() instead.
- * @param string|array|null $field The field to get invalid value for, or the value to set.
- * @param mixed|null $value The invalid value to be set for $field.
- * @param bool $overwrite Whether or not to overwrite pre-existing values for $field.
- * @return $this|mixed
- */
- public function invalid($field = null, $value = null, $overwrite = false)
- {
- deprecationWarning(
- get_called_class() . '::invalid() is deprecated. ' .
- 'Use setInvalid()/getInvalid()/getInvalidField() instead.'
- );
- if ($field === null) {
- return $this->_invalid;
- }
-
- if (is_string($field) && $value === null) {
- $value = isset($this->_invalid[$field]) ? $this->_invalid[$field] : null;
-
- return $value;
- }
-
- if (!is_array($field)) {
- $field = [$field => $value];
- }
-
- foreach ($field as $f => $value) {
- if ($overwrite) {
- $this->_invalid[$f] = $value;
- continue;
- }
- $this->_invalid += [$f => $value];
- }
-
- return $this;
- }
-
- /**
- * Stores whether or not a property value can be changed or set in this entity.
- * The special property `*` can also be marked as accessible or protected, meaning
- * that any other property specified before will take its value. For example
- * `$entity->accessible('*', true)` means that any property not specified already
- * will be accessible by default.
- *
- * You can also call this method with an array of properties, in which case they
- * will each take the accessibility value specified in the second argument.
- *
- * ### Example:
- *
- * ```
- * $entity->accessible('id', true); // Mark id as not protected
- * $entity->accessible('author_id', false); // Mark author_id as protected
- * $entity->accessible(['id', 'user_id'], true); // Mark both properties as accessible
- * $entity->accessible('*', false); // Mark all properties as protected
- * ```
- *
- * When called without the second param it will return whether or not the property
- * can be set.
- *
- * ### Example:
- *
- * ```
- * $entity->accessible('id'); // Returns whether it can be set or not
- * ```
- *
- * @deprecated 3.4.0 Use EntityTrait::setAccess() and EntityTrait::isAccessible()
- * @param string|array $property single or list of properties to change its accessibility
- * @param bool|null $set true marks the property as accessible, false will
- * mark it as protected.
- * @return $this|bool
- */
- public function accessible($property, $set = null)
- {
- deprecationWarning(
- get_called_class() . '::accessible() is deprecated. ' .
- 'Use setAccess()/isAccessible() instead.'
- );
- if ($set === null) {
- return $this->isAccessible($property);
- }
-
- return $this->setAccess($property, $set);
- }
-
- /**
- * Stores whether or not a property value can be changed or set in this entity.
- * The special property `*` can also be marked as accessible or protected, meaning
- * that any other property specified before will take its value. For example
- * `$entity->setAccess('*', true)` means that any property not specified already
+ * Stores whether or not a field value can be changed or set in this entity.
+ * The special field `*` can also be marked as accessible or protected, meaning
+ * that any other field specified before will take its value. For example
+ * `$entity->setAccess('*', true)` means that any field not specified already
* will be accessible by default.
*
- * You can also call this method with an array of properties, in which case they
+ * You can also call this method with an array of fields, in which case they
* will each take the accessibility value specified in the second argument.
*
* ### Example:
@@ -1376,18 +1136,18 @@ public function accessible($property, $set = null)
* ```
* $entity->setAccess('id', true); // Mark id as not protected
* $entity->setAccess('author_id', false); // Mark author_id as protected
- * $entity->setAccess(['id', 'user_id'], true); // Mark both properties as accessible
- * $entity->setAccess('*', false); // Mark all properties as protected
+ * $entity->setAccess(['id', 'user_id'], true); // Mark both fields as accessible
+ * $entity->setAccess('*', false); // Mark all fields as protected
* ```
*
- * @param string|string[] $property single or list of properties to change its accessibility
- * @param bool $set true marks the property as accessible, false will
+ * @param string|array $field Single or list of fields to change its accessibility
+ * @param bool $set True marks the field as accessible, false will
* mark it as protected.
* @return $this
*/
- public function setAccess($property, $set)
+ public function setAccess($field, bool $set)
{
- if ($property === '*') {
+ if ($field === '*') {
$this->_accessible = array_map(function ($p) use ($set) {
return (bool)$set;
}, $this->_accessible);
@@ -1396,7 +1156,7 @@ public function setAccess($property, $set)
return $this;
}
- foreach ((array)$property as $prop) {
+ foreach ((array)$field as $prop) {
$this->_accessible[$prop] = (bool)$set;
}
@@ -1404,18 +1164,7 @@ public function setAccess($property, $set)
}
/**
- * Returns the raw accessible configuration for this entity.
- * The `*` wildcard refers to all fields.
- *
- * @return bool[]
- */
- public function getAccessible()
- {
- return $this->_accessible;
- }
-
- /**
- * Checks if a property is accessible
+ * Checks if a field is accessible
*
* ### Example:
*
@@ -1423,13 +1172,12 @@ public function getAccessible()
* $entity->isAccessible('id'); // Returns whether it can be set or not
* ```
*
- * @param string $property Property name to check
+ * @param string $field Field name to check
* @return bool
*/
- public function isAccessible($property)
+ public function isAccessible(string $field): bool
{
- $value = isset($this->_accessible[$property]) ?
- $this->_accessible[$property] :
+ $value = $this->_accessible[$field] ??
null;
return ($value === null && !empty($this->_accessible['*'])) || $value;
@@ -1440,7 +1188,7 @@ public function isAccessible($property)
*
* @return string
*/
- public function getSource()
+ public function getSource(): string
{
return $this->_registryAlias;
}
@@ -1451,46 +1199,21 @@ public function getSource()
* @param string $alias the alias of the repository
* @return $this
*/
- public function setSource($alias)
+ public function setSource(string $alias)
{
$this->_registryAlias = $alias;
return $this;
}
- /**
- * Returns the alias of the repository from which this entity came from.
- *
- * If called with no arguments, it returns the alias of the repository
- * this entity came from if it is known.
- *
- * @deprecated 3.4.0 Use EntityTrait::getSource() and EntityTrait::setSource()
- * @param string|null $alias the alias of the repository
- * @return string|$this
- */
- public function source($alias = null)
- {
- deprecationWarning(
- get_called_class() . '::source() is deprecated. ' .
- 'Use setSource()/getSource() instead.'
- );
- if ($alias === null) {
- return $this->getSource();
- }
-
- $this->setSource($alias);
-
- return $this;
- }
-
/**
* Returns a string representation of this object in a human readable format.
*
* @return string
*/
- public function __toString()
+ public function __toString(): string
{
- return json_encode($this, JSON_PRETTY_PRINT);
+ return (string)json_encode($this, JSON_PRETTY_PRINT);
}
/**
@@ -1499,14 +1222,14 @@ public function __toString()
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
- $properties = $this->_properties;
+ $fields = $this->_fields;
foreach ($this->_virtual as $field) {
- $properties[$field] = $this->$field;
+ $fields[$field] = $this->$field;
}
- return $properties + [
+ return $fields + [
'[new]' => $this->isNew(),
'[accessible]' => $this->_accessible,
'[dirty]' => $this->_dirty,
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/Exception/InvalidPrimaryKeyException.php b/app/vendor/cakephp/cakephp/src/Datasource/Exception/InvalidPrimaryKeyException.php
index db51daa76..5263361f2 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/Exception/InvalidPrimaryKeyException.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/Exception/InvalidPrimaryKeyException.php
@@ -1,4 +1,6 @@
modelClass === null) {
$this->modelClass = $name;
@@ -81,31 +83,30 @@ protected function _setModelClass($name)
*
* @param string|null $modelClass Name of model class to load. Defaults to $this->modelClass.
* The name can be an alias like `'Post'` or FQCN like `App\Model\Table\PostsTable::class`.
- * @param string|null $modelType The type of repository to load. Defaults to the modelType() value.
+ * @param string|null $modelType The type of repository to load. Defaults to the getModelType() value.
* @return \Cake\Datasource\RepositoryInterface The model instance created.
* @throws \Cake\Datasource\Exception\MissingModelException If the model class cannot be found.
- * @throws \InvalidArgumentException When using a type that has not been registered.
- * @throws \UnexpectedValueException If no model type has been defined
+ * @throws \UnexpectedValueException If $modelClass argument is not provided
+ * and ModelAwareTrait::$modelClass property value is empty.
*/
- public function loadModel($modelClass = null, $modelType = null)
+ public function loadModel(?string $modelClass = null, ?string $modelType = null): RepositoryInterface
{
if ($modelClass === null) {
$modelClass = $this->modelClass;
}
+ if (empty($modelClass)) {
+ throw new UnexpectedValueException('Default modelClass is empty');
+ }
if ($modelType === null) {
$modelType = $this->getModelType();
-
- if ($modelType === null) {
- throw new UnexpectedValueException('No model type has been defined');
- }
}
- $alias = null;
$options = [];
if (strpos($modelClass, '\\') === false) {
- list(, $alias) = pluginSplit($modelClass, true);
+ [, $alias] = pluginSplit($modelClass, true);
} else {
$options['className'] = $modelClass;
+ /** @psalm-suppress PossiblyFalseOperand */
$alias = substr(
$modelClass,
strrpos($modelClass, '\\') + 1,
@@ -139,7 +140,7 @@ public function loadModel($modelClass = null, $modelType = null)
* @param callable $factory The factory function used to create instances.
* @return void
*/
- public function modelFactory($type, callable $factory)
+ public function modelFactory(string $type, callable $factory): void
{
$this->_modelFactories[$type] = $factory;
}
@@ -149,7 +150,7 @@ public function modelFactory($type, callable $factory)
*
* @return string
*/
- public function getModelType()
+ public function getModelType(): string
{
return $this->_modelType;
}
@@ -160,32 +161,10 @@ public function getModelType()
* @param string $modelType The model type
* @return $this
*/
- public function setModelType($modelType)
+ public function setModelType(string $modelType)
{
$this->_modelType = $modelType;
return $this;
}
-
- /**
- * Set or get the model type to be used by this class
- *
- * @deprecated 3.5.0 Use getModelType()/setModelType() instead.
- * @param string|null $modelType The model type or null to retrieve the current
- * @return string|$this
- */
- public function modelType($modelType = null)
- {
- deprecationWarning(
- get_called_class() . '::modelType() is deprecated. ' .
- 'Use setModelType()/getModelType() instead.'
- );
- if ($modelType === null) {
- return $this->_modelType;
- }
-
- $this->_modelType = $modelType;
-
- return $this;
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/Paginator.php b/app/vendor/cakephp/cakephp/src/Datasource/Paginator.php
index 29e926f77..118a7ad28 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/Paginator.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/Paginator.php
@@ -1,4 +1,6 @@
getRepository();
+ if ($object === null) {
+ throw new Exception('No repository set for query.');
+ }
}
$data = $this->extractData($object, $params, $settings);
@@ -195,7 +202,7 @@ public function paginate($object, array $params = [], array $settings = [])
* @param array $data Pagination data.
* @return \Cake\Datasource\QueryInterface
*/
- protected function getQuery(RepositoryInterface $object, QueryInterface $query = null, array $data)
+ protected function getQuery(RepositoryInterface $object, ?QueryInterface $query = null, array $data): QueryInterface
{
if ($query === null) {
$query = $object->find($data['finder'], $data['options']);
@@ -213,7 +220,7 @@ protected function getQuery(RepositoryInterface $object, QueryInterface $query =
* @param array $data Pagination data.
* @return int|null
*/
- protected function getCount(QueryInterface $query, array $data)
+ protected function getCount(QueryInterface $query, array $data): ?int
{
return $query->count();
}
@@ -226,7 +233,7 @@ protected function getCount(QueryInterface $query, array $data)
* @param array $settings The settings/configuration used for pagination.
* @return array Array with keys 'defaults', 'options' and 'finder'
*/
- protected function extractData(RepositoryInterface $object, array $params, array $settings)
+ protected function extractData(RepositoryInterface $object, array $params, array $settings): array
{
$alias = $object->getAlias();
$defaults = $this->getDefaults($alias, $settings);
@@ -236,7 +243,7 @@ protected function extractData(RepositoryInterface $object, array $params, array
$options += ['page' => 1, 'scope' => null];
$options['page'] = (int)$options['page'] < 1 ? 1 : (int)$options['page'];
- list($finder, $options) = $this->_extractFinder($options);
+ [$finder, $options] = $this->_extractFinder($options);
return compact('defaults', 'options', 'finder');
}
@@ -248,7 +255,7 @@ protected function extractData(RepositoryInterface $object, array $params, array
* 'count', 'defaults', 'finder', 'numResults'.
* @return array Paging params.
*/
- protected function buildParams(array $data)
+ protected function buildParams(array $data): array
{
$limit = $data['options']['limit'];
@@ -281,7 +288,7 @@ protected function buildParams(array $data)
* @param array $data Paginator data.
* @return array Updated params.
*/
- protected function addPageCountParams(array $params, array $data)
+ protected function addPageCountParams(array $params, array $data): array
{
$page = $params['page'];
$pageCount = 0;
@@ -306,7 +313,7 @@ protected function addPageCountParams(array $params, array $data)
* @param array $data Paginator data.
* @return array Updated params.
*/
- protected function addStartEndParams(array $params, array $data)
+ protected function addStartEndParams(array $params, array $data): array
{
$start = $end = 0;
@@ -328,13 +335,13 @@ protected function addStartEndParams(array $params, array $data)
* @param array $data Paging data.
* @return array Updated params.
*/
- protected function addPrevNextParams(array $params, array $data)
+ protected function addPrevNextParams(array $params, array $data): array
{
$params['prevPage'] = $params['page'] > 1;
if ($params['count'] === null) {
$params['nextPage'] = true;
} else {
- $params['nextPage'] = $params['count'] > ($params['page'] * $params['perPage']);
+ $params['nextPage'] = $params['count'] > $params['page'] * $params['perPage'];
}
return $params;
@@ -347,7 +354,7 @@ protected function addPrevNextParams(array $params, array $data)
* @param array $data Paging data.
* @return array Updated params.
*/
- protected function addSortingParams(array $params, array $data)
+ protected function addSortingParams(array $params, array $data): array
{
$defaults = $data['defaults'];
$order = (array)$data['options']['order'];
@@ -376,7 +383,7 @@ protected function addSortingParams(array $params, array $data)
* @return array An array containing in the first position the finder name
* and in the second the options to be passed to it.
*/
- protected function _extractFinder($options)
+ protected function _extractFinder(array $options): array
{
$type = !empty($options['finder']) ? $options['finder'] : 'all';
unset($options['finder'], $options['maxLimit']);
@@ -394,7 +401,7 @@ protected function _extractFinder($options)
*
* @return array
*/
- public function getPagingParams()
+ public function getPagingParams(): array
{
return $this->_pagingParams;
}
@@ -415,7 +422,7 @@ public function getPagingParams()
* @param array $settings The settings to merge with the request data.
* @return array Array of merged options.
*/
- public function mergeOptions($params, $settings)
+ public function mergeOptions(array $params, array $settings): array
{
if (!empty($settings['scope'])) {
$scope = $settings['scope'];
@@ -435,15 +442,15 @@ public function mergeOptions($params, $settings)
* @return array An array of pagination settings for a model,
* or the general settings.
*/
- public function getDefaults($alias, $settings)
+ public function getDefaults(string $alias, array $settings): array
{
if (isset($settings[$alias])) {
$settings = $settings[$alias];
}
$defaults = $this->getConfig();
- $maxLimit = isset($settings['maxLimit']) ? $settings['maxLimit'] : $defaults['maxLimit'];
- $limit = isset($settings['limit']) ? $settings['limit'] : $defaults['limit'];
+ $maxLimit = $settings['maxLimit'] ?? $defaults['maxLimit'];
+ $limit = $settings['limit'] ?? $defaults['limit'];
if ($limit > $maxLimit) {
$limit = $maxLimit;
@@ -481,18 +488,18 @@ public function getDefaults($alias, $settings)
* @return array An array of options with sort + direction removed and
* replaced with order if possible.
*/
- public function validateSort(RepositoryInterface $object, array $options)
+ public function validateSort(RepositoryInterface $object, array $options): array
{
if (isset($options['sort'])) {
$direction = null;
if (isset($options['direction'])) {
$direction = strtolower($options['direction']);
}
- if (!in_array($direction, ['asc', 'desc'])) {
+ if (!in_array($direction, ['asc', 'desc'], true)) {
$direction = 'asc';
}
- $order = (isset($options['order']) && is_array($options['order'])) ? $options['order'] : [];
+ $order = isset($options['order']) && is_array($options['order']) ? $options['order'] : [];
if ($order && $options['sort'] && strpos($options['sort'], '.') === false) {
$order = $this->_removeAliases($order, $object->getAlias());
}
@@ -542,7 +549,7 @@ public function validateSort(RepositoryInterface $object, array $options)
* @param string $model Current model alias
* @return array $fields Unaliased fields where applicable
*/
- protected function _removeAliases($fields, $model)
+ protected function _removeAliases(array $fields, string $model): array
{
$result = [];
foreach ($fields as $field => $sort) {
@@ -551,7 +558,7 @@ protected function _removeAliases($fields, $model)
continue;
}
- list ($alias, $currentField) = explode('.', $field);
+ [$alias, $currentField] = explode('.', $field);
if ($alias === $model) {
$result[$currentField] = $sort;
@@ -572,7 +579,7 @@ protected function _removeAliases($fields, $model)
* @param bool $whitelisted Whether or not the field was whitelisted.
* @return array Final order array.
*/
- protected function _prefix(RepositoryInterface $object, $order, $whitelisted = false)
+ protected function _prefix(RepositoryInterface $object, array $order, bool $whitelisted = false): array
{
$tableAlias = $object->getAlias();
$tableOrder = [];
@@ -585,7 +592,7 @@ protected function _prefix(RepositoryInterface $object, $order, $whitelisted = f
$alias = $tableAlias;
if (strpos($key, '.') !== false) {
- list($alias, $field) = explode('.', $key);
+ [$alias, $field] = explode('.', $key);
}
$correctAlias = ($tableAlias === $alias);
@@ -611,7 +618,7 @@ protected function _prefix(RepositoryInterface $object, $order, $whitelisted = f
* @param array $options An array of options with a limit key to be checked.
* @return array An array of options for pagination.
*/
- public function checkLimit(array $options)
+ public function checkLimit(array $options): array
{
$options['limit'] = (int)$options['limit'];
if (empty($options['limit']) || $options['limit'] < 1) {
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/PaginatorInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/PaginatorInterface.php
index 54ccf31fc..c2bff1a17 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/PaginatorInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/PaginatorInterface.php
@@ -1,4 +1,6 @@
_key = $key;
- if (!is_string($config) && !($config instanceof CacheEngine)) {
- throw new RuntimeException('Cache configs must be strings or CacheEngine instances.');
+ if (!is_string($config) && !($config instanceof CacheInterface)) {
+ throw new RuntimeException('Cache configs must be strings or \Psr\SimpleCache\CacheInterface instances.');
}
$this->_config = $config;
}
@@ -66,13 +70,13 @@ public function __construct($key, $config)
* Load the cached results from the cache or run the query.
*
* @param object $query The query the cache read is for.
- * @return \Cake\Datasource\ResultSetInterface|null Either the cached results or null.
+ * @return mixed|null Either the cached results or null.
*/
- public function fetch($query)
+ public function fetch(object $query)
{
$key = $this->_resolveKey($query);
$storage = $this->_resolveCacher();
- $result = $storage->read($key);
+ $result = $storage->get($key);
if (empty($result)) {
return null;
}
@@ -87,12 +91,12 @@ public function fetch($query)
* @param \Traversable $results The result set to store.
* @return bool True if the data was successfully cached, false on failure
*/
- public function store($query, Traversable $results)
+ public function store(object $query, Traversable $results): bool
{
$key = $this->_resolveKey($query);
$storage = $this->_resolveCacher();
- return $storage->write($key, $results);
+ return (bool)$storage->set($key, $results);
}
/**
@@ -102,7 +106,7 @@ public function store($query, Traversable $results)
* @return string
* @throws \RuntimeException
*/
- protected function _resolveKey($query)
+ protected function _resolveKey(object $query): string
{
if (is_string($this->_key)) {
return $this->_key;
@@ -120,12 +124,12 @@ protected function _resolveKey($query)
/**
* Get the cache engine.
*
- * @return \Cake\Cache\CacheEngine
+ * @return \Psr\SimpleCache\CacheInterface
*/
protected function _resolveCacher()
{
if (is_string($this->_config)) {
- return Cache::engine($this->_config);
+ return Cache::pool($this->_config);
}
return $this->_config;
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/QueryInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/QueryInterface.php
index 71d083911..55dba5a97 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/QueryInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/QueryInterface.php
@@ -1,4 +1,6 @@
value array representing a single aliased field
@@ -49,9 +52,9 @@ interface QueryInterface
*
* @param string $field The field to alias
* @param string|null $alias the alias used to prefix the field
- * @return string
+ * @return array
*/
- public function aliasField($field, $alias = null);
+ public function aliasField(string $field, ?string $alias = null): array;
/**
* Runs `aliasField()` for each field in the provided list and returns
@@ -61,7 +64,7 @@ public function aliasField($field, $alias = null);
* @param string|null $defaultAlias The default alias
* @return string[]
*/
- public function aliasFields($fields, $defaultAlias = null);
+ public function aliasFields(array $fields, ?string $defaultAlias = null): array;
/**
* Fetch the results for this query.
@@ -74,7 +77,7 @@ public function aliasFields($fields, $defaultAlias = null);
*
* @return \Cake\Datasource\ResultSetInterface
*/
- public function all();
+ public function all(): ResultSetInterface;
/**
* Populates or adds parts to current query clauses using an array.
@@ -131,9 +134,9 @@ public function applyOptions(array $options);
*
* @param string $finder The finder method to use.
* @param array $options The options for the finder.
- * @return $this Returns a modified query.
+ * @return static Returns a modified query.
*/
- public function find($finder, array $options = []);
+ public function find(string $finder, array $options = []);
/**
* Returns the first result out of executing this query, if the query has not been
@@ -145,7 +148,7 @@ public function find($finder, array $options = []);
* $singleUser = $query->select(['id', 'username'])->first();
* ```
*
- * @return mixed the first result from the ResultSet
+ * @return \Cake\Datasource\EntityInterface|array|null the first result from the ResultSet
*/
public function first();
@@ -154,7 +157,7 @@ public function first();
*
* @return int
*/
- public function count();
+ public function count(): int;
/**
* Sets the number of records that should be retrieved from database,
@@ -169,7 +172,7 @@ public function count();
* $query->limit($query->newExpr()->add(['1 + 1'])); // LIMIT (1 + 1)
* ```
*
- * @param int $num number of records to be returned
+ * @param int|\Cake\Database\ExpressionInterface|null $num number of records to be returned
* @return $this
*/
public function limit($num);
@@ -189,7 +192,7 @@ public function limit($num);
* $query->offset($query->newExpr()->add(['1 + 1'])); // OFFSET (1 + 1)
* ```
*
- * @param int $num number of records to be skipped
+ * @param int|\Cake\Database\ExpressionInterface|null $num number of records to be skipped
* @return $this
*/
public function offset($num);
@@ -218,9 +221,7 @@ public function offset($num);
* `ORDER BY title DESC, author_id ASC`
*
* ```
- * $query
- * ->order(['title' => $query->newExpr('DESC NULLS FIRST')])
- * ->order('author_id');
+ * $query->order(['title' => 'DESC NULLS FIRST'])->order('author_id');
* ```
*
* Will generate:
@@ -239,7 +240,7 @@ public function offset($num);
* If you need to set complex expressions as order conditions, you
* should use `orderAsc()` or `orderDesc()`.
*
- * @param array|string $fields fields to be added to the list
+ * @param array|\Cake\Database\ExpressionInterface|\Closure|string $fields fields to be added to the list
* @param bool $overwrite whether to reset order with field list or not
* @return $this
*/
@@ -260,23 +261,31 @@ public function order($fields, $overwrite = false);
* @return $this
* @throws \InvalidArgumentException If page number < 1.
*/
- public function page($num, $limit = null);
+ public function page(int $num, ?int $limit = null);
/**
* Returns an array representation of the results after executing the query.
*
* @return array
*/
- public function toArray();
+ public function toArray(): array;
+
+ /**
+ * Set the default Table object that will be used by this query
+ * and form the `FROM` clause.
+ *
+ * @param \Cake\Datasource\RepositoryInterface $repository The default repository object to use
+ * @return $this
+ */
+ public function repository(RepositoryInterface $repository);
/**
* Returns the default repository object that will be used by this query,
* that is, the repository that will appear in the from clause.
*
- * @param \Cake\Datasource\RepositoryInterface|null $repository The default repository object to use
- * @return \Cake\Datasource\RepositoryInterface|$this
+ * @return \Cake\Datasource\RepositoryInterface|null $repository The default repository object to use
*/
- public function repository(RepositoryInterface $repository = null);
+ public function getRepository(): ?RepositoryInterface;
/**
* Adds a condition or set of conditions to be used in the WHERE clause for this
@@ -385,10 +394,10 @@ public function repository(RepositoryInterface $repository = null);
* If you use string conditions make sure that your values are correctly quoted.
* The safest thing you can do is to never use string conditions.
*
- * @param string|array|callable|null $conditions The conditions to filter on.
+ * @param string|array|\Closure|null $conditions The conditions to filter on.
* @param array $types associative array of type names used to bind values to query
* @param bool $overwrite whether to reset conditions with passed list or not
* @return $this
*/
- public function where($conditions = null, $types = [], $overwrite = false);
+ public function where($conditions = null, array $types = [], bool $overwrite = false);
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php b/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php
index fd180d1b2..a9d1d4b98 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php
@@ -1,4 +1,6 @@
getRepository();
- }
-
$this->_repository = $table;
return $this;
@@ -113,7 +103,7 @@ public function repository(RepositoryInterface $table = null)
*
* @return \Cake\Datasource\RepositoryInterface
*/
- public function getRepository()
+ public function getRepository(): RepositoryInterface
{
return $this->_repository;
}
@@ -127,10 +117,10 @@ public function getRepository()
*
* This method is most useful when combined with results stored in a persistent cache.
*
- * @param \Cake\Datasource\ResultSetInterface $results The results this query should return.
+ * @param iterable $results The results this query should return.
* @return $this
*/
- public function setResult($results)
+ public function setResult(iterable $results)
{
$this->_results = $results;
@@ -143,7 +133,8 @@ public function setResult($results)
* iterated without having to call execute() manually, thus making it look like
* a result set instead of the query itself.
*
- * @return \Iterator
+ * @return \Cake\Datasource\ResultSetInterface
+ * @psalm-suppress ImplementedReturnTypeMismatch
*/
public function getIterator()
{
@@ -182,8 +173,8 @@ public function getIterator()
*
* @param \Closure|string|false $key Either the cache key or a function to generate the cache key.
* When using a function, this query instance will be supplied as an argument.
- * @param string|\Cake\Cache\CacheEngine $config Either the name of the cache config to use, or
- * a cache config instance.
+ * @param string|\Psr\SimpleCache\CacheInterface $config Either the name of the cache config to use, or
+ * a cache engine instance.
* @return $this
*/
public function cache($key, $config = 'default')
@@ -203,7 +194,7 @@ public function cache($key, $config = 'default')
*
* @return bool
*/
- public function isEagerLoaded()
+ public function isEagerLoaded(): bool
{
return $this->_eagerLoaded;
}
@@ -212,20 +203,11 @@ public function isEagerLoaded()
* Sets the query instance to be an eager loaded query. If no argument is
* passed, the current configured query `_eagerLoaded` value is returned.
*
- * @deprecated 3.5.0 Use isEagerLoaded() for the getter part instead.
- * @param bool|null $value Whether or not to eager load.
- * @return $this|bool
+ * @param bool $value Whether or not to eager load.
+ * @return $this
*/
- public function eagerLoaded($value = null)
+ public function eagerLoaded(bool $value)
{
- if ($value === null) {
- deprecationWarning(
- 'Using ' . get_called_class() . '::eagerLoaded() as a getter is deprecated. ' .
- 'Use isEagerLoaded() instead.'
- );
-
- return $this->_eagerLoaded;
- }
$this->_eagerLoaded = $value;
return $this;
@@ -243,13 +225,13 @@ public function eagerLoaded($value = null)
* @param string|null $alias the alias used to prefix the field
* @return array
*/
- public function aliasField($field, $alias = null)
+ public function aliasField(string $field, ?string $alias = null): array
{
$namespaced = strpos($field, '.') !== false;
$aliasedField = $field;
if ($namespaced) {
- list($alias, $field) = explode('.', $field);
+ [$alias, $field] = explode('.', $field);
}
if (!$alias) {
@@ -270,9 +252,9 @@ public function aliasField($field, $alias = null)
*
* @param array $fields The fields to alias
* @param string|null $defaultAlias The default alias
- * @return array
+ * @return string[]
*/
- public function aliasFields($fields, $defaultAlias = null)
+ public function aliasFields(array $fields, ?string $defaultAlias = null): array
{
$aliased = [];
foreach ($fields as $alias => $field) {
@@ -297,7 +279,7 @@ public function aliasFields($fields, $defaultAlias = null)
*
* @return \Cake\Datasource\ResultSetInterface
*/
- public function all()
+ public function all(): ResultSetInterface
{
if ($this->_results !== null) {
return $this->_results;
@@ -322,7 +304,7 @@ public function all()
*
* @return array
*/
- public function toArray()
+ public function toArray(): array
{
return $this->all()->toArray();
}
@@ -334,32 +316,26 @@ public function toArray()
* The MapReduce routing will only be run when the query is executed and the first
* result is attempted to be fetched.
*
- * If the first argument is set to null, it will return the list of previously
- * registered map reduce routines. This is deprecated as of 3.6.0 - use getMapReducers() instead.
- *
* If the third argument is set to true, it will erase previous map reducers
* and replace it with the arguments passed.
*
* @param callable|null $mapper The mapper callable.
* @param callable|null $reducer The reducing function.
* @param bool $overwrite Set to true to overwrite existing map + reduce functions.
- * @return $this|array
+ * @return $this
* @see \Cake\Collection\Iterator\MapReduce for details on how to use emit data to the map reducer.
*/
- public function mapReduce(callable $mapper = null, callable $reducer = null, $overwrite = false)
+ public function mapReduce(?callable $mapper = null, ?callable $reducer = null, bool $overwrite = false)
{
if ($overwrite) {
$this->_mapReduce = [];
}
if ($mapper === null) {
if (!$overwrite) {
- deprecationWarning(
- 'Using QueryTrait::mapReduce() as a getter is deprecated. ' .
- 'Use getMapReducers() instead.'
- );
+ throw new InvalidArgumentException('$mapper can be null only when $overwrite is true.');
}
- return $this->_mapReduce;
+ return $this;
}
$this->_mapReduce[] = compact('mapper', 'reducer');
@@ -371,7 +347,7 @@ public function mapReduce(callable $mapper = null, callable $reducer = null, $ov
*
* @return array
*/
- public function getMapReducers()
+ public function getMapReducers(): array
{
return $this->_mapReduce;
}
@@ -387,9 +363,6 @@ public function getMapReducers()
* the return value for this query's result. Formatter functions are applied
* after all the `MapReduce` routines for this query have been executed.
*
- * If the first argument is set to null, it will return the list of previously
- * registered format routines. This is deprecated as of 3.6.0 - use getResultFormatters() instead.
- *
* If the second argument is set to true, it will erase previous formatters
* and replace them with the passed first argument.
*
@@ -411,23 +384,21 @@ public function getMapReducers()
* ```
*
* @param callable|null $formatter The formatting callable.
- * @param bool|int $mode Whether or not to overwrite, append or prepend the formatter.
- * @return $this|array
+ * @param int|true $mode Whether or not to overwrite, append or prepend the formatter.
+ * @return $this
+ * @throws \InvalidArgumentException
*/
- public function formatResults(callable $formatter = null, $mode = 0)
+ public function formatResults(?callable $formatter = null, $mode = self::APPEND)
{
if ($mode === self::OVERWRITE) {
$this->_formatters = [];
}
if ($formatter === null) {
if ($mode !== self::OVERWRITE) {
- deprecationWarning(
- 'Using QueryTrait::formatResults() as a getter is deprecated. ' .
- 'Use getResultFormatters() instead.'
- );
+ throw new InvalidArgumentException('$formatter can be null only when $mode is overwrite.');
}
- return $this->_formatters;
+ return $this;
}
if ($mode === self::PREPEND) {
@@ -444,9 +415,9 @@ public function formatResults(callable $formatter = null, $mode = 0)
/**
* Returns the list of previously registered format routines.
*
- * @return array
+ * @return callable[]
*/
- public function getResultFormatters()
+ public function getResultFormatters(): array
{
return $this->_formatters;
}
@@ -508,7 +479,7 @@ public function firstOrFail()
* be processed by this class and not returned by this function
* @return array
*/
- public function getOptions()
+ public function getOptions(): array
{
return $this->_options;
}
@@ -521,10 +492,10 @@ public function getOptions()
* @return mixed
* @throws \BadMethodCallException if no such method exists in result set
*/
- public function __call($method, $arguments)
+ public function __call(string $method, array $arguments)
{
$resultSetClass = $this->_decoratorClass();
- if (in_array($method, get_class_methods($resultSetClass))) {
+ if (in_array($method, get_class_methods($resultSetClass), true)) {
$results = $this->all();
return $results->$method(...$arguments);
@@ -546,9 +517,9 @@ abstract public function applyOptions(array $options);
/**
* Executes this query and returns a traversable object containing the results
*
- * @return \Traversable
+ * @return \Cake\Datasource\ResultSetInterface
*/
- abstract protected function _execute();
+ abstract protected function _execute(): ResultSetInterface;
/**
* Decorates the results iterator with MapReduce routines and formatters
@@ -556,7 +527,7 @@ abstract protected function _execute();
* @param \Traversable $result Original results
* @return \Cake\Datasource\ResultSetInterface
*/
- protected function _decorateResults($result)
+ protected function _decorateResults(Traversable $result): ResultSetInterface
{
$decorator = $this->_decoratorClass();
foreach ($this->_mapReduce as $functions) {
@@ -582,8 +553,9 @@ protected function _decorateResults($result)
* Returns the name of the class to be used for decorating results
*
* @return string
+ * @psalm-return class-string<\Cake\Datasource\ResultSetInterface>
*/
- protected function _decoratorClass()
+ protected function _decoratorClass(): string
{
return ResultSetDecorator::class;
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/README.md b/app/vendor/cakephp/cakephp/src/Datasource/README.md
index 9f756bca9..093a6c26f 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/README.md
+++ b/app/vendor/cakephp/cakephp/src/Datasource/README.md
@@ -27,7 +27,7 @@ Additionally, this package provides a few traits and classes you can use in your
* `EntityTrait` - Contains the default implementation for the `EntityInterface`.
* `QueryTrait` - Exposes the methods for creating a query object capable of returning decoratable collections.
-* `ResultSetDecorator` - Decorates any traversable object, so it complies with `ResultSetInterface`.
+* `ResultSetDecorator` - Decorates any traversable object so it complies with `ResultSetInterface`.
## Connections
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/RepositoryInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/RepositoryInterface.php
index 3405acbd8..b8ffbeb2c 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/RepositoryInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/RepositoryInterface.php
@@ -1,4 +1,6 @@
new value.
+ * @param string|array|\Closure|\Cake\Database\Expression\QueryExpression $fields A hash of field => new value.
* @param mixed $conditions Conditions to be used, accepts anything Query::where()
* can take.
* @return int Count Returns the affected rows.
*/
- public function updateAll($fields, $conditions);
+ public function updateAll($fields, $conditions): int;
/**
* Deletes all records matching the provided conditions.
@@ -110,16 +128,16 @@ public function updateAll($fields, $conditions);
* @return int Returns the number of affected rows.
* @see \Cake\Datasource\RepositoryInterface::delete()
*/
- public function deleteAll($conditions);
+ public function deleteAll($conditions): int;
/**
* Returns true if there is any record in this repository matching the specified
* conditions.
*
- * @param array|\ArrayAccess $conditions list of conditions to pass to the query
+ * @param array $conditions list of conditions to pass to the query
* @return bool
*/
- public function exists($conditions);
+ public function exists($conditions): bool;
/**
* Persists an entity based on the fields that are marked as dirty and
@@ -142,7 +160,18 @@ public function save(EntityInterface $entity, $options = []);
* @param array|\ArrayAccess $options The options for the delete.
* @return bool success
*/
- public function delete(EntityInterface $entity, $options = []);
+ public function delete(EntityInterface $entity, $options = []): bool;
+
+ /**
+ * This creates a new entity object.
+ *
+ * Careful: This does not trigger any field validation.
+ * This entity can be persisted without validation error as empty record.
+ * Always patch in required fields before saving.
+ *
+ * @return \Cake\Datasource\EntityInterface
+ */
+ public function newEmptyEntity(): EntityInterface;
/**
* Create a new entity + associated entities from an array.
@@ -158,11 +187,11 @@ public function delete(EntityInterface $entity, $options = []);
* on the primary key data existing in the database when the entity
* is saved. Until the entity is saved, it will be a detached record.
*
- * @param array|null $data The data to build an entity with.
+ * @param array $data The data to build an entity with.
* @param array $options A list of options for the object hydration.
* @return \Cake\Datasource\EntityInterface
*/
- public function newEntity($data = null, array $options = []);
+ public function newEntity(array $data, array $options = []): EntityInterface;
/**
* Create a list of entities + associated entities from an array.
@@ -180,7 +209,7 @@ public function newEntity($data = null, array $options = []);
* @param array $options A list of options for the objects hydration.
* @return \Cake\Datasource\EntityInterface[] An array of hydrated records.
*/
- public function newEntities(array $data, array $options = []);
+ public function newEntities(array $data, array $options = []): array;
/**
* Merges the passed `$data` into `$entity` respecting the accessible
@@ -199,7 +228,7 @@ public function newEntities(array $data, array $options = []);
* @param array $options A list of options for the object hydration.
* @return \Cake\Datasource\EntityInterface
*/
- public function patchEntity(EntityInterface $entity, array $data, array $options = []);
+ public function patchEntity(EntityInterface $entity, array $data, array $options = []): EntityInterface;
/**
* Merges each of the elements passed in `$data` into the entities
@@ -219,5 +248,5 @@ public function patchEntity(EntityInterface $entity, array $data, array $options
* @param array $options A list of options for the objects hydration.
* @return \Cake\Datasource\EntityInterface[]
*/
- public function patchEntities($entities, array $data, array $options = []);
+ public function patchEntities(iterable $entities, array $data, array $options = []): array;
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ResultSetDecorator.php b/app/vendor/cakephp/cakephp/src/Datasource/ResultSetDecorator.php
index cf4da00d9..e59e63e54 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ResultSetDecorator.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ResultSetDecorator.php
@@ -1,4 +1,6 @@
getInnerIterator() instanceof Countable) {
- return $this->getInnerIterator()->count();
+ $iterator = $this->getInnerIterator();
+ if ($iterator instanceof Countable) {
+ return $iterator->count();
}
return count($this->toArray());
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ResultSetInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/ResultSetInterface.php
index f6166e08b..a62ee77f3 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ResultSetInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ResultSetInterface.php
@@ -1,4 +1,6 @@
rule = $rule;
$this->name = $name;
@@ -89,10 +91,10 @@ public function setOptions(array $options)
*
* Only truthy names will be set.
*
- * @param string $name The name to set.
+ * @param string|null $name The name to set.
* @return $this
*/
- public function setName($name)
+ public function setName(?string $name)
{
if ($name) {
$this->name = $name;
@@ -109,7 +111,7 @@ public function setName($name)
* @param array $scope The rule's scope/options.
* @return bool Whether or not the rule passed.
*/
- public function __invoke($entity, $scope)
+ public function __invoke(EntityInterface $entity, array $scope): bool
{
$rule = $this->rule;
$pass = $rule($entity, $this->options + $scope);
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/RulesAwareTrait.php b/app/vendor/cakephp/cakephp/src/Datasource/RulesAwareTrait.php
index 5cabda5da..af4287db2 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/RulesAwareTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/RulesAwareTrait.php
@@ -1,4 +1,6 @@
rulesChecker();
$options = $options ?: new ArrayObject();
@@ -88,12 +90,13 @@ public function checkRules(EntityInterface $entity, $operation = RulesChecker::C
* @see \Cake\Datasource\RulesChecker
* @return \Cake\Datasource\RulesChecker
*/
- public function rulesChecker()
+ public function rulesChecker(): RulesChecker
{
if ($this->_rulesChecker !== null) {
return $this->_rulesChecker;
}
- $class = defined('static::RULES_CLASS') ? static::RULES_CLASS : 'Cake\Datasource\RulesChecker';
+ /** @psalm-var class-string<\Cake\Datasource\RulesChecker> $class */
+ $class = defined('static::RULES_CLASS') ? static::RULES_CLASS : RulesChecker::class;
$this->_rulesChecker = $this->buildRules(new $class(['repository' => $this]));
$this->dispatchEvent('Model.buildRules', ['rules' => $this->_rulesChecker]);
@@ -109,7 +112,7 @@ public function rulesChecker()
* @param \Cake\Datasource\RulesChecker $rules The rules object to be modified.
* @return \Cake\Datasource\RulesChecker
*/
- public function buildRules(RulesChecker $rules)
+ public function buildRules(RulesChecker $rules): RulesChecker
{
return $rules;
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/RulesChecker.php b/app/vendor/cakephp/cakephp/src/Datasource/RulesChecker.php
index f0bfedef9..2d7e76225 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/RulesChecker.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/RulesChecker.php
@@ -1,4 +1,6 @@
checkCreate($entity, $options);
@@ -250,7 +252,7 @@ public function check(EntityInterface $entity, $mode, array $options = [])
* @param array $options Extra options to pass to checker functions.
* @return bool
*/
- public function checkCreate(EntityInterface $entity, array $options = [])
+ public function checkCreate(EntityInterface $entity, array $options = []): bool
{
return $this->_checkRules($entity, $options, array_merge($this->_rules, $this->_createRules));
}
@@ -263,7 +265,7 @@ public function checkCreate(EntityInterface $entity, array $options = [])
* @param array $options Extra options to pass to checker functions.
* @return bool
*/
- public function checkUpdate(EntityInterface $entity, array $options = [])
+ public function checkUpdate(EntityInterface $entity, array $options = []): bool
{
return $this->_checkRules($entity, $options, array_merge($this->_rules, $this->_updateRules));
}
@@ -276,7 +278,7 @@ public function checkUpdate(EntityInterface $entity, array $options = [])
* @param array $options Extra options to pass to checker functions.
* @return bool
*/
- public function checkDelete(EntityInterface $entity, array $options = [])
+ public function checkDelete(EntityInterface $entity, array $options = []): bool
{
return $this->_checkRules($entity, $options, $this->_deleteRules);
}
@@ -287,10 +289,10 @@ public function checkDelete(EntityInterface $entity, array $options = [])
*
* @param \Cake\Datasource\EntityInterface $entity The entity to check for validity.
* @param array $options Extra options to pass to checker functions.
- * @param array $rules The list of rules that must be checked.
+ * @param \Cake\Datasource\RuleInvoker[] $rules The list of rules that must be checked.
* @return bool
*/
- protected function _checkRules(EntityInterface $entity, array $options = [], array $rules = [])
+ protected function _checkRules(EntityInterface $entity, array $options = [], array $rules = []): bool
{
$success = true;
$options += $this->_options;
@@ -306,11 +308,11 @@ protected function _checkRules(EntityInterface $entity, array $options = [], arr
* property in the entity is marked as invalid.
*
* @param callable $rule The rule to decorate
- * @param string $name The alias for a rule.
+ * @param string|array|null $name The alias for a rule or an array of options
* @param array $options The options containing the error message and field.
- * @return callable
+ * @return \Cake\Datasource\RuleInvoker
*/
- protected function _addError($rule, $name, $options)
+ protected function _addError(callable $rule, $name = null, array $options = []): RuleInvoker
{
if (is_array($name)) {
$options = $name;
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/SchemaInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/SchemaInterface.php
index 93ecf29b5..fdcb7a8ef 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/SchemaInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/SchemaInterface.php
@@ -1,4 +1,6 @@
=5.6.0,<8.0.0",
- "cakephp/core": "^3.6.0"
+ "php": ">=7.2.0",
+ "cakephp/core": "^4.0",
+ "psr/log": "^1.1",
+ "psr/simple-cache": "^1.0"
},
"suggest": {
"cakephp/utility": "If you decide to use EntityTrait.",
diff --git a/app/vendor/cakephp/cakephp/src/Error/BaseErrorHandler.php b/app/vendor/cakephp/cakephp/src/Error/BaseErrorHandler.php
index 73002551c..b73639325 100644
--- a/app/vendor/cakephp/cakephp/src/Error/BaseErrorHandler.php
+++ b/app/vendor/cakephp/cakephp/src/Error/BaseErrorHandler.php
@@ -1,4 +1,6 @@
true,
+ 'trace' => false,
+ 'skipLog' => [],
+ 'errorLogger' => ErrorLogger::class,
+ ];
/**
* @var bool
*/
protected $_handled = false;
+ /**
+ * Exception logger instance.
+ *
+ * @var \Cake\Error\ErrorLogger|null
+ */
+ protected $logger;
+
/**
* Display an error message in an environment specific way.
*
@@ -51,7 +68,7 @@ abstract class BaseErrorHandler
* @param bool $debug Whether or not the app is in debug mode.
* @return void
*/
- abstract protected function _displayError($error, $debug);
+ abstract protected function _displayError(array $error, bool $debug): void;
/**
* Display an exception in an environment specific way.
@@ -59,33 +76,30 @@ abstract protected function _displayError($error, $debug);
* Subclasses should implement this method to display an uncaught exception as
* desired for the runtime they operate in.
*
- * @param \Exception $exception The uncaught exception.
+ * @param \Throwable $exception The uncaught exception.
* @return void
*/
- abstract protected function _displayException($exception);
+ abstract protected function _displayException(Throwable $exception): void;
/**
* Register the error and exception handlers.
*
* @return void
*/
- public function register()
+ public function register(): void
{
$level = -1;
- if (isset($this->_options['errorLevel'])) {
- $level = $this->_options['errorLevel'];
+ if (isset($this->_config['errorLevel'])) {
+ $level = $this->_config['errorLevel'];
}
error_reporting($level);
set_error_handler([$this, 'handleError'], $level);
- set_exception_handler([$this, 'wrapAndHandleException']);
- register_shutdown_function(function () {
+ set_exception_handler([$this, 'handleException']);
+ register_shutdown_function(function (): void {
if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && $this->_handled) {
return;
}
- $megabytes = Configure::read('Error.extraFatalErrorMemory');
- if ($megabytes === null) {
- $megabytes = 4;
- }
+ $megabytes = $this->_config['extraFatalErrorMemory'] ?? 4;
if ($megabytes > 0) {
$this->increaseMemoryLimit($megabytes * 1024);
}
@@ -127,14 +141,20 @@ public function register()
* @param array|null $context Context
* @return bool True if error was handled
*/
- public function handleError($code, $description, $file = null, $line = null, $context = null)
- {
+ public function handleError(
+ int $code,
+ string $description,
+ ?string $file = null,
+ ?int $line = null,
+ ?array $context = null
+ ): bool {
if (error_reporting() === 0) {
return false;
}
$this->_handled = true;
- list($error, $log) = static::mapErrorCode($code);
+ [$error, $log] = static::mapErrorCode($code);
if ($log === LOG_ERR) {
+ /** @psalm-suppress PossiblyNullArgument */
return $this->handleFatalError($code, $description, $file, $line);
}
$data = [
@@ -161,7 +181,7 @@ public function handleError($code, $description, $file = null, $line = null, $co
$data += [
'context' => $context,
'start' => $start,
- 'path' => Debugger::trimPath($file),
+ 'path' => Debugger::trimPath((string)$file),
];
}
$this->_displayError($data, $debug);
@@ -175,14 +195,13 @@ public function handleError($code, $description, $file = null, $line = null, $co
* then, it wraps the passed object inside another Exception object
* for backwards compatibility purposes.
*
- * @param \Exception|\Error $exception The exception to handle
+ * @param \Throwable $exception The exception to handle
* @return void
+ * @deprecated 4.0.0 Unused method will be removed in 5.0
*/
- public function wrapAndHandleException($exception)
+ public function wrapAndHandleException(Throwable $exception): void
{
- if ($exception instanceof Error) {
- $exception = new PHP7ErrorException($exception);
- }
+ deprecationWarning('This method is no longer in use. Call handleException instead.');
$this->handleException($exception);
}
@@ -192,16 +211,17 @@ public function wrapAndHandleException($exception)
* Uses a template method provided by subclasses to display errors in an
* environment appropriate way.
*
- * @param \Exception $exception Exception instance.
+ * @param \Throwable $exception Exception instance.
* @return void
* @throws \Exception When renderer class not found
* @see https://secure.php.net/manual/en/function.set-exception-handler.php
*/
- public function handleException(Exception $exception)
+ public function handleException(Throwable $exception): void
{
$this->_displayException($exception);
- $this->_logException($exception);
- $this->_stop($exception->getCode() ?: 1);
+ $this->logException($exception);
+ $code = $exception->getCode() ?: 1;
+ $this->_stop((int)$code);
}
/**
@@ -212,7 +232,7 @@ public function handleException(Exception $exception)
* @param int $code Exit code.
* @return void
*/
- protected function _stop($code)
+ protected function _stop(int $code): void
{
// Do nothing.
}
@@ -226,7 +246,7 @@ protected function _stop($code)
* @param int $line Line that triggered the error
* @return bool
*/
- public function handleFatalError($code, $description, $file, $line)
+ public function handleFatalError(int $code, string $description, string $file, int $line): bool
{
$data = [
'code' => $code,
@@ -249,7 +269,7 @@ public function handleFatalError($code, $description, $file, $line)
* @param int $additionalKb Number in kilobytes
* @return void
*/
- public function increaseMemoryLimit($additionalKb)
+ public function increaseMemoryLimit(int $additionalKb): void
{
$limit = ini_get('memory_limit');
if (!strlen($limit) || $limit === '-1') {
@@ -275,11 +295,11 @@ public function increaseMemoryLimit($additionalKb)
/**
* Log an error.
*
- * @param string $level The level name of the log.
+ * @param int|string $level The level name of the log.
* @param array $data Array of error data.
* @return bool
*/
- protected function _logError($level, $data)
+ protected function _logError($level, array $data): bool
{
$message = sprintf(
'%s (%s): %s in [%s, line %s]',
@@ -289,7 +309,8 @@ protected function _logError($level, $data)
$data['file'],
$data['line']
);
- if (!empty($this->_options['trace'])) {
+ if (!empty($this->_config['trace'])) {
+ /** @var string $trace */
$trace = Debugger::trace([
'start' => 1,
'format' => 'log',
@@ -297,7 +318,7 @@ protected function _logError($level, $data)
$request = Router::getRequest();
if ($request) {
- $message .= $this->_requestContext($request);
+ $message .= $this->getLogger()->getRequestContext($request);
}
$message .= "\nTrace:\n" . $trace . "\n";
}
@@ -307,114 +328,35 @@ protected function _logError($level, $data)
}
/**
- * Handles exception logging
+ * Log an error for the exception if applicable.
*
- * @param \Exception $exception Exception instance.
+ * @param \Throwable $exception The exception to log a message for.
+ * @param \Psr\Http\Message\ServerRequestInterface $request The current request.
* @return bool
*/
- protected function _logException(Exception $exception)
+ public function logException(Throwable $exception, ?ServerRequestInterface $request = null): bool
{
- $config = $this->_options;
- $unwrapped = $exception instanceof PHP7ErrorException ?
- $exception->getError() :
- $exception;
-
- if (empty($config['log'])) {
+ if (empty($this->_config['log'])) {
return false;
}
- if (!empty($config['skipLog'])) {
- foreach ((array)$config['skipLog'] as $class) {
- if ($unwrapped instanceof $class) {
- return false;
- }
- }
- }
-
- return Log::error($this->_getMessage($exception));
- }
-
- /**
- * Get the request context for an error/exception trace.
- *
- * @param \Cake\Http\ServerRequest $request The request to read from.
- * @return string
- */
- protected function _requestContext($request)
- {
- $message = "\nRequest URL: " . $request->getRequestTarget();
-
- $referer = $request->getEnv('HTTP_REFERER');
- if ($referer) {
- $message .= "\nReferer URL: " . $referer;
- }
- $clientIp = $request->clientIp();
- if ($clientIp && $clientIp !== '::1') {
- $message .= "\nClient IP: " . $clientIp;
- }
-
- return $message;
- }
-
- /**
- * Generates a formatted error message
- *
- * @param \Exception $exception Exception instance
- * @return string Formatted message
- */
- protected function _getMessage(Exception $exception)
- {
- $message = $this->getMessageForException($exception);
-
- $request = Router::getRequest();
- if ($request) {
- $message .= $this->_requestContext($request);
- }
-
- return $message;
+ return $this->getLogger()->log($exception, $request ?? Router::getRequest());
}
/**
- * Generate the message for the exception
+ * Get exception logger.
*
- * @param \Exception $exception The exception to log a message for.
- * @param bool $isPrevious False for original exception, true for previous
- * @return string Error message
+ * @return \Cake\Error\ErrorLogger
*/
- protected function getMessageForException($exception, $isPrevious = false)
+ public function getLogger()
{
- $exception = $exception instanceof PHP7ErrorException ?
- $exception->getError() :
- $exception;
- $config = $this->_options;
-
- $message = sprintf(
- '%s[%s] %s in %s on line %s',
- $isPrevious ? "\nCaused by: " : '',
- get_class($exception),
- $exception->getMessage(),
- $exception->getFile(),
- $exception->getLine()
- );
- $debug = Configure::read('debug');
-
- if ($debug && method_exists($exception, 'getAttributes')) {
- $attributes = $exception->getAttributes();
- if ($attributes) {
- $message .= "\nException Attributes: " . var_export($exception->getAttributes(), true);
- }
- }
-
- if (!empty($config['trace'])) {
- $message .= "\nStack Trace:\n" . $exception->getTraceAsString() . "\n\n";
- }
-
- $previous = $exception->getPrevious();
- if ($previous) {
- $message .= $this->getMessageForException($previous, true);
+ if ($this->logger === null) {
+ /** @var \Cake\Error\ErrorLogger $logger */
+ $logger = new $this->_config['errorLogger']($this->_config);
+ $this->logger = $logger;
}
- return $message;
+ return $this->logger;
}
/**
@@ -423,7 +365,7 @@ protected function getMessageForException($exception, $isPrevious = false)
* @param int $code Error code to map
* @return array Array of error word, and log location.
*/
- public static function mapErrorCode($code)
+ public static function mapErrorCode(int $code): array
{
$levelMap = [
E_PARSE => 'error',
diff --git a/app/vendor/cakephp/cakephp/src/Error/ConsoleErrorHandler.php b/app/vendor/cakephp/cakephp/src/Error/ConsoleErrorHandler.php
new file mode 100644
index 000000000..1ece35cf1
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Error/ConsoleErrorHandler.php
@@ -0,0 +1,127 @@
+ new ConsoleOutput('php://stderr'),
+ 'log' => false,
+ ];
+
+ $this->setConfig($config);
+ $this->_stderr = $this->_config['stderr'];
+ }
+
+ /**
+ * Handle errors in the console environment. Writes errors to stderr,
+ * and logs messages if Configure::read('debug') is false.
+ *
+ * @param \Throwable $exception Exception instance.
+ * @return void
+ * @throws \Exception When renderer class not found
+ * @see https://secure.php.net/manual/en/function.set-exception-handler.php
+ */
+ public function handleException(Throwable $exception): void
+ {
+ $this->_displayException($exception);
+ $this->logException($exception);
+ $code = $exception->getCode();
+ $code = $code && is_int($code) ? $code : 1;
+ $this->_stop($code);
+ }
+
+ /**
+ * Prints an exception to stderr.
+ *
+ * @param \Throwable $exception The exception to handle
+ * @return void
+ */
+ protected function _displayException(Throwable $exception): void
+ {
+ $errorName = 'Exception:';
+ if ($exception instanceof FatalErrorException) {
+ $errorName = 'Fatal Error:';
+ }
+
+ $message = sprintf(
+ "%s %s\nIn [%s, line %s]\n",
+ $errorName,
+ $exception->getMessage(),
+ $exception->getFile(),
+ $exception->getLine()
+ );
+ $this->_stderr->write($message);
+ }
+
+ /**
+ * Prints an error to stderr.
+ *
+ * Template method of BaseErrorHandler.
+ *
+ * @param array $error An array of error data.
+ * @param bool $debug Whether or not the app is in debug mode.
+ * @return void
+ */
+ protected function _displayError(array $error, bool $debug): void
+ {
+ $message = sprintf(
+ "%s\nIn [%s, line %s]",
+ $error['description'],
+ $error['file'],
+ $error['line']
+ );
+ $message = sprintf(
+ "%s Error: %s\n",
+ $error['error'],
+ $message
+ );
+ $this->_stderr->write($message);
+ }
+
+ /**
+ * Stop the execution and set the exit code for the process.
+ *
+ * @param int $code The exit code.
+ * @return void
+ */
+ protected function _stop(int $code): void
+ {
+ exit($code);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Error/Debugger.php b/app/vendor/cakephp/cakephp/src/Error/Debugger.php
index aaaf28f87..b66e1ffc1 100644
--- a/app/vendor/cakephp/cakephp/src/Error/Debugger.php
+++ b/app/vendor/cakephp/cakephp/src/Error/Debugger.php
@@ -1,4 +1,6 @@
[],
];
- /**
- * A list of errors generated by the application.
- *
- * @var array
- */
- public $errors = [];
-
/**
* The current output format.
*
@@ -162,9 +158,9 @@ public function __construct()
* Returns a reference to the Debugger singleton object instance.
*
* @param string|null $class Class name.
- * @return \Cake\Error\Debugger
+ * @return static
*/
- public static function getInstance($class = null)
+ public static function getInstance(?string $class = null)
{
static $instance = [];
if (!empty($class)) {
@@ -188,8 +184,12 @@ public static function getInstance($class = null)
* @return mixed Config value being read, or the object itself on write operations.
* @throws \Cake\Core\Exception\Exception When trying to set a key that is invalid.
*/
- public static function configInstance($key = null, $value = null, $merge = true)
+ public static function configInstance($key = null, $value = null, bool $merge = true)
{
+ if ($key === null) {
+ return static::getInstance()->getConfig($key);
+ }
+
if (is_array($key) || func_num_args() >= 2) {
return static::getInstance()->setConfig($key, $value, $merge);
}
@@ -202,7 +202,7 @@ public static function configInstance($key = null, $value = null, $merge = true)
*
* @return array
*/
- public static function outputMask()
+ public static function outputMask(): array
{
return static::configInstance('outputMask');
}
@@ -218,7 +218,7 @@ public static function outputMask()
* @param bool $merge Whether to recursively merge or overwrite existing config, defaults to true.
* @return void
*/
- public static function setOutputMask(array $value, $merge = true)
+ public static function setOutputMask(array $value, bool $merge = true): void
{
static::configInstance('outputMask', $value, $merge);
}
@@ -230,9 +230,9 @@ public static function setOutputMask(array $value, $merge = true)
* @param int $depth The depth to output to. Defaults to 3.
* @return void
* @see \Cake\Error\Debugger::exportVar()
- * @link https://book.cakephp.org/3/en/development/debugging.html#outputting-values
+ * @link https://book.cakephp.org/4/en/development/debugging.html#outputting-values
*/
- public static function dump($var, $depth = 3)
+ public static function dump($var, int $depth = 3): void
{
pr(static::exportVar($var, $depth));
}
@@ -246,7 +246,7 @@ public static function dump($var, $depth = 3)
* @param int $depth The depth to output to. Defaults to 3.
* @return void
*/
- public static function log($var, $level = 'debug', $depth = 3)
+ public static function log($var, $level = 'debug', int $depth = 3): void
{
/** @var string $source */
$source = static::trace(['start' => 1]);
@@ -269,7 +269,7 @@ public static function log($var, $level = 'debug', $depth = 3)
*
* @param array $options Format for outputting stack trace.
* @return string|array Formatted stack trace.
- * @link https://book.cakephp.org/3/en/development/debugging.html#generating-stack-traces
+ * @link https://book.cakephp.org/4/en/development/debugging.html#generating-stack-traces
*/
public static function trace(array $options = [])
{
@@ -288,14 +288,14 @@ public static function trace(array $options = [])
* will be displayed.
* - `start` - The stack frame to start generating a trace from. Defaults to 0
*
- * @param array|\Exception $backtrace Trace as array or an exception object.
+ * @param array|\Throwable $backtrace Trace as array or an exception object.
* @param array $options Format for outputting stack trace.
* @return string|array Formatted stack trace.
- * @link https://book.cakephp.org/3/en/development/debugging.html#generating-stack-traces
+ * @link https://book.cakephp.org/4/en/development/debugging.html#generating-stack-traces
*/
- public static function formatTrace($backtrace, $options = [])
+ public static function formatTrace($backtrace, array $options = [])
{
- if ($backtrace instanceof Exception) {
+ if ($backtrace instanceof Throwable) {
$backtrace = $backtrace->getTrace();
}
$self = Debugger::getInstance();
@@ -340,7 +340,7 @@ public static function formatTrace($backtrace, $options = [])
$reference .= ')';
}
}
- if (in_array($signature, $options['exclude'])) {
+ if (in_array($signature, $options['exclude'], true)) {
continue;
}
if ($options['format'] === 'points' && $trace['file'] !== '[internal]') {
@@ -374,7 +374,7 @@ public static function formatTrace($backtrace, $options = [])
* @param string $path Path to shorten.
* @return string Normalized path
*/
- public static function trimPath($path)
+ public static function trimPath(string $path): string
{
if (defined('APP') && strpos($path, APP) === 0) {
return str_replace(APP, 'APP/', $path);
@@ -408,9 +408,9 @@ public static function trimPath($path)
* @param int $context Number of lines of context to extract above and below $line.
* @return array Set of lines highlighted
* @see https://secure.php.net/highlight_string
- * @link https://book.cakephp.org/3/en/development/debugging.html#getting-an-excerpt-from-a-file
+ * @link https://book.cakephp.org/4/en/development/debugging.html#getting-an-excerpt-from-a-file
*/
- public static function excerpt($file, $line, $context = 2)
+ public static function excerpt(string $file, int $line, int $context = 2): array
{
$lines = [];
if (!file_exists($file)) {
@@ -432,7 +432,7 @@ public static function excerpt($file, $line, $context = 2)
continue;
}
$string = str_replace(["\r\n", "\n"], '', static::_highlight($data[$i]));
- if ($i == $line) {
+ if ($i === $line) {
$lines[] = '' . $string . '';
} else {
$lines[] = $string;
@@ -449,7 +449,7 @@ public static function excerpt($file, $line, $context = 2)
* @param string $str The string to convert.
* @return string
*/
- protected static function _highlight($str)
+ protected static function _highlight(string $str): string
{
if (function_exists('hphp_log') || function_exists('hphp_gettid')) {
return htmlentities($str);
@@ -492,7 +492,7 @@ protected static function _highlight($str)
* @param int $depth The depth to output to. Defaults to 3.
* @return string Variable as a formatted string
*/
- public static function exportVar($var, $depth = 3)
+ public static function exportVar($var, int $depth = 3): string
{
return static::_export($var, $depth, 0);
}
@@ -505,7 +505,7 @@ public static function exportVar($var, $depth = 3)
* @param int $indent The current indentation level.
* @return string The dumped variable.
*/
- protected static function _export($var, $depth, $indent)
+ protected static function _export($var, int $depth, int $indent): string
{
switch (static::getType($var)) {
case 'boolean':
@@ -551,10 +551,10 @@ protected static function _export($var, $depth, $indent)
* @param int $indent The current indentation level.
* @return string Exported array.
*/
- protected static function _array(array $var, $depth, $indent)
+ protected static function _array(array $var, int $depth, int $indent): string
{
$out = '[';
- $break = $end = null;
+ $break = $end = '';
if (!empty($var)) {
$break = "\n" . str_repeat("\t", $indent);
$end = "\n" . str_repeat("\t", $indent - 1);
@@ -592,7 +592,7 @@ protected static function _array(array $var, $depth, $indent)
* @return string
* @see \Cake\Error\Debugger::exportVar()
*/
- protected static function _object($var, $depth, $indent)
+ protected static function _object(object $var, int $depth, int $indent): string
{
$out = '';
$props = [];
@@ -618,7 +618,9 @@ protected static function _object($var, $depth, $indent)
$outputMask = (array)static::outputMask();
$objectVars = get_object_vars($var);
foreach ($objectVars as $key => $value) {
- $value = array_key_exists($key, $outputMask) ? $outputMask[$key] : static::_export($value, $depth - 1, $indent);
+ $value = array_key_exists($key, $outputMask)
+ ? $outputMask[$key]
+ : static::_export($value, $depth - 1, $indent);
$props[] = "$key => " . $value;
}
@@ -631,10 +633,21 @@ protected static function _object($var, $depth, $indent)
foreach ($filters as $filter => $visibility) {
$reflectionProperties = $ref->getProperties($filter);
foreach ($reflectionProperties as $reflectionProperty) {
+ $value = null;
$reflectionProperty->setAccessible(true);
- $property = $reflectionProperty->getValue($var);
- $value = static::_export($property, $depth - 1, $indent);
+ if (
+ method_exists($reflectionProperty, 'isInitialized') &&
+ !$reflectionProperty->isInitialized($var)
+ ) {
+ $value = '[uninitialized]';
+ }
+
+ if ($value === null) {
+ $property = $reflectionProperty->getValue($var);
+ $value = static::_export($property, $depth - 1, $indent);
+ }
+
$key = $reflectionProperty->name;
$props[] = sprintf(
'[%s] %s => %s',
@@ -657,7 +670,7 @@ protected static function _object($var, $depth, $indent)
*
* @return string Returns the current format when getting.
*/
- public static function getOutputFormat()
+ public static function getOutputFormat(): string
{
return Debugger::getInstance()->_outputFormat;
}
@@ -669,41 +682,14 @@ public static function getOutputFormat()
* @return void
* @throws \InvalidArgumentException When choosing a format that doesn't exist.
*/
- public static function setOutputFormat($format)
- {
- $self = Debugger::getInstance();
-
- if (!isset($self->_templates[$format])) {
- throw new InvalidArgumentException('Invalid Debugger output format.');
- }
- $self->_outputFormat = $format;
- }
-
- /**
- * Get/Set the output format for Debugger error rendering.
- *
- * @deprecated 3.5.0 Use getOutputFormat()/setOutputFormat() instead.
- * @param string|null $format The format you want errors to be output as.
- * Leave null to get the current format.
- * @return string|null Returns null when setting. Returns the current format when getting.
- * @throws \InvalidArgumentException When choosing a format that doesn't exist.
- */
- public static function outputAs($format = null)
+ public static function setOutputFormat(string $format): void
{
- deprecationWarning(
- 'Debugger::outputAs() is deprecated. Use Debugger::getOutputFormat()/setOutputFormat() instead.'
- );
$self = Debugger::getInstance();
- if ($format === null) {
- return $self->_outputFormat;
- }
if (!isset($self->_templates[$format])) {
throw new InvalidArgumentException('Invalid Debugger output format.');
}
$self->_outputFormat = $format;
-
- return null;
}
/**
@@ -749,7 +735,7 @@ public static function outputAs($format = null)
* @param array $strings Template strings, or a callback to be used for the output format.
* @return array The resulting format string set.
*/
- public static function addFormat($format, array $strings)
+ public static function addFormat(string $format, array $strings): array
{
$self = Debugger::getInstance();
if (isset($self->_templates[$format])) {
@@ -774,7 +760,7 @@ public static function addFormat($format, array $strings)
* @param array $data Data to output.
* @return void
*/
- public function outputError($data)
+ public function outputError(array $data): void
{
$defaults = [
'level' => 0,
@@ -862,7 +848,7 @@ public function outputError($data)
* @param mixed $var The variable to get the type of.
* @return string The type of variable.
*/
- public static function getType($var)
+ public static function getType($var): string
{
if (is_object($var)) {
return get_class($var);
@@ -902,7 +888,7 @@ public static function getType($var)
* data in a browser-friendly way.
* @return void
*/
- public static function printVar($var, $location = [], $showHtml = null)
+ public static function printVar($var, array $location = [], ?bool $showHtml = null): void
{
$location += ['file' => null, 'line' => null];
$file = $location['file'];
@@ -954,15 +940,40 @@ public static function printVar($var, $location = [], $showHtml = null)
printf($template, $lineInfo, $var);
}
+ /**
+ * Format an exception message to be HTML formatted.
+ *
+ * Does the following formatting operations:
+ *
+ * - HTML escape the message.
+ * - Convert `bool` into `bool`
+ * - Convert newlines into `
`
+ *
+ * @param string $message The string message to format.
+ * @return string Formatted message.
+ */
+ public static function formatHtmlMessage(string $message): string
+ {
+ $message = h($message);
+ $message = preg_replace('/`([^`]+)`/', '$1', $message);
+ $message = nl2br($message);
+
+ return $message;
+ }
+
/**
* Verifies that the application's salt and cipher seed value has been changed from the default value.
*
* @return void
*/
- public static function checkSecurityKeys()
+ public static function checkSecurityKeys(): void
{
if (Security::getSalt() === '__SALT__') {
- trigger_error(sprintf('Please change the value of %s in %s to a salt value specific to your application.', '\'Security.salt\'', 'ROOT/config/app.php'), E_USER_NOTICE);
+ trigger_error(sprintf(
+ 'Please change the value of %s in %s to a salt value specific to your application.',
+ '\'Security.salt\'',
+ 'ROOT/config/app.php'
+ ), E_USER_NOTICE);
}
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Error/ErrorHandler.php b/app/vendor/cakephp/cakephp/src/Error/ErrorHandler.php
index 18ef14c70..b78de70b5 100644
--- a/app/vendor/cakephp/cakephp/src/Error/ErrorHandler.php
+++ b/app/vendor/cakephp/cakephp/src/Error/ErrorHandler.php
@@ -1,4 +1,6 @@
true,
- 'trace' => false,
+ $config += [
'exceptionRenderer' => ExceptionRenderer::class,
];
- $this->_options = $options + $defaults;
+
+ $this->setConfig($config);
}
/**
@@ -110,7 +113,7 @@ public function __construct($options = [])
* @param bool $debug Whether or not the app is in debug mode.
* @return void
*/
- protected function _displayError($error, $debug)
+ protected function _displayError(array $error, bool $debug): void
{
if (!$debug) {
return;
@@ -121,55 +124,67 @@ protected function _displayError($error, $debug)
/**
* Displays an exception response body.
*
- * @param \Exception $exception The exception to display.
+ * @param \Throwable $exception The exception to display.
* @return void
* @throws \Exception When the chosen exception renderer is invalid.
*/
- protected function _displayException($exception)
+ protected function _displayException(Throwable $exception): void
{
- $rendererClassName = App::className($this->_options['exceptionRenderer'], 'Error');
try {
- if (!$rendererClassName) {
- throw new Exception("$rendererClassName is an invalid class.");
- }
- /** @var \Cake\Error\ExceptionRendererInterface $renderer */
- $renderer = new $rendererClassName($exception);
+ $renderer = $this->getRenderer(
+ $exception,
+ Router::getRequest()
+ );
$response = $renderer->render();
- $this->_clearOutput();
$this->_sendResponse($response);
} catch (Throwable $exception) {
$this->_logInternalError($exception);
- } catch (Exception $exception) {
- $this->_logInternalError($exception);
}
}
/**
- * Clear output buffers so error pages display properly.
+ * Get a renderer instance.
*
- * Easily stubbed in testing.
- *
- * @return void
+ * @param \Throwable $exception The exception being rendered.
+ * @param \Psr\Http\Message\ServerRequestInterface|null $request The request.
+ * @return \Cake\Error\ExceptionRendererInterface The exception renderer.
+ * @throws \RuntimeException When the renderer class cannot be found.
*/
- protected function _clearOutput()
- {
- while (ob_get_level()) {
- ob_end_clean();
+ public function getRenderer(
+ Throwable $exception,
+ ?ServerRequestInterface $request = null
+ ): ExceptionRendererInterface {
+ $renderer = $this->_config['exceptionRenderer'];
+
+ if (is_string($renderer)) {
+ /** @var class-string<\Cake\Error\ExceptionRendererInterface>|null $class */
+ $class = App::className($renderer, 'Error');
+ if (!$class) {
+ throw new RuntimeException(sprintf(
+ "The '%s' renderer class could not be found.",
+ $renderer
+ ));
+ }
+
+ return new $class($exception, $request);
}
+
+ /** @var callable $factory */
+ $factory = $renderer;
+
+ return $factory($exception, $request);
}
/**
- * Logs both PHP5 and PHP7 errors.
- *
- * The PHP5 part will be removed with 4.0.
+ * Log internal errors.
*
- * @param \Throwable|\Exception $exception Exception.
+ * @param \Throwable $exception Exception.
* @return void
*/
- protected function _logInternalError($exception)
+ protected function _logInternalError(Throwable $exception): void
{
// Disable trace for internal errors.
- $this->_options['trace'] = false;
+ $this->_config['trace'] = false;
$message = sprintf(
"[%s] %s (%s:%s)\n%s", // Keeping same message format
get_class($exception),
@@ -187,7 +202,7 @@ protected function _logInternalError($exception)
* @param string|\Cake\Http\Response $response Either the message or response object.
* @return void
*/
- protected function _sendResponse($response)
+ protected function _sendResponse($response): void
{
if (is_string($response)) {
echo $response;
diff --git a/app/vendor/cakephp/cakephp/src/Error/ErrorLogger.php b/app/vendor/cakephp/cakephp/src/Error/ErrorLogger.php
new file mode 100644
index 000000000..06380ab03
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Error/ErrorLogger.php
@@ -0,0 +1,154 @@
+ [],
+ 'trace' => false,
+ ];
+
+ /**
+ * Constructor
+ *
+ * @param array $config Config array.
+ */
+ public function __construct(array $config = [])
+ {
+ $this->setConfig($config);
+ }
+
+ /**
+ * Generate the error log message.
+ *
+ * @param \Throwable $exception The exception to log a message for.
+ * @param \Psr\Http\Message\ServerRequestInterface|null $request The current request if available.
+ * @return bool
+ */
+ public function log(Throwable $exception, ?ServerRequestInterface $request = null): bool
+ {
+ foreach ($this->getConfig('skipLog') as $class) {
+ if ($exception instanceof $class) {
+ return false;
+ }
+ }
+
+ $message = $this->getMessage($exception);
+
+ if ($request !== null) {
+ $message .= $this->getRequestContext($request);
+ }
+
+ $message .= "\n\n";
+
+ return Log::error($message);
+ }
+
+ /**
+ * Generate the message for the exception
+ *
+ * @param \Throwable $exception The exception to log a message for.
+ * @param bool $isPrevious False for original exception, true for previous
+ * @return string Error message
+ */
+ protected function getMessage(Throwable $exception, bool $isPrevious = false): string
+ {
+ $message = sprintf(
+ '%s[%s] %s in %s on line %s',
+ $isPrevious ? "\nCaused by: " : '',
+ get_class($exception),
+ $exception->getMessage(),
+ $exception->getFile(),
+ $exception->getLine()
+ );
+ $debug = Configure::read('debug');
+
+ if ($debug && $exception instanceof Exception) {
+ $attributes = $exception->getAttributes();
+ if ($attributes) {
+ $message .= "\nException Attributes: " . var_export($exception->getAttributes(), true);
+ }
+ }
+
+ if ($this->getConfig('trace')) {
+ /** @var array $trace */
+ $trace = Debugger::formatTrace($exception, ['format' => 'points']);
+ $message .= "\nStack Trace:\n";
+ foreach ($trace as $line) {
+ if (is_string($line)) {
+ $message .= '- ' . $line;
+ } else {
+ $message .= "- {$line['file']}:{$line['line']}\n";
+ }
+ }
+ }
+
+ $previous = $exception->getPrevious();
+ if ($previous) {
+ $message .= $this->getMessage($previous, true);
+ }
+
+ return $message;
+ }
+
+ /**
+ * Get the request context for an error/exception trace.
+ *
+ * @param \Psr\Http\Message\ServerRequestInterface $request The request to read from.
+ * @return string
+ */
+ public function getRequestContext(ServerRequestInterface $request): string
+ {
+ $message = "\nRequest URL: " . $request->getRequestTarget();
+
+ $referer = $request->getHeaderLine('Referer');
+ if ($referer) {
+ $message .= "\nReferer URL: " . $referer;
+ }
+
+ if (method_exists($request, 'clientIp')) {
+ $clientIp = $request->clientIp();
+ if ($clientIp && $clientIp !== '::1') {
+ $message .= "\nClient IP: " . $clientIp;
+ }
+ }
+
+ return $message;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Error/ExceptionRenderer.php b/app/vendor/cakephp/cakephp/src/Error/ExceptionRenderer.php
index 7e8bd9095..24b517768 100644
--- a/app/vendor/cakephp/cakephp/src/Error/ExceptionRenderer.php
+++ b/app/vendor/cakephp/cakephp/src/Error/ExceptionRenderer.php
@@ -1,4 +1,6 @@
error = $exception;
$this->request = $request;
$this->controller = $this->_getController();
}
- /**
- * Returns the unwrapped exception object in case we are dealing with
- * a PHP 7 Error object
- *
- * @param \Exception $exception The object to unwrap
- * @return \Exception|\Error
- */
- protected function _unwrap($exception)
- {
- return $exception instanceof PHP7ErrorException ? $exception->getError() : $exception;
- }
-
/**
* Get the controller instance to handle the exception.
* Override this method in subclasses to customize the controller used.
@@ -122,10 +115,10 @@ protected function _unwrap($exception)
* @return \Cake\Controller\Controller
* @triggers Controller.startup $controller
*/
- protected function _getController()
+ protected function _getController(): Controller
{
$request = $this->request;
- $routerRequest = Router::getRequest(true);
+ $routerRequest = Router::getRequest();
// Fallback to the request in the router or make a new one from
// $_SERVER
if ($request === null) {
@@ -134,73 +127,78 @@ protected function _getController()
// If the current request doesn't have routing data, but we
// found a request in the router context copy the params over
- if ($request->getParam('controller') === false && $routerRequest !== null) {
+ if ($request->getParam('controller') === null && $routerRequest !== null) {
$request = $request->withAttribute('params', $routerRequest->getAttribute('params'));
}
- $response = new Response();
- $controller = null;
-
+ $errorOccured = false;
try {
- $namespace = 'Controller';
- $prefix = $request->getParam('prefix');
- if ($prefix) {
- if (strpos($prefix, '/') === false) {
- $namespace .= '/' . Inflector::camelize($prefix);
- } else {
- $prefixes = array_map(
- 'Cake\Utility\Inflector::camelize',
- explode('/', $prefix)
- );
- $namespace .= '/' . implode('/', $prefixes);
- }
- }
+ $params = $request->getAttribute('params');
+ $params['controller'] = 'Error';
- $class = App::className('Error', $namespace, 'Controller');
- if (!$class && $namespace !== 'Controller') {
+ $factory = new ControllerFactory();
+ $class = $factory->getControllerClass($request->withAttribute('params', $params));
+
+ if (!$class) {
+ /** @var string $class */
$class = App::className('Error', 'Controller', 'Controller');
}
/** @var \Cake\Controller\Controller $controller */
- $controller = new $class($request, $response);
+ $controller = new $class($request);
$controller->startupProcess();
- $startup = true;
- } catch (Exception $e) {
- $startup = false;
+ } catch (Throwable $e) {
+ $errorOccured = true;
+ }
+
+ if (!isset($controller)) {
+ return new Controller($request);
}
// Retry RequestHandler, as another aspect of startupProcess()
// could have failed. Ignore any exceptions out of startup, as
// there could be userland input data parsers.
- if ($startup === false && !empty($controller) && isset($controller->RequestHandler)) {
+ if ($errorOccured && isset($controller->RequestHandler)) {
try {
$event = new Event('Controller.startup', $controller);
$controller->RequestHandler->startup($event);
- } catch (Exception $e) {
+ } catch (Throwable $e) {
}
}
- if (empty($controller)) {
- $controller = new Controller($request, $response);
- }
return $controller;
}
+ /**
+ * Clear output buffers so error pages display properly.
+ *
+ * @return void
+ */
+ protected function clearOutput(): void
+ {
+ if (in_array(PHP_SAPI, ['cli', 'phpdbg'])) {
+ return;
+ }
+ while (ob_get_level()) {
+ ob_end_clean();
+ }
+ }
+
/**
* Renders the response for the exception.
*
* @return \Cake\Http\Response The response to be sent.
*/
- public function render()
+ public function render(): ResponseInterface
{
$exception = $this->error;
$code = $this->_code($exception);
$method = $this->_method($exception);
$template = $this->_template($exception, $method, $code);
- $unwrapped = $this->_unwrap($exception);
+ $this->clearOutput();
if (method_exists($this, $method)) {
- return $this->_customMethod($method, $unwrapped);
+ return $this->_customMethod($method, $exception);
}
$message = $this->_message($exception, $code);
@@ -217,28 +215,35 @@ public function render()
$viewVars = [
'message' => $message,
'url' => h($url),
- 'error' => $unwrapped,
+ 'error' => $exception,
'code' => $code,
- '_serialize' => ['message', 'url', 'code'],
];
+ $serialize = ['message', 'url', 'code'];
$isDebug = Configure::read('debug');
if ($isDebug) {
- $viewVars['trace'] = Debugger::formatTrace($unwrapped->getTrace(), [
+ $trace = (array)Debugger::formatTrace($exception->getTrace(), [
'format' => 'array',
'args' => false,
]);
- $viewVars['file'] = $exception->getFile() ?: 'null';
- $viewVars['line'] = $exception->getLine() ?: 'null';
- $viewVars['_serialize'][] = 'file';
- $viewVars['_serialize'][] = 'line';
+ $origin = [
+ 'file' => $exception->getFile() ?: 'null',
+ 'line' => $exception->getLine() ?: 'null',
+ ];
+ // Traces don't include the origin file/line.
+ array_unshift($trace, $origin);
+ $viewVars['trace'] = $trace;
+ $viewVars += $origin;
+ $serialize[] = 'file';
+ $serialize[] = 'line';
}
$this->controller->set($viewVars);
+ $this->controller->viewBuilder()->setOption('serialize', $serialize);
- if ($unwrapped instanceof CakeException && $isDebug) {
- $this->controller->set($unwrapped->getAttributes());
+ if ($exception instanceof CakeException && $isDebug) {
+ $this->controller->set($exception->getAttributes());
}
- $this->controller->response = $response;
+ $this->controller->setResponse($response);
return $this->_outputMessage($template);
}
@@ -247,15 +252,15 @@ public function render()
* Render a custom error method/template.
*
* @param string $method The method name to invoke.
- * @param \Exception $exception The exception to render.
+ * @param \Throwable $exception The exception to render.
* @return \Cake\Http\Response The response to send.
*/
- protected function _customMethod($method, $exception)
+ protected function _customMethod(string $method, Throwable $exception): Response
{
$result = call_user_func([$this, $method], $exception);
$this->_shutdown();
if (is_string($result)) {
- $result = $this->controller->response->withStringBody($result);
+ $result = $this->controller->getResponse()->withStringBody($result);
}
return $result;
@@ -264,13 +269,12 @@ protected function _customMethod($method, $exception)
/**
* Get method name
*
- * @param \Exception $exception Exception instance.
+ * @param \Throwable $exception Exception instance.
* @return string
*/
- protected function _method(Exception $exception)
+ protected function _method(Throwable $exception): string
{
- $exception = $this->_unwrap($exception);
- list(, $baseClass) = namespaceSplit(get_class($exception));
+ [, $baseClass] = namespaceSplit(get_class($exception));
if (substr($baseClass, -9) === 'Exception') {
$baseClass = substr($baseClass, 0, -9);
@@ -284,13 +288,12 @@ protected function _method(Exception $exception)
/**
* Get error message.
*
- * @param \Exception $exception Exception.
+ * @param \Throwable $exception Exception.
* @param int $code Error code.
* @return string Error message
*/
- protected function _message(Exception $exception, $code)
+ protected function _message(Throwable $exception, int $code): string
{
- $exception = $this->_unwrap($exception);
$message = $exception->getMessage();
if (
@@ -310,14 +313,13 @@ protected function _message(Exception $exception, $code)
/**
* Get template for rendering exception info.
*
- * @param \Exception $exception Exception instance.
+ * @param \Throwable $exception Exception instance.
* @param string $method Method name.
* @param int $code Error code.
* @return string Template name
*/
- protected function _template(Exception $exception, $method, $code)
+ protected function _template(Throwable $exception, string $method, int $code): string
{
- $exception = $this->_unwrap($exception);
$isHttpException = $exception instanceof HttpException;
if (!Configure::read('debug') && !$isHttpException || $isHttpException) {
@@ -341,15 +343,13 @@ protected function _template(Exception $exception, $method, $code)
/**
* Get HTTP status code.
*
- * @param \Exception $exception Exception.
+ * @param \Throwable $exception Exception.
* @return int A valid HTTP error status code.
*/
- protected function _code(Exception $exception)
+ protected function _code(Throwable $exception): int
{
$code = 500;
-
- $exception = $this->_unwrap($exception);
- $errorCode = $exception->getCode();
+ $errorCode = (int)$exception->getCode();
if ($errorCode >= 400 && $errorCode < 600) {
$code = $errorCode;
}
@@ -363,7 +363,7 @@ protected function _code(Exception $exception)
* @param string $template The template to render.
* @return \Cake\Http\Response A response object that can be sent.
*/
- protected function _outputMessage($template)
+ protected function _outputMessage(string $template): Response
{
try {
$this->controller->render($template);
@@ -371,7 +371,13 @@ protected function _outputMessage($template)
return $this->_shutdown();
} catch (MissingTemplateException $e) {
$attributes = $e->getAttributes();
- if (isset($attributes['file']) && strpos($attributes['file'], 'error500') !== false) {
+ if (
+ $e instanceof MissingLayoutException ||
+ (
+ isset($attributes['file']) &&
+ strpos($attributes['file'], 'error500') !== false
+ )
+ ) {
return $this->_outputMessageSafe('error500');
}
@@ -383,7 +389,7 @@ protected function _outputMessage($template)
}
return $this->_outputMessageSafe('error500');
- } catch (Exception $e) {
+ } catch (Throwable $e) {
return $this->_outputMessageSafe('error500');
}
}
@@ -395,21 +401,21 @@ protected function _outputMessage($template)
* @param string $template The template to render.
* @return \Cake\Http\Response A response object that can be sent.
*/
- protected function _outputMessageSafe($template)
+ protected function _outputMessageSafe(string $template): Response
{
- $helpers = ['Form', 'Html'];
- $this->controller->helpers = $helpers;
$builder = $this->controller->viewBuilder();
- $builder->setHelpers($helpers, false)
+ $builder
+ ->setHelpers([], false)
->setLayoutPath('')
->setTemplatePath('Error');
$view = $this->controller->createView('View');
- $this->controller->response = $this->controller->response
+ $response = $this->controller->getResponse()
->withType('html')
->withStringBody($view->render($template, 'error'));
+ $this->controller->setResponse($response);
- return $this->controller->response;
+ return $response;
}
/**
@@ -419,70 +425,11 @@ protected function _outputMessageSafe($template)
*
* @return \Cake\Http\Response The response to serve.
*/
- protected function _shutdown()
+ protected function _shutdown(): Response
{
$this->controller->dispatchEvent('Controller.shutdown');
- $dispatcher = DispatcherFactory::create();
- $eventManager = $dispatcher->getEventManager();
- foreach ($dispatcher->filters() as $filter) {
- $eventManager->on($filter);
- }
- $args = [
- 'request' => $this->controller->request,
- 'response' => $this->controller->response,
- ];
- $result = $dispatcher->dispatchEvent('Dispatcher.afterDispatch', $args);
-
- return $result->getData('response');
- }
-
- /**
- * Magic accessor for properties made protected.
- *
- * @param string $name Name of the attribute to get.
- * @return mixed
- */
- public function __get($name)
- {
- $protected = [
- 'error',
- 'controller',
- 'template',
- 'method',
- ];
- if (in_array($name, $protected, true)) {
- deprecationWarning(sprintf(
- 'ExceptionRenderer::$%s is now protected and should no longer be accessed in public context.',
- $name
- ));
- }
-
- return $this->{$name};
- }
-
- /**
- * Magic setter for properties made protected.
- *
- * @param string $name Name to property.
- * @param mixed $value Value for property.
- * @return void
- */
- public function __set($name, $value)
- {
- $protected = [
- 'error',
- 'controller',
- 'template',
- 'method',
- ];
- if (in_array($name, $protected, true)) {
- deprecationWarning(sprintf(
- 'ExceptionRenderer::$%s is now protected and should no longer be accessed in public context.',
- $name
- ));
- }
- $this->{$name} = $value;
+ return $this->controller->getResponse();
}
/**
@@ -491,7 +438,7 @@ public function __set($name, $value)
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
return [
'error' => $this->error,
diff --git a/app/vendor/cakephp/cakephp/src/Error/ExceptionRendererInterface.php b/app/vendor/cakephp/cakephp/src/Error/ExceptionRendererInterface.php
index f76939ca6..103e244ac 100644
--- a/app/vendor/cakephp/cakephp/src/Error/ExceptionRendererInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Error/ExceptionRendererInterface.php
@@ -1,4 +1,6 @@
file = $file;
diff --git a/app/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php b/app/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php
index ab3f80b03..c24867214 100644
--- a/app/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php
@@ -1,4 +1,6 @@
[],
'log' => true,
'trace' => false,
+ 'exceptionRenderer' => ExceptionRenderer::class,
];
/**
- * Exception render.
+ * Error handler instance.
*
- * @var \Cake\Error\ExceptionRendererInterface|callable|string|null
+ * @var \Cake\Error\ErrorHandler|null
*/
- protected $exceptionRenderer;
+ protected $errorHandler;
/**
* Constructor
*
- * @param string|callable|null $exceptionRenderer The renderer or class name
- * to use or a callable factory. If null, Configure::read('Error.exceptionRenderer')
- * will be used.
- * @param array $config Configuration options to use. If empty, `Configure::read('Error')`
- * will be used.
+ * @param \Cake\Error\ErrorHandler|array $errorHandler The error handler instance
+ * or config array.
+ * @throws \InvalidArgumentException
*/
- public function __construct($exceptionRenderer = null, array $config = [])
+ public function __construct($errorHandler = [])
{
- if ($exceptionRenderer) {
- $this->exceptionRenderer = $exceptionRenderer;
+ if (func_num_args() > 1) {
+ deprecationWarning(
+ 'The signature of ErrorHandlerMiddleware::__construct() has changed. '
+ . 'Pass the config array as 1st argument instead.'
+ );
+
+ $errorHandler = func_get_arg(1);
}
- $config = $config ?: Configure::read('Error');
- $this->setConfig($config);
+ if (is_array($errorHandler)) {
+ $this->setConfig($errorHandler);
- if (PHP_VERSION_ID >= 70400 && Configure::read('debug')) {
- ini_set('zend.exception_ignore_args', 0);
+ return;
}
+
+ if (!$errorHandler instanceof ErrorHandler) {
+ throw new InvalidArgumentException(sprintf(
+ '$errorHandler argument must be a config array or ErrorHandler instance. Got `%s` instead.',
+ getTypeName($errorHandler)
+ ));
+ }
+
+ $this->errorHandler = $errorHandler;
}
/**
* Wrap the remaining middleware with error handling.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @param \Psr\Http\Message\ResponseInterface $response The response.
- * @param callable $next Callback to invoke the next middleware.
- * @return \Psr\Http\Message\ResponseInterface A response
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
+ * @return \Psr\Http\Message\ResponseInterface A response.
*/
- public function __invoke($request, $response, $next)
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
try {
- return $next($request, $response);
+ return $handler->handle($request);
} catch (Throwable $exception) {
- return $this->handleException($exception, $request, $response);
- } catch (Exception $exception) {
- return $this->handleException($exception, $request, $response);
+ return $this->handleException($exception, $request);
}
}
/**
* Handle an exception and generate an error response
*
- * @param \Exception $exception The exception to handle.
+ * @param \Throwable $exception The exception to handle.
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @param \Psr\Http\Message\ResponseInterface $response The response.
* @return \Psr\Http\Message\ResponseInterface A response
*/
- public function handleException($exception, $request, $response)
+ public function handleException(Throwable $exception, ServerRequestInterface $request): ResponseInterface
{
- $renderer = $this->getRenderer($exception, $request);
- try {
- $res = $renderer->render();
- $this->logException($request, $exception);
+ $errorHandler = $this->getErrorHandler();
+ $renderer = $errorHandler->getRenderer($exception, $request);
- return $res;
- } catch (Throwable $exception) {
- $this->logException($request, $exception);
- $response = $this->handleInternalError($response);
- } catch (Exception $exception) {
- $this->logException($request, $exception);
- $response = $this->handleInternalError($response);
+ try {
+ $response = $renderer->render();
+ $errorHandler->logException($exception, $request);
+ } catch (Throwable $internalException) {
+ $errorHandler->logException($internalException, $request);
+ $response = $this->handleInternalError();
}
return $response;
}
/**
- * @param \Psr\Http\Message\ResponseInterface $response The response
- * @return \Psr\Http\Message\ResponseInterface A response
- */
- protected function handleInternalError($response)
- {
- $body = $response->getBody();
- $body->write('An Internal Server Error Occurred');
-
- return $response->withStatus(500)
- ->withBody($body);
- }
-
- /**
- * Get a renderer instance
+ * Handle internal errors.
*
- * @param \Exception $exception The exception being rendered.
- * @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @return \Cake\Error\ExceptionRendererInterface The exception renderer.
- * @throws \Exception When the renderer class cannot be found.
- */
- protected function getRenderer($exception, $request)
- {
- if (!$this->exceptionRenderer) {
- $this->exceptionRenderer = $this->getConfig('exceptionRenderer') ?: ExceptionRenderer::class;
- }
-
- // For PHP5 backwards compatibility
- if ($exception instanceof Error) {
- $exception = new PHP7ErrorException($exception);
- }
-
- if (is_string($this->exceptionRenderer)) {
- $class = App::className($this->exceptionRenderer, 'Error');
- if (!$class) {
- throw new Exception(sprintf(
- "The '%s' renderer class could not be found.",
- $this->exceptionRenderer
- ));
- }
-
- return new $class($exception, $request);
- }
- $factory = $this->exceptionRenderer;
-
- return $factory($exception, $request);
- }
-
- /**
- * Log an error for the exception if applicable.
- *
- * @param \Psr\Http\Message\ServerRequestInterface $request The current request.
- * @param \Exception $exception The exception to log a message for.
- * @return void
- */
- protected function logException($request, $exception)
- {
- if (!$this->getConfig('log')) {
- return;
- }
-
- foreach ((array)$this->getConfig('skipLog') as $class) {
- if ($exception instanceof $class) {
- return;
- }
- }
-
- Log::error($this->getMessage($request, $exception));
- }
-
- /**
- * Generate the error log message.
- *
- * @param \Psr\Http\Message\ServerRequestInterface $request The current request.
- * @param \Exception $exception The exception to log a message for.
- * @return string Error message
+ * @return \Psr\Http\Message\ResponseInterface A response
*/
- protected function getMessage($request, $exception)
+ protected function handleInternalError(): ResponseInterface
{
- $message = $this->getMessageForException($exception);
-
- $message .= "\nRequest URL: " . $request->getRequestTarget();
- $referer = $request->getHeaderLine('Referer');
- if ($referer) {
- $message .= "\nReferer URL: " . $referer;
- }
- $message .= "\n\n";
+ $response = new Response(['body' => 'An Internal Server Error Occurred']);
- return $message;
+ return $response->withStatus(500);
}
/**
- * Generate the message for the exception
+ * Get a error handler instance
*
- * @param \Exception $exception The exception to log a message for.
- * @param bool $isPrevious False for original exception, true for previous
- * @return string Error message
+ * @return \Cake\Error\ErrorHandler The error handler.
*/
- protected function getMessageForException($exception, $isPrevious = false)
+ protected function getErrorHandler(): ErrorHandler
{
- $message = sprintf(
- '%s[%s] %s (%s:%s)',
- $isPrevious ? "\nCaused by: " : '',
- get_class($exception),
- $exception->getMessage(),
- $exception->getFile(),
- $exception->getLine()
- );
- $debug = Configure::read('debug');
-
- if ($debug && $exception instanceof CakeException) {
- $attributes = $exception->getAttributes();
- if ($attributes) {
- $message .= "\nException Attributes: " . var_export($exception->getAttributes(), true);
- }
- }
-
- if ($this->getConfig('trace')) {
- $message .= "\n" . $exception->getTraceAsString();
- }
-
- $previous = $exception->getPrevious();
- if ($previous) {
- $message .= $this->getMessageForException($previous, true);
+ if ($this->errorHandler === null) {
+ /** @var class-string<\Cake\Error\ErrorHandler> $className */
+ $className = App::className('ErrorHandler', 'Error');
+ $this->errorHandler = new $className($this->getConfig());
}
- return $message;
+ return $this->errorHandler;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Error/PHP7ErrorException.php b/app/vendor/cakephp/cakephp/src/Error/PHP7ErrorException.php
deleted file mode 100644
index a8b853beb..000000000
--- a/app/vendor/cakephp/cakephp/src/Error/PHP7ErrorException.php
+++ /dev/null
@@ -1,62 +0,0 @@
-_error = $error;
- $this->message = $error->getMessage();
- $this->code = $error->getCode();
- $this->file = $error->getFile();
- $this->line = $error->getLine();
- $msg = sprintf(
- '(%s) - %s in %s on %s',
- get_class($error),
- $this->message,
- $this->file ?: 'null',
- $this->line ?: 'null'
- );
- parent::__construct($msg, $this->code, $error->getPrevious());
- }
-
- /**
- * Returns the wrapped error object
- *
- * @return \Error
- */
- public function getError()
- {
- return $this->_error;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Event/Decorator/AbstractDecorator.php b/app/vendor/cakephp/cakephp/src/Event/Decorator/AbstractDecorator.php
index 762896f74..5061d607e 100644
--- a/app/vendor/cakephp/cakephp/src/Event/Decorator/AbstractDecorator.php
+++ b/app/vendor/cakephp/cakephp/src/Event/Decorator/AbstractDecorator.php
@@ -1,4 +1,6 @@
_callable;
diff --git a/app/vendor/cakephp/cakephp/src/Event/Decorator/ConditionDecorator.php b/app/vendor/cakephp/cakephp/src/Event/Decorator/ConditionDecorator.php
index 5784225f3..92c7b9f3b 100644
--- a/app/vendor/cakephp/cakephp/src/Event/Decorator/ConditionDecorator.php
+++ b/app/vendor/cakephp/cakephp/src/Event/Decorator/ConditionDecorator.php
@@ -1,4 +1,6 @@
_evaluateCondition('if', $event);
$unless = $this->_evaluateCondition('unless', $event);
@@ -56,10 +58,10 @@ public function canTrigger(Event $event)
* Evaluates the filter conditions
*
* @param string $condition Condition type
- * @param \Cake\Event\Event $event Event object
+ * @param \Cake\Event\EventInterface $event Event object
* @return bool
*/
- protected function _evaluateCondition($condition, Event $event)
+ protected function _evaluateCondition(string $condition, EventInterface $event): bool
{
if (!isset($this->_options[$condition])) {
return $condition !== 'unless';
@@ -68,6 +70,6 @@ protected function _evaluateCondition($condition, Event $event)
throw new RuntimeException(self::class . ' the `' . $condition . '` condition is not a callable!');
}
- return $this->_options[$condition]($event);
+ return (bool)$this->_options[$condition]($event);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Event/Decorator/SubjectFilterDecorator.php b/app/vendor/cakephp/cakephp/src/Event/Decorator/SubjectFilterDecorator.php
index b25b5c9a9..a591e483e 100644
--- a/app/vendor/cakephp/cakephp/src/Event/Decorator/SubjectFilterDecorator.php
+++ b/app/vendor/cakephp/cakephp/src/Event/Decorator/SubjectFilterDecorator.php
@@ -1,4 +1,6 @@
getSubject());
if (!isset($this->_options['allowedSubject'])) {
throw new RuntimeException(self::class . ' Missing subject filter options!');
}
@@ -57,6 +59,12 @@ public function canTrigger(Event $event)
$this->_options['allowedSubject'] = [$this->_options['allowedSubject']];
}
- return in_array($class, $this->_options['allowedSubject']);
+ try {
+ $subject = $event->getSubject();
+ } catch (Exception $e) {
+ return false;
+ }
+
+ return in_array(get_class($subject), $this->_options['allowedSubject'], true);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Event/Event.php b/app/vendor/cakephp/cakephp/src/Event/Event.php
index ae5c87287..36c34a99e 100644
--- a/app/vendor/cakephp/cakephp/src/Event/Event.php
+++ b/app/vendor/cakephp/cakephp/src/Event/Event.php
@@ -1,4 +1,6 @@
$userData]);
- * $event = new Event('User.afterRegister', $UserModel);
+ * $event = new Event('User.afterRegister', $userModel);
* ```
*
* @param string $name Name of the event
- * @param object|null $subject the object that this event applies to (usually the object that is generating the event)
- * @param array|\ArrayAccess|null $data any value you wish to be transported with this event to it can be read by listeners
+ * @param object|null $subject the object that this event applies to
+ * (usually the object that is generating the event).
+ * @param array|\ArrayAccess|null $data any value you wish to be transported
+ * with this event to it can be read by listeners.
+ * @psalm-param TSubject|null $subject
*/
- public function __construct($name, $subject = null, $data = null)
+ public function __construct(string $name, $subject = null, $data = null)
{
$this->_name = $name;
$this->_subject = $subject;
$this->_data = (array)$data;
}
- /**
- * Provides read-only access for the name and subject properties.
- *
- * @param string $attribute Attribute name.
- * @return mixed
- * @deprecated 3.4.0 Public properties will be removed.
- */
- public function __get($attribute)
- {
- if (!in_array($attribute, ['name', 'subject', 'data', 'result'])) {
- return $this->{$attribute};
- }
-
- $method = 'get' . ucfirst($attribute);
- deprecationWarning(
- "Event::\${$attribute} is deprecated. " .
- "Use Event::{$method}() instead."
- );
- if ($attribute === 'name' || $attribute === 'subject') {
- return $this->{$attribute}();
- }
- if ($attribute === 'data') {
- return $this->_data;
- }
- if ($attribute === 'result') {
- return $this->result;
- }
- }
-
- /**
- * Provides backward compatibility for write access to data and result properties.
- *
- * @param string $attribute Attribute name.
- * @param mixed $value The value to set.
- * @return void
- * @deprecated 3.4.0 Public properties will be removed.
- */
- public function __set($attribute, $value)
- {
- $method = 'set' . ucfirst($attribute);
- deprecationWarning(
- "Event::\${$attribute} is deprecated. " .
- "Use Event::{$method}() instead."
- );
- if ($attribute === 'data') {
- $this->_data = (array)$value;
- }
- if ($attribute === 'result') {
- $this->result = $value;
- }
- }
-
/**
* Returns the name of this event. This is usually used as the event identifier
*
* @return string
- * @deprecated 3.4.0 use getName() instead.
*/
- public function name()
- {
- deprecationWarning('Event::name() is deprecated. Use Event::getName() instead.');
-
- return $this->_name;
- }
-
- /**
- * Returns the name of this event. This is usually used as the event identifier
- *
- * @return string
- */
- public function getName()
+ public function getName(): string
{
return $this->_name;
}
@@ -155,23 +100,19 @@ public function getName()
/**
* Returns the subject of this event
*
- * @return object
- * @deprecated 3.4.0 use getSubject() instead.
- */
- public function subject()
- {
- deprecationWarning('Event::subject() is deprecated. Use Event::getSubject() instead.');
-
- return $this->_subject;
- }
-
- /**
- * Returns the subject of this event
+ * If the event has no subject an exception will be raised.
*
* @return object
+ * @throws \Cake\Core\Exception\Exception
+ * @psalm-return TSubject
+ * @psalm-suppress LessSpecificImplementedReturnType
*/
public function getSubject()
{
+ if ($this->_subject === null) {
+ throw new Exception('No subject set for this event');
+ }
+
return $this->_subject;
}
@@ -180,7 +121,7 @@ public function getSubject()
*
* @return void
*/
- public function stopPropagation()
+ public function stopPropagation(): void
{
$this->_stopped = true;
}
@@ -190,24 +131,11 @@ public function stopPropagation()
*
* @return bool True if the event is stopped
*/
- public function isStopped()
+ public function isStopped(): bool
{
return $this->_stopped;
}
- /**
- * The result value of the event listeners
- *
- * @return mixed
- * @deprecated 3.4.0 use getResult() instead.
- */
- public function result()
- {
- deprecationWarning('Event::result() is deprecated. Use Event::getResult() instead.');
-
- return $this->result;
- }
-
/**
* The result value of the event listeners
*
@@ -235,28 +163,13 @@ public function setResult($value = null)
* Access the event data/payload.
*
* @param string|null $key The data payload element to return, or null to return all data.
- * @return array|mixed|null The data payload if $key is null, or the data value for the given $key. If the $key does not
- * exist a null value is returned.
- * @deprecated 3.4.0 use getData() instead.
- */
- public function data($key = null)
- {
- deprecationWarning('Event::data() is deprecated. Use Event::getData() instead.');
-
- return $this->getData($key);
- }
-
- /**
- * Access the event data/payload.
- *
- * @param string|null $key The data payload element to return, or null to return all data.
- * @return array|mixed|null The data payload if $key is null, or the data value for the given $key. If the $key does not
- * exist a null value is returned.
+ * @return array|mixed|null The data payload if $key is null, or the data value for the given $key.
+ * If the $key does not exist a null value is returned.
*/
- public function getData($key = null)
+ public function getData(?string $key = null)
{
if ($key !== null) {
- return isset($this->_data[$key]) ? $this->_data[$key] : null;
+ return $this->_data[$key] ?? null;
}
return (array)$this->_data;
diff --git a/app/vendor/cakephp/cakephp/src/Event/EventDispatcherInterface.php b/app/vendor/cakephp/cakephp/src/Event/EventDispatcherInterface.php
index 6e424a5d0..3bd812d09 100644
--- a/app/vendor/cakephp/cakephp/src/Event/EventDispatcherInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Event/EventDispatcherInterface.php
@@ -1,4 +1,6 @@
setEventManager($eventManager);
- }
-
- return $this->getEventManager();
- }
-
- /**
- * Returns the Cake\Event\EventManager manager instance for this object.
- *
- * You can use this instance to register any new listeners or callbacks to the
- * object events, or create your own events and trigger them at will.
- *
- * @return \Cake\Event\EventManager
+ * @return \Cake\Event\EventManagerInterface
*/
- public function getEventManager()
+ public function getEventManager(): EventManagerInterface
{
if ($this->_eventManager === null) {
$this->_eventManager = new EventManager();
@@ -75,15 +54,15 @@ public function getEventManager()
}
/**
- * Returns the Cake\Event\EventManager manager instance for this object.
+ * Returns the Cake\Event\EventManagerInterface instance for this object.
*
* You can use this instance to register any new listeners or callbacks to the
* object events, or create your own events and trigger them at will.
*
- * @param \Cake\Event\EventManager $eventManager the eventManager to set
+ * @param \Cake\Event\EventManagerInterface $eventManager the eventManager to set
* @return $this
*/
- public function setEventManager(EventManager $eventManager)
+ public function setEventManager(EventManagerInterface $eventManager)
{
$this->_eventManager = $eventManager;
@@ -100,14 +79,15 @@ public function setEventManager(EventManager $eventManager)
* it can be read by listeners.
* @param object|null $subject The object that this event applies to
* ($this by default).
- * @return \Cake\Event\Event
+ * @return \Cake\Event\EventInterface
*/
- public function dispatchEvent($name, $data = null, $subject = null)
+ public function dispatchEvent(string $name, ?array $data = null, ?object $subject = null): EventInterface
{
if ($subject === null) {
$subject = $this;
}
+ /** @var \Cake\Event\EventInterface $event */
$event = new $this->_eventClass($name, $subject, $data);
$this->getEventManager()->dispatch($event);
diff --git a/app/vendor/cakephp/cakephp/src/Event/EventInterface.php b/app/vendor/cakephp/cakephp/src/Event/EventInterface.php
index 4733ccea6..e67aceed1 100644
--- a/app/vendor/cakephp/cakephp/src/Event/EventInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Event/EventInterface.php
@@ -1,4 +1,6 @@
_events = [];
}
@@ -42,10 +44,10 @@ public function flush()
/**
* Adds an event to the list when event listing is enabled.
*
- * @param \Cake\Event\Event $event An event to the list of dispatched events.
+ * @param \Cake\Event\EventInterface $event An event to the list of dispatched events.
* @return void
*/
- public function add(Event $event)
+ public function add(EventInterface $event): void
{
$this->_events[] = $event;
}
@@ -57,7 +59,7 @@ public function add(Event $event)
* @param mixed $offset An offset to check for.
* @return bool True on success or false on failure.
*/
- public function offsetExists($offset)
+ public function offsetExists($offset): bool
{
return isset($this->_events[$offset]);
}
@@ -86,7 +88,7 @@ public function offsetGet($offset)
* @param mixed $value The value to set.
* @return void
*/
- public function offsetSet($offset, $value)
+ public function offsetSet($offset, $value): void
{
$this->_events[$offset] = $value;
}
@@ -98,7 +100,7 @@ public function offsetSet($offset, $value)
* @param mixed $offset The offset to unset.
* @return void
*/
- public function offsetUnset($offset)
+ public function offsetUnset($offset): void
{
unset($this->_events[$offset]);
}
@@ -109,7 +111,7 @@ public function offsetUnset($offset)
* @link https://secure.php.net/manual/en/countable.count.php
* @return int The custom count as an integer.
*/
- public function count()
+ public function count(): int
{
return count($this->_events);
}
@@ -120,7 +122,7 @@ public function count()
* @param string $name Event name.
* @return bool
*/
- public function hasEvent($name)
+ public function hasEvent(string $name): bool
{
foreach ($this->_events as $event) {
if ($event->getName() === $name) {
diff --git a/app/vendor/cakephp/cakephp/src/Event/EventListenerInterface.php b/app/vendor/cakephp/cakephp/src/Event/EventListenerInterface.php
index 9e4389399..484cddf99 100644
--- a/app/vendor/cakephp/cakephp/src/Event/EventListenerInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Event/EventListenerInterface.php
@@ -1,4 +1,6 @@
on($callable);
-
- return;
- }
- if ($options) {
- $this->on($eventKey, $options, $callable);
-
- return;
- }
- $this->on($eventKey, $callable);
- }
-
- /**
- * {@inheritDoc}
- */
- public function on($eventKey = null, $options = [], $callable = null)
+ public function on($eventKey, $options = [], ?callable $callable = null)
{
if ($eventKey instanceof EventListenerInterface) {
$this->_attachSubscriber($eventKey);
return $this;
}
+
$argCount = func_num_args();
if ($argCount === 2) {
$this->_listeners[$eventKey][static::$defaultPriority][] = [
@@ -144,18 +112,13 @@ public function on($eventKey = null, $options = [], $callable = null)
return $this;
}
- if ($argCount === 3) {
- $priority = isset($options['priority']) ? $options['priority'] : static::$defaultPriority;
- $this->_listeners[$eventKey][$priority][] = [
- 'callable' => $callable,
- ];
- return $this;
- }
- throw new InvalidArgumentException(
- 'Invalid arguments for EventManager::on(). ' .
- "Expected 1, 2 or 3 arguments. Got {$argCount} arguments."
- );
+ $priority = $options['priority'] ?? static::$defaultPriority;
+ $this->_listeners[$eventKey][$priority][] = [
+ 'callable' => $callable,
+ ];
+
+ return $this;
}
/**
@@ -165,16 +128,16 @@ public function on($eventKey = null, $options = [], $callable = null)
* @param \Cake\Event\EventListenerInterface $subscriber Event listener.
* @return void
*/
- protected function _attachSubscriber(EventListenerInterface $subscriber)
+ protected function _attachSubscriber(EventListenerInterface $subscriber): void
{
foreach ((array)$subscriber->implementedEvents() as $eventKey => $function) {
$options = [];
$method = $function;
if (is_array($function) && isset($function['callable'])) {
- list($method, $options) = $this->_extractCallable($function, $subscriber);
+ [$method, $options] = $this->_extractCallable($function, $subscriber);
} elseif (is_array($function) && is_numeric(key($function))) {
foreach ($function as $f) {
- list($method, $options) = $this->_extractCallable($f, $subscriber);
+ [$method, $options] = $this->_extractCallable($f, $subscriber);
$this->on($eventKey, $options, $method);
}
continue;
@@ -192,14 +155,16 @@ protected function _attachSubscriber(EventListenerInterface $subscriber)
*
* @param array $function the array taken from a handler definition for an event
* @param \Cake\Event\EventListenerInterface $object The handler object
- * @return callable
+ * @return array
*/
- protected function _extractCallable($function, $object)
+ protected function _extractCallable(array $function, EventListenerInterface $object): array
{
+ /** @var callable $method */
$method = $function['callable'];
$options = $function;
unset($options['callable']);
if (is_string($method)) {
+ /** @var callable $method */
$method = [$object, $method];
}
@@ -207,26 +172,7 @@ protected function _extractCallable($function, $object)
}
/**
- * Removes a listener from the active listeners.
- *
- * @param callable|\Cake\Event\EventListenerInterface $callable any valid PHP callback type or an instance of EventListenerInterface
- * @param string|null $eventKey The event unique identifier name with which the callback has been associated
- * @return void
- * @deprecated 3.0.0 Use off() instead.
- */
- public function detach($callable, $eventKey = null)
- {
- deprecationWarning('EventManager::detach() is deprecated. Use EventManager::off() instead.');
- if ($eventKey === null) {
- $this->off($callable);
-
- return;
- }
- $this->off($eventKey, $callable);
- }
-
- /**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function off($eventKey, $callable = null)
{
@@ -235,26 +181,38 @@ public function off($eventKey, $callable = null)
return $this;
}
- if ($callable instanceof EventListenerInterface) {
- $this->_detachSubscriber($callable, $eventKey);
+
+ if (!is_string($eventKey)) {
+ if (!is_callable($eventKey)) {
+ throw new Exception(
+ 'First argument of EventManager::off() must be ' .
+ ' string or EventListenerInterface instance or callable.'
+ );
+ }
+
+ foreach (array_keys($this->_listeners) as $name) {
+ $this->off($name, $eventKey);
+ }
return $this;
}
- if ($callable === null && is_string($eventKey)) {
- unset($this->_listeners[$eventKey]);
+
+ if ($callable instanceof EventListenerInterface) {
+ $this->_detachSubscriber($callable, $eventKey);
return $this;
}
+
if ($callable === null) {
- foreach (array_keys($this->_listeners) as $name) {
- $this->off($name, $eventKey);
- }
+ unset($this->_listeners[$eventKey]);
return $this;
}
+
if (empty($this->_listeners[$eventKey])) {
return $this;
}
+
foreach ($this->_listeners[$eventKey] as $priority => $callables) {
foreach ($callables as $k => $callback) {
if ($callback['callable'] === $callable) {
@@ -274,7 +232,7 @@ public function off($eventKey, $callable = null)
* @param string|null $eventKey optional event key name to unsubscribe the listener from
* @return void
*/
- protected function _detachSubscriber(EventListenerInterface $subscriber, $eventKey = null)
+ protected function _detachSubscriber(EventListenerInterface $subscriber, ?string $eventKey = null): void
{
$events = (array)$subscriber->implementedEvents();
if (!empty($eventKey) && empty($events[$eventKey])) {
@@ -287,7 +245,7 @@ protected function _detachSubscriber(EventListenerInterface $subscriber, $eventK
if (is_array($function)) {
if (is_numeric(key($function))) {
foreach ($function as $handler) {
- $handler = isset($handler['callable']) ? $handler['callable'] : $handler;
+ $handler = $handler['callable'] ?? $handler;
$this->off($key, [$subscriber, $handler]);
}
continue;
@@ -299,9 +257,9 @@ protected function _detachSubscriber(EventListenerInterface $subscriber, $eventK
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function dispatch($event)
+ public function dispatch($event): EventInterface
{
if (is_string($event)) {
$event = new Event($event);
@@ -346,15 +304,15 @@ public function dispatch($event)
*/
protected function _callListener(callable $listener, EventInterface $event)
{
- $data = $event->getData();
+ $data = (array)$event->getData();
return $listener($event, ...array_values($data));
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function listeners($eventKey)
+ public function listeners(string $eventKey): array
{
$localListeners = [];
if (!$this->_isGlobal) {
@@ -387,7 +345,7 @@ public function listeners($eventKey)
* @param string $eventKey Event key.
* @return array
*/
- public function prioritisedListeners($eventKey)
+ public function prioritisedListeners(string $eventKey): array
{
if (empty($this->_listeners[$eventKey])) {
return [];
@@ -402,7 +360,7 @@ public function prioritisedListeners($eventKey)
* @param string $eventKeyPattern Pattern to match.
* @return array
*/
- public function matchingListeners($eventKeyPattern)
+ public function matchingListeners(string $eventKeyPattern): array
{
$matchPattern = '/' . preg_quote($eventKeyPattern, '/') . '/';
$matches = array_intersect_key(
@@ -418,9 +376,9 @@ public function matchingListeners($eventKeyPattern)
/**
* Returns the event list.
*
- * @return \Cake\Event\EventList
+ * @return \Cake\Event\EventList|null
*/
- public function getEventList()
+ public function getEventList(): ?EventList
{
return $this->_eventList;
}
@@ -428,10 +386,10 @@ public function getEventList()
/**
* Adds an event to the list if the event list object is present.
*
- * @param \Cake\Event\Event $event An event to add to the list.
+ * @param \Cake\Event\EventInterface $event An event to add to the list.
* @return $this
*/
- public function addEventToList(Event $event)
+ public function addEventToList(EventInterface $event)
{
if ($this->_eventList) {
$this->_eventList->add($event);
@@ -446,7 +404,7 @@ public function addEventToList(Event $event)
* @param bool $enabled True or false to enable / disable it.
* @return $this
*/
- public function trackEvents($enabled)
+ public function trackEvents(bool $enabled)
{
$this->_trackEvents = (bool)$enabled;
@@ -458,7 +416,7 @@ public function trackEvents($enabled)
*
* @return bool
*/
- public function isTrackingEvents()
+ public function isTrackingEvents(): bool
{
return $this->_trackEvents && $this->_eventList;
}
@@ -495,7 +453,7 @@ public function unsetEventList()
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$properties = get_object_vars($this);
$properties['_generalManager'] = '(object) EventManager';
@@ -511,9 +469,12 @@ public function __debugInfo()
$count = count($this->_eventList);
for ($i = 0; $i < $count; $i++) {
$event = $this->_eventList[$i];
- $subject = $event->getSubject();
- $properties['_dispatchedEvents'][] = $event->getName() . ' with ' .
- (is_object($subject) ? 'subject ' . get_class($subject) : 'no subject');
+ try {
+ $subject = $event->getSubject();
+ $properties['_dispatchedEvents'][] = $event->getName() . ' with subject ' . get_class($subject);
+ } catch (Exception $e) {
+ $properties['_dispatchedEvents'][] = $event->getName() . ' with no subject';
+ }
}
} else {
$properties['_dispatchedEvents'] = null;
diff --git a/app/vendor/cakephp/cakephp/src/Event/EventManagerInterface.php b/app/vendor/cakephp/cakephp/src/Event/EventManagerInterface.php
index 236eedf11..80d90a0e1 100644
--- a/app/vendor/cakephp/cakephp/src/Event/EventManagerInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Event/EventManagerInterface.php
@@ -1,4 +1,6 @@
on('Model.beforeSave', ['priority' => 90], $callable);
* ```
*
- * @param string|\Cake\Event\EventListenerInterface|null $eventKey The event unique identifier name
+ * @param string|\Cake\Event\EventListenerInterface $eventKey The event unique identifier name
* with which the callback will be associated. If $eventKey is an instance of
* Cake\Event\EventListenerInterface its events will be bound using the `implementedEvents` methods.
*
@@ -55,7 +57,7 @@ interface EventManagerInterface
* @throws \InvalidArgumentException When event key is missing or callable is not an
* instance of Cake\Event\EventListenerInterface.
*/
- public function on($eventKey = null, $options = [], $callable = null);
+ public function on($eventKey, $options = [], ?callable $callable = null);
/**
* Remove a listener from the active listeners.
@@ -84,9 +86,9 @@ public function on($eventKey = null, $options = [], $callable = null);
* $manager->off($callback);
* ```
*
- * @param string|\Cake\Event\EventListenerInterface $eventKey The event unique identifier name
+ * @param string|\Cake\Event\EventListenerInterface|callable $eventKey The event unique identifier name
* with which the callback has been associated, or the $listener you want to remove.
- * @param callable|null $callable The callback you want to detach.
+ * @param \Cake\Event\EventListenerInterface|callable|null $callable The callback you want to detach.
* @return $this
*/
public function off($eventKey, $callable = null);
@@ -98,7 +100,7 @@ public function off($eventKey, $callable = null);
* @return \Cake\Event\EventInterface
* @triggers $event
*/
- public function dispatch($event);
+ public function dispatch($event): EventInterface;
/**
* Returns a list of all listeners for an eventKey in the order they should be called
@@ -106,5 +108,5 @@ public function dispatch($event);
* @param string $eventKey Event key.
* @return array
*/
- public function listeners($eventKey);
+ public function listeners(string $eventKey): array;
}
diff --git a/app/vendor/cakephp/cakephp/src/Event/EventManagerTrait.php b/app/vendor/cakephp/cakephp/src/Event/EventManagerTrait.php
deleted file mode 100644
index 4425af18c..000000000
--- a/app/vendor/cakephp/cakephp/src/Event/EventManagerTrait.php
+++ /dev/null
@@ -1,25 +0,0 @@
-=5.6.0,<8.0.0",
- "cakephp/core": "^3.6.0"
+ "php": ">=7.2.0",
+ "cakephp/core": "^4.0"
},
"autoload": {
"psr-4": {
diff --git a/app/vendor/cakephp/cakephp/src/Filesystem/File.php b/app/vendor/cakephp/cakephp/src/Filesystem/File.php
index 21c02c026..b146b71de 100644
--- a/app/vendor/cakephp/cakephp/src/Filesystem/File.php
+++ b/app/vendor/cakephp/cakephp/src/Filesystem/File.php
@@ -1,4 +1,6 @@
Folder = new Folder($splInfo->getPath(), $create, $mode);
@@ -104,7 +108,7 @@ public function __destruct()
*
* @return bool Success
*/
- public function create()
+ public function create(): bool
{
$dir = $this->Folder->pwd();
@@ -122,7 +126,7 @@ public function create()
* @param bool $force If true then the file will be re-opened even if its already opened, otherwise it won't
* @return bool True on success, false on failure
*/
- public function open($mode = 'r', $force = false)
+ public function open(string $mode = 'r', bool $force = false): bool
{
if (!$force && is_resource($this->handle)) {
return true;
@@ -139,14 +143,14 @@ public function open($mode = 'r', $force = false)
/**
* Return the contents of this file as a string.
*
- * @param int|false $lengthInBytes The length to read in bytes or `false` for the full file. Defaults to `false`.
+ * @param string|false $bytes where to start
* @param string $mode A `fread` compatible mode.
* @param bool $force If true then the file will be re-opened even if its already opened, otherwise it won't
* @return string|false String on success, false on failure
*/
- public function read($lengthInBytes = false, $mode = 'rb', $force = false)
+ public function read($bytes = false, string $mode = 'rb', bool $force = false)
{
- if ($lengthInBytes === false && $this->lock === null) {
+ if ($bytes === false && $this->lock === null) {
return file_get_contents($this->path);
}
if ($this->open($mode, $force) === false) {
@@ -155,8 +159,8 @@ public function read($lengthInBytes = false, $mode = 'rb', $force = false)
if ($this->lock !== null && flock($this->handle, LOCK_SH) === false) {
return false;
}
- if (is_int($lengthInBytes)) {
- return fread($this->handle, $lengthInBytes);
+ if (is_int($bytes)) {
+ return fread($this->handle, $bytes);
}
$data = '';
@@ -167,7 +171,7 @@ public function read($lengthInBytes = false, $mode = 'rb', $force = false)
if ($this->lock !== null) {
flock($this->handle, LOCK_UN);
}
- if ($lengthInBytes === false) {
+ if ($bytes === false) {
$this->close();
}
@@ -177,11 +181,12 @@ public function read($lengthInBytes = false, $mode = 'rb', $force = false)
/**
* Sets or gets the offset for the currently opened file.
*
- * @param int|bool $offset The $offset in bytes to seek. If set to false then the current offset is returned.
+ * @param int|false $offset The $offset in bytes to seek. If set to false then the current offset is returned.
* @param int $seek PHP Constant SEEK_SET | SEEK_CUR | SEEK_END determining what the $offset is relative to
- * @return int|bool True on success, false on failure (set mode), false on failure or integer offset on success (get mode)
+ * @return int|bool True on success, false on failure (set mode), false on failure
+ * or integer offset on success (get mode).
*/
- public function offset($offset = false, $seek = SEEK_SET)
+ public function offset($offset = false, int $seek = SEEK_SET)
{
if ($offset === false) {
if (is_resource($this->handle)) {
@@ -203,7 +208,7 @@ public function offset($offset = false, $seek = SEEK_SET)
* @param bool $forceWindows If true forces Windows new line string.
* @return string The with converted line endings.
*/
- public static function prepare($data, $forceWindows = false)
+ public static function prepare(string $data, bool $forceWindows = false): string
{
$lineBreak = "\n";
if (DIRECTORY_SEPARATOR === '\\' || $forceWindows === true) {
@@ -221,7 +226,7 @@ public static function prepare($data, $forceWindows = false)
* @param bool $force Force the file to open
* @return bool Success
*/
- public function write($data, $mode = 'w', $force = false)
+ public function write(string $data, string $mode = 'w', bool $force = false): bool
{
$success = false;
if ($this->open($mode, $force) === true) {
@@ -247,7 +252,7 @@ public function write($data, $mode = 'w', $force = false)
* @param bool $force Force the file to open
* @return bool Success
*/
- public function append($data, $force = false)
+ public function append(string $data, bool $force = false): bool
{
return $this->write($data, 'a', $force);
}
@@ -257,7 +262,7 @@ public function append($data, $force = false)
*
* @return bool True if closing was successful or file was already closed, otherwise false
*/
- public function close()
+ public function close(): bool
{
if (!is_resource($this->handle)) {
return true;
@@ -271,12 +276,10 @@ public function close()
*
* @return bool Success
*/
- public function delete()
+ public function delete(): bool
{
- if (is_resource($this->handle)) {
- fclose($this->handle);
- $this->handle = null;
- }
+ $this->close();
+ $this->handle = null;
if ($this->exists()) {
return unlink($this->path);
}
@@ -296,7 +299,7 @@ public function delete()
*
* @return array File information.
*/
- public function info()
+ public function info(): array
{
if (!$this->info) {
$this->info = pathinfo($this->path);
@@ -358,11 +361,11 @@ public function name()
* @param string|null $ext The name of the extension
* @return string the file basename.
*/
- protected static function _basename($path, $ext = null)
+ protected static function _basename(string $path, ?string $ext = null): string
{
// check for multibyte string and use basename() if not found
if (mb_strlen($path) === strlen($path)) {
- return ($ext === null) ? basename($path) : basename($path, $ext);
+ return $ext === null ? basename($path) : basename($path, $ext);
}
$splInfo = new SplFileInfo($path);
@@ -372,10 +375,10 @@ protected static function _basename($path, $ext = null)
return $name;
}
$ext = preg_quote($ext);
- $new = preg_replace("/({$ext})$/u", "", $name);
+ $new = preg_replace("/({$ext})$/u", '', $name);
// basename of '/etc/.d' is '.d' not ''
- return ($new === '') ? $name : $new;
+ return $new === '' ? $name : $new;
}
/**
@@ -385,13 +388,13 @@ protected static function _basename($path, $ext = null)
* @param string|null $ext The name of the extension to make safe if different from $this->ext
* @return string The extension of the file
*/
- public function safe($name = null, $ext = null)
+ public function safe(?string $name = null, ?string $ext = null): string
{
if (!$name) {
- $name = $this->name;
+ $name = (string)$this->name;
}
if (!$ext) {
- $ext = $this->ext();
+ $ext = (string)$this->ext();
}
return preg_replace("/(?:[^\w\.-]+)/", '_', static::_basename($name, $ext));
@@ -400,8 +403,9 @@ public function safe($name = null, $ext = null)
/**
* Get md5 Checksum of file with previous check of Filesize
*
- * @param int|bool $maxsize in MB or true to force
- * @return string|false md5 Checksum {@link https://secure.php.net/md5_file See md5_file()}, or false in case of an error
+ * @param int|true $maxsize in MB or true to force
+ * @return string|false md5 Checksum {@link https://secure.php.net/md5_file See md5_file()},
+ * or false in case of an error.
*/
public function md5($maxsize = 5)
{
@@ -410,7 +414,7 @@ public function md5($maxsize = 5)
}
$size = $this->size();
- if ($size && $size < ($maxsize * 1024) * 1024) {
+ if ($size && $size < $maxsize * 1024 * 1024) {
return md5_file($this->path);
}
@@ -420,13 +424,13 @@ public function md5($maxsize = 5)
/**
* Returns the full path of the file.
*
- * @return string Full path to the file
+ * @return string|false Full path to the file, or false on failure
*/
public function pwd()
{
if ($this->path === null) {
$dir = $this->Folder->pwd();
- if (is_dir($dir)) {
+ if ($dir && is_dir($dir)) {
$this->path = $this->Folder->slashTerm($dir) . $this->name;
}
}
@@ -439,11 +443,11 @@ public function pwd()
*
* @return bool True if it exists, false otherwise
*/
- public function exists()
+ public function exists(): bool
{
$this->clearStatCache();
- return (file_exists($this->path) && is_file($this->path));
+ return $this->path && file_exists($this->path) && is_file($this->path);
}
/**
@@ -454,7 +458,7 @@ public function exists()
public function perms()
{
if ($this->exists()) {
- return substr(sprintf('%o', fileperms($this->path)), -4);
+ return decoct(fileperms($this->path) & 0777);
}
return false;
@@ -479,7 +483,7 @@ public function size()
*
* @return bool True if it's writable, false otherwise
*/
- public function writable()
+ public function writable(): bool
{
return is_writable($this->path);
}
@@ -489,7 +493,7 @@ public function writable()
*
* @return bool True if it's executable, false otherwise
*/
- public function executable()
+ public function executable(): bool
{
return is_executable($this->path);
}
@@ -499,7 +503,7 @@ public function executable()
*
* @return bool True if file is readable, false otherwise
*/
- public function readable()
+ public function readable(): bool
{
return is_readable($this->path);
}
@@ -507,7 +511,7 @@ public function readable()
/**
* Returns the file's owner.
*
- * @return int|false The file owner, or false in case of an error
+ * @return int|false The file owner, or bool in case of an error
*/
public function owner()
{
@@ -565,7 +569,7 @@ public function lastChange()
*
* @return \Cake\Filesystem\Folder Current folder
*/
- public function folder()
+ public function folder(): Folder
{
return $this->Folder;
}
@@ -577,7 +581,7 @@ public function folder()
* @param bool $overwrite Overwrite $dest if exists
* @return bool Success
*/
- public function copy($dest, $overwrite = true)
+ public function copy(string $dest, bool $overwrite = true): bool
{
if (!$this->exists() || is_file($dest) && !$overwrite) {
return false;
@@ -603,7 +607,7 @@ public function mime()
if (!$type) {
return false;
}
- list($type) = explode(';', $type);
+ [$type] = explode(';', $type);
return $type;
}
@@ -621,9 +625,9 @@ public function mime()
* the stat cache for the current path only.
* @return void
*/
- public function clearStatCache($all = false)
+ public function clearStatCache($all = false): void
{
- if ($all === false) {
+ if ($all === false && $this->path) {
clearstatcache(true, $this->path);
}
@@ -637,7 +641,7 @@ public function clearStatCache($all = false)
* @param string|array $replace Text(s) to replace with.
* @return bool Success
*/
- public function replaceText($search, $replace)
+ public function replaceText($search, $replace): bool
{
if (!$this->open('r+')) {
return false;
diff --git a/app/vendor/cakephp/cakephp/src/Filesystem/Filesystem.php b/app/vendor/cakephp/cakephp/src/Filesystem/Filesystem.php
new file mode 100644
index 000000000..90ef244e6
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Filesystem/Filesystem.php
@@ -0,0 +1,269 @@
+filterIterator($directory, $filter);
+ }
+
+ /**
+ * Find files/ directories recursively in given directory path.
+ *
+ * @param string $path Directory path.
+ * @param mixed $filter If string will be used as regex for filtering using
+ * `RegexIterator`, if callable will be as callback for `CallbackFilterIterator`.
+ * Hidden directories (starting with dot e.g. .git) are always skipped.
+ * @param int|null $flags Flags for FilesystemIterator::__construct();
+ * @return \Iterator
+ */
+ public function findRecursive(string $path, $filter = null, ?int $flags = null): Iterator
+ {
+ $flags = $flags ?? FilesystemIterator::KEY_AS_PATHNAME
+ | FilesystemIterator::CURRENT_AS_FILEINFO
+ | FilesystemIterator::SKIP_DOTS;
+ $directory = new RecursiveDirectoryIterator($path, $flags);
+
+ $dirFilter = new RecursiveCallbackFilterIterator(
+ $directory,
+ function (SplFileInfo $current) {
+ if ($current->getFilename()[0] === '.' && $current->isDir()) {
+ return false;
+ }
+
+ return true;
+ }
+ );
+
+ $flatten = new RecursiveIteratorIterator(
+ $dirFilter,
+ RecursiveIteratorIterator::CHILD_FIRST
+ );
+
+ if ($filter === null) {
+ return $flatten;
+ }
+
+ return $this->filterIterator($flatten, $filter);
+ }
+
+ /**
+ * Wrap iterator in additional filtering iterator.
+ *
+ * @param \Iterator $iterator Iterator
+ * @param mixed $filter Regex string or callback.
+ * @return \Iterator
+ */
+ protected function filterIterator(Iterator $iterator, $filter): Iterator
+ {
+ if (is_string($filter)) {
+ return new RegexIterator($iterator, $filter);
+ }
+
+ return new CallbackFilterIterator($iterator, $filter);
+ }
+
+ /**
+ * Dump contents to file.
+ *
+ * @param string $filename File path.
+ * @param string $content Content to dump.
+ * @return void
+ * @throws \Cake\Core\Exception\Exception When dumping fails.
+ */
+ public function dumpFile(string $filename, string $content): void
+ {
+ $dir = dirname($filename);
+ if (!is_dir($dir)) {
+ $this->mkdir($dir);
+ }
+
+ $exists = file_exists($filename);
+
+ if ($this->isStream($filename)) {
+ // phpcs:ignore
+ $success = @file_put_contents($filename, $content);
+ } else {
+ // phpcs:ignore
+ $success = @file_put_contents($filename, $content, LOCK_EX);
+ }
+
+ if ($success === false) {
+ throw new Exception(sprintf('Failed dumping content to file `%s`', $dir));
+ }
+
+ if (!$exists) {
+ chmod($filename, 0666 & ~umask());
+ }
+ }
+
+ /**
+ * Create directory.
+ *
+ * @param string $dir Directory path.
+ * @param int $mode Octal mode passed to mkdir(). Defaults to 0755.
+ * @return void
+ * @throws \Cake\Core\Exception\Exception When directory creation fails.
+ */
+ public function mkdir(string $dir, int $mode = 0755): void
+ {
+ if (is_dir($dir)) {
+ return;
+ }
+
+ $old = umask(0);
+ // phpcs:ignore
+ if (@mkdir($dir, $mode, true) === false) {
+ umask($old);
+ throw new Exception(sprintf('Failed to create directory "%s"', $dir));
+ }
+
+ umask($old);
+ }
+
+ /**
+ * Delete directory along with all it's contents.
+ *
+ * @param string $path Directory path.
+ * @return bool
+ * @throws \Cake\Core\Exception\Exception If path is not a directory.
+ */
+ public function deleteDir(string $path): bool
+ {
+ if (!file_exists($path)) {
+ return true;
+ }
+
+ if (!is_dir($path)) {
+ throw new Exception(sprintf('"%s" is not a directory', $path));
+ }
+
+ $iterator = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
+ RecursiveIteratorIterator::CHILD_FIRST
+ );
+
+ $result = true;
+ foreach ($iterator as $fileInfo) {
+ if ($fileInfo->getType() === self::TYPE_DIR) {
+ // phpcs:ignore
+ $result = $result && @rmdir($fileInfo->getPathname());
+ continue;
+ }
+
+ // phpcs:ignore
+ $result = $result && @unlink($fileInfo->getPathname());
+ }
+
+ // phpcs:ignore
+ $result = $result && @rmdir($path);
+
+ return $result;
+ }
+
+ /**
+ * Copies directory with all it's contents.
+ *
+ * @param string $source Source path.
+ * @param string $destination Destination path.
+ * @return bool
+ */
+ public function copyDir(string $source, string $destination): bool
+ {
+ $destination = (new SplFileInfo($destination))->getPathname();
+
+ if (!is_dir($destination)) {
+ $this->mkdir($destination);
+ }
+
+ $iterator = new FilesystemIterator($source);
+
+ $result = true;
+ foreach ($iterator as $fileInfo) {
+ if ($fileInfo->isDir()) {
+ $result = $result && $this->copyDir(
+ $fileInfo->getPathname(),
+ $destination . DIRECTORY_SEPARATOR . $fileInfo->getFilename()
+ );
+ } else {
+ // phpcs:ignore
+ $result = $result && @copy(
+ $fileInfo->getPathname(),
+ $destination . DIRECTORY_SEPARATOR . $fileInfo->getFilename()
+ );
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Check whether the given path is a stream path.
+ *
+ * @param string $path Path.
+ * @return bool
+ */
+ public function isStream(string $path): bool
+ {
+ return strpos($path, '://') !== false;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Filesystem/Folder.php b/app/vendor/cakephp/cakephp/src/Filesystem/Folder.php
index 9a81de315..a8cdac495 100644
--- a/app/vendor/cakephp/cakephp/src/Filesystem/Folder.php
+++ b/app/vendor/cakephp/cakephp/src/Filesystem/Folder.php
@@ -1,4 +1,6 @@
path;
}
@@ -170,7 +173,7 @@ public function pwd()
* @param string $path Path to the directory to change to
* @return string|false The new path. Returns false on failure
*/
- public function cd($path)
+ public function cd(string $path)
{
$path = $this->realpath($path);
if ($path !== false && is_dir($path)) {
@@ -190,7 +193,7 @@ public function cd($path)
* @param bool $fullPath True returns the full path
* @return array Contents of current directory as an array, an empty array on failure
*/
- public function read($sort = self::SORT_NAME, $exceptions = false, $fullPath = false)
+ public function read($sort = self::SORT_NAME, $exceptions = false, bool $fullPath = false): array
{
$dirs = $files = [];
@@ -253,12 +256,12 @@ public function read($sort = self::SORT_NAME, $exceptions = false, $fullPath = f
* Returns an array of all matching files in current directory.
*
* @param string $regexpPattern Preg_match pattern (Defaults to: .*)
- * @param bool $sort Whether results should be sorted.
+ * @param string|bool $sort Whether results should be sorted.
* @return array Files that match given pattern
*/
- public function find($regexpPattern = '.*', $sort = false)
+ public function find(string $regexpPattern = '.*', $sort = false): array
{
- list(, $files) = $this->read($sort);
+ [, $files] = $this->read($sort);
return array_values(preg_grep('/^' . $regexpPattern . '$/i', $files));
}
@@ -267,10 +270,10 @@ public function find($regexpPattern = '.*', $sort = false)
* Returns an array of all matching files in and below current directory.
*
* @param string $pattern Preg_match pattern (Defaults to: .*)
- * @param bool $sort Whether results should be sorted.
+ * @param string|bool $sort Whether results should be sorted.
* @return array Files matching $pattern
*/
- public function findRecursive($pattern = '.*', $sort = false)
+ public function findRecursive(string $pattern = '.*', $sort = false): array
{
if (!$this->pwd()) {
return [];
@@ -289,9 +292,9 @@ public function findRecursive($pattern = '.*', $sort = false)
* @param bool $sort Whether results should be sorted.
* @return array Files matching pattern
*/
- protected function _findRecursive($pattern, $sort = false)
+ protected function _findRecursive(string $pattern, bool $sort = false): array
{
- list($dirs, $files) = $this->read($sort);
+ [$dirs, $files] = $this->read($sort);
$found = [];
foreach ($files as $file) {
@@ -315,9 +318,9 @@ protected function _findRecursive($pattern, $sort = false)
* @param string $path Path to check
* @return bool true if windows path, false otherwise
*/
- public static function isWindowsPath($path)
+ public static function isWindowsPath(string $path): bool
{
- return (preg_match('/^[A-Z]:\\\\/i', $path) || substr($path, 0, 2) === '\\\\');
+ return preg_match('/^[A-Z]:\\\\/i', $path) || substr($path, 0, 2) === '\\\\';
}
/**
@@ -326,7 +329,7 @@ public static function isWindowsPath($path)
* @param string $path Path to check
* @return bool true if path is absolute.
*/
- public static function isAbsolute($path)
+ public static function isAbsolute(string $path): bool
{
if (empty($path)) {
return false;
@@ -344,24 +347,10 @@ public static function isAbsolute($path)
* @param string $path Path to check
* @return bool True if path is registered stream wrapper.
*/
- public static function isRegisteredStreamWrapper($path)
+ public static function isRegisteredStreamWrapper(string $path): bool
{
return preg_match('/^[^:\/\/]+?(?=:\/\/)/', $path, $matches) &&
- in_array($matches[0], stream_get_wrappers());
- }
-
- /**
- * Returns a correct set of slashes for given $path. (\\ for Windows paths and / for other paths.)
- *
- * @param string $path Path to check
- * @return string Set of slashes ("\\" or "/")
- * @deprecated 3.7.0 This method will be removed in 4.0.0. Use correctSlashFor() instead.
- */
- public static function normalizePath($path)
- {
- deprecationWarning('Folder::normalizePath() is deprecated. Use Folder::correctSlashFor() instead.');
-
- return Folder::correctSlashFor($path);
+ in_array($matches[0], stream_get_wrappers(), true);
}
/**
@@ -370,10 +359,10 @@ public static function normalizePath($path)
* @param string $path Path to transform
* @return string Path with the correct set of slashes ("\\" or "/")
*/
- public static function normalizeFullPath($path)
+ public static function normalizeFullPath(string $path): string
{
$to = Folder::correctSlashFor($path);
- $from = ($to == '/' ? '\\' : '/');
+ $from = ($to === '/' ? '\\' : '/');
return str_replace($from, $to, $path);
}
@@ -384,7 +373,7 @@ public static function normalizeFullPath($path)
* @param string $path Path to check
* @return string Set of slashes ("\\" or "/")
*/
- public static function correctSlashFor($path)
+ public static function correctSlashFor(string $path): string
{
return Folder::isWindowsPath($path) ? '\\' : '/';
}
@@ -395,7 +384,7 @@ public static function correctSlashFor($path)
* @param string $path Path to check
* @return string Path with ending slash
*/
- public static function slashTerm($path)
+ public static function slashTerm(string $path): string
{
if (Folder::isSlashTerm($path)) {
return $path;
@@ -411,7 +400,7 @@ public static function slashTerm($path)
* @param string|array $element Element to add at end of path
* @return string Combined path
*/
- public static function addPathElement($path, $element)
+ public static function addPathElement(string $path, $element): string
{
$element = (array)$element;
array_unshift($element, rtrim($path, DIRECTORY_SEPARATOR));
@@ -419,22 +408,6 @@ public static function addPathElement($path, $element)
return implode(DIRECTORY_SEPARATOR, $element);
}
- /**
- * Returns true if the Folder is in the given Cake path.
- *
- * @param string $path The path to check.
- * @return bool
- * @deprecated 3.2.12 This method will be removed in 4.0.0. Use inPath() instead.
- */
- public function inCakePath($path = '')
- {
- deprecationWarning('Folder::inCakePath() is deprecated. Use Folder::inPath() instead.');
- $dir = substr(Folder::slashTerm(ROOT), 0, -1);
- $newdir = $dir . $path;
-
- return $this->inPath($newdir);
- }
-
/**
* Returns true if the Folder is in the given path.
*
@@ -443,7 +416,7 @@ public function inCakePath($path = '')
* @return bool
* @throws \InvalidArgumentException When the given `$path` argument is not an absolute path.
*/
- public function inPath($path, $reverse = false)
+ public function inPath(string $path, bool $reverse = false): bool
{
if (!Folder::isAbsolute($path)) {
throw new InvalidArgumentException('The $path argument is expected to be an absolute path.');
@@ -465,21 +438,21 @@ public function inPath($path, $reverse = false)
* Change the mode on a directory structure recursively. This includes changing the mode on files as well.
*
* @param string $path The path to chmod.
- * @param int|bool $mode Octal value, e.g. 0755.
+ * @param int|null $mode Octal value, e.g. 0755.
* @param bool $recursive Chmod recursively, set to false to only change the current directory.
- * @param array $exceptions Array of files, directories to skip.
+ * @param string[] $exceptions Array of files, directories to skip.
* @return bool Success.
*/
- public function chmod($path, $mode = false, $recursive = true, array $exceptions = [])
+ public function chmod(string $path, ?int $mode = null, bool $recursive = true, array $exceptions = []): bool
{
if (!$mode) {
$mode = $this->mode;
}
if ($recursive === false && is_dir($path)) {
- //@codingStandardsIgnoreStart
+ // phpcs:disable
if (@chmod($path, intval($mode, 8))) {
- //@codingStandardsIgnoreEnd
+ // phpcs:enable
$this->_messages[] = sprintf('%s changed to %s', $path, $mode);
return true;
@@ -498,13 +471,13 @@ public function chmod($path, $mode = false, $recursive = true, array $exceptions
$check = explode(DIRECTORY_SEPARATOR, $fullpath);
$count = count($check);
- if (in_array($check[$count - 1], $exceptions)) {
+ if (in_array($check[$count - 1], $exceptions, true)) {
continue;
}
- //@codingStandardsIgnoreStart
+ // phpcs:disable
if (@chmod($fullpath, intval($mode, 8))) {
- //@codingStandardsIgnoreEnd
+ // phpcs:enable
$this->_messages[] = sprintf('%s changed to %s', $fullpath, $mode);
} else {
$this->_errors[] = sprintf('%s NOT changed to %s', $fullpath, $mode);
@@ -527,7 +500,7 @@ public function chmod($path, $mode = false, $recursive = true, array $exceptions
* @param bool $fullPath Whether to return the full path or only the directory name.
* @return array Array of subdirectories for the provided or current path.
*/
- public function subdirectories($path = null, $fullPath = true)
+ public function subdirectories(?string $path = null, bool $fullPath = true): array
{
if (!$path) {
$path = $this->path;
@@ -559,7 +532,7 @@ public function subdirectories($path = null, $fullPath = true)
* @param string|null $type either 'file' or 'dir'. Null returns both files and directories
* @return array Array of nested directories and files in each directory
*/
- public function tree($path = null, $exceptions = false, $type = null)
+ public function tree(?string $path = null, $exceptions = false, ?string $type = null): array
{
if (!$path) {
$path = $this->path;
@@ -579,11 +552,12 @@ public function tree($path = null, $exceptions = false, $type = null)
}
try {
- $directory = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME | RecursiveDirectoryIterator::CURRENT_AS_SELF);
+ $directory = new RecursiveDirectoryIterator(
+ $path,
+ RecursiveDirectoryIterator::KEY_AS_PATHNAME | RecursiveDirectoryIterator::CURRENT_AS_SELF
+ );
$iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
} catch (Exception $e) {
- unset($directory, $iterator);
-
if ($type === null) {
return [[], []];
}
@@ -599,14 +573,12 @@ public function tree($path = null, $exceptions = false, $type = null)
if ($skipHidden) {
$subPathName = $fsIterator->getSubPathname();
if ($subPathName[0] === '.' || strpos($subPathName, DIRECTORY_SEPARATOR . '.') !== false) {
- unset($fsIterator);
continue;
}
}
/** @var \FilesystemIterator $item */
$item = $fsIterator->current();
if (!empty($exceptions) && isset($exceptions[$item->getFilename()])) {
- unset($fsIterator, $item);
continue;
}
@@ -615,15 +587,7 @@ public function tree($path = null, $exceptions = false, $type = null)
} elseif ($item->isDir() && !$item->isDot()) {
$directories[] = $itemPath;
}
-
- // inner iterators need to be unset too in order for locks on parents to be released
- unset($fsIterator, $item);
}
-
- // unsetting iterators helps releasing possible locks in certain environments,
- // which could otherwise make `rmdir()` fail
- unset($directory, $iterator);
-
if ($type === null) {
return [$directories, $files];
}
@@ -642,10 +606,10 @@ public function tree($path = null, $exceptions = false, $type = null)
* @param string $pathname The directory structure to create. Either an absolute or relative
* path. If the path is relative and exists in the process' cwd it will not be created.
* Otherwise relative paths will be prefixed with the current pwd().
- * @param int|bool $mode octal value 0755
+ * @param int|null $mode octal value 0755
* @return bool Returns TRUE on success, FALSE on failure
*/
- public function create($pathname, $mode = false)
+ public function create(string $pathname, ?int $mode = null): bool
{
if (is_dir($pathname) || empty($pathname)) {
return true;
@@ -691,7 +655,7 @@ public function create($pathname, $mode = false)
*
* @return int size in bytes of current folder
*/
- public function dirsize()
+ public function dirsize(): int
{
$size = 0;
$directory = Folder::slashTerm($this->path);
@@ -729,7 +693,7 @@ public function dirsize()
* @param string|null $path Path of directory to delete
* @return bool Success
*/
- public function delete($path = null)
+ public function delete(?string $path = null): bool
{
if (!$path) {
$path = $this->pwd();
@@ -743,47 +707,36 @@ public function delete($path = null)
$directory = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::CURRENT_AS_SELF);
$iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::CHILD_FIRST);
} catch (Exception $e) {
- unset($directory, $iterator);
-
return false;
}
foreach ($iterator as $item) {
$filePath = $item->getPathname();
if ($item->isFile() || $item->isLink()) {
- //@codingStandardsIgnoreStart
+ // phpcs:disable
if (@unlink($filePath)) {
- //@codingStandardsIgnoreEnd
+ // phpcs:enable
$this->_messages[] = sprintf('%s removed', $filePath);
} else {
$this->_errors[] = sprintf('%s NOT removed', $filePath);
}
} elseif ($item->isDir() && !$item->isDot()) {
- //@codingStandardsIgnoreStart
+ // phpcs:disable
if (@rmdir($filePath)) {
- //@codingStandardsIgnoreEnd
+ // phpcs:enable
$this->_messages[] = sprintf('%s removed', $filePath);
} else {
$this->_errors[] = sprintf('%s NOT removed', $filePath);
- unset($directory, $iterator, $item);
-
return false;
}
}
-
- // inner iterators need to be unset too in order for locks on parents to be released
- unset($item);
}
- // unsetting iterators helps releasing possible locks in certain environments,
- // which could otherwise make `rmdir()` fail
- unset($directory, $iterator);
-
$path = rtrim($path, DIRECTORY_SEPARATOR);
- //@codingStandardsIgnoreStart
+ // phpcs:disable
if (@rmdir($path)) {
- //@codingStandardsIgnoreEnd
+ // phpcs:enable
$this->_messages[] = sprintf('%s removed', $path);
} else {
$this->_errors[] = sprintf('%s NOT removed', $path);
@@ -800,28 +753,22 @@ public function delete($path = null)
*
* ### Options
*
- * - `to` The directory to copy to.
* - `from` The directory to copy from, this will cause a cd() to occur, changing the results of pwd().
* - `mode` The mode to copy the files/directories with as integer, e.g. 0775.
* - `skip` Files/directories to skip.
* - `scheme` Folder::MERGE, Folder::OVERWRITE, Folder::SKIP
* - `recursive` Whether to copy recursively or not (default: true - recursive)
*
- * @param array|string $options Either an array of options (see above) or a string of the destination directory.
+ * @param string $to The directory to copy to.
+ * @param array $options Array of options (see above).
* @return bool Success.
*/
- public function copy($options)
+ public function copy(string $to, array $options = []): bool
{
if (!$this->pwd()) {
return false;
}
- $to = null;
- if (is_string($options)) {
- $to = $options;
- $options = [];
- }
$options += [
- 'to' => $to,
'from' => $this->path,
'mode' => $this->mode,
'skip' => [],
@@ -830,7 +777,7 @@ public function copy($options)
];
$fromDir = $options['from'];
- $toDir = $options['to'];
+ $toDir = $to;
$mode = $options['mode'];
if (!$this->cd($fromDir)) {
@@ -850,14 +797,14 @@ public function copy($options)
}
$exceptions = array_merge(['.', '..', '.svn'], $options['skip']);
- //@codingStandardsIgnoreStart
+ // phpcs:disable
if ($handle = @opendir($fromDir)) {
- //@codingStandardsIgnoreEnd
+ // phpcs:enable
while (($item = readdir($handle)) !== false) {
$to = Folder::addPathElement($toDir, $item);
- if (($options['scheme'] != Folder::SKIP || !is_dir($to)) && !in_array($item, $exceptions)) {
+ if (($options['scheme'] !== Folder::SKIP || !is_dir($to)) && !in_array($item, $exceptions, true)) {
$from = Folder::addPathElement($fromDir, $item);
- if (is_file($from) && (!is_file($to) || $options['scheme'] != Folder::SKIP)) {
+ if (is_file($from) && (!is_file($to) || $options['scheme'] !== Folder::SKIP)) {
if (copy($from, $to)) {
chmod($to, intval($mode, 8));
touch($to, filemtime($from));
@@ -883,14 +830,14 @@ public function copy($options)
chmod($to, $mode);
umask($old);
$this->_messages[] = sprintf('%s created', $to);
- $options = ['to' => $to, 'from' => $from] + $options;
- $this->copy($options);
+ $options = ['from' => $from] + $options;
+ $this->copy($to, $options);
} else {
$this->_errors[] = sprintf('%s not created', $to);
}
} elseif (is_dir($from) && $options['scheme'] === Folder::MERGE) {
- $options = ['to' => $to, 'from' => $from] + $options;
- $this->copy($options);
+ $options = ['from' => $from] + $options;
+ $this->copy($to, $options);
}
}
}
@@ -907,27 +854,22 @@ public function copy($options)
*
* ### Options
*
- * - `to` The directory to copy to.
* - `from` The directory to copy from, this will cause a cd() to occur, changing the results of pwd().
- * - `chmod` The mode to copy the files/directories with.
+ * - `mode` The mode to copy the files/directories with as integer, e.g. 0775.
* - `skip` Files/directories to skip.
* - `scheme` Folder::MERGE, Folder::OVERWRITE, Folder::SKIP
* - `recursive` Whether to copy recursively or not (default: true - recursive)
*
- * @param array|string $options (to, from, chmod, skip, scheme)
+ * @param string $to The directory to move to.
+ * @param array $options Array of options (see above).
* @return bool Success
*/
- public function move($options)
+ public function move(string $to, array $options = []): bool
{
- $to = null;
- if (is_string($options)) {
- $to = $options;
- $options = (array)$options;
- }
- $options += ['to' => $to, 'from' => $this->path, 'mode' => $this->mode, 'skip' => [], 'recursive' => true];
+ $options += ['from' => $this->path, 'mode' => $this->mode, 'skip' => [], 'recursive' => true];
- if ($this->copy($options) && $this->delete($options['from'])) {
- return (bool)$this->cd($options['to']);
+ if ($this->copy($to, $options) && $this->delete($options['from'])) {
+ return (bool)$this->cd($to);
}
return false;
@@ -939,7 +881,7 @@ public function move($options)
* @param bool $reset Reset message stack after reading
* @return array
*/
- public function messages($reset = true)
+ public function messages(bool $reset = true): array
{
$messages = $this->_messages;
if ($reset) {
@@ -955,7 +897,7 @@ public function messages($reset = true)
* @param bool $reset Reset error stack after reading
* @return array
*/
- public function errors($reset = true)
+ public function errors(bool $reset = true): array
{
$errors = $this->_errors;
if ($reset) {
@@ -1013,7 +955,7 @@ public function realpath($path)
* @param string $path Path to check
* @return bool true if path ends with slash, false otherwise
*/
- public static function isSlashTerm($path)
+ public static function isSlashTerm(string $path): bool
{
$lastChar = $path[strlen($path) - 1];
diff --git a/app/vendor/cakephp/cakephp/src/Filesystem/LICENSE.txt b/app/vendor/cakephp/cakephp/src/Filesystem/LICENSE.txt
index 0c4b7932c..0b3b94303 100644
--- a/app/vendor/cakephp/cakephp/src/Filesystem/LICENSE.txt
+++ b/app/vendor/cakephp/cakephp/src/Filesystem/LICENSE.txt
@@ -1,7 +1,7 @@
The MIT License (MIT)
CakePHP(tm) : The Rapid Development PHP Framework (https://cakephp.org)
-Copyright (c) 2005-2016, Cake Software Foundation, Inc. (https://cakefoundation.org)
+Copyright (c) 2005-2019, Cake Software Foundation, Inc. (https://cakefoundation.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/vendor/cakephp/cakephp/src/Filesystem/README.md b/app/vendor/cakephp/cakephp/src/Filesystem/README.md
index 74ec083ea..df1862ebb 100644
--- a/app/vendor/cakephp/cakephp/src/Filesystem/README.md
+++ b/app/vendor/cakephp/cakephp/src/Filesystem/README.md
@@ -1,19 +1,21 @@
[](https://packagist.org/packages/cakephp/filesystem)
[](LICENSE.txt)
-# CakePHP Filesystem Library
+# This package is deprecated.
+
+## CakePHP Filesystem Library
The Folder and File utilities are convenience classes to help you read from and write/append to files; list files within a folder and other common directory related tasks.
## Basic Usage
-Create a folder instance and search for all the `.ctp` files within it:
+Create a folder instance and search for all the `.php` files within it:
```php
use Cake\Filesystem\Folder;
$dir = new Folder('/path/to/folder');
-$files = $dir->find('.*\.ctp');
+$files = $dir->find('.*\.php');
```
Now you can loop through the files and read from or write/append to the contents or simply delete the file:
@@ -32,4 +34,4 @@ foreach ($files as $file) {
## Documentation
Please make sure you check the [official
-documentation](https://book.cakephp.org/3/en/core-libraries/file-folder.html)
+documentation](https://book.cakephp.org/4/en/core-libraries/file-folder.html)
diff --git a/app/vendor/cakephp/cakephp/src/Filesystem/composer.json b/app/vendor/cakephp/cakephp/src/Filesystem/composer.json
index 62dc4ffec..edaffd5b6 100644
--- a/app/vendor/cakephp/cakephp/src/Filesystem/composer.json
+++ b/app/vendor/cakephp/cakephp/src/Filesystem/composer.json
@@ -23,8 +23,8 @@
"source": "https://github.com/cakephp/filesystem"
},
"require": {
- "php": ">=5.6.0,<8.0.0",
- "cakephp/core": "^3.6.0"
+ "php": ">=7.2.0",
+ "cakephp/core": "^4.0"
},
"autoload": {
"psr-4": {
diff --git a/app/vendor/cakephp/cakephp/src/Form/Form.php b/app/vendor/cakephp/cakephp/src/Form/Form.php
index bbff3c653..530651b5e 100644
--- a/app/vendor/cakephp/cakephp/src/Form/Form.php
+++ b/app/vendor/cakephp/cakephp/src/Form/Form.php
@@ -1,4 +1,6 @@
schema()` and `$form->validator()`.
- *
* Forms are conventionally placed in the `App\Form` namespace.
*/
class Form implements EventListenerInterface, EventDispatcherInterface, ValidatorAwareInterface
@@ -48,24 +43,32 @@ class Form implements EventListenerInterface, EventDispatcherInterface, Validato
use EventDispatcherTrait;
use ValidatorAwareTrait;
+ /**
+ * Name of default validation set.
+ *
+ * @var string
+ */
+ public const DEFAULT_VALIDATOR = 'default';
+
/**
* The alias this object is assigned to validators as.
*
* @var string
*/
- const VALIDATOR_PROVIDER_NAME = 'form';
+ public const VALIDATOR_PROVIDER_NAME = 'form';
/**
* The name of the event dispatched when a validator has been built.
*
* @var string
*/
- const BUILD_VALIDATOR_EVENT = 'Form.buildValidator';
+ public const BUILD_VALIDATOR_EVENT = 'Form.buildValidator';
/**
* Schema class.
*
* @var string
+ * @psalm-var class-string<\Cake\Form\Schema>
*/
protected $_schemaClass = Schema::class;
@@ -83,18 +86,10 @@ class Form implements EventListenerInterface, EventDispatcherInterface, Validato
*/
protected $_errors = [];
- /**
- * The validator used by this form.
- *
- * @var \Cake\Validation\Validator
- */
- protected $_validator;
-
/**
* Form's data.
*
* @var array
- * @since 3.7.0
*/
protected $_data = [];
@@ -104,13 +99,21 @@ class Form implements EventListenerInterface, EventDispatcherInterface, Validato
* @param \Cake\Event\EventManager|null $eventManager The event manager.
* Defaults to a new instance.
*/
- public function __construct(EventManager $eventManager = null)
+ public function __construct(?EventManager $eventManager = null)
{
if ($eventManager !== null) {
$this->setEventManager($eventManager);
}
$this->getEventManager()->on($this);
+
+ if (method_exists($this, '_buildValidator')) {
+ deprecationWarning(
+ static::class . ' implements `_buildValidator` which is no longer used. ' .
+ 'You should implement `buildValidator(Validator $validator, string $name): void` ' .
+ 'or `validationDefault(Validator $validator): Validator` instead.'
+ );
+ }
}
/**
@@ -122,11 +125,15 @@ public function __construct(EventManager $eventManager = null)
*
* @return array
*/
- public function implementedEvents()
+ public function implementedEvents(): array
{
- return [
- 'Form.buildValidator' => 'buildValidator',
- ];
+ if (method_exists($this, 'buildValidator')) {
+ return [
+ self::BUILD_VALIDATOR_EVENT => 'buildValidator',
+ ];
+ }
+
+ return [];
}
/**
@@ -139,7 +146,7 @@ public function implementedEvents()
* @param \Cake\Form\Schema|null $schema The schema to set, or null.
* @return \Cake\Form\Schema the schema instance.
*/
- public function schema(Schema $schema = null)
+ public function schema(?Schema $schema = null): Schema
{
if ($schema === null && empty($this->_schema)) {
$schema = $this->_buildSchema(new $this->_schemaClass());
@@ -161,108 +168,25 @@ public function schema(Schema $schema = null)
* @param \Cake\Form\Schema $schema The schema to customize.
* @return \Cake\Form\Schema The schema to use.
*/
- protected function _buildSchema(Schema $schema)
+ protected function _buildSchema(Schema $schema): Schema
{
return $schema;
}
- /**
- * Get/Set the validator for this form.
- *
- * This method will call `_buildValidator()` when the validator
- * is first built. This hook method lets you configure the
- * validator or load a pre-defined one.
- *
- * @param \Cake\Validation\Validator|null $validator The validator to set, or null.
- * @return \Cake\Validation\Validator the validator instance.
- * @deprecated 3.6.0 Use Form::getValidator()/setValidator() instead.
- */
- public function validator(Validator $validator = null)
- {
- deprecationWarning(
- 'Form::validator() is deprecated. ' .
- 'Use Form::getValidator()/setValidator() instead.'
- );
-
- if ($validator === null && empty($this->_validator)) {
- $validator = $this->_buildValidator(new $this->_validatorClass());
- }
- if ($validator) {
- $this->_validator = $validator;
- $this->setValidator('default', $validator);
- }
-
- return $this->getValidator();
- }
-
- /**
- * A hook method intended to be implemented by subclasses.
- *
- * You can use this method to define the validator using
- * the methods on Cake\Validation\Validator or loads a pre-defined
- * validator from a concrete class.
- *
- * @param \Cake\Validation\Validator $validator The validator to customize.
- * @return \Cake\Validation\Validator The validator to use.
- * @deprecated 3.6.0 Use Form::getValidator()/setValidator() and buildValidator() instead.
- */
- protected function _buildValidator(Validator $validator)
- {
- return $validator;
- }
-
- /**
- * Callback method for Form.buildValidator event.
- *
- * @param \Cake\Event\Event $event The Form.buildValidator event instance.
- * @param \Cake\Validation\Validator $validator The validator to customize.
- * @param string $name Validator name
- * @return void
- */
- public function buildValidator(Event $event, Validator $validator, $name)
- {
- $this->_buildValidator($validator);
- }
-
/**
* Used to check if $data passes this form's validation.
*
* @param array $data The data to check.
* @return bool Whether or not the data is valid.
*/
- public function validate(array $data)
+ public function validate(array $data): bool
{
$validator = $this->getValidator();
- if (!$validator->count()) {
- $method = new ReflectionMethod($this, 'validator');
- if ($method->getDeclaringClass()->getName() !== __CLASS__) {
- $validator = $this->validator();
- }
- }
$this->_errors = $validator->validate($data);
return count($this->_errors) === 0;
}
- /**
- * Get the errors in the form
- *
- * Will return the errors from the last call
- * to `validate()` or `execute()`.
- *
- * @return array Last set validation errors.
- * @deprecated 3.7.0 Use Form::getErrors() instead.
- */
- public function errors()
- {
- deprecationWarning(
- 'Form::errors() is deprecated. ' .
- 'Use Form::getErrors() instead.'
- );
-
- return $this->getErrors();
- }
-
/**
* Get the errors in the form
*
@@ -271,7 +195,7 @@ public function errors()
*
* @return array Last set validation errors.
*/
- public function getErrors()
+ public function getErrors(): array
{
return $this->_errors;
}
@@ -287,7 +211,6 @@ public function getErrors()
* $form->setErrors($errors);
* ```
*
- * @since 3.5.1
* @param array $errors Errors list.
* @return $this
*/
@@ -310,7 +233,7 @@ public function setErrors(array $errors)
* @return bool False on validation failure, otherwise returns the
* result of the `_execute()` method.
*/
- public function execute(array $data)
+ public function execute(array $data): bool
{
if (!$this->validate($data)) {
return false;
@@ -327,7 +250,7 @@ public function execute(array $data)
* @param array $data Form data.
* @return bool
*/
- protected function _execute(array $data)
+ protected function _execute(array $data): bool
{
return true;
}
@@ -338,9 +261,8 @@ protected function _execute(array $data)
* @param string|null $field The field name or null to get data array with
* all fields.
* @return mixed
- * @since 3.7.0
*/
- public function getData($field = null)
+ public function getData(?string $field = null)
{
if ($field === null) {
return $this->_data;
@@ -354,7 +276,6 @@ public function getData($field = null)
*
* @param array $data Data array.
* @return $this
- * @since 3.7.0
*/
public function setData(array $data)
{
@@ -368,7 +289,7 @@ public function setData(array $data)
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$special = [
'_schema' => $this->schema()->__debugInfo(),
diff --git a/app/vendor/cakephp/cakephp/src/Form/FormProtector.php b/app/vendor/cakephp/cakephp/src/Form/FormProtector.php
new file mode 100644
index 000000000..e981f096d
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Form/FormProtector.php
@@ -0,0 +1,591 @@
+unlockedFields = $data['unlockedFields'];
+ }
+ }
+
+ /**
+ * Validate submitted form data.
+ *
+ * @param mixed $formData Form data.
+ * @param string $url URL form was POSTed to.
+ * @param string $sessionId Session id for hash generation.
+ * @return bool
+ */
+ public function validate($formData, string $url, string $sessionId): bool
+ {
+ $this->debugMessage = null;
+
+ $extractedToken = $this->extractToken($formData);
+ if (empty($extractedToken)) {
+ return false;
+ }
+
+ $hashParts = $this->extractHashParts($formData);
+ $generatedToken = $this->generateHash(
+ $hashParts['fields'],
+ $hashParts['unlockedFields'],
+ $url,
+ $sessionId
+ );
+
+ if (hash_equals($generatedToken, $extractedToken)) {
+ return true;
+ }
+
+ if (Configure::read('debug')) {
+ $debugMessage = $this->debugTokenNotMatching($formData, $hashParts + compact('url', 'sessionId'));
+ if ($debugMessage) {
+ $this->debugMessage = $debugMessage;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine which fields of a form should be used for hash.
+ *
+ * @param string|array $field Reference to field to be secured. Can be dot
+ * separated string to indicate nesting or array of fieldname parts.
+ * @param bool $lock Whether this field should be part of the validation
+ * or excluded as part of the unlockedFields. Default `true`.
+ * @param mixed $value Field value, if value should not be tampered with.
+ * @return $this
+ */
+ public function addField($field, bool $lock = true, $value = null)
+ {
+ if (is_string($field)) {
+ $field = $this->getFieldNameArray($field);
+ }
+
+ if (empty($field)) {
+ return $this;
+ }
+
+ foreach ($this->unlockedFields as $unlockField) {
+ $unlockParts = explode('.', $unlockField);
+ if (array_values(array_intersect($field, $unlockParts)) === $unlockParts) {
+ return $this;
+ }
+ }
+
+ $field = implode('.', $field);
+ $field = preg_replace('/(\.\d+)+$/', '', $field);
+
+ if ($lock) {
+ if (!in_array($field, $this->fields, true)) {
+ if ($value !== null) {
+ $this->fields[$field] = $value;
+
+ return $this;
+ }
+ if (isset($this->fields[$field])) {
+ unset($this->fields[$field]);
+ }
+ $this->fields[] = $field;
+ }
+ } else {
+ $this->unlockField($field);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Parses the field name to create a dot separated name value for use in
+ * field hash. If fieldname is of form Model[field] or Model.field an array of
+ * fieldname parts like ['Model', 'field'] is returned.
+ *
+ * @param string $name The form inputs name attribute.
+ * @return string[] Array of field name params like ['Model.field'] or
+ * ['Model', 'field'] for array fields or empty array if $name is empty.
+ */
+ protected function getFieldNameArray(string $name): array
+ {
+ if (empty($name) && $name !== '0') {
+ return [];
+ }
+
+ if (strpos($name, '[') === false) {
+ return Hash::filter(explode('.', $name));
+ }
+ $parts = explode('[', $name);
+ $parts = array_map(function ($el) {
+ return trim($el, ']');
+ }, $parts);
+
+ return Hash::filter($parts, 'strlen');
+ }
+
+ /**
+ * Add to the list of fields that are currently unlocked.
+ *
+ * Unlocked fields are not included in the field hash.
+ *
+ * @param string $name The dot separated name for the field.
+ * @return $this
+ */
+ public function unlockField($name)
+ {
+ if (!in_array($name, $this->unlockedFields, true)) {
+ $this->unlockedFields[] = $name;
+ }
+
+ $index = array_search($name, $this->fields, true);
+ if ($index !== false) {
+ unset($this->fields[$index]);
+ }
+ unset($this->fields[$name]);
+
+ return $this;
+ }
+
+ /**
+ * Get validation error message.
+ *
+ * @return string|null
+ */
+ public function getError(): ?string
+ {
+ return $this->debugMessage;
+ }
+
+ /**
+ * Extract token from data.
+ *
+ * @param mixed $formData Data to validate.
+ * @return string|null Fields token on success, null on failure.
+ */
+ protected function extractToken($formData): ?string
+ {
+ if (!is_array($formData)) {
+ $this->debugMessage = 'Request data is not an array.';
+
+ return null;
+ }
+
+ $message = '`%s` was not found in request data.';
+ if (!isset($formData['_Token'])) {
+ $this->debugMessage = sprintf($message, '_Token');
+
+ return null;
+ }
+ if (!isset($formData['_Token']['fields'])) {
+ $this->debugMessage = sprintf($message, '_Token.fields');
+
+ return null;
+ }
+ if (!is_string($formData['_Token']['fields'])) {
+ $this->debugMessage = '`_Token.fields` is invalid.';
+
+ return null;
+ }
+ if (!isset($formData['_Token']['unlocked'])) {
+ $this->debugMessage = sprintf($message, '_Token.unlocked');
+
+ return null;
+ }
+ if (Configure::read('debug') && !isset($formData['_Token']['debug'])) {
+ $this->debugMessage = sprintf($message, '_Token.debug');
+
+ return null;
+ }
+ if (!Configure::read('debug') && isset($formData['_Token']['debug'])) {
+ $this->debugMessage = 'Unexpected `_Token.debug` found in request data';
+
+ return null;
+ }
+
+ $token = urldecode($formData['_Token']['fields']);
+ if (strpos($token, ':')) {
+ [$token, ] = explode(':', $token, 2);
+ }
+
+ return $token;
+ }
+
+ /**
+ * Return hash parts for the token generation
+ *
+ * @param array $formData Form data.
+ * @return array
+ * @psalm-return array{fields: array, unlockedFields: array}
+ */
+ protected function extractHashParts(array $formData): array
+ {
+ $fields = $this->extractFields($formData);
+ $unlockedFields = $this->sortedUnlockedFields($formData);
+
+ return [
+ 'fields' => $fields,
+ 'unlockedFields' => $unlockedFields,
+ ];
+ }
+
+ /**
+ * Return the fields list for the hash calculation
+ *
+ * @param array $formData Data array
+ * @return array
+ */
+ protected function extractFields(array $formData): array
+ {
+ $locked = '';
+ $token = urldecode($formData['_Token']['fields']);
+ $unlocked = urldecode($formData['_Token']['unlocked']);
+
+ if (strpos($token, ':')) {
+ [, $locked] = explode(':', $token, 2);
+ }
+ unset($formData['_Token']);
+
+ $locked = $locked ? explode('|', $locked) : [];
+ $unlocked = $unlocked ? explode('|', $unlocked) : [];
+
+ $fields = Hash::flatten($formData);
+ $fieldList = array_keys($fields);
+ $multi = $lockedFields = [];
+ $isUnlocked = false;
+
+ foreach ($fieldList as $i => $key) {
+ if (is_string($key) && preg_match('/(\.\d+){1,10}$/', $key)) {
+ $multi[$i] = preg_replace('/(\.\d+){1,10}$/', '', $key);
+ unset($fieldList[$i]);
+ } else {
+ $fieldList[$i] = (string)$key;
+ }
+ }
+ if (!empty($multi)) {
+ $fieldList += array_unique($multi);
+ }
+
+ $unlockedFields = array_unique(
+ array_merge(
+ $this->unlockedFields,
+ $unlocked
+ )
+ );
+
+ foreach ($fieldList as $i => $key) {
+ $isLocked = in_array($key, $locked, true);
+
+ if (!empty($unlockedFields)) {
+ foreach ($unlockedFields as $off) {
+ $off = explode('.', $off);
+ $field = array_values(array_intersect(explode('.', $key), $off));
+ $isUnlocked = ($field === $off);
+ if ($isUnlocked) {
+ break;
+ }
+ }
+ }
+
+ if ($isUnlocked || $isLocked) {
+ unset($fieldList[$i]);
+ if ($isLocked) {
+ $lockedFields[$key] = $fields[$key];
+ }
+ }
+ }
+ sort($fieldList, SORT_STRING);
+ ksort($lockedFields, SORT_STRING);
+ $fieldList += $lockedFields;
+
+ return $fieldList;
+ }
+
+ /**
+ * Get the sorted unlocked string
+ *
+ * @param array $formData Data array
+ * @return string[]
+ */
+ protected function sortedUnlockedFields(array $formData): array
+ {
+ $unlocked = urldecode($formData['_Token']['unlocked']);
+ if (empty($unlocked)) {
+ return [];
+ }
+
+ $unlocked = explode('|', $unlocked);
+ sort($unlocked, SORT_STRING);
+
+ return $unlocked;
+ }
+
+ /**
+ * Generate the token data.
+ *
+ * @param string $url Form URL.
+ * @param string $sessionId Session Id.
+ * @return array The token data.
+ * @psalm-return array{fields: string, unlocked: string, debug: string}
+ */
+ public function buildTokenData(string $url = '', string $sessionId = ''): array
+ {
+ $fields = $this->fields;
+ $unlockedFields = $this->unlockedFields;
+
+ $locked = [];
+ foreach ($fields as $key => $value) {
+ if (is_numeric($value)) {
+ $value = (string)$value;
+ }
+ if (!is_int($key)) {
+ $locked[$key] = $value;
+ unset($fields[$key]);
+ }
+ }
+
+ sort($unlockedFields, SORT_STRING);
+ sort($fields, SORT_STRING);
+ ksort($locked, SORT_STRING);
+ $fields += $locked;
+
+ $fields = $this->generateHash($fields, $unlockedFields, $url, $sessionId);
+ $locked = implode('|', array_keys($locked));
+
+ return [
+ 'fields' => urlencode($fields . ':' . $locked),
+ 'unlocked' => urlencode(implode('|', $unlockedFields)),
+ 'debug' => urlencode(json_encode([
+ $url,
+ $this->fields,
+ $this->unlockedFields,
+ ])),
+ ];
+ }
+
+ /**
+ * Generate validation hash.
+ *
+ * @param array $fields Fields list.
+ * @param array $unlockedFields Unlocked fields.
+ * @param string $url Form URL.
+ * @param string $sessionId Session Id.
+ * @return string
+ */
+ protected function generateHash(array $fields, array $unlockedFields, string $url, string $sessionId)
+ {
+ $hashParts = [
+ $url,
+ serialize($fields),
+ implode('|', $unlockedFields),
+ $sessionId,
+ ];
+
+ return hash_hmac('sha1', implode('', $hashParts), Security::getSalt());
+ }
+
+ /**
+ * Create a message for humans to understand why Security token is not matching
+ *
+ * @param array $formData Data.
+ * @param array $hashParts Elements used to generate the Token hash
+ * @return string Message explaining why the tokens are not matching
+ */
+ protected function debugTokenNotMatching(array $formData, array $hashParts): string
+ {
+ $messages = [];
+ if (!isset($formData['_Token']['debug'])) {
+ return 'Form protection debug token not found.';
+ }
+
+ $expectedParts = json_decode(urldecode($formData['_Token']['debug']), true);
+ if (!is_array($expectedParts) || count($expectedParts) !== 3) {
+ return 'Invalid form protection debug token.';
+ }
+ $expectedUrl = Hash::get($expectedParts, 0);
+ $url = Hash::get($hashParts, 'url');
+ if ($expectedUrl !== $url) {
+ $messages[] = sprintf('URL mismatch in POST data (expected `%s` but found `%s`)', $expectedUrl, $url);
+ }
+ $expectedFields = Hash::get($expectedParts, 1);
+ $dataFields = Hash::get($hashParts, 'fields') ?: [];
+ $fieldsMessages = $this->debugCheckFields(
+ (array)$dataFields,
+ $expectedFields,
+ 'Unexpected field `%s` in POST data',
+ 'Tampered field `%s` in POST data (expected value `%s` but found `%s`)',
+ 'Missing field `%s` in POST data'
+ );
+ $expectedUnlockedFields = Hash::get($expectedParts, 2);
+ $dataUnlockedFields = Hash::get($hashParts, 'unlockedFields') ?: [];
+ $unlockFieldsMessages = $this->debugCheckFields(
+ (array)$dataUnlockedFields,
+ $expectedUnlockedFields,
+ 'Unexpected unlocked field `%s` in POST data',
+ '',
+ 'Missing unlocked field: `%s`'
+ );
+
+ $messages = array_merge($messages, $fieldsMessages, $unlockFieldsMessages);
+
+ return implode(', ', $messages);
+ }
+
+ /**
+ * Iterates data array to check against expected
+ *
+ * @param array $dataFields Fields array, containing the POST data fields
+ * @param array $expectedFields Fields array, containing the expected fields we should have in POST
+ * @param string $intKeyMessage Message string if unexpected found in data fields indexed by int (not protected)
+ * @param string $stringKeyMessage Message string if tampered found in
+ * data fields indexed by string (protected).
+ * @param string $missingMessage Message string if missing field
+ * @return string[] Messages
+ */
+ protected function debugCheckFields(
+ array $dataFields,
+ array $expectedFields = [],
+ string $intKeyMessage = '',
+ string $stringKeyMessage = '',
+ string $missingMessage = ''
+ ): array {
+ $messages = $this->matchExistingFields($dataFields, $expectedFields, $intKeyMessage, $stringKeyMessage);
+ $expectedFieldsMessage = $this->debugExpectedFields($expectedFields, $missingMessage);
+ if ($expectedFieldsMessage !== null) {
+ $messages[] = $expectedFieldsMessage;
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Generate array of messages for the existing fields in POST data, matching dataFields in $expectedFields
+ * will be unset
+ *
+ * @param array $dataFields Fields array, containing the POST data fields
+ * @param array $expectedFields Fields array, containing the expected fields we should have in POST
+ * @param string $intKeyMessage Message string if unexpected found in data fields indexed by int (not protected)
+ * @param string $stringKeyMessage Message string if tampered found in
+ * data fields indexed by string (protected)
+ * @return string[] Error messages
+ */
+ protected function matchExistingFields(
+ array $dataFields,
+ array &$expectedFields,
+ string $intKeyMessage,
+ string $stringKeyMessage
+ ): array {
+ $messages = [];
+ foreach ($dataFields as $key => $value) {
+ if (is_int($key)) {
+ $foundKey = array_search($value, (array)$expectedFields, true);
+ if ($foundKey === false) {
+ $messages[] = sprintf($intKeyMessage, $value);
+ } else {
+ unset($expectedFields[$foundKey]);
+ }
+ } else {
+ if (isset($expectedFields[$key]) && $value !== $expectedFields[$key]) {
+ $messages[] = sprintf($stringKeyMessage, $key, $expectedFields[$key], $value);
+ }
+ unset($expectedFields[$key]);
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Generate debug message for the expected fields
+ *
+ * @param array $expectedFields Expected fields
+ * @param string $missingMessage Message template
+ * @return string|null Error message about expected fields
+ */
+ protected function debugExpectedFields(array $expectedFields = [], string $missingMessage = ''): ?string
+ {
+ if (count($expectedFields) === 0) {
+ return null;
+ }
+
+ $expectedFieldNames = [];
+ foreach ((array)$expectedFields as $key => $expectedField) {
+ if (is_int($key)) {
+ $expectedFieldNames[] = $expectedField;
+ } else {
+ $expectedFieldNames[] = $key;
+ }
+ }
+
+ return sprintf($missingMessage, implode(', ', $expectedFieldNames));
+ }
+
+ /**
+ * Return debug info
+ *
+ * @return array
+ */
+ public function __debugInfo(): array
+ {
+ return [
+ 'fields' => $this->fields,
+ 'unlockedFields' => $this->unlockedFields,
+ 'debugMessage' => $this->debugMessage,
+ ];
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Form/LICENSE.txt b/app/vendor/cakephp/cakephp/src/Form/LICENSE.txt
index 0c4b7932c..0b3b94303 100644
--- a/app/vendor/cakephp/cakephp/src/Form/LICENSE.txt
+++ b/app/vendor/cakephp/cakephp/src/Form/LICENSE.txt
@@ -1,7 +1,7 @@
The MIT License (MIT)
CakePHP(tm) : The Rapid Development PHP Framework (https://cakephp.org)
-Copyright (c) 2005-2016, Cake Software Foundation, Inc. (https://cakefoundation.org)
+Copyright (c) 2005-2019, Cake Software Foundation, Inc. (https://cakefoundation.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/vendor/cakephp/cakephp/src/Form/README.md b/app/vendor/cakephp/cakephp/src/Form/README.md
index fe8caef68..e7594cbc6 100644
--- a/app/vendor/cakephp/cakephp/src/Form/README.md
+++ b/app/vendor/cakephp/cakephp/src/Form/README.md
@@ -60,4 +60,4 @@ $errors = $contact->getErrors();
## Documentation
-Please make sure you check the [official documentation](https://book.cakephp.org/3/en/core-libraries/form.html)
+Please make sure you check the [official documentation](https://book.cakephp.org/4/en/core-libraries/form.html)
diff --git a/app/vendor/cakephp/cakephp/src/Form/Schema.php b/app/vendor/cakephp/cakephp/src/Form/Schema.php
index db30fa203..9f9ae2fe8 100644
--- a/app/vendor/cakephp/cakephp/src/Form/Schema.php
+++ b/app/vendor/cakephp/cakephp/src/Form/Schema.php
@@ -1,4 +1,6 @@
$attrs];
@@ -78,7 +80,7 @@ public function addField($name, $attrs)
* @param string $name The field to remove.
* @return $this
*/
- public function removeField($name)
+ public function removeField(string $name)
{
unset($this->_fields[$name]);
@@ -90,7 +92,7 @@ public function removeField($name)
*
* @return string[] The list of field names.
*/
- public function fields()
+ public function fields(): array
{
return array_keys($this->_fields);
}
@@ -101,7 +103,7 @@ public function fields()
* @param string $name The field name.
* @return array|null The attributes for a field, or null.
*/
- public function field($name)
+ public function field(string $name): ?array
{
if (!isset($this->_fields[$name])) {
return null;
@@ -117,7 +119,7 @@ public function field($name)
* @return string|null Either the field type or null if the
* field does not exist.
*/
- public function fieldType($name)
+ public function fieldType(string $name): ?string
{
$field = $this->field($name);
if (!$field) {
@@ -132,7 +134,7 @@ public function fieldType($name)
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
return [
'_fields' => $this->_fields,
diff --git a/app/vendor/cakephp/cakephp/src/Form/composer.json b/app/vendor/cakephp/cakephp/src/Form/composer.json
index f186aa5d8..794281138 100644
--- a/app/vendor/cakephp/cakephp/src/Form/composer.json
+++ b/app/vendor/cakephp/cakephp/src/Form/composer.json
@@ -21,9 +21,9 @@
"source": "https://github.com/cakephp/form"
},
"require": {
- "php": ">=5.6.0,<8.0.0",
- "cakephp/event": "^3.6.0",
- "cakephp/validation": "^3.6.0"
+ "php": ">=7.2.0",
+ "cakephp/event": "^4.0",
+ "cakephp/validation": "^4.0"
},
"autoload": {
"psr-4": {
diff --git a/app/vendor/cakephp/cakephp/src/Http/ActionDispatcher.php b/app/vendor/cakephp/cakephp/src/Http/ActionDispatcher.php
deleted file mode 100644
index b8f40f329..000000000
--- a/app/vendor/cakephp/cakephp/src/Http/ActionDispatcher.php
+++ /dev/null
@@ -1,171 +0,0 @@
-setEventManager($eventManager);
- }
- foreach ($filters as $filter) {
- $this->addFilter($filter);
- }
- $this->factory = $factory ?: new ControllerFactory();
- }
-
- /**
- * Dispatches a Request & Response
- *
- * @param \Cake\Http\ServerRequest $request The request to dispatch.
- * @param \Cake\Http\Response $response The response to dispatch.
- * @return \Cake\Http\Response A modified/replaced response.
- * @throws \ReflectionException
- */
- public function dispatch(ServerRequest $request, Response $response)
- {
- if (Router::getRequest(true) !== $request) {
- Router::pushRequest($request);
- }
- $beforeEvent = $this->dispatchEvent('Dispatcher.beforeDispatch', compact('request', 'response'));
-
- $request = $beforeEvent->getData('request');
- if ($beforeEvent->getResult() instanceof Response) {
- return $beforeEvent->getResult();
- }
-
- // Use the controller built by an beforeDispatch
- // event handler if there is one.
- if ($beforeEvent->getData('controller') instanceof Controller) {
- $controller = $beforeEvent->getData('controller');
- } else {
- $controller = $this->factory->create($request, $response);
- }
-
- $response = $this->_invoke($controller);
- if ($request->getParam('return')) {
- return $response;
- }
-
- $afterEvent = $this->dispatchEvent('Dispatcher.afterDispatch', compact('request', 'response'));
-
- return $afterEvent->getData('response');
- }
-
- /**
- * Invoke a controller's action and wrapping methods.
- *
- * @param \Cake\Controller\Controller $controller The controller to invoke.
- * @return \Cake\Http\Response The response
- * @throws \LogicException If the controller action returns a non-response value.
- */
- protected function _invoke(Controller $controller)
- {
- $this->dispatchEvent('Dispatcher.invokeController', ['controller' => $controller]);
-
- $result = $controller->startupProcess();
- if ($result instanceof Response) {
- return $result;
- }
-
- $response = $controller->invokeAction();
- if ($response !== null && !($response instanceof Response)) {
- throw new LogicException('Controller actions can only return Cake\Http\Response or null.');
- }
-
- if (!$response && $controller->isAutoRenderEnabled()) {
- $controller->render();
- }
-
- $result = $controller->shutdownProcess();
- if ($result instanceof Response) {
- return $result;
- }
- if (!$response) {
- $response = $controller->getResponse();
- }
-
- return $response;
- }
-
- /**
- * Add a filter to this dispatcher.
- *
- * The added filter will be attached to the event manager used
- * by this dispatcher.
- *
- * @param \Cake\Event\EventListenerInterface $filter The filter to connect. Can be
- * any EventListenerInterface. Typically an instance of \Cake\Routing\DispatcherFilter.
- * @return void
- * @deprecated This is only available for backwards compatibility with DispatchFilters
- */
- public function addFilter(EventListenerInterface $filter)
- {
- deprecationWarning(
- 'ActionDispatcher::addFilter() is deprecated. ' .
- 'This is only available for backwards compatibility with DispatchFilters'
- );
-
- $this->filters[] = $filter;
- $this->getEventManager()->on($filter);
- }
-
- /**
- * Get the connected filters.
- *
- * @return array
- */
- public function getFilters()
- {
- return $this->filters;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Http/BaseApplication.php b/app/vendor/cakephp/cakephp/src/Http/BaseApplication.php
index 35a3677d9..02109f9b6 100644
--- a/app/vendor/cakephp/cakephp/src/Http/BaseApplication.php
+++ b/app/vendor/cakephp/cakephp/src/Http/BaseApplication.php
@@ -1,4 +1,6 @@
configDir = $configDir;
+ * @param \Cake\Http\ControllerFactoryInterface $controllerFactory Controller factory.
+ */
+ public function __construct(
+ string $configDir,
+ ?EventManagerInterface $eventManager = null,
+ ?ControllerFactoryInterface $controllerFactory = null
+ ) {
+ $this->configDir = rtrim($configDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$this->plugins = Plugin::getCollection();
$this->_eventManager = $eventManager ?: EventManager::instance();
+ $this->controllerFactory = $controllerFactory;
}
/**
- * @param \Cake\Http\MiddlewareQueue $middleware The middleware queue to set in your App Class
+ * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to set in your App Class
* @return \Cake\Http\MiddlewareQueue
*/
- abstract public function middleware($middleware);
+ abstract public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue;
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function pluginMiddleware($middleware)
+ public function pluginMiddleware(MiddlewareQueue $middleware): MiddlewareQueue
{
foreach ($this->plugins->with('middleware') as $plugin) {
$middleware = $plugin->middleware($middleware);
@@ -90,93 +107,42 @@ public function pluginMiddleware($middleware)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function addPlugin($name, array $config = [])
{
if (is_string($name)) {
- $plugin = $this->makePlugin($name, $config);
+ $plugin = $this->plugins->create($name, $config);
} else {
$plugin = $name;
}
- if (!$plugin instanceof PluginInterface) {
- throw new InvalidArgumentException(sprintf(
- "The `%s` plugin does not implement Cake\Core\PluginInterface.",
- get_class($plugin)
- ));
- }
$this->plugins->add($plugin);
return $this;
}
- /**
- * Add an optional plugin
- *
- * If it isn't available, ignore it.
- *
- * @param string|\Cake\Core\PluginInterface $name The plugin name or plugin object.
- * @param array $config The configuration data for the plugin if using a string for $name
- * @return $this
- */
- public function addOptionalPlugin($name, array $config = [])
- {
- try {
- $this->addPlugin($name, $config);
- } catch (MissingPluginException $e) {
- // Do not halt if the plugin is missing
- }
-
- return $this;
- }
-
/**
* Get the plugin collection in use.
*
* @return \Cake\Core\PluginCollection
*/
- public function getPlugins()
+ public function getPlugins(): PluginCollection
{
return $this->plugins;
}
/**
- * Create a plugin instance from a classname and configuration
- *
- * @param string $name The plugin classname
- * @param array $config Configuration options for the plugin
- * @return \Cake\Core\PluginInterface
- */
- protected function makePlugin($name, array $config)
- {
- $className = $name;
- if (strpos($className, '\\') === false) {
- $className = str_replace('/', '\\', $className) . '\\' . 'Plugin';
- }
- if (class_exists($className)) {
- return new $className($config);
- }
-
- if (!isset($config['path'])) {
- $config['path'] = $this->plugins->findPath($name);
- }
- $config['name'] = $name;
-
- return new BasePlugin($config);
- }
-
- /**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function bootstrap()
+ public function bootstrap(): void
{
- require_once $this->configDir . '/bootstrap.php';
+ require_once $this->configDir . 'bootstrap.php';
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function pluginBootstrap()
+ public function pluginBootstrap(): void
{
foreach ($this->plugins->with('bootstrap') as $plugin) {
$plugin->bootstrap($this);
@@ -191,20 +157,18 @@ public function pluginBootstrap()
* @param \Cake\Routing\RouteBuilder $routes A route builder to add routes into.
* @return void
*/
- public function routes($routes)
+ public function routes(RouteBuilder $routes): void
{
- if (!Router::$initialized) {
- // Prevent routes from being loaded again
- Router::$initialized = true;
-
- require $this->configDir . '/routes.php';
+ // Only load routes if the router is empty
+ if (!Router::routes()) {
+ require $this->configDir . 'routes.php';
}
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function pluginRoutes($routes)
+ public function pluginRoutes(RouteBuilder $routes): RouteBuilder
{
foreach ($this->plugins->with('routes') as $plugin) {
$plugin->routes($routes);
@@ -222,15 +186,15 @@ public function pluginRoutes($routes)
* @param \Cake\Console\CommandCollection $commands The CommandCollection to add commands into.
* @return \Cake\Console\CommandCollection The updated collection.
*/
- public function console($commands)
+ public function console(CommandCollection $commands): CommandCollection
{
return $commands->addMany($commands->autoDiscover());
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function pluginConsole($commands)
+ public function pluginConsole(CommandCollection $commands): CommandCollection
{
foreach ($this->plugins->with('console') as $plugin) {
$commands = $plugin->console($commands);
@@ -247,22 +211,21 @@ public function pluginConsole($commands)
* - Invoke the controller.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request
- * @param \Psr\Http\Message\ResponseInterface $response The response
- * @param callable $next The next middleware
* @return \Psr\Http\Message\ResponseInterface
*/
- public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
- {
- return $this->getDispatcher()->dispatch($request, $response);
- }
+ public function handle(
+ ServerRequestInterface $request
+ ): ResponseInterface {
+ if ($this->controllerFactory === null) {
+ $this->controllerFactory = new ControllerFactory();
+ }
- /**
- * Get the ActionDispatcher.
- *
- * @return \Cake\Http\ActionDispatcher
- */
- protected function getDispatcher()
- {
- return new ActionDispatcher(null, $this->getEventManager(), DispatcherFactory::filters());
+ if (Router::getRequest() !== $request) {
+ Router::setRequest($request);
+ }
+
+ $controller = $this->controllerFactory->create($request);
+
+ return $this->controllerFactory->invoke($controller);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/CallbackStream.php b/app/vendor/cakephp/cakephp/src/Http/CallbackStream.php
index 64510cb1d..4f930e276 100644
--- a/app/vendor/cakephp/cakephp/src/Http/CallbackStream.php
+++ b/app/vendor/cakephp/cakephp/src/Http/CallbackStream.php
@@ -1,4 +1,6 @@
detach();
$result = '';
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client.php b/app/vendor/cakephp/cakephp/src/Http/Client.php
index 6848957ee..3a1e2d83d 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client.php
@@ -1,4 +1,6 @@
setConfig($config);
@@ -199,7 +205,7 @@ public function __construct($config = [])
*
* @return \Cake\Http\Cookie\CookieCollection
*/
- public function cookies()
+ public function cookies(): CookieCollection
{
return $this->_cookies;
}
@@ -230,15 +236,15 @@ public function addCookie(CookieInterface $cookie)
* this feature.
*
* @param string $url The url or path you want to request.
- * @param array $data The query data you want to send.
+ * @param array|string $data The query data you want to send.
* @param array $options Additional options for the request.
* @return \Cake\Http\Client\Response
*/
- public function get($url, $data = [], array $options = [])
+ public function get(string $url, $data = [], array $options = []): Response
{
$options = $this->_mergeOptions($options);
$body = null;
- if (isset($data['_content'])) {
+ if (is_array($data) && isset($data['_content'])) {
$body = $data['_content'];
unset($data['_content']);
}
@@ -260,7 +266,7 @@ public function get($url, $data = [], array $options = [])
* @param array $options Additional options for the request.
* @return \Cake\Http\Client\Response
*/
- public function post($url, $data = [], array $options = [])
+ public function post(string $url, $data = [], array $options = []): Response
{
$options = $this->_mergeOptions($options);
$url = $this->buildUrl($url, [], $options);
@@ -276,7 +282,7 @@ public function post($url, $data = [], array $options = [])
* @param array $options Additional options for the request.
* @return \Cake\Http\Client\Response
*/
- public function put($url, $data = [], array $options = [])
+ public function put(string $url, $data = [], array $options = []): Response
{
$options = $this->_mergeOptions($options);
$url = $this->buildUrl($url, [], $options);
@@ -292,7 +298,7 @@ public function put($url, $data = [], array $options = [])
* @param array $options Additional options for the request.
* @return \Cake\Http\Client\Response
*/
- public function patch($url, $data = [], array $options = [])
+ public function patch(string $url, $data = [], array $options = []): Response
{
$options = $this->_mergeOptions($options);
$url = $this->buildUrl($url, [], $options);
@@ -308,7 +314,7 @@ public function patch($url, $data = [], array $options = [])
* @param array $options Additional options for the request.
* @return \Cake\Http\Client\Response
*/
- public function options($url, $data = [], array $options = [])
+ public function options(string $url, $data = [], array $options = []): Response
{
$options = $this->_mergeOptions($options);
$url = $this->buildUrl($url, [], $options);
@@ -324,7 +330,7 @@ public function options($url, $data = [], array $options = [])
* @param array $options Additional options for the request.
* @return \Cake\Http\Client\Response
*/
- public function trace($url, $data = [], array $options = [])
+ public function trace(string $url, $data = [], array $options = []): Response
{
$options = $this->_mergeOptions($options);
$url = $this->buildUrl($url, [], $options);
@@ -340,7 +346,7 @@ public function trace($url, $data = [], array $options = [])
* @param array $options Additional options for the request.
* @return \Cake\Http\Client\Response
*/
- public function delete($url, $data = [], array $options = [])
+ public function delete(string $url, $data = [], array $options = []): Response
{
$options = $this->_mergeOptions($options);
$url = $this->buildUrl($url, [], $options);
@@ -356,7 +362,7 @@ public function delete($url, $data = [], array $options = [])
* @param array $options Additional options for the request.
* @return \Cake\Http\Client\Response
*/
- public function head($url, array $data = [], array $options = [])
+ public function head(string $url, array $data = [], array $options = []): Response
{
$options = $this->_mergeOptions($options);
$url = $this->buildUrl($url, $data, $options);
@@ -373,7 +379,7 @@ public function head($url, array $data = [], array $options = [])
* @param array $options The options to use. Contains auth, proxy, etc.
* @return \Cake\Http\Client\Response
*/
- protected function _doRequest($method, $url, $data, $options)
+ protected function _doRequest(string $method, string $url, $data, $options): Response
{
$request = $this->_createRequest(
$method,
@@ -391,22 +397,34 @@ protected function _doRequest($method, $url, $data, $options)
* @param array $options Options to merge.
* @return array Options merged with set config.
*/
- protected function _mergeOptions($options)
+ protected function _mergeOptions(array $options): array
{
return Hash::merge($this->_config, $options);
}
+ /**
+ * Sends a PSR-7 request and returns a PSR-7 response.
+ *
+ * @param \Psr\Http\Message\RequestInterface $request Request instance.
+ * @return \Psr\Http\Message\ResponseInterface Response instance.
+ * @throws \Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request.
+ */
+ public function sendRequest(RequestInterface $request): ResponseInterface
+ {
+ return $this->send($request, $this->_config);
+ }
+
/**
* Send a request.
*
* Used internally by other methods, but can also be used to send
* handcrafted Request objects.
*
- * @param \Cake\Http\Client\Request $request The request to send.
+ * @param \Psr\Http\Message\RequestInterface $request The request to send.
* @param array $options Additional options to use.
* @return \Cake\Http\Client\Response
*/
- public function send(Request $request, $options = [])
+ public function send(RequestInterface $request, array $options = []): Response
{
$redirects = 0;
if (isset($options['redirect'])) {
@@ -439,14 +457,13 @@ public function send(Request $request, $options = [])
/**
* Send a request without redirection.
*
- * @param \Cake\Http\Client\Request $request The request to send.
+ * @param \Psr\Http\Message\RequestInterface $request The request to send.
* @param array $options Additional options to use.
* @return \Cake\Http\Client\Response
*/
- protected function _sendRequest(Request $request, $options)
+ protected function _sendRequest(RequestInterface $request, array $options): Response
{
$responses = $this->_adapter->send($request, $options);
- $url = $request->getUri();
foreach ($responses as $response) {
$this->_cookies = $this->_cookies->addFromResponse($response, $request);
}
@@ -462,13 +479,13 @@ protected function _sendRequest(Request $request, $options)
* @param array $options The config options stored with Client::config()
* @return string A complete url with scheme, port, host, and path.
*/
- public function buildUrl($url, $query = [], $options = [])
+ public function buildUrl(string $url, $query = [], array $options = []): string
{
if (empty($options) && empty($query)) {
return $url;
}
if ($query) {
- $q = (strpos($url, '?') === false) ? '?' : '&';
+ $q = strpos($url, '?') === false ? '?' : '&';
$url .= $q;
$url .= is_string($query) ? $query : http_build_query($query);
}
@@ -492,7 +509,7 @@ public function buildUrl($url, $query = [], $options = [])
'https' => 443,
];
$out = $options['scheme'] . '://' . $options['host'];
- if ($options['port'] && $options['port'] != $defaultPorts[$options['scheme']]) {
+ if ($options['port'] && (int)$options['port'] !== $defaultPorts[$options['scheme']]) {
$out .= ':' . $options['port'];
}
$out .= '/' . ltrim($url, '/');
@@ -509,9 +526,9 @@ public function buildUrl($url, $query = [], $options = [])
* @param array $options The options to use. Contains auth, proxy, etc.
* @return \Cake\Http\Client\Request
*/
- protected function _createRequest($method, $url, $data, $options)
+ protected function _createRequest(string $method, string $url, $data, $options): Request
{
- $headers = isset($options['headers']) ? (array)$options['headers'] : [];
+ $headers = (array)($options['headers'] ?? []);
if (isset($options['type'])) {
$headers = array_merge($headers, $this->_typeHeaders($options['type']));
}
@@ -520,9 +537,9 @@ protected function _createRequest($method, $url, $data, $options)
}
$request = new Request($url, $method, $headers, $data);
+ /** @var \Cake\Http\Client\Request $request */
$request = $request->withProtocolVersion($this->getConfig('protocolVersion'));
-
- $cookies = isset($options['cookies']) ? $options['cookies'] : [];
+ $cookies = $options['cookies'] ?? [];
/** @var \Cake\Http\Client\Request $request */
$request = $this->_cookies->addToRequest($request, $cookies);
if (isset($options['auth'])) {
@@ -542,8 +559,9 @@ protected function _createRequest($method, $url, $data, $options)
* @param string $type short type alias or full mimetype.
* @return string[] Headers to set on the request.
* @throws \Cake\Core\Exception\Exception When an unknown type alias is used.
+ * @psalm-return array{Accept: string, Content-Type: string}
*/
- protected function _typeHeaders($type)
+ protected function _typeHeaders(string $type): array
{
if (strpos($type, '/') !== false) {
return [
@@ -575,14 +593,13 @@ protected function _typeHeaders($type)
* @param array $options Array of options containing the 'auth' key.
* @return \Cake\Http\Client\Request The updated request object.
*/
- protected function _addAuthentication(Request $request, $options)
+ protected function _addAuthentication(Request $request, array $options): Request
{
$auth = $options['auth'];
/** @var \Cake\Http\Client\Auth\Basic $adapter */
$adapter = $this->_createAuth($auth, $options);
- $result = $adapter->authentication($request, $options['auth']);
- return $result ?: $request;
+ return $adapter->authentication($request, $options['auth']);
}
/**
@@ -595,14 +612,13 @@ protected function _addAuthentication(Request $request, $options)
* @param array $options Array of options containing the 'proxy' key.
* @return \Cake\Http\Client\Request The updated request object.
*/
- protected function _addProxy(Request $request, $options)
+ protected function _addProxy(Request $request, array $options): Request
{
$auth = $options['proxy'];
/** @var \Cake\Http\Client\Auth\Basic $adapter */
$adapter = $this->_createAuth($auth, $options);
- $result = $adapter->proxyAuthentication($request, $options['proxy']);
- return $result ?: $request;
+ return $adapter->proxyAuthentication($request, $options['proxy']);
}
/**
@@ -616,7 +632,7 @@ protected function _addProxy(Request $request, $options)
* @return object Authentication strategy instance.
* @throws \Cake\Core\Exception\Exception when an invalid strategy is chosen.
*/
- protected function _createAuth($auth, $options)
+ protected function _createAuth(array $auth, array $options)
{
if (empty($auth['type'])) {
$auth['type'] = 'basic';
@@ -632,5 +648,3 @@ protected function _createAuth($auth, $options)
return new $class($this, $options);
}
}
-// @deprecated 3.4.0 Backwards compatibility with earler 3.x versions.
-class_alias('Cake\Http\Client', 'Cake\Network\Http\Client');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Curl.php b/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Curl.php
index ba39347ac..68dee3dda 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Curl.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Curl.php
@@ -1,4 +1,6 @@
buildOptions($request, $options);
curl_setopt_array($ch, $options);
+ /** @var string|false $body */
$body = $this->exec($ch);
if ($body === false) {
$errorCode = curl_errno($ch);
$error = curl_error($ch);
curl_close($ch);
- $status = 500;
- if ($errorCode === CURLE_OPERATION_TIMEOUTED) {
- $status = 504;
+ $message = "cURL Error ({$errorCode}) {$error}";
+ $errorNumbers = [
+ CURLE_FAILED_INIT,
+ CURLE_URL_MALFORMAT,
+ CURLE_URL_MALFORMAT_USER,
+ ];
+ if (in_array($errorCode, $errorNumbers, true)) {
+ throw new RequestException($message, $request);
}
- throw new HttpException("cURL Error ({$errorCode}) {$error}", $status);
+ throw new NetworkException($message, $request);
}
$responses = $this->createResponse($ch, $body);
@@ -59,11 +76,11 @@ public function send(Request $request, array $options)
/**
* Convert client options into curl options.
*
- * @param \Cake\Http\Client\Request $request The request.
+ * @param \Psr\Http\Message\RequestInterface $request The request.
* @param array $options The client options
* @return array
*/
- public function buildOptions(Request $request, array $options)
+ public function buildOptions(RequestInterface $request, array $options): array
{
$headers = [];
foreach ($request->getHeaders() as $key => $values) {
@@ -86,10 +103,6 @@ public function buildOptions(Request $request, array $options)
$out[CURLOPT_POST] = true;
break;
- case Request::METHOD_HEAD:
- $out[CURLOPT_NOBODY] = true;
- break;
-
default:
$out[CURLOPT_POST] = true;
$out[CURLOPT_CUSTOMREQUEST] = $request->getMethod();
@@ -97,17 +110,18 @@ public function buildOptions(Request $request, array $options)
}
$body = $request->getBody();
- if ($body) {
- $body->rewind();
- $out[CURLOPT_POSTFIELDS] = $body->getContents();
- // GET requests with bodies require custom request to be used.
- if (isset($out[CURLOPT_HTTPGET])) {
- $out[CURLOPT_CUSTOMREQUEST] = 'get';
- }
+ $body->rewind();
+ $out[CURLOPT_POSTFIELDS] = $body->getContents();
+ // GET requests with bodies require custom request to be used.
+ if (strlen($out[CURLOPT_POSTFIELDS]) && isset($out[CURLOPT_HTTPGET])) {
+ $out[CURLOPT_CUSTOMREQUEST] = 'get';
+ }
+ if ($out[CURLOPT_POSTFIELDS] === '') {
+ unset($out[CURLOPT_POSTFIELDS]);
}
if (empty($options['ssl_cafile'])) {
- $options['ssl_cafile'] = CORE_PATH . 'config' . DIRECTORY_SEPARATOR . 'cacert.pem';
+ $options['ssl_cafile'] = CaBundle::getBundledCaBundlePath();
}
if (!empty($options['ssl_verify_host'])) {
// Value of 1 or true is deprecated. Only 2 or 0 should be used now.
@@ -146,10 +160,10 @@ public function buildOptions(Request $request, array $options)
/**
* Convert HTTP version number into curl value.
*
- * @param \Cake\Http\Client\Request $request The request to get a protocol version for.
+ * @param \Psr\Http\Message\RequestInterface $request The request to get a protocol version for.
* @return int
*/
- protected function getProtocolVersion(Request $request)
+ protected function getProtocolVersion(RequestInterface $request): int
{
switch ($request->getProtocolVersion()) {
case '1.0':
@@ -175,9 +189,9 @@ protected function getProtocolVersion(Request $request)
*
* @param resource $handle Curl handle
* @param string $responseData string The response data from curl_exec
- * @return \Cake\Http\Client\Response
+ * @return \Cake\Http\Client\Response[]
*/
- protected function createResponse($handle, $responseData)
+ protected function createResponse($handle, $responseData): array
{
$headerSize = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
$headers = trim(substr($responseData, 0, $headerSize));
@@ -191,7 +205,7 @@ protected function createResponse($handle, $responseData)
* Execute the curl handle.
*
* @param resource $ch Curl Resource handle
- * @return string
+ * @return string|bool
*/
protected function exec($ch)
{
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Stream.php b/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Stream.php
index 125a74d6a..6f5b31a9c 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Stream.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Stream.php
@@ -1,4 +1,6 @@
_stream = null;
$this->_context = null;
@@ -88,7 +92,7 @@ public function send(Request $request, array $options)
* @param string $content The response content.
* @return \Cake\Http\Client\Response[] The list of responses from the request(s)
*/
- public function createResponses($headers, $content)
+ public function createResponses(array $headers, string $content): array
{
$indexes = $responses = [];
foreach ($headers as $i => $header) {
@@ -98,9 +102,10 @@ public function createResponses($headers, $content)
}
$last = count($indexes) - 1;
foreach ($indexes as $i => $start) {
+ /** @psalm-suppress InvalidOperand */
$end = isset($indexes[$i + 1]) ? $indexes[$i + 1] - $start : null;
$headerSlice = array_slice($headers, $start, $end);
- $body = $i == $last ? $content : '';
+ $body = $i === $last ? $content : '';
$responses[] = $this->_buildResponse($headerSlice, $body);
}
@@ -110,18 +115,18 @@ public function createResponses($headers, $content)
/**
* Build the stream context out of the request object.
*
- * @param \Cake\Http\Client\Request $request The request to build context from.
+ * @param \Psr\Http\Message\RequestInterface $request The request to build context from.
* @param array $options Additional request options.
* @return void
*/
- protected function _buildContext(Request $request, $options)
+ protected function _buildContext(RequestInterface $request, array $options): void
{
$this->_buildContent($request, $options);
$this->_buildHeaders($request, $options);
$this->_buildOptions($request, $options);
$url = $request->getUri();
- $scheme = parse_url($url, PHP_URL_SCHEME);
+ $scheme = parse_url((string)$url, PHP_URL_SCHEME);
if ($scheme === 'https') {
$this->_buildSslContext($request, $options);
}
@@ -136,11 +141,11 @@ protected function _buildContext(Request $request, $options)
*
* Creates cookies & headers.
*
- * @param \Cake\Http\Client\Request $request The request being sent.
+ * @param \Psr\Http\Message\RequestInterface $request The request being sent.
* @param array $options Array of options to use.
* @return void
*/
- protected function _buildHeaders(Request $request, $options)
+ protected function _buildHeaders(RequestInterface $request, array $options): void
{
$headers = [];
foreach ($request->getHeaders() as $name => $values) {
@@ -155,11 +160,11 @@ protected function _buildHeaders(Request $request, $options)
* If the $request->body() is a string, it will be used as is.
* Array data will be processed with Cake\Http\Client\FormData
*
- * @param \Cake\Http\Client\Request $request The request being sent.
+ * @param \Psr\Http\Message\RequestInterface $request The request being sent.
* @param array $options Array of options to use.
* @return void
*/
- protected function _buildContent(Request $request, $options)
+ protected function _buildContent(RequestInterface $request, array $options): void
{
$body = $request->getBody();
if (empty($body)) {
@@ -174,11 +179,11 @@ protected function _buildContent(Request $request, $options)
/**
* Build miscellaneous options for the request.
*
- * @param \Cake\Http\Client\Request $request The request being sent.
+ * @param \Psr\Http\Message\RequestInterface $request The request being sent.
* @param array $options Array of options to use.
* @return void
*/
- protected function _buildOptions(Request $request, $options)
+ protected function _buildOptions(RequestInterface $request, array $options): void
{
$this->_contextOptions['method'] = $request->getMethod();
$this->_contextOptions['protocol_version'] = $request->getProtocolVersion();
@@ -199,11 +204,11 @@ protected function _buildOptions(Request $request, $options)
/**
* Build SSL options for the request.
*
- * @param \Cake\Http\Client\Request $request The request being sent.
+ * @param \Psr\Http\Message\RequestInterface $request The request being sent.
* @param array $options Array of options to use.
* @return void
*/
- protected function _buildSslContext(Request $request, $options)
+ protected function _buildSslContext(RequestInterface $request, array $options): void
{
$sslOptions = [
'ssl_verify_peer',
@@ -212,15 +217,14 @@ protected function _buildSslContext(Request $request, $options)
'ssl_allow_self_signed',
'ssl_cafile',
'ssl_local_cert',
- 'ssl_local_pk',
'ssl_passphrase',
];
if (empty($options['ssl_cafile'])) {
- $options['ssl_cafile'] = CORE_PATH . 'config' . DIRECTORY_SEPARATOR . 'cacert.pem';
+ $options['ssl_cafile'] = CaBundle::getBundledCaBundlePath();
}
if (!empty($options['ssl_verify_host'])) {
$url = $request->getUri();
- $host = parse_url($url, PHP_URL_HOST);
+ $host = parse_url((string)$url, PHP_URL_HOST);
$this->_sslContextOptions['peer_name'] = $host;
}
foreach ($sslOptions as $key) {
@@ -234,11 +238,11 @@ protected function _buildSslContext(Request $request, $options)
/**
* Open the stream and send the request.
*
- * @param \Cake\Http\Client\Request $request The request object.
+ * @param \Psr\Http\Message\RequestInterface $request The request object.
* @return array Array of populated Response objects
- * @throws \Cake\Http\Exception\HttpException
+ * @throws \Psr\Http\Client\NetworkExceptionInterface
*/
- protected function _send(Request $request)
+ protected function _send(RequestInterface $request): array
{
$deadline = false;
if (isset($this->_contextOptions['timeout']) && $this->_contextOptions['timeout'] > 0) {
@@ -246,7 +250,7 @@ protected function _send(Request $request)
}
$url = $request->getUri();
- $this->_open($url);
+ $this->_open((string)$url, $request);
$content = '';
$timedOut = false;
@@ -263,11 +267,13 @@ protected function _send(Request $request)
break;
}
}
+ /** @psalm-suppress PossiblyNullArgument */
$meta = stream_get_meta_data($this->_stream);
+ /** @psalm-suppress InvalidPropertyAssignmentValue */
fclose($this->_stream);
if ($timedOut) {
- throw new HttpException('Connection timed out ' . $url, 504);
+ throw new NetworkException('Connection timed out ' . $url, $request);
}
$headers = $meta['wrapper_data'];
@@ -285,7 +291,7 @@ protected function _send(Request $request)
* @param string $body The response body.
* @return \Cake\Http\Client\Response
*/
- protected function _buildResponse($headers, $body)
+ protected function _buildResponse(array $headers, string $body): Response
{
return new Response($headers, $body);
}
@@ -294,22 +300,30 @@ protected function _buildResponse($headers, $body)
* Open the socket and handle any connection errors.
*
* @param string $url The url to connect to.
+ * @param \Psr\Http\Message\RequestInterface $request The request object.
* @return void
- * @throws \Cake\Core\Exception\Exception
+ * @throws \Psr\Http\Client\RequestExceptionInterface
*/
- protected function _open($url)
+ protected function _open(string $url, RequestInterface $request): void
{
- set_error_handler(function ($code, $message) {
+ if (!(bool)ini_get('allow_url_fopen')) {
+ throw new ClientException('The PHP directive `allow_url_fopen` must be enabled.');
+ }
+
+ set_error_handler(function ($code, $message): bool {
$this->_connectionErrors[] = $message;
+
+ return true;
});
try {
+ /** @psalm-suppress PossiblyNullArgument */
$this->_stream = fopen($url, 'rb', false, $this->_context);
} finally {
restore_error_handler();
}
if (!$this->_stream || !empty($this->_connectionErrors)) {
- throw new Exception(implode("\n", $this->_connectionErrors));
+ throw new RequestException(implode("\n", $this->_connectionErrors), $request);
}
}
@@ -320,11 +334,8 @@ protected function _open($url)
*
* @return array
*/
- public function contextOptions()
+ public function contextOptions(): array
{
return array_merge($this->_contextOptions, $this->_sslContextOptions);
}
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\Adapter\Stream', 'Cake\Network\Http\Adapter\Stream');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/AdapterInterface.php b/app/vendor/cakephp/cakephp/src/Http/Client/AdapterInterface.php
index e3c5c9480..b64c81dab 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/AdapterInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/AdapterInterface.php
@@ -1,4 +1,6 @@
_generateHeader($credentials['username'], $credentials['password']);
@@ -50,7 +52,7 @@ public function authentication(Request $request, array $credentials)
* @return \Cake\Http\Client\Request The updated request.
* @see https://www.ietf.org/rfc/rfc2617.txt
*/
- public function proxyAuthentication(Request $request, array $credentials)
+ public function proxyAuthentication(Request $request, array $credentials): Request
{
if (isset($credentials['username'], $credentials['password'])) {
$value = $this->_generateHeader($credentials['username'], $credentials['password']);
@@ -68,11 +70,8 @@ public function proxyAuthentication(Request $request, array $credentials)
* @param string $pass Password.
* @return string
*/
- protected function _generateHeader($user, $pass)
+ protected function _generateHeader(string $user, string $pass): string
{
return 'Basic ' . base64_encode($user . ':' . $pass);
}
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\Auth\Basic', 'Cake\Network\Http\Auth\Basic');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Digest.php b/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Digest.php
index e374e3511..ef313371d 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Digest.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Digest.php
@@ -1,4 +1,6 @@
_client = $client;
}
@@ -50,7 +52,7 @@ public function __construct(Client $client, $options = null)
* @return \Cake\Http\Client\Request The updated request.
* @see https://www.ietf.org/rfc/rfc2617.txt
*/
- public function authentication(Request $request, array $credentials)
+ public function authentication(Request $request, array $credentials): Request
{
if (!isset($credentials['username'], $credentials['password'])) {
return $request;
@@ -77,10 +79,10 @@ public function authentication(Request $request, array $credentials)
* @param array $credentials Authentication credentials.
* @return array modified credentials.
*/
- protected function _getServerInfo(Request $request, $credentials)
+ protected function _getServerInfo(Request $request, array $credentials): array
{
$response = $this->_client->get(
- $request->getUri(),
+ (string)$request->getUri(),
[],
['auth' => ['type' => null]]
);
@@ -111,19 +113,21 @@ protected function _getServerInfo(Request $request, $credentials)
* @param array $credentials Authentication credentials.
* @return string
*/
- protected function _generateHeader(Request $request, $credentials)
+ protected function _generateHeader(Request $request, array $credentials): string
{
$path = $request->getUri()->getPath();
$a1 = md5($credentials['username'] . ':' . $credentials['realm'] . ':' . $credentials['password']);
$a2 = md5($request->getMethod() . ':' . $path);
- $nc = null;
+ $nc = '';
if (empty($credentials['qop'])) {
$response = md5($a1 . ':' . $credentials['nonce'] . ':' . $a2);
} else {
$credentials['cnonce'] = uniqid();
$nc = sprintf('%08x', $credentials['nc']++);
- $response = md5($a1 . ':' . $credentials['nonce'] . ':' . $nc . ':' . $credentials['cnonce'] . ':auth:' . $a2);
+ $response = md5(
+ $a1 . ':' . $credentials['nonce'] . ':' . $nc . ':' . $credentials['cnonce'] . ':auth:' . $a2
+ );
}
$authHeader = 'Digest ';
@@ -142,6 +146,3 @@ protected function _generateHeader(Request $request, $credentials)
return $authHeader;
}
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\Auth\Digest', 'Cake\Network\Http\Auth\Digest');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Oauth.php b/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Oauth.php
index ef22138c9..46b1ab733 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Oauth.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Oauth.php
@@ -1,4 +1,6 @@
'1.0',
@@ -128,24 +131,20 @@ protected function _plaintext($request, $credentials)
* @param array $credentials Authentication credentials.
* @return string
*/
- protected function _hmacSha1($request, $credentials)
+ protected function _hmacSha1(Request $request, array $credentials): string
{
- $nonce = isset($credentials['nonce']) ? $credentials['nonce'] : uniqid();
- $timestamp = isset($credentials['timestamp']) ? $credentials['timestamp'] : time();
+ $nonce = $credentials['nonce'] ?? uniqid();
+ $timestamp = $credentials['timestamp'] ?? time();
$values = [
'oauth_version' => '1.0',
'oauth_nonce' => $nonce,
'oauth_timestamp' => $timestamp,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_token' => $credentials['token'],
- 'oauth_consumer_key' => $this->_encode($credentials['consumerKey']),
+ 'oauth_consumer_key' => $credentials['consumerKey'],
];
$baseString = $this->baseString($request, $values);
- // Consumer key should only be encoded for base string calculation as
- // auth header generation already encodes independently
- $values['oauth_consumer_key'] = $credentials['consumerKey'];
-
if (isset($credentials['realm'])) {
$values['oauth_realm'] = $credentials['realm'];
}
@@ -170,14 +169,14 @@ protected function _hmacSha1($request, $credentials)
* @return string
* @throws \RuntimeException
*/
- protected function _rsaSha1($request, $credentials)
+ protected function _rsaSha1(Request $request, array $credentials): string
{
if (!function_exists('openssl_pkey_get_private')) {
throw new RuntimeException('RSA-SHA1 signature method requires the OpenSSL extension.');
}
- $nonce = isset($credentials['nonce']) ? $credentials['nonce'] : bin2hex(Security::randomBytes(16));
- $timestamp = isset($credentials['timestamp']) ? $credentials['timestamp'] : time();
+ $nonce = $credentials['nonce'] ?? bin2hex(Security::randomBytes(16));
+ $timestamp = $credentials['timestamp'] ?? time();
$values = [
'oauth_version' => '1.0',
'oauth_nonce' => $nonce,
@@ -208,7 +207,7 @@ protected function _rsaSha1($request, $credentials)
}
$credentials += [
- 'privateKeyPassphrase' => null,
+ 'privateKeyPassphrase' => '',
];
if (is_resource($credentials['privateKeyPassphrase'])) {
$resource = $credentials['privateKeyPassphrase'];
@@ -239,7 +238,7 @@ protected function _rsaSha1($request, $credentials)
* @param array $oauthValues Oauth values.
* @return string
*/
- public function baseString($request, $oauthValues)
+ public function baseString(Request $request, array $oauthValues): string
{
$parts = [
$request->getMethod(),
@@ -259,7 +258,7 @@ public function baseString($request, $oauthValues)
* @param \Psr\Http\Message\UriInterface $uri Uri object to build a normalized version of.
* @return string Normalized URL
*/
- protected function _normalizedUrl($uri)
+ protected function _normalizedUrl(UriInterface $uri): string
{
$out = $uri->getScheme() . '://';
$out .= strtolower($uri->getHost());
@@ -280,19 +279,14 @@ protected function _normalizedUrl($uri)
* @param array $oauthValues Oauth values.
* @return string sorted and normalized values
*/
- protected function _normalizedParams($request, $oauthValues)
+ protected function _normalizedParams(Request $request, array $oauthValues): string
{
- $query = parse_url($request->getUri(), PHP_URL_QUERY);
- parse_str($query, $queryArgs);
+ $query = parse_url((string)$request->getUri(), PHP_URL_QUERY);
+ parse_str((string)$query, $queryArgs);
$post = [];
- $body = $request->body();
- if (is_string($body) && $request->getHeaderLine('content-type') === 'application/x-www-form-urlencoded') {
- parse_str($body, $post);
- }
- if (is_array($body)) {
- $post = $body;
- }
+ $body = (string)$request->getBody();
+ parse_str($body, $post);
$args = array_merge($queryArgs, $oauthValues, $post);
$pairs = $this->_normalizeData($args);
@@ -313,7 +307,7 @@ protected function _normalizedParams($request, $oauthValues)
* @see https://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
* @return array
*/
- protected function _normalizeData($args, $path = '')
+ protected function _normalizeData(array $args, string $path = ''): array
{
$data = [];
foreach ($args as $key => $value) {
@@ -344,12 +338,12 @@ protected function _normalizeData($args, $path = '')
* @param array $data The oauth_* values to build
* @return string
*/
- protected function _buildAuth($data)
+ protected function _buildAuth(array $data): string
{
$out = 'OAuth ';
$params = [];
foreach ($data as $key => $value) {
- $params[] = $key . '="' . $this->_encode($value) . '"';
+ $params[] = $key . '="' . $this->_encode((string)$value) . '"';
}
$out .= implode(',', $params);
@@ -362,11 +356,8 @@ protected function _buildAuth($data)
* @param string $value Value to encode.
* @return string
*/
- protected function _encode($value)
+ protected function _encode(string $value): string
{
return str_replace(['%7E', '+'], ['~', ' '], rawurlencode($value));
}
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\Auth\Oauth', 'Cake\Network\Http\Auth\Oauth');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/CookieCollection.php b/app/vendor/cakephp/cakephp/src/Http/Client/CookieCollection.php
deleted file mode 100644
index 387f63924..000000000
--- a/app/vendor/cakephp/cakephp/src/Http/Client/CookieCollection.php
+++ /dev/null
@@ -1,120 +0,0 @@
-getHeader('Set-Cookie');
- $cookies = $this->parseSetCookieHeader($header);
- $cookies = $this->setRequestDefaults($cookies, $host, $path);
- foreach ($cookies as $cookie) {
- $this->cookies[$cookie->getId()] = $cookie;
- }
- $this->removeExpiredCookies($host, $path);
- }
-
- /**
- * Get stored cookies for a URL.
- *
- * Finds matching stored cookies and returns a simple array
- * of name => value
- *
- * @param string $url The URL to find cookies for.
- * @return array
- */
- public function get($url)
- {
- $path = parse_url($url, PHP_URL_PATH) ?: '/';
- $host = parse_url($url, PHP_URL_HOST);
- $scheme = parse_url($url, PHP_URL_SCHEME);
-
- return $this->findMatchingCookies($scheme, $host, $path);
- }
-
- /**
- * Get all the stored cookies as arrays.
- *
- * @return array
- */
- public function getAll()
- {
- $out = [];
- foreach ($this->cookies as $cookie) {
- $out[] = $this->convertCookieToArray($cookie);
- }
-
- return $out;
- }
-
- /**
- * Convert the cookie into an array of its properties.
- *
- * Primarily useful where backwards compatibility is needed.
- *
- * @param \Cake\Http\Cookie\CookieInterface $cookie Cookie object.
- * @return array
- */
- protected function convertCookieToArray(CookieInterface $cookie)
- {
- return [
- 'name' => $cookie->getName(),
- 'value' => $cookie->getValue(),
- 'path' => $cookie->getPath(),
- 'domain' => $cookie->getDomain(),
- 'secure' => $cookie->isSecure(),
- 'httponly' => $cookie->isHttpOnly(),
- 'expires' => $cookie->getExpiresTimestamp(),
- ];
- }
-}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\CookieCollection', 'Cake\Network\Http\CookieCollection');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Exception/ClientException.php b/app/vendor/cakephp/cakephp/src/Http/Client/Exception/ClientException.php
new file mode 100644
index 000000000..c3f77459a
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Exception/ClientException.php
@@ -0,0 +1,26 @@
+request = $request;
+ parent::__construct($message, 0, $previous);
+ }
+
+ /**
+ * Returns the request.
+ *
+ * The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
+ *
+ * @return \Psr\Http\Message\RequestInterface
+ */
+ public function getRequest(): RequestInterface
+ {
+ return $this->request;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Exception/RequestException.php b/app/vendor/cakephp/cakephp/src/Http/Client/Exception/RequestException.php
new file mode 100644
index 000000000..ab8b06874
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Exception/RequestException.php
@@ -0,0 +1,62 @@
+request = $request;
+ parent::__construct($message, 0, $previous);
+ }
+
+ /**
+ * Returns the request.
+ *
+ * The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
+ *
+ * @return \Psr\Http\Message\RequestInterface
+ */
+ public function getRequest(): RequestInterface
+ {
+ return $this->request;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/FormData.php b/app/vendor/cakephp/cakephp/src/Http/Client/FormData.php
index 2b6124ae5..0e87c1fbf 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/FormData.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/FormData.php
@@ -1,4 +1,6 @@
_boundary) {
return $this->_boundary;
}
- $this->_boundary = md5(uniqid(time()));
+ $this->_boundary = md5(uniqid((string)time()));
return $this->_boundary;
}
@@ -75,7 +77,7 @@ public function boundary()
* @param string $value The value to add.
* @return \Cake\Http\Client\FormDataPart
*/
- public function newPart($name, $value)
+ public function newPart(string $name, string $value): FormDataPart
{
return new FormDataPart($name, $value);
}
@@ -89,22 +91,24 @@ public function newPart($name, $value)
* If the $value is an array, multiple parts will be added.
* Files will be read from their current position and saved in memory.
*
- * @param string|\Cake\Http\Client\FormData $name The name of the part to add,
+ * @param string|\Cake\Http\Client\FormDataPart $name The name of the part to add,
* or the part data object.
* @param mixed $value The value for the part.
* @return $this
*/
public function add($name, $value = null)
{
- if (is_array($value)) {
- $this->addRecursive($name, $value);
- } elseif (is_resource($value)) {
- $this->addFile($name, $value);
- } elseif ($name instanceof FormDataPart && $value === null) {
+ if (is_string($name)) {
+ if (is_array($value)) {
+ $this->addRecursive($name, $value);
+ } elseif (is_resource($value)) {
+ $this->addFile($name, $value);
+ } else {
+ $this->_parts[] = $this->newPart($name, (string)$value);
+ }
+ } else {
$this->_hasComplexPart = true;
$this->_parts[] = $name;
- } else {
- $this->_parts[] = $this->newPart($name, $value);
}
return $this;
@@ -135,7 +139,7 @@ public function addMany(array $data)
* @param mixed $value Either a string filename, or a filehandle.
* @return \Cake\Http\Client\FormDataPart
*/
- public function addFile($name, $value)
+ public function addFile(string $name, $value): FormDataPart
{
$this->_hasFile = true;
@@ -173,7 +177,7 @@ public function addFile($name, $value)
* @param mixed $value The value to add.
* @return void
*/
- public function addRecursive($name, $value)
+ public function addRecursive(string $name, $value): void
{
foreach ($value as $key => $value) {
$key = $name . '[' . $key . ']';
@@ -186,7 +190,7 @@ public function addRecursive($name, $value)
*
* @return int
*/
- public function count()
+ public function count(): int
{
return count($this->_parts);
}
@@ -197,7 +201,7 @@ public function count()
*
* @return bool Whether or not there is a file in this payload.
*/
- public function hasFile()
+ public function hasFile(): bool
{
return $this->_hasFile;
}
@@ -211,7 +215,7 @@ public function hasFile()
*
* @return bool Whether or not the payload is multipart.
*/
- public function isMultipart()
+ public function isMultipart(): bool
{
return $this->hasFile() || $this->_hasComplexPart;
}
@@ -224,7 +228,7 @@ public function isMultipart()
*
* @return string
*/
- public function contentType()
+ public function contentType(): string
{
if (!$this->isMultipart()) {
return 'application/x-www-form-urlencoded';
@@ -239,7 +243,7 @@ public function contentType()
*
* @return string
*/
- public function __toString()
+ public function __toString(): string
{
if ($this->isMultipart()) {
$boundary = $this->boundary();
@@ -261,6 +265,3 @@ public function __toString()
return http_build_query($data);
}
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\FormData', 'Cake\Network\Http\FormData');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/FormDataPart.php b/app/vendor/cakephp/cakephp/src/Http/Client/FormDataPart.php
index d30f778d3..002c9ca6f 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/FormDataPart.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/FormDataPart.php
@@ -1,4 +1,6 @@
_name = $name;
$this->_value = $value;
@@ -106,14 +107,15 @@ public function __construct($name, $value, $disposition = 'form-data', $charset
* header from being added.
*
* @param string|null $disposition Use null to get/string to set.
- * @return string|null
+ * @return string
*/
- public function disposition($disposition = null)
+ public function disposition(?string $disposition = null): string
{
if ($disposition === null) {
return $this->_disposition;
}
- $this->_disposition = $disposition;
+
+ return $this->_disposition = $disposition;
}
/**
@@ -122,12 +124,13 @@ public function disposition($disposition = null)
* @param string|null $id The content id.
* @return string|null
*/
- public function contentId($id = null)
+ public function contentId(?string $id = null): ?string
{
if ($id === null) {
return $this->_contentId;
}
- $this->_contentId = $id;
+
+ return $this->_contentId = $id;
}
/**
@@ -139,12 +142,13 @@ public function contentId($id = null)
* @param string|null $filename Use null to get/string to set.
* @return string|null
*/
- public function filename($filename = null)
+ public function filename(?string $filename = null): ?string
{
if ($filename === null) {
return $this->_filename;
}
- $this->_filename = $filename;
+
+ return $this->_filename = $filename;
}
/**
@@ -153,12 +157,13 @@ public function filename($filename = null)
* @param string|null $type Use null to get/string to set.
* @return string|null
*/
- public function type($type)
+ public function type(?string $type): ?string
{
if ($type === null) {
return $this->_type;
}
- $this->_type = $type;
+
+ return $this->_type = $type;
}
/**
@@ -169,12 +174,13 @@ public function type($type)
* @param string|null $type The type of encoding the value has.
* @return string|null
*/
- public function transferEncoding($type)
+ public function transferEncoding(?string $type): ?string
{
if ($type === null) {
return $this->_transferEncoding;
}
- $this->_transferEncoding = $type;
+
+ return $this->_transferEncoding = $type;
}
/**
@@ -182,7 +188,7 @@ public function transferEncoding($type)
*
* @return string
*/
- public function name()
+ public function name(): string
{
return $this->_name;
}
@@ -192,7 +198,7 @@ public function name()
*
* @return string
*/
- public function value()
+ public function value(): string
{
return $this->_value;
}
@@ -204,7 +210,7 @@ public function value()
*
* @return string
*/
- public function __toString()
+ public function __toString(): string
{
$out = '';
if ($this->_disposition) {
@@ -227,7 +233,7 @@ public function __toString()
$out .= 'Content-ID: <' . $this->_contentId . ">\r\n";
}
$out .= "\r\n";
- $out .= (string)$this->_value;
+ $out .= $this->_value;
return $out;
}
@@ -242,7 +248,7 @@ public function __toString()
* @param string $value The value of the header parameter
* @return string
*/
- protected function _headerParameterToString($name, $value)
+ protected function _headerParameterToString(string $name, string $value): string
{
$transliterated = Text::transliterate(str_replace('"', '', $value));
$return = sprintf('%s="%s"', $name, $transliterated);
@@ -253,6 +259,3 @@ protected function _headerParameterToString($name, $value)
return $return;
}
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\FormDataPart', 'Cake\Network\Http\FormData\Part');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Message.php b/app/vendor/cakephp/cakephp/src/Http/Client/Message.php
index 9ad5dc227..a23282d20 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Message.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Message.php
@@ -1,4 +1,6 @@
headers;
- }
-
/**
* Get all cookies
*
* @return array
*/
- public function cookies()
+ public function cookies(): array
{
return $this->_cookies;
}
-
- /**
- * Get/set the body for the message.
- *
- * @param string|null $body The body for the request. Leave null for get
- * @return mixed Either $this or the body value.
- */
- public function body($body = null)
- {
- if ($body === null) {
- return $this->_body;
- }
- $this->_body = $body;
-
- return $this;
- }
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\Message', 'Cake\Network\Http\Message');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Request.php b/app/vendor/cakephp/cakephp/src/Http/Client/Request.php
index 1d259c538..9ae13cb08 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Request.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Request.php
@@ -1,4 +1,6 @@
validateMethod($method);
- $this->method = $method;
+ $this->setMethod($method);
$this->uri = $this->createUri($url);
$headers += [
'Connection' => 'close',
'User-Agent' => 'CakePHP',
];
$this->addHeaders($headers);
- $this->body($data);
- }
-
- /**
- * Get/Set the HTTP method.
- *
- * *Warning* This method mutates the request in-place for backwards
- * compatibility reasons, and is not part of the PSR7 interface.
- *
- * @param string|null $method The method for the request.
- * @return $this|string Either this or the current method.
- * @throws \Cake\Core\Exception\Exception On invalid methods.
- * @deprecated 3.3.0 Use getMethod() and withMethod() instead.
- */
- public function method($method = null)
- {
- deprecationWarning(
- 'Request::method() is deprecated. ' .
- 'Use getMethod() and withMethod() instead.'
- );
-
- if ($method === null) {
- return $this->method;
- }
- $name = get_called_class() . '::METHOD_' . strtoupper($method);
- if (!defined($name)) {
- throw new Exception('Invalid method type');
- }
- $this->method = $method;
-
- return $this;
- }
-
- /**
- * Get/Set the url for the request.
- *
- * *Warning* This method mutates the request in-place for backwards
- * compatibility reasons, and is not part of the PSR7 interface.
- *
- * @param string|null $url The url for the request. Leave null for get
- * @return $this|string Either $this or the url value.
- * @deprecated 3.3.0 Use getUri() and withUri() instead.
- */
- public function url($url = null)
- {
- deprecationWarning(
- 'Request::url() is deprecated. ' .
- 'Use getUri() and withUri() instead.'
- );
-
- if ($url === null) {
- return '' . $this->getUri();
- }
- $this->uri = $this->createUri($url);
-
- return $this;
- }
-
- /**
- * Get/Set headers into the request.
- *
- * You can get the value of a header, or set one/many headers.
- * Headers are set / fetched in a case insensitive way.
- *
- * ### Getting headers
- *
- * ```
- * $request->header('Content-Type');
- * ```
- *
- * ### Setting one header
- *
- * ```
- * $request->header('Content-Type', 'application/json');
- * ```
- *
- * ### Setting multiple headers
- *
- * ```
- * $request->header(['Connection' => 'close', 'User-Agent' => 'CakePHP']);
- * ```
- *
- * *Warning* This method mutates the request in-place for backwards
- * compatibility reasons, and is not part of the PSR7 interface.
- *
- * @param string|array|null $name The name to get, or array of multiple values to set.
- * @param string|null $value The value to set for the header.
- * @return mixed Either $this when setting or header value when getting.
- * @deprecated 3.3.0 Use withHeader() and getHeaderLine() instead.
- */
- public function header($name = null, $value = null)
- {
- deprecationWarning(
- 'Request::header() is deprecated. ' .
- 'Use withHeader() and getHeaderLine() instead.'
- );
- if ($value === null && is_string($name)) {
- $val = $this->getHeaderLine($name);
- if ($val === '') {
- return null;
- }
-
- return $val;
- }
-
- if ($value !== null && !is_array($name)) {
- $name = [$name => $value];
+ if ($data === null) {
+ $this->stream = new Stream('php://memory', 'rw');
+ } else {
+ $this->setContent($data);
}
- $this->addHeaders($name);
-
- return $this;
}
/**
@@ -168,7 +62,7 @@ public function header($name = null, $value = null)
* @param array $headers The headers to add.
* @return void
*/
- protected function addHeaders(array $headers)
+ protected function addHeaders(array $headers): void
{
foreach ($headers as $key => $val) {
$normalized = strtolower($key);
@@ -178,110 +72,27 @@ protected function addHeaders(array $headers)
}
/**
- * Get/Set cookie values.
- *
- * ### Getting a cookie
- *
- * ```
- * $request->cookie('session');
- * ```
- *
- * ### Setting one cookie
- *
- * ```
- * $request->cookie('session', '123456');
- * ```
- *
- * ### Setting multiple headers
- *
- * ```
- * $request->cookie(['test' => 'value', 'split' => 'banana']);
- * ```
- *
- * @param string $name The name of the cookie to get/set
- * @param string|null $value Either the value or null when getting values.
- * @return mixed Either $this or the cookie value.
- * @deprecated 3.5.0 No longer used. CookieCollections now add `Cookie` header to the request
- * before sending. Use Cake\Http\Cookie\CookieCollection::addToRequest() to make adding cookies
- * to a request easier.
- */
- public function cookie($name, $value = null)
- {
- deprecationWarning(
- 'Request::cookie() is deprecated. ' .
- 'The Client internals now add the required `Cookie` header to the ' .
- 'request before sending. Use Cake\Http\Cookie\CookieCollection::addToRequest() ' .
- 'to make adding cookies to a request easier.'
- );
-
- if ($value === null && is_string($name)) {
- return isset($this->_cookies[$name]) ? $this->_cookies[$name] : null;
- }
- if (is_string($name) && is_string($value)) {
- $name = [$name => $value];
- }
- foreach ($name as $key => $val) {
- $this->_cookies[$key] = $val;
- }
-
- return $this;
- }
-
- /**
- * Get/Set HTTP version.
- *
- * *Warning* This method mutates the request in-place for backwards
- * compatibility reasons, and is not part of the PSR7 interface.
- *
- * @param string|null $version The HTTP version.
- * @return $this|string Either $this or the HTTP version.
- * @deprecated 3.3.0 Use getProtocolVersion() and withProtocolVersion() instead.
- */
- public function version($version = null)
- {
- deprecationWarning(
- 'Request::version() is deprecated. ' .
- 'Use getProtocolVersion() and withProtocolVersion() instead.'
- );
-
- if ($version === null) {
- return $this->protocol;
- }
-
- $this->protocol = $version;
-
- return $this;
- }
-
- /**
- * Get/set the body/payload for the message.
+ * Set the body/payload for the message.
*
* Array data will be serialized with Cake\Http\FormData,
* and the content-type will be set.
*
- * @param string|array|null $body The body for the request. Leave null for get
- * @return mixed Either $this or the body value.
+ * @param string|array $content The body for the request.
+ * @return $this
*/
- public function body($body = null)
+ protected function setContent($content)
{
- if ($body === null) {
- $body = $this->getBody();
-
- return $body ? $body->__toString() : '';
- }
- if (is_array($body)) {
+ if (is_array($content)) {
$formData = new FormData();
- $formData->addMany($body);
+ $formData->addMany($content);
$this->addHeaders(['Content-Type' => $formData->contentType()]);
- $body = (string)$formData;
+ $content = (string)$formData;
}
+
$stream = new Stream('php://memory', 'rw');
- $stream->write($body);
+ $stream->write($content);
$this->stream = $stream;
return $this;
}
}
-
-// @deprecated 3.4.0 Add backwards compact alias.
-class_alias('Cake\Http\Client\Request', 'Cake\Network\Http\Request');
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Response.php b/app/vendor/cakephp/cakephp/src/Http/Client/Response.php
index 3c9be24e6..ee41e4f63 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Response.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Response.php
@@ -1,4 +1,6 @@
property names for __get()
- *
- * @var array
- */
- protected $_exposedProperties = [
- 'cookies' => '_getCookies',
- 'body' => '_getBody',
- 'code' => 'code',
- 'json' => '_getJson',
- 'xml' => '_getXml',
- 'headers' => '_getHeaders',
- ];
-
- /**
- * Map of deprecated magic properties.
- *
- * @var array
- * @internal
- */
- protected $_deprecatedMagicProperties = [
- 'cookies' => 'getCookies()',
- 'body' => 'getStringBody()',
- 'json' => 'getJson()',
- 'xml' => 'getXml()',
- 'headers' => 'getHeaders()',
- ];
-
/**
* Constructor
*
* @param array $headers Unparsed headers.
* @param string $body The response body.
*/
- public function __construct($headers = [], $body = '')
+ public function __construct(array $headers = [], string $body = '')
{
$this->_parseHeaders($headers);
if ($this->getHeaderLine('Content-Encoding') === 'gzip') {
@@ -175,7 +147,7 @@ public function __construct($headers = [], $body = '')
* @return string
* @throws \RuntimeException When attempting to decode gzip content without gzinflate.
*/
- protected function _decodeGzipBody($body)
+ protected function _decodeGzipBody(string $body): string
{
if (!function_exists('gzinflate')) {
throw new RuntimeException('Cannot decompress gzip response body without gzinflate()');
@@ -189,6 +161,8 @@ protected function _decodeGzipBody($body)
if (substr($body, $offset, 1) === "\x08") {
return gzinflate(substr($body, $offset + 8));
}
+
+ throw new RuntimeException('Invalid gzip response');
}
/**
@@ -200,9 +174,9 @@ protected function _decodeGzipBody($body)
* @param array $headers Headers to parse.
* @return void
*/
- protected function _parseHeaders($headers)
+ protected function _parseHeaders(array $headers): void
{
- foreach ($headers as $key => $value) {
+ foreach ($headers as $value) {
if (substr($value, 0, 5) === 'HTTP/') {
preg_match('/HTTP\/([\d.]+) ([0-9]+)(.*)/i', $value, $matches);
$this->protocol = $matches[1];
@@ -213,7 +187,7 @@ protected function _parseHeaders($headers)
if (strpos($value, ':') === false) {
continue;
}
- list($name, $value) = explode(':', $value, 2);
+ [$name, $value] = explode(':', $value, 2);
$value = trim($value);
$name = trim($name);
@@ -229,21 +203,13 @@ protected function _parseHeaders($headers)
}
/**
- * Check if the response was OK
+ * Check if the response status code was in the 2xx/3xx range
*
* @return bool
*/
- public function isOk()
+ public function isOk(): bool
{
- $codes = [
- static::STATUS_OK,
- static::STATUS_CREATED,
- static::STATUS_ACCEPTED,
- static::STATUS_NON_AUTHORITATIVE_INFORMATION,
- static::STATUS_NO_CONTENT,
- ];
-
- return in_array($this->code, $codes);
+ return $this->code >= 200 && $this->code <= 399;
}
/**
@@ -251,7 +217,7 @@ public function isOk()
*
* @return bool
*/
- public function isSuccess()
+ public function isSuccess(): bool
{
return $this->code >= 200 && $this->code <= 299;
}
@@ -261,7 +227,7 @@ public function isSuccess()
*
* @return bool
*/
- public function isRedirect()
+ public function isRedirect(): bool
{
$codes = [
static::STATUS_MOVED_PERMANENTLY,
@@ -270,44 +236,26 @@ public function isRedirect()
static::STATUS_TEMPORARY_REDIRECT,
];
- return (
- in_array($this->code, $codes) &&
- $this->getHeaderLine('Location')
- );
+ return in_array($this->code, $codes, true) &&
+ $this->getHeaderLine('Location');
}
/**
- * Get the status code from the response
- *
- * @return int
- * @deprecated 3.3.0 Use getStatusCode() instead.
- */
- public function statusCode()
- {
- deprecationWarning(
- 'Response::statusCode() is deprecated. ' .
- 'Use Response::getStatusCode() instead.'
- );
-
- return $this->code;
- }
-
- /**
- * {@inheritdoc}
+ * {@inheritDoc}
*
* @return int The status code.
*/
- public function getStatusCode()
+ public function getStatusCode(): int
{
- return $this->code;
+ return (int)$this->code;
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*
* @param int $code The status code to set.
* @param string $reasonPhrase The status reason phrase.
- * @return $this A copy of the current object with an updated status code.
+ * @return static A copy of the current object with an updated status code.
*/
public function withStatus($code, $reasonPhrase = '')
{
@@ -319,37 +267,21 @@ public function withStatus($code, $reasonPhrase = '')
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*
* @return string The current reason phrase.
*/
- public function getReasonPhrase()
+ public function getReasonPhrase(): string
{
return $this->reasonPhrase;
}
- /**
- * Get the encoding if it was set.
- *
- * @return string|null
- * @deprecated 3.3.0 Use getEncoding() instead.
- */
- public function encoding()
- {
- deprecationWarning(
- 'Response::encoding() is deprecated. ' .
- 'Use Response::getEncoding() instead.'
- );
-
- return $this->getEncoding();
- }
-
/**
* Get the encoding if it was set.
*
* @return string|null
*/
- public function getEncoding()
+ public function getEncoding(): ?string
{
$content = $this->getHeaderLine('content-type');
if (!$content) {
@@ -363,72 +295,12 @@ public function getEncoding()
return $matches[1];
}
- /**
- * Read single/multiple header value(s) out.
- *
- * @param string|null $name The name of the header you want. Leave
- * null to get all headers.
- * @return mixed Null when the header doesn't exist. An array
- * will be returned when getting all headers or when getting
- * a header that had multiple values set. Otherwise a string
- * will be returned.
- * @deprecated 3.3.0 Use getHeader() and getHeaderLine() instead.
- */
- public function header($name = null)
- {
- deprecationWarning(
- 'Response::header() is deprecated. ' .
- 'Use Response::getHeader() and getHeaderLine() instead.'
- );
-
- if ($name === null) {
- return $this->_getHeaders();
- }
- $header = $this->getHeader($name);
- if (count($header) === 1) {
- return $header[0];
- }
-
- return $header;
- }
-
- /**
- * Read single/multiple cookie values out.
- *
- * *Note* This method will only provide access to cookies that
- * were added as part of the constructor. If cookies are added post
- * construction they will not be accessible via this method.
- *
- * @param string|null $name The name of the cookie you want. Leave
- * null to get all cookies.
- * @param bool $all Get all parts of the cookie. When false only
- * the value will be returned.
- * @return mixed
- * @deprecated 3.3.0 Use getCookie(), getCookieData() or getCookies() instead.
- */
- public function cookie($name = null, $all = false)
- {
- deprecationWarning(
- 'Response::cookie() is deprecated. ' .
- 'Use Response::getCookie(), getCookieData() or getCookies() instead.'
- );
-
- if ($name === null) {
- return $this->getCookies();
- }
- if ($all) {
- return $this->getCookieData($name);
- }
-
- return $this->getCookie($name);
- }
-
/**
* Get the all cookie data.
*
* @return array The cookie data
*/
- public function getCookies()
+ public function getCookies(): array
{
return $this->_getCookies();
}
@@ -441,7 +313,7 @@ public function getCookies()
*
* @return \Cake\Http\Cookie\CookieCollection
*/
- public function getCookieCollection()
+ public function getCookieCollection(): CookieCollection
{
$this->buildCookieCollection();
@@ -454,9 +326,10 @@ public function getCookieCollection()
* @param string $name The name of the cookie value.
* @return string|array|null Either the cookie's value or null when the cookie is undefined.
*/
- public function getCookie($name)
+ public function getCookie(string $name)
{
$this->buildCookieCollection();
+
if (!$this->cookies->has($name)) {
return null;
}
@@ -470,7 +343,7 @@ public function getCookie($name)
* @param string $name The name of the cookie value.
* @return array|null Either the cookie's data or null when the cookie is undefined.
*/
- public function getCookieData($name)
+ public function getCookieData(string $name): ?array
{
$this->buildCookieCollection();
@@ -478,31 +351,7 @@ public function getCookieData($name)
return null;
}
- $cookie = $this->cookies->get($name);
-
- return $this->convertCookieToArray($cookie);
- }
-
- /**
- * Convert the cookie into an array of its properties.
- *
- * This method is compatible with older client code that
- * expects date strings instead of timestamps.
- *
- * @param \Cake\Http\Cookie\CookieInterface $cookie Cookie object.
- * @return array
- */
- protected function convertCookieToArray(CookieInterface $cookie)
- {
- return [
- 'name' => $cookie->getName(),
- 'value' => $cookie->getValue(),
- 'path' => $cookie->getPath(),
- 'domain' => $cookie->getDomain(),
- 'secure' => $cookie->isSecure(),
- 'httponly' => $cookie->isHttpOnly(),
- 'expires' => $cookie->getFormattedExpires(),
- ];
+ return $this->cookies->get($name)->toArray();
}
/**
@@ -510,12 +359,12 @@ protected function convertCookieToArray(CookieInterface $cookie)
*
* @return void
*/
- protected function buildCookieCollection()
+ protected function buildCookieCollection(): void
{
- if ($this->cookies) {
+ if ($this->cookies !== null) {
return;
}
- $this->cookies = CookiesCollection::createFromHeader($this->getHeader('Set-Cookie'));
+ $this->cookies = CookieCollection::createFromHeader($this->getHeader('Set-Cookie'));
}
/**
@@ -523,64 +372,18 @@ protected function buildCookieCollection()
*
* @return array Array of Cookie data.
*/
- protected function _getCookies()
+ protected function _getCookies(): array
{
$this->buildCookieCollection();
- $cookies = [];
- foreach ($this->cookies as $cookie) {
- $cookies[$cookie->getName()] = $this->convertCookieToArray($cookie);
- }
-
- return $cookies;
- }
-
- /**
- * Get the HTTP version used.
- *
- * @return string
- * @deprecated 3.3.0 Use getProtocolVersion()
- */
- public function version()
- {
- deprecationWarning(
- 'Response::version() is deprecated. ' .
- 'Use Response::getProtocolVersion() instead.'
- );
-
- return $this->protocol;
- }
-
- /**
- * Get the response body.
- *
- * By passing in a $parser callable, you can get the decoded
- * response content back.
- *
- * For example to get the json data as an object:
- *
- * ```
- * $body = $response->getJson();
- * ```
- *
- * @param callable|null $parser The callback to use to decode
- * the response body.
- * @return mixed The response body.
- * @deprecated 3.7.0 Use getStringBody()/getJson()/getXml() instead.
- */
- public function body($parser = null)
- {
- deprecationWarning(
- 'Response::body() is deprecated. Use getStringBody()/getJson()/getXml() instead.'
- );
-
- $stream = $this->stream;
- $stream->rewind();
- if ($parser) {
- return $parser($stream->getContents());
+ $out = [];
+ /** @var \Cake\Http\Cookie\Cookie[] $cookies */
+ $cookies = $this->cookies;
+ foreach ($cookies as $cookie) {
+ $out[$cookie->getName()] = $cookie->toArray();
}
- return $stream->getContents();
+ return $out;
}
/**
@@ -588,7 +391,7 @@ public function body($parser = null)
*
* @return string
*/
- public function getStringBody()
+ public function getStringBody(): string
{
return $this->_getBody();
}
@@ -596,7 +399,7 @@ public function getStringBody()
/**
* Get the response body as JSON decoded data.
*
- * @return array|null
+ * @return mixed
*/
public function getJson()
{
@@ -606,7 +409,7 @@ public function getJson()
/**
* Get the response body as JSON decoded data.
*
- * @return array|null
+ * @return mixed
*/
protected function _getJson()
{
@@ -622,7 +425,7 @@ protected function _getJson()
*
* @return \SimpleXMLElement|null
*/
- public function getXml()
+ public function getXml(): ?SimpleXMLElement
{
return $this->_getXml();
}
@@ -632,9 +435,9 @@ public function getXml()
*
* @return \SimpleXMLElement|null
*/
- protected function _getXml()
+ protected function _getXml(): ?SimpleXMLElement
{
- if ($this->_xml) {
+ if ($this->_xml !== null) {
return $this->_xml;
}
libxml_use_internal_errors();
@@ -651,9 +454,9 @@ protected function _getXml()
/**
* Provides magic __get() support.
*
- * @return array
+ * @return string[]
*/
- protected function _getHeaders()
+ protected function _getHeaders(): array
{
$out = [];
foreach ($this->headers as $key => $values) {
@@ -668,79 +471,10 @@ protected function _getHeaders()
*
* @return string
*/
- protected function _getBody()
+ protected function _getBody(): string
{
$this->stream->rewind();
return $this->stream->getContents();
}
-
- /**
- * Read values as properties.
- *
- * @param string $name Property name.
- * @return mixed
- */
- public function __get($name)
- {
- if (!isset($this->_exposedProperties[$name])) {
- return false;
- }
- $key = $this->_exposedProperties[$name];
- if (substr($key, 0, 4) === '_get') {
- deprecationWarning(sprintf(
- 'Response::%s is deprecated. Use Response::%s instead.',
- $name,
- $this->_deprecatedMagicProperties[$name]
- ));
-
- return $this->{$key}();
- }
-
- if ($key === 'code') {
- deprecationWarning(
- 'Response::code() is deprecated. ' .
- 'Use Response::getStatusCode() instead.'
- );
- }
-
- return $this->{$key};
- }
-
- /**
- * isset/empty test with -> syntax.
- *
- * @param string $name Property name.
- * @return bool
- */
- public function __isset($name)
- {
- if (!isset($this->_exposedProperties[$name])) {
- return false;
- }
- $key = $this->_exposedProperties[$name];
- if (substr($key, 0, 4) === '_get') {
- deprecationWarning(sprintf(
- 'Response::%s is deprecated. Use Response::%s instead.',
- $name,
- $this->_deprecatedMagicProperties[$name]
- ));
-
- $val = $this->{$key}();
-
- return $val !== null;
- }
-
- if ($key === 'code') {
- deprecationWarning(
- 'Response::code() is deprecated. ' .
- 'Use Response::getStatusCode() instead.'
- );
- }
-
- return isset($this->{$key});
- }
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Client\Response', 'Cake\Network\Http\Response');
diff --git a/app/vendor/cakephp/cakephp/src/Http/ControllerFactory.php b/app/vendor/cakephp/cakephp/src/Http/ControllerFactory.php
index 6d5b06301..4e01026b8 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ControllerFactory.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ControllerFactory.php
@@ -1,112 +1,10 @@
getControllerClass($request);
- if (!$className) {
- $this->missingController($request);
- }
- $reflection = new ReflectionClass($className);
- if ($reflection->isAbstract() || $reflection->isInterface()) {
- $this->missingController($request);
- }
-
- /** @var \Cake\Controller\Controller $controller */
- $controller = $reflection->newInstance($request, $response);
-
- return $controller;
- }
-
- /**
- * Determine the controller class name based on current request and controller param
- *
- * @param \Cake\Http\ServerRequest $request The request to build a controller for.
- * @return string|null
- */
- public function getControllerClass(ServerRequest $request)
- {
- $pluginPath = $controller = null;
- $namespace = 'Controller';
- if ($request->getParam('controller')) {
- $controller = $request->getParam('controller');
- }
- if ($request->getParam('plugin')) {
- $pluginPath = $request->getParam('plugin') . '.';
- }
- if ($request->getParam('prefix')) {
- if (strpos($request->getParam('prefix'), '/') === false) {
- $namespace .= '/' . Inflector::camelize($request->getParam('prefix'));
- } else {
- $prefixes = array_map(
- 'Cake\Utility\Inflector::camelize',
- explode('/', $request->getParam('prefix'))
- );
- $namespace .= '/' . implode('/', $prefixes);
- }
- }
- $firstChar = substr($controller, 0, 1);
-
- // Disallow plugin short forms, / and \\ from
- // controller names as they allow direct references to
- // be created.
- if (
- strpos($controller, '\\') !== false ||
- strpos($controller, '/') !== false ||
- strpos($controller, '.') !== false ||
- $firstChar === strtolower($firstChar)
- ) {
- $this->missingController($request);
- }
-
- return App::className($pluginPath . $controller, $namespace, 'Controller') ?: null;
- }
-
- /**
- * Throws an exception when a controller is missing.
- *
- * @param \Cake\Http\ServerRequest $request The request.
- * @throws \Cake\Routing\Exception\MissingControllerException
- * @return void
- */
- protected function missingController($request)
- {
- throw new MissingControllerException([
- 'class' => $request->getParam('controller'),
- 'plugin' => $request->getParam('plugin'),
- 'prefix' => $request->getParam('prefix'),
- '_ext' => $request->getParam('_ext'),
- ]);
- }
-}
+declare(strict_types=1);
+
+class_alias(
+ 'Cake\Controller\ControllerFactory',
+ 'Cake\Http\ControllerFactory'
+);
+deprecationWarning(
+ 'Use Cake\Controller\ControllerFactory instead of Cake\Http\ControllerFactory.'
+);
diff --git a/app/vendor/cakephp/cakephp/src/Http/ControllerFactoryInterface.php b/app/vendor/cakephp/cakephp/src/Http/ControllerFactoryInterface.php
new file mode 100644
index 000000000..9628ad69c
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/ControllerFactoryInterface.php
@@ -0,0 +1,47 @@
+withValue('0');
* ```
*
- * @link https://tools.ietf.org/html/rfc6265
+ * @link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03
* @link https://en.wikipedia.org/wiki/HTTP_cookie
* @see \Cake\Http\Cookie\CookieCollection for working with collections of cookies.
* @see \Cake\Http\Response::getCookieCollection() for working with response cookies.
@@ -110,6 +112,21 @@ class Cookie implements CookieInterface
*/
protected $sameSite = null;
+ /**
+ * Default attributes for a cookie.
+ *
+ * @var array
+ * @see \Cake\Cookie\Cookie::setDefaults()
+ */
+ protected static $defaults = [
+ 'expires' => null,
+ 'path' => '/',
+ 'domain' => '',
+ 'secure' => false,
+ 'httponly' => false,
+ 'samesite' => null,
+ ];
+
/**
* Constructor
*
@@ -121,62 +138,208 @@ class Cookie implements CookieInterface
* @param string $name Cookie name
* @param string|array $value Value of the cookie
* @param \DateTime|\DateTimeImmutable|null $expiresAt Expiration time and date
- * @param string $path Path
- * @param string $domain Domain
- * @param bool $secure Is secure
- * @param bool $httpOnly HTTP Only
+ * @param string|null $path Path
+ * @param string|null $domain Domain
+ * @param bool|null $secure Is secure
+ * @param bool|null $httpOnly HTTP Only
* @param string|null $sameSite Samesite
- * @throws \InvalidArgumentException If an invalid value is passed for any of the arguments.
*/
public function __construct(
- $name,
+ string $name,
$value = '',
- $expiresAt = null,
- $path = '/',
- $domain = '',
- $secure = false,
- $httpOnly = false,
- $sameSite = null
+ ?DateTimeInterface $expiresAt = null,
+ ?string $path = null,
+ ?string $domain = null,
+ ?bool $secure = null,
+ ?bool $httpOnly = null,
+ ?string $sameSite = null
) {
$this->validateName($name);
$this->name = $name;
$this->_setValue($value);
- $this->validateString($domain);
- $this->domain = $domain;
-
- $this->validateBool($httpOnly);
- $this->httpOnly = $httpOnly;
-
- $this->validateString($path);
- $this->path = $path;
-
- $this->validateBool($secure);
- $this->secure = $secure;
-
- if ($sameSite) {
+ $this->domain = $domain ?? static::$defaults['domain'];
+ $this->httpOnly = $httpOnly ?? static::$defaults['httponly'];
+ $this->path = $path ?? static::$defaults['path'];
+ $this->secure = $secure ?? static::$defaults['secure'];
+ if ($sameSite === null) {
+ $this->sameSite = static::$defaults['samesite'];
+ } else {
$this->validateSameSiteValue($sameSite);
$this->sameSite = $sameSite;
}
if ($expiresAt) {
$expiresAt = $expiresAt->setTimezone(new DateTimeZone('GMT'));
+ } else {
+ $expiresAt = static::$defaults['expires'];
}
$this->expiresAt = $expiresAt;
}
+ /**
+ * Set default options for the cookies.
+ *
+ * Valid option keys are:
+ *
+ * - `expires`: Can be a UNIX timestamp or `strtotime()` compatible string or `DateTimeInterface` instance or `null`.
+ * - `path`: A path string. Defauts to `'/'`.
+ * - `domain`: Domain name string. Defaults to `''`.
+ * - `httponly`: Boolean. Defaults to `false`.
+ * - `secure`: Boolean. Defaults to `false`.
+ * - `samesite`: Can be one of `CookieInterface::SAMESITE_LAX`, `CookieInterface::SAMESITE_STRICT`,
+ * `CookieInterface::SAMESITE_NONE` or `null`. Defaults to `null`.
+ *
+ * @param array $options Default options.
+ * @return void
+ */
+ public static function setDefaults(array $options): void
+ {
+ if (isset($options['expires'])) {
+ $options['expires'] = static::dateTimeInstance($options['expires']);
+ }
+ if (isset($options['samesite'])) {
+ static::validateSameSiteValue($options['samesite']);
+ }
+
+ static::$defaults = $options + static::$defaults;
+ }
+
+ /**
+ * Factory method to create Cookie instances.
+ *
+ * @param string $name Cookie name
+ * @param string|array $value Value of the cookie
+ * @param array $options Cookies options.
+ * @return static
+ * @see \Cake\Cookie\Cookie::setDefaults()
+ */
+ public static function create(string $name, $value, array $options = [])
+ {
+ $options += static::$defaults;
+ $options['expires'] = static::dateTimeInstance($options['expires']);
+
+ return new static(
+ $name,
+ $value,
+ $options['expires'],
+ $options['path'],
+ $options['domain'],
+ $options['secure'],
+ $options['httponly'],
+ $options['samesite']
+ );
+ }
+
+ /**
+ * Converts non null expiry value into DateTimeInterface instance.
+ *
+ * @param mixed $expires Expiry value.
+ * @return \DateTimeInterface|null
+ */
+ protected static function dateTimeInstance($expires): ?DateTimeInterface
+ {
+ if ($expires === null) {
+ return $expires;
+ }
+
+ if ($expires instanceof DateTimeInterface) {
+ /** @psalm-suppress UndefinedInterfaceMethod */
+ return $expires->setTimezone(new DateTimeZone('GMT'));
+ }
+
+ if (!is_string($expires) && !is_int($expires)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid type `%s` for expires. Expected an string, integer or DateTime object.',
+ getTypeName($expires)
+ ));
+ }
+
+ if (!is_numeric($expires)) {
+ $expires = strtotime($expires) ?: null;
+ }
+
+ if ($expires !== null) {
+ $expires = new DateTimeImmutable('@' . (string)$expires);
+ }
+
+ return $expires;
+ }
+
+ /**
+ * Create Cookie instance from "set-cookie" header string.
+ *
+ * @param string $cookie Cookie header string.
+ * @param array $defaults Default attributes.
+ * @return static
+ * @see \Cake\Cookie\Cookie::setDefaults()
+ */
+ public static function createFromHeaderString(string $cookie, array $defaults = [])
+ {
+ if (strpos($cookie, '";"') !== false) {
+ $cookie = str_replace('";"', '{__cookie_replace__}', $cookie);
+ $parts = str_replace('{__cookie_replace__}', '";"', explode(';', $cookie));
+ } else {
+ $parts = preg_split('/\;[ \t]*/', $cookie);
+ }
+
+ [$name, $value] = explode('=', array_shift($parts), 2);
+ $data = [
+ 'name' => urldecode($name),
+ 'value' => urldecode($value),
+ ] + $defaults;
+
+ foreach ($parts as $part) {
+ if (strpos($part, '=') !== false) {
+ [$key, $value] = explode('=', $part);
+ } else {
+ $key = $part;
+ $value = true;
+ }
+
+ $key = strtolower($key);
+ $data[$key] = $value;
+ }
+
+ if (isset($data['max-age'])) {
+ $data['expires'] = time() + (int)$data['max-age'];
+ unset($data['max-age']);
+ }
+
+ if (isset($data['samesite'])) {
+ // Ignore invalid value when parsing headers
+ // https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1
+ if (!in_array($data['samesite'], CookieInterface::SAMESITE_VALUES, true)) {
+ unset($data['samesite']);
+ }
+ }
+
+ $name = (string)$data['name'];
+ $value = (string)$data['value'];
+ unset($data['name'], $data['value']);
+
+ return Cookie::create(
+ $name,
+ $value,
+ $data
+ );
+ }
+
/**
* Returns a header value as string
*
* @return string
*/
- public function toHeaderValue()
+ public function toHeaderValue(): string
{
$value = $this->value;
if ($this->isExpanded) {
+ /** @psalm-suppress PossiblyInvalidArgument */
$value = $this->_flatten($this->value);
}
+ $headerValue = [];
+ /** @psalm-suppress PossiblyInvalidArgument */
$headerValue[] = sprintf('%s=%s', $this->name, rawurlencode($value));
if ($this->expiresAt) {
@@ -185,12 +348,12 @@ public function toHeaderValue()
if ($this->path !== '') {
$headerValue[] = sprintf('path=%s', $this->path);
}
- if ($this->sameSite) {
- $headerValue[] = sprintf('samesite=%s', $this->sameSite);
- }
if ($this->domain !== '') {
$headerValue[] = sprintf('domain=%s', $this->domain);
}
+ if ($this->sameSite) {
+ $headerValue[] = sprintf('samesite=%s', $this->sameSite);
+ }
if ($this->secure) {
$headerValue[] = 'secure';
}
@@ -202,9 +365,9 @@ public function toHeaderValue()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function withName($name)
+ public function withName(string $name)
{
$this->validateName($name);
$new = clone $this;
@@ -214,17 +377,17 @@ public function withName($name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getId()
+ public function getId(): string
{
return "{$this->name};{$this->domain};{$this->path}";
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getName()
+ public function getName(): string
{
return $this->name;
}
@@ -237,7 +400,7 @@ public function getName()
* @throws \InvalidArgumentException
* @link https://tools.ietf.org/html/rfc2616#section-2.2 Rules for naming cookies.
*/
- protected function validateName($name)
+ protected function validateName(string $name): void
{
if (preg_match("/[=,;\t\r\n\013\014]/", $name)) {
throw new InvalidArgumentException(
@@ -251,7 +414,7 @@ protected function validateName($name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getValue()
{
@@ -259,11 +422,25 @@ public function getValue()
}
/**
- * {@inheritDoc}
+ * Gets the cookie value as a string.
+ *
+ * This will collapse any complex data in the cookie with json_encode()
+ *
+ * @return mixed
+ * @deprecated 4.0.0 Use {@link getScalarValue()} instead.
*/
public function getStringValue()
+ {
+ return $this->getScalarValue();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getScalarValue()
{
if ($this->isExpanded) {
+ /** @psalm-suppress PossiblyInvalidArgument */
return $this->_flatten($this->value);
}
@@ -271,7 +448,7 @@ public function getStringValue()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function withValue($value)
{
@@ -284,21 +461,20 @@ public function withValue($value)
/**
* Setter for the value attribute.
*
- * @param mixed $value The value to store.
+ * @param string|array $value The value to store.
* @return void
*/
- protected function _setValue($value)
+ protected function _setValue($value): void
{
$this->isExpanded = is_array($value);
$this->value = $value;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function withPath($path)
+ public function withPath(string $path)
{
- $this->validateString($path);
$new = clone $this;
$new->path = $path;
@@ -306,19 +482,18 @@ public function withPath($path)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getPath()
+ public function getPath(): string
{
return $this->path;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function withDomain($domain)
+ public function withDomain(string $domain)
{
- $this->validateString($domain);
$new = clone $this;
$new->domain = $domain;
@@ -326,44 +501,26 @@ public function withDomain($domain)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getDomain()
+ public function getDomain(): string
{
return $this->domain;
}
/**
- * Validate that an argument is a string
- *
- * @param string $value The value to validate.
- * @return void
- * @throws \InvalidArgumentException
+ * @inheritDoc
*/
- protected function validateString($value)
- {
- if (!is_string($value)) {
- throw new InvalidArgumentException(sprintf(
- 'The provided arg must be of type `string` but `%s` given',
- gettype($value)
- ));
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function isSecure()
+ public function isSecure(): bool
{
return $this->secure;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function withSecure($secure)
+ public function withSecure(bool $secure)
{
- $this->validateBool($secure);
$new = clone $this;
$new->secure = $secure;
@@ -371,11 +528,10 @@ public function withSecure($secure)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function withHttpOnly($httpOnly)
+ public function withHttpOnly(bool $httpOnly)
{
- $this->validateBool($httpOnly);
$new = clone $this;
$new->httpOnly = $httpOnly;
@@ -383,32 +539,15 @@ public function withHttpOnly($httpOnly)
}
/**
- * Validate that an argument is a boolean
- *
- * @param bool $value The value to validate.
- * @return void
- * @throws \InvalidArgumentException
+ * @inheritDoc
*/
- protected function validateBool($value)
- {
- if (!is_bool($value)) {
- throw new InvalidArgumentException(sprintf(
- 'The provided arg must be of type `bool` but `%s` given',
- gettype($value)
- ));
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function isHttpOnly()
+ public function isHttpOnly(): bool
{
return $this->httpOnly;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function withExpiry($dateTime)
{
@@ -419,7 +558,7 @@ public function withExpiry($dateTime)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getExpiry()
{
@@ -427,21 +566,21 @@ public function getExpiry()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getExpiresTimestamp()
+ public function getExpiresTimestamp(): ?int
{
if (!$this->expiresAt) {
return null;
}
- return $this->expiresAt->format('U');
+ return (int)$this->expiresAt->format('U');
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getFormattedExpires()
+ public function getFormattedExpires(): string
{
if (!$this->expiresAt) {
return '';
@@ -451,9 +590,9 @@ public function getFormattedExpires()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function isExpired($time = null)
+ public function isExpired($time = null): bool
{
$time = $time ?: new DateTimeImmutable('now', new DateTimeZone('UTC'));
if (!$this->expiresAt) {
@@ -464,46 +603,39 @@ public function isExpired($time = null)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function withNeverExpire()
{
$new = clone $this;
- $new->expiresAt = Chronos::createFromDate(2038, 1, 1);
+ $new->expiresAt = new DateTimeImmutable('2038-01-01');
return $new;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function withExpired()
{
$new = clone $this;
- $new->expiresAt = Chronos::createFromTimestamp(1);
+ $new->expiresAt = new DateTimeImmutable('1970-01-01 00:00:01');
return $new;
}
/**
- * Get the SameSite attribute.
- *
- * @return string|null
+ * @inheritDoc
*/
- public function getSameSite()
+ public function getSameSite(): ?string
{
return $this->sameSite;
}
/**
- * Create a cookie with an updated SameSite option.
- *
- * @param string|null $sameSite Value for to set for Samesite option.
- * One of CookieInterface::SAMESITE_* constants.
- * @return static
- * @throws \InvalidArgumentException If argument value is not one of CookieInterface::SAMESITE_VALUES
+ * @inheritDoc
*/
- public function withSameSite($sameSite = null)
+ public function withSameSite(?string $sameSite)
{
if ($sameSite !== null) {
$this->validateSameSiteValue($sameSite);
@@ -522,11 +654,11 @@ public function withSameSite($sameSite = null)
* @return void
* @throws \InvalidArgumentException
*/
- protected static function validateSameSiteValue($sameSite)
+ protected static function validateSameSiteValue(string $sameSite)
{
if (!in_array($sameSite, CookieInterface::SAMESITE_VALUES, true)) {
throw new InvalidArgumentException(
- 'SameSite value must be either of: ' . implode(', ', CookieInterface::SAMESITE_VALUES)
+ 'Samesite value must be either of: ' . implode(', ', CookieInterface::SAMESITE_VALUES)
);
}
}
@@ -540,12 +672,14 @@ protected static function validateSameSiteValue($sameSite)
* @param string $path Path to check
* @return bool
*/
- public function check($path)
+ public function check(string $path): bool
{
if ($this->isExpanded === false) {
+ /** @psalm-suppress PossiblyInvalidArgument */
$this->value = $this->_expand($this->value);
}
+ /** @psalm-suppress PossiblyInvalidArgument */
return Hash::check($this->value, $path);
}
@@ -556,12 +690,15 @@ public function check($path)
* @param mixed $value Value to write
* @return static
*/
- public function withAddedValue($path, $value)
+ public function withAddedValue(string $path, $value)
{
$new = clone $this;
if ($new->isExpanded === false) {
+ /** @psalm-suppress PossiblyInvalidArgument */
$new->value = $new->_expand($new->value);
}
+
+ /** @psalm-suppress PossiblyInvalidArgument */
$new->value = Hash::insert($new->value, $path, $value);
return $new;
@@ -573,12 +710,15 @@ public function withAddedValue($path, $value)
* @param string $path Path to remove
* @return static
*/
- public function withoutAddedValue($path)
+ public function withoutAddedValue(string $path)
{
$new = clone $this;
if ($new->isExpanded === false) {
+ /** @psalm-suppress PossiblyInvalidArgument */
$new->value = $new->_expand($new->value);
}
+
+ /** @psalm-suppress PossiblyInvalidArgument */
$new->value = Hash::remove($new->value, $path);
return $new;
@@ -593,9 +733,10 @@ public function withoutAddedValue($path)
* @param string $path Path to read the data from
* @return mixed
*/
- public function read($path = null)
+ public function read(?string $path = null)
{
if ($this->isExpanded === false) {
+ /** @psalm-suppress PossiblyInvalidArgument */
$this->value = $this->_expand($this->value);
}
@@ -603,6 +744,7 @@ public function read($path = null)
return $this->value;
}
+ /** @psalm-suppress PossiblyInvalidArgument */
return Hash::get($this->value, $path);
}
@@ -611,18 +753,49 @@ public function read($path = null)
*
* @return bool
*/
- public function isExpanded()
+ public function isExpanded(): bool
{
return $this->isExpanded;
}
+ /**
+ * @inheritDoc
+ */
+ public function getOptions(): array
+ {
+ $options = [
+ 'expires' => (int)$this->getExpiresTimestamp(),
+ 'path' => $this->path,
+ 'domain' => $this->domain,
+ 'secure' => $this->secure,
+ 'httponly' => $this->httpOnly,
+ ];
+
+ if ($this->sameSite !== null) {
+ $options['samesite'] = $this->sameSite;
+ }
+
+ return $options;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function toArray(): array
+ {
+ return [
+ 'name' => $this->name,
+ 'value' => $this->getScalarValue(),
+ ] + $this->getOptions();
+ }
+
/**
* Implode method to keep keys are multidimensional arrays
*
* @param array $array Map of key and values
* @return string A json encoded string.
*/
- protected function _flatten(array $array)
+ protected function _flatten(array $array): string
{
return json_encode($array);
}
@@ -634,14 +807,14 @@ protected function _flatten(array $array)
* @param string $string A string containing JSON encoded data, or a bare string.
* @return string|array Map of key and values
*/
- protected function _expand($string)
+ protected function _expand(string $string)
{
$this->isExpanded = true;
$first = substr($string, 0, 1);
if ($first === '{' || $first === '[') {
$ret = json_decode($string, true);
- return ($ret !== null) ? $ret : $string;
+ return $ret ?? $string;
}
$array = [];
diff --git a/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieCollection.php b/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieCollection.php
index 6a3b575c9..23b84be42 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieCollection.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieCollection.php
@@ -1,4 +1,6 @@
cookies);
}
@@ -114,9 +125,10 @@ public function add(CookieInterface $cookie)
* Get the first cookie by name.
*
* @param string $name The name of the cookie.
- * @return \Cake\Http\Cookie\CookieInterface|null
+ * @return \Cake\Http\Cookie\CookieInterface
+ * @throws \InvalidArgumentException If cookie not found.
*/
- public function get($name)
+ public function get(string $name): CookieInterface
{
$key = mb_strtolower($name);
foreach ($this->cookies as $cookie) {
@@ -125,7 +137,12 @@ public function get($name)
}
}
- return null;
+ throw new InvalidArgumentException(
+ sprintf(
+ 'Cookie %s not found. Use has() to check first for existence.',
+ $name
+ )
+ );
}
/**
@@ -134,7 +151,7 @@ public function get($name)
* @param string $name The cookie name to check.
* @return bool True if the cookie exists, otherwise false.
*/
- public function has($name)
+ public function has(string $name): bool
{
$key = mb_strtolower($name);
foreach ($this->cookies as $cookie) {
@@ -154,7 +171,7 @@ public function has($name)
* @param string $name The name of the cookie to remove.
* @return static
*/
- public function remove($name)
+ public function remove(string $name)
{
$new = clone $this;
$key = mb_strtolower($name);
@@ -170,11 +187,11 @@ public function remove($name)
/**
* Checks if only valid cookie objects are in the array
*
- * @param array $cookies Array of cookie objects
+ * @param \Cake\Http\Cookie\CookieInterface[] $cookies Array of cookie objects
* @return void
* @throws \InvalidArgumentException
*/
- protected function checkCookies(array $cookies)
+ protected function checkCookies(array $cookies): void
{
foreach ($cookies as $index => $cookie) {
if (!$cookie instanceof CookieInterface) {
@@ -193,9 +210,10 @@ protected function checkCookies(array $cookies)
/**
* Gets the iterator
*
- * @return \ArrayIterator
+ * @return \Cake\Http\Cookie\CookieInterface[]
+ * @psalm-return \Traversable
*/
- public function getIterator()
+ public function getIterator(): Traversable
{
return new ArrayIterator($this->cookies);
}
@@ -212,7 +230,7 @@ public function getIterator()
* is useful when you have cookie data from outside the collection you want to send.
* @return \Psr\Http\Message\RequestInterface An updated request.
*/
- public function addToRequest(RequestInterface $request, array $extraCookies = [])
+ public function addToRequest(RequestInterface $request, array $extraCookies = []): RequestInterface
{
$uri = $request->getUri();
$cookies = $this->findMatchingCookies(
@@ -223,7 +241,7 @@ public function addToRequest(RequestInterface $request, array $extraCookies = []
$cookies = array_merge($cookies, $extraCookies);
$cookiePairs = [];
foreach ($cookies as $key => $value) {
- $cookie = sprintf("%s=%s", rawurlencode($key), rawurlencode($value));
+ $cookie = sprintf('%s=%s', rawurlencode($key), rawurlencode($value));
$size = strlen($cookie);
if ($size > 4096) {
triggerWarning(sprintf(
@@ -249,7 +267,7 @@ public function addToRequest(RequestInterface $request, array $extraCookies = []
* @param string $path The path to match
* @return array An array of cookie name/value pairs
*/
- protected function findMatchingCookies($scheme, $host, $path)
+ protected function findMatchingCookies(string $scheme, string $host, string $path): array
{
$out = [];
$now = new DateTimeImmutable('now', new DateTimeZone('UTC'));
@@ -294,8 +312,10 @@ public function addFromResponse(ResponseInterface $response, RequestInterface $r
$host = $uri->getHost();
$path = $uri->getPath() ?: '/';
- $cookies = static::parseSetCookieHeader($response->getHeader('Set-Cookie'));
- $cookies = $this->setRequestDefaults($cookies, $host, $path);
+ $cookies = static::createFromHeader(
+ $response->getHeader('Set-Cookie'),
+ ['domain' => $host, 'path' => $path]
+ );
$new = clone $this;
foreach ($cookies as $cookie) {
$new->cookies[$cookie->getId()] = $cookie;
@@ -305,99 +325,6 @@ public function addFromResponse(ResponseInterface $response, RequestInterface $r
return $new;
}
- /**
- * Apply path and host to the set of cookies if they are not set.
- *
- * @param array $cookies An array of cookies to update.
- * @param string $host The host to set.
- * @param string $path The path to set.
- * @return array An array of updated cookies.
- */
- protected function setRequestDefaults(array $cookies, $host, $path)
- {
- $out = [];
- foreach ($cookies as $name => $cookie) {
- if (!$cookie->getDomain()) {
- $cookie = $cookie->withDomain($host);
- }
- if (!$cookie->getPath()) {
- $cookie = $cookie->withPath($path);
- }
- $out[] = $cookie;
- }
-
- return $out;
- }
-
- /**
- * Parse Set-Cookie headers into array
- *
- * @param array $values List of Set-Cookie Header values.
- * @return \Cake\Http\Cookie\Cookie[] An array of cookie objects
- */
- protected static function parseSetCookieHeader($values)
- {
- $cookies = [];
- foreach ($values as $value) {
- $value = rtrim($value, ';');
- $parts = preg_split('/\;[ \t]*/', $value);
-
- $name = false;
- $cookie = [
- 'value' => '',
- 'path' => '',
- 'domain' => '',
- 'secure' => false,
- 'httponly' => false,
- 'expires' => null,
- 'max-age' => null,
- ];
- foreach ($parts as $i => $part) {
- if (strpos($part, '=') !== false) {
- list($key, $value) = explode('=', $part, 2);
- } else {
- $key = $part;
- $value = true;
- }
- if ($i === 0) {
- $name = $key;
- $cookie['value'] = urldecode($value);
- continue;
- }
- $key = strtolower($key);
- if (array_key_exists($key, $cookie) && !strlen($cookie[$key])) {
- $cookie[$key] = $value;
- }
- }
- try {
- $expires = null;
- if ($cookie['max-age'] !== null) {
- $expires = new DateTimeImmutable('@' . (time() + $cookie['max-age']));
- } elseif ($cookie['expires']) {
- $expires = new DateTimeImmutable('@' . strtotime($cookie['expires']));
- }
- } catch (Exception $e) {
- $expires = null;
- }
-
- try {
- $cookies[] = new Cookie(
- $name,
- $cookie['value'],
- $expires,
- $cookie['path'],
- $cookie['domain'],
- $cookie['secure'],
- $cookie['httponly']
- );
- } catch (Exception $e) {
- // Don't blow up on invalid cookies
- }
- }
-
- return $cookies;
- }
-
/**
* Remove expired cookies from the collection.
*
@@ -405,16 +332,18 @@ protected static function parseSetCookieHeader($values)
* @param string $path The path to check for expired cookies on.
* @return void
*/
- protected function removeExpiredCookies($host, $path)
+ protected function removeExpiredCookies(string $host, string $path): void
{
$time = new DateTimeImmutable('now', new DateTimeZone('UTC'));
$hostPattern = '/' . preg_quote($host, '/') . '$/';
foreach ($this->cookies as $i => $cookie) {
- $expired = $cookie->isExpired($time);
+ if (!$cookie->isExpired($time)) {
+ continue;
+ }
$pathMatches = strpos($path, $cookie->getPath()) === 0;
$hostMatches = preg_match($hostPattern, $cookie->getDomain());
- if ($pathMatches && $hostMatches && $expired) {
+ if ($pathMatches && $hostMatches) {
unset($this->cookies[$i]);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieInterface.php b/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieInterface.php
index 3a5b42346..070ff7c23 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieInterface.php
@@ -1,4 +1,6 @@
_origin = $origin;
$this->_isSsl = $isSsl;
@@ -80,7 +82,7 @@ public function __construct(MessageInterface $response, $origin, $isSsl = false)
*
* @return \Psr\Http\Message\MessageInterface A new instance of the response with new headers.
*/
- public function build()
+ public function build(): MessageInterface
{
$response = $this->_response;
if (empty($this->_origin)) {
@@ -126,7 +128,7 @@ public function allowOrigin($domains)
* @param string[] $domains Domain names to normalize.
* @return array
*/
- protected function _normalizeDomains($domains)
+ protected function _normalizeDomains(array $domains): array
{
$result = [];
foreach ($domains as $domain) {
@@ -200,7 +202,7 @@ public function exposeHeaders(array $headers)
/**
* Define the max-age preflight OPTIONS requests are valid for.
*
- * @param int $age The max-age for OPTIONS requests in seconds
+ * @param int|string $age The max-age for OPTIONS requests in seconds
* @return $this
*/
public function maxAge($age)
diff --git a/app/vendor/cakephp/cakephp/src/Http/Exception/BadRequestException.php b/app/vendor/cakephp/cakephp/src/Http/Exception/BadRequestException.php
index 62ff763cc..8277a2629 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Exception/BadRequestException.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Exception/BadRequestException.php
@@ -1,4 +1,6 @@
addParser(
['application/json', 'text/json'],
- [$this, 'decodeJson']
+ Closure::fromCallable([$this, 'decodeJson'])
);
}
if ($options['xml']) {
$this->addParser(
['application/xml', 'text/xml'],
- [$this, 'decodeXml']
+ Closure::fromCallable([$this, 'decodeXml'])
);
}
if ($options['methods']) {
@@ -89,6 +94,16 @@ public function setMethods(array $methods)
return $this;
}
+ /**
+ * Get the HTTP methods to parse request bodies on.
+ *
+ * @return string[]
+ */
+ public function getMethods(): array
+ {
+ return $this->methods;
+ }
+
/**
* Add a parser.
*
@@ -105,11 +120,11 @@ public function setMethods(array $methods)
* ```
*
* @param string[] $types An array of content-type header values to match. eg. application/json
- * @param callable $parser The parser function. Must return an array of data to be inserted
+ * @param \Closure $parser The parser function. Must return an array of data to be inserted
* into the request.
* @return $this
*/
- public function addParser(array $types, callable $parser)
+ public function addParser(array $types, Closure $parser)
{
foreach ($types as $type) {
$type = strtolower($type);
@@ -119,25 +134,34 @@ public function addParser(array $types, callable $parser)
return $this;
}
+ /**
+ * Get the current parsers
+ *
+ * @return \Closure[]
+ */
+ public function getParsers(): array
+ {
+ return $this->parsers;
+ }
+
/**
* Apply the middleware.
*
* Will modify the request adding a parsed body if the content-type is known.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @param \Psr\Http\Message\ResponseInterface $response The response.
- * @param callable $next Callback to invoke the next middleware.
- * @return \Cake\Http\Response A response
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
+ * @return \Psr\Http\Message\ResponseInterface A response.
*/
- public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (!in_array($request->getMethod(), $this->methods, true)) {
- return $next($request, $response);
+ return $handler->handle($request);
}
- list($type) = explode(';', $request->getHeaderLine('Content-Type'));
+ [$type] = explode(';', $request->getHeaderLine('Content-Type'));
$type = strtolower($type);
if (!isset($this->parsers[$type])) {
- return $next($request, $response);
+ return $handler->handle($request);
}
$parser = $this->parsers[$type];
@@ -147,16 +171,16 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res
}
$request = $request->withParsedBody($result);
- return $next($request, $response);
+ return $handler->handle($request);
}
/**
* Decode JSON into an array.
*
* @param string $body The request body to decode
- * @return array
+ * @return mixed
*/
- protected function decodeJson($body)
+ protected function decodeJson(string $body)
{
return json_decode($body, true);
}
@@ -167,7 +191,7 @@ protected function decodeJson($body)
* @param string $body The request body to decode
* @return array
*/
- protected function decodeXml($body)
+ protected function decodeXml(string $body): array
{
try {
$xml = Xml::build($body, ['return' => 'domdocument', 'readFile' => false]);
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/ClosureDecoratorMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/ClosureDecoratorMiddleware.php
new file mode 100644
index 000000000..c85640716
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/ClosureDecoratorMiddleware.php
@@ -0,0 +1,81 @@
+callable = $callable;
+ }
+
+ /**
+ * Run the callable to process an incoming server request.
+ *
+ * @param \Psr\Http\Message\ServerRequestInterface $request Request instance.
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler Request handler instance.
+ * @return \Psr\Http\Message\ResponseInterface
+ */
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+ {
+ return ($this->callable)(
+ $request,
+ $handler
+ );
+ }
+
+ /**
+ * @internal
+ * @return callable
+ */
+ public function getCallable(): callable
+ {
+ return $this->callable;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/CspMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/CspMiddleware.php
index ab528e9de..8ce975d08 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Middleware/CspMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/CspMiddleware.php
@@ -1,4 +1,5 @@
csp->injectCSPHeader($responseInterface);
+ $response = $handler->handle($request);
- return $next($requestInterface, $response, $next);
+ // phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.InvalidFormat
+ /** @var \Psr\Http\Message\ResponseInterface */
+ return $this->csp->injectCSPHeader($response);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php
index 5c6b410a7..3c7c292eb 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php
@@ -1,4 +1,6 @@
Form->create(...)` is used in a view.
+ *
+ * @see https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie
*/
-class CsrfProtectionMiddleware
+class CsrfProtectionMiddleware implements MiddlewareInterface
{
/**
- * Default config for the CSRF handling.
+ * Config for the CSRF handling.
*
* - `cookieName` The name of the cookie to send.
* - `expiry` A strotime compatible value of how long the CSRF token should last.
* Defaults to browser session.
* - `secure` Whether or not the cookie will be set with the Secure flag. Defaults to false.
* - `httpOnly` Whether or not the cookie will be set with the HttpOnly flag. Defaults to false.
- * - `samesite` Value for "SameSite" attribute. Default to null.
* - `field` The form field to check. Changing this will also require configuring
* FormHelper.
*
* @var array
*/
- protected $_defaultConfig = [
+ protected $_config = [
'cookieName' => 'csrfToken',
'expiry' => 0,
'secure' => false,
'httpOnly' => false,
- 'samesite' => null,
'field' => '_csrfToken',
];
- /**
- * Configuration
- *
- * @var array
- */
- protected $_config = [];
-
/**
* Callback for deciding whether or not to skip the token check for particular request.
*
@@ -77,53 +76,66 @@ class CsrfProtectionMiddleware
*/
protected $whitelistCallback;
+ /**
+ * @var int
+ */
+ public const TOKEN_VALUE_LENGTH = 16;
+
/**
* Constructor
*
- * @param array $config Config options. See $_defaultConfig for valid keys.
+ * @param array $config Config options. See $_config for valid keys.
*/
public function __construct(array $config = [])
{
- $this->_config = $config + $this->_defaultConfig;
+ $this->_config = $config + $this->_config;
}
/**
* Checks and sets the CSRF token depending on the HTTP verb.
*
- * @param \Cake\Http\ServerRequest $request The request.
- * @param \Cake\Http\Response $response The response.
- * @param callable $next Callback to invoke the next middleware.
- * @return \Cake\Http\Response A response
+ * @param \Psr\Http\Message\ServerRequestInterface $request The request.
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
+ * @return \Psr\Http\Message\ResponseInterface A response.
*/
- public function __invoke(ServerRequest $request, Response $response, $next)
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
+ $method = $request->getMethod();
+ $hasData = in_array($method, ['PUT', 'POST', 'DELETE', 'PATCH'], true)
+ || $request->getParsedBody();
+
if (
- $this->whitelistCallback !== null
+ $hasData
+ && $this->whitelistCallback !== null
&& call_user_func($this->whitelistCallback, $request) === true
) {
- return $next($request, $response);
+ $request = $this->_unsetTokenField($request);
+
+ return $handler->handle($request);
}
$cookies = $request->getCookieParams();
$cookieData = Hash::get($cookies, $this->_config['cookieName']);
if (is_string($cookieData) && strlen($cookieData) > 0) {
- $params = $request->getAttribute('params');
- $params['_csrfToken'] = $cookieData;
- $request = $request->withAttribute('params', $params);
+ $request = $request->withAttribute('csrfToken', $cookieData);
}
- $method = $request->getMethod();
if ($method === 'GET' && $cookieData === null) {
- $token = $this->_createToken();
- $request = $this->_addTokenToRequest($token, $request);
- $response = $this->_addTokenCookie($token, $request, $response);
+ $token = $this->createToken();
+ $request = $request->withAttribute('csrfToken', $token);
+ /** @var mixed $response */
+ $response = $handler->handle($request);
- return $next($request, $response);
+ return $this->_addTokenCookie($token, $request, $response);
}
- $request = $this->_validateAndUnsetTokenField($request);
- return $next($request, $response);
+ if ($hasData) {
+ $this->_validateToken($request);
+ $request = $this->_unsetTokenField($request);
+ }
+
+ return $handler->handle($request);
}
/**
@@ -143,20 +155,17 @@ public function whitelistCallback(callable $callback)
}
/**
- * Checks if the request is POST, PUT, DELETE or PATCH and validates the CSRF token
+ * Remove CSRF protection token from request data.
*
- * @param \Cake\Http\ServerRequest $request The request object.
- * @return \Cake\Http\ServerRequest
+ * @param \Psr\Http\Message\ServerRequestInterface $request The request object.
+ * @return \Psr\Http\Message\ServerRequestInterface
*/
- protected function _validateAndUnsetTokenField(ServerRequest $request)
+ protected function _unsetTokenField(ServerRequestInterface $request): ServerRequestInterface
{
- if (in_array($request->getMethod(), ['PUT', 'POST', 'DELETE', 'PATCH'], true) || $request->getData()) {
- $this->_validateToken($request);
- $body = $request->getParsedBody();
- if (is_array($body)) {
- unset($body[$this->_config['field']]);
- $request = $request->withParsedBody($body);
- }
+ $body = $request->getParsedBody();
+ if (is_array($body)) {
+ unset($body[$this->_config['field']]);
+ $request = $request->withParsedBody($body);
}
return $request;
@@ -166,73 +175,129 @@ protected function _validateAndUnsetTokenField(ServerRequest $request)
* Create a new token to be used for CSRF protection
*
* @return string
+ * @deprecated 4.0.6 Use {@link createToken()} instead.
*/
- protected function _createToken()
+ protected function _createToken(): string
{
- return hash('sha512', Security::randomBytes(16), false);
+ return $this->createToken();
}
/**
- * Add a CSRF token to the request parameters.
+ * Create a new token to be used for CSRF protection
*
- * @param string $token The token to add.
- * @param \Cake\Http\ServerRequest $request The request to augment
- * @return \Cake\Http\ServerRequest Modified request
+ * @return string
*/
- protected function _addTokenToRequest($token, ServerRequest $request)
+ public function createToken(): string
{
- $params = $request->getAttribute('params');
- $params['_csrfToken'] = $token;
+ $value = Security::randomString(static::TOKEN_VALUE_LENGTH);
- return $request->withAttribute('params', $params);
+ return $value . hash_hmac('sha1', $value, Security::getSalt());
}
/**
- * Add a CSRF token to the response cookies.
+ * Verify that CSRF token was originally generated by the receiving application.
*
- * @param string $token The token to add.
- * @param \Cake\Http\ServerRequest $request The request to validate against.
- * @param \Cake\Http\Response $response The response.
- * @return \Cake\Http\Response $response Modified response.
+ * @param string $token The CSRF token.
+ * @return bool
*/
- protected function _addTokenCookie($token, ServerRequest $request, Response $response)
+ protected function _verifyToken(string $token): bool
{
- $expiry = new Time($this->_config['expiry']);
+ if (strlen($token) <= self::TOKEN_VALUE_LENGTH) {
+ return false;
+ }
- $cookie = new Cookie(
- $this->_config['cookieName'],
- $token,
- $expiry,
- $request->getAttribute('webroot'),
- '',
- (bool)$this->_config['secure'],
- (bool)$this->_config['httpOnly'],
- isset($this->_config['samesite']) ? $this->_config['samesite'] : $this->_defaultConfig['samesite']
- );
+ $key = substr($token, 0, static::TOKEN_VALUE_LENGTH);
+ $hmac = substr($token, static::TOKEN_VALUE_LENGTH);
+
+ $expectedHmac = hash_hmac('sha1', $key, Security::getSalt());
- return $response->withCookie($cookie);
+ return hash_equals($hmac, $expectedHmac);
+ }
+
+ /**
+ * Add a CSRF token to the response cookies.
+ *
+ * @param string $token The token to add.
+ * @param \Psr\Http\Message\ServerRequestInterface $request The request to validate against.
+ * @param \Psr\Http\Message\ResponseInterface $response The response.
+ * @return \Psr\Http\Message\ResponseInterface $response Modified response.
+ */
+ protected function _addTokenCookie(
+ string $token,
+ ServerRequestInterface $request,
+ ResponseInterface $response
+ ): ResponseInterface {
+ $cookie = $this->_createCookie($token, $request);
+ if ($response instanceof Response) {
+ return $response->withCookie($cookie);
+ }
+
+ return $response->withAddedHeader('Set-Cookie', $cookie->toHeaderValue());
}
/**
* Validate the request data against the cookie token.
*
- * @param \Cake\Http\ServerRequest $request The request to validate against.
+ * @param \Psr\Http\Message\ServerRequestInterface $request The request to validate against.
* @return void
* @throws \Cake\Http\Exception\InvalidCsrfTokenException When the CSRF token is invalid or missing.
*/
- protected function _validateToken(ServerRequest $request)
+ protected function _validateToken(ServerRequestInterface $request): void
{
- $cookies = $request->getCookieParams();
- $cookie = Hash::get($cookies, $this->_config['cookieName']);
- $post = Hash::get($request->getParsedBody(), $this->_config['field']);
- $header = $request->getHeaderLine('X-CSRF-Token');
+ $cookie = Hash::get($request->getCookieParams(), $this->_config['cookieName']);
+
+ if (!$cookie || !is_string($cookie)) {
+ throw new InvalidCsrfTokenException(__d('cake', 'Missing or incorrect CSRF cookie type.'));
+ }
+
+ if (!$this->_verifyToken($cookie)) {
+ $exception = new InvalidCsrfTokenException(__d('cake', 'Missing or invalid CSRF cookie.'));
+
+ $expiredCookie = $this->_createCookie('', $request)->withExpired();
+ $exception->responseHeader('Set-Cookie', $expiredCookie->toHeaderValue());
- if (!$cookie) {
- throw new InvalidCsrfTokenException(__d('cake', 'Missing CSRF token cookie'));
+ throw $exception;
}
- if (!Security::constantEquals($post, $cookie) && !Security::constantEquals($header, $cookie)) {
- throw new InvalidCsrfTokenException(__d('cake', 'CSRF token mismatch.'));
+ $body = $request->getParsedBody();
+ if (is_array($body) || $body instanceof ArrayAccess) {
+ $post = (string)Hash::get($body, $this->_config['field']);
+ if (hash_equals($post, $cookie)) {
+ return;
+ }
+ }
+
+ $header = $request->getHeaderLine('X-CSRF-Token');
+ if (hash_equals($header, $cookie)) {
+ return;
}
+
+ throw new InvalidCsrfTokenException(__d(
+ 'cake',
+ 'CSRF token from either the request body or request headers did not match or is missing.'
+ ));
+ }
+
+ /**
+ * Create response cookie
+ *
+ * @param string $value Cookie value
+ * @param \Psr\Http\Message\ServerRequestInterface $request The request object.
+ * @return \Cake\Http\Cookie\CookieInterface
+ */
+ protected function _createCookie(string $value, ServerRequestInterface $request): CookieInterface
+ {
+ $cookie = Cookie::create(
+ $this->_config['cookieName'],
+ $value,
+ [
+ 'expires' => $this->_config['expiry'] ?: null,
+ 'path' => $request->getAttribute('webroot'),
+ 'secure' => $this->_config['secure'],
+ 'httponly' => $this->_config['httpOnly'],
+ ]
+ );
+
+ return $cookie;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/DoublePassDecoratorMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/DoublePassDecoratorMiddleware.php
new file mode 100644
index 000000000..287d80c59
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/DoublePassDecoratorMiddleware.php
@@ -0,0 +1,87 @@
+callable = $callable;
+ }
+
+ /**
+ * Run the internal double pass callable to process an incoming server request.
+ *
+ * @param \Psr\Http\Message\ServerRequestInterface $request Request instance.
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler Request handler instance.
+ * @return \Psr\Http\Message\ResponseInterface
+ */
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+ {
+ return ($this->callable)(
+ $request,
+ new Response(),
+ function ($request, $res) use ($handler) {
+ return $handler->handle($request);
+ }
+ );
+ }
+
+ /**
+ * @internal
+ * @return callable
+ */
+ public function getCallable(): callable
+ {
+ return $this->callable;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/EncryptedCookieMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/EncryptedCookieMiddleware.php
index 991182972..132b24f21 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Middleware/EncryptedCookieMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/EncryptedCookieMiddleware.php
@@ -1,4 +1,6 @@
cookieNames = $cookieNames;
$this->key = $key;
@@ -78,16 +81,16 @@ public function __construct(array $cookieNames, $key, $cipherType = 'aes')
* Apply cookie encryption/decryption.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @param \Psr\Http\Message\ResponseInterface $response The response.
- * @param callable $next The next middleware to call.
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
* @return \Psr\Http\Message\ResponseInterface A response.
*/
- public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if ($request->getCookieParams()) {
$request = $this->decodeCookies($request);
}
- $response = $next($request, $response);
+
+ $response = $handler->handle($request);
if ($response->hasHeader('Set-Cookie')) {
$response = $this->encodeSetCookieHeader($response);
}
@@ -105,7 +108,7 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res
*
* @return string
*/
- protected function _getCookieEncryptionKey()
+ protected function _getCookieEncryptionKey(): string
{
return $this->key;
}
@@ -116,7 +119,7 @@ protected function _getCookieEncryptionKey()
* @param \Psr\Http\Message\ServerRequestInterface $request The request to decode cookies from.
* @return \Psr\Http\Message\ServerRequestInterface Updated request with decoded cookies.
*/
- protected function decodeCookies(ServerRequestInterface $request)
+ protected function decodeCookies(ServerRequestInterface $request): ServerRequestInterface
{
$cookies = $request->getCookieParams();
foreach ($this->cookieNames as $name) {
@@ -134,8 +137,9 @@ protected function decodeCookies(ServerRequestInterface $request)
* @param \Cake\Http\Response $response The response to encode cookies in.
* @return \Cake\Http\Response Updated response with encoded cookies.
*/
- protected function encodeCookies(Response $response)
+ protected function encodeCookies(Response $response): Response
{
+ /** @var \Cake\Http\Cookie\CookieInterface[] $cookies */
$cookies = $response->getCookieCollection();
foreach ($cookies as $cookie) {
if (in_array($cookie->getName(), $this->cookieNames, true)) {
@@ -153,8 +157,9 @@ protected function encodeCookies(Response $response)
* @param \Psr\Http\Message\ResponseInterface $response The response to encode cookies in.
* @return \Psr\Http\Message\ResponseInterface Updated response with encoded cookies.
*/
- protected function encodeSetCookieHeader(ResponseInterface $response)
+ protected function encodeSetCookieHeader(ResponseInterface $response): ResponseInterface
{
+ /** @var \Cake\Http\Cookie\CookieInterface[] $cookies */
$cookies = CookieCollection::createFromHeader($response->getHeader('Set-Cookie'));
$header = [];
foreach ($cookies as $cookie) {
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/HttpsEnforcerMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/HttpsEnforcerMiddleware.php
new file mode 100644
index 000000000..491417b26
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/HttpsEnforcerMiddleware.php
@@ -0,0 +1,98 @@
+ true,
+ 'statusCode' => 301,
+ 'headers' => [],
+ 'disableOnDebug' => true,
+ ];
+
+ /**
+ * Constructor
+ *
+ * @param array $config The options to use.
+ * @see self::$config
+ */
+ public function __construct(array $config = [])
+ {
+ $this->config = $config + $this->config;
+ }
+
+ /**
+ * Check whether request has been made using HTTPS.
+ *
+ * Depending on the configuration and request method, either redirects to
+ * same URL with https or throws an exception.
+ *
+ * @param \Psr\Http\Message\ServerRequestInterface $request The request.
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
+ * @return \Psr\Http\Message\ResponseInterface A response.
+ * @throws \Cake\Http\Exception\BadRequestException
+ */
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+ {
+ if (
+ $request->getUri()->getScheme() === 'https'
+ || ($this->config['disableOnDebug']
+ && Configure::read('debug'))
+ ) {
+ return $handler->handle($request);
+ }
+
+ if ($this->config['redirect'] && $request->getMethod() === 'GET') {
+ $uri = $request->getUri()->withScheme('https');
+
+ return new RedirectResponse(
+ $uri,
+ $this->config['statusCode'],
+ $this->config['headers']
+ );
+ }
+
+ throw new BadRequestException(
+ 'Requests to this URL must be made with HTTPS.'
+ );
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/SecurityHeadersMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/SecurityHeadersMiddleware.php
index 82eeb4dd9..01c4bb2e4 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Middleware/SecurityHeadersMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/SecurityHeadersMiddleware.php
@@ -1,4 +1,6 @@
checkValues($option, [self::DENY, self::SAMEORIGIN, self::ALLOW_FROM]);
@@ -186,7 +190,7 @@ public function setXFrameOptions($option = self::SAMEORIGIN, $url = null)
* @param string $mode Mode value. Available Values: '1', '0', 'block'
* @return $this
*/
- public function setXssProtection($mode = self::XSS_BLOCK)
+ public function setXssProtection(string $mode = self::XSS_BLOCK)
{
$mode = (string)$mode;
@@ -208,7 +212,7 @@ public function setXssProtection($mode = self::XSS_BLOCK)
* 'by-ftp-filename'
* @return $this
*/
- public function setCrossDomainPolicy($policy = self::ALL)
+ public function setCrossDomainPolicy(string $policy = self::ALL)
{
$this->checkValues($policy, [
self::ALL,
@@ -230,9 +234,9 @@ public function setCrossDomainPolicy($policy = self::ALL)
* @param string[] $allowed List of allowed values
* @return void
*/
- protected function checkValues($value, array $allowed)
+ protected function checkValues(string $value, array $allowed): void
{
- if (!in_array($value, $allowed)) {
+ if (!in_array($value, $allowed, true)) {
throw new InvalidArgumentException(sprintf(
'Invalid arg `%s`, use one of these: %s',
$value,
@@ -245,13 +249,12 @@ protected function checkValues($value, array $allowed)
* Serve assets if the path matches one.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @param \Psr\Http\Message\ResponseInterface $response The response.
- * @param callable $next Callback to invoke the next middleware.
- * @return \Psr\Http\Message\ResponseInterface A response
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
+ * @return \Psr\Http\Message\ResponseInterface A response.
*/
- public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
- $response = $next($request, $response);
+ $response = $handler->handle($request);
foreach ($this->headers as $header => $value) {
$response = $response->withHeader($header, $value);
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/MiddlewareApplication.php b/app/vendor/cakephp/cakephp/src/Http/MiddlewareApplication.php
new file mode 100644
index 000000000..89cf261a5
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/MiddlewareApplication.php
@@ -0,0 +1,56 @@
+ 'Not found', 'status' => 404]);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Http/MiddlewareQueue.php b/app/vendor/cakephp/cakephp/src/Http/MiddlewareQueue.php
index 7e05983c1..ccdd4a87f 100644
--- a/app/vendor/cakephp/cakephp/src/Http/MiddlewareQueue.php
+++ b/app/vendor/cakephp/cakephp/src/Http/MiddlewareQueue.php
@@ -1,4 +1,6 @@
*/
- protected $callables = [];
+ protected $queue = [];
/**
* Constructor
@@ -50,55 +60,45 @@ public function __construct(array $middleware = [])
}
/**
- * Get the middleware at the provided index.
+ * Resolve middleware name to a PSR 15 compliant middleware instance.
*
- * @param int $index The index to fetch.
- * @return callable|null Either the callable middleware or null
- * if the index is undefined.
+ * @param string|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware to resolve.
+ * @return \Psr\Http\Server\MiddlewareInterface
+ * @throws \RuntimeException If Middleware not found.
*/
- public function get($index)
+ protected function resolve($middleware): MiddlewareInterface
{
- if (isset($this->callables[$index])) {
- return $this->callables[$index];
+ if (is_string($middleware)) {
+ $className = App::className($middleware, 'Middleware', 'Middleware');
+ if ($className === null) {
+ throw new RuntimeException(sprintf(
+ 'Middleware "%s" was not found.',
+ $middleware
+ ));
+ }
+ $middleware = new $className();
}
- return $this->resolve($index);
- }
+ if ($middleware instanceof MiddlewareInterface) {
+ return $middleware;
+ }
- /**
- * Resolve middleware name to callable.
- *
- * @param int $index The index to fetch.
- * @return callable|null Either the callable middleware or null
- * if the index is undefined.
- */
- protected function resolve($index)
- {
- if (!isset($this->queue[$index])) {
- return null;
+ if (!$middleware instanceof Closure) {
+ return new DoublePassDecoratorMiddleware($middleware);
}
- if (is_string($this->queue[$index])) {
- $class = $this->queue[$index];
- $className = App::className($class, 'Middleware', 'Middleware');
- if (!$className || !class_exists($className)) {
- throw new RuntimeException(sprintf(
- 'Middleware "%s" was not found.',
- $class
- ));
- }
- $callable = new $className();
- } else {
- $callable = $this->queue[$index];
+ $info = new ReflectionFunction($middleware);
+ if ($info->getNumberOfParameters() > 2) {
+ return new DoublePassDecoratorMiddleware($middleware);
}
- return $this->callables[$index] = $callable;
+ return new ClosureDecoratorMiddleware($middleware);
}
/**
- * Append a middleware callable to the end of the queue.
+ * Append a middleware to the end of the queue.
*
- * @param callable|string|array $middleware The middleware(s) to append.
+ * @param string|array|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware(s) to append.
* @return $this
*/
public function add($middleware)
@@ -116,7 +116,7 @@ public function add($middleware)
/**
* Alias for MiddlewareQueue::add().
*
- * @param callable|string|array $middleware The middleware(s) to append.
+ * @param string|array|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware(s) to append.
* @return $this
* @see MiddlewareQueue::add()
*/
@@ -128,7 +128,7 @@ public function push($middleware)
/**
* Prepend a middleware to the start of the queue.
*
- * @param callable|string|array $middleware The middleware(s) to prepend.
+ * @param string|array|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware(s) to prepend.
* @return $this
*/
public function prepend($middleware)
@@ -144,16 +144,16 @@ public function prepend($middleware)
}
/**
- * Insert a middleware callable at a specific index.
+ * Insert a middleware at a specific index.
*
- * If the index already exists, the new callable will be inserted,
+ * If the index already exists, the new middleware will be inserted,
* and the existing element will be shifted one index greater.
*
* @param int $index The index to insert at.
- * @param callable|string $middleware The middleware to insert.
+ * @param string|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware to insert.
* @return $this
*/
- public function insertAt($index, $middleware)
+ public function insertAt(int $index, $middleware)
{
array_splice($this->queue, $index, 0, [$middleware]);
@@ -161,23 +161,26 @@ public function insertAt($index, $middleware)
}
/**
- * Insert a middleware object before the first matching class.
+ * Insert a middleware before the first matching class.
*
* Finds the index of the first middleware that matches the provided class,
- * and inserts the supplied callable before it.
+ * and inserts the supplied middleware before it.
*
* @param string $class The classname to insert the middleware before.
- * @param callable|string $middleware The middleware to insert.
+ * @param string|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware to insert.
* @return $this
* @throws \LogicException If middleware to insert before is not found.
*/
- public function insertBefore($class, $middleware)
+ public function insertBefore(string $class, $middleware)
{
$found = false;
$i = 0;
foreach ($this->queue as $i => $object) {
if (
- (is_string($object) && $object === $class)
+ (
+ is_string($object)
+ && $object === $class
+ )
|| is_a($object, $class)
) {
$found = true;
@@ -194,20 +197,23 @@ public function insertBefore($class, $middleware)
* Insert a middleware object after the first matching class.
*
* Finds the index of the first middleware that matches the provided class,
- * and inserts the supplied callable after it. If the class is not found,
+ * and inserts the supplied middleware after it. If the class is not found,
* this method will behave like add().
*
* @param string $class The classname to insert the middleware before.
- * @param callable|string $middleware The middleware to insert.
+ * @param string|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware to insert.
* @return $this
*/
- public function insertAfter($class, $middleware)
+ public function insertAfter(string $class, $middleware)
{
$found = false;
$i = 0;
foreach ($this->queue as $i => $object) {
if (
- (is_string($object) && $object === $class)
+ (
+ is_string($object)
+ && $object === $class
+ )
|| is_a($object, $class)
) {
$found = true;
@@ -228,8 +234,87 @@ public function insertAfter($class, $middleware)
*
* @return int
*/
- public function count()
+ public function count(): int
{
return count($this->queue);
}
+
+ /**
+ * Seeks to a given position in the queue.
+ *
+ * @param int $position The position to seek to.
+ * @return void
+ * @see \SeekableIterator::seek()
+ */
+ public function seek($position): void
+ {
+ if (!isset($this->queue[$position])) {
+ throw new OutOfBoundsException("Invalid seek position ($position)");
+ }
+
+ $this->position = $position;
+ }
+
+ /**
+ * Rewinds back to the first element of the queue.
+ *
+ * @return void
+ * @see \Iterator::rewind()
+ */
+ public function rewind(): void
+ {
+ $this->position = 0;
+ }
+
+ /**
+ * Returns the current middleware.
+ *
+ * @return \Psr\Http\Server\MiddlewareInterface
+ * @see \Iterator::current()
+ */
+ public function current(): MiddlewareInterface
+ {
+ if (!isset($this->queue[$this->position])) {
+ throw new OutOfBoundsException("Invalid current position ($this->position)");
+ }
+
+ if ($this->queue[$this->position] instanceof MiddlewareInterface) {
+ return $this->queue[$this->position];
+ }
+
+ return $this->queue[$this->position] = $this->resolve($this->queue[$this->position]);
+ }
+
+ /**
+ * Return the key of the middleware.
+ *
+ * @return int
+ * @see \Iterator::key()
+ */
+ public function key(): int
+ {
+ return $this->position;
+ }
+
+ /**
+ * Moves the current position to the next middleware.
+ *
+ * @return void
+ * @see \Iterator::next()
+ */
+ public function next(): void
+ {
+ ++$this->position;
+ }
+
+ /**
+ * Checks if current position is valid.
+ *
+ * @return bool
+ * @see \Iterator::valid()
+ */
+ public function valid(): bool
+ {
+ return isset($this->queue[$this->position]);
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/README.md b/app/vendor/cakephp/cakephp/src/Http/README.md
new file mode 100644
index 000000000..e67f57a18
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/README.md
@@ -0,0 +1,98 @@
+[](https://packagist.org/packages/cakephp/http)
+[](LICENSE.txt)
+
+# CakePHP Http Library
+
+This library provides a PSR-15 Http middleware server, PSR-7 Request and
+Response objects, and a PSR-18 Http Client. Together these classes let you
+handle incoming server requests and send outgoing HTTP requests.
+
+## Using the Http Client
+
+Sending requests is straight forward. Doing a GET request looks like
+
+```php
+use Cake\Http\Client;
+
+$http = new Client();
+
+// Simple get
+$response = $http->get('http://example.com/test.html');
+
+// Simple get with querystring
+$response = $http->get('http://example.com/search', ['q' => 'widget']);
+
+// Simple get with querystring & additional headers
+$response = $http->get('http://example.com/search', ['q' => 'widget'], [
+ 'headers' => ['X-Requested-With' => 'XMLHttpRequest'],
+]);
+```
+
+To learn more read the [Http Client documentation](https://book.cakephp.org/4/en/core-libraries/httpclient.html).
+
+## Using the Http Server
+
+The Http Server allows an `HttpApplicationInterface` to process requests and
+emit responses. To get started first implement the
+`Cake\Http\HttpApplicationInterface` A minimal example would could look like:
+
+```php
+namespace App;
+
+use Cake\Core\HttpApplicationInterface;
+use Cake\Http\MiddlewareQueue;
+
+class Application implements HttpApplicationInterface
+{
+ /**
+ * Load all the application configuration and bootstrap logic.
+ *
+ * @return void
+ */
+ public function bootstrap(): void
+ {
+ // Load configuration here. This is the first
+ // method Cake\Http\Server will call on your application.
+ }
+
+ /**
+ * Define the HTTP middleware layers for an application.
+ *
+ * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to set in your App Class
+ * @return \Cake\Http\MiddlewareQueue
+ */
+ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
+ {
+ // Add middleware for your application.
+ return $middlewareQueue;
+ }
+}
+```
+
+Once you have an application with some middleware. You can start accepting
+requests. In your application's webroot, you can add an `index.php` and process
+requests:
+
+```php
+emit($server->run());
+```
+
+You can then run your application using PHP's built in webserver:
+
+```bash
+php -S localhost:8765 -t ./webroot ./webroot/index.php
+```
+
+For more information on middleware, [consult the
+documentation](https://book.cakephp.org/4/en/controllers/middleware.html)
diff --git a/app/vendor/cakephp/cakephp/src/Http/RequestTransformer.php b/app/vendor/cakephp/cakephp/src/Http/RequestTransformer.php
deleted file mode 100644
index cd1f59180..000000000
--- a/app/vendor/cakephp/cakephp/src/Http/RequestTransformer.php
+++ /dev/null
@@ -1,157 +0,0 @@
-getParsedBody();
- $headers = [];
- foreach ($request->getHeaders() as $k => $value) {
- $name = sprintf('HTTP_%s', strtoupper(str_replace('-', '_', $k)));
- $headers[$name] = implode(',', $value);
- }
- $server = $headers + $request->getServerParams();
-
- $files = static::getFiles($request);
- if (!empty($files)) {
- $post = Hash::merge($post, $files);
- }
-
- $input = $request->getBody()->getContents();
- $input = $input === '' ? null : $input;
-
- return new ServerRequest([
- 'query' => $request->getQueryParams(),
- 'post' => $post,
- 'cookies' => $request->getCookieParams(),
- 'environment' => $server,
- 'params' => static::getParams($request),
- 'url' => $request->getUri()->getPath(),
- 'base' => $request->getAttribute('base', ''),
- 'webroot' => $request->getAttribute('webroot', '/'),
- 'session' => $request->getAttribute('session', null),
- 'input' => $input,
- ]);
- }
-
- /**
- * Extract the routing parameters out of the request object.
- *
- * @param \Psr\Http\Message\ServerRequestInterface $request The request to extract params from.
- * @return array The routing parameters.
- */
- protected static function getParams(PsrRequest $request)
- {
- $params = (array)$request->getAttribute('params', []);
- $params += [
- 'plugin' => null,
- 'controller' => null,
- 'action' => null,
- '_ext' => null,
- 'pass' => [],
- ];
-
- return $params;
- }
-
- /**
- * Extract the uploaded files out of the request object.
- *
- * CakePHP expects to get arrays of file information and
- * not the parsed objects that PSR7 requests contain. Downsample the data here.
- *
- * @param \Psr\Http\Message\ServerRequestInterface $request The request to extract files from.
- * @return array The routing parameters.
- */
- protected static function getFiles($request)
- {
- return static::convertFiles([], $request->getUploadedFiles());
- }
-
- /**
- * Convert a nested array of files to arrays.
- *
- * @param array $data The data to add files to.
- * @param array $files The file objects to convert.
- * @param string $path The current array path.
- * @return array Converted file data
- */
- protected static function convertFiles($data, $files, $path = '')
- {
- foreach ($files as $key => $file) {
- $newPath = $path;
- if ($newPath === '') {
- $newPath = $key;
- }
- if ($newPath !== $key) {
- $newPath .= '.' . $key;
- }
-
- if (is_array($file)) {
- $data = static::convertFiles($data, $file, $newPath);
- } else {
- $data = Hash::insert($data, $newPath, static::convertFile($file));
- }
- }
-
- return $data;
- }
-
- /**
- * Convert a single file back into an array.
- *
- * @param \Psr\Http\Message\UploadedFileInterface $file The file to convert.
- * @return array
- */
- protected static function convertFile($file)
- {
- $error = $file->getError();
- $tmpName = '';
- if ($error === UPLOAD_ERR_OK) {
- $tmpName = $file->getStream()->getMetadata('uri');
- }
-
- return [
- 'name' => $file->getClientFilename(),
- 'type' => $file->getClientMediaType(),
- 'tmp_name' => $tmpName,
- 'error' => $error,
- 'size' => $file->getSize(),
- ];
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Response.php b/app/vendor/cakephp/cakephp/src/Http/Response.php
index 7fb615a37..3276cd9cc 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Response.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Response.php
@@ -1,4 +1,6 @@
'image/x-xbitmap',
'xpm' => 'image/x-xpixmap',
'xwd' => 'image/x-xwindowdump',
- 'psd' => ['application/photoshop', 'application/psd', 'image/psd', 'image/x-photoshop', 'image/photoshop', 'zz-application/zz-winassoc-psd'],
+ 'psd' => [
+ 'application/photoshop',
+ 'application/psd',
+ 'image/psd',
+ 'image/x-photoshop',
+ 'image/photoshop',
+ 'zz-application/zz-winassoc-psd',
+ ],
'ice' => 'x-conference/x-cooltalk',
'iges' => 'model/iges',
'igs' => 'model/iges',
@@ -358,13 +363,6 @@ class Response implements ResponseInterface
'bmp' => 'image/bmp',
];
- /**
- * Protocol header to send to the client
- *
- * @var string
- */
- protected $_protocol = 'HTTP/1.1';
-
/**
* Status code to send to the client
*
@@ -375,7 +373,7 @@ class Response implements ResponseInterface
/**
* File object for file to be read out as response
*
- * @var \Cake\Filesystem\File|null
+ * @var \SplFileInfo|null
*/
protected $_file;
@@ -406,7 +404,7 @@ class Response implements ResponseInterface
*
* @var \Cake\Http\Cookie\CookieCollection
*/
- protected $_cookies = null;
+ protected $_cookies;
/**
* Reason Phrase
@@ -433,8 +431,8 @@ class Response implements ResponseInterface
* Constructor
*
* @param array $options list of parameters to setup the response. Possible values are:
+ *
* - body: the response text that should be sent to the client
- * - statusCodes: additional allowable response codes
* - status: the HTTP status code to respond with
* - type: a complete mime-type string or an extension mapped in this class
* - charset: the charset for the response body
@@ -459,9 +457,6 @@ public function __construct(array $options = [])
if (isset($options['body'])) {
$this->stream->write($options['body']);
}
- if (isset($options['statusCodes'])) {
- $this->httpCodes($options['statusCodes']);
- }
if (isset($options['status'])) {
$this->_setStatus($options['status']);
}
@@ -482,99 +477,11 @@ public function __construct(array $options = [])
*
* @return void
*/
- protected function _createStream()
+ protected function _createStream(): void
{
$this->stream = new Stream($this->_streamTarget, $this->_streamMode);
}
- /**
- * Sends the complete response to the client including headers and message body.
- * Will echo out the content in the response body.
- *
- * @return void
- * @deprecated 3.4.0 Will be removed in 4.0.0. Use Cake\Http\ResponseEmitter if required
- */
- public function send()
- {
- deprecationWarning('Response::send() will be removed in 4.0.0');
-
- if ($this->hasHeader('Location') && $this->_status === 200) {
- $this->statusCode(302);
- }
-
- $this->_setContent();
- $this->sendHeaders();
-
- if ($this->_file) {
- $this->_sendFile($this->_file, $this->_fileRange);
- $this->_file = null;
- $this->_fileRange = [];
- } else {
- $this->_sendContent($this->getBody());
- }
-
- if (function_exists('fastcgi_finish_request')) {
- fastcgi_finish_request();
- }
- }
-
- /**
- * Sends the HTTP headers and cookies.
- *
- * @return void
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- public function sendHeaders()
- {
- deprecationWarning(
- 'Will be removed in 4.0.0'
- );
-
- $file = $line = null;
- if (headers_sent($file, $line)) {
- Log::warning("Headers already sent in {$file}:{$line}");
-
- return;
- }
-
- $codeMessage = $this->_statusCodes[$this->_status];
- $this->_setCookies();
- $this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}");
-
- foreach ($this->headers as $header => $values) {
- foreach ((array)$values as $value) {
- $this->_sendHeader($header, $value);
- }
- }
- }
-
- /**
- * Sets the cookies that have been added via Cake\Http\Response::cookie() before any
- * other output is sent to the client. Will set the cookies in the order they
- * have been set.
- *
- * @return void
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- protected function _setCookies()
- {
- deprecationWarning(
- 'Will be removed in 4.0.0'
- );
-
- foreach ($this->_cookies as $cookie) {
- setcookie(
- $cookie->getName(),
- $cookie->getValue(),
- $cookie->getExpiresTimestamp(),
- $cookie->getPath(),
- $cookie->getDomain(),
- $cookie->isSecure(),
- $cookie->isHttpOnly()
- );
- }
- }
-
/**
* Formats the Content-Type header based on the configured contentType and charset
* the charset will only be set in the header if the response is of type text/*
@@ -582,9 +489,9 @@ protected function _setCookies()
* @param string $type The type to set.
* @return void
*/
- protected function _setContentType($type)
+ protected function _setContentType(string $type): void
{
- if (in_array($this->_status, [304, 204])) {
+ if (in_array($this->_status, [304, 204], true)) {
$this->_clearHeader('Content-Type');
return;
@@ -611,199 +518,6 @@ protected function _setContentType($type)
}
}
- /**
- * Sets the response body to an empty text if the status code is 204 or 304
- *
- * @return void
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- protected function _setContent()
- {
- deprecationWarning(
- 'Will be removed in 4.0.0'
- );
-
- if (in_array($this->_status, [304, 204])) {
- $this->body('');
- }
- }
-
- /**
- * Sends a header to the client.
- *
- * @param string $name the header name
- * @param string|null $value the header value
- * @return void
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- protected function _sendHeader($name, $value = null)
- {
- deprecationWarning(
- 'Will be removed in 4.0.0'
- );
-
- if ($value === null) {
- header($name);
- } else {
- header("{$name}: {$value}");
- }
- }
-
- /**
- * Sends a content string to the client.
- *
- * If the content is a callable, it is invoked. The callable should either
- * return a string or output content directly and have no return value.
- *
- * @param string|callable $content String to send as response body or callable
- * which returns/outputs content.
- * @return void
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- protected function _sendContent($content)
- {
- deprecationWarning(
- 'Will be removed in 4.0.0'
- );
-
- if (!is_string($content) && is_callable($content)) {
- $content = $content();
- }
-
- echo $content;
- }
-
- /**
- * Buffers a header string to be sent
- * Returns the complete list of buffered headers
- *
- * ### Single header
- * ```
- * header('Location', 'http://example.com');
- * ```
- *
- * ### Multiple headers
- * ```
- * header(['Location' => 'http://example.com', 'X-Extra' => 'My header']);
- * ```
- *
- * ### String header
- * ```
- * header('WWW-Authenticate: Negotiate');
- * ```
- *
- * ### Array of string headers
- * ```
- * header(['WWW-Authenticate: Negotiate', 'Content-type: application/pdf']);
- * ```
- *
- * Multiple calls for setting the same header name will have the same effect as setting the header once
- * with the last value sent for it
- * ```
- * header('WWW-Authenticate: Negotiate');
- * header('WWW-Authenticate: Not-Negotiate');
- * ```
- * will have the same effect as only doing
- * ```
- * header('WWW-Authenticate: Not-Negotiate');
- * ```
- *
- * @param string|array|null $header An array of header strings or a single header string
- * - an associative array of "header name" => "header value" is also accepted
- * - an array of string headers is also accepted
- * @param string|array|null $value The header value(s)
- * @return array List of headers to be sent
- * @deprecated 3.4.0 Use `withHeader()`, `getHeaderLine()` and `getHeaders()` instead.
- */
- public function header($header = null, $value = null)
- {
- deprecationWarning(
- 'Response::header() is deprecated. ' .
- 'Use `withHeader()`, `getHeaderLine()` and `getHeaders()` instead.'
- );
-
- if ($header === null) {
- return $this->getSimpleHeaders();
- }
-
- $headers = is_array($header) ? $header : [$header => $value];
- foreach ($headers as $header => $value) {
- if (is_numeric($header)) {
- list($header, $value) = [$value, null];
- }
- if ($value === null) {
- list($header, $value) = explode(':', $header, 2);
- }
-
- $lower = strtolower($header);
- if (array_key_exists($lower, $this->headerNames)) {
- $header = $this->headerNames[$lower];
- } else {
- $this->headerNames[$lower] = $header;
- }
-
- $this->headers[$header] = is_array($value) ? array_map('trim', $value) : [trim($value)];
- }
-
- return $this->getSimpleHeaders();
- }
-
- /**
- * Backwards compatibility helper for getting flattened headers.
- *
- * Previously CakePHP would store headers as a simple dictionary, now that
- * we're supporting PSR7, the internal storage has each header as an array.
- *
- * @return array
- */
- protected function getSimpleHeaders()
- {
- $out = [];
- foreach ($this->headers as $key => $values) {
- $header = $this->headerNames[strtolower($key)];
- if (count($values) === 1) {
- $values = $values[0];
- }
- $out[$header] = $values;
- }
-
- return $out;
- }
-
- /**
- * Accessor for the location header.
- *
- * Get/Set the Location header value.
- *
- * @param string|null $url Either null to get the current location, or a string to set one.
- * @return string|null When setting the location null will be returned. When reading the location
- * a string of the current location header value (if any) will be returned.
- * @deprecated 3.4.0 Mutable responses are deprecated. Use `withLocation()` and `getHeaderLine()`
- * instead.
- */
- public function location($url = null)
- {
- deprecationWarning(
- 'Response::location() is deprecated. ' .
- 'Mutable responses are deprecated. Use `withLocation()` and `getHeaderLine()` instead.'
- );
-
- if ($url === null) {
- $result = $this->getHeaderLine('Location');
- if (!$result) {
- return null;
- }
-
- return $result;
- }
- if ($this->_status === 200) {
- $this->_status = 302;
- }
- $this->_setHeader('Location', $url);
-
- return null;
- }
-
/**
* Return an instance with an updated location header.
*
@@ -813,7 +527,7 @@ public function location($url = null)
* @param string $url The location to redirect to.
* @return static A new response with the Location header set.
*/
- public function withLocation($url)
+ public function withLocation(string $url)
{
$new = $this->withHeader('Location', $url);
if ($new->_status === 200) {
@@ -830,7 +544,7 @@ public function withLocation($url)
* @param string $value Header value.
* @return void
*/
- protected function _setHeader($header, $value)
+ protected function _setHeader(string $header, string $value): void
{
$normalized = strtolower($header);
$this->headerNames[$normalized] = $header;
@@ -843,7 +557,7 @@ protected function _setHeader($header, $value)
* @param string $header Header key.
* @return void
*/
- protected function _clearHeader($header)
+ protected function _clearHeader(string $header): void
{
$normalized = strtolower($header);
if (!isset($this->headerNames[$normalized])) {
@@ -853,94 +567,6 @@ protected function _clearHeader($header)
unset($this->headerNames[$normalized], $this->headers[$original]);
}
- /**
- * Buffers the response message to be sent
- * if $content is null the current buffer is returned
- *
- * @param string|callable|null $content the string or callable message to be sent
- * @return string|null Current message buffer if $content param is passed as null
- * @deprecated 3.4.0 Mutable response methods are deprecated. Use `withBody()`/`withStringBody()` and `getBody()` instead.
- */
- public function body($content = null)
- {
- deprecationWarning(
- 'Response::body() is deprecated. ' .
- 'Mutable response methods are deprecated. Use `withBody()` and `getBody()` instead.'
- );
-
- if ($content === null) {
- if ($this->stream->isSeekable()) {
- $this->stream->rewind();
- }
- $result = $this->stream->getContents();
- if (strlen($result) === 0) {
- return null;
- }
-
- return $result;
- }
-
- // Compatibility with closure/streaming responses
- if (!is_string($content) && is_callable($content)) {
- $this->stream = new CallbackStream($content);
- } else {
- $this->_createStream();
- $this->stream->write($content);
- }
-
- return $content;
- }
-
- /**
- * Handles the callable body for backward compatibility reasons.
- *
- * @param callable $content Callable content.
- * @return string
- */
- protected function _handleCallableBody(callable $content)
- {
- ob_start();
- $result1 = $content();
- $result2 = ob_get_contents();
- ob_get_clean();
-
- if ($result1) {
- return $result1;
- }
-
- return $result2;
- }
-
- /**
- * Sets the HTTP status code to be sent.
- * If $code is null the current code is returned
- *
- * If the status code is 304 or 204, the existing Content-Type header
- * will be cleared, as these response codes have no body.
- *
- * @param int|null $code the HTTP status code
- * @return int Current status code
- * @throws \InvalidArgumentException When an unknown status code is reached.
- * @deprecated 3.4.0 Use `getStatusCode()` and `withStatus()` instead.
- */
- public function statusCode($code = null)
- {
- deprecationWarning(
- 'Response::statusCode() is deprecated. ' .
- 'Use `getStatusCode()` and `withStatus()` instead.'
- );
-
- if ($code === null) {
- return $this->_status;
- }
- if (!isset($this->_statusCodes[$code])) {
- throw new InvalidArgumentException('Unknown status code');
- }
- $this->_setStatus($code);
-
- return $code;
- }
-
/**
* Gets the response status code.
*
@@ -949,7 +575,7 @@ public function statusCode($code = null)
*
* @return int Status code.
*/
- public function getStatusCode()
+ public function getStatusCode(): int
{
return $this->_status;
}
@@ -999,7 +625,7 @@ public function withStatus($code, $reasonPhrase = '')
* @return void
* @throws \InvalidArgumentException For invalid status code arguments.
*/
- protected function _setStatus($code, $reasonPhrase = '')
+ protected function _setStatus(int $code, string $reasonPhrase = ''): void
{
if ($code < static::STATUS_CODE_MIN || $code > static::STATUS_CODE_MAX) {
throw new InvalidArgumentException(sprintf(
@@ -1033,132 +659,11 @@ protected function _setStatus($code, $reasonPhrase = '')
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
* @return string Reason phrase; must return an empty string if none present.
*/
- public function getReasonPhrase()
+ public function getReasonPhrase(): string
{
return $this->_reasonPhrase;
}
- /**
- * Queries & sets valid HTTP response codes & messages.
- *
- * @param int|array|null $code If $code is an integer, then the corresponding code/message is
- * returned if it exists, null if it does not exist. If $code is an array, then the
- * keys are used as codes and the values as messages to add to the default HTTP
- * codes. The codes must be integers greater than 99 and less than 1000. Keep in
- * mind that the HTTP specification outlines that status codes begin with a digit
- * between 1 and 5, which defines the class of response the client is to expect.
- * Example:
- *
- * httpCodes(404); // returns [404 => 'Not Found']
- *
- * httpCodes([
- * 381 => 'Unicorn Moved',
- * 555 => 'Unexpected Minotaur'
- * ]); // sets these new values, and returns true
- *
- * httpCodes([
- * 0 => 'Nothing Here',
- * -1 => 'Reverse Infinity',
- * 12345 => 'Universal Password',
- * 'Hello' => 'World'
- * ]); // throws an exception due to invalid codes
- *
- * For more on HTTP status codes see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
- * @return mixed Associative array of the HTTP codes as keys, and the message
- * strings as values, or null of the given $code does not exist.
- * @throws \InvalidArgumentException If an attempt is made to add an invalid status code
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- public function httpCodes($code = null)
- {
- deprecationWarning('Response::httpCodes(). Will be removed in 4.0.0');
-
- if (empty($code)) {
- return $this->_statusCodes;
- }
- if (is_array($code)) {
- $codes = array_keys($code);
- $min = min($codes);
- if (!is_int($min) || $min < 100 || max($codes) > 999) {
- throw new InvalidArgumentException('Invalid status code');
- }
- $this->_statusCodes = $code + $this->_statusCodes;
-
- return true;
- }
- if (!isset($this->_statusCodes[$code])) {
- return null;
- }
-
- return [$code => $this->_statusCodes[$code]];
- }
-
- /**
- * Sets the response content type. It can be either a file extension
- * which will be mapped internally to a mime-type or a string representing a mime-type
- * if $contentType is null the current content type is returned
- * if $contentType is an associative array, content type definitions will be stored/replaced
- *
- * ### Setting the content type
- *
- * ```
- * type('jpg');
- * ```
- *
- * If you attempt to set the type on a 304 or 204 status code response, the
- * content type will not take effect as these status codes do not have content-types.
- *
- * ### Returning the current content type
- *
- * ```
- * type();
- * ```
- *
- * ### Storing content type definitions
- *
- * ```
- * type(['keynote' => 'application/keynote', 'bat' => 'application/bat']);
- * ```
- *
- * ### Replacing a content type definition
- *
- * ```
- * type(['jpg' => 'text/plain']);
- * ```
- *
- * @param string|array|null $contentType Content type key.
- * @return mixed Current content type or false if supplied an invalid content type.
- * @deprecated 3.5.5 Use getType() or withType() instead.
- */
- public function type($contentType = null)
- {
- deprecationWarning(
- 'Response::type() is deprecated. ' .
- 'Use setTypeMap(), getType() or withType() instead.'
- );
-
- if ($contentType === null) {
- return $this->getType();
- }
- if (is_array($contentType)) {
- foreach ($contentType as $type => $definition) {
- $this->_mimeTypes[$type] = $definition;
- }
-
- return $this->getType();
- }
- if (isset($this->_mimeTypes[$contentType])) {
- $contentType = $this->_mimeTypes[$contentType];
- $contentType = is_array($contentType) ? current($contentType) : $contentType;
- }
- if (strpos($contentType, '/') === false) {
- return false;
- }
- $this->_setContentType($contentType);
-
- return $contentType;
- }
-
/**
* Sets a content type definition into the map.
*
@@ -1170,7 +675,7 @@ public function type($contentType = null)
* @param string|array $mimeType Definition of the mime type.
* @return void
*/
- public function setTypeMap($type, $mimeType)
+ public function setTypeMap(string $type, $mimeType): void
{
$this->_mimeTypes[$type] = $mimeType;
}
@@ -1180,7 +685,7 @@ public function setTypeMap($type, $mimeType)
*
* @return string
*/
- public function getType()
+ public function getType(): string
{
$header = $this->getHeaderLine('Content-Type');
if (strpos($header, ';') !== false) {
@@ -1199,7 +704,7 @@ public function getType()
* @param string $contentType Either a file extension which will be mapped to a mime-type or a concrete mime-type.
* @return static
*/
- public function withType($contentType)
+ public function withType(string $contentType)
{
$mappedType = $this->resolveType($contentType);
$new = clone $this;
@@ -1215,7 +720,7 @@ public function withType($contentType)
* @return string The resolved content-type
* @throws \InvalidArgumentException When an invalid content-type or alias is used.
*/
- protected function resolveType($contentType)
+ protected function resolveType(string $contentType): string
{
$mapped = $this->getMimeType($contentType);
if ($mapped) {
@@ -1236,7 +741,7 @@ protected function resolveType($contentType)
* @param string $alias the content type alias to map
* @return string|array|false String mapped mime type or false if $alias is not mapped
*/
- public function getMimeType($alias)
+ public function getMimeType(string $alias)
{
if (isset($this->_mimeTypes[$alias])) {
return $this->_mimeTypes[$alias];
@@ -1260,7 +765,7 @@ public function mapType($ctype)
}
foreach ($this->_mimeTypes as $alias => $types) {
- if (in_array($ctype, (array)$types)) {
+ if (in_array($ctype, (array)$types, true)) {
return $alias;
}
}
@@ -1268,36 +773,12 @@ public function mapType($ctype)
return null;
}
- /**
- * Sets the response charset
- * if $charset is null the current charset is returned
- *
- * @param string|null $charset Character set string.
- * @return string Current charset
- * @deprecated 3.5.0 Use getCharset()/withCharset() instead.
- */
- public function charset($charset = null)
- {
- deprecationWarning(
- 'Response::charset() is deprecated. ' .
- 'Use getCharset()/withCharset() instead.'
- );
-
- if ($charset === null) {
- return $this->_charset;
- }
- $this->_charset = $charset;
- $this->_setContentType($this->getType());
-
- return $this->_charset;
- }
-
/**
* Returns the current charset.
*
* @return string
*/
- public function getCharset()
+ public function getCharset(): string
{
return $this->_charset;
}
@@ -1308,7 +789,7 @@ public function getCharset()
* @param string $charset Character set string.
* @return static
*/
- public function withCharset($charset)
+ public function withCharset(string $charset)
{
$new = clone $this;
$new->_charset = $charset;
@@ -1317,24 +798,6 @@ public function withCharset($charset)
return $new;
}
- /**
- * Sets the correct headers to instruct the client to not cache the response
- *
- * @return void
- * @deprecated 3.4.0 Use withDisabledCache() instead.
- */
- public function disableCache()
- {
- deprecationWarning(
- 'Response::disableCache() is deprecated. ' .
- 'Use withDisabledCache() instead.'
- );
-
- $this->_setHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT');
- $this->_setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
- $this->_setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
- }
-
/**
* Create a new instance with headers to instruct the client to not cache the response
*
@@ -1348,101 +811,28 @@ public function withDisabledCache()
}
/**
- * Sets the correct headers to instruct the client to cache the response.
+ * Create a new instance with the headers to enable client caching.
*
- * @param string|int|\DateTimeInterface|null $since a valid time since the response text has not been modified
- * @param string|int $time a valid time for cache expiry
- * @return void
- * @throws \InvalidArgumentException
- * @deprecated 3.4.0 Use withCache() instead.
+ * @param int|string $since a valid time since the response text has not been modified
+ * @param int|string $time a valid time for cache expiry
+ * @return static
*/
- public function cache($since, $time = '+1 day')
+ public function withCache($since, $time = '+1 day')
{
- deprecationWarning(
- 'Response::cache() is deprecated. ' .
- 'Use withCache() instead.'
- );
-
if (!is_int($time)) {
$time = strtotime($time);
if ($time === false) {
- throw new InvalidArgumentException('Invalid time parameter. Ensure your time value can be parsed by strtotime');
+ throw new InvalidArgumentException(
+ 'Invalid time parameter. Ensure your time value can be parsed by strtotime'
+ );
}
}
- $this->_setHeader('Date', gmdate('D, d M Y H:i:s ', time()) . 'GMT');
-
- $this->modified($since);
- $this->expires($time);
- $this->sharable(true);
- $this->maxAge($time - time());
- }
-
- /**
- * Create a new instance with the headers to enable client caching.
- *
- * @param string|int|\DateTimeInterface|null $since A valid time since the response text has not been modified
- * @param string|int $time A valid time for cache expiry
- * @return static
- * @throws \InvalidArgumentException
- */
- public function withCache($since, $time = '+1 day')
- {
- if (!is_int($time)) {
- $time = strtotime($time);
- if ($time === false) {
- throw new InvalidArgumentException('Invalid time parameter. Ensure your time value can be parsed by strtotime');
- }
- }
-
- return $this->withHeader('Date', gmdate('D, d M Y H:i:s ', time()) . 'GMT')
- ->withModified($since)
- ->withExpires($time)
- ->withSharable(true)
- ->withMaxAge($time - time());
- }
-
- /**
- * Sets whether a response is eligible to be cached by intermediate proxies
- * This method controls the `public` or `private` directive in the Cache-Control
- * header
- *
- * @param bool|null $public If set to true, the Cache-Control header will be set as public
- * if set to false, the response will be set to private
- * if no value is provided, it will return whether the response is sharable or not
- * @param int|null $time time in seconds after which the response should no longer be considered fresh
- * @return bool|null
- */
- public function sharable($public = null, $time = null)
- {
- deprecationWarning(
- 'Response::sharable() is deprecated. ' .
- 'Use withSharable() instead.'
- );
- if ($public === null) {
- $public = array_key_exists('public', $this->_cacheDirectives);
- $private = array_key_exists('private', $this->_cacheDirectives);
- $noCache = array_key_exists('no-cache', $this->_cacheDirectives);
- if (!$public && !$private && !$noCache) {
- return null;
- }
-
- return $public || !($private || $noCache);
- }
- if ($public) {
- $this->_cacheDirectives['public'] = true;
- unset($this->_cacheDirectives['private']);
- } else {
- $this->_cacheDirectives['private'] = true;
- unset($this->_cacheDirectives['public']);
- }
-
- $this->maxAge($time);
- if (!$time) {
- $this->_setCacheControl();
- }
-
- return (bool)$public;
+ return $this->withHeader('Date', gmdate('D, j M Y G:i:s ', time()) . 'GMT')
+ ->withModified($since)
+ ->withExpires($time)
+ ->withSharable(true)
+ ->withMaxAge($time - time());
}
/**
@@ -1453,7 +843,7 @@ public function sharable($public = null, $time = null)
* @param int|null $time time in seconds after which the response should no longer be considered fresh.
* @return static
*/
- public function withSharable($public, $time = null)
+ public function withSharable(bool $public, ?int $time = null)
{
$new = clone $this;
unset($new->_cacheDirectives['private'], $new->_cacheDirectives['public']);
@@ -1469,34 +859,6 @@ public function withSharable($public, $time = null)
return $new;
}
- /**
- * Sets the Cache-Control s-maxage directive.
- *
- * The max-age is the number of seconds after which the response should no longer be considered
- * a good candidate to be fetched from a shared cache (like in a proxy server).
- * If called with no parameters, this function will return the current max-age value if any
- *
- * @deprecated 3.6.5 Use withSharedMaxAge() instead.
- * @param int|null $seconds if null, the method will return the current s-maxage value
- * @return int|null
- */
- public function sharedMaxAge($seconds = null)
- {
- deprecationWarning(
- 'Response::sharedMaxAge() is deprecated. ' .
- 'Use withSharedMaxAge() instead.'
- );
- if ($seconds !== null) {
- $this->_cacheDirectives['s-maxage'] = $seconds;
- $this->_setCacheControl();
- }
- if (isset($this->_cacheDirectives['s-maxage'])) {
- return $this->_cacheDirectives['s-maxage'];
- }
-
- return null;
- }
-
/**
* Create a new instance with the Cache-Control s-maxage directive.
*
@@ -1506,7 +868,7 @@ public function sharedMaxAge($seconds = null)
* @param int $seconds The number of seconds for shared max-age
* @return static
*/
- public function withSharedMaxAge($seconds)
+ public function withSharedMaxAge(int $seconds)
{
$new = clone $this;
$new->_cacheDirectives['s-maxage'] = $seconds;
@@ -1515,33 +877,6 @@ public function withSharedMaxAge($seconds)
return $new;
}
- /**
- * Sets the Cache-Control max-age directive.
- * The max-age is the number of seconds after which the response should no longer be considered
- * a good candidate to be fetched from the local (client) cache.
- * If called with no parameters, this function will return the current max-age value if any
- *
- * @deprecated 3.6.5 Use withMaxAge() instead.
- * @param int|null $seconds if null, the method will return the current max-age value
- * @return int|null
- */
- public function maxAge($seconds = null)
- {
- deprecationWarning(
- 'Response::maxAge() is deprecated. ' .
- 'Use withMaxAge() instead.'
- );
- if ($seconds !== null) {
- $this->_cacheDirectives['max-age'] = $seconds;
- $this->_setCacheControl();
- }
- if (isset($this->_cacheDirectives['max-age'])) {
- return $this->_cacheDirectives['max-age'];
- }
-
- return null;
- }
-
/**
* Create an instance with Cache-Control max-age directive set.
*
@@ -1551,7 +886,7 @@ public function maxAge($seconds = null)
* @param int $seconds The seconds a cached response can be considered valid
* @return static
*/
- public function withMaxAge($seconds)
+ public function withMaxAge(int $seconds)
{
$new = clone $this;
$new->_cacheDirectives['max-age'] = $seconds;
@@ -1560,37 +895,6 @@ public function withMaxAge($seconds)
return $new;
}
- /**
- * Sets the Cache-Control must-revalidate directive.
- * must-revalidate indicates that the response should not be served
- * stale by a cache under any circumstance without first revalidating
- * with the origin.
- * If called with no parameters, this function will return whether must-revalidate is present.
- *
- * @param bool|null $enable if null, the method will return the current
- * must-revalidate value. If boolean sets or unsets the directive.
- * @return bool
- * @deprecated 3.4.0 Use withMustRevalidate() instead.
- */
- public function mustRevalidate($enable = null)
- {
- deprecationWarning(
- 'Response::mustRevalidate() is deprecated. ' .
- 'Use withMustRevalidate() instead.'
- );
-
- if ($enable !== null) {
- if ($enable) {
- $this->_cacheDirectives['must-revalidate'] = true;
- } else {
- unset($this->_cacheDirectives['must-revalidate']);
- }
- $this->_setCacheControl();
- }
-
- return array_key_exists('must-revalidate', $this->_cacheDirectives);
- }
-
/**
* Create an instance with Cache-Control must-revalidate directive set.
*
@@ -1602,7 +906,7 @@ public function mustRevalidate($enable = null)
* @param bool $enable If boolean sets or unsets the directive.
* @return static
*/
- public function withMustRevalidate($enable)
+ public function withMustRevalidate(bool $enable)
{
$new = clone $this;
if ($enable) {
@@ -1621,7 +925,7 @@ public function withMustRevalidate($enable)
*
* @return void
*/
- protected function _setCacheControl()
+ protected function _setCacheControl(): void
{
$control = '';
foreach ($this->_cacheDirectives as $key => $val) {
@@ -1632,39 +936,6 @@ protected function _setCacheControl()
$this->_setHeader('Cache-Control', $control);
}
- /**
- * Sets the Expires header for the response by taking an expiration time
- * If called with no parameters it will return the current Expires value
- *
- * ### Examples:
- *
- * `$response->expires('now')` Will Expire the response cache now
- * `$response->expires(new DateTime('+1 day'))` Will set the expiration in next 24 hours
- * `$response->expires()` Will return the current expiration header value
- *
- * @param string|int|\DateTimeInterface|null $time Valid time string or \DateTime instance.
- * @return string|null
- * @deprecated 3.4.0 Use withExpires() instead.
- */
- public function expires($time = null)
- {
- deprecationWarning(
- 'Response::expires() is deprecated. ' .
- 'Use withExpires() instead.'
- );
-
- if ($time !== null) {
- $date = $this->_getUTCDate($time);
- $this->_setHeader('Expires', $date->format('D, j M Y H:i:s') . ' GMT');
- }
-
- if ($this->hasHeader('Expires')) {
- return $this->getHeaderLine('Expires');
- }
-
- return null;
- }
-
/**
* Create a new instance with the Expires header set.
*
@@ -1688,39 +959,6 @@ public function withExpires($time)
return $this->withHeader('Expires', $date->format('D, j M Y H:i:s') . ' GMT');
}
- /**
- * Sets the Last-Modified header for the response by taking a modification time
- * If called with no parameters it will return the current Last-Modified value
- *
- * ### Examples:
- *
- * `$response->modified('now')` Will set the Last-Modified to the current time
- * `$response->modified(new DateTime('+1 day'))` Will set the modification date in the past 24 hours
- * `$response->modified()` Will return the current Last-Modified header value
- *
- * @param string|int|\DateTimeInterface|null $time Valid time string or \DateTime instance.
- * @return string|null
- * @deprecated 3.4.0 Use withModified() instead.
- */
- public function modified($time = null)
- {
- deprecationWarning(
- 'Response::modified() is deprecated. ' .
- 'Use withModified() or getHeaderLine("Last-Modified") instead.'
- );
-
- if ($time !== null) {
- $date = $this->_getUTCDate($time);
- $this->_setHeader('Last-Modified', $date->format('D, j M Y H:i:s') . ' GMT');
- }
-
- if ($this->hasHeader('Last-Modified')) {
- return $this->getHeaderLine('Last-Modified');
- }
-
- return null;
- }
-
/**
* Create a new instance with the Last-Modified header set.
*
@@ -1734,7 +972,7 @@ public function modified($time = null)
* $response->withModified(new DateTime('+1 day'))
* ```
*
- * @param string|int|\DateTimeInterface|null $time Valid time string or \DateTimeInterface instance.
+ * @param int|string|\DateTimeInterface $time Valid time string or \DateTime instance.
* @return static
*/
public function withModified($time)
@@ -1753,7 +991,7 @@ public function withModified($time)
*
* @return void
*/
- public function notModified()
+ public function notModified(): void
{
$this->_createStream();
$this->_setStatus(304);
@@ -1801,36 +1039,6 @@ public function withNotModified()
return $new;
}
- /**
- * Sets the Vary header for the response, if an array is passed,
- * values will be imploded into a comma separated string. If no
- * parameters are passed, then an array with the current Vary header
- * value is returned
- *
- * @param string|array|null $cacheVariances A single Vary string or an array
- * containing the list for variances.
- * @return array|null
- * @deprecated 3.4.0 Use withVary() instead.
- */
- public function vary($cacheVariances = null)
- {
- deprecationWarning(
- 'Response::vary() is deprecated. ' .
- 'Use withVary() instead.'
- );
-
- if ($cacheVariances !== null) {
- $cacheVariances = (array)$cacheVariances;
- $this->_setHeader('Vary', implode(', ', $cacheVariances));
- }
-
- if ($this->hasHeader('Vary')) {
- return explode(', ', $this->getHeaderLine('Vary'));
- }
-
- return null;
- }
-
/**
* Create a new instance with the Vary header set.
*
@@ -1847,46 +1055,6 @@ public function withVary($cacheVariances)
return $this->withHeader('Vary', (array)$cacheVariances);
}
- /**
- * Sets the response Etag, Etags are a strong indicative that a response
- * can be cached by a HTTP client. A bad way of generating Etags is
- * creating a hash of the response output, instead generate a unique
- * hash of the unique components that identifies a request, such as a
- * modification time, a resource Id, and anything else you consider it
- * makes it unique.
- *
- * Second parameter is used to instruct clients that the content has
- * changed, but semantically, it can be used as the same thing. Think
- * for instance of a page with a hit counter, two different page views
- * are equivalent, but they differ by a few bytes. This leaves off to
- * the Client the decision of using or not the cached page.
- *
- * If no parameters are passed, current Etag header is returned.
- *
- * @param string|null $hash The unique hash that identifies this response
- * @param bool $weak Whether the response is semantically the same as
- * other with the same hash or not
- * @return string|null
- * @deprecated 3.4.0 Use withEtag() instead.
- */
- public function etag($hash = null, $weak = false)
- {
- deprecationWarning(
- 'Response::etag() is deprecated. ' .
- 'Use withEtag() or getHeaderLine("Etag") instead.'
- );
-
- if ($hash !== null) {
- $this->_setHeader('Etag', sprintf('%s"%s"', $weak ? 'W/' : null, $hash));
- }
-
- if ($this->hasHeader('Etag')) {
- return $this->getHeaderLine('Etag');
- }
-
- return null;
- }
-
/**
* Create a new instance with the Etag header set.
*
@@ -1908,9 +1076,9 @@ public function etag($hash = null, $weak = false)
* other with the same hash or not. Defaults to false
* @return static
*/
- public function withEtag($hash, $weak = false)
+ public function withEtag(string $hash, bool $weak = false)
{
- $hash = sprintf('%s"%s"', $weak ? 'W/' : null, $hash);
+ $hash = sprintf('%s"%s"', $weak ? 'W/' : '', $hash);
return $this->withHeader('Etag', $hash);
}
@@ -1922,16 +1090,17 @@ public function withEtag($hash, $weak = false)
* @param string|int|\DateTimeInterface|null $time Valid time string or \DateTimeInterface instance.
* @return \DateTimeInterface
*/
- protected function _getUTCDate($time = null)
+ protected function _getUTCDate($time = null): DateTimeInterface
{
if ($time instanceof DateTimeInterface) {
$result = clone $time;
} elseif (is_int($time)) {
$result = new DateTime(date('Y-m-d H:i:s', $time));
} else {
- $result = new DateTime($time);
+ $result = new DateTime($time ?? 'now');
}
+ /** @psalm-suppress UndefinedInterfaceMethod */
return $result->setTimezone(new DateTimeZone('UTC'));
}
@@ -1941,11 +1110,11 @@ protected function _getUTCDate($time = null)
*
* @return bool false if client does not accept compressed responses or no handler is available, true otherwise
*/
- public function compress()
+ public function compress(): bool
{
$compressionEnabled = ini_get('zlib.output_compression') !== '1' &&
extension_loaded('zlib') &&
- (strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false);
+ (strpos((string)env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false);
return $compressionEnabled && ob_start('ob_gzhandler');
}
@@ -1955,88 +1124,23 @@ public function compress()
*
* @return bool
*/
- public function outputCompressed()
+ public function outputCompressed(): bool
{
- return strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false
+ return strpos((string)env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false
&& (ini_get('zlib.output_compression') === '1' || in_array('ob_gzhandler', ob_list_handlers(), true));
}
- /**
- * Sets the correct headers to instruct the browser to download the response as a file.
- *
- * @param string $filename The name of the file as the browser will download the response
- * @return void
- * @deprecated 3.4.0 Use withDownload() instead.
- */
- public function download($filename)
- {
- deprecationWarning(
- 'Response::download() is deprecated. ' .
- 'Use withDownload() instead.'
- );
-
- $this->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
- }
-
/**
* Create a new instance with the Content-Disposition header set.
*
* @param string $filename The name of the file as the browser will download the response
* @return static
*/
- public function withDownload($filename)
+ public function withDownload(string $filename)
{
return $this->withHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
}
- /**
- * Sets the protocol to be used when sending the response. Defaults to HTTP/1.1
- * If called with no arguments, it will return the current configured protocol
- *
- * @param string|null $protocol Protocol to be used for sending response.
- * @return string Protocol currently set
- * @deprecated 3.4.0 Use getProtocolVersion() instead.
- */
- public function protocol($protocol = null)
- {
- deprecationWarning(
- 'Response::protocol() is deprecated. ' .
- 'Use getProtocolVersion() instead.'
- );
-
- if ($protocol !== null) {
- $this->_protocol = $protocol;
- }
-
- return $this->_protocol;
- }
-
- /**
- * Sets the Content-Length header for the response
- * If called with no arguments returns the last Content-Length set
- *
- * @param int|null $bytes Number of bytes
- * @return string|null
- * @deprecated 3.4.0 Use withLength() to set length instead.
- */
- public function length($bytes = null)
- {
- deprecationWarning(
- 'Response::length() is deprecated. ' .
- 'Use withLength() instead.'
- );
-
- if ($bytes !== null) {
- $this->_setHeader('Content-Length', $bytes);
- }
-
- if ($this->hasHeader('Content-Length')) {
- return $this->getHeaderLine('Content-Length');
- }
-
- return null;
- }
-
/**
* Create a new response with the Content-Length header set.
*
@@ -2070,7 +1174,7 @@ public function withLength($bytes)
* @return static
* @since 3.6.0
*/
- public function withAddedLink($url, $options = [])
+ public function withAddedLink(string $url, array $options = [])
{
$params = [];
foreach ($options as $key => $option) {
@@ -2100,7 +1204,7 @@ public function withAddedLink($url, $options = [])
* @param \Cake\Http\ServerRequest $request Request object
* @return bool Whether the response was marked as not modified or not.
*/
- public function checkNotModified(ServerRequest $request)
+ public function checkNotModified(ServerRequest $request): bool
{
$etags = preg_split('/\s*,\s*/', (string)$request->getHeaderLine('If-None-Match'), 0, PREG_SPLIT_NO_EMPTY);
$responseTag = $this->getHeaderLine('Etag');
@@ -2132,160 +1236,28 @@ public function checkNotModified(ServerRequest $request)
*
* @return string
*/
- public function __toString()
+ public function __toString(): string
{
$this->stream->rewind();
return (string)$this->stream->getContents();
}
- /**
- * Getter/Setter for cookie configs
- *
- * This method acts as a setter/getter depending on the type of the argument.
- * If the method is called with no arguments, it returns all configurations.
- *
- * If the method is called with a string as argument, it returns either the
- * given configuration if it is set, or null, if it's not set.
- *
- * If the method is called with an array as argument, it will set the cookie
- * configuration to the cookie container.
- *
- * ### Options (when setting a configuration)
- * - name: The Cookie name
- * - value: Value of the cookie
- * - expire: Time the cookie expires in
- * - path: Path the cookie applies to
- * - domain: Domain the cookie is for.
- * - secure: Is the cookie https?
- * - httpOnly: Is the cookie available in the client?
- *
- * ### Examples
- *
- * ### Getting all cookies
- *
- * `$this->cookie()`
- *
- * ### Getting a certain cookie configuration
- *
- * `$this->cookie('MyCookie')`
- *
- * ### Setting a cookie configuration
- *
- * `$this->cookie((array) $options)`
- *
- * @param array|null $options Either null to get all cookies, string for a specific cookie
- * or array to set cookie.
- * @return mixed
- * @deprecated 3.4.0 Use getCookie(), getCookies() and withCookie() instead.
- */
- public function cookie($options = null)
- {
- deprecationWarning(
- 'Response::cookie() is deprecated. ' .
- 'Use getCookie(), getCookies() and withCookie() instead.'
- );
-
- if ($options === null) {
- return $this->getCookies();
- }
-
- if (is_string($options)) {
- if (!$this->_cookies->has($options)) {
- return null;
- }
-
- $cookie = $this->_cookies->get($options);
-
- return $this->convertCookieToArray($cookie);
- }
-
- $options += [
- 'name' => 'CakeCookie[default]',
- 'value' => '',
- 'expire' => 0,
- 'path' => '/',
- 'domain' => '',
- 'secure' => false,
- 'httpOnly' => false,
- ];
- $expires = $options['expire'] ? new DateTime('@' . $options['expire']) : null;
- $cookie = new Cookie(
- $options['name'],
- $options['value'],
- $expires,
- $options['path'],
- $options['domain'],
- $options['secure'],
- $options['httpOnly']
- );
- $this->_cookies = $this->_cookies->add($cookie);
- }
-
/**
* Create a new response with a cookie set.
*
- * ### Data
- *
- * - `value`: Value of the cookie
- * - `expire`: Time the cookie expires in
- * - `path`: Path the cookie applies to
- * - `domain`: Domain the cookie is for.
- * - `secure`: Is the cookie https?
- * - `httpOnly`: Is the cookie available in the client?
- *
- * ### Examples
+ * ### Example
*
* ```
- * // set scalar value with defaults
- * $response = $response->withCookie('remember_me', 1);
- *
- * // customize cookie attributes
- * $response = $response->withCookie('remember_me', ['path' => '/login']);
- *
* // add a cookie object
* $response = $response->withCookie(new Cookie('remember_me', 1));
* ```
*
- * @param string|\Cake\Http\Cookie\Cookie $name The name of the cookie to set, or a cookie object
- * @param array|string $data Either a string value, or an array of cookie options.
+ * @param \Cake\Http\Cookie\CookieInterface $cookie cookie object
* @return static
*/
- public function withCookie($name, $data = '')
+ public function withCookie(CookieInterface $cookie)
{
- if ($name instanceof Cookie) {
- $cookie = $name;
- } else {
- deprecationWarning(
- get_called_class() . '::withCookie(string $name, array $data) is deprecated. ' .
- 'Pass an instance of \Cake\Http\Cookie\Cookie instead.'
- );
-
- if (!is_array($data)) {
- $data = ['value' => $data];
- }
- $data += [
- 'value' => '',
- 'expire' => 0,
- 'path' => '/',
- 'domain' => '',
- 'secure' => false,
- 'httpOnly' => false,
- 'samesite' => null,
- ];
- $expires = $data['expire'] ? new DateTime('@' . $data['expire']) : null;
- $cookie = new Cookie(
- $name,
- $data['value'],
- $expires,
- $data['path'],
- $data['domain'],
- $data['secure'],
- $data['httpOnly'],
- $data['samesite']
- );
- }
-
$new = clone $this;
$new->_cookies = $new->_cookies->add($cookie);
@@ -2295,57 +1267,19 @@ public function withCookie($name, $data = '')
/**
* Create a new response with an expired cookie set.
*
- * ### Options
- *
- * - `path`: Path the cookie applies to
- * - `domain`: Domain the cookie is for.
- * - `secure`: Is the cookie https?
- * - `httpOnly`: Is the cookie available in the client?
- *
- * ### Examples
+ * ### Example
*
* ```
- * // set scalar value with defaults
- * $response = $response->withExpiredCookie('remember_me');
- *
- * // customize cookie attributes
- * $response = $response->withExpiredCookie('remember_me', ['path' => '/login']);
- *
* // add a cookie object
* $response = $response->withExpiredCookie(new Cookie('remember_me'));
* ```
*
- * @param string|\Cake\Http\Cookie\CookieInterface $name The name of the cookie to expire, or a cookie object
- * @param array $options An array of cookie options.
+ * @param \Cake\Http\Cookie\CookieInterface $cookie cookie object
* @return static
*/
- public function withExpiredCookie($name, $options = [])
+ public function withExpiredCookie(CookieInterface $cookie)
{
- if ($name instanceof CookieInterface) {
- $cookie = $name->withExpired();
- } else {
- deprecationWarning(
- get_called_class() . '::withExpiredCookie(string $name, array $data) is deprecated. ' .
- 'Pass an instance of \Cake\Http\Cookie\Cookie instead.'
- );
-
- $options += [
- 'path' => '/',
- 'domain' => '',
- 'secure' => false,
- 'httpOnly' => false,
- ];
-
- $cookie = new Cookie(
- $name,
- '',
- DateTime::createFromFormat('U', 1),
- $options['path'],
- $options['domain'],
- $options['secure'],
- $options['httpOnly']
- );
- }
+ $cookie = $cookie->withExpired();
$new = clone $this;
$new->_cookies = $new->_cookies->add($cookie);
@@ -2362,15 +1296,13 @@ public function withExpiredCookie($name, $options = [])
* @param string $name The cookie name you want to read.
* @return array|null Either the cookie data or null
*/
- public function getCookie($name)
+ public function getCookie(string $name): ?array
{
if (!$this->_cookies->has($name)) {
return null;
}
- $cookie = $this->_cookies->get($name);
-
- return $this->convertCookieToArray($cookie);
+ return $this->_cookies->get($name)->toArray();
}
/**
@@ -2380,45 +1312,24 @@ public function getCookie($name)
*
* @return array
*/
- public function getCookies()
+ public function getCookies(): array
{
$out = [];
- foreach ($this->_cookies as $cookie) {
- $out[$cookie->getName()] = $this->convertCookieToArray($cookie);
+ /** @var \Cake\Http\Cookie\Cookie[] $cookies */
+ $cookies = $this->_cookies;
+ foreach ($cookies as $cookie) {
+ $out[$cookie->getName()] = $cookie->toArray();
}
return $out;
}
- /**
- * Convert the cookie into an array of its properties.
- *
- * This method is compatible with the historical behavior of Cake\Http\Response,
- * where `httponly` is `httpOnly` and `expires` is `expire`
- *
- * @param \Cake\Http\Cookie\CookieInterface $cookie Cookie object.
- * @return array
- */
- protected function convertCookieToArray(CookieInterface $cookie)
- {
- return [
- 'name' => $cookie->getName(),
- 'value' => $cookie->getStringValue(),
- 'path' => $cookie->getPath(),
- 'domain' => $cookie->getDomain(),
- 'secure' => $cookie->isSecure(),
- 'httpOnly' => $cookie->isHttpOnly(),
- 'expire' => $cookie->getExpiresTimestamp(),
- 'samesite' => $cookie->getSameSite(),
- ];
- }
-
/**
* Get the CookieCollection from the response
*
* @return \Cake\Http\Cookie\CookieCollection
*/
- public function getCookieCollection()
+ public function getCookieCollection(): CookieCollection
{
return $this->_cookies;
}
@@ -2438,7 +1349,7 @@ public function withCookieCollection(CookieCollection $cookieCollection)
}
/**
- * Setup access for origin and methods on cross origin requests
+ * Get a CorsBuilder instance for defining CORS headers.
*
* This method allow multiple ways to setup the domains, see the examples
*
@@ -2471,115 +1382,15 @@ public function withCookieCollection(CookieCollection $cookieCollection)
* Instead the builder object should be used.
*
* @param \Cake\Http\ServerRequest $request Request object
- * @param string|string[] $allowedDomains List of allowed domains, see method description for more details
- * @param string|string[] $allowedMethods List of HTTP verbs allowed
- * @param string|string[] $allowedHeaders List of HTTP headers allowed
* @return \Cake\Http\CorsBuilder A builder object the provides a fluent interface for defining
* additional CORS headers.
*/
- public function cors(ServerRequest $request, $allowedDomains = [], $allowedMethods = [], $allowedHeaders = [])
+ public function cors(ServerRequest $request): CorsBuilder
{
$origin = $request->getHeaderLine('Origin');
$ssl = $request->is('ssl');
- $builder = new CorsBuilder($this, $origin, $ssl);
- if (!$origin) {
- return $builder;
- }
- if (empty($allowedDomains) && empty($allowedMethods) && empty($allowedHeaders)) {
- return $builder;
- }
- deprecationWarning(
- 'The $allowedDomains, $allowedMethods, and $allowedHeaders parameters of Response::cors() ' .
- 'are deprecated. Instead you should use the builder methods on the return of cors().'
- );
-
- $updated = $builder->allowOrigin($allowedDomains)
- ->allowMethods((array)$allowedMethods)
- ->allowHeaders((array)$allowedHeaders)
- ->build();
-
- // If $updated is a new instance, mutate this object in-place
- // to retain existing behavior.
- if ($updated !== $this) {
- foreach ($updated->getHeaders() as $name => $values) {
- if (!$this->hasHeader($name)) {
- $this->_setHeader($name, $values[0]);
- }
- }
- }
- return $builder;
- }
-
- /**
- * Setup for display or download the given file.
- *
- * If $_SERVER['HTTP_RANGE'] is set a slice of the file will be
- * returned instead of the entire file.
- *
- * ### Options keys
- *
- * - name: Alternate download name
- * - download: If `true` sets download header and forces file to be downloaded rather than displayed in browser
- *
- * @param string $path Path to file. If the path is not an absolute path that resolves
- * to a file, `APP` will be prepended to the path (this behavior is deprecated).
- * @param array $options Options See above.
- * @return void
- * @throws \Cake\Http\Exception\NotFoundException
- * @deprecated 3.4.0 Use withFile() instead.
- */
- public function file($path, array $options = [])
- {
- deprecationWarning(
- 'Response::file() is deprecated. ' .
- 'Use withFile() instead.'
- );
-
- $file = $this->validateFile($path);
- $options += [
- 'name' => null,
- 'download' => null,
- ];
-
- $extension = strtolower($file->ext());
- $download = $options['download'];
- if ((!$extension || $this->type($extension) === false) && $download === null) {
- $download = true;
- }
-
- $fileSize = $file->size();
- if ($download) {
- $agent = env('HTTP_USER_AGENT');
-
- if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) {
- $contentType = 'application/octet-stream';
- } elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) {
- $contentType = 'application/force-download';
- }
-
- if (!empty($contentType)) {
- $this->type($contentType);
- }
- if ($options['name'] === null) {
- $name = $file->name;
- } else {
- $name = $options['name'];
- }
- $this->download($name);
- $this->header('Content-Transfer-Encoding', 'binary');
- }
-
- $this->header('Accept-Ranges', 'bytes');
- $httpRange = env('HTTP_RANGE');
- if (isset($httpRange)) {
- $this->_fileRange($file, $httpRange);
- } else {
- $this->header('Content-Length', $fileSize);
- }
-
- $this->_file = $file;
- $this->stream = new Stream($file->path, 'rb');
+ return new CorsBuilder($this, $origin, $ssl);
}
/**
@@ -2596,13 +1407,12 @@ public function file($path, array $options = [])
* - download: If `true` sets download header and forces file to
* be downloaded rather than displayed inline.
*
- * @param string $path Path to file. If the path is not an absolute path that resolves
- * to a file, `APP` will be prepended to the path (this behavior is deprecated).
+ * @param string $path Absolute path to file.
* @param array $options Options See above.
* @return static
* @throws \Cake\Http\Exception\NotFoundException
*/
- public function withFile($path, array $options = [])
+ public function withFile(string $path, array $options = [])
{
$file = $this->validateFile($path);
$options += [
@@ -2610,7 +1420,7 @@ public function withFile($path, array $options = [])
'download' => null,
];
- $extension = strtolower($file->ext());
+ $extension = strtolower($file->getExtension());
$mapped = $this->getMimeType($extension);
if ((!$extension || !$mapped) && $options['download'] === null) {
$options['download'] = true;
@@ -2621,33 +1431,33 @@ public function withFile($path, array $options = [])
$new = $new->withType($extension);
}
- $fileSize = $file->size();
+ $fileSize = $file->getSize();
if ($options['download']) {
- $agent = env('HTTP_USER_AGENT');
+ $agent = (string)env('HTTP_USER_AGENT');
- if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) {
+ if ($agent && preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) {
$contentType = 'application/octet-stream';
- } elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) {
+ } elseif ($agent && preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) {
$contentType = 'application/force-download';
}
if (isset($contentType)) {
$new = $new->withType($contentType);
}
- $name = $options['name'] ?: $file->name;
+ $name = $options['name'] ?: $file->getFileName();
$new = $new->withDownload($name)
->withHeader('Content-Transfer-Encoding', 'binary');
}
$new = $new->withHeader('Accept-Ranges', 'bytes');
- $httpRange = env('HTTP_RANGE');
- if (isset($httpRange)) {
+ $httpRange = (string)env('HTTP_RANGE');
+ if ($httpRange) {
$new->_fileRange($file, $httpRange);
} else {
$new = $new->withHeader('Content-Length', (string)$fileSize);
}
$new->_file = $file;
- $new->stream = new Stream($file->path, 'rb');
+ $new->stream = new Stream($file->getPathname(), 'rb');
return $new;
}
@@ -2658,7 +1468,7 @@ public function withFile($path, array $options = [])
* @param string $string The string to be sent
* @return static
*/
- public function withStringBody($string)
+ public function withStringBody(?string $string)
{
$new = clone $this;
$new->_createStream();
@@ -2672,29 +1482,16 @@ public function withStringBody($string)
*
* @param string $path The path to the file.
* @throws \Cake\Http\Exception\NotFoundException
- * @return \Cake\Filesystem\File
+ * @return \SplFileInfo
*/
- protected function validateFile($path)
+ protected function validateFile(string $path): SplFileInfo
{
if (strpos($path, '../') !== false || strpos($path, '..\\') !== false) {
throw new NotFoundException(__d('cake', 'The requested file contains `..` and will not be read.'));
}
- if (!is_file($path)) {
- deprecationWarning(
- 'Automatic prefixing of paths with `APP` by `Response::file()` and `withFile()` is deprecated. ' .
- 'Use absolute paths instead.'
- );
- $path = APP . $path;
- }
- if (!Folder::isAbsolute($path)) {
- deprecationWarning(
- 'Serving files via `file()` or `withFile()` using relative paths is deprecated.' .
- 'Use an absolute path instead.'
- );
- }
- $file = new File($path);
- if (!$file->exists() || !$file->readable()) {
+ $file = new SplFileInfo($path);
+ if (!$file->isFile() || !$file->isReadable()) {
if (Configure::read('debug')) {
throw new NotFoundException(sprintf('The requested file %s was not found or not readable', $path));
}
@@ -2707,9 +1504,9 @@ protected function validateFile($path)
/**
* Get the current file if one exists.
*
- * @return \Cake\Filesystem\File|null The file to use in the response or null
+ * @return \SplFileInfo|null The file to use in the response or null
*/
- public function getFile()
+ public function getFile(): ?SplFileInfo
{
return $this->_file;
}
@@ -2720,15 +1517,13 @@ public function getFile()
* If an invalid range is requested a 416 Status code will be used
* in the response.
*
- * @param \Cake\Filesystem\File $file The file to set a range on.
+ * @param \SplFileInfo $file The file to set a range on.
* @param string $httpRange The range to use.
* @return void
- * @deprecated 3.4.0 Long term this needs to be refactored to follow immutable paradigms.
- * However for now, it is simpler to leave this alone.
*/
- protected function _fileRange($file, $httpRange)
+ protected function _fileRange(SplFileInfo $file, string $httpRange): void
{
- $fileSize = $file->size();
+ $fileSize = $file->getSize();
$lastByte = $fileSize - 1;
$start = 0;
$end = $lastByte;
@@ -2736,11 +1531,11 @@ protected function _fileRange($file, $httpRange)
preg_match('/^bytes\s*=\s*(\d+)?\s*-\s*(\d+)?$/', $httpRange, $matches);
if ($matches) {
$start = $matches[1];
- $end = isset($matches[2]) ? $matches[2] : '';
+ $end = $matches[2] ?? '';
}
if ($start === '') {
- $start = $fileSize - $end;
+ $start = $fileSize - (int)$end;
$end = $lastByte;
}
if ($end === '') {
@@ -2754,133 +1549,20 @@ protected function _fileRange($file, $httpRange)
return;
}
- $this->_setHeader('Content-Length', $end - $start + 1);
+ /** @psalm-suppress PossiblyInvalidOperand */
+ $this->_setHeader('Content-Length', (string)($end - $start + 1));
$this->_setHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $fileSize);
$this->_setStatus(206);
$this->_fileRange = [$start, $end];
}
- /**
- * Reads out a file, and echos the content to the client.
- *
- * @param \Cake\Filesystem\File $file File object
- * @param array $range The range to read out of the file.
- * @return bool True is whole file is echoed successfully or false if client connection is lost in between
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- protected function _sendFile($file, $range)
- {
- deprecationWarning('Will be removed in 4.0.0');
-
- ob_implicit_flush(true);
-
- $file->open('rb');
-
- $end = $start = false;
- if ($range) {
- list($start, $end) = $range;
- }
- if ($start !== false) {
- $file->offset($start);
- }
-
- $bufferSize = 8192;
- if (strpos(ini_get('disable_functions'), 'set_time_limit') === false) {
- set_time_limit(0);
- }
- session_write_close();
- while (!feof($file->handle)) {
- if (!$this->_isActive()) {
- $file->close();
-
- return false;
- }
- $offset = $file->offset();
- if ($end && $offset >= $end) {
- break;
- }
- if ($end && $offset + $bufferSize >= $end) {
- $bufferSize = $end - $offset + 1;
- }
- echo fread($file->handle, $bufferSize);
- }
- $file->close();
-
- return true;
- }
-
- /**
- * Returns true if connection is still active
- *
- * @return bool
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- protected function _isActive()
- {
- deprecationWarning('Will be removed in 4.0.0');
-
- return connection_status() === CONNECTION_NORMAL && !connection_aborted();
- }
-
- /**
- * Clears the contents of the topmost output buffer and discards them
- *
- * @return bool
- * @deprecated 3.2.4 This function is not needed anymore
- */
- protected function _clearBuffer()
- {
- deprecationWarning(
- 'This function is not needed anymore and will be removed.'
- );
-
- //@codingStandardsIgnoreStart
- return @ob_end_clean();
- //@codingStandardsIgnoreEnd
- }
-
- /**
- * Flushes the contents of the output buffer
- *
- * @return void
- * @deprecated 3.2.4 This function is not needed anymore
- */
- protected function _flushBuffer()
- {
- deprecationWarning(
- 'This function is not needed anymore and will be removed.'
- );
-
- //@codingStandardsIgnoreStart
- @flush();
- if (ob_get_level()) {
- @ob_flush();
- }
- //@codingStandardsIgnoreEnd
- }
-
- /**
- * Stop execution of the current script. Wraps exit() making
- * testing easier.
- *
- * @param int|string $status See https://secure.php.net/exit for values
- * @return void
- * @deprecated 3.4.0 Will be removed in 4.0.0
- */
- public function stop($status = 0)
- {
- deprecationWarning('Will be removed in 4.0.0');
-
- exit($status);
- }
-
/**
* Returns an array that can be used to describe the internal state of this
* object.
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
return [
'status' => $this->_status,
@@ -2894,6 +1576,3 @@ public function __debugInfo()
];
}
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\Response', 'Cake\Network\Response');
diff --git a/app/vendor/cakephp/cakephp/src/Http/ResponseEmitter.php b/app/vendor/cakephp/cakephp/src/Http/ResponseEmitter.php
index 81ab6d2e7..a0779bb8a 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ResponseEmitter.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ResponseEmitter.php
@@ -1,4 +1,6 @@
maxBufferLength = $maxBufferLength;
+ }
+
+ /**
+ * Emit a response.
+ *
+ * Emits a response, including status line, headers, and the message body,
+ * according to the environment.
+ *
+ * @param \Psr\Http\Message\ResponseInterface $response The response to emit.
+ * @return bool
+ */
+ public function emit(ResponseInterface $response): bool
+ {
+ $file = '';
+ $line = 0;
if (headers_sent($file, $line)) {
$message = "Unable to emit headers. Headers sent in file=$file line=$line";
- if (Configure::read('debug')) {
- trigger_error($message, E_USER_WARNING);
- } else {
- Log::warning($message);
- }
+ trigger_error($message, E_USER_WARNING);
}
$this->emitStatusLine($response);
@@ -62,27 +77,27 @@ public function emit(ResponseInterface $response, $maxBufferLength = 8192)
$range = $this->parseContentRange($response->getHeaderLine('Content-Range'));
if (is_array($range)) {
- $this->emitBodyRange($range, $response, $maxBufferLength);
+ $this->emitBodyRange($range, $response);
} else {
- $this->emitBody($response, $maxBufferLength);
+ $this->emitBody($response);
}
if (function_exists('fastcgi_finish_request')) {
- session_write_close();
fastcgi_finish_request();
}
+
+ return true;
}
/**
* Emit the message body.
*
* @param \Psr\Http\Message\ResponseInterface $response The response to emit
- * @param int $maxBufferLength The chunk size to emit
* @return void
*/
- protected function emitBody(ResponseInterface $response, $maxBufferLength)
+ protected function emitBody(ResponseInterface $response): void
{
- if (in_array($response->getStatusCode(), [204, 304])) {
+ if (in_array($response->getStatusCode(), [204, 304], true)) {
return;
}
$body = $response->getBody();
@@ -95,7 +110,7 @@ protected function emitBody(ResponseInterface $response, $maxBufferLength)
$body->rewind();
while (!$body->eof()) {
- echo $body->read($maxBufferLength);
+ echo $body->read($this->maxBufferLength);
}
}
@@ -104,12 +119,11 @@ protected function emitBody(ResponseInterface $response, $maxBufferLength)
*
* @param array $range The range data to emit
* @param \Psr\Http\Message\ResponseInterface $response The response to emit
- * @param int $maxBufferLength The chunk size to emit
* @return void
*/
- protected function emitBodyRange(array $range, ResponseInterface $response, $maxBufferLength)
+ protected function emitBodyRange(array $range, ResponseInterface $response): void
{
- list($unit, $first, $last, $length) = $range;
+ [, $first, $last] = $range;
$body = $response->getBody();
@@ -125,12 +139,12 @@ protected function emitBodyRange(array $range, ResponseInterface $response, $max
$pos = 0;
$length = $last - $first + 1;
while (!$body->eof() && $pos < $length) {
- if (($pos + $maxBufferLength) > $length) {
+ if ($pos + $this->maxBufferLength > $length) {
echo $body->read($length - $pos);
break;
}
- echo $body->read($maxBufferLength);
+ echo $body->read($this->maxBufferLength);
$pos = $body->tell();
}
}
@@ -144,7 +158,7 @@ protected function emitBodyRange(array $range, ResponseInterface $response, $max
* @param \Psr\Http\Message\ResponseInterface $response The response to emit
* @return void
*/
- protected function emitStatusLine(ResponseInterface $response)
+ protected function emitStatusLine(ResponseInterface $response): void
{
$reasonPhrase = $response->getReasonPhrase();
header(sprintf(
@@ -166,11 +180,11 @@ protected function emitStatusLine(ResponseInterface $response)
* @param \Psr\Http\Message\ResponseInterface $response The response to emit
* @return void
*/
- protected function emitHeaders(ResponseInterface $response)
+ protected function emitHeaders(ResponseInterface $response): void
{
$cookies = [];
- if (method_exists($response, 'getCookies')) {
- $cookies = $response->getCookies();
+ if (method_exists($response, 'getCookieCollection')) {
+ $cookies = iterator_to_array($response->getCookieCollection());
}
foreach ($response->getHeaders() as $name => $values) {
@@ -195,97 +209,48 @@ protected function emitHeaders(ResponseInterface $response)
/**
* Emit cookies using setcookie()
*
- * @param array $cookies An array of Set-Cookie headers.
+ * @param (string|\Cake\Http\Cookie\CookieInterface)[] $cookies An array of cookies.
* @return void
*/
- protected function emitCookies(array $cookies)
+ protected function emitCookies(array $cookies): void
{
foreach ($cookies as $cookie) {
- if (is_array($cookie)) {
- $options = $cookie;
- $options['httponly'] = $options['httpOnly'];
- $options['expires'] = $options['expire'];
- unset($options['name'], $options['value'], $options['httpOnly'], $options['expire']);
-
- $this->setcookie(
- $cookie['name'],
- $cookie['value'],
- $options
- );
- continue;
- }
-
- if (strpos($cookie, '";"') !== false) {
- $cookie = str_replace('";"', '{__cookie_replace__}', $cookie);
- $parts = str_replace('{__cookie_replace__}', '";"', explode(';', $cookie));
- } else {
- $parts = preg_split('/\;[ \t]*/', $cookie);
- }
-
- list($name, $value) = explode('=', array_shift($parts), 2);
- $name = urldecode($name);
- $value = urldecode($value);
- $data = [
- 'expires' => 0,
- 'path' => '',
- 'domain' => '',
- 'secure' => false,
- 'httponly' => false,
- 'samesite' => null,
- ];
-
- foreach ($parts as $part) {
- if (strpos($part, '=') !== false) {
- list($key, $val) = explode('=', $part);
- } else {
- $key = $part;
- $val = true;
- }
-
- $key = strtolower($key);
- $data[$key] = $val;
- }
- if (is_string($data['expires'])) {
- $data['expires'] = strtotime($data['expires']);
- }
- unset($data['']);
-
- $this->setcookie($name, $value, $data);
+ $this->setCookie($cookie);
}
}
/**
- * Set cookies uses setcookie()
+ * Helper methods to set cookie.
*
- * @param string $name Cookie name.
- * @param string $value Cookie value.
- * @param array $options Cookie options.
- * @return void
+ * @param string|\Cake\Http\Cookie\CookieInterface $cookie Cookie.
+ * @return bool
*/
- protected function setcookie($name, $value, array $options)
+ protected function setCookie($cookie): bool
{
- if (PHP_VERSION_ID >= 70300) {
- setcookie(
- $name,
- $value,
- $options
- );
+ if (is_string($cookie)) {
+ $cookie = Cookie::createFromHeaderString($cookie, ['path' => '']);
+ }
- return;
+ if (PHP_VERSION_ID >= 70300) {
+ return setcookie($cookie->getName(), $cookie->getScalarValue(), $cookie->getOptions());
}
- if (!empty($options['samesite'])) {
- $options['path'] .= '; SameSite=' . $options['samesite'];
+ $path = $cookie->getPath();
+ $sameSite = $cookie->getSameSite();
+ if ($sameSite !== null) {
+ // Temporary hack for PHP 7.2 to set "SameSite" attribute
+ // https://stackoverflow.com/questions/39750906/php-setcookie-samesite-strict
+ $path .= '; samesite=' . $sameSite;
}
- setcookie(
- $name,
- $value,
- $options['expires'],
- $options['path'],
- $options['domain'],
- $options['secure'],
- $options['httponly']
+ return setcookie(
+ $cookie->getName(),
+ $cookie->getScalarValue(),
+ $cookie->getExpiresTimestamp() ?: 0,
+ $path,
+ $cookie->getDomain(),
+ $cookie->isSecure(),
+ $cookie->isHttpOnly()
);
}
@@ -296,9 +261,9 @@ protected function setcookie($name, $value, array $options)
* @param int|null $maxBufferLevel Flush up to this buffer level.
* @return void
*/
- protected function flush($maxBufferLevel = null)
+ protected function flush(?int $maxBufferLevel = null): void
{
- if (null === $maxBufferLevel) {
+ if ($maxBufferLevel === null) {
$maxBufferLevel = ob_get_level();
}
@@ -315,7 +280,7 @@ protected function flush($maxBufferLevel = null)
* @return array|false [unit, first, last, length]; returns false if no
* content range or an invalid content range is provided
*/
- protected function parseContentRange($header)
+ protected function parseContentRange(string $header)
{
if (preg_match('/(?P[\w]+)\s+(?P\d+)-(?P\d+)\/(?P\d+|\*)/', $header, $matches)) {
return [
diff --git a/app/vendor/cakephp/cakephp/src/Http/ResponseTransformer.php b/app/vendor/cakephp/cakephp/src/Http/ResponseTransformer.php
deleted file mode 100644
index 3bdac5113..000000000
--- a/app/vendor/cakephp/cakephp/src/Http/ResponseTransformer.php
+++ /dev/null
@@ -1,275 +0,0 @@
- $response->getStatusCode(),
- 'body' => $body['body'],
- ];
- $cake = new CakeResponse($data);
- if ($body['file']) {
- $cake->file($body['file']);
- }
- $cookies = static::parseCookies($response->getHeader('Set-Cookie'));
- foreach ($cookies as $cookie) {
- $cake->cookie($cookie);
- }
- $headers = static::collapseHeaders($response);
- $cake->header($headers);
-
- if (!empty($headers['Content-Type'])) {
- $cake->type($headers['Content-Type']);
- }
-
- return $cake;
- }
-
- /**
- * Get the response body from a PSR7 Response.
- *
- * @param \Psr\Http\Message\ResponseInterface $response The response to convert.
- * @return array A hash of 'body' and 'file'
- */
- protected static function getBody(PsrResponse $response)
- {
- $stream = $response->getBody();
- if ($stream->getMetadata('wrapper_type') === 'plainfile') {
- return ['body' => '', 'file' => $stream->getMetadata('uri')];
- }
- if ($stream->getSize() === 0) {
- return ['body' => '', 'file' => false];
- }
- $stream->rewind();
-
- return ['body' => $stream->getContents(), 'file' => false];
- }
-
- /**
- * Parse the Set-Cookie headers in a PSR7 response
- * into the format CakePHP expects.
- *
- * @param array $cookieHeader A list of Set-Cookie headers.
- * @return array Parsed cookie data.
- */
- protected static function parseCookies(array $cookieHeader)
- {
- $cookies = [];
- foreach ($cookieHeader as $cookie) {
- if (strpos($cookie, '";"') !== false) {
- $cookie = str_replace('";"', '{__cookie_replace__}', $cookie);
- $parts = preg_split('/\;[ \t]*/', $cookie);
- $parts = str_replace('{__cookie_replace__}', '";"', $parts);
- } else {
- $parts = preg_split('/\;[ \t]*/', $cookie);
- }
-
- list($name, $value) = explode('=', array_shift($parts), 2);
- $parsed = ['name' => $name, 'value' => urldecode($value)];
-
- foreach ($parts as $part) {
- if (strpos($part, '=') !== false) {
- list($key, $value) = explode('=', $part);
- } else {
- $key = $part;
- $value = true;
- }
-
- $key = strtolower($key);
- if ($key === 'httponly') {
- $key = 'httpOnly';
- }
- if ($key === 'expires') {
- $key = 'expire';
- $value = strtotime($value);
- }
- if (!isset($parsed[$key])) {
- $parsed[$key] = $value;
- }
- }
- $cookies[] = $parsed;
- }
-
- return $cookies;
- }
-
- /**
- * Convert a PSR7 Response headers into a flat array
- *
- * @param \Psr\Http\Message\ResponseInterface $response The response to convert.
- * @return array Headers.
- */
- protected static function collapseHeaders(PsrResponse $response)
- {
- $out = [];
- foreach ($response->getHeaders() as $name => $value) {
- if (count($value) === 1) {
- $out[$name] = $value[0];
- } else {
- $out[$name] = $value;
- }
- }
-
- return $out;
- }
-
- /**
- * Convert a CakePHP response into a PSR7 one.
- *
- * @param \Cake\Http\Response $response The CakePHP response to convert
- * @return \Psr\Http\Message\ResponseInterface $response The equivalent PSR7 response.
- */
- public static function toPsr(CakeResponse $response)
- {
- $status = $response->statusCode();
- $headers = $response->header();
- if (!isset($headers['Content-Type'])) {
- $headers = static::setContentType($headers, $response);
- }
- $cookies = $response->cookie();
- if ($cookies) {
- $headers['Set-Cookie'] = static::buildCookieHeader($cookies);
- }
- $stream = static::getStream($response);
-
- return new DiactorosResponse($stream, $status, $headers);
- }
-
- /**
- * Add in the Content-Type header if necessary.
- *
- * @param array $headers The headers to update
- * @param \Cake\Http\Response $response The CakePHP response to convert
- * @return array The updated headers.
- */
- protected static function setContentType($headers, $response)
- {
- if (isset($headers['Content-Type'])) {
- return $headers;
- }
- if (in_array($response->statusCode(), [204, 304])) {
- return $headers;
- }
-
- $whitelist = [
- 'application/javascript', 'application/json', 'application/xml', 'application/rss+xml',
- ];
-
- $type = $response->type();
- $charset = $response->charset();
-
- $hasCharset = false;
- if ($charset && (strpos($type, 'text/') === 0 || in_array($type, $whitelist))) {
- $hasCharset = true;
- }
-
- $value = $type;
- if ($hasCharset) {
- $value = "{$type}; charset={$charset}";
- }
- $headers['Content-Type'] = $value;
-
- return $headers;
- }
-
- /**
- * Convert an array of cookies into header lines.
- *
- * @param array $cookies The cookies to serialize.
- * @return array A list of cookie header values.
- */
- protected static function buildCookieHeader($cookies)
- {
- $headers = [];
- foreach ($cookies as $cookie) {
- $parts = [
- sprintf('%s=%s', urlencode($cookie['name']), urlencode($cookie['value'])),
- ];
- if ($cookie['expire']) {
- $cookie['expire'] = gmdate('D, d M Y H:i:s T', $cookie['expire']);
- }
- $attributes = [
- 'expire' => 'Expires=%s',
- 'path' => 'Path=%s',
- 'domain' => 'Domain=%s',
- 'httpOnly' => 'HttpOnly',
- 'secure' => 'Secure',
- ];
- foreach ($attributes as $key => $attr) {
- if ($cookie[$key]) {
- $parts[] = sprintf($attr, $cookie[$key]);
- }
- }
- $headers[] = implode('; ', $parts);
- }
-
- return $headers;
- }
-
- /**
- * Get the stream for the new response.
- *
- * @param \Cake\Http\Response $response The cake response to extract the body from.
- * @return \Psr\Http\Message\StreamInterface|string The stream.
- */
- protected static function getStream($response)
- {
- $stream = 'php://memory';
- $body = $response->body();
- if (is_string($body) && strlen($body)) {
- $stream = new Stream('php://memory', 'wb');
- $stream->write($body);
-
- return $stream;
- }
- if (is_callable($body)) {
- $stream = new CallbackStream($body);
-
- return $stream;
- }
- $file = $response->getFile();
- if ($file) {
- $stream = new Stream($file->path, 'rb');
-
- return $stream;
- }
-
- return $stream;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Runner.php b/app/vendor/cakephp/cakephp/src/Http/Runner.php
index a6eaa8146..f9ced44c3 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Runner.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Runner.php
@@ -1,4 +1,6 @@
middleware = $middleware;
- $this->index = 0;
+ public function run(
+ MiddlewareQueue $queue,
+ ServerRequestInterface $request,
+ ?RequestHandlerInterface $fallbackHandler = null
+ ): ResponseInterface {
+ $this->queue = $queue;
+ $this->queue->rewind();
+ $this->fallbackHandler = $fallbackHandler;
- return $this->__invoke($request, $response);
+ return $this->handle($request);
}
/**
+ * Handle incoming server request and return a response.
+ *
* @param \Psr\Http\Message\ServerRequestInterface $request The server request
- * @param \Psr\Http\Message\ResponseInterface $response The response object
* @return \Psr\Http\Message\ResponseInterface An updated response
*/
- public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
+ public function handle(ServerRequestInterface $request): ResponseInterface
{
- $next = $this->middleware->get($this->index);
- if ($next) {
- $this->index++;
+ if ($this->queue->valid()) {
+ $middleware = $this->queue->current();
+ $this->queue->next();
- return $next($request, $response, $this);
+ return $middleware->process($request, $this);
}
- // End of the queue
+ if ($this->fallbackHandler) {
+ return $this->fallbackHandler->handle($request);
+ }
+
+ $response = new Response([
+ 'body' => 'Middleware queue was exhausted without returning a response '
+ . 'and no fallback request handler was set for Runner',
+ 'status' => 500,
+ ]);
+
return $response;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Server.php b/app/vendor/cakephp/cakephp/src/Http/Server.php
index ac286f3de..416808662 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Server.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Server.php
@@ -1,4 +1,6 @@
app = $app;
- $this->setRunner(new Runner());
+ $this->runner = $runner ?? new Runner();
}
/**
@@ -72,35 +68,29 @@ public function __construct(HttpApplicationInterface $app)
* - Run the middleware queue including the application.
*
* @param \Psr\Http\Message\ServerRequestInterface|null $request The request to use or null.
- * @param \Psr\Http\Message\ResponseInterface|null $response The response to use or null.
+ * @param \Cake\Http\MiddlewareQueue $middlewareQueue MiddlewareQueue or null.
* @return \Psr\Http\Message\ResponseInterface
* @throws \RuntimeException When the application does not make a response.
*/
- public function run(ServerRequestInterface $request = null, ResponseInterface $response = null)
- {
+ public function run(
+ ?ServerRequestInterface $request = null,
+ ?MiddlewareQueue $middlewareQueue = null
+ ): ResponseInterface {
$this->bootstrap();
- $response = $response ?: new Response();
$request = $request ?: ServerRequestFactory::fromGlobals();
- $middleware = $this->app->middleware(new MiddlewareQueue());
+ $middleware = $this->app->middleware($middlewareQueue ?? new MiddlewareQueue());
if ($this->app instanceof PluginApplicationInterface) {
$middleware = $this->app->pluginMiddleware($middleware);
}
- if (!($middleware instanceof MiddlewareQueue)) {
- throw new RuntimeException('The application `middleware` method did not return a middleware queue.');
- }
$this->dispatchEvent('Server.buildMiddleware', ['middleware' => $middleware]);
- $middleware->add($this->app);
- $response = $this->runner->run($middleware, $request, $response);
+ $response = $this->runner->run($middleware, $request, $this->app);
- if (!($response instanceof ResponseInterface)) {
- throw new RuntimeException(sprintf(
- 'Application did not create a response. Got "%s" instead.',
- is_object($response) ? get_class($response) : $response
- ));
+ if ($request instanceof ServerRequest) {
+ $request->getSession()->close();
}
return $response;
@@ -115,7 +105,7 @@ public function run(ServerRequestInterface $request = null, ResponseInterface $r
*
* @return void
*/
- protected function bootstrap()
+ protected function bootstrap(): void
{
$this->app->bootstrap();
@@ -128,11 +118,11 @@ protected function bootstrap()
* Emit the response using the PHP SAPI.
*
* @param \Psr\Http\Message\ResponseInterface $response The response to emit
- * @param \Laminas\Diactoros\Response\EmitterInterface|null $emitter The emitter to use.
+ * @param \Laminas\HttpHandlerRunner\Emitter\EmitterInterface|null $emitter The emitter to use.
* When null, a SAPI Stream Emitter will be used.
* @return void
*/
- public function emit(ResponseInterface $response, EmitterInterface $emitter = null)
+ public function emit(ResponseInterface $response, ?EmitterInterface $emitter = null): void
{
if (!$emitter) {
$emitter = new ResponseEmitter();
@@ -145,32 +135,19 @@ public function emit(ResponseInterface $response, EmitterInterface $emitter = nu
*
* @return \Cake\Core\HttpApplicationInterface The application that will be run.
*/
- public function getApp()
+ public function getApp(): HttpApplicationInterface
{
return $this->app;
}
- /**
- * Set the runner
- *
- * @param \Cake\Http\Runner $runner The runner to use.
- * @return $this
- */
- public function setRunner(Runner $runner)
- {
- $this->runner = $runner;
-
- return $this;
- }
-
/**
* Get the application's event manager or the global one.
*
- * @return \Cake\Event\EventManager
+ * @return \Cake\Event\EventManagerInterface
*/
- public function getEventManager()
+ public function getEventManager(): EventManagerInterface
{
- if ($this->app instanceof PluginApplicationInterface) {
+ if ($this->app instanceof EventDispatcherInterface) {
return $this->app->getEventManager();
}
@@ -178,38 +155,18 @@ public function getEventManager()
}
/**
- * Get/set the application's event manager.
- *
- * If the application does not support events and this method is used as
- * a setter, an exception will be raised.
- *
- * @param \Cake\Event\EventManager|null $events The event manager to set.
- * @return \Cake\Event\EventManager|$this
- * @deprecated 3.6.0 Will be removed in 4.0
- */
- public function eventManager(EventManager $events = null)
- {
- deprecationWarning('eventManager() is deprecated. Use getEventManager()/setEventManager() instead.');
- if ($events === null) {
- return $this->getEventManager();
- }
-
- return $this->setEventManager($events);
- }
-
- /**
- * Get/set the application's event manager.
+ * Set the application's event manager.
*
- * If the application does not support events and this method is used as
- * a setter, an exception will be raised.
+ * If the application does not support events, an exception will be raised.
*
- * @param \Cake\Event\EventManager $events The event manager to set.
+ * @param \Cake\Event\EventManagerInterface $eventManager The event manager to set.
* @return $this
+ * @throws \InvalidArgumentException
*/
- public function setEventManager(EventManager $events)
+ public function setEventManager(EventManagerInterface $eventManager)
{
- if ($this->app instanceof PluginApplicationInterface) {
- $this->app->setEventManager($events);
+ if ($this->app instanceof EventDispatcherInterface) {
+ $this->app->setEventManager($eventManager);
return $this;
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/ServerRequest.php b/app/vendor/cakephp/cakephp/src/Http/ServerRequest.php
index 87014b205..098a8297e 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ServerRequest.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ServerRequest.php
@@ -1,4 +1,6 @@
null,
@@ -56,7 +55,6 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
* data.
*
* @var array|object|null
- * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getData() instead.
*/
protected $data = [];
@@ -64,7 +62,6 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
* Array of query string arguments
*
* @var array
- * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getQuery() or getQueryParams() instead.
*/
protected $query = [];
@@ -72,7 +69,6 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
* Array of cookie data.
*
* @var array
- * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getCookie() instead.
*/
protected $cookies = [];
@@ -83,19 +79,10 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
*/
protected $_environment = [];
- /**
- * The URL string used for the request.
- *
- * @var string
- * @deprecated 3.6.0 This public property will be removed in 4.0.0. Use getPath() instead.
- */
- protected $url;
-
/**
* Base URL path.
*
* @var string
- * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getAttribute('base') instead.
*/
protected $base;
@@ -103,18 +90,9 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
* webroot path segment for the request.
*
* @var string
- * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getAttribute('webroot') instead.
*/
protected $webroot = '/';
- /**
- * The full address to the current request
- *
- * @var string
- * @deprecated 3.4.0 This public property will be removed in 4.0.0. Use getAttribute('here') or getUri()->getPath() instead.
- */
- protected $here;
-
/**
* Whether or not to trust HTTP_X headers set by most load balancers.
* Only set to true if your application runs behind load balancers/proxies
@@ -131,20 +109,13 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
*/
protected $trustedProxies = [];
- /**
- * Contents of php://input
- *
- * @var string
- */
- protected $_input;
-
/**
* The built in detectors used with `is()` can be modified with `addDetector()`.
*
* There are several ways to specify a detector, see \Cake\Http\ServerRequest::addDetector() for the
* various formats and ways to define detectors.
*
- * @var array
+ * @var (array|callable)[]
*/
protected static $_detectors = [
'get' => ['env' => 'REQUEST_METHOD', 'value' => 'GET'],
@@ -156,8 +127,6 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
'options' => ['env' => 'REQUEST_METHOD', 'value' => 'OPTIONS'],
'ssl' => ['env' => 'HTTPS', 'options' => [1, 'on']],
'ajax' => ['env' => 'HTTP_X_REQUESTED_WITH', 'value' => 'XMLHttpRequest'],
- 'flash' => ['env' => 'HTTP_USER_AGENT', 'pattern' => '/^(Shockwave|Adobe) Flash/'],
- 'requested' => ['param' => 'requested', 'value' => 1],
'json' => ['accept' => ['application/json'], 'param' => '_ext', 'value' => 'json'],
'xml' => ['accept' => ['application/xml', 'text/xml'], 'param' => '_ext', 'value' => 'xml'],
];
@@ -225,48 +194,12 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
*/
protected $requestTarget;
- /**
- * List of deprecated properties that have backwards
- * compatibility offered through magic methods.
- *
- * @var array
- */
- private $deprecatedProperties = [
- 'data' => ['get' => 'getData()', 'set' => 'withData()'],
- 'query' => ['get' => 'getQuery()', 'set' => 'withQueryParams()'],
- 'params' => ['get' => 'getParam()', 'set' => 'withParam()'],
- 'cookies' => ['get' => 'getCookie()', 'set' => 'withCookieParams()'],
- 'url' => ['get' => 'getPath()', 'set' => 'withRequestTarget()'],
- 'base' => ['get' => 'getAttribute("base")', 'set' => 'withAttribute("base")'],
- 'webroot' => ['get' => 'getAttribute("webroot")', 'set' => 'withAttribute("webroot")'],
- 'here' => ['get' => 'getAttribute("here")', 'set' => 'withAttribute("here")'],
- ];
-
/**
* Whether to merge file uploads as objects (`true`) or arrays (`false`).
*
* @var bool
*/
- private $mergeFilesAsObjects = false;
-
- /**
- * Wrapper method to create a new request from PHP superglobals.
- *
- * Uses the $_GET, $_POST, $_FILES, $_COOKIE, $_SERVER, $_ENV and php://input data to construct
- * the request.
- *
- * @return self
- * @deprecated 3.4.0 Use `Cake\Http\ServerRequestFactory` instead.
- */
- public static function createFromGlobals()
- {
- deprecationWarning(
- 'ServerRequest::createFromGlobals() is deprecated. ' .
- 'Use `Cake\Http\ServerRequestFactory` instead.'
- );
-
- return ServerRequestFactory::fromGlobals();
- }
+ protected $mergeFilesAsObjects = true;
/**
* Create a new request object.
@@ -281,7 +214,7 @@ public static function createFromGlobals()
* - `cookies` Cookies for this request.
* - `environment` $_SERVER and $_ENV data.
* - `url` The URL without the base path for the request.
- * - `uri` The PSR7 UriInterface object. If null, one will be created.
+ * - `uri` The PSR7 UriInterface object. If null, one will be created from `url` or `environment`.
* - `base` The base URL for the request.
* - `webroot` The webroot directory for the request.
* - `input` The data that would come from php://input this is useful for simulating
@@ -289,14 +222,10 @@ public static function createFromGlobals()
* - `session` An instance of a Session object
* - `mergeFilesAsObjects` Whether to merge file uploads as objects (`true`) or arrays (`false`).
*
- * @param string|array $config An array of request data to create a request with.
- * The string version of this argument is *deprecated* and will be removed in 4.0.0
+ * @param array $config An array of request data to create a request with.
*/
- public function __construct($config = [])
+ public function __construct(array $config = [])
{
- if (is_string($config)) {
- $config = ['url' => $config];
- }
$config += [
'params' => $this->params,
'query' => [],
@@ -309,7 +238,7 @@ public function __construct($config = [])
'base' => '',
'webroot' => '',
'input' => null,
- 'mergeFilesAsObjects' => false,
+ 'mergeFilesAsObjects' => true,
];
$this->_setConfig($config);
@@ -321,7 +250,7 @@ public function __construct($config = [])
* @param array $config The config data to use.
* @return void
*/
- protected function _setConfig($config)
+ protected function _setConfig(array $config): void
{
if (strlen($config['url']) > 1 && $config['url'][0] === '/') {
$config['url'] = substr($config['url'], 1);
@@ -347,7 +276,7 @@ protected function _setConfig($config)
// UriInterface implementations happy.
$querystr = '';
if (strpos($config['url'], '?') !== false) {
- list($config['url'], $querystr) = explode('?', $config['url']);
+ [$config['url'], $querystr] = explode('?', $config['url']);
}
if (strlen($config['url'])) {
$uri = $uri->withPath('/' . $config['url']);
@@ -360,9 +289,6 @@ protected function _setConfig($config)
$this->base = $config['base'];
$this->webroot = $config['webroot'];
- $this->url = substr($uri->getPath(), 1);
- $this->here = $this->base . '/' . $this->url;
-
if (isset($config['input'])) {
$stream = new Stream('php://memory', 'rw');
$stream->write($config['input']);
@@ -386,8 +312,8 @@ protected function _setConfig($config)
* HTTP override value. The 'ORIGINAL_REQUEST_METHOD' is also preserved, if you
* want the read the non-simulated HTTP method the client used.
*
- * @param array $data Array of post data.
- * @return array
+ * @param mixed $data Array of post data.
+ * @return mixed
*/
protected function _processPost($data)
{
@@ -396,7 +322,7 @@ protected function _processPost($data)
if (
in_array($method, ['PUT', 'DELETE', 'PATCH'], true) &&
- strpos($this->contentType(), 'application/x-www-form-urlencoded') === 0
+ strpos((string)$this->contentType(), 'application/x-www-form-urlencoded') === 0
) {
$data = $this->input();
parse_str($data, $data);
@@ -426,9 +352,9 @@ protected function _processPost($data)
* @param string $queryString A query string from the URL if provided
* @return array An array containing the parsed query string as keys/values.
*/
- protected function _processGet($query, $queryString = '')
+ protected function _processGet(array $query, string $queryString = ''): array
{
- $unsetUrl = '/' . str_replace(['.', ' '], '_', urldecode($this->url));
+ $unsetUrl = str_replace(['.', ' '], '_', urldecode($this->uri->getPath()));
unset($query[$unsetUrl], $query[$this->base . $unsetUrl]);
if (strlen($queryString)) {
parse_str($queryString, $queryArgs);
@@ -441,18 +367,16 @@ protected function _processGet($query, $queryString = '')
/**
* Process uploaded files and move things onto the post data.
*
- * @param array $post Post data to merge files onto.
- * @param array $files Uploaded files to merge in.
+ * @param mixed $post Post data to merge files onto.
+ * @param mixed $files Uploaded files to merge in.
* @return array merged post + file data.
*/
protected function _processFiles($post, $files)
{
- if (
- empty($files) ||
- !is_array($files)
- ) {
+ if (!is_array($post) || !is_array($files) || empty($files)) {
return $post;
}
+
$fileData = [];
foreach ($files as $key => $value) {
if ($value instanceof UploadedFileInterface) {
@@ -484,7 +408,7 @@ protected function _processFiles($post, $files)
if ($error === UPLOAD_ERR_OK) {
$tmpName = $file->getStream()->getMetadata('uri');
}
- $post = Hash::insert($post, $key, [
+ $post = Hash::insert($post, (string)$key, [
'tmp_name' => $tmpName,
'error' => $error,
'name' => $file->getClientFilename(),
@@ -503,7 +427,7 @@ protected function _processFiles($post, $files)
* recursively process the data.
*
* @param array $value $_FILES struct
- * @return array|UploadedFileInterface
+ * @return array|\Psr\Http\Message\UploadedFileInterface
*/
protected function _createUploadedFile(array $value)
{
@@ -529,7 +453,7 @@ protected function _createUploadedFile(array $value)
* @param array $files The file data to normalize & convert.
* @return array An array of UploadedFileInterface objects.
*/
- protected function _normalizeNestedFiles(array $files = [])
+ protected function _normalizeNestedFiles(array $files = []): array
{
$normalizedFiles = [];
foreach (array_keys($files['tmp_name']) as $key) {
@@ -549,9 +473,9 @@ protected function _normalizeNestedFiles(array $files = [])
/**
* Get the content type used in this request.
*
- * @return string
+ * @return string|null
*/
- public function contentType()
+ public function contentType(): ?string
{
$type = $this->getEnv('CONTENT_TYPE');
if ($type) {
@@ -566,44 +490,20 @@ public function contentType()
*
* @return \Cake\Http\Session
*/
- public function getSession()
+ public function getSession(): Session
{
return $this->session;
}
- /**
- * Returns the instance of the Session object for this request
- *
- * If a session object is passed as first argument it will be set as
- * the session to use for this request
- *
- * @deprecated 3.5.0 Use getSession() instead. The setter part will be removed.
- * @param \Cake\Http\Session|null $session the session object to use
- * @return \Cake\Http\Session
- */
- public function session(Session $session = null)
- {
- deprecationWarning(
- 'ServerRequest::session() is deprecated. ' .
- 'Use getSession() instead. The setter part will be removed.'
- );
-
- if ($session === null) {
- return $this->session;
- }
-
- return $this->session = $session;
- }
-
/**
* Get the IP the client is using, or says they are using.
*
* @return string The client IP.
*/
- public function clientIp()
+ public function clientIp(): string
{
if ($this->trustProxy && $this->getEnv('HTTP_X_FORWARDED_FOR')) {
- $addresses = array_map('trim', explode(',', $this->getEnv('HTTP_X_FORWARDED_FOR')));
+ $addresses = array_map('trim', explode(',', (string)$this->getEnv('HTTP_X_FORWARDED_FOR')));
$trusted = (count($this->trustedProxies) > 0);
$n = count($addresses);
@@ -627,7 +527,7 @@ public function clientIp()
$ipaddr = $this->getEnv('REMOTE_ADDR');
}
- return trim($ipaddr);
+ return trim((string)$ipaddr);
}
/**
@@ -636,7 +536,7 @@ public function clientIp()
* @param string[] $proxies ips list of trusted proxies
* @return void
*/
- public function setTrustedProxies(array $proxies)
+ public function setTrustedProxies(array $proxies): void
{
$this->trustedProxies = $proxies;
$this->trustProxy = true;
@@ -647,7 +547,7 @@ public function setTrustedProxies(array $proxies)
*
* @return string[]
*/
- public function getTrustedProxies()
+ public function getTrustedProxies(): array
{
return $this->trustedProxies;
}
@@ -657,9 +557,9 @@ public function getTrustedProxies()
*
* @param bool $local Attempt to return a local address.
* Local addresses do not contain hostnames.
- * @return string The referring address for this request.
+ * @return string|null The referring address for this request or null.
*/
- public function referer($local = false)
+ public function referer(bool $local = true): ?string
{
$ref = $this->getEnv('HTTP_REFERER');
@@ -681,7 +581,7 @@ public function referer($local = false)
}
}
- return '/';
+ return null;
}
/**
@@ -692,7 +592,7 @@ public function referer($local = false)
* @return mixed
* @throws \BadMethodCallException when an invalid method is called.
*/
- public function __call($name, $params)
+ public function __call(string $name, array $params)
{
if (strpos($name, 'is') === 0) {
$type = strtolower(substr($name, 2));
@@ -704,94 +604,6 @@ public function __call($name, $params)
throw new BadMethodCallException(sprintf('Method "%s()" does not exist', $name));
}
- /**
- * Magic set method allows backward compatibility for former public properties
- *
- * @param string $name The property being accessed.
- * @param mixed $value The property value.
- * @return mixed Either the value of the parameter or null.
- * @deprecated 3.6.0 Public properties will be removed in 4.0.0.
- * Use appropriate setters instead.
- */
- public function __set($name, $value)
- {
- if (isset($this->deprecatedProperties[$name])) {
- $method = $this->deprecatedProperties[$name]['set'];
- deprecationWarning(
- "Setting {$name} as a property will be removed in 4.0.0. " .
- "Use {$method} instead."
- );
-
- return $this->{$name} = $value;
- }
- throw new BadMethodCallException("Cannot set {$name} it is not a known property.");
- }
-
- /**
- * Magic get method allows access to parsed routing parameters directly on the object.
- *
- * Allows access to `$this->params['controller']` via `$this->controller`
- *
- * @param string $name The property being accessed.
- * @return mixed Either the value of the parameter or null.
- * @deprecated 3.4.0 Accessing routing parameters through __get will removed in 4.0.0.
- * Use getParam() instead.
- */
- public function &__get($name)
- {
- if (isset($this->deprecatedProperties[$name])) {
- $method = $this->deprecatedProperties[$name]['get'];
- deprecationWarning(
- "Accessing `{$name}` as a property will be removed in 4.0.0. " .
- "Use request->{$method} instead."
- );
-
- return $this->{$name};
- }
-
- deprecationWarning(sprintf(
- 'Accessing routing parameters through `%s` will removed in 4.0.0. ' .
- 'Use `getParam()` instead.',
- $name
- ));
-
- if (isset($this->params[$name])) {
- return $this->params[$name];
- }
- $value = null;
-
- return $value;
- }
-
- /**
- * Magic isset method allows isset/empty checks
- * on routing parameters.
- *
- * @param string $name The property being accessed.
- * @return bool Existence
- * @deprecated 3.4.0 Accessing routing parameters through __isset will removed in 4.0.0.
- * Use getParam() instead.
- */
- public function __isset($name)
- {
- if (isset($this->deprecatedProperties[$name])) {
- $method = $this->deprecatedProperties[$name]['get'];
- deprecationWarning(
- "Accessing {$name} as a property will be removed in 4.0.0. " .
- "Use {$method} instead."
- );
-
- return isset($this->{$name});
- }
-
- deprecationWarning(
- 'Accessing routing parameters through __isset will removed in 4.0.0. ' .
- 'Use getParam() instead.'
- );
-
- return isset($this->params[$name]);
- }
-
/**
* Check whether or not a Request is a certain type.
*
@@ -801,10 +613,10 @@ public function __isset($name)
*
* @param string|string[] $type The type of request you want to check. If an array
* this method will return true if the request matches any type.
- * @param mixed ...$args List of arguments
+ * @param string ...$args List of arguments
* @return bool Whether or not the request is the type you are checking.
*/
- public function is($type, ...$args)
+ public function is($type, ...$args): bool
{
if (is_array($type)) {
foreach ($type as $_type) {
@@ -835,7 +647,7 @@ public function is($type, ...$args)
*
* @return void
*/
- public function clearDetectorCache()
+ public function clearDetectorCache(): void
{
$this->_detectorCache = [];
}
@@ -847,7 +659,7 @@ public function clearDetectorCache()
* @param array $args Array of custom detector arguments.
* @return bool Whether or not the request is the type you are checking.
*/
- protected function _is($type, $args)
+ protected function _is(string $type, array $args): bool
{
$detect = static::$_detectors[$type];
if (is_callable($detect)) {
@@ -877,11 +689,11 @@ protected function _is($type, $args)
* @param array $detect Detector options array.
* @return bool Whether or not the request is the type you are checking.
*/
- protected function _acceptHeaderDetector($detect)
+ protected function _acceptHeaderDetector(array $detect): bool
{
- $acceptHeaders = explode(',', $this->getEnv('HTTP_ACCEPT'));
+ $acceptHeaders = explode(',', (string)$this->getEnv('HTTP_ACCEPT'));
foreach ($detect['accept'] as $header) {
- if (in_array($header, $acceptHeaders)) {
+ if (in_array($header, $acceptHeaders, true)) {
return true;
}
}
@@ -895,7 +707,7 @@ protected function _acceptHeaderDetector($detect)
* @param array $detect Detector options array.
* @return bool Whether or not the request is the type you are checking.
*/
- protected function _headerDetector($detect)
+ protected function _headerDetector(array $detect): bool
{
foreach ($detect['header'] as $header => $value) {
$header = $this->getEnv('http_' . $header);
@@ -904,7 +716,7 @@ protected function _headerDetector($detect)
return call_user_func($value, $header);
}
- return ($header === $value);
+ return $header === $value;
}
}
@@ -917,7 +729,7 @@ protected function _headerDetector($detect)
* @param array $detect Detector options array.
* @return bool Whether or not the request is the type you are checking.
*/
- protected function _paramDetector($detect)
+ protected function _paramDetector(array $detect): bool
{
$key = $detect['param'];
if (isset($detect['value'])) {
@@ -938,19 +750,19 @@ protected function _paramDetector($detect)
* @param array $detect Detector options array.
* @return bool Whether or not the request is the type you are checking.
*/
- protected function _environmentDetector($detect)
+ protected function _environmentDetector(array $detect): bool
{
if (isset($detect['env'])) {
if (isset($detect['value'])) {
return $this->getEnv($detect['env']) == $detect['value'];
}
if (isset($detect['pattern'])) {
- return (bool)preg_match($detect['pattern'], $this->getEnv($detect['env']));
+ return (bool)preg_match($detect['pattern'], (string)$this->getEnv($detect['env']));
}
if (isset($detect['options'])) {
$pattern = '/' . implode('|', $detect['options']) . '/i';
- return (bool)preg_match($pattern, $this->getEnv($detect['env']));
+ return (bool)preg_match($pattern, (string)$this->getEnv($detect['env']));
}
}
@@ -968,7 +780,7 @@ protected function _environmentDetector($detect)
* @return bool Success.
* @see \Cake\Http\ServerRequest::is()
*/
- public function isAll(array $types)
+ public function isAll(array $types): bool
{
foreach ($types as $type) {
if (!$this->is($type)) {
@@ -1006,7 +818,7 @@ public function isAll(array $types)
* Allows for custom detectors on the request parameters.
*
* ```
- * addDetector('requested', ['param' => 'requested', 'value' => 1]);
+ * addDetector('admin', ['param' => 'prefix', 'value' => 'admin']);
* ```
*
* ### Accept comparison
@@ -1055,7 +867,7 @@ public function isAll(array $types)
* @param callable|array $callable A callable or options array for the detector definition.
* @return void
*/
- public static function addDetector($name, $callable)
+ public static function addDetector(string $name, $callable): void
{
$name = strtolower($name);
if (is_callable($callable)) {
@@ -1064,85 +876,19 @@ public static function addDetector($name, $callable)
return;
}
if (isset(static::$_detectors[$name], $callable['options'])) {
+ /** @psalm-suppress PossiblyInvalidArgument */
$callable = Hash::merge(static::$_detectors[$name], $callable);
}
static::$_detectors[$name] = $callable;
}
- /**
- * Add parameters to the request's parsed parameter set. This will overwrite any existing parameters.
- * This modifies the parameters available through `$request->getParam()`.
- *
- * @param array $params Array of parameters to merge in
- * @return $this The current object, you can chain this method.
- * @deprecated 3.6.0 ServerRequest::addParams() is deprecated. Use `withParam()` or
- * `withAttribute('params')` instead.
- */
- public function addParams(array $params)
- {
- deprecationWarning(
- 'ServerRequest::addParams() is deprecated. ' .
- 'Use `withParam()` or `withAttribute("params", $params)` instead.'
- );
- $this->params = array_merge($this->params, $params);
-
- return $this;
- }
-
- /**
- * Add paths to the requests' paths vars. This will overwrite any existing paths.
- * Provides an easy way to modify, here, webroot and base.
- *
- * @param array $paths Array of paths to merge in
- * @return $this The current object, you can chain this method.
- * @deprecated 3.6.0 Mutating a request in place is deprecated. Use `withAttribute()` to modify paths instead.
- */
- public function addPaths(array $paths)
- {
- deprecationWarning(
- 'ServerRequest::addPaths() is deprecated. ' .
- 'Use `withAttribute($key, $value)` instead.'
- );
- foreach (['webroot', 'here', 'base'] as $element) {
- if (isset($paths[$element])) {
- $this->{$element} = $paths[$element];
- }
- }
-
- return $this;
- }
-
- /**
- * Get the value of the current requests URL. Will include the query string arguments.
- *
- * @param bool $base Include the base path, set to false to trim the base path off.
- * @return string The current request URL including query string args.
- * @deprecated 3.4.0 This method will be removed in 4.0.0. You should use getRequestTarget() instead.
- */
- public function here($base = true)
- {
- deprecationWarning(
- 'ServerRequest::here() will be removed in 4.0.0. You should use getRequestTarget() instead.'
- );
-
- $url = $this->here;
- if (!empty($this->query)) {
- $url .= '?' . http_build_query($this->query, null, '&');
- }
- if (!$base) {
- $url = preg_replace('/^' . preg_quote($this->base, '/') . '/', '', $url, 1);
- }
-
- return $url;
- }
-
/**
* Normalize a header name into the SERVER version.
*
* @param string $name The header name.
* @return string The normalized header name.
*/
- protected function normalizeHeaderName($name)
+ protected function normalizeHeaderName(string $name): string
{
$name = str_replace('-', '_', strtoupper($name));
if (!in_array($name, ['CONTENT_LENGTH', 'CONTENT_TYPE'], true)) {
@@ -1152,29 +898,6 @@ protected function normalizeHeaderName($name)
return $name;
}
- /**
- * Read an HTTP header from the Request information.
- *
- * If the header is not defined in the request, this method
- * will fallback to reading data from $_SERVER and $_ENV.
- * This fallback behavior is deprecated, and will be removed in 4.0.0
- *
- * @param string $name Name of the header you want.
- * @return string|null Either null on no header being set or the value of the header.
- * @deprecated 4.0.0 The automatic fallback to env() will be removed in 4.0.0, see getHeader()
- */
- public function header($name)
- {
- deprecationWarning(
- 'ServerRequest::header() is deprecated. ' .
- 'The automatic fallback to env() will be removed in 4.0.0, see getHeader()'
- );
-
- $name = $this->normalizeHeaderName($name);
-
- return $this->getEnv($name);
- }
-
/**
* Get all headers in the request.
*
@@ -1184,10 +907,10 @@ public function header($name)
* While header names are not case-sensitive, getHeaders() will normalize
* the headers.
*
- * @return array An associative array of headers and their values.
+ * @return string[][] An associative array of headers and their values.
* @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
*/
- public function getHeaders()
+ public function getHeaders(): array
{
$headers = [];
foreach ($this->_environment as $key => $value) {
@@ -1215,7 +938,7 @@ public function getHeaders()
* @return bool Whether or not the header is defined.
* @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
*/
- public function hasHeader($name)
+ public function hasHeader($name): bool
{
$name = $this->normalizeHeaderName($name);
@@ -1229,11 +952,11 @@ public function hasHeader($name)
* is not present an empty array will be returned.
*
* @param string $name The header you want to get (case-insensitive)
- * @return array An associative array of headers and their values.
+ * @return string[] An associative array of headers and their values.
* If the header doesn't exist, an empty array will be returned.
* @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
*/
- public function getHeader($name)
+ public function getHeader($name): array
{
$name = $this->normalizeHeaderName($name);
if (isset($this->_environment[$name])) {
@@ -1250,7 +973,7 @@ public function getHeader($name)
* @return string Header values collapsed into a comma separated string.
* @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
*/
- public function getHeaderLine($name)
+ public function getHeaderLine($name): string
{
$value = $this->getHeader($name);
@@ -1315,22 +1038,6 @@ public function withoutHeader($name)
return $new;
}
- /**
- * Get the HTTP method used for this request.
- *
- * @return string The name of the HTTP method used.
- * @deprecated 3.4.0 This method will be removed in 4.0.0. Use getMethod() instead.
- */
- public function method()
- {
- deprecationWarning(
- 'ServerRequest::method() is deprecated. ' .
- 'This method will be removed in 4.0.0. Use getMethod() instead.'
- );
-
- return $this->getEnv('REQUEST_METHOD');
- }
-
/**
* Get the HTTP method used for this request.
* There are a few ways to specify a method.
@@ -1345,9 +1052,9 @@ public function method()
* @return string The name of the HTTP method used.
* @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
*/
- public function getMethod()
+ public function getMethod(): string
{
- return $this->getEnv('REQUEST_METHOD');
+ return (string)$this->getEnv('REQUEST_METHOD');
}
/**
@@ -1384,7 +1091,7 @@ public function withMethod($method)
* @return array
* @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
*/
- public function getServerParams()
+ public function getServerParams(): array
{
return $this->_environment;
}
@@ -1396,7 +1103,7 @@ public function getServerParams()
* @return array
* @link http://www.php-fig.org/psr/psr-7/ This method is part of the PSR-7 server request interface.
*/
- public function getQueryParams()
+ public function getQueryParams(): array
{
return $this->query;
}
@@ -1419,9 +1126,9 @@ public function withQueryParams(array $query)
/**
* Get the host that the request was handled on.
*
- * @return string
+ * @return string|null
*/
- public function host()
+ public function host(): ?string
{
if ($this->trustProxy && $this->getEnv('HTTP_X_FORWARDED_HOST')) {
return $this->getEnv('HTTP_X_FORWARDED_HOST');
@@ -1433,9 +1140,9 @@ public function host()
/**
* Get the port the request was handled on.
*
- * @return string
+ * @return string|null
*/
- public function port()
+ public function port(): ?string
{
if ($this->trustProxy && $this->getEnv('HTTP_X_FORWARDED_PORT')) {
return $this->getEnv('HTTP_X_FORWARDED_PORT');
@@ -1449,9 +1156,9 @@ public function port()
*
* e.g. 'http', or 'https'
*
- * @return string The scheme used for the request.
+ * @return string|null The scheme used for the request.
*/
- public function scheme()
+ public function scheme(): ?string
{
if ($this->trustProxy && $this->getEnv('HTTP_X_FORWARDED_PROTO')) {
return $this->getEnv('HTTP_X_FORWARDED_PROTO');
@@ -1467,9 +1174,14 @@ public function scheme()
* While `example.co.uk` contains 2.
* @return string Domain name without subdomains.
*/
- public function domain($tldLength = 1)
+ public function domain(int $tldLength = 1): string
{
- $segments = explode('.', $this->host());
+ $host = $this->host();
+ if (empty($host)) {
+ return '';
+ }
+
+ $segments = explode('.', $host);
$domain = array_slice($segments, -1 * ($tldLength + 1));
return implode('.', $domain);
@@ -1480,11 +1192,16 @@ public function domain($tldLength = 1)
*
* @param int $tldLength Number of segments your tld contains. For example: `example.com` contains 1 tld.
* While `example.co.uk` contains 2.
- * @return array An array of subdomains.
+ * @return string[] An array of subdomains.
*/
- public function subdomains($tldLength = 1)
+ public function subdomains(int $tldLength = 1): array
{
- $segments = explode('.', $this->host());
+ $host = $this->host();
+ if (empty($host)) {
+ return [];
+ }
+
+ $segments = explode('.', $host);
return array_slice($segments, 0, -1 * ($tldLength + 1));
}
@@ -1512,7 +1229,7 @@ public function subdomains($tldLength = 1)
* @return array|bool Either an array of all the types the client accepts or a boolean if they accept the
* provided type.
*/
- public function accepts($type = null)
+ public function accepts(?string $type = null)
{
$raw = $this->parseAccept();
$accept = [];
@@ -1535,7 +1252,7 @@ public function accepts($type = null)
*
* @return array An array of prefValue => [content/types]
*/
- public function parseAccept()
+ public function parseAccept(): array
{
return $this->_parseAcceptWithQualifier($this->getHeaderLine('Accept'));
}
@@ -1554,7 +1271,7 @@ public function parseAccept()
* @param string|null $language The language to test.
* @return array|bool If a $language is provided, a boolean. Otherwise the array of accepted languages.
*/
- public function acceptLanguage($language = null)
+ public function acceptLanguage(?string $language = null)
{
$raw = $this->_parseAcceptWithQualifier($this->getHeaderLine('Accept-Language'));
$accept = [];
@@ -1583,7 +1300,7 @@ public function acceptLanguage($language = null)
* @param string $header Header to parse.
* @return array
*/
- protected function _parseAcceptWithQualifier($header)
+ protected function _parseAcceptWithQualifier(string $header): array
{
$accept = [];
$headers = explode(',', $header);
@@ -1615,38 +1332,16 @@ protected function _parseAcceptWithQualifier($header)
return $accept;
}
- /**
- * Provides a read accessor for `$this->query`.
- * Allows you to use a `Hash::get()` compatible syntax for reading post data.
- *
- * @param string|null $name Query string variable name or null to read all.
- * @return string|array|null The value being read
- * @deprecated 3.4.0 Use getQuery() or the PSR-7 getQueryParams() and withQueryParams() methods instead.
- */
- public function query($name = null)
- {
- deprecationWarning(
- 'ServerRequest::query() is deprecated. ' .
- 'Use getQuery() or the PSR-7 getQueryParams() and withQueryParams() methods instead.'
- );
-
- if ($name === null) {
- return $this->query;
- }
-
- return $this->getQuery($name);
- }
-
/**
* Read a specific query value or dotted path.
*
- * Developers are encouraged to use getQueryParams() when possible as it is PSR-7 compliant, and this method
- * is not.
+ * Developers are encouraged to use getQueryParams() if they need the whole query array,
+ * as it is PSR-7 compliant, and this method is not. Using Hash::get() you can also get single params.
*
* ### PSR-7 Alternative
*
* ```
- * $value = Hash::get($request->getQueryParams(), 'Post.id', null);
+ * $value = Hash::get($request->getQueryParams(), 'Post.id');
* ```
*
* @param string|null $name The name or dotted path to the query param or null to read all.
@@ -1654,7 +1349,7 @@ public function query($name = null)
* @return array|string|null Query data.
* @see ServerRequest::getQueryParams()
*/
- public function getQuery($name = null, $default = null)
+ public function getQuery(?string $name = null, $default = null)
{
if ($name === null) {
return $this->query;
@@ -1663,51 +1358,6 @@ public function getQuery($name = null, $default = null)
return Hash::get($this->query, $name, $default);
}
- /**
- * Provides a read/write accessor for `$this->data`.
- * Allows you to use a `Hash::get()` compatible syntax for reading post data.
- *
- * ### Reading values.
- *
- * ```
- * $request->data('Post.title');
- * ```
- *
- * When reading values you will get `null` for keys/values that do not exist.
- *
- * ### Writing values
- *
- * ```
- * $request->data('Post.title', 'New post!');
- * ```
- *
- * You can write to any value, even paths/keys that do not exist, and the arrays
- * will be created for you.
- *
- * @param string|null $name Dot separated name of the value to read/write
- * @param mixed ...$args The data to set (deprecated)
- * @return mixed|$this Either the value being read, or this so you can chain consecutive writes.
- * @deprecated 3.4.0 Use withData() and getData() or getParsedBody() instead.
- */
- public function data($name = null, ...$args)
- {
- deprecationWarning(
- 'ServerRequest::data() is deprecated. ' .
- 'Use withData() and getData() or getParsedBody() instead.'
- );
-
- if (count($args) === 1) {
- $this->data = Hash::insert($this->data, $name, $args[0]);
-
- return $this;
- }
- if ($name !== null) {
- return Hash::get($this->data, $name);
- }
-
- return $this->data;
- }
-
/**
* Provides a safe accessor for request data. Allows
* you to use Hash::get() compatible paths.
@@ -1727,11 +1377,20 @@ public function data($name = null, ...$args)
*
* When reading values you will get `null` for keys/values that do not exist.
*
+ * Developers are encouraged to use getParsedBody() if they need the whole data array,
+ * as it is PSR-7 compliant, and this method is not. Using Hash::get() you can also get single params.
+ *
+ * ### PSR-7 Alternative
+ *
+ * ```
+ * $value = Hash::get($request->getParsedBody(), 'Post.id');
+ * ```
+ *
* @param string|null $name Dot separated name of the value to read. Or null to read all data.
* @param mixed $default The default data.
- * @return array|string|null The value being read.
+ * @return mixed The value being read.
*/
- public function getData($name = null, $default = null)
+ public function getData(?string $name = null, $default = null)
{
if ($name === null) {
return $this->data;
@@ -1740,34 +1399,10 @@ public function getData($name = null, $default = null)
return $default;
}
+ /** @psalm-suppress PossiblyNullArgument */
return Hash::get($this->data, $name, $default);
}
- /**
- * Safely access the values in $this->params.
- *
- * @param string $name The name of the parameter to get.
- * @param mixed ...$args Value to set (deprecated).
- * @return mixed|$this The value of the provided parameter. Will
- * return false if the parameter doesn't exist or is falsey.
- * @deprecated 3.4.0 Use getParam() and withParam() instead.
- */
- public function param($name, ...$args)
- {
- deprecationWarning(
- 'ServerRequest::param() is deprecated. ' .
- 'Use getParam() and withParam() instead.'
- );
-
- if (count($args) === 1) {
- $this->params = Hash::insert($this->params, $name, $args[0]);
-
- return $this;
- }
-
- return $this->getParam($name);
- }
-
/**
* Read data from `php://input`. Useful when interacting with XML or JSON
* request body content.
@@ -1786,13 +1421,13 @@ public function param($name, ...$args)
*
* Any additional parameters are applied to the callback in the order they are given.
*
- * @param string|null $callback A decoding callback that will convert the string data to another
+ * @param callable|null $callback A decoding callback that will convert the string data to another
* representation. Leave empty to access the raw input data. You can also
* supply additional parameters for the decoding callback using var args, see above.
- * @param array ...$args The additional arguments
- * @return string The decoded/processed request data.
+ * @param mixed ...$args The additional arguments
+ * @return mixed The decoded/processed request data.
*/
- public function input($callback = null, ...$args)
+ public function input(?callable $callback = null, ...$args)
{
$this->stream->rewind();
$input = $this->stream->getContents();
@@ -1805,35 +1440,14 @@ public function input($callback = null, ...$args)
return $input;
}
- /**
- * Read cookie data from the request's cookie data.
- *
- * @param string $key The key you want to read.
- * @return string|null Either the cookie value, or null if the value doesn't exist.
- * @deprecated 3.4.0 Use getCookie() instead.
- */
- public function cookie($key)
- {
- deprecationWarning(
- 'ServerRequest::cookie() is deprecated. ' .
- 'Use getCookie() instead.'
- );
-
- if (isset($this->cookies[$key])) {
- return $this->cookies[$key];
- }
-
- return null;
- }
-
/**
* Read cookie data from the request's cookie data.
*
* @param string $key The key or dotted path you want to read.
- * @param string $default The default value if the cookie is not set.
+ * @param string|array|null $default The default value if the cookie is not set.
* @return string|array|null Either the cookie value, or null if the value doesn't exist.
*/
- public function getCookie($key, $default = null)
+ public function getCookie(string $key, $default = null)
{
return Hash::get($this->cookies, $key, $default);
}
@@ -1853,7 +1467,7 @@ public function getCookie($key, $default = null)
*
* @return \Cake\Http\Cookie\CookieCollection
*/
- public function getCookieCollection()
+ public function getCookieCollection(): CookieCollection
{
return CookieCollection::createFromServerRequest($this);
}
@@ -1882,7 +1496,7 @@ public function withCookieCollection(CookieCollection $cookies)
*
* @return array An array of cookie data.
*/
- public function getCookieParams()
+ public function getCookieParams(): array
{
return $this->cookies;
}
@@ -1909,8 +1523,8 @@ public function withCookieParams(array $cookies)
* post data. For other content types, it may be the deserialized request
* body.
*
- * @return object|array|null The deserialized body parameters, if any.
- * These will typically be an array or object.
+ * @return array|object|null The deserialized body parameters, if any.
+ * These will typically be an array.
*/
public function getParsedBody()
{
@@ -1920,7 +1534,7 @@ public function getParsedBody()
/**
* Update the parsed body and get a new instance.
*
- * @param object|array|null $data The deserialized body data. This will
+ * @param array|object|null $data The deserialized body data. This will
* typically be in an array or object.
* @return static
*/
@@ -1937,14 +1551,14 @@ public function withParsedBody($data)
*
* @return string HTTP protocol version.
*/
- public function getProtocolVersion()
+ public function getProtocolVersion(): string
{
if ($this->protocol) {
return $this->protocol;
}
// Lazily populate this data as it is generally not used.
- preg_match('/^HTTP\/([\d.]+)$/', $this->getEnv('SERVER_PROTOCOL'), $match);
+ preg_match('/^HTTP\/([\d.]+)$/', (string)$this->getEnv('SERVER_PROTOCOL'), $match);
$protocol = '1.1';
if (isset($match[1])) {
$protocol = $match[1];
@@ -1983,14 +1597,14 @@ public function withProtocolVersion($version)
* variable's value that does not exist.
* @return string|null Either the environment value, or null if the value doesn't exist.
*/
- public function getEnv($key, $default = null)
+ public function getEnv(string $key, ?string $default = null): ?string
{
$key = strtoupper($key);
if (!array_key_exists($key, $this->_environment)) {
$this->_environment[$key] = env($key);
}
- return $this->_environment[$key] !== null ? $this->_environment[$key] : $default;
+ return $this->_environment[$key] !== null ? (string)$this->_environment[$key] : $default;
}
/**
@@ -2003,7 +1617,7 @@ public function getEnv($key, $default = null)
* @param string $value Value to set
* @return static
*/
- public function withEnv($key, $value)
+ public function withEnv(string $key, string $value)
{
$new = clone $this;
$new->_environment[$key] = $value;
@@ -2012,40 +1626,6 @@ public function withEnv($key, $value)
return $new;
}
- /**
- * Get/Set value from the request's environment data.
- * Fallback to using env() if key not set in $environment property.
- *
- * @deprecated 3.5.0 Use getEnv()/withEnv() instead.
- * @param string $key The key you want to read/write from/to.
- * @param string|null $value Value to set. Default null.
- * @param string|null $default Default value when trying to retrieve an environment
- * variable's value that does not exist. The value parameter must be null.
- * @return $this|string|null This instance if used as setter,
- * if used as getter either the environment value, or null if the value doesn't exist.
- */
- public function env($key, $value = null, $default = null)
- {
- deprecationWarning(
- 'ServerRequest::env() is deprecated. ' .
- 'Use getEnv()/withEnv() instead.'
- );
-
- if ($value !== null) {
- $this->_environment[$key] = $value;
- $this->clearDetectorCache();
-
- return $this;
- }
-
- $key = strtoupper($key);
- if (!array_key_exists($key, $this->_environment)) {
- $this->_environment[$key] = env($key);
- }
-
- return $this->_environment[$key] !== null ? $this->_environment[$key] : $default;
- }
-
/**
* Allow only certain HTTP request methods, if the request method does not match
* a 405 error will be shown and the required "Allow" response header will be set.
@@ -2060,10 +1640,10 @@ public function env($key, $value = null, $default = null)
* and a 405 error will be returned.
*
* @param string|array $methods Allowed HTTP request methods.
- * @return bool true
+ * @return true
* @throws \Cake\Http\Exception\MethodNotAllowedException
*/
- public function allowMethod($methods)
+ public function allowMethod($methods): bool
{
$methods = (array)$methods;
foreach ($methods as $method) {
@@ -2077,44 +1657,6 @@ public function allowMethod($methods)
throw $e;
}
- /**
- * Read data from php://input, mocked in tests.
- *
- * @return string contents of php://input
- */
- protected function _readInput()
- {
- if (empty($this->_input)) {
- $fh = fopen('php://input', 'rb');
- $content = stream_get_contents($fh);
- fclose($fh);
- $this->_input = $content;
- }
-
- return $this->_input;
- }
-
- /**
- * Modify data originally from `php://input`. Useful for altering json/xml data
- * in middleware or DispatcherFilters before it gets to RequestHandlerComponent
- *
- * @param string $input A string to replace original parsed data from input()
- * @return void
- * @deprecated 3.4.0 This method will be removed in 4.0.0. Use withBody() instead.
- */
- public function setInput($input)
- {
- deprecationWarning(
- 'This method will be removed in 4.0.0.' .
- 'Use withBody() instead.'
- );
-
- $stream = new Stream('php://memory', 'rw');
- $stream->write($input);
- $stream->rewind();
- $this->stream = $stream;
- }
-
/**
* Update the request with a new request data element.
*
@@ -2127,10 +1669,13 @@ public function setInput($input)
* @param mixed $value The value to insert into the request data.
* @return static
*/
- public function withData($name, $value)
+ public function withData(string $name, $value)
{
$copy = clone $this;
- $copy->data = Hash::insert($copy->data, $name, $value);
+
+ if (is_array($copy->data)) {
+ $copy->data = Hash::insert($copy->data, $name, $value);
+ }
return $copy;
}
@@ -2144,10 +1689,13 @@ public function withData($name, $value)
* @param string $name The dot separated path to remove.
* @return static
*/
- public function withoutData($name)
+ public function withoutData(string $name)
{
$copy = clone $this;
- $copy->data = Hash::remove($copy->data, $name);
+
+ if (is_array($copy->data)) {
+ $copy->data = Hash::remove($copy->data, $name);
+ }
return $copy;
}
@@ -2162,7 +1710,7 @@ public function withoutData($name)
* @param mixed $value The value to insert into the the request parameters.
* @return static
*/
- public function withParam($name, $value)
+ public function withParam(string $name, $value)
{
$copy = clone $this;
$copy->params = Hash::insert($copy->params, $name, $value);
@@ -2174,10 +1722,10 @@ public function withParam($name, $value)
* Safely access the values in $this->params.
*
* @param string $name The name or dotted path to parameter.
- * @param mixed $default The default value if `$name` is not set. Default `false`.
+ * @param mixed $default The default value if `$name` is not set. Default `null`.
* @return mixed
*/
- public function getParam($name, $default = false)
+ public function getParam(string $name, $default = null)
{
return Hash::get($this->params, $name, $default);
}
@@ -2231,6 +1779,10 @@ public function withoutAttribute($name)
public function getAttribute($name, $default = null)
{
if (in_array($name, $this->emulatedAttributes, true)) {
+ if ($name === 'here') {
+ return $this->base . $this->uri->getPath();
+ }
+
return $this->{$name};
}
if (array_key_exists($name, $this->attributes)) {
@@ -2248,13 +1800,13 @@ public function getAttribute($name, $default = null)
*
* @return array
*/
- public function getAttributes()
+ public function getAttributes(): array
{
$emulated = [
'params' => $this->params,
'webroot' => $this->webroot,
'base' => $this->base,
- 'here' => $this->here,
+ 'here' => $this->base . $this->uri->getPath(),
];
return $this->attributes + $emulated;
@@ -2266,7 +1818,7 @@ public function getAttributes()
* @param string $path The dot separated path to the file you want.
* @return \Psr\Http\Message\UploadedFileInterface|null
*/
- public function getUploadedFile($path)
+ public function getUploadedFile(string $path): ?UploadedFileInterface
{
$file = Hash::get($this->uploadedFiles, $path);
if (!$file instanceof UploadedFile) {
@@ -2281,7 +1833,7 @@ public function getUploadedFile($path)
*
* @return array
*/
- public function getUploadedFiles()
+ public function getUploadedFiles(): array
{
return $this->uploadedFiles;
}
@@ -2310,7 +1862,7 @@ public function withUploadedFiles(array $files)
* @return void
* @throws \InvalidArgumentException If any leaf elements are not valid files.
*/
- protected function validateUploadedFiles(array $uploadedFiles, $path)
+ protected function validateUploadedFiles(array $uploadedFiles, string $path): void
{
foreach ($uploadedFiles as $key => $file) {
if (is_array($file)) {
@@ -2329,7 +1881,7 @@ protected function validateUploadedFiles(array $uploadedFiles, $path)
*
* @return \Psr\Http\Message\StreamInterface Returns the body as a stream.
*/
- public function getBody()
+ public function getBody(): StreamInterface
{
return $this->stream;
}
@@ -2354,7 +1906,7 @@ public function withBody(StreamInterface $body)
* @return \Psr\Http\Message\UriInterface Returns a UriInterface instance
* representing the URI of the request.
*/
- public function getUri()
+ public function getUri(): UriInterface
{
return $this->uri;
}
@@ -2382,8 +1934,9 @@ public function withUri(UriInterface $uri, $preserveHost = false)
if (!$host) {
return $new;
}
- if ($uri->getPort()) {
- $host .= ':' . $uri->getPort();
+ $port = $uri->getPort();
+ if ($port) {
+ $host .= ':' . $port;
}
$new->_environment['HTTP_HOST'] = $host;
@@ -2401,6 +1954,7 @@ public function withUri(UriInterface $uri, $preserveHost = false)
* request-target forms allowed in request messages)
* @param string $target The request target.
* @return static
+ * @psalm-suppress MoreSpecificImplementedParamType
*/
public function withRequestTarget($target)
{
@@ -2420,7 +1974,7 @@ public function withRequestTarget($target)
*
* @return string
*/
- public function getRequestTarget()
+ public function getRequestTarget(): string
{
if ($this->requestTarget !== null) {
return $this->requestTarget;
@@ -2444,100 +1998,14 @@ public function getRequestTarget()
* @return string
* @since 3.6.1
*/
- public function getPath()
+ public function getPath(): string
{
if ($this->requestTarget === null) {
return $this->uri->getPath();
}
- list($path) = explode('?', $this->requestTarget);
+ [$path] = explode('?', $this->requestTarget);
return $path;
}
-
- /**
- * Array access read implementation
- *
- * @param string $name Name of the key being accessed.
- * @return mixed
- * @deprecated 3.4.0 The ArrayAccess methods will be removed in 4.0.0. Use getParam(), getData() and getQuery() instead.
- */
- public function offsetGet($name)
- {
- deprecationWarning(
- 'The ArrayAccess methods will be removed in 4.0.0.' .
- 'Use getParam(), getData() and getQuery() instead.'
- );
-
- if (isset($this->params[$name])) {
- return $this->params[$name];
- }
- if ($name === 'url') {
- return $this->query;
- }
- if ($name === 'data') {
- return $this->data;
- }
-
- return null;
- }
-
- /**
- * Array access write implementation
- *
- * @param string $name Name of the key being written
- * @param mixed $value The value being written.
- * @return void
- * @deprecated 3.4.0 The ArrayAccess methods will be removed in 4.0.0. Use withParam() instead.
- */
- public function offsetSet($name, $value)
- {
- deprecationWarning(
- 'The ArrayAccess methods will be removed in 4.0.0.' .
- 'Use withParam() instead.'
- );
-
- $this->params[$name] = $value;
- }
-
- /**
- * Array access isset() implementation
- *
- * @param string $name thing to check.
- * @return bool
- * @deprecated 3.4.0 The ArrayAccess methods will be removed in 4.0.0. Use getParam() instead.
- */
- public function offsetExists($name)
- {
- deprecationWarning(
- 'The ArrayAccess methods will be removed in 4.0.0.' .
- 'Use getParam() instead.'
- );
-
- if ($name === 'url' || $name === 'data') {
- return true;
- }
-
- return isset($this->params[$name]);
- }
-
- /**
- * Array access unset() implementation
- *
- * @param string $name Name to unset.
- * @return void
- * @deprecated 3.4.0 The ArrayAccess methods will be removed in 4.0.0. Use withParam() instead.
- */
- public function offsetUnset($name)
- {
- deprecationWarning(
- 'The ArrayAccess methods will be removed in 4.0.0.' .
- 'Use withParam() instead.'
- );
-
- unset($this->params[$name]);
- }
}
-
-// @deprecated 3.4.0 Add backwards compat alias.
-class_alias('Cake\Http\ServerRequest', 'Cake\Network\Request');
diff --git a/app/vendor/cakephp/cakephp/src/Http/ServerRequestFactory.php b/app/vendor/cakephp/cakephp/src/Http/ServerRequestFactory.php
index 707322872..d1e9a8967 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ServerRequestFactory.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ServerRequestFactory.php
@@ -1,4 +1,6 @@
'php',
'cookiePath' => $uri->webroot,
];
$session = Session::create($sessionConfig);
+ /** @psalm-suppress NoInterfaceProperties */
$request = new ServerRequest([
'environment' => $server,
'uri' => $uri,
@@ -54,12 +78,42 @@ public static function fromGlobals(
'webroot' => $uri->webroot,
'base' => $uri->base,
'session' => $session,
- 'mergeFilesAsObjects' => Configure::read('App.uploadedFilesAsObjects', false),
+ 'mergeFilesAsObjects' => Configure::read('App.uploadedFilesAsObjects', true),
+ 'input' => $server['CAKEPHP_INPUT'] ?? null,
]);
return $request;
}
+ /**
+ * Create a new server request.
+ *
+ * Note that server-params are taken precisely as given - no parsing/processing
+ * of the given values is performed, and, in particular, no attempt is made to
+ * determine the HTTP method or URI, which must be provided explicitly.
+ *
+ * @param string $method The HTTP method associated with the request.
+ * @param \Psr\Http\Message\UriInterface|string $uri The URI associated with the request. If
+ * the value is a string, the factory MUST create a UriInterface
+ * instance based on it.
+ * @param array $serverParams Array of SAPI parameters with which to seed
+ * the generated request instance.
+ * @return \Psr\Http\Message\ServerRequestInterface
+ */
+ public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface
+ {
+ $serverParams['REQUEST_METHOD'] = $method;
+ $options = ['environment' => $serverParams];
+
+ if ($uri instanceof UriInterface) {
+ $options['uri'] = $uri;
+ } else {
+ $options['url'] = $uri;
+ }
+
+ return new ServerRequest($options);
+ }
+
/**
* Create a new Uri instance from the provided server data.
*
@@ -67,13 +121,13 @@ public static function fromGlobals(
* $_SERVER will be added into the $server parameter.
* @return \Psr\Http\Message\UriInterface New instance.
*/
- public static function createUri(array $server = [])
+ public static function createUri(array $server = []): UriInterface
{
$server += $_SERVER;
- $server = static::normalizeServer($server);
- $headers = static::marshalHeaders($server);
+ $server = normalizeServer($server);
+ $headers = marshalHeadersFromSapi($server);
- return static::marshalUriFromServer($server, $headers);
+ return static::marshalUriFromSapi($server, $headers);
}
/**
@@ -86,10 +140,10 @@ public static function createUri(array $server = [])
* @param array $headers The normalized headers
* @return \Psr\Http\Message\UriInterface a constructed Uri
*/
- public static function marshalUriFromServer(array $server, array $headers)
+ protected static function marshalUriFromSapi(array $server, array $headers): UriInterface
{
- $uri = parent::marshalUriFromServer($server, $headers);
- list($base, $webroot) = static::getBase($uri, $server);
+ $uri = marshalUriFromSapi($server, $headers);
+ [$base, $webroot] = static::getBase($uri, $server);
// Look in PATH_INFO first, as this is the exact value we need prepared
// by PHP.
@@ -106,7 +160,9 @@ public static function marshalUriFromServer(array $server, array $headers)
// Splat on some extra attributes to save
// some method calls.
+ /** @psalm-suppress NoInterfaceProperties */
$uri->base = $base;
+ /** @psalm-suppress NoInterfaceProperties */
$uri->webroot = $webroot;
return $uri;
@@ -119,7 +175,7 @@ public static function marshalUriFromServer(array $server, array $headers)
* @param \Psr\Http\Message\UriInterface $uri The uri to update.
* @return \Psr\Http\Message\UriInterface The modified Uri instance.
*/
- protected static function updatePath($base, $uri)
+ protected static function updatePath(string $base, UriInterface $uri): UriInterface
{
$path = $uri->getPath();
if (strlen($base) > 0 && strpos($path, $base) === 0) {
@@ -150,7 +206,7 @@ protected static function updatePath($base, $uri)
* @param array $server The SERVER data to use.
* @return array An array containing the [baseDir, webroot]
*/
- protected static function getBase($uri, $server)
+ protected static function getBase(UriInterface $uri, array $server): array
{
$config = (array)Configure::read('App') + [
'base' => null,
diff --git a/app/vendor/cakephp/cakephp/src/Http/Session.php b/app/vendor/cakephp/cakephp/src/Http/Session.php
index 20ba16a23..77cb73845 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Session.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Session.php
@@ -1,4 +1,6 @@
=')) {
- unset($sessionConfig['ini']['session.save_handler']);
- }
-
if (!isset($sessionConfig['ini']['session.use_strict_mode']) && ini_get('session.use_strict_mode') != 1) {
$sessionConfig['ini']['session.use_strict_mode'] = 1;
}
@@ -132,33 +131,30 @@ public static function create($sessionConfig = [])
* Get one of the prebaked default session configurations.
*
* @param string $name Config name.
- * @return bool|array
+ * @return array|false
*/
- protected static function _defaultConfig($name)
+ protected static function _defaultConfig(string $name)
{
+ $tmp = defined('TMP') ? TMP : sys_get_temp_dir() . DIRECTORY_SEPARATOR;
$defaults = [
'php' => [
- 'cookie' => 'CAKEPHP',
'ini' => [
'session.use_trans_sid' => 0,
],
],
'cake' => [
- 'cookie' => 'CAKEPHP',
'ini' => [
'session.use_trans_sid' => 0,
'session.serialize_handler' => 'php',
'session.use_cookies' => 1,
- 'session.save_path' => TMP . 'sessions',
+ 'session.save_path' => $tmp . 'sessions',
'session.save_handler' => 'files',
],
],
'cache' => [
- 'cookie' => 'CAKEPHP',
'ini' => [
'session.use_trans_sid' => 0,
'session.use_cookies' => 1,
- 'session.save_handler' => 'user',
],
'handler' => [
'engine' => 'CacheSession',
@@ -166,11 +162,9 @@ protected static function _defaultConfig($name)
],
],
'database' => [
- 'cookie' => 'CAKEPHP',
'ini' => [
'session.use_trans_sid' => 0,
'session.use_cookies' => 1,
- 'session.save_handler' => 'user',
'session.serialize_handler' => 'php',
],
'handler' => [
@@ -180,6 +174,13 @@ protected static function _defaultConfig($name)
];
if (isset($defaults[$name])) {
+ if (
+ PHP_VERSION_ID >= 70300
+ && ($name !== 'php' || empty(ini_get('session.cookie_samesite')))
+ ) {
+ $defaults['php']['ini']['session.cookie_samesite'] = 'Lax';
+ }
+
return $defaults[$name];
}
@@ -195,20 +196,27 @@ protected static function _defaultConfig($name)
* - cookiePath: The url path for which session cookie is set. Maps to the
* `session.cookie_path` php.ini config. Defaults to base path of app.
* - ini: A list of php.ini directives to change before the session start.
- * - handler: An array containing at least the `class` key. To be used as the session
+ * - handler: An array containing at least the `engine` key. To be used as the session
* engine for persisting data. The rest of the keys in the array will be passed as
- * the configuration array for the engine. You can set the `class` key to an already
+ * the configuration array for the engine. You can set the `engine` key to an already
* instantiated session handler object.
*
* @param array $config The Configuration to apply to this session object
*/
public function __construct(array $config = [])
{
- if (isset($config['timeout'])) {
+ $config += [
+ 'timeout' => null,
+ 'cookie' => null,
+ 'ini' => [],
+ 'handler' => [],
+ ];
+
+ if ($config['timeout']) {
$config['ini']['session.gc_maxlifetime'] = 60 * $config['timeout'];
}
- if (!empty($config['cookie'])) {
+ if ($config['cookie']) {
$config['ini']['session.name'] = $config['cookie'];
}
@@ -217,11 +225,9 @@ public function __construct(array $config = [])
$config['ini']['session.cookie_path'] = $cookiePath;
}
- if (!empty($config['ini']) && is_array($config['ini'])) {
- $this->options($config['ini']);
- }
+ $this->options($config['ini']);
- if (!empty($config['handler']['engine'])) {
+ if (!empty($config['handler'])) {
$class = $config['handler']['engine'];
unset($config['handler']['engine']);
$this->engine($class, $config['handler']);
@@ -249,7 +255,7 @@ public function __construct(array $config = [])
* @return \SessionHandlerInterface|null
* @throws \InvalidArgumentException
*/
- public function engine($class = null, array $options = [])
+ public function engine($class = null, array $options = []): ?SessionHandlerInterface
{
if ($class === null) {
return $this->_engine;
@@ -259,12 +265,6 @@ public function engine($class = null, array $options = [])
}
$className = App::className($class, 'Http/Session');
- if (!$className) {
- $className = App::className($class, 'Network/Session');
- if ($className) {
- deprecationWarning('Session adapters should be moved to the Http/Session namespace.');
- }
- }
if (!$className) {
throw new InvalidArgumentException(
sprintf('The class "%s" does not exist and cannot be used as a session engine', $class)
@@ -287,7 +287,7 @@ public function engine($class = null, array $options = [])
* @param \SessionHandlerInterface $handler The handler to set
* @return \SessionHandlerInterface
*/
- protected function setEngine(SessionHandlerInterface $handler)
+ protected function setEngine(SessionHandlerInterface $handler): SessionHandlerInterface
{
if (!headers_sent() && session_status() !== \PHP_SESSION_ACTIVE) {
session_set_save_handler($handler, false);
@@ -310,7 +310,7 @@ protected function setEngine(SessionHandlerInterface $handler)
* @return void
* @throws \RuntimeException if any directive could not be set
*/
- public function options(array $options)
+ public function options(array $options): void
{
if (session_status() === \PHP_SESSION_ACTIVE || headers_sent()) {
return;
@@ -331,7 +331,7 @@ public function options(array $options)
* @return bool True if session was started
* @throws \RuntimeException if the session was already started
*/
- public function start()
+ public function start(): bool
{
if ($this->_started) {
return true;
@@ -348,7 +348,7 @@ public function start()
throw new RuntimeException('Session was already started');
}
- if (ini_get('session.use_cookies') && headers_sent($file, $line)) {
+ if (ini_get('session.use_cookies') && headers_sent()) {
return false;
}
@@ -370,14 +370,20 @@ public function start()
/**
* Write data and close the session
*
- * @return bool True if session was started
+ * @return true
*/
- public function close()
+ public function close(): bool
{
if (!$this->_started) {
return true;
}
+ if ($this->_isCLI) {
+ $this->_started = false;
+
+ return true;
+ }
+
if (!session_write_close()) {
throw new RuntimeException('Could not close the session');
}
@@ -392,7 +398,7 @@ public function close()
*
* @return bool True if session has been started.
*/
- public function started()
+ public function started(): bool
{
return $this->_started || session_status() === \PHP_SESSION_ACTIVE;
}
@@ -403,7 +409,7 @@ public function started()
* @param string|null $name Variable name to check for
* @return bool True if variable is there
*/
- public function check($name = null)
+ public function check(?string $name = null): bool
{
if ($this->_hasSession() && !$this->started()) {
$this->start();
@@ -413,6 +419,10 @@ public function check($name = null)
return false;
}
+ if ($name === null) {
+ return (bool)$_SESSION;
+ }
+
return Hash::get($_SESSION, $name) !== null;
}
@@ -420,10 +430,10 @@ public function check($name = null)
* Returns given session variable, or all of them, if no parameters given.
*
* @param string|null $name The name of the session variable (or a path as sent to Hash.extract)
- * @return mixed|null The value of the session variable, null if session not available,
+ * @return string|array|null The value of the session variable, null if session not available,
* session not started, or provided name not found in the session.
*/
- public function read($name = null)
+ public function read(?string $name = null)
{
if ($this->_hasSession() && !$this->started()) {
$this->start();
@@ -434,7 +444,7 @@ public function read($name = null)
}
if ($name === null) {
- return isset($_SESSION) ? $_SESSION : [];
+ return $_SESSION ?: [];
}
return Hash::get($_SESSION, $name);
@@ -447,7 +457,7 @@ public function read($name = null)
* @return mixed The value of the session variable, null if session not available,
* session not started, or provided name not found in the session.
*/
- public function consume($name)
+ public function consume(string $name)
{
if (empty($name)) {
return null;
@@ -467,19 +477,18 @@ public function consume($name)
* @param mixed $value Value to write
* @return void
*/
- public function write($name, $value = null)
+ public function write($name, $value = null): void
{
if (!$this->started()) {
$this->start();
}
- $write = $name;
if (!is_array($name)) {
- $write = [$name => $value];
+ $name = [$name => $value];
}
- $data = isset($_SESSION) ? $_SESSION : [];
- foreach ($write as $key => $val) {
+ $data = $_SESSION ?? [];
+ foreach ($name as $key => $val) {
$data = Hash::insert($data, $key, $val);
}
@@ -500,7 +509,7 @@ public function write($name, $value = null)
* @param string|null $id Id to replace the current session id
* @return string Session id
*/
- public function id($id = null)
+ public function id(?string $id = null): string
{
if ($id !== null && !headers_sent()) {
session_id($id);
@@ -515,7 +524,7 @@ public function id($id = null)
* @param string $name Session variable to remove
* @return void
*/
- public function delete($name)
+ public function delete(string $name): void
{
if ($this->check($name)) {
$this->_overwrite($_SESSION, Hash::remove($_SESSION, $name));
@@ -529,7 +538,7 @@ public function delete($name)
* @param array $new New set of variable => value
* @return void
*/
- protected function _overwrite(&$old, $new)
+ protected function _overwrite(array &$old, array $new): void
{
if (!empty($old)) {
foreach ($old as $key => $var) {
@@ -548,7 +557,7 @@ protected function _overwrite(&$old, $new)
*
* @return void
*/
- public function destroy()
+ public function destroy(): void
{
if ($this->_hasSession() && !$this->started()) {
$this->start();
@@ -570,7 +579,7 @@ public function destroy()
* @param bool $renew If session should be renewed, as well. Defaults to false.
* @return void
*/
- public function clear($renew = false)
+ public function clear(bool $renew = false): void
{
$_SESSION = [];
if ($renew) {
@@ -583,7 +592,7 @@ public function clear($renew = false)
*
* @return bool
*/
- protected function _hasSession()
+ protected function _hasSession(): bool
{
return !ini_get('session.use_cookies')
|| isset($_COOKIE[session_name()])
@@ -596,7 +605,7 @@ protected function _hasSession()
*
* @return void
*/
- public function renew()
+ public function renew(): void
{
if (!$this->_hasSession() || $this->_isCLI) {
return;
@@ -604,25 +613,15 @@ public function renew()
$this->start();
$params = session_get_cookie_params();
- if (PHP_VERSION_ID >= 70300) {
- unset($params['lifetime']);
- $params['expires'] = time() - 42000;
- setcookie(
- session_name(),
- '',
- $params
- );
- } else {
- setcookie(
- session_name(),
- '',
- time() - 42000,
- $params['path'],
- $params['domain'],
- $params['secure'],
- $params['httponly']
- );
- }
+ setcookie(
+ session_name(),
+ '',
+ time() - 42000,
+ $params['path'],
+ $params['domain'],
+ $params['secure'],
+ $params['httponly']
+ );
if (session_id() !== '') {
session_regenerate_id(true);
@@ -635,7 +634,7 @@ public function renew()
*
* @return bool
*/
- protected function _timedOut()
+ protected function _timedOut(): bool
{
$time = $this->read('Config.time');
$result = false;
diff --git a/app/vendor/cakephp/cakephp/src/Http/Session/CacheSession.php b/app/vendor/cakephp/cakephp/src/Http/Session/CacheSession.php
index ab05b4e81..1b4366cdb 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Session/CacheSession.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Session/CacheSession.php
@@ -1,4 +1,6 @@
_options['config']);
@@ -96,7 +98,7 @@ public function read($id)
* @param string $data The data to be saved.
* @return bool True for successful write, false otherwise.
*/
- public function write($id, $data)
+ public function write($id, $data): bool
{
if (!$id) {
return false;
@@ -111,7 +113,7 @@ public function write($id, $data)
* @param string $id ID that uniquely identifies session in cache.
* @return bool Always true.
*/
- public function destroy($id)
+ public function destroy($id): bool
{
Cache::delete($id, $this->_options['config']);
@@ -119,15 +121,13 @@ public function destroy($id)
}
/**
- * Helper function called on gc for cache sessions.
+ * No-op method. Always returns true since cache engine don't have garbage collection.
*
* @param int $maxlifetime Sessions that have not updated for the last maxlifetime seconds will be removed.
* @return bool Always true.
*/
- public function gc($maxlifetime)
+ public function gc($maxlifetime): bool
{
- Cache::gc($this->_options['config'], time() - $maxlifetime);
-
return true;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Session/DatabaseSession.php b/app/vendor/cakephp/cakephp/src/Http/Session/DatabaseSession.php
index 0b1433e97..42b3e9fc4 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Session/DatabaseSession.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Session/DatabaseSession.php
@@ -1,4 +1,6 @@
_timeout = $timeout;
@@ -87,7 +89,7 @@ public function setTimeout($timeout)
* @param string $name The session name.
* @return bool Success
*/
- public function open($savePath, $name)
+ public function open($savePath, $name): bool
{
return true;
}
@@ -97,7 +99,7 @@ public function open($savePath, $name)
*
* @return bool Success
*/
- public function close()
+ public function close(): bool
{
return true;
}
@@ -105,15 +107,17 @@ public function close()
/**
* Method used to read from a database session.
*
- * @param string|int $id ID that uniquely identifies session in database.
+ * @param string $id ID that uniquely identifies session in database.
* @return string Session data or empty string if it does not exist.
*/
- public function read($id)
+ public function read($id): string
{
+ /** @var string $pkField */
+ $pkField = $this->_table->getPrimaryKey();
$result = $this->_table
->find('all')
->select(['data'])
- ->where([$this->_table->getPrimaryKey() => $id])
+ ->where([$pkField => $id])
->disableHydration()
->first();
@@ -137,18 +141,20 @@ public function read($id)
/**
* Helper function called on write for database sessions.
*
- * @param string|int $id ID that uniquely identifies session in database.
- * @param mixed $data The data to be saved.
+ * @param string $id ID that uniquely identifies session in database.
+ * @param string $data The data to be saved.
* @return bool True for successful write, false otherwise.
*/
- public function write($id, $data)
+ public function write($id, $data): bool
{
if (!$id) {
return false;
}
$expires = time() + $this->_timeout;
$record = compact('data', 'expires');
- $record[$this->_table->getPrimaryKey()] = $id;
+ /** @var string $pkField */
+ $pkField = $this->_table->getPrimaryKey();
+ $record[$pkField] = $id;
$result = $this->_table->save(new Entity($record));
return (bool)$result;
@@ -157,13 +163,15 @@ public function write($id, $data)
/**
* Method called on the destruction of a database session.
*
- * @param string|int $id ID that uniquely identifies session in database.
+ * @param string $id ID that uniquely identifies session in database.
* @return bool True for successful delete, false otherwise.
*/
- public function destroy($id)
+ public function destroy($id): bool
{
+ /** @var string $pkField */
+ $pkField = $this->_table->getPrimaryKey();
$this->_table->delete(new Entity(
- [$this->_table->getPrimaryKey() => $id],
+ [$pkField => $id],
['markNew' => false]
));
@@ -176,7 +184,7 @@ public function destroy($id)
* @param int $maxlifetime Sessions that have not updated for the last maxlifetime seconds will be removed.
* @return bool True on success, false on failure.
*/
- public function gc($maxlifetime)
+ public function gc($maxlifetime): bool
{
$this->_table->deleteAll(['expires <' => time()]);
diff --git a/app/vendor/cakephp/cakephp/src/Http/composer.json b/app/vendor/cakephp/cakephp/src/Http/composer.json
new file mode 100644
index 000000000..5802f3e21
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/composer.json
@@ -0,0 +1,49 @@
+{
+ "name": "cakephp/http",
+ "description": "CakePHP HTTP client and PSR7/15 middleware libraries",
+ "type": "library",
+ "keywords": [
+ "cakephp",
+ "http",
+ "psr7",
+ "psr15"
+ ],
+ "homepage": "https://cakephp.org",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/http/graphs/contributors"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/cakephp/cakephp/issues",
+ "forum": "https://stackoverflow.com/tags/cakephp",
+ "irc": "irc://irc.freenode.org/cakephp",
+ "source": "https://github.com/cakephp/http"
+ },
+ "require": {
+ "php": ">=7.2.0",
+ "cakephp/core": "^4.0",
+ "cakephp/event": "^4.0",
+ "cakephp/utility": "^4.0",
+ "composer/ca-bundle": "^1.2",
+ "psr/http-client": "^1.0",
+ "psr/http-server-handler": "^1.0",
+ "psr/http-server-middleware": "^1.0",
+ "laminas/laminas-diactoros": "^2.1",
+ "laminas/laminas-httphandlerrunner": "^1.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "^1.0"
+ },
+ "suggest": {
+ "cakephp/cache": "To use cache session storage",
+ "cakephp/orm": "To use database session storage"
+ },
+ "autoload": {
+ "psr-4": {
+ "Cake\\Http\\": "."
+ }
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/ChainMessagesLoader.php b/app/vendor/cakephp/cakephp/src/I18n/ChainMessagesLoader.php
index 4557c69bb..80693adc5 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/ChainMessagesLoader.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/ChainMessagesLoader.php
@@ -1,4 +1,6 @@
_loaders as $k => $loader) {
if (!is_callable($loader)) {
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Date.php b/app/vendor/cakephp/cakephp/src/I18n/Date.php
index 4f5e3ed16..9ae44c786 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Date.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Date.php
@@ -1,4 +1,6 @@
another Date object representing the "now" date
* - `format` => a fall back format if the relative time is longer than the duration specified by end
* - `accuracy` => Specifies how accurate the date should be described (array)
- * - year => The format if years > 0 (default "day")
- * - month => The format if months > 0 (default "day")
- * - week => The format if weeks > 0 (default "day")
- * - day => The format if weeks > 0 (default "day")
+ * - year => The format if years > 0 (default "day")
+ * - month => The format if months > 0 (default "day")
+ * - week => The format if weeks > 0 (default "day")
+ * - day => The format if weeks > 0 (default "day")
* - `end` => The end of relative date telling
* - `relativeString` => The printf compatible string when outputting relative date
* - `absoluteString` => The printf compatible string when outputting absolute date
@@ -128,8 +168,9 @@ class Date extends MutableDate implements JsonSerializable
* @param array $options Array of options.
* @return string Relative time string.
*/
- public function timeAgoInWords(array $options = [])
+ public function timeAgoInWords(array $options = []): string
{
- return static::diffFormatter()->dateAgoInWords($this, $options);
+ /** @psalm-suppress UndefinedInterfaceMethod */
+ return static::getDiffFormatter()->dateAgoInWords($this, $options);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/DateFormatTrait.php b/app/vendor/cakephp/cakephp/src/I18n/DateFormatTrait.php
index 423d1a7a1..f50cc1a63 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/DateFormatTrait.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/DateFormatTrait.php
@@ -1,4 +1,6 @@
i18nFormat(static::$niceFormat, $timezone, $locale);
}
@@ -209,7 +150,7 @@ public function i18nFormat($format = null, $timezone = null, $locale = null)
$time = $time->timezone($timezone);
}
- $format = $format !== null ? $format : static::$_toStringFormat;
+ $format = $format ?? static::$_toStringFormat;
$locale = $locale ?: static::$defaultLocale;
return $this->_formatObject($time, $format, $locale);
@@ -224,12 +165,12 @@ public function i18nFormat($format = null, $timezone = null, $locale = null)
* @param string|null $locale The locale name in which the date should be displayed.
* @return string
*/
- protected function _formatObject($date, $format, $locale)
+ protected function _formatObject($date, $format, ?string $locale): string
{
- $pattern = $dateFormat = $timeFormat = $calendar = null;
+ $pattern = $timeFormat = null;
if (is_array($format)) {
- list($dateFormat, $timeFormat) = $format;
+ [$dateFormat, $timeFormat] = $format;
} elseif (is_numeric($format)) {
$dateFormat = $format;
} else {
@@ -237,16 +178,17 @@ protected function _formatObject($date, $format, $locale)
$pattern = $format;
}
+ if ($locale === null) {
+ $locale = I18n::getLocale();
+ }
+
+ // phpcs:ignore Generic.Files.LineLength
if (preg_match('/@calendar=(japanese|buddhist|chinese|persian|indian|islamic|hebrew|coptic|ethiopic)/', $locale)) {
$calendar = IntlDateFormatter::TRADITIONAL;
} else {
$calendar = IntlDateFormatter::GREGORIAN;
}
- if ($locale === null) {
- $locale = I18n::getLocale();
- }
-
$timezone = $date->getTimezone()->getName();
$key = "{$locale}.{$dateFormat}.{$timeFormat}.{$timezone}.{$calendar}.{$pattern}";
@@ -264,7 +206,7 @@ protected function _formatObject($date, $format, $locale)
$calendar,
(string)$pattern
);
- if (!$formatter) {
+ if ($formatter === false) {
throw new RuntimeException(
'Your version of icu does not support creating a date formatter for ' .
"`$key`. You should try to upgrade libicu and the intl extension."
@@ -277,9 +219,9 @@ protected function _formatObject($date, $format, $locale)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function __toString()
+ public function __toString(): string
{
return (string)$this->i18nFormat();
}
@@ -290,7 +232,7 @@ public function __toString()
*
* @return void
*/
- public static function resetToStringFormat()
+ public static function resetToStringFormat(): void
{
static::setToStringFormat([IntlDateFormatter::SHORT, IntlDateFormatter::SHORT]);
}
@@ -309,7 +251,7 @@ public static function resetToStringFormat()
* @param string|array|int $format Format.
* @return void
*/
- public static function setToStringFormat($format)
+ public static function setToStringFormat($format): void
{
static::$_toStringFormat = $format;
}
@@ -325,14 +267,11 @@ public static function setToStringFormat($format)
* will be used for formatting the date part of the object and the second position
* will be used to format the time part.
*
- * Alternatively, the format can provide a callback. In this case, the callback
- * can receive this datetime object and return a formatted string.
- *
* @see \Cake\I18n\Time::i18nFormat()
- * @param string|array|int|\Closure $format Format.
+ * @param string|array|int $format Format.
* @return void
*/
- public static function setJsonEncodeFormat($format)
+ public static function setJsonEncodeFormat($format): void
{
static::$_jsonEncodeFormat = $format;
}
@@ -345,6 +284,10 @@ public static function setJsonEncodeFormat($format)
*
* When no $format is provided, the `toString` format will be used.
*
+ * Unlike DateTime, the time zone of the returned instance is always converted
+ * to `$tz` (default time zone if null) even if the `$time` string specified a
+ * time zone. This is a limitation of IntlDateFormatter.
+ *
* If it was impossible to parse the provided time, null will be returned.
*
* Example:
@@ -356,44 +299,48 @@ public static function setJsonEncodeFormat($format)
* ```
*
* @param string $time The time string to parse.
- * @param string|array|null $format Any format accepted by IntlDateFormatter.
+ * @param string|int[]|null $format Any format accepted by IntlDateFormatter.
+ * @param \DateTimeZone|string|null $tz The timezone for the instance
* @return static|null
+ * @throws \InvalidArgumentException If $format is a single int instead of array of constants
*/
- public static function parseDateTime($time, $format = null)
+ public static function parseDateTime(string $time, $format = null, $tz = null)
{
$dateFormat = $format ?: static::$_toStringFormat;
$timeFormat = $pattern = null;
if (is_array($dateFormat)) {
- list($newDateFormat, $timeFormat) = $dateFormat;
+ [$newDateFormat, $timeFormat] = $dateFormat;
$dateFormat = $newDateFormat;
} else {
$pattern = $dateFormat;
$dateFormat = null;
- }
- if (static::$_isDateInstance === null) {
- static::$_isDateInstance =
- is_subclass_of(static::class, ChronosDate::class) ||
- is_subclass_of(static::class, MutableDate::class);
+ if (is_int($pattern)) {
+ throw new InvalidArgumentException(
+ 'If $format is an IntlDateFormatter constant, must be an array.'
+ );
+ }
}
- $defaultTimezone = static::$_isDateInstance ? 'UTC' : date_default_timezone_get();
$formatter = datefmt_create(
- static::$defaultLocale,
- $dateFormat,
- $timeFormat,
- $defaultTimezone,
+ (string)static::$defaultLocale,
+ $dateFormat ?? 0,
+ $timeFormat ?? 0,
+ $tz,
null,
- $pattern
+ $pattern ?? ''
);
- $formatter->setLenient(static::$lenientParsing);
-
$time = $formatter->parse($time);
if ($time !== false) {
- $result = new static('@' . $time);
+ $dateTime = new DateTime('@' . $time);
+
+ if (!($tz instanceof DateTimeZone)) {
+ $tz = new DateTimeZone($tz ?? date_default_timezone_get());
+ }
+ $dateTime->setTimezone($tz);
- return static::$_isDateInstance ? $result : $result->setTimezone($defaultTimezone);
+ return new static($dateTime);
}
return null;
@@ -418,10 +365,10 @@ public static function parseDateTime($time, $format = null)
* ```
*
* @param string $date The date string to parse.
- * @param string|int|null $format Any format accepted by IntlDateFormatter.
+ * @param string|int|array|null $format Any format accepted by IntlDateFormatter.
* @return static|null
*/
- public static function parseDate($date, $format = null)
+ public static function parseDate(string $date, $format = null)
{
if (is_int($format)) {
$format = [$format, -1];
@@ -451,7 +398,7 @@ public static function parseDate($date, $format = null)
* @param string|int|null $format Any format accepted by IntlDateFormatter.
* @return static|null
*/
- public static function parseTime($time, $format = null)
+ public static function parseTime(string $time, $format = null)
{
if (is_int($format)) {
$format = [-1, $format];
@@ -464,35 +411,37 @@ public static function parseTime($time, $format = null)
/**
* Returns a string that should be serialized when converting this object to json
*
- * @return string
+ * @return string|int
*/
public function jsonSerialize()
{
- if (is_callable(static::$_jsonEncodeFormat)) {
- return call_user_func(static::$_jsonEncodeFormat, $this);
- }
-
return $this->i18nFormat(static::$_jsonEncodeFormat);
}
/**
- * Get the difference formatter instance or overwrite the current one.
+ * Get the difference formatter instance.
*
- * @param \Cake\I18n\RelativeTimeFormatter|null $formatter The formatter instance when setting.
- * @return \Cake\I18n\RelativeTimeFormatter The formatter instance.
+ * @return \Cake\Chronos\DifferenceFormatterInterface
*/
- public static function diffFormatter($formatter = null)
+ public static function getDiffFormatter(): DifferenceFormatterInterface
{
- if ($formatter === null) {
- // Use the static property defined in chronos.
- if (static::$diffFormatter === null) {
- static::$diffFormatter = new RelativeTimeFormatter();
- }
-
- return static::$diffFormatter;
+ // Use the static property defined in chronos.
+ if (static::$diffFormatter === null) {
+ static::$diffFormatter = new RelativeTimeFormatter();
}
- return static::$diffFormatter = $formatter;
+ return static::$diffFormatter;
+ }
+
+ /**
+ * Set the difference formatter instance.
+ *
+ * @param \Cake\Chronos\DifferenceFormatterInterface $formatter The formatter instance when setting.
+ * @return void
+ */
+ public static function setDiffFormatter(DifferenceFormatterInterface $formatter): void
+ {
+ static::$diffFormatter = $formatter;
}
/**
@@ -500,8 +449,9 @@ public static function diffFormatter($formatter = null)
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
+ /** @psalm-suppress PossiblyNullReference */
return [
'time' => $this->format('Y-m-d H:i:s.uP'),
'timezone' => $this->getTimezone()->getName(),
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Formatter/IcuFormatter.php b/app/vendor/cakephp/cakephp/src/I18n/Formatter/IcuFormatter.php
index e02d5264f..4232da6ec 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Formatter/IcuFormatter.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Formatter/IcuFormatter.php
@@ -1,4 +1,6 @@
_formatMessage($locale, $message, $vars);
+ }
+
+ /**
+ * Does the actual formatting using the MessageFormatter class
+ *
+ * @param string $locale The locale in which the message is presented.
+ * @param string $message The message to be translated
+ * @param array $vars The list of values to interpolate in the message
+ * @return string The formatted message
+ * @throws \Aura\Intl\Exception\CannotInstantiateFormatter if any error occurred
+ * while parsing the message
+ * @throws \Aura\Intl\Exception\CannotFormat If any error related to the passed
+ * variables is found
+ */
+ protected function _formatMessage(string $locale, string $message, array $vars): string
{
if ($message === '') {
return $message;
@@ -48,10 +68,6 @@ public function format($locale, $message, array $vars)
// The user might be interested in what went wrong, so replay the
// previous action using the object oriented style to figure out
$formatter = new MessageFormatter($locale, $message);
- if (!$formatter) {
- throw new CannotInstantiateFormatter(intl_get_error_message(), intl_get_error_code());
- }
-
$formatter->format($vars);
throw new CannotFormat($formatter->getErrorMessage(), $formatter->getErrorCode());
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Formatter/SprintfFormatter.php b/app/vendor/cakephp/cakephp/src/I18n/Formatter/SprintfFormatter.php
index 460d7d3c8..2609ce023 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Formatter/SprintfFormatter.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Formatter/SprintfFormatter.php
@@ -1,4 +1,6 @@
another Date object representing the "now" date
* - `format` => a fall back format if the relative time is longer than the duration specified by end
* - `accuracy` => Specifies how accurate the date should be described (array)
- * - year => The format if years > 0 (default "day")
- * - month => The format if months > 0 (default "day")
- * - week => The format if weeks > 0 (default "day")
- * - day => The format if weeks > 0 (default "day")
+ * - year => The format if years > 0 (default "day")
+ * - month => The format if months > 0 (default "day")
+ * - week => The format if weeks > 0 (default "day")
+ * - day => The format if weeks > 0 (default "day")
* - `end` => The end of relative date telling
* - `relativeString` => The printf compatible string when outputting relative date
* - `absoluteString` => The printf compatible string when outputting absolute date
@@ -130,8 +170,9 @@ class FrozenDate extends ChronosDate implements JsonSerializable
* @param array $options Array of options.
* @return string Relative time string.
*/
- public function timeAgoInWords(array $options = [])
+ public function timeAgoInWords(array $options = []): string
{
- return static::diffFormatter()->dateAgoInWords($this, $options);
+ /** @psalm-suppress UndefinedInterfaceMethod */
+ return static::getDiffFormatter()->dateAgoInWords($this, $options);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/FrozenTime.php b/app/vendor/cakephp/cakephp/src/I18n/FrozenTime.php
index 61909ac17..bd342a5eb 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/FrozenTime.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/FrozenTime.php
@@ -1,4 +1,6 @@
another Time object representing the "now" time
* - `format` => a fall back format if the relative time is longer than the duration specified by end
* - `accuracy` => Specifies how accurate the date should be described (array)
- * - year => The format if years > 0 (default "day")
- * - month => The format if months > 0 (default "day")
- * - week => The format if weeks > 0 (default "day")
- * - day => The format if weeks > 0 (default "hour")
- * - hour => The format if hours > 0 (default "minute")
- * - minute => The format if minutes > 0 (default "minute")
- * - second => The format if seconds > 0 (default "second")
+ * - year => The format if years > 0 (default "day")
+ * - month => The format if months > 0 (default "day")
+ * - week => The format if weeks > 0 (default "day")
+ * - day => The format if weeks > 0 (default "hour")
+ * - hour => The format if hours > 0 (default "minute")
+ * - minute => The format if minutes > 0 (default "minute")
+ * - second => The format if seconds > 0 (default "second")
* - `end` => The end of relative time telling
* - `relativeString` => The printf compatible string when outputting relative time
* - `absoluteString` => The printf compatible string when outputting absolute time
@@ -158,9 +178,10 @@ public function __construct($time = null, $tz = null)
* @param array $options Array of options.
* @return string Relative time string.
*/
- public function timeAgoInWords(array $options = [])
+ public function timeAgoInWords(array $options = []): string
{
- return static::diffFormatter()->timeAgoInWords($this, $options);
+ /** @psalm-suppress UndefinedInterfaceMethod */
+ return static::getDiffFormatter()->timeAgoInWords($this, $options);
}
/**
@@ -178,7 +199,7 @@ public function timeAgoInWords(array $options = [])
* @return array List of timezone identifiers
* @since 2.2
*/
- public static function listTimezones($filter = null, $country = null, $options = [])
+ public static function listTimezones($filter = null, ?string $country = null, $options = []): array
{
if (is_bool($options)) {
$options = [
@@ -202,7 +223,7 @@ public static function listTimezones($filter = null, $country = null, $options =
if ($filter === null) {
$filter = DateTimeZone::ALL;
}
- $identifiers = DateTimeZone::listIdentifiers($filter, $country);
+ $identifiers = DateTimeZone::listIdentifiers($filter, (string)$country) ?: [];
if ($regex) {
foreach ($identifiers as $key => $tz) {
@@ -217,14 +238,14 @@ public static function listTimezones($filter = null, $country = null, $options =
$now = time();
$before = $options['before'];
$after = $options['after'];
- foreach ($identifiers as $key => $tz) {
- $abbr = null;
+ foreach ($identifiers as $tz) {
+ $abbr = '';
if ($options['abbr']) {
$dateTimeZone = new DateTimeZone($tz);
$trans = $dateTimeZone->getTransitions($now, $now);
$abbr = isset($trans[0]['abbr']) ?
$before . $trans[0]['abbr'] . $after :
- null;
+ '';
}
$item = explode('/', $tz, 2);
if (isset($item[1])) {
@@ -239,54 +260,4 @@ public static function listTimezones($filter = null, $country = null, $options =
return array_combine($identifiers, $identifiers);
}
-
- /**
- * Returns true this instance happened within the specified interval
- *
- * This overridden method provides backwards compatible behavior for integers,
- * or strings with trailing spaces. This behavior is *deprecated* and will be
- * removed in future versions of CakePHP.
- *
- * @param string|int $timeInterval the numeric value with space then time type.
- * Example of valid types: 6 hours, 2 days, 1 minute.
- * @return bool
- */
- public function wasWithinLast($timeInterval)
- {
- $tmp = trim($timeInterval);
- if (is_numeric($tmp)) {
- deprecationWarning(
- 'Passing int/numeric string into FrozenTime::wasWithinLast() is deprecated. ' .
- 'Pass strings including interval eg. "6 days"'
- );
- $timeInterval = $tmp . ' days';
- }
-
- return parent::wasWithinLast($timeInterval);
- }
-
- /**
- * Returns true this instance will happen within the specified interval
- *
- * This overridden method provides backwards compatible behavior for integers,
- * or strings with trailing spaces. This behavior is *deprecated* and will be
- * removed in future versions of CakePHP.
- *
- * @param string|int $timeInterval the numeric value with space then time type.
- * Example of valid types: 6 hours, 2 days, 1 minute.
- * @return bool
- */
- public function isWithinNext($timeInterval)
- {
- $tmp = trim($timeInterval);
- if (is_numeric($tmp)) {
- deprecationWarning(
- 'Passing int/numeric string into FrozenTime::isWithinNext() is deprecated. ' .
- 'Pass strings including interval eg. "6 days"'
- );
- $timeInterval = $tmp . ' days';
- }
-
- return parent::isWithinNext($timeInterval);
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/I18n.php b/app/vendor/cakephp/cakephp/src/I18n/I18n.php
index db3248652..b1ae94ef9 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/I18n.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/I18n.php
@@ -1,4 +1,6 @@
setCacher(Cache::engine('_cake_core_'));
+ if (class_exists(Cache::class)) {
+ static::$_collection->setCacher(Cache::pool('_cake_core_'));
}
return static::$_collection;
}
- /**
- * Returns an instance of a translator that was configured for the name and passed
- * locale. If no locale is passed then it takes the value returned by the `getLocale()` method.
- *
- * This method can be used to configure future translators, this is achieved by passing a callable
- * as the last argument of this function.
- *
- * ### Example:
- *
- * ```
- * I18n::setTranslator('default', function () {
- * $package = new \Aura\Intl\Package();
- * $package->setMessages([
- * 'Cake' => 'Gâteau'
- * ]);
- * return $package;
- * }, 'fr_FR');
- *
- * $translator = I18n::translator('default', 'fr_FR');
- * echo $translator->translate('Cake');
- * ```
- *
- * You can also use the `Cake\I18n\MessagesFileLoader` class to load a specific
- * file from a folder. For example for loading a `my_translations.po` file from
- * the `src/Locale/custom` folder, you would do:
- *
- * ```
- * I18n::translator(
- * 'default',
- * 'fr_FR',
- * new MessagesFileLoader('my_translations', 'custom', 'po');
- * );
- * ```
- *
- * @deprecated 3.5 Use getTranslator() and setTranslator()
- * @param string $name The domain of the translation messages.
- * @param string|null $locale The locale for the translator.
- * @param callable|null $loader A callback function or callable class responsible for
- * constructing a translations package instance.
- * @return \Aura\Intl\TranslatorInterface|null The configured translator.
- * @throws \Aura\Intl\Exception
- */
- public static function translator($name = 'default', $locale = null, callable $loader = null)
- {
- deprecationWarning(
- 'I18n::translator() is deprecated. ' .
- 'Use I18n::setTranslator()/getTranslator() instead.'
- );
- if ($loader !== null) {
- static::setTranslator($name, $loader, $locale);
-
- return null;
- }
-
- return self::getTranslator($name, $locale);
- }
-
/**
* Sets a translator.
*
@@ -161,7 +108,7 @@ public static function translator($name = 'default', $locale = null, callable $l
*
* You can also use the `Cake\I18n\MessagesFileLoader` class to load a specific
* file from a folder. For example for loading a `my_translations.po` file from
- * the `src/Locale/custom` folder, you would do:
+ * the `resources/locales/custom` folder, you would do:
*
* ```
* I18n::setTranslator(
@@ -177,7 +124,7 @@ public static function translator($name = 'default', $locale = null, callable $l
* @param string|null $locale The locale for the translator.
* @return void
*/
- public static function setTranslator($name, callable $loader, $locale = null)
+ public static function setTranslator(string $name, callable $loader, ?string $locale = null): void
{
$locale = $locale ?: static::getLocale();
@@ -197,7 +144,7 @@ public static function setTranslator($name, callable $loader, $locale = null)
* @return \Aura\Intl\TranslatorInterface The configured translator.
* @throws \Aura\Intl\Exception
*/
- public static function getTranslator($name = 'default', $locale = null)
+ public static function getTranslator(string $name = 'default', ?string $locale = null): TranslatorInterface
{
$translators = static::translators();
@@ -207,6 +154,12 @@ public static function getTranslator($name = 'default', $locale = null)
}
$translator = $translators->get($name);
+ if ($translator === null) {
+ throw new Exception(sprintf(
+ 'Translator for domain "%s" could not be found.',
+ $name
+ ));
+ }
if (isset($currentLocale)) {
$translators->setLocale($currentLocale);
@@ -234,7 +187,7 @@ public static function getTranslator($name = 'default', $locale = null)
* ```
* use Cake\I18n\MessagesFileLoader;
* I18n::config('my_domain', function ($name, $locale) {
- * // Load src/Locale/$locale/filename.po
+ * // Load resources/locales/$locale/filename.po
* $fileLoader = new MessagesFileLoader('filename', $locale, 'po');
* return $fileLoader();
* });
@@ -258,37 +211,11 @@ public static function getTranslator($name = 'default', $locale = null)
* instance to be used for assembling a new translator.
* @return void
*/
- public static function config($name, callable $loader)
+ public static function config(string $name, callable $loader): void
{
static::translators()->registerLoader($name, $loader);
}
- /**
- * Sets the default locale to use for future translator instances.
- * This also affects the `intl.default_locale` PHP setting.
- *
- * When called with no arguments it will return the currently configure
- * locale as stored in the `intl.default_locale` PHP setting.
- *
- * @deprecated 3.5 Use setLocale() and getLocale().
- * @param string|null $locale The name of the locale to set as default.
- * @return string|null The name of the default locale.
- */
- public static function locale($locale = null)
- {
- deprecationWarning(
- 'I18n::locale() is deprecated. ' .
- 'Use I18n::setLocale()/getLocale() instead.'
- );
- if (!empty($locale)) {
- static::setLocale($locale);
-
- return null;
- }
-
- return self::getLocale();
- }
-
/**
* Sets the default locale to use for future translator instances.
* This also affects the `intl.default_locale` PHP setting.
@@ -296,7 +223,7 @@ public static function locale($locale = null)
* @param string $locale The name of the locale to set as default.
* @return void
*/
- public static function setLocale($locale)
+ public static function setLocale(string $locale): void
{
static::getDefaultLocale();
Locale::setDefault($locale);
@@ -311,7 +238,7 @@ public static function setLocale($locale)
*
* @return string The name of the default locale.
*/
- public static function getLocale()
+ public static function getLocale(): string
{
static::getDefaultLocale();
$current = Locale::getDefault();
@@ -323,21 +250,6 @@ public static function getLocale()
return $current;
}
- /**
- * This returns the default locale before any modifications, i.e.
- * the value as stored in the `intl.default_locale` PHP setting before
- * any manipulation by this class.
- *
- * @deprecated 3.5 Use getDefaultLocale()
- * @return string
- */
- public static function defaultLocale()
- {
- deprecationWarning('I18n::defaultLocale() is deprecated. Use I18n::getDefaultLocale() instead.');
-
- return static::getDefaultLocale();
- }
-
/**
* Returns the default locale.
*
@@ -347,7 +259,7 @@ public static function defaultLocale()
*
* @return string
*/
- public static function getDefaultLocale()
+ public static function getDefaultLocale(): string
{
if (static::$_defaultLocale === null) {
static::$_defaultLocale = Locale::getDefault() ?: static::DEFAULT_LOCALE;
@@ -356,34 +268,12 @@ public static function getDefaultLocale()
return static::$_defaultLocale;
}
- /**
- * Sets the name of the default messages formatter to use for future
- * translator instances.
- *
- * By default the `default` and `sprintf` formatters are available.
- *
- * If called with no arguments, it will return the currently configured value.
- *
- * @deprecated 3.5 Use getDefaultFormatter() and setDefaultFormatter().
- * @param string|null $name The name of the formatter to use.
- * @return string The name of the formatter.
- */
- public static function defaultFormatter($name = null)
- {
- deprecationWarning(
- 'I18n::defaultFormatter() is deprecated. ' .
- 'Use I18n::setDefaultFormatter()/getDefaultFormatter() instead.'
- );
-
- return static::translators()->defaultFormatter($name);
- }
-
/**
* Returns the currently configured default formatter.
*
* @return string The name of the formatter.
*/
- public static function getDefaultFormatter()
+ public static function getDefaultFormatter(): string
{
return static::translators()->defaultFormatter();
}
@@ -396,7 +286,7 @@ public static function getDefaultFormatter()
* @param string $name The name of the formatter to use.
* @return void
*/
- public static function setDefaultFormatter($name)
+ public static function setDefaultFormatter(string $name): void
{
static::translators()->defaultFormatter($name);
}
@@ -407,7 +297,7 @@ public static function setDefaultFormatter($name)
* @param bool $enable flag to enable or disable fallback
* @return void
*/
- public static function useFallback($enable = true)
+ public static function useFallback(bool $enable = true): void
{
static::translators()->useFallback($enable);
}
@@ -418,7 +308,7 @@ public static function useFallback($enable = true)
*
* @return void
*/
- public static function clear()
+ public static function clear(): void
{
static::$_collection = null;
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/I18nDateTimeInterface.php b/app/vendor/cakephp/cakephp/src/I18n/I18nDateTimeInterface.php
new file mode 100644
index 000000000..02822624a
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/I18n/I18nDateTimeInterface.php
@@ -0,0 +1,224 @@
+i18nFormat(); // outputs '4/20/14, 10:10 PM' for the en-US locale
+ * $time->i18nFormat(\IntlDateFormatter::FULL); // Use the full date and time format
+ * $time->i18nFormat([\IntlDateFormatter::FULL, \IntlDateFormatter::SHORT]); // Use full date but short time format
+ * $time->i18nFormat('yyyy-MM-dd HH:mm:ss'); // outputs '2014-04-20 22:10'
+ * $time->i18nFormat(Time::UNIX_TIMESTAMP_FORMAT); // outputs '1398031800'
+ * ```
+ *
+ * If you wish to control the default format to be used for this method, you can alter
+ * the value of the static `Time::$defaultLocale` variable and set it to one of the
+ * possible formats accepted by this function.
+ *
+ * You can read about the available IntlDateFormatter constants at
+ * https://secure.php.net/manual/en/class.intldateformatter.php
+ *
+ * If you need to display the date in a different timezone than the one being used for
+ * this Time object without altering its internal state, you can pass a timezone
+ * string or object as the second parameter.
+ *
+ * Finally, should you need to use a different locale for displaying this time object,
+ * pass a locale string as the third parameter to this function.
+ *
+ * ### Examples
+ *
+ * ```
+ * $time = new Time('2014-04-20 22:10');
+ * $time->i18nFormat(null, null, 'de-DE');
+ * $time->i18nFormat(\IntlDateFormatter::FULL, 'Europe/Berlin', 'de-DE');
+ * ```
+ *
+ * You can control the default locale to be used by setting the static variable
+ * `Time::$defaultLocale` to a valid locale string. If empty, the default will be
+ * taken from the `intl.default_locale` ini config.
+ *
+ * @param string|int|null $format Format string.
+ * @param string|\DateTimeZone|null $timezone Timezone string or DateTimeZone object
+ * in which the date will be displayed. The timezone stored for this object will not
+ * be changed.
+ * @param string|null $locale The locale name in which the date should be displayed (e.g. pt-BR)
+ * @return string|int Formatted and translated date string
+ */
+ public function i18nFormat($format = null, $timezone = null, $locale = null);
+
+ /**
+ * Resets the format used to the default when converting an instance of this type to
+ * a string
+ *
+ * @return void
+ */
+ public static function resetToStringFormat(): void;
+
+ /**
+ * Sets the default format used when type converting instances of this type to string
+ *
+ * @param string|array|int $format Format.
+ * @return void
+ */
+ public static function setToStringFormat($format): void;
+
+ /**
+ * Sets the default format used when converting this object to json
+ *
+ * @param string|array|int $format Format.
+ * @return void
+ */
+ public static function setJsonEncodeFormat($format): void;
+
+ /**
+ * Returns a new Time object after parsing the provided time string based on
+ * the passed or configured date time format. This method is locale dependent,
+ * Any string that is passed to this function will be interpreted as a locale
+ * dependent string.
+ *
+ * When no $format is provided, the `toString` format will be used.
+ *
+ * If it was impossible to parse the provided time, null will be returned.
+ *
+ * Example:
+ *
+ * ```
+ * $time = Time::parseDateTime('10/13/2013 12:54am');
+ * $time = Time::parseDateTime('13 Oct, 2013 13:54', 'dd MMM, y H:mm');
+ * $time = Time::parseDateTime('10/10/2015', [IntlDateFormatter::SHORT, -1]);
+ * ```
+ *
+ * @param string $time The time string to parse.
+ * @param string|int[]|null $format Any format accepted by IntlDateFormatter.
+ * @param \DateTimeZone|string|null $tz The timezone for the instance
+ * @return static|null
+ * @throws \InvalidArgumentException If $format is a single int instead of array of constants
+ */
+ public static function parseDateTime(string $time, $format = null, $tz = null);
+
+ /**
+ * Returns a new Time object after parsing the provided $date string based on
+ * the passed or configured date time format. This method is locale dependent,
+ * Any string that is passed to this function will be interpreted as a locale
+ * dependent string.
+ *
+ * When no $format is provided, the `wordFormat` format will be used.
+ *
+ * If it was impossible to parse the provided time, null will be returned.
+ *
+ * Example:
+ *
+ * ```
+ * $time = Time::parseDate('10/13/2013');
+ * $time = Time::parseDate('13 Oct, 2013', 'dd MMM, y');
+ * $time = Time::parseDate('13 Oct, 2013', IntlDateFormatter::SHORT);
+ * ```
+ *
+ * @param string $date The date string to parse.
+ * @param string|int|array|null $format Any format accepted by IntlDateFormatter.
+ * @return static|null
+ */
+ public static function parseDate(string $date, $format = null);
+
+ /**
+ * Returns a new Time object after parsing the provided $time string based on
+ * the passed or configured date time format. This method is locale dependent,
+ * Any string that is passed to this function will be interpreted as a locale
+ * dependent string.
+ *
+ * When no $format is provided, the IntlDateFormatter::SHORT format will be used.
+ *
+ * If it was impossible to parse the provided time, null will be returned.
+ *
+ * Example:
+ *
+ * ```
+ * $time = Time::parseTime('11:23pm');
+ * ```
+ *
+ * @param string $time The time string to parse.
+ * @param string|int|null $format Any format accepted by IntlDateFormatter.
+ * @return static|null
+ */
+ public static function parseTime(string $time, $format = null);
+
+ /**
+ * Get the difference formatter instance.
+ *
+ * @return \Cake\Chronos\DifferenceFormatterInterface The formatter instance.
+ */
+ public static function getDiffFormatter(): DifferenceFormatterInterface;
+
+ /**
+ * Set the difference formatter instance.
+ *
+ * @param \Cake\Chronos\DifferenceFormatterInterface $formatter The formatter instance when setting.
+ * @return void
+ */
+ public static function setDiffFormatter(DifferenceFormatterInterface $formatter): void;
+}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/LICENSE.txt b/app/vendor/cakephp/cakephp/src/I18n/LICENSE.txt
index 0c4b7932c..0b3b94303 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/LICENSE.txt
+++ b/app/vendor/cakephp/cakephp/src/I18n/LICENSE.txt
@@ -1,7 +1,7 @@
The MIT License (MIT)
CakePHP(tm) : The Rapid Development PHP Framework (https://cakephp.org)
-Copyright (c) 2005-2016, Cake Software Foundation, Inc. (https://cakefoundation.org)
+Copyright (c) 2005-2019, Cake Software Foundation, Inc. (https://cakefoundation.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/vendor/cakephp/cakephp/src/I18n/MessagesFileLoader.php b/app/vendor/cakephp/cakephp/src/I18n/MessagesFileLoader.php
index f98691bef..662625b00 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/MessagesFileLoader.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/MessagesFileLoader.php
@@ -1,4 +1,6 @@
_name = $name;
$this->_locale = $locale;
@@ -147,7 +149,7 @@ public function __invoke()
*
* @return string[] The list of folders where the translation file should be looked for
*/
- public function translationsFolders()
+ public function translationsFolders(): array
{
$locale = Locale::parseLocale($this->_locale) + ['region' => null];
@@ -158,9 +160,9 @@ public function translationsFolders()
$searchPaths = [];
- $localePaths = App::path('Locale');
+ $localePaths = App::path('locales');
if (empty($localePaths) && defined('APP')) {
- $localePaths[] = APP . 'Locale' . DIRECTORY_SEPARATOR;
+ $localePaths[] = ROOT . 'resources' . DIRECTORY_SEPARATOR . 'locales' . DIRECTORY_SEPARATOR;
}
foreach ($localePaths as $path) {
foreach ($folders as $folder) {
@@ -171,7 +173,7 @@ public function translationsFolders()
// If space is not added after slash, the character after it remains lowercased
$pluginName = Inflector::camelize(str_replace('/', '/ ', $this->_name));
if (Plugin::isLoaded($pluginName)) {
- $basePath = Plugin::classPath($pluginName) . 'Locale' . DIRECTORY_SEPARATOR;
+ $basePath = App::path('locales', $pluginName)[0];
foreach ($folders as $folder) {
$searchPaths[] = $basePath . $folder . DIRECTORY_SEPARATOR;
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Middleware/LocaleSelectorMiddleware.php b/app/vendor/cakephp/cakephp/src/I18n/Middleware/LocaleSelectorMiddleware.php
index 9d2e2c360..6d32035c2 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Middleware/LocaleSelectorMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Middleware/LocaleSelectorMiddleware.php
@@ -1,4 +1,6 @@
getHeaderLine('Accept-Language'));
if (!$locale) {
- return $next($request, $response);
+ return $handler->handle($request);
}
if ($this->locales !== ['*']) {
$locale = Locale::lookup($this->locales, $locale, true);
@@ -62,6 +67,6 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res
I18n::setLocale($locale);
}
- return $next($request, $response);
+ return $handler->handle($request);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Number.php b/app/vendor/cakephp/cakephp/src/I18n/Number.php
index 060a7eef1..33d70c814 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Number.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Number.php
@@ -1,4 +1,6 @@
$precision, 'places' => $precision] + $options);
@@ -93,9 +103,9 @@ public static function precision($value, $precision = 3, array $options = [])
*
* @param int|string $size Size in bytes
* @return string Human readable size
- * @link https://book.cakephp.org/3/en/core-libraries/number.html#interacting-with-human-readable-values
+ * @link https://book.cakephp.org/4/en/core-libraries/number.html#interacting-with-human-readable-values
*/
- public static function toReadableSize($size)
+ public static function toReadableSize($size): string
{
$size = (int)$size;
@@ -125,9 +135,9 @@ public static function toReadableSize($size)
* @param int $precision The precision of the returned number
* @param array $options Options
* @return string Percentage string
- * @link https://book.cakephp.org/3/en/core-libraries/number.html#formatting-percentages
+ * @link https://book.cakephp.org/4/en/core-libraries/number.html#formatting-percentages
*/
- public static function toPercentage($value, $precision = 2, array $options = [])
+ public static function toPercentage($value, int $precision = 2, array $options = []): string
{
$options += ['multiply' => false, 'type' => NumberFormatter::PERCENT];
if (!$options['multiply']) {
@@ -153,7 +163,7 @@ public static function toPercentage($value, $precision = 2, array $options = [])
* @param array $options An array with options.
* @return string Formatted number
*/
- public static function format($value, array $options = [])
+ public static function format($value, array $options = []): string
{
$formatter = static::formatter($options);
$options += ['before' => '', 'after' => ''];
@@ -174,7 +184,7 @@ public static function format($value, array $options = [])
* @param array $options An array with options.
* @return float point number
*/
- public static function parseFloat($value, array $options = [])
+ public static function parseFloat(string $value, array $options = []): float
{
$formatter = static::formatter($options);
@@ -196,7 +206,7 @@ public static function parseFloat($value, array $options = [])
* @param array $options Options list.
* @return string formatted delta
*/
- public static function formatDelta($value, array $options = [])
+ public static function formatDelta($value, array $options = []): string
{
$options += ['places' => 0];
$value = number_format((float)$value, $options['places'], '.', '');
@@ -229,7 +239,7 @@ public static function formatDelta($value, array $options = [])
* @param array $options Options list.
* @return string Number formatted as a currency.
*/
- public static function currency($value, $currency = null, array $options = [])
+ public static function currency($value, ?string $currency = null, array $options = []): string
{
$value = (float)$value;
$currency = $currency ?: static::getDefaultCurrency();
@@ -242,28 +252,33 @@ public static function currency($value, $currency = null, array $options = [])
$abs = abs($value);
if (!empty($options['fractionSymbol']) && $abs > 0 && $abs < 1) {
$value *= 100;
- $pos = isset($options['fractionPosition']) ? $options['fractionPosition'] : 'after';
+ $pos = $options['fractionPosition'] ?? 'after';
return static::format($value, ['precision' => 0, $pos => $options['fractionSymbol']]);
}
- $before = isset($options['before']) ? $options['before'] : null;
- $after = isset($options['after']) ? $options['after'] : null;
+ $before = $options['before'] ?? '';
+ $after = $options['after'] ?? '';
+ if ($currency) {
+ $value = $formatter->formatCurrency($value, $currency);
+ } else {
+ $formatter->format($value, NumberFormatter::TYPE_CURRENCY);
+ }
- return $before . $formatter->formatCurrency($value, $currency) . $after;
+ return $before . $value . $after;
}
/**
* Getter/setter for default currency. This behavior is *deprecated* and will be
* removed in future versions of CakePHP.
*
- * @deprecated 3.9 Use getDefaultCurrency() and setDefaultCurrency()
- * @param string|false|null $currency Default currency string to be used by currency()
+ * @deprecated 3.9.0 Use {@link getDefaultCurrency()} and {@link setDefaultCurrency()} instead.
+ * @param string|false|null $currency Default currency string to be used by {@link currency()}
* if $currency argument is not provided. If boolean false is passed, it will clear the
* currently stored value
* @return string|null Currency
*/
- public static function defaultCurrency($currency = null)
+ public static function defaultCurrency($currency = null): ?string
{
deprecationWarning(
'Number::defaultCurrency() is deprecated. ' .
@@ -276,7 +291,8 @@ public static function defaultCurrency($currency = null)
// This doesn't seem like a useful result to return, but it's what the old version did.
// Retaining it for backward compatibility.
return null;
- } elseif ($currency !== null) {
+ }
+ if ($currency !== null) {
static::setDefaultCurrency($currency);
}
@@ -288,7 +304,7 @@ public static function defaultCurrency($currency = null)
*
* @return string Currency
*/
- public static function getDefaultCurrency()
+ public static function getDefaultCurrency(): string
{
if (static::$_defaultCurrency === null) {
$locale = ini_get('intl.default_locale') ?: static::DEFAULT_LOCALE;
@@ -302,12 +318,12 @@ public static function getDefaultCurrency()
/**
* Setter for default currency
*
- * @param string|null $currency Default currency string to be used by currency()
+ * @param string|null $currency Default currency string to be used by {@link currency()}
* if $currency argument is not provided. If null is passed, it will clear the
* currently stored value
* @return void
*/
- public static function setDefaultCurrency($currency = null)
+ public static function setDefaultCurrency(?string $currency = null): void
{
static::$_defaultCurrency = $currency;
}
@@ -317,7 +333,7 @@ public static function setDefaultCurrency($currency = null)
*
* @return string Currency Format
*/
- public static function getDefaultCurrencyFormat()
+ public static function getDefaultCurrencyFormat(): string
{
if (static::$_defaultCurrencyFormat === null) {
static::$_defaultCurrencyFormat = static::FORMAT_CURRENCY;
@@ -334,7 +350,7 @@ public static function getDefaultCurrencyFormat()
* currently stored value
* @return void
*/
- public static function setDefaultCurrencyFormat($currencyFormat = null)
+ public static function setDefaultCurrencyFormat($currencyFormat = null): void
{
static::$_defaultCurrencyFormat = $currencyFormat;
}
@@ -359,9 +375,9 @@ public static function setDefaultCurrencyFormat($currencyFormat = null)
* @param array $options An array with options.
* @return \NumberFormatter The configured formatter instance
*/
- public static function formatter($options = [])
+ public static function formatter(array $options = []): NumberFormatter
{
- $locale = isset($options['locale']) ? $options['locale'] : ini_get('intl.default_locale');
+ $locale = $options['locale'] ?? ini_get('intl.default_locale');
if (!$locale) {
$locale = static::DEFAULT_LOCALE;
@@ -411,7 +427,7 @@ public static function formatter($options = [])
* @param array $options See Number::formatter() for possible options.
* @return void
*/
- public static function config($locale, $type = NumberFormatter::DECIMAL, array $options = [])
+ public static function config(string $locale, int $type = NumberFormatter::DECIMAL, array $options = []): void
{
static::$_formatters[$locale][$type] = static::_setAttributes(
new NumberFormatter($locale, $type),
@@ -426,7 +442,7 @@ public static function config($locale, $type = NumberFormatter::DECIMAL, array $
* @param array $options See Number::formatter() for possible options.
* @return \NumberFormatter
*/
- protected static function _setAttributes(NumberFormatter $formatter, array $options = [])
+ protected static function _setAttributes(NumberFormatter $formatter, array $options = []): NumberFormatter
{
if (isset($options['places'])) {
$formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $options['places']);
@@ -466,7 +482,7 @@ protected static function _setAttributes(NumberFormatter $formatter, array $opti
* @param array $options An array with options.
* @return string
*/
- public static function ordinal($value, array $options = [])
+ public static function ordinal($value, array $options = []): string
{
return static::formatter(['type' => NumberFormatter::ORDINAL] + $options)->format($value);
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Parser/MoFileParser.php b/app/vendor/cakephp/cakephp/src/I18n/Parser/MoFileParser.php
index c48471c55..7285ad224 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Parser/MoFileParser.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Parser/MoFileParser.php
@@ -1,4 +1,6 @@
_addMessage($messages, $item);
+ /** @psalm-suppress InvalidArrayOffset */
$item['ids']['singular'] = substr($line, 7, -1);
$stage = ['ids', 'singular'];
} elseif (substr($line, 0, 8) === 'msgstr "') {
@@ -103,17 +106,29 @@ public function parse($resource)
} elseif ($line[0] === '"') {
switch (count($stage)) {
case 2:
+ /**
+ * @psalm-suppress PossiblyUndefinedArrayOffset
+ * @psalm-suppress InvalidArrayOffset
+ * @psalm-suppress PossiblyNullArrayAccess
+ */
$item[$stage[0]][$stage[1]] .= substr($line, 1, -1);
break;
case 1:
+ /**
+ * @psalm-suppress PossiblyUndefinedArrayOffset
+ * @psalm-suppress PossiblyInvalidOperand
+ * @psalm-suppress PossiblyNullOperand
+ */
$item[$stage[0]] .= substr($line, 1, -1);
break;
}
} elseif (substr($line, 0, 14) === 'msgid_plural "') {
+ /** @psalm-suppress InvalidArrayOffset */
$item['ids']['plural'] = substr($line, 14, -1);
$stage = ['ids', 'plural'];
} elseif (substr($line, 0, 7) === 'msgstr[') {
+ /** @var int $size */
$size = strpos($line, ']');
$row = (int)substr($line, 7, 1);
$item['translated'][$row] = substr($line, $size + 3, -1);
@@ -134,21 +149,21 @@ public function parse($resource)
* @param array $item The current item being inspected
* @return void
*/
- protected function _addMessage(array &$messages, array $item)
+ protected function _addMessage(array &$messages, array $item): void
{
if (empty($item['ids']['singular']) && empty($item['ids']['plural'])) {
return;
}
$singular = stripcslashes($item['ids']['singular']);
- $context = isset($item['context']) ? $item['context'] : null;
+ $context = $item['context'] ?? null;
$translation = $item['translated'];
if (is_array($translation)) {
$translation = $translation[0];
}
- $translation = stripcslashes($translation);
+ $translation = stripcslashes((string)$translation);
if ($context !== null && !isset($messages[$singular]['_context'][$context])) {
$messages[$singular]['_context'][$context] = $translation;
diff --git a/app/vendor/cakephp/cakephp/src/I18n/PluralRules.php b/app/vendor/cakephp/cakephp/src/I18n/PluralRules.php
index 649058bdd..bad31ab85 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/PluralRules.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/PluralRules.php
@@ -1,4 +1,6 @@
now($date->getTimezone());
}
+ /** @psalm-suppress PossiblyNullArgument */
$diffInterval = $date->diff($other);
switch (true) {
- case ($diffInterval->y > 0):
+ case $diffInterval->y > 0:
$count = $diffInterval->y;
$message = __dn('cake', '{0} year', '{0} years', $count, $count);
break;
- case ($diffInterval->m > 0):
+ case $diffInterval->m > 0:
$count = $diffInterval->m;
$message = __dn('cake', '{0} month', '{0} months', $count, $count);
break;
- case ($diffInterval->d > 0):
+ case $diffInterval->d > 0:
$count = $diffInterval->d;
- if ($count >= ChronosInterface::DAYS_PER_WEEK) {
- $count = (int)($count / ChronosInterface::DAYS_PER_WEEK);
+ if ($count >= I18nDateTimeInterface::DAYS_PER_WEEK) {
+ $count = (int)($count / I18nDateTimeInterface::DAYS_PER_WEEK);
$message = __dn('cake', '{0} week', '{0} weeks', $count, $count);
} else {
$message = __dn('cake', '{0} day', '{0} days', $count, $count);
}
break;
- case ($diffInterval->h > 0):
+ case $diffInterval->h > 0:
$count = $diffInterval->h;
$message = __dn('cake', '{0} hour', '{0} hours', $count, $count);
break;
- case ($diffInterval->i > 0):
+ case $diffInterval->i > 0:
$count = $diffInterval->i;
$message = __dn('cake', '{0} minute', '{0} minutes', $count, $count);
break;
@@ -86,15 +92,15 @@ public function diffForHumans(ChronosInterface $date, ChronosInterface $other =
/**
* Format a into a relative timestring.
*
- * @param \DateTimeInterface $time The time instance to format.
+ * @param \Cake\I18n\I18nDateTimeInterface $time The time instance to format.
* @param array $options Array of options.
* @return string Relative time string.
* @see \Cake\I18n\Time::timeAgoInWords()
*/
- public function timeAgoInWords(DateTimeInterface $time, array $options = [])
+ public function timeAgoInWords(I18nDateTimeInterface $time, array $options = []): string
{
$options = $this->_options($options, FrozenTime::class);
- if ($options['timezone'] && $time instanceof ChronosInterface) {
+ if ($options['timezone']) {
$time = $time->timezone($options['timezone']);
}
@@ -119,7 +125,7 @@ public function timeAgoInWords(DateTimeInterface $time, array $options = [])
}
$diffData = $this->_diffData($futureTime, $pastTime, $backwards, $options);
- list($fNum, $fWord, $years, $months, $weeks, $days, $hours, $minutes, $seconds) = array_values($diffData);
+ [$fNum, $fWord, $years, $months, $weeks, $days, $hours, $minutes, $seconds] = array_values($diffData);
$relativeDate = [];
if ($fNum >= 1 && $years > 0) {
@@ -186,23 +192,41 @@ public function timeAgoInWords(DateTimeInterface $time, array $options = [])
* @param array $options An array of options.
* @return array An array of values.
*/
- protected function _diffData($futureTime, $pastTime, $backwards, $options)
+ protected function _diffData($futureTime, $pastTime, bool $backwards, $options): array
{
- $diff = (int)$futureTime - (int)$pastTime;
+ $futureTime = (int)$futureTime;
+ $pastTime = (int)$pastTime;
+ $diff = $futureTime - $pastTime;
// If more than a week, then take into account the length of months
if ($diff >= 604800) {
- list($future['H'], $future['i'], $future['s'], $future['d'], $future['m'], $future['Y']) = explode('/', date('H/i/s/d/m/Y', $futureTime));
-
- list($past['H'], $past['i'], $past['s'], $past['d'], $past['m'], $past['Y']) = explode('/', date('H/i/s/d/m/Y', $pastTime));
+ $future = [];
+ [
+ $future['H'],
+ $future['i'],
+ $future['s'],
+ $future['d'],
+ $future['m'],
+ $future['Y'],
+ ] = explode('/', date('H/i/s/d/m/Y', $futureTime));
+
+ $past = [];
+ [
+ $past['H'],
+ $past['i'],
+ $past['s'],
+ $past['d'],
+ $past['m'],
+ $past['Y'],
+ ] = explode('/', date('H/i/s/d/m/Y', $pastTime));
$weeks = $days = $hours = $minutes = $seconds = 0;
$years = (int)$future['Y'] - (int)$past['Y'];
- $months = (int)$future['m'] + ((12 * $years) - (int)$past['m']);
+ $months = (int)$future['m'] + (12 * $years) - (int)$past['m'];
if ($months >= 12) {
$years = floor($months / 12);
- $months -= ($years * 12);
+ $months -= $years * 12;
}
if ((int)$future['m'] < (int)$past['m'] && (int)$future['Y'] - (int)$past['Y'] === 1) {
$years--;
@@ -215,17 +239,17 @@ protected function _diffData($futureTime, $pastTime, $backwards, $options)
$daysInFutureMonth = (int)date('t', mktime(0, 0, 0, (int)$future['m'] - 1, 1, (int)$future['Y']));
if (!$backwards) {
- $days = ($daysInPastMonth - (int)$past['d']) + (int)$future['d'];
+ $days = $daysInPastMonth - (int)$past['d'] + (int)$future['d'];
} else {
- $days = ($daysInFutureMonth - (int)$past['d']) + (int)$future['d'];
+ $days = $daysInFutureMonth - (int)$past['d'] + (int)$future['d'];
}
- if ($future['m'] != $past['m']) {
+ if ($future['m'] !== $past['m']) {
$months--;
}
}
- if (!$months && $years >= 1 && $diff < ($years * 31536000)) {
+ if (!$months && $years >= 1 && $diff < $years * 31536000) {
$months = 11;
$years--;
}
@@ -237,19 +261,19 @@ protected function _diffData($futureTime, $pastTime, $backwards, $options)
if ($days >= 7) {
$weeks = floor($days / 7);
- $days -= ($weeks * 7);
+ $days -= $weeks * 7;
}
} else {
$years = $months = $weeks = 0;
$days = floor($diff / 86400);
- $diff -= ($days * 86400);
+ $diff -= $days * 86400;
$hours = floor($diff / 3600);
- $diff -= ($hours * 3600);
+ $diff -= $hours * 3600;
$minutes = floor($diff / 60);
- $diff -= ($minutes * 60);
+ $diff -= $minutes * 60;
$seconds = $diff;
}
@@ -268,23 +292,37 @@ protected function _diffData($futureTime, $pastTime, $backwards, $options)
$fWord = $options['accuracy']['minute'];
}
- $fNum = str_replace(['year', 'month', 'week', 'day', 'hour', 'minute', 'second'], [1, 2, 3, 4, 5, 6, 7], $fWord);
-
- return [$fNum, $fWord, $years, $months, $weeks, $days, $hours, $minutes, $seconds];
+ $fNum = str_replace(
+ ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'],
+ ['1', '2', '3', '4', '5', '6', '7'],
+ $fWord
+ );
+
+ return [
+ $fNum,
+ $fWord,
+ (int)$years,
+ (int)$months,
+ (int)$weeks,
+ (int)$days,
+ (int)$hours,
+ (int)$minutes,
+ (int)$seconds,
+ ];
}
/**
* Format a into a relative date string.
*
- * @param \DateTimeInterface $date The date to format.
+ * @param \Cake\I18n\I18nDateTimeInterface $date The date to format.
* @param array $options Array of options.
* @return string Relative date string.
* @see \Cake\I18n\Date::timeAgoInWords()
*/
- public function dateAgoInWords(DateTimeInterface $date, array $options = [])
+ public function dateAgoInWords(I18nDateTimeInterface $date, array $options = []): string
{
$options = $this->_options($options, FrozenDate::class);
- if ($options['timezone'] && $date instanceof ChronosInterface) {
+ if ($options['timezone']) {
$date = $date->timezone($options['timezone']);
}
@@ -309,7 +347,7 @@ public function dateAgoInWords(DateTimeInterface $date, array $options = [])
}
$diffData = $this->_diffData($futureTime, $pastTime, $backwards, $options);
- list($fNum, $fWord, $years, $months, $weeks, $days) = array_values($diffData);
+ [$fNum, $fWord, $years, $months, $weeks, $days] = array_values($diffData);
$relativeDate = [];
if ($fNum >= 1 && $years > 0) {
@@ -358,8 +396,9 @@ public function dateAgoInWords(DateTimeInterface $date, array $options = [])
* @param array $options The options provided by the user.
* @param string $class The class name to use for defaults.
* @return array Options with defaults applied.
+ * @psalm-param class-string<\Cake\I18n\FrozenDate>|class-string<\Cake\I18n\FrozenTime> $class
*/
- protected function _options($options, $class)
+ protected function _options(array $options, string $class): array
{
$options += [
'from' => $class::now(),
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Time.php b/app/vendor/cakephp/cakephp/src/I18n/Time.php
index e67b2c2e5..2705dbcdd 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Time.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Time.php
@@ -1,4 +1,6 @@
i18nFormat(static::$niceFormat, $timezone, $locale);
+ return (string)$this->i18nFormat(static::$niceFormat, $timezone, $locale);
}
/**
@@ -139,9 +159,9 @@ public function nice($timezone = null, $locale = null)
*
* @return bool
*/
- public function isThisWeek()
+ public function isThisWeek(): bool
{
- return static::now($this->getTimezone())->format('W o') == $this->format('W o');
+ return static::now($this->getTimezone())->format('W o') === $this->format('W o');
}
/**
@@ -149,9 +169,9 @@ public function isThisWeek()
*
* @return bool
*/
- public function isThisMonth()
+ public function isThisMonth(): bool
{
- return static::now($this->getTimezone())->format('m Y') == $this->format('m Y');
+ return static::now($this->getTimezone())->format('m Y') === $this->format('m Y');
}
/**
@@ -159,9 +179,9 @@ public function isThisMonth()
*
* @return bool
*/
- public function isThisYear()
+ public function isThisYear(): bool
{
- return static::now($this->getTimezone())->format('Y') == $this->format('Y');
+ return static::now($this->getTimezone())->format('Y') === $this->format('Y');
}
/**
@@ -170,7 +190,7 @@ public function isThisYear()
* @param bool $range Range.
* @return string[]|int 1, 2, 3, or 4 quarter of year, or array if $range true
*/
- public function toQuarter($range = false)
+ public function toQuarter(bool $range = false)
{
$quarter = (int)ceil((int)$this->format('m') / 3);
if ($range === false) {
@@ -185,9 +205,10 @@ public function toQuarter($range = false)
return [$year . '-04-01', $year . '-06-30'];
case 3:
return [$year . '-07-01', $year . '-09-30'];
- case 4:
- return [$year . '-10-01', $year . '-12-31'];
}
+
+ // 4th quarter
+ return [$year . '-10-01', $year . '-12-31'];
}
/**
@@ -195,7 +216,7 @@ public function toQuarter($range = false)
*
* @return string UNIX timestamp
*/
- public function toUnixString()
+ public function toUnixString(): string
{
return $this->format('U');
}
@@ -209,13 +230,13 @@ public function toUnixString()
* - `from` => another Time object representing the "now" time
* - `format` => a fall back format if the relative time is longer than the duration specified by end
* - `accuracy` => Specifies how accurate the date should be described (array)
- * - year => The format if years > 0 (default "day")
- * - month => The format if months > 0 (default "day")
- * - week => The format if weeks > 0 (default "day")
- * - day => The format if weeks > 0 (default "hour")
- * - hour => The format if hours > 0 (default "minute")
- * - minute => The format if minutes > 0 (default "minute")
- * - second => The format if seconds > 0 (default "second")
+ * - year => The format if years > 0 (default "day")
+ * - month => The format if months > 0 (default "day")
+ * - week => The format if weeks > 0 (default "day")
+ * - day => The format if weeks > 0 (default "hour")
+ * - hour => The format if hours > 0 (default "minute")
+ * - minute => The format if minutes > 0 (default "minute")
+ * - second => The format if seconds > 0 (default "second")
* - `end` => The end of relative time telling
* - `relativeString` => The `printf` compatible string when outputting relative time
* - `absoluteString` => The `printf` compatible string when outputting absolute time
@@ -237,9 +258,10 @@ public function toUnixString()
* @param array $options Array of options.
* @return string Relative time string.
*/
- public function timeAgoInWords(array $options = [])
+ public function timeAgoInWords(array $options = []): string
{
- return static::diffFormatter()->timeAgoInWords($this, $options);
+ /** @psalm-suppress UndefinedInterfaceMethod */
+ return static::getDiffFormatter()->timeAgoInWords($this, $options);
}
/**
@@ -257,7 +279,7 @@ public function timeAgoInWords(array $options = [])
* @return array List of timezone identifiers
* @since 2.2
*/
- public static function listTimezones($filter = null, $country = null, $options = [])
+ public static function listTimezones($filter = null, ?string $country = null, $options = []): array
{
if (is_bool($options)) {
$options = [
@@ -281,7 +303,7 @@ public static function listTimezones($filter = null, $country = null, $options =
if ($filter === null) {
$filter = DateTimeZone::ALL;
}
- $identifiers = DateTimeZone::listIdentifiers($filter, $country);
+ $identifiers = DateTimeZone::listIdentifiers($filter, (string)$country) ?: [];
if ($regex) {
foreach ($identifiers as $key => $tz) {
@@ -296,14 +318,14 @@ public static function listTimezones($filter = null, $country = null, $options =
$now = time();
$before = $options['before'];
$after = $options['after'];
- foreach ($identifiers as $key => $tz) {
- $abbr = null;
+ foreach ($identifiers as $tz) {
+ $abbr = '';
if ($options['abbr']) {
$dateTimeZone = new DateTimeZone($tz);
$trans = $dateTimeZone->getTransitions($now, $now);
$abbr = isset($trans[0]['abbr']) ?
$before . $trans[0]['abbr'] . $after :
- null;
+ '';
}
$item = explode('/', $tz, 2);
if (isset($item[1])) {
@@ -318,54 +340,4 @@ public static function listTimezones($filter = null, $country = null, $options =
return array_combine($identifiers, $identifiers);
}
-
- /**
- * Returns true this instance will happen within the specified interval
- *
- * This overridden method provides backwards compatible behavior for integers,
- * or strings with trailing spaces. This behavior is *deprecated* and will be
- * removed in future versions of CakePHP.
- *
- * @param string|int $timeInterval the numeric value with space then time type.
- * Example of valid types: 6 hours, 2 days, 1 minute.
- * @return bool
- */
- public function wasWithinLast($timeInterval)
- {
- $tmp = trim($timeInterval);
- if (is_numeric($tmp)) {
- deprecationWarning(
- 'Passing int/numeric string into Time::wasWithinLast() is deprecated. ' .
- 'Pass strings including interval eg. "6 days"'
- );
- $timeInterval = $tmp . ' days';
- }
-
- return parent::wasWithinLast($timeInterval);
- }
-
- /**
- * Returns true this instance happened within the specified interval
- *
- * This overridden method provides backwards compatible behavior for integers,
- * or strings with trailing spaces. This behavior is *deprecated* and will be
- * removed in future versions of CakePHP.
- *
- * @param string|int $timeInterval the numeric value with space then time type.
- * Example of valid types: 6 hours, 2 days, 1 minute.
- * @return bool
- */
- public function isWithinNext($timeInterval)
- {
- $tmp = trim($timeInterval);
- if (is_numeric($tmp)) {
- deprecationWarning(
- 'Passing int/numeric string into Time::isWithinNext() is deprecated. ' .
- 'Pass strings including interval eg. "6 days"'
- );
- $timeInterval = $tmp . ' days';
- }
-
- return parent::isWithinNext($timeInterval);
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Translator.php b/app/vendor/cakephp/cakephp/src/I18n/Translator.php
index 4c4751bca..50ecd85a5 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Translator.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Translator.php
@@ -1,4 +1,6 @@
getMessage(static::PLURAL_PREFIX . $key);
@@ -59,7 +61,7 @@ public function translate($key, array $tokensValues = [])
unset($tokensValues['_context']);
}
- if (!$tokensValues) {
+ if (empty($tokensValues)) {
// Fallback for plurals that were using the singular key
if (is_array($message)) {
return array_values($message + [''])[0];
@@ -75,17 +77,15 @@ public function translate($key, array $tokensValues = [])
// Resolve plural form.
if (is_array($message)) {
- $count = isset($tokensValues['_count']) ? (int)$tokensValues['_count'] : 0;
- $form = PluralRules::calculate($this->locale, $count);
- $message = isset($message[$form]) ? $message[$form] : (string)end($message);
+ $count = $tokensValues['_count'] ?? 0;
+ $form = PluralRules::calculate($this->locale, (int)$count);
+ $message = $message[$form] ?? (string)end($message);
}
if (strlen($message) === 0) {
$message = $key;
}
- unset($tokensValues['_count'], $tokensValues['_singular']);
-
return $this->formatter->format($this->locale, $message, $tokensValues);
}
@@ -93,13 +93,13 @@ public function translate($key, array $tokensValues = [])
* Resolve a message's context structure.
*
* @param string $key The message key being handled.
- * @param string|array $message The message content.
+ * @param array $message The message content.
* @param array $vars The variables containing the `_context` key.
* @return string|array
*/
- protected function resolveContext($key, $message, array $vars)
+ protected function resolveContext(string $key, array $message, array $vars)
{
- $context = isset($vars['_context']) ? $vars['_context'] : null;
+ $context = $vars['_context'] ?? null;
// No or missing context, fallback to the key/first message
if ($context === null) {
diff --git a/app/vendor/cakephp/cakephp/src/I18n/TranslatorFactory.php b/app/vendor/cakephp/cakephp/src/I18n/TranslatorFactory.php
index c34f9e2b0..29478392e 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/TranslatorFactory.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/TranslatorFactory.php
@@ -1,4 +1,6 @@
*/
protected $class = Translator::class;
@@ -48,12 +51,12 @@ public function newInstance(
$locale,
Package $package,
FormatterInterface $formatter,
- TranslatorInterface $fallback = null
+ ?TranslatorInterface $fallback = null
) {
$class = $this->class;
if ($fallback !== null && get_class($fallback) !== $class) {
throw new RuntimeException(sprintf(
- 'Translator fallback class %s does not match Cake\I18n\Translator, try clearing your _cake_core_ cache.',
+ 'Translator fallback class %s does not match Cake\I18n\Translator, try clearing your _cake_core_ cache',
get_class($fallback)
));
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/TranslatorRegistry.php b/app/vendor/cakephp/cakephp/src/I18n/TranslatorRegistry.php
index b773501a7..e00734528 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/TranslatorRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/TranslatorRegistry.php
@@ -1,4 +1,6 @@
_cacher = $cacher;
}
@@ -124,6 +127,7 @@ public function setCacher(CacheEngine $cacher)
* @return \Aura\Intl\TranslatorInterface|null A translator object.
* @throws \Aura\Intl\Exception If no translator with that name could be found
* for the given locale.
+ * @psalm-suppress ImplementedReturnTypeMismatch
*/
public function get($name, $locale = null)
{
@@ -139,15 +143,17 @@ public function get($name, $locale = null)
return $this->registry[$name][$locale];
}
- if (!$this->_cacher) {
+ if ($this->_cacher === null) {
return $this->registry[$name][$locale] = $this->_getTranslator($name, $locale);
}
- $key = "translations.$name.$locale";
- $translator = $this->_cacher->read($key);
+ // Cache keys cannot contain / if they go to file engine.
+ $keyName = str_replace('/', '.', $name);
+ $key = "translations.{$keyName}.{$locale}";
+ $translator = $this->_cacher->get($key);
if (!$translator || !$translator->getPackage()) {
$translator = $this->_getTranslator($name, $locale);
- $this->_cacher->write($key, $translator);
+ $this->_cacher->set($key, $translator);
}
return $this->registry[$name][$locale] = $translator;
@@ -157,11 +163,11 @@ public function get($name, $locale = null)
* Gets a translator from the registry by package for a locale.
*
* @param string $name The translator package to retrieve.
- * @param string|null $locale The locale to use; if empty, uses the default
+ * @param string $locale The locale to use; if empty, uses the default
* locale.
* @return \Aura\Intl\TranslatorInterface A translator object.
*/
- protected function _getTranslator($name, $locale)
+ protected function _getTranslator(string $name, string $locale): TranslatorInterface
{
try {
return parent::get($name, $locale);
@@ -186,7 +192,7 @@ protected function _getTranslator($name, $locale)
* @param callable $loader A callable object that should return a Package
* @return void
*/
- public function registerLoader($name, callable $loader)
+ public function registerLoader(string $name, callable $loader): void
{
$this->_loaders[$name] = $loader;
}
@@ -200,7 +206,7 @@ public function registerLoader($name, callable $loader)
* @param string|null $name The name of the formatter to use.
* @return string The name of the formatter.
*/
- public function defaultFormatter($name = null)
+ public function defaultFormatter(?string $name = null): string
{
if ($name === null) {
return $this->_defaultFormatter;
@@ -215,7 +221,7 @@ public function defaultFormatter($name = null)
* @param bool $enable flag to enable or disable fallback
* @return void
*/
- public function useFallback($enable = true)
+ public function useFallback(bool $enable = true): void
{
$this->_useFallback = $enable;
}
@@ -226,9 +232,9 @@ public function useFallback($enable = true)
*
* @param string $name The translation package name.
* @param string $locale The locale to create the translator for.
- * @return \Aura\Intl\Translator
+ * @return \Aura\Intl\TranslatorInterface|\Closure
*/
- protected function _fallbackLoader($name, $locale)
+ protected function _fallbackLoader(string $name, string $locale)
{
return $this->_loaders[$this->_fallbackLoader]($name, $locale);
}
@@ -236,9 +242,9 @@ protected function _fallbackLoader($name, $locale)
/**
* Returns a function that can be used as a loader for the registerLoaderMethod
*
- * @return callable
+ * @return \Closure
*/
- protected function _partialLoader()
+ protected function _partialLoader(): Closure
{
return function ($name, $locale) {
return $this->_fallbackLoader($name, $locale);
@@ -253,7 +259,7 @@ protected function _partialLoader()
* @param string $locale The locale that should be built the package for
* @return \Aura\Intl\TranslatorInterface A translator object.
*/
- protected function _getFromLoader($name, $locale)
+ protected function _getFromLoader(string $name, string $locale): TranslatorInterface
{
$loader = $this->_loaders[$name]($name, $locale);
$package = $loader;
@@ -278,7 +284,7 @@ protected function _getFromLoader($name, $locale)
* @param callable $loader invokable loader
* @return callable loader
*/
- public function setLoaderFallback($name, callable $loader)
+ public function setLoaderFallback(string $name, callable $loader): callable
{
$fallbackDomain = 'default';
if (!$this->_useFallback || $name === $fallbackDomain) {
diff --git a/app/vendor/cakephp/cakephp/src/I18n/composer.json b/app/vendor/cakephp/cakephp/src/I18n/composer.json
index 611e487ad..94976f05e 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/composer.json
+++ b/app/vendor/cakephp/cakephp/src/I18n/composer.json
@@ -28,10 +28,10 @@
"source": "https://github.com/cakephp/i18n"
},
"require": {
- "php": ">=5.6.0,<8.0.0",
+ "php": ">=7.2.0",
"ext-intl": "*",
- "cakephp/core": "^3.6.0",
- "cakephp/chronos": "^1.0.0",
+ "cakephp/core": "^4.0",
+ "cakephp/chronos": "^2.0.0",
"aura/intl": "^3.0.0"
},
"suggest": {
diff --git a/app/vendor/cakephp/cakephp/src/I18n/functions.php b/app/vendor/cakephp/cakephp/src/I18n/functions.php
index bbb6aeeda..5775595c9 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/functions.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/functions.php
@@ -1,4 +1,6 @@
content[] = $level . ' ' . $this->_format($message, $context);
+ }
+
+ /**
+ * Read the internal storage
+ *
+ * @return string[]
+ */
+ public function read(): array
+ {
+ return $this->content;
+ }
+
+ /**
+ * Reset internal storage.
+ *
+ * @return void
+ */
+ public function clear(): void
+ {
+ $this->content = [];
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Log/Engine/BaseLog.php b/app/vendor/cakephp/cakephp/src/Log/Engine/BaseLog.php
index 2ef6fcc3f..28f0a9146 100644
--- a/app/vendor/cakephp/cakephp/src/Log/Engine/BaseLog.php
+++ b/app/vendor/cakephp/cakephp/src/Log/Engine/BaseLog.php
@@ -1,4 +1,6 @@
_config['levels'];
}
@@ -79,34 +79,17 @@ public function scopes()
}
/**
- * Converts to string the provided data so it can be logged. The context
- * can optionally be used by log engines to interpolate variables
+ * Formats the message to be logged.
+ *
+ * The context can optionally be used by log engines to interpolate variables
* or add additional info to the logged message.
*
- * @param mixed $data The data to be converted to string and logged.
+ * @param string $message The message to be formatted.
* @param array $context Additional logging information for the message.
* @return string
*/
- protected function _format($data, array $context = [])
+ protected function _format(string $message, array $context = []): string
{
- if (is_string($data)) {
- return $data;
- }
-
- $isObject = is_object($data);
-
- if ($isObject && $data instanceof EntityInterface) {
- return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
- }
-
- if ($isObject && method_exists($data, '__toString')) {
- return (string)$data;
- }
-
- if ($isObject && $data instanceof JsonSerializable) {
- return json_encode($data, JSON_UNESCAPED_UNICODE);
- }
-
- return print_r($data, true);
+ return $message;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Log/Engine/ConsoleLog.php b/app/vendor/cakephp/cakephp/src/Log/Engine/ConsoleLog.php
index 6566df300..fbc7899b1 100644
--- a/app/vendor/cakephp/cakephp/src/Log/Engine/ConsoleLog.php
+++ b/app/vendor/cakephp/cakephp/src/Log/Engine/ConsoleLog.php
@@ -1,4 +1,6 @@
_format($message, $context);
$output = date('Y-m-d H:i:s') . ' ' . ucfirst($level) . ': ' . $message;
- return (bool)$this->_output->write(sprintf('<%s>%s%s>', $level, $output, $level));
+ $this->_output->write(sprintf('<%s>%s%s>', $level, $output, $level));
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Log/Engine/FileLog.php b/app/vendor/cakephp/cakephp/src/Log/Engine/FileLog.php
index e9114529d..e52fe7629 100644
--- a/app/vendor/cakephp/cakephp/src/Log/Engine/FileLog.php
+++ b/app/vendor/cakephp/cakephp/src/Log/Engine/FileLog.php
@@ -1,4 +1,6 @@
_config['path'])) {
- $this->_path = $this->_config['path'];
- }
- if (
- $this->_path !== null &&
- Configure::read('debug') &&
- !is_dir($this->_path)
- ) {
+ $this->_path = $this->getConfig('path', sys_get_temp_dir());
+ if (Configure::read('debug') && !is_dir($this->_path)) {
mkdir($this->_path, 0775, true);
}
@@ -112,13 +108,13 @@ public function __construct(array $config = [])
/**
* Implements writing to log files.
*
- * @param string $level The severity level of the message being written.
- * See Cake\Log\Log::$_levels for list of possible levels.
+ * @param mixed $level The severity level of the message being written.
* @param string $message The message you want to log.
* @param array $context Additional information about the logged message
- * @return bool success of write.
+ * @return void
+ * @see Cake\Log\Log::$_levels
*/
- public function log($level, $message, array $context = [])
+ public function log($level, $message, array $context = []): void
{
$message = $this->_format($message, $context);
$output = date('Y-m-d H:i:s') . ' ' . ucfirst($level) . ': ' . $message . "\n";
@@ -130,11 +126,13 @@ public function log($level, $message, array $context = [])
$pathname = $this->_path . $filename;
$mask = $this->_config['mask'];
if (!$mask) {
- return file_put_contents($pathname, $output, FILE_APPEND);
+ file_put_contents($pathname, $output, FILE_APPEND);
+
+ return;
}
$exists = file_exists($pathname);
- $result = file_put_contents($pathname, $output, FILE_APPEND);
+ file_put_contents($pathname, $output, FILE_APPEND);
static $selfError = false;
if (!$selfError && !$exists && !chmod($pathname, (int)$mask)) {
@@ -145,8 +143,6 @@ public function log($level, $message, array $context = [])
), E_USER_WARNING);
$selfError = false;
}
-
- return $result;
}
/**
@@ -155,7 +151,7 @@ public function log($level, $message, array $context = [])
* @param string $level The level of log.
* @return string File name
*/
- protected function _getFilename($level)
+ protected function _getFilename(string $level): string
{
$debugTypes = ['notice', 'info', 'debug'];
@@ -163,7 +159,7 @@ protected function _getFilename($level)
$filename = $this->_file;
} elseif ($level === 'error' || $level === 'warning') {
$filename = 'error.log';
- } elseif (in_array($level, $debugTypes)) {
+ } elseif (in_array($level, $debugTypes, true)) {
$filename = 'debug.log';
} else {
$filename = $level . '.log';
@@ -180,7 +176,7 @@ protected function _getFilename($level)
* @return bool|null True if rotated successfully or false in case of error.
* Null if file doesn't need to be rotated.
*/
- protected function _rotateFile($filename)
+ protected function _rotateFile(string $filename): ?bool
{
$filePath = $this->_path . $filename;
clearstatcache(true, $filePath);
diff --git a/app/vendor/cakephp/cakephp/src/Log/Engine/SyslogLog.php b/app/vendor/cakephp/cakephp/src/Log/Engine/SyslogLog.php
index efbeb0f82..2fc469e20 100644
--- a/app/vendor/cakephp/cakephp/src/Log/Engine/SyslogLog.php
+++ b/app/vendor/cakephp/cakephp/src/Log/Engine/SyslogLog.php
@@ -1,4 +1,6 @@
_open) {
$config = $this->_config;
@@ -108,8 +111,6 @@ public function log($level, $message, array $context = [])
$message = sprintf($this->_config['format'], $level, $message);
$this->_write($priority, $message);
}
-
- return true;
}
/**
@@ -121,7 +122,7 @@ public function log($level, $message, array $context = [])
* @param int $facility the stream or facility to log to
* @return void
*/
- protected function _open($ident, $options, $facility)
+ protected function _open(string $ident, int $options, int $facility): void
{
openlog($ident, $options, $facility);
}
@@ -134,7 +135,7 @@ protected function _open($ident, $options, $facility)
* @param string $message Message to log.
* @return bool
*/
- protected function _write($priority, $message)
+ protected function _write(int $priority, string $message): bool
{
return syslog($priority, $message);
}
diff --git a/app/vendor/cakephp/cakephp/src/Log/LICENSE.txt b/app/vendor/cakephp/cakephp/src/Log/LICENSE.txt
index 0c4b7932c..0b3b94303 100644
--- a/app/vendor/cakephp/cakephp/src/Log/LICENSE.txt
+++ b/app/vendor/cakephp/cakephp/src/Log/LICENSE.txt
@@ -1,7 +1,7 @@
The MIT License (MIT)
CakePHP(tm) : The Rapid Development PHP Framework (https://cakephp.org)
-Copyright (c) 2005-2016, Cake Software Foundation, Inc. (https://cakefoundation.org)
+Copyright (c) 2005-2019, Cake Software Foundation, Inc. (https://cakefoundation.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/vendor/cakephp/cakephp/src/Log/Log.php b/app/vendor/cakephp/cakephp/src/Log/Log.php
index 61997446a..1d102c305 100644
--- a/app/vendor/cakephp/cakephp/src/Log/Log.php
+++ b/app/vendor/cakephp/cakephp/src/Log/Log.php
@@ -1,4 +1,6 @@
*/
protected static $_dsnClassMap = [
- 'console' => 'Cake\Log\Engine\ConsoleLog',
- 'file' => 'Cake\Log\Engine\FileLog',
- 'syslog' => 'Cake\Log\Engine\SyslogLog',
+ 'console' => Engine\ConsoleLog::class,
+ 'file' => Engine\FileLog::class,
+ 'syslog' => Engine\SyslogLog::class,
];
/**
@@ -128,7 +132,7 @@ class Log
/**
* LogEngineRegistry class
*
- * @var \Cake\Log\LogEngineRegistry|null
+ * @var \Cake\Log\LogEngineRegistry
*/
protected static $_registry;
@@ -170,7 +174,7 @@ class Log
*
* @return void
*/
- protected static function _init()
+ protected static function _init(): void
{
if (empty(static::$_registry)) {
static::$_registry = new LogEngineRegistry();
@@ -187,14 +191,14 @@ protected static function _init()
*
* @return void
*/
- protected static function _loadConfig()
+ protected static function _loadConfig(): void
{
foreach (static::$_config as $name => $properties) {
if (isset($properties['engine'])) {
$properties['className'] = $properties['engine'];
}
- if (!static::$_registry->has($name)) {
- static::$_registry->load($name, $properties);
+ if (!static::$_registry->has((string)$name)) {
+ static::$_registry->load((string)$name, $properties);
}
}
}
@@ -209,9 +213,11 @@ protected static function _loadConfig()
*
* @return void
*/
- public static function reset()
+ public static function reset(): void
{
- static::$_registry = null;
+ if (!empty(static::$_registry)) {
+ static::$_registry->reset();
+ }
static::$_config = [];
static::$_dirtyConfig = true;
}
@@ -222,9 +228,9 @@ public static function reset()
* Call this method to obtain current
* level configuration.
*
- * @return string[] active log levels
+ * @return string[] Active log levels
*/
- public static function levels()
+ public static function levels(): array
{
return static::$_levels;
}
@@ -269,7 +275,7 @@ public static function levels()
* @return void
* @throws \BadMethodCallException When trying to modify an existing config.
*/
- public static function setConfig($key, $config = null)
+ public static function setConfig($key, $config = null): void
{
static::_setConfig($key, $config);
static::$_dirtyConfig = true;
@@ -279,16 +285,16 @@ public static function setConfig($key, $config = null)
* Get a logging engine.
*
* @param string $name Key name of a configured adapter to get.
- * @return \Cake\Log\Engine\BaseLog|false Instance of BaseLog or false if not found
+ * @return \Psr\Log\LoggerInterface|null Instance of LoggerInterface or false if not found
*/
- public static function engine($name)
+ public static function engine(string $name): ?LoggerInterface
{
static::_init();
if (static::$_registry->{$name}) {
return static::$_registry->{$name};
}
- return false;
+ return null;
}
/**
@@ -336,7 +342,7 @@ public static function engine($name)
*
* @param int|string $level The severity level of the message being written.
* The value must be an integer or string matching a known level.
- * @param mixed $message Message content to log
+ * @param string $message Message content to log
* @param string|array $context Additional data to be used for logging the message.
* The special `scope` key can be passed to be used for further filtering of the
* log engines to be used. If a string or a numerically index array is passed, it
@@ -345,15 +351,16 @@ public static function engine($name)
* @return bool Success
* @throws \InvalidArgumentException If invalid level is passed.
*/
- public static function write($level, $message, $context = [])
+ public static function write($level, string $message, $context = []): bool
{
static::_init();
- if (is_int($level) && in_array($level, static::$_levelMap)) {
- $level = array_search($level, static::$_levelMap);
+ if (is_int($level) && in_array($level, static::$_levelMap, true)) {
+ $level = array_search($level, static::$_levelMap, true);
}
- if (!in_array($level, static::$_levels)) {
- throw new InvalidArgumentException(sprintf('Invalid log level "%s"', $level));
+ if (!in_array($level, static::$_levels, true)) {
+ /** @psalm-suppress PossiblyFalseArgument */
+ throw new InvalidArgumentException(sprintf('Invalid log level `%s`', $level));
}
$logged = false;
@@ -375,7 +382,7 @@ public static function write($level, $message, $context = [])
$scopes = [];
}
- $correctLevel = empty($levels) || in_array($level, $levels);
+ $correctLevel = empty($levels) || in_array($level, $levels, true);
$inScope = $scopes === false && empty($context['scope']) || $scopes === [] ||
is_array($scopes) && array_intersect((array)$context['scope'], $scopes);
@@ -399,7 +406,7 @@ public static function write($level, $message, $context = [])
* See Cake\Log\Log::setConfig() for more information on logging scopes.
* @return bool Success
*/
- public static function emergency($message, $context = [])
+ public static function emergency(string $message, $context = []): bool
{
return static::write(__FUNCTION__, $message, $context);
}
@@ -415,7 +422,7 @@ public static function emergency($message, $context = [])
* See Cake\Log\Log::setConfig() for more information on logging scopes.
* @return bool Success
*/
- public static function alert($message, $context = [])
+ public static function alert(string $message, $context = []): bool
{
return static::write(__FUNCTION__, $message, $context);
}
@@ -431,7 +438,7 @@ public static function alert($message, $context = [])
* See Cake\Log\Log::setConfig() for more information on logging scopes.
* @return bool Success
*/
- public static function critical($message, $context = [])
+ public static function critical(string $message, $context = []): bool
{
return static::write(__FUNCTION__, $message, $context);
}
@@ -447,7 +454,7 @@ public static function critical($message, $context = [])
* See Cake\Log\Log::setConfig() for more information on logging scopes.
* @return bool Success
*/
- public static function error($message, $context = [])
+ public static function error(string $message, $context = []): bool
{
return static::write(__FUNCTION__, $message, $context);
}
@@ -463,7 +470,7 @@ public static function error($message, $context = [])
* See Cake\Log\Log::setConfig() for more information on logging scopes.
* @return bool Success
*/
- public static function warning($message, $context = [])
+ public static function warning(string $message, $context = []): bool
{
return static::write(__FUNCTION__, $message, $context);
}
@@ -479,7 +486,7 @@ public static function warning($message, $context = [])
* See Cake\Log\Log::setConfig() for more information on logging scopes.
* @return bool Success
*/
- public static function notice($message, $context = [])
+ public static function notice(string $message, $context = []): bool
{
return static::write(__FUNCTION__, $message, $context);
}
@@ -495,7 +502,7 @@ public static function notice($message, $context = [])
* See Cake\Log\Log::setConfig() for more information on logging scopes.
* @return bool Success
*/
- public static function debug($message, $context = [])
+ public static function debug(string $message, $context = []): bool
{
return static::write(__FUNCTION__, $message, $context);
}
@@ -511,7 +518,7 @@ public static function debug($message, $context = [])
* See Cake\Log\Log::setConfig() for more information on logging scopes.
* @return bool Success
*/
- public static function info($message, $context = [])
+ public static function info(string $message, $context = []): bool
{
return static::write(__FUNCTION__, $message, $context);
}
diff --git a/app/vendor/cakephp/cakephp/src/Log/LogEngineRegistry.php b/app/vendor/cakephp/cakephp/src/Log/LogEngineRegistry.php
index 48202f018..e90b4b634 100644
--- a/app/vendor/cakephp/cakephp/src/Log/LogEngineRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/Log/LogEngineRegistry.php
@@ -1,4 +1,6 @@
*/
class LogEngineRegistry extends ObjectRegistry
{
@@ -30,14 +34,11 @@ class LogEngineRegistry extends ObjectRegistry
* Part of the template method for Cake\Core\ObjectRegistry::load()
*
* @param string $class Partial classname to resolve.
- * @return string|false Either the correct classname or false.
+ * @return string|null Either the correct class name or null.
+ * @psalm-return class-string|null
*/
- protected function _resolveClassName($class)
+ protected function _resolveClassName(string $class): ?string
{
- if (is_object($class)) {
- return $class;
- }
-
return App::className($class, 'Log/Engine', 'Log');
}
@@ -51,7 +52,7 @@ protected function _resolveClassName($class)
* @return void
* @throws \RuntimeException
*/
- protected function _throwMissingClassError($class, $plugin)
+ protected function _throwMissingClassError(string $class, ?string $plugin): void
{
throw new RuntimeException(sprintf('Could not load class %s', $class));
}
@@ -67,7 +68,7 @@ protected function _throwMissingClassError($class, $plugin)
* @return \Psr\Log\LoggerInterface The constructed logger class.
* @throws \RuntimeException when an object doesn't implement the correct interface.
*/
- protected function _create($class, $alias, $settings)
+ protected function _create($class, string $alias, array $settings): LoggerInterface
{
if (is_callable($class)) {
$class = $class($alias);
@@ -78,6 +79,7 @@ protected function _create($class, $alias, $settings)
}
if (!isset($instance)) {
+ /** @psalm-suppress UndefinedClass */
$instance = new $class($settings);
}
@@ -85,9 +87,11 @@ protected function _create($class, $alias, $settings)
return $instance;
}
- throw new RuntimeException(
- 'Loggers must implement Psr\Log\LoggerInterface.'
- );
+ throw new RuntimeException(sprintf(
+ 'Loggers must implement %s. Found `%s` instance instead.',
+ LoggerInterface::class,
+ getTypeName($instance)
+ ));
}
/**
@@ -96,7 +100,7 @@ protected function _create($class, $alias, $settings)
* @param string $name The logger name.
* @return $this
*/
- public function unload($name)
+ public function unload(string $name)
{
unset($this->_loaded[$name]);
diff --git a/app/vendor/cakephp/cakephp/src/Log/LogTrait.php b/app/vendor/cakephp/cakephp/src/Log/LogTrait.php
index 0aac978f6..e87b061d8 100644
--- a/app/vendor/cakephp/cakephp/src/Log/LogTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Log/LogTrait.php
@@ -1,4 +1,6 @@
'Cake\Log\Engine\SyslogLog',
+ 'className' => \Cake\Log\Engine\SyslogLog::class,
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
]);
```
@@ -80,4 +80,4 @@ Log::warning('this gets written only to payments.log', ['scope' => ['payments']]
## Documentation
-Please make sure you check the [official documentation](https://book.cakephp.org/3/en/core-libraries/logging.html)
+Please make sure you check the [official documentation](https://book.cakephp.org/4/en/core-libraries/logging.html)
diff --git a/app/vendor/cakephp/cakephp/src/Log/composer.json b/app/vendor/cakephp/cakephp/src/Log/composer.json
index eeb2dacc3..0d43640be 100644
--- a/app/vendor/cakephp/cakephp/src/Log/composer.json
+++ b/app/vendor/cakephp/cakephp/src/Log/composer.json
@@ -23,10 +23,13 @@
"source": "https://github.com/cakephp/log"
},
"require": {
- "php": ">=5.6.0,<8.0.0",
- "cakephp/core": "^3.6.0",
+ "php": ">=7.2.0",
+ "cakephp/core": "^4.0",
"psr/log": "^1.0.0"
},
+ "provide": {
+ "psr/log-implementation": "^1.0.0"
+ },
"autoload": {
"psr-4": {
"Cake\\Log\\": "."
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/AbstractTransport.php b/app/vendor/cakephp/cakephp/src/Mailer/AbstractTransport.php
index 7fca94e49..772e0c05c 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/AbstractTransport.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/AbstractTransport.php
@@ -1,4 +1,6 @@
setConfig($config);
}
/**
- * Help to convert headers in string
+ * Check that at least one destination header is set.
*
- * @param array $headers Headers in format key => value
- * @param string $eol End of line string.
- * @return string
+ * @param \Cake\Mailer\Message $message Message instance.
+ * @return void
+ * @throws \Cake\Core\Exception\Exception If at least one of to, cc or bcc is not specified.
*/
- protected function _headersToString($headers, $eol = "\r\n")
+ protected function checkRecipient(Message $message): void
{
- $out = '';
- foreach ($headers as $key => $value) {
- if ($value === false || $value === null || $value === '') {
- continue;
- }
-
- foreach ((array)$value as $val) {
- $out .= $key . ': ' . $val . $eol;
- }
+ if (
+ $message->getTo() === []
+ && $message->getCc() === []
+ && $message->getBcc() === []
+ ) {
+ throw new Exception(
+ 'You must specify at least one recipient.'
+ . ' Use one of `setTo`, `setCc` or `setBcc` to define a recipient.'
+ );
}
- if (!empty($out)) {
- $out = substr($out, 0, -1 * strlen($eol));
- }
-
- return $out;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Email.php b/app/vendor/cakephp/cakephp/src/Mailer/Email.php
index 59f1e0d2a..a22cb19e1 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Email.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Email.php
@@ -1,4 +1,6 @@
*/
- protected $_returnPath = [];
+ protected $messageClass = Message::class;
/**
- * Carbon Copy
+ * Message instance.
*
- * List of email's that should receive a copy of the email.
- * The Recipient WILL be able to see this list
- *
- * @var array
+ * @var \Cake\Mailer\Message
*/
- protected $_cc = [];
+ protected $message;
/**
- * Blind Carbon Copy
- *
- * List of email's that should receive a copy of the email.
- * The Recipient WILL NOT be able to see this list
+ * Constructor
*
- * @var array
+ * @param array|string|null $config Array of configs, or string to load configs from app.php
*/
- protected $_bcc = [];
+ public function __construct($config = null)
+ {
+ $this->message = new $this->messageClass();
- /**
- * Message ID
- *
- * @var bool|string
- */
- protected $_messageId = true;
+ if ($config === null) {
+ $config = Mailer::getConfig('default');
+ }
- /**
- * Domain for messageId generation.
- * Needs to be manually set for CLI mailing as env('HTTP_HOST') is empty
- *
- * @var string
- */
- protected $_domain;
+ if ($config) {
+ $this->setProfile($config);
+ }
+ }
/**
- * The subject of the email
+ * Clone Renderer instance when email object is cloned.
*
- * @var string
+ * @return void
*/
- protected $_subject = '';
+ public function __clone()
+ {
+ if ($this->renderer) {
+ $this->renderer = clone $this->renderer;
+ }
- /**
- * Associative array of a user defined headers
- * Keys will be prefixed 'X-' as per RFC2822 Section 4.7.5
- *
- * @var array
- */
- protected $_headers = [];
+ if ($this->message !== null) {
+ $this->message = clone $this->message;
+ }
+ }
/**
- * Text message
+ * Magic method to forward method class to Email instance.
*
- * @var string
+ * @param string $method Method name.
+ * @param array $args Method arguments
+ * @return $this|mixed
*/
- protected $_textMessage = '';
+ public function __call(string $method, array $args)
+ {
+ $result = $this->message->$method(...$args);
- /**
- * Html message
- *
- * @var string
- */
- protected $_htmlMessage = '';
+ if (strpos($method, 'get') === 0) {
+ return $result;
+ }
- /**
- * Final message to send
- *
- * @var array
- */
- protected $_message = [];
+ $getters = ['message'];
+ if (in_array($method, $getters, true)) {
+ return $result;
+ }
- /**
- * Available formats to be sent.
- *
- * @var array
- */
- protected $_emailFormatAvailable = ['text', 'html', 'both'];
+ return $this;
+ }
/**
- * What format should the email be sent in
+ * Get message instance.
*
- * @var string
+ * @return \Cake\Mailer\Message
*/
- protected $_emailFormat = 'text';
+ public function getMessage(): Message
+ {
+ return $this->message;
+ }
/**
- * The transport instance to use for sending mail.
+ * Sets view class for render.
*
- * @var \Cake\Mailer\AbstractTransport|null
+ * @param string $viewClass View class name.
+ * @return $this
*/
- protected $_transport;
+ public function setViewRenderer(string $viewClass)
+ {
+ $this->getRenderer()->viewBuilder()->setClassName($viewClass);
- /**
- * Charset the email body is sent in
- *
- * @var string
- */
- public $charset = 'utf-8';
+ return $this;
+ }
/**
- * Charset the email header is sent in
- * If null, the $charset property will be used as default
+ * Gets view class for render.
*
- * @var string|null
+ * @return string
+ * @psalm-suppress InvalidNullableReturnType
*/
- public $headerCharset;
+ public function getViewRenderer(): string
+ {
+ /** @psalm-suppress NullableReturnStatement */
+ return $this->getRenderer()->viewBuilder()->getClassName();
+ }
/**
- * The email transfer encoding used.
- * If null, the $charset property is used for determined the transfer encoding.
+ * Sets variables to be set on render.
*
- * @var string|null
+ * @param array $viewVars Variables to set for view.
+ * @return $this
*/
- protected $transferEncoding;
+ public function setViewVars(array $viewVars)
+ {
+ $this->getRenderer()->viewBuilder()->setVars($viewVars);
- /**
- * Available encoding to be set for transfer.
- *
- * @var array
- */
- protected $_transferEncodingAvailable = [
- '7bit',
- '8bit',
- 'base64',
- 'binary',
- 'quoted-printable',
- ];
+ return $this;
+ }
/**
- * The application wide charset, used to encode headers and body
+ * Gets variables to be set on render.
*
- * @var string|null
+ * @return array
*/
- protected $_appCharset;
+ public function getViewVars(): array
+ {
+ return $this->getRenderer()->viewBuilder()->getVars();
+ }
/**
- * List of files that should be attached to the email.
- *
- * Only absolute paths
+ * Sets the transport.
*
- * @var array
- */
- protected $_attachments = [];
-
- /**
- * If set, boundary to use for multipart mime messages
+ * When setting the transport you can either use the name
+ * of a configured transport or supply a constructed transport.
*
- * @var string|null
+ * @param string|\Cake\Mailer\AbstractTransport $name Either the name of a configured
+ * transport, or a transport instance.
+ * @return $this
+ * @throws \LogicException When the chosen transport lacks a send method.
+ * @throws \InvalidArgumentException When $name is neither a string nor an object.
*/
- protected $_boundary;
+ public function setTransport($name)
+ {
+ if (is_string($name)) {
+ $transport = TransportFactory::get($name);
+ } elseif (is_object($name)) {
+ $transport = $name;
+ } else {
+ throw new InvalidArgumentException(sprintf(
+ 'The value passed for the "$name" argument must be either a string, or an object, %s given.',
+ gettype($name)
+ ));
+ }
+ if (!method_exists($transport, 'send')) {
+ throw new LogicException(sprintf('The "%s" do not have send method.', get_class($transport)));
+ }
- /**
- * Contains the optional priority of the email.
- *
- * @var int|null
- */
- protected $_priority;
+ $this->_transport = $transport;
- /**
- * An array mapping url schemes to fully qualified Transport class names.
- * Unused.
- *
- * @var string[]
- * @deprecated 3.7.0 This property is unused and will be removed in 4.0.0.
- */
- protected static $_dsnClassMap = [];
+ return $this;
+ }
/**
- * A copy of the configuration profile for this
- * instance. This copy can be modified with Email::profile().
+ * Gets the transport.
*
- * @var array
+ * @return \Cake\Mailer\AbstractTransport|null
*/
- protected $_profile = [];
+ public function getTransport(): ?AbstractTransport
+ {
+ return $this->_transport;
+ }
/**
- * 8Bit character sets
+ * Get generated message (used by transport classes)
*
- * @var array
+ * @param string|null $type Use MESSAGE_* constants or null to return the full message as array
+ * @return string|array String if type is given, array if type is null
*/
- protected $_charset8bit = ['UTF-8', 'SHIFT_JIS'];
+ public function message(?string $type = null)
+ {
+ if ($type === null) {
+ return $this->message->getBody();
+ }
- /**
- * Define Content-Type charset name
- *
- * @var array
- */
- protected $_contentTypeCharset = [
- 'ISO-2022-JP-MS' => 'ISO-2022-JP',
- ];
+ $method = 'getBody' . ucfirst($type);
- /**
- * Regex for email validation
- *
- * If null, filter_var() will be used. Use the emailPattern() method
- * to set a custom pattern.'
- *
- * @var string
- */
- protected $_emailPattern = self::EMAIL_PATTERN;
+ return $this->message->$method();
+ }
/**
- * Constructor
+ * Sets the configuration profile to use for this instance.
*
- * @param array|string|null $config Array of configs, or string to load configs from app.php
+ * @param string|array $config String with configuration name, or
+ * an array with config.
+ * @return $this
*/
- public function __construct($config = null)
+ public function setProfile($config)
{
- $this->_appCharset = Configure::read('App.encoding');
- if ($this->_appCharset !== null) {
- $this->charset = $this->_appCharset;
+ if (is_string($config)) {
+ $name = $config;
+ $config = Mailer::getConfig($name);
+ if (empty($config)) {
+ throw new InvalidArgumentException(sprintf('Unknown email configuration "%s".', $name));
+ }
+ unset($name);
}
- $this->_domain = preg_replace('/\:\d+$/', '', env('HTTP_HOST'));
- if (empty($this->_domain)) {
- $this->_domain = php_uname('n');
+
+ $this->_profile = array_merge($this->_profile, $config);
+
+ $simpleMethods = [
+ 'transport',
+ ];
+ foreach ($simpleMethods as $method) {
+ if (isset($config[$method])) {
+ $this->{'set' . ucfirst($method)}($config[$method]);
+ unset($config[$method]);
+ }
}
- $this->viewBuilder()
- ->setClassName('Cake\View\View')
- ->setTemplate('')
- ->setLayout('default')
- ->setHelpers(['Html']);
+ $viewBuilderMethods = [
+ 'template', 'layout', 'theme',
+ ];
+ foreach ($viewBuilderMethods as $method) {
+ if (array_key_exists($method, $config)) {
+ $this->getRenderer()->viewBuilder()->{'set' . ucfirst($method)}($config[$method]);
+ unset($config[$method]);
+ }
+ }
- if ($config === null) {
- $config = static::getConfig('default');
+ if (array_key_exists('helpers', $config)) {
+ $this->getRenderer()->viewBuilder()->setHelpers($config['helpers'], false);
+ unset($config['helpers']);
}
- if ($config) {
- $this->setProfile($config);
+ if (array_key_exists('viewRenderer', $config)) {
+ $this->getRenderer()->viewBuilder()->setClassName($config['viewRenderer']);
+ unset($config['viewRenderer']);
}
- if (empty($this->headerCharset)) {
- $this->headerCharset = $this->charset;
+ if (array_key_exists('viewVars', $config)) {
+ $this->getRenderer()->viewBuilder()->setVars($config['viewVars']);
+ unset($config['viewVars']);
}
- }
- /**
- * Clone ViewBuilder instance when email object is cloned.
- *
- * @return void
- */
- public function __clone()
- {
- $this->_viewBuilder = clone $this->viewBuilder();
- }
+ $this->message->setConfig($config);
- /**
- * Sets "from" address.
- *
- * @param string|array $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- * @throws \InvalidArgumentException
- */
- public function setFrom($email, $name = null)
- {
- return $this->_setEmailSingle('_from', $email, $name, 'From requires only 1 email address.');
+ return $this;
}
/**
- * Gets "from" address.
+ * Gets the configuration profile to use for this instance.
*
* @return array
*/
- public function getFrom()
+ public function getProfile(): array
{
- return $this->_from;
+ return $this->_profile;
}
/**
- * From
+ * Send an email using the specified content, template and layout
*
- * @deprecated 3.4.0 Use setFrom()/getFrom() instead.
- * @param string|array|null $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return array|$this
- * @throws \InvalidArgumentException
+ * @param string|array|null $content String with message or array with messages
+ * @return array
+ * @throws \BadMethodCallException
+ * @psalm-return array{headers: string, message: string}
*/
- public function from($email = null, $name = null)
+ public function send($content = null): array
{
- deprecationWarning('Email::from() is deprecated. Use Email::setFrom() or Email::getFrom() instead.');
- if ($email === null) {
- return $this->getFrom();
+ if (is_array($content)) {
+ $content = implode("\n", $content) . "\n";
+ }
+
+ $this->render($content);
+
+ $transport = $this->getTransport();
+ if (!$transport) {
+ $msg = 'Cannot send email, transport was not defined. Did you call transport() or define ' .
+ ' a transport in the set profile?';
+ throw new BadMethodCallException($msg);
}
+ $contents = $transport->send($this->message);
+ $this->_logDelivery($contents);
- return $this->setFrom($email, $name);
+ return $contents;
}
/**
- * Sets the "sender" address. See rfc link below for full explanation.
+ * Render email.
*
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- * @throws \InvalidArgumentException
- * @link https://tools.ietf.org/html/rfc2822.html#section-3.6.2
+ * @param string|array|null $content Content array or string
+ * @return void
*/
- public function setSender($email, $name = null)
+ public function render($content = null): void
{
- return $this->_setEmailSingle('_sender', $email, $name, 'Sender requires only 1 email address.');
+ if (is_array($content)) {
+ $content = implode("\n", $content) . "\n";
+ }
+
+ $this->message->setBody(
+ $this->getRenderer()->render(
+ (string)$content,
+ $this->message->getBodyTypes()
+ )
+ );
}
/**
- * Gets the "sender" address. See rfc link below for full explanation.
+ * Get view builder.
*
- * @return array
- * @link https://tools.ietf.org/html/rfc2822.html#section-3.6.2
+ * @return \Cake\View\ViewBuilder
*/
- public function getSender()
+ public function viewBuilder(): ViewBuilder
{
- return $this->_sender;
+ return $this->getRenderer()->viewBuilder();
}
/**
- * Sender
+ * Get email renderer.
*
- * @deprecated 3.4.0 Use setSender()/getSender() instead.
- * @param string|array|null $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return array|$this
- * @throws \InvalidArgumentException
+ * @return \Cake\Mailer\Renderer
*/
- public function sender($email = null, $name = null)
+ public function getRenderer(): Renderer
{
- deprecationWarning('Email::sender() is deprecated. Use Email::setSender() or Email::getSender() instead.');
-
- if ($email === null) {
- return $this->getSender();
+ if ($this->renderer === null) {
+ $this->renderer = new Renderer();
}
- return $this->setSender($email, $name);
+ return $this->renderer;
}
/**
- * Sets "Reply-To" address.
+ * Set email renderer.
*
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
+ * @param \Cake\Mailer\Renderer $renderer Render instance.
* @return $this
- * @throws \InvalidArgumentException
*/
- public function setReplyTo($email, $name = null)
+ public function setRenderer(Renderer $renderer)
{
- return $this->_setEmail('_replyTo', $email, $name);
+ $this->renderer = $renderer;
+
+ return $this;
}
/**
- * Gets "Reply-To" address.
- *
- * @return array
- */
- public function getReplyTo()
- {
- return $this->_replyTo;
- }
-
- /**
- * Reply-To
- *
- * @deprecated 3.4.0 Use setReplyTo()/getReplyTo() instead.
- * @param string|array|null $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return array|$this
- * @throws \InvalidArgumentException
- */
- public function replyTo($email = null, $name = null)
- {
- deprecationWarning('Email::replyTo() is deprecated. Use Email::setReplyTo() or Email::getReplyTo() instead.');
-
- if ($email === null) {
- return $this->getReplyTo();
- }
-
- return $this->setReplyTo($email, $name);
- }
-
- /**
- * Sets Read Receipt (Disposition-Notification-To header).
- *
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- * @throws \InvalidArgumentException
- */
- public function setReadReceipt($email, $name = null)
- {
- return $this->_setEmailSingle('_readReceipt', $email, $name, 'Disposition-Notification-To requires only 1 email address.');
- }
-
- /**
- * Gets Read Receipt (Disposition-Notification-To header).
- *
- * @return array
- */
- public function getReadReceipt()
- {
- return $this->_readReceipt;
- }
-
- /**
- * Read Receipt (Disposition-Notification-To header)
- *
- * @deprecated 3.4.0 Use setReadReceipt()/getReadReceipt() instead.
- * @param string|array|null $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return array|$this
- * @throws \InvalidArgumentException
- */
- public function readReceipt($email = null, $name = null)
- {
- deprecationWarning('Email::readReceipt() is deprecated. Use Email::setReadReceipt() or Email::getReadReceipt() instead.');
-
- if ($email === null) {
- return $this->getReadReceipt();
- }
-
- return $this->setReadReceipt($email, $name);
- }
-
- /**
- * Return Path
- *
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- * @throws \InvalidArgumentException
- */
- public function setReturnPath($email, $name = null)
- {
- return $this->_setEmailSingle('_returnPath', $email, $name, 'Return-Path requires only 1 email address.');
- }
-
- /**
- * Gets return path.
- *
- * @return array
- */
- public function getReturnPath()
- {
- return $this->_returnPath;
- }
-
- /**
- * Return Path
- *
- * @deprecated 3.4.0 Use setReturnPath()/getReturnPath() instead.
- * @param string|array|null $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return array|$this
- * @throws \InvalidArgumentException
- */
- public function returnPath($email = null, $name = null)
- {
- deprecationWarning('Email::returnPath() is deprecated. Use Email::setReturnPath() or Email::getReturnPath() instead.');
- if ($email === null) {
- return $this->getReturnPath();
- }
-
- return $this->setReturnPath($email, $name);
- }
-
- /**
- * Sets "to" address.
- *
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- */
- public function setTo($email, $name = null)
- {
- return $this->_setEmail('_to', $email, $name);
- }
-
- /**
- * Gets "to" address
- *
- * @return array
- */
- public function getTo()
- {
- return $this->_to;
- }
-
- /**
- * To
- *
- * @deprecated 3.4.0 Use setTo()/getTo() instead.
- * @param string|array|null $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return array|$this
- */
- public function to($email = null, $name = null)
- {
- deprecationWarning('Email::to() is deprecated. Use Email::setTo() or Email::getTo() instead.');
-
- if ($email === null) {
- return $this->getTo();
- }
-
- return $this->setTo($email, $name);
- }
-
- /**
- * Add To
- *
- * @param string|array $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- */
- public function addTo($email, $name = null)
- {
- return $this->_addEmail('_to', $email, $name);
- }
-
- /**
- * Sets "cc" address.
- *
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- */
- public function setCc($email, $name = null)
- {
- return $this->_setEmail('_cc', $email, $name);
- }
-
- /**
- * Gets "cc" address.
- *
- * @return array
- */
- public function getCc()
- {
- return $this->_cc;
- }
-
- /**
- * Cc
- *
- * @deprecated 3.4.0 Use setCc()/getCc() instead.
- * @param string|array|null $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return array|$this
- */
- public function cc($email = null, $name = null)
- {
- deprecationWarning('Email::cc() is deprecated. Use Email::setCc() or Email::getCc() instead.');
-
- if ($email === null) {
- return $this->getCc();
- }
-
- return $this->setCc($email, $name);
- }
-
- /**
- * Add Cc
- *
- * @param string|array $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- */
- public function addCc($email, $name = null)
- {
- return $this->_addEmail('_cc', $email, $name);
- }
-
- /**
- * Sets "bcc" address.
- *
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- */
- public function setBcc($email, $name = null)
- {
- return $this->_setEmail('_bcc', $email, $name);
- }
-
- /**
- * Gets "bcc" address.
- *
- * @return array
- */
- public function getBcc()
- {
- return $this->_bcc;
- }
-
- /**
- * Bcc
- *
- * @deprecated 3.4.0 Use setBcc()/getBcc() instead.
- * @param string|array|null $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return array|$this
- */
- public function bcc($email = null, $name = null)
- {
- deprecationWarning('Email::bcc() is deprecated. Use Email::setBcc() or Email::getBcc() instead.');
-
- if ($email === null) {
- return $this->getBcc();
- }
-
- return $this->setBcc($email, $name);
- }
-
- /**
- * Add Bcc
- *
- * @param string|array $email Null to get, String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string|null $name Name
- * @return $this
- */
- public function addBcc($email, $name = null)
- {
- return $this->_addEmail('_bcc', $email, $name);
- }
-
- /**
- * Charset setter.
- *
- * @param string|null $charset Character set.
- * @return $this
- */
- public function setCharset($charset)
- {
- $this->charset = $charset;
- if (!$this->headerCharset) {
- $this->headerCharset = $charset;
- }
-
- return $this;
- }
-
- /**
- * Charset getter.
- *
- * @return string Charset
- */
- public function getCharset()
- {
- return $this->charset;
- }
-
- /**
- * Charset setter/getter
- *
- * @deprecated 3.4.0 Use setCharset()/getCharset() instead.
- * @param string|null $charset Character set.
- * @return string Charset
- */
- public function charset($charset = null)
- {
- deprecationWarning('Email::charset() is deprecated. Use Email::setCharset() or Email::getCharset() instead.');
-
- if ($charset === null) {
- return $this->getCharset();
- }
- $this->setCharset($charset);
-
- return $this->charset;
- }
-
- /**
- * HeaderCharset setter.
- *
- * @param string|null $charset Character set.
- * @return $this
- */
- public function setHeaderCharset($charset)
- {
- $this->headerCharset = $charset;
-
- return $this;
- }
-
- /**
- * HeaderCharset getter.
- *
- * @return string Charset
- */
- public function getHeaderCharset()
- {
- return $this->headerCharset ? $this->headerCharset : $this->charset;
- }
-
- /**
- * HeaderCharset setter/getter
- *
- * @deprecated 3.4.0 Use setHeaderCharset()/getHeaderCharset() instead.
- * @param string|null $charset Character set.
- * @return string Charset
- */
- public function headerCharset($charset = null)
- {
- deprecationWarning('Email::headerCharset() is deprecated. Use Email::setHeaderCharset() or Email::getHeaderCharset() instead.');
-
- if ($charset === null) {
- return $this->getHeaderCharset();
- }
-
- $this->setHeaderCharset($charset);
-
- return $this->headerCharset;
- }
-
- /**
- * TransferEncoding setter.
- *
- * @param string|null $encoding Encoding set.
- * @return $this
- */
- public function setTransferEncoding($encoding)
- {
- $encoding = strtolower($encoding);
- if (!in_array($encoding, $this->_transferEncodingAvailable)) {
- throw new InvalidArgumentException(
- sprintf(
- 'Transfer encoding not available. Can be : %s.',
- implode(', ', $this->_transferEncodingAvailable)
- )
- );
- }
- $this->transferEncoding = $encoding;
-
- return $this;
- }
-
- /**
- * TransferEncoding getter.
- *
- * @return string|null Encoding
- */
- public function getTransferEncoding()
- {
- return $this->transferEncoding;
- }
-
- /**
- * EmailPattern setter/getter
- *
- * @param string|null $regex The pattern to use for email address validation,
- * null to unset the pattern and make use of filter_var() instead.
- * @return $this
- */
- public function setEmailPattern($regex)
- {
- $this->_emailPattern = $regex;
-
- return $this;
- }
-
- /**
- * EmailPattern setter/getter
- *
- * @return string
- */
- public function getEmailPattern()
- {
- return $this->_emailPattern;
- }
-
- /**
- * EmailPattern setter/getter
- *
- * @deprecated 3.4.0 Use setEmailPattern()/getEmailPattern() instead.
- * @param string|false|null $regex The pattern to use for email address validation,
- * null to unset the pattern and make use of filter_var() instead, false or
- * nothing to return the current value
- * @return string|$this
- */
- public function emailPattern($regex = false)
- {
- deprecationWarning('Email::emailPattern() is deprecated. Use Email::setEmailPattern() or Email::getEmailPattern() instead.');
-
- if ($regex === false) {
- return $this->getEmailPattern();
- }
-
- return $this->setEmailPattern($regex);
- }
-
- /**
- * Set email
- *
- * @param string $varName Property name
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string $name Name
- * @return $this
- * @throws \InvalidArgumentException
- */
- protected function _setEmail($varName, $email, $name)
- {
- if (!is_array($email)) {
- $this->_validateEmail($email, $varName);
- if ($name === null) {
- $name = $email;
- }
- $this->{$varName} = [$email => $name];
-
- return $this;
- }
- $list = [];
- foreach ($email as $key => $value) {
- if (is_int($key)) {
- $key = $value;
- }
- $this->_validateEmail($key, $varName);
- $list[$key] = $value;
- }
- $this->{$varName} = $list;
-
- return $this;
- }
-
- /**
- * Validate email address
- *
- * @param string $email Email address to validate
- * @param string $context Which property was set
- * @return void
- * @throws \InvalidArgumentException If email address does not validate
- */
- protected function _validateEmail($email, $context)
- {
- if ($this->_emailPattern === null) {
- if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
- return;
- }
- } elseif (preg_match($this->_emailPattern, $email)) {
- return;
- }
-
- $context = ltrim($context, '_');
- if ($email == '') {
- throw new InvalidArgumentException(sprintf('The email set for "%s" is empty.', $context));
- }
- throw new InvalidArgumentException(sprintf('Invalid email set for "%s". You passed "%s".', $context, $email));
- }
-
- /**
- * Set only 1 email
- *
- * @param string $varName Property name
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string $name Name
- * @param string $throwMessage Exception message
- * @return $this
- * @throws \InvalidArgumentException
- */
- protected function _setEmailSingle($varName, $email, $name, $throwMessage)
- {
- if ($email === []) {
- $this->{$varName} = $email;
-
- return $this;
- }
-
- $current = $this->{$varName};
- $this->_setEmail($varName, $email, $name);
- if (count($this->{$varName}) !== 1) {
- $this->{$varName} = $current;
- throw new InvalidArgumentException($throwMessage);
- }
-
- return $this;
- }
-
- /**
- * Add email
- *
- * @param string $varName Property name
- * @param string|array $email String with email,
- * Array with email as key, name as value or email as value (without name)
- * @param string $name Name
- * @return $this
- * @throws \InvalidArgumentException
- */
- protected function _addEmail($varName, $email, $name)
- {
- if (!is_array($email)) {
- $this->_validateEmail($email, $varName);
- if ($name === null) {
- $name = $email;
- }
- $this->{$varName}[$email] = $name;
-
- return $this;
- }
- $list = [];
- foreach ($email as $key => $value) {
- if (is_int($key)) {
- $key = $value;
- }
- $this->_validateEmail($key, $varName);
- $list[$key] = $value;
- }
- $this->{$varName} = array_merge($this->{$varName}, $list);
-
- return $this;
- }
-
- /**
- * Sets subject.
- *
- * @param string $subject Subject string.
- * @return $this
- */
- public function setSubject($subject)
- {
- $this->_subject = $this->_encode((string)$subject);
-
- return $this;
- }
-
- /**
- * Gets subject.
- *
- * @return string
- */
- public function getSubject()
- {
- return $this->_subject;
- }
-
- /**
- * Get/Set Subject.
- *
- * @deprecated 3.4.0 Use setSubject()/getSubject() instead.
- * @param string|null $subject Subject string.
- * @return string|$this
- */
- public function subject($subject = null)
- {
- deprecationWarning('Email::subject() is deprecated. Use Email::setSubject() or Email::getSubject() instead.');
-
- if ($subject === null) {
- return $this->getSubject();
- }
-
- return $this->setSubject($subject);
- }
-
- /**
- * Get original subject without encoding
- *
- * @return string Original subject
- */
- public function getOriginalSubject()
- {
- return $this->_decode($this->_subject);
- }
-
- /**
- * Sets headers for the message
- *
- * @param array $headers Associative array containing headers to be set.
- * @return $this
- */
- public function setHeaders(array $headers)
- {
- $this->_headers = $headers;
-
- return $this;
- }
-
- /**
- * Add header for the message
- *
- * @param array $headers Headers to set.
- * @return $this
- */
- public function addHeaders(array $headers)
- {
- $this->_headers = Hash::merge($this->_headers, $headers);
-
- return $this;
- }
-
- /**
- * Get list of headers
- *
- * ### Includes:
- *
- * - `from`
- * - `replyTo`
- * - `readReceipt`
- * - `returnPath`
- * - `to`
- * - `cc`
- * - `bcc`
- * - `subject`
- *
- * @param array $include List of headers.
- * @return array
- */
- public function getHeaders(array $include = [])
- {
- if ($include == array_values($include)) {
- $include = array_fill_keys($include, true);
- }
- $defaults = array_fill_keys(
- [
- 'from', 'sender', 'replyTo', 'readReceipt', 'returnPath',
- 'to', 'cc', 'bcc', 'subject'],
- false
- );
- $include += $defaults;
-
- $headers = [];
- $relation = [
- 'from' => 'From',
- 'replyTo' => 'Reply-To',
- 'readReceipt' => 'Disposition-Notification-To',
- 'returnPath' => 'Return-Path',
- 'to' => 'To',
- 'cc' => 'Cc',
- 'bcc' => 'Bcc',
- ];
- $headerMultipleEmails = ['to', 'cc', 'bcc', 'replyTo'];
- foreach ($relation as $key => $header) {
- $var = '_' . $key;
- if (!$include[$key]) {
- continue;
- }
- if (in_array($key, $headerMultipleEmails, true)) {
- $headers[$header] = implode(', ', $this->_formatAddress($this->{$var}));
- } else {
- $headers[$header] = current($this->_formatAddress($this->{$var}));
- }
- }
- if ($include['sender']) {
- if (key($this->_sender) === key($this->_from)) {
- $headers['Sender'] = '';
- } else {
- $headers['Sender'] = current($this->_formatAddress($this->_sender));
- }
- }
-
- $headers += $this->_headers;
- if (!isset($headers['Date'])) {
- $headers['Date'] = date(DATE_RFC2822);
- }
- if ($this->_messageId !== false) {
- if ($this->_messageId === true) {
- $this->_messageId = '<' . str_replace('-', '', Text::uuid()) . '@' . $this->_domain . '>';
- }
-
- $headers['Message-ID'] = $this->_messageId;
- }
-
- if ($this->_priority) {
- $headers['X-Priority'] = $this->_priority;
- }
-
- if ($include['subject']) {
- $headers['Subject'] = $this->_subject;
- }
-
- $headers['MIME-Version'] = '1.0';
- if ($this->_attachments) {
- $headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->_boundary . '"';
- } elseif ($this->_emailFormat === 'both') {
- $headers['Content-Type'] = 'multipart/alternative; boundary="' . $this->_boundary . '"';
- } elseif ($this->_emailFormat === 'text') {
- $headers['Content-Type'] = 'text/plain; charset=' . $this->_getContentTypeCharset();
- } elseif ($this->_emailFormat === 'html') {
- $headers['Content-Type'] = 'text/html; charset=' . $this->_getContentTypeCharset();
- }
- $headers['Content-Transfer-Encoding'] = $this->_getContentTransferEncoding();
-
- return $headers;
- }
-
- /**
- * Format addresses
- *
- * If the address contains non alphanumeric/whitespace characters, it will
- * be quoted as characters like `:` and `,` are known to cause issues
- * in address header fields.
- *
- * @param array $address Addresses to format.
- * @return array
- */
- protected function _formatAddress($address)
- {
- $return = [];
- foreach ($address as $email => $alias) {
- if ($email === $alias) {
- $return[] = $email;
- } else {
- $encoded = $this->_encode($alias);
- if ($encoded === $alias && preg_match('/[^a-z0-9 ]/i', $encoded)) {
- $encoded = '"' . str_replace('"', '\"', $encoded) . '"';
- }
- $return[] = sprintf('%s <%s>', $encoded, $email);
- }
- }
-
- return $return;
- }
-
- /**
- * Sets template.
- *
- * @param string|null $template Template name or null to not use.
- * @return $this
- * @deprecated 3.7.0 Use $email->viewBuilder()->setTemplate() instead.
- */
- public function setTemplate($template)
- {
- deprecationWarning(
- 'Email::setTemplate() is deprecated. Use $email->viewBuilder()->setTemplate() instead.'
- );
-
- $this->viewBuilder()->setTemplate($template ?: '');
-
- return $this;
- }
-
- /**
- * Gets template.
- *
- * @return string
- * @deprecated 3.7.0 Use $email->viewBuilder()->getTemplate() instead.
- */
- public function getTemplate()
- {
- deprecationWarning(
- 'Email::getTemplate() is deprecated. Use $email->viewBuilder()->getTemplate() instead.'
- );
-
- return $this->viewBuilder()->getTemplate();
- }
-
- /**
- * Sets layout.
- *
- * @param string|null $layout Layout name or null to not use
- * @return $this
- * @deprecated 3.7.0 Use $email->viewBuilder()->setLayout() instead.
- */
- public function setLayout($layout)
- {
- deprecationWarning(
- 'Email::setLayout() is deprecated. Use $email->viewBuilder()->setLayout() instead.'
- );
-
- $this->viewBuilder()->setLayout($layout ?: false);
-
- return $this;
- }
-
- /**
- * Gets layout.
- *
- * @deprecated 3.7.0 Use $email->viewBuilder()->getLayout() instead.
- * @return string
- */
- public function getLayout()
- {
- deprecationWarning(
- 'Email::getLayout() is deprecated. Use $email->viewBuilder()->getLayout() instead.'
- );
-
- return $this->viewBuilder()->getLayout();
- }
-
- /**
- * Template and layout
- *
- * @deprecated 3.4.0 Use setTemplate()/getTemplate() and setLayout()/getLayout() instead.
- * @param bool|string $template Template name or null to not use
- * @param bool|string $layout Layout name or null to not use
- * @return array|$this
- */
- public function template($template = false, $layout = false)
- {
- deprecationWarning(
- 'Email::template() is deprecated. ' .
- 'Use $email->viewBuilder()->getTemplate()/setTemplate() ' .
- 'and $email->viewBuilder()->getLayout()/setLayout() instead.'
- );
-
- if ($template === false) {
- return [
- 'template' => $this->viewBuilder()->getTemplate(),
- 'layout' => $this->viewBuilder()->getLayout(),
- ];
- }
- $this->viewBuilder()->setTemplate($template);
- if ($layout !== false) {
- $this->viewBuilder()->setLayout($layout);
- }
-
- return $this;
- }
-
- /**
- * Sets view class for render.
- *
- * @param string $viewClass View class name.
- * @return $this
- */
- public function setViewRenderer($viewClass)
- {
- $this->viewBuilder()->setClassName($viewClass);
-
- return $this;
- }
-
- /**
- * Gets view class for render.
- *
- * @return string
- */
- public function getViewRenderer()
- {
- return $this->viewBuilder()->getClassName();
- }
-
- /**
- * View class for render
- *
- * @deprecated 3.4.0 Use setViewRenderer()/getViewRenderer() instead.
- * @param string|null $viewClass View class name.
- * @return string|$this
- */
- public function viewRender($viewClass = null)
- {
- deprecationWarning('Email::viewRender() is deprecated. Use Email::setViewRenderer() or Email::getViewRenderer() instead.');
-
- if ($viewClass === null) {
- return $this->getViewRenderer();
- }
- $this->setViewRenderer($viewClass);
-
- return $this;
- }
-
- /**
- * Sets variables to be set on render.
- *
- * @param array $viewVars Variables to set for view.
- * @return $this
- */
- public function setViewVars($viewVars)
- {
- $this->set((array)$viewVars);
-
- return $this;
- }
-
- /**
- * Gets variables to be set on render.
- *
- * @return array
- */
- public function getViewVars()
- {
- return $this->viewVars;
- }
-
- /**
- * Variables to be set on render
- *
- * @deprecated 3.4.0 Use setViewVars()/getViewVars() instead.
- * @param array|null $viewVars Variables to set for view.
- * @return array|$this
- */
- public function viewVars($viewVars = null)
- {
- deprecationWarning('Email::viewVars() is deprecated. Use Email::setViewVars() or Email::getViewVars() instead.');
-
- if ($viewVars === null) {
- return $this->getViewVars();
- }
-
- return $this->setViewVars($viewVars);
- }
-
- /**
- * Sets theme to use when rendering.
- *
- * @param string $theme Theme name.
- * @return $this
- * @deprecated 3.7.0 Use $email->viewBuilder()->setTheme() instead.
- */
- public function setTheme($theme)
- {
- deprecationWarning(
- 'Email::setTheme() is deprecated. Use $email->viewBuilder()->setTheme() instead.'
- );
-
- $this->viewBuilder()->setTheme($theme);
-
- return $this;
- }
-
- /**
- * Gets theme to use when rendering.
- *
- * @return string
- * @deprecated 3.7.0 Use $email->viewBuilder()->getTheme() instead.
- */
- public function getTheme()
- {
- deprecationWarning(
- 'Email::getTheme() is deprecated. Use $email->viewBuilder()->getTheme() instead.'
- );
-
- return $this->viewBuilder()->getTheme();
- }
-
- /**
- * Theme to use when rendering
- *
- * @deprecated 3.4.0 Use setTheme()/getTheme() instead.
- * @param string|null $theme Theme name.
- * @return string|$this
- */
- public function theme($theme = null)
- {
- deprecationWarning(
- 'Email::theme() is deprecated. Use $email->viewBuilder()->getTheme()/setTheme() instead.'
- );
-
- if ($theme === null) {
- return $this->viewBuilder()->getTheme();
- }
-
- $this->viewBuilder()->setTheme($theme);
-
- return $this;
- }
-
- /**
- * Sets helpers to be used when rendering.
- *
- * @param array $helpers Helpers list.
- * @return $this
- * @deprecated 3.7.0 Use $email->viewBuilder()->setHelpers() instead.
- */
- public function setHelpers(array $helpers)
- {
- deprecationWarning(
- 'Email::setHelpers() is deprecated. Use $email->viewBuilder()->setHelpers() instead.'
- );
-
- $this->viewBuilder()->setHelpers($helpers, false);
-
- return $this;
- }
-
- /**
- * Gets helpers to be used when rendering.
- *
- * @return array
- * @deprecated 3.7.0 Use $email->viewBuilder()->getHelpers() instead.
- */
- public function getHelpers()
- {
- deprecationWarning(
- 'Email::getHelpers() is deprecated. Use $email->viewBuilder()->getHelpers() instead.'
- );
-
- return $this->viewBuilder()->getHelpers();
- }
-
- /**
- * Helpers to be used in render
- *
- * @deprecated 3.4.0 Use setHelpers()/getHelpers() instead.
- * @param array|null $helpers Helpers list.
- * @return array|$this
- */
- public function helpers($helpers = null)
- {
- deprecationWarning(
- 'Email::helpers() is deprecated. Use $email->viewBuilder()->getHelpers()/setHelpers() instead.'
- );
-
- if ($helpers === null) {
- return $this->viewBuilder()->getHelpers();
- }
-
- $this->viewBuilder()->setHelpers((array)$helpers);
-
- return $this;
- }
-
- /**
- * Sets email format.
- *
- * @param string $format Formatting string.
- * @return $this
- * @throws \InvalidArgumentException
- */
- public function setEmailFormat($format)
- {
- if (!in_array($format, $this->_emailFormatAvailable)) {
- throw new InvalidArgumentException('Format not available.');
- }
- $this->_emailFormat = $format;
-
- return $this;
- }
-
- /**
- * Gets email format.
- *
- * @return string
- */
- public function getEmailFormat()
- {
- return $this->_emailFormat;
- }
-
- /**
- * Email format
- *
- * @deprecated 3.4.0 Use setEmailFormat()/getEmailFormat() instead.
- * @param string|null $format Formatting string.
- * @return string|$this
- * @throws \InvalidArgumentException
- */
- public function emailFormat($format = null)
- {
- deprecationWarning('Email::emailFormat() is deprecated. Use Email::setEmailFormat() or Email::getEmailFormat() instead.');
-
- if ($format === null) {
- return $this->getEmailFormat();
- }
-
- return $this->setEmailFormat($format);
- }
-
- /**
- * Sets the transport.
- *
- * When setting the transport you can either use the name
- * of a configured transport or supply a constructed transport.
- *
- * @param string|\Cake\Mailer\AbstractTransport $name Either the name of a configured
- * transport, or a transport instance.
- * @return $this
- * @throws \LogicException When the chosen transport lacks a send method.
- * @throws \InvalidArgumentException When $name is neither a string nor an object.
- */
- public function setTransport($name)
- {
- if (is_string($name)) {
- $transport = TransportFactory::get($name);
- } elseif (is_object($name)) {
- $transport = $name;
- } else {
- throw new InvalidArgumentException(
- sprintf('The value passed for the "$name" argument must be either a string, or an object, %s given.', gettype($name))
- );
- }
- if (!method_exists($transport, 'send')) {
- throw new LogicException(sprintf('The "%s" do not have send method.', get_class($transport)));
- }
-
- $this->_transport = $transport;
-
- return $this;
- }
-
- /**
- * Gets the transport.
- *
- * @return \Cake\Mailer\AbstractTransport
- */
- public function getTransport()
- {
- return $this->_transport;
- }
-
- /**
- * Get/set the transport.
- *
- * When setting the transport you can either use the name
- * of a configured transport or supply a constructed transport.
- *
- * @deprecated 3.4.0 Use setTransport()/getTransport() instead.
- * @param string|\Cake\Mailer\AbstractTransport|null $name Either the name of a configured
- * transport, or a transport instance.
- * @return \Cake\Mailer\AbstractTransport|$this
- * @throws \LogicException When the chosen transport lacks a send method.
- * @throws \InvalidArgumentException When $name is neither a string nor an object.
- */
- public function transport($name = null)
- {
- deprecationWarning('Email::transport() is deprecated. Use Email::setTransport() or Email::getTransport() instead.');
-
- if ($name === null) {
- return $this->getTransport();
- }
-
- return $this->setTransport($name);
- }
-
- /**
- * Sets message ID.
- *
- * @param bool|string $message True to generate a new Message-ID, False to ignore (not send in email), String to set as Message-ID.
- * @return $this
- * @throws \InvalidArgumentException
- */
- public function setMessageId($message)
- {
- if (is_bool($message)) {
- $this->_messageId = $message;
- } else {
- if (!preg_match('/^\<.+@.+\>$/', $message)) {
- throw new InvalidArgumentException('Invalid format to Message-ID. The text should be something like ""');
- }
- $this->_messageId = $message;
- }
-
- return $this;
- }
-
- /**
- * Gets message ID.
- *
- * @return bool|string
- */
- public function getMessageId()
- {
- return $this->_messageId;
- }
-
- /**
- * Message-ID
- *
- * @deprecated 3.4.0 Use setMessageId()/getMessageId() instead.
- * @param bool|string|null $message True to generate a new Message-ID, False to ignore (not send in email), String to set as Message-ID
- * @return bool|string|$this
- * @throws \InvalidArgumentException
- */
- public function messageId($message = null)
- {
- deprecationWarning('Email::messageId() is deprecated. Use Email::setMessageId() or Email::getMessageId() instead.');
-
- if ($message === null) {
- return $this->getMessageId();
- }
-
- return $this->setMessageId($message);
- }
-
- /**
- * Sets domain.
- *
- * Domain as top level (the part after @).
- *
- * @param string $domain Manually set the domain for CLI mailing.
- * @return $this
- */
- public function setDomain($domain)
- {
- $this->_domain = $domain;
-
- return $this;
- }
-
- /**
- * Gets domain.
- *
- * @return string
- */
- public function getDomain()
- {
- return $this->_domain;
- }
-
- /**
- * Domain as top level (the part after @)
- *
- * @deprecated 3.4.0 Use setDomain()/getDomain() instead.
- * @param string|null $domain Manually set the domain for CLI mailing
- * @return string|$this
- */
- public function domain($domain = null)
- {
- deprecationWarning('Email::domain() is deprecated. Use Email::setDomain() or Email::getDomain() instead.');
-
- if ($domain === null) {
- return $this->getDomain();
- }
-
- return $this->setDomain($domain);
- }
-
- /**
- * Add attachments to the email message
- *
- * Attachments can be defined in a few forms depending on how much control you need:
- *
- * Attach a single file:
- *
- * ```
- * $email->setAttachments('path/to/file');
- * ```
- *
- * Attach a file with a different filename:
- *
- * ```
- * $email->setAttachments(['custom_name.txt' => 'path/to/file.txt']);
- * ```
- *
- * Attach a file and specify additional properties:
- *
- * ```
- * $email->setAttachments(['custom_name.png' => [
- * 'file' => 'path/to/file',
- * 'mimetype' => 'image/png',
- * 'contentId' => 'abc123',
- * 'contentDisposition' => false
- * ]
- * ]);
- * ```
- *
- * Attach a file from string and specify additional properties:
- *
- * ```
- * $email->setAttachments(['custom_name.png' => [
- * 'data' => file_get_contents('path/to/file'),
- * 'mimetype' => 'image/png'
- * ]
- * ]);
- * ```
- *
- * The `contentId` key allows you to specify an inline attachment. In your email text, you
- * can use `
` to display the image inline.
- *
- * The `contentDisposition` key allows you to disable the `Content-Disposition` header, this can improve
- * attachment compatibility with outlook email clients.
- *
- * @param string|array $attachments String with the filename or array with filenames
- * @return $this
- * @throws \InvalidArgumentException
- */
- public function setAttachments($attachments)
- {
- $attach = [];
- foreach ((array)$attachments as $name => $fileInfo) {
- if (!is_array($fileInfo)) {
- $fileInfo = ['file' => $fileInfo];
- }
- if (!isset($fileInfo['file'])) {
- if (!isset($fileInfo['data'])) {
- throw new InvalidArgumentException('No file or data specified.');
- }
- if (is_int($name)) {
- throw new InvalidArgumentException('No filename specified.');
- }
- $fileInfo['data'] = chunk_split(base64_encode($fileInfo['data']), 76, "\r\n");
- } else {
- $fileName = $fileInfo['file'];
- $fileInfo['file'] = realpath($fileInfo['file']);
- if ($fileInfo['file'] === false || !file_exists($fileInfo['file'])) {
- throw new InvalidArgumentException(sprintf('File not found: "%s"', $fileName));
- }
- if (is_int($name)) {
- $name = basename($fileInfo['file']);
- }
- }
- if (!isset($fileInfo['mimetype']) && isset($fileInfo['file']) && function_exists('mime_content_type')) {
- $fileInfo['mimetype'] = mime_content_type($fileInfo['file']);
- }
- if (!isset($fileInfo['mimetype'])) {
- $fileInfo['mimetype'] = 'application/octet-stream';
- }
- $attach[$name] = $fileInfo;
- }
- $this->_attachments = $attach;
-
- return $this;
- }
-
- /**
- * Gets attachments to the email message.
- *
- * @return array Array of attachments.
- */
- public function getAttachments()
- {
- return $this->_attachments;
- }
-
- /**
- * Add attachments to the email message
- *
- * Attachments can be defined in a few forms depending on how much control you need:
- *
- * Attach a single file:
- *
- * ```
- * $email->setAttachments('path/to/file');
- * ```
- *
- * Attach a file with a different filename:
- *
- * ```
- * $email->setAttachments(['custom_name.txt' => 'path/to/file.txt']);
- * ```
- *
- * Attach a file and specify additional properties:
- *
- * ```
- * $email->setAttachments(['custom_name.png' => [
- * 'file' => 'path/to/file',
- * 'mimetype' => 'image/png',
- * 'contentId' => 'abc123',
- * 'contentDisposition' => false
- * ]
- * ]);
- * ```
- *
- * Attach a file from string and specify additional properties:
- *
- * ```
- * $email->setAttachments(['custom_name.png' => [
- * 'data' => file_get_contents('path/to/file'),
- * 'mimetype' => 'image/png'
- * ]
- * ]);
- * ```
- *
- * The `contentId` key allows you to specify an inline attachment. In your email text, you
- * can use `
` to display the image inline.
- *
- * The `contentDisposition` key allows you to disable the `Content-Disposition` header, this can improve
- * attachment compatibility with outlook email clients.
- *
- * @deprecated 3.4.0 Use setAttachments()/getAttachments() instead.
- * @param string|array|null $attachments String with the filename or array with filenames
- * @return array|$this Either the array of attachments when getting or $this when setting.
- * @throws \InvalidArgumentException
- */
- public function attachments($attachments = null)
- {
- deprecationWarning('Email::attachments() is deprecated. Use Email::setAttachments() or Email::getAttachments() instead.');
-
- if ($attachments === null) {
- return $this->getAttachments();
- }
-
- return $this->setAttachments($attachments);
- }
-
- /**
- * Add attachments
- *
- * @param string|array $attachments String with the filename or array with filenames
- * @return $this
- * @throws \InvalidArgumentException
- * @see \Cake\Mailer\Email::attachments()
- */
- public function addAttachments($attachments)
- {
- $current = $this->_attachments;
- $this->setAttachments($attachments);
- $this->_attachments = array_merge($current, $this->_attachments);
-
- return $this;
- }
-
- /**
- * Get generated message (used by transport classes)
- *
- * @param string|null $type Use MESSAGE_* constants or null to return the full message as array
- * @return string|array String if type is given, array if type is null
- */
- public function message($type = null)
- {
- switch ($type) {
- case static::MESSAGE_HTML:
- return $this->_htmlMessage;
- case static::MESSAGE_TEXT:
- return $this->_textMessage;
- }
-
- return $this->_message;
- }
-
- /**
- * Sets priority.
- *
- * @param int|null $priority 1 (highest) to 5 (lowest)
- * @return $this
- */
- public function setPriority($priority)
- {
- $this->_priority = $priority;
-
- return $this;
- }
-
- /**
- * Gets priority.
- *
- * @return int
- */
- public function getPriority()
- {
- return $this->_priority;
- }
-
- /**
- * Sets transport configuration.
- *
- * Use this method to define transports to use in delivery profiles.
- * Once defined you cannot edit the configurations, and must use
- * Email::dropTransport() to flush the configuration first.
- *
- * When using an array of configuration data a new transport
- * will be constructed for each message sent. When using a Closure, the
- * closure will be evaluated for each message.
- *
- * The `className` is used to define the class to use for a transport.
- * It can either be a short name, or a fully qualified class name
- *
- * @param string|array $key The configuration name to write. Or
- * an array of multiple transports to set.
- * @param array|\Cake\Mailer\AbstractTransport|null $config Either an array of configuration
- * data, or a transport instance. Null when using key as array.
- * @return void
- * @deprecated 3.7.0 Use TransportFactory::setConfig() instead.
- */
- public static function setConfigTransport($key, $config = null)
- {
- deprecationWarning('Email::setConfigTransport() is deprecated. Use TransportFactory::setConfig() instead.');
-
- TransportFactory::setConfig($key, $config);
- }
-
- /**
- * Gets current transport configuration.
- *
- * @param string $key The configuration name to read.
- * @return array|null Transport config.
- * @deprecated 3.7.0 Use TransportFactory::getConfig() instead.
- */
- public static function getConfigTransport($key)
- {
- deprecationWarning('Email::getConfigTransport() is deprecated. Use TransportFactory::getConfig() instead.');
-
- return TransportFactory::getConfig($key);
- }
-
- /**
- * Add or read transport configuration.
- *
- * Use this method to define transports to use in delivery profiles.
- * Once defined you cannot edit the configurations, and must use
- * Email::dropTransport() to flush the configuration first.
- *
- * When using an array of configuration data a new transport
- * will be constructed for each message sent. When using a Closure, the
- * closure will be evaluated for each message.
- *
- * The `className` is used to define the class to use for a transport.
- * It can either be a short name, or a fully qualified classname
- *
- * @deprecated 3.4.0 Use TransportFactory::setConfig()/getConfig() instead.
- * @param string|array $key The configuration name to read/write. Or
- * an array of multiple transports to set.
- * @param array|\Cake\Mailer\AbstractTransport|null $config Either an array of configuration
- * data, or a transport instance.
- * @return array|null Either null when setting or an array of data when reading.
- * @throws \BadMethodCallException When modifying an existing configuration.
- */
- public static function configTransport($key, $config = null)
- {
- deprecationWarning('Email::configTransport() is deprecated. Use TransportFactory::setConfig() or TransportFactory::getConfig() instead.');
-
- if ($config === null && is_string($key)) {
- return TransportFactory::getConfig($key);
- }
- if ($config === null && is_array($key)) {
- TransportFactory::setConfig($key);
-
- return null;
- }
-
- TransportFactory::setConfig($key, $config);
- }
-
- /**
- * Returns an array containing the named transport configurations
- *
- * @return array Array of configurations.
- * @deprecated 3.7.0 Use TransportFactory::configured() instead.
- */
- public static function configuredTransport()
- {
- deprecationWarning('Email::configuredTransport() is deprecated. Use TransportFactory::configured().');
-
- return TransportFactory::configured();
- }
-
- /**
- * Delete transport configuration.
- *
- * @param string $key The transport name to remove.
- * @return void
- * @deprecated 3.7.0 Use TransportFactory::drop() instead.
- */
- public static function dropTransport($key)
- {
- deprecationWarning('Email::dropTransport() is deprecated. Use TransportFactory::drop().');
-
- TransportFactory::drop($key);
- }
-
- /**
- * Sets the configuration profile to use for this instance.
- *
- * @param string|array $config String with configuration name, or
- * an array with config.
- * @return $this
- */
- public function setProfile($config)
- {
- if (!is_array($config)) {
- $config = (string)$config;
- }
- $this->_applyConfig($config);
-
- return $this;
- }
-
- /**
- * Gets the configuration profile to use for this instance.
- *
- * @return string|array
- */
- public function getProfile()
- {
- return $this->_profile;
- }
-
- /**
- * Get/Set the configuration profile to use for this instance.
- *
- * @deprecated 3.4.0 Use setProfile()/getProfile() instead.
- * @param array|string|null $config String with configuration name, or
- * an array with config or null to return current config.
- * @return string|array|$this
- */
- public function profile($config = null)
- {
- deprecationWarning('Email::profile() is deprecated. Use Email::setProfile() or Email::getProfile() instead.');
-
- if ($config === null) {
- return $this->getProfile();
- }
-
- return $this->setProfile($config);
- }
-
- /**
- * Send an email using the specified content, template and layout
- *
- * @param string|array|null $content String with message or array with messages
- * @return array
- * @throws \BadMethodCallException
- */
- public function send($content = null)
- {
- if (empty($this->_from)) {
- throw new BadMethodCallException('From is not specified.');
- }
- if (empty($this->_to) && empty($this->_cc) && empty($this->_bcc)) {
- throw new BadMethodCallException('You need specify one destination on to, cc or bcc.');
- }
-
- if (is_array($content)) {
- $content = implode("\n", $content) . "\n";
- }
-
- $this->_message = $this->_render($this->_wrap($content));
-
- $transport = $this->getTransport();
- if (!$transport) {
- $msg = 'Cannot send email, transport was not defined. Did you call transport() or define ' .
- ' a transport in the set profile?';
- throw new BadMethodCallException($msg);
- }
- $contents = $transport->send($this);
- $this->_logDelivery($contents);
-
- return $contents;
- }
-
- /**
- * Log the email message delivery.
+ * Log the email message delivery.
*
* @param array $contents The content with 'headers' and 'message' keys.
* @return void
*/
- protected function _logDelivery($contents)
+ protected function _logDelivery(array $contents): void
{
if (empty($this->_profile['log'])) {
return;
@@ -2186,42 +473,49 @@ protected function _logDelivery($contents)
* @param string|array $value The value to convert
* @return string
*/
- protected function flatten($value)
+ protected function flatten($value): string
{
- return is_array($value) ? implode(';', $value) : (string)$value;
+ return is_array($value) ? implode(';', $value) : $value;
}
/**
* Static method to fast create an instance of \Cake\Mailer\Email
*
- * @param string|array|null $to Address to send (see Cake\Mailer\Email::to()). If null, will try to use 'to' from transport config
+ * @param string|array|null $to Address to send (see Cake\Mailer\Email::to()).
+ * If null, will try to use 'to' from transport config
* @param string|null $subject String of subject or null to use 'subject' from transport config
* @param string|array|null $message String with message or array with variables to be used in render
* @param string|array $config String to use Email delivery profile from app.php or array with configs
* @param bool $send Send the email or just return the instance pre-configured
- * @return static Instance of Cake\Mailer\Email
+ * @return \Cake\Mailer\Email Instance of Cake\Mailer\Email
* @throws \InvalidArgumentException
*/
- public static function deliver($to = null, $subject = null, $message = null, $config = 'default', $send = true)
- {
- $class = __CLASS__;
-
+ public static function deliver(
+ $to = null,
+ ?string $subject = null,
+ $message = null,
+ $config = 'default',
+ bool $send = true
+ ) {
if (is_array($config) && !isset($config['transport'])) {
$config['transport'] = 'default';
}
- /** @var \Cake\Mailer\Email $instance */
- $instance = new $class($config);
+
+ $instance = new static($config);
if ($to !== null) {
- $instance->setTo($to);
+ $instance->getMessage()->setTo($to);
}
if ($subject !== null) {
- $instance->setSubject($subject);
+ $instance->getMessage()->setSubject($subject);
}
if (is_array($message)) {
$instance->setViewVars($message);
$message = null;
- } elseif ($message === null && array_key_exists('message', $config = $instance->getProfile())) {
- $message = $config['message'];
+ } elseif ($message === null) {
+ $config = $instance->getProfile();
+ if (array_key_exists('message', $config)) {
+ $message = $config['message'];
+ }
}
if ($send === true) {
@@ -2231,64 +525,6 @@ public static function deliver($to = null, $subject = null, $message = null, $co
return $instance;
}
- /**
- * Apply the config to an instance
- *
- * @param string|array $config Configuration options.
- * @return void
- * @throws \InvalidArgumentException When using a configuration that doesn't exist.
- */
- protected function _applyConfig($config)
- {
- if (is_string($config)) {
- $name = $config;
- $config = static::getConfig($name);
- if (empty($config)) {
- throw new InvalidArgumentException(sprintf('Unknown email configuration "%s".', $name));
- }
- unset($name);
- }
-
- $this->_profile = array_merge($this->_profile, $config);
-
- $simpleMethods = [
- 'from', 'sender', 'to', 'replyTo', 'readReceipt', 'returnPath',
- 'cc', 'bcc', 'messageId', 'domain', 'subject', 'attachments',
- 'transport', 'emailFormat', 'emailPattern', 'charset', 'headerCharset',
- ];
- foreach ($simpleMethods as $method) {
- if (isset($config[$method])) {
- $this->{'set' . ucfirst($method)}($config[$method]);
- }
- }
-
- if (empty($this->headerCharset)) {
- $this->headerCharset = $this->charset;
- }
- if (isset($config['headers'])) {
- $this->setHeaders($config['headers']);
- }
-
- $viewBuilderMethods = [
- 'template', 'layout', 'theme',
- ];
- foreach ($viewBuilderMethods as $method) {
- if (array_key_exists($method, $config)) {
- $this->viewBuilder()->{'set' . ucfirst($method)}($config[$method]);
- }
- }
-
- if (array_key_exists('helpers', $config)) {
- $this->viewBuilder()->setHelpers($config['helpers'], false);
- }
- if (array_key_exists('viewRender', $config)) {
- $this->viewBuilder()->setClassName($config['viewRender']);
- }
- if (array_key_exists('viewVars', $config)) {
- $this->set($config['viewVars']);
- }
- }
-
/**
* Reset all the internal variables to be able to send out a new email.
*
@@ -2296,561 +532,29 @@ protected function _applyConfig($config)
*/
public function reset()
{
- $this->_to = [];
- $this->_from = [];
- $this->_sender = [];
- $this->_replyTo = [];
- $this->_readReceipt = [];
- $this->_returnPath = [];
- $this->_cc = [];
- $this->_bcc = [];
- $this->_messageId = true;
- $this->_subject = '';
- $this->_headers = [];
- $this->_textMessage = '';
- $this->_htmlMessage = '';
- $this->_message = [];
- $this->_emailFormat = 'text';
+ $this->message->reset();
+ if ($this->renderer !== null) {
+ $this->renderer->reset();
+ }
$this->_transport = null;
- $this->_priority = null;
- $this->charset = 'utf-8';
- $this->headerCharset = null;
- $this->transferEncoding = null;
- $this->_attachments = [];
$this->_profile = [];
- $this->_emailPattern = self::EMAIL_PATTERN;
-
- $this->viewBuilder()->setLayout('default');
- $this->viewBuilder()->setTemplate('');
- $this->viewBuilder()->setClassName('Cake\View\View');
- $this->viewVars = [];
- $this->viewBuilder()->setTheme(false);
- $this->viewBuilder()->setHelpers(['Html'], false);
return $this;
}
- /**
- * Encode the specified string using the current charset
- *
- * @param string $text String to encode
- * @return string Encoded string
- */
- protected function _encode($text)
- {
- $restore = mb_internal_encoding();
- mb_internal_encoding($this->_appCharset);
- if (empty($this->headerCharset)) {
- $this->headerCharset = $this->charset;
- }
- $return = mb_encode_mimeheader($text, $this->headerCharset, 'B');
- mb_internal_encoding($restore);
-
- return $return;
- }
-
- /**
- * Decode the specified string
- *
- * @param string $text String to decode
- * @return string Decoded string
- */
- protected function _decode($text)
- {
- $restore = mb_internal_encoding();
- mb_internal_encoding($this->_appCharset);
- $return = mb_decode_mimeheader($text);
- mb_internal_encoding($restore);
-
- return $return;
- }
-
- /**
- * Translates a string for one charset to another if the App.encoding value
- * differs and the mb_convert_encoding function exists
- *
- * @param string $text The text to be converted
- * @param string $charset the target encoding
- * @return string
- */
- protected function _encodeString($text, $charset)
- {
- if ($this->_appCharset === $charset) {
- return $text;
- }
-
- return mb_convert_encoding($text, $charset, $this->_appCharset);
- }
-
- /**
- * Wrap the message to follow the RFC 2822 - 2.1.1
- *
- * @param string $message Message to wrap
- * @param int $wrapLength The line length
- * @return array Wrapped message
- */
- protected function _wrap($message, $wrapLength = Email::LINE_LENGTH_MUST)
- {
- if (strlen($message) === 0) {
- return [''];
- }
- $message = str_replace(["\r\n", "\r"], "\n", $message);
- $lines = explode("\n", $message);
- $formatted = [];
- $cut = ($wrapLength == Email::LINE_LENGTH_MUST);
-
- foreach ($lines as $line) {
- if (empty($line) && $line !== '0') {
- $formatted[] = '';
- continue;
- }
- if (strlen($line) < $wrapLength) {
- $formatted[] = $line;
- continue;
- }
- if (!preg_match('/<[a-z]+.*>/i', $line)) {
- $formatted = array_merge(
- $formatted,
- explode("\n", Text::wordWrap($line, $wrapLength, "\n", $cut))
- );
- continue;
- }
-
- $tagOpen = false;
- $tmpLine = $tag = '';
- $tmpLineLength = 0;
- for ($i = 0, $count = strlen($line); $i < $count; $i++) {
- $char = $line[$i];
- if ($tagOpen) {
- $tag .= $char;
- if ($char === '>') {
- $tagLength = strlen($tag);
- if ($tagLength + $tmpLineLength < $wrapLength) {
- $tmpLine .= $tag;
- $tmpLineLength += $tagLength;
- } else {
- if ($tmpLineLength > 0) {
- $formatted = array_merge(
- $formatted,
- explode("\n", Text::wordWrap(trim($tmpLine), $wrapLength, "\n", $cut))
- );
- $tmpLine = '';
- $tmpLineLength = 0;
- }
- if ($tagLength > $wrapLength) {
- $formatted[] = $tag;
- } else {
- $tmpLine = $tag;
- $tmpLineLength = $tagLength;
- }
- }
- $tag = '';
- $tagOpen = false;
- }
- continue;
- }
- if ($char === '<') {
- $tagOpen = true;
- $tag = '<';
- continue;
- }
- if ($char === ' ' && $tmpLineLength >= $wrapLength) {
- $formatted[] = $tmpLine;
- $tmpLineLength = 0;
- continue;
- }
- $tmpLine .= $char;
- $tmpLineLength++;
- if ($tmpLineLength === $wrapLength) {
- $nextChar = isset($line[$i + 1]) ? $line[$i + 1] : '';
- if ($nextChar === ' ' || $nextChar === '<') {
- $formatted[] = trim($tmpLine);
- $tmpLine = '';
- $tmpLineLength = 0;
- if ($nextChar === ' ') {
- $i++;
- }
- } else {
- $lastSpace = strrpos($tmpLine, ' ');
- if ($lastSpace === false) {
- continue;
- }
- $formatted[] = trim(substr($tmpLine, 0, $lastSpace));
- $tmpLine = substr($tmpLine, $lastSpace + 1);
-
- $tmpLineLength = strlen($tmpLine);
- }
- }
- }
- if (!empty($tmpLine)) {
- $formatted[] = $tmpLine;
- }
- }
- $formatted[] = '';
-
- return $formatted;
- }
-
- /**
- * Create unique boundary identifier
- *
- * @return void
- */
- protected function _createBoundary()
- {
- if ($this->_attachments || $this->_emailFormat === 'both') {
- $this->_boundary = md5(Security::randomBytes(16));
- }
- }
-
- /**
- * Attach non-embedded files by adding file contents inside boundaries.
- *
- * @param string|null $boundary Boundary to use. If null, will default to $this->_boundary
- * @return array An array of lines to add to the message
- */
- protected function _attachFiles($boundary = null)
- {
- if ($boundary === null) {
- $boundary = $this->_boundary;
- }
-
- $msg = [];
- foreach ($this->_attachments as $filename => $fileInfo) {
- if (!empty($fileInfo['contentId'])) {
- continue;
- }
- $data = isset($fileInfo['data']) ? $fileInfo['data'] : $this->_readFile($fileInfo['file']);
- $hasDisposition = (
- !isset($fileInfo['contentDisposition']) ||
- $fileInfo['contentDisposition']
- );
- $part = new FormDataPart('', $data, '', $this->getHeaderCharset());
-
- if ($hasDisposition) {
- $part->disposition('attachment');
- $part->filename($filename);
- }
- $part->transferEncoding('base64');
- $part->type($fileInfo['mimetype']);
-
- $msg[] = '--' . $boundary;
- $msg[] = (string)$part;
- $msg[] = '';
- }
-
- return $msg;
- }
-
- /**
- * Read the file contents and return a base64 version of the file contents.
- *
- * @param string $path The absolute path to the file to read.
- * @return string File contents in base64 encoding
- */
- protected function _readFile($path)
- {
- $File = new File($path);
-
- return chunk_split(base64_encode($File->read()));
- }
-
- /**
- * Attach inline/embedded files to the message.
- *
- * @param string|null $boundary Boundary to use. If null, will default to $this->_boundary
- * @return array An array of lines to add to the message
- */
- protected function _attachInlineFiles($boundary = null)
- {
- if ($boundary === null) {
- $boundary = $this->_boundary;
- }
-
- $msg = [];
- foreach ($this->_attachments as $filename => $fileInfo) {
- if (empty($fileInfo['contentId'])) {
- continue;
- }
- $data = isset($fileInfo['data']) ? $fileInfo['data'] : $this->_readFile($fileInfo['file']);
-
- $msg[] = '--' . $boundary;
- $part = new FormDataPart('', $data, 'inline', $this->getHeaderCharset());
- $part->type($fileInfo['mimetype']);
- $part->transferEncoding('base64');
- $part->contentId($fileInfo['contentId']);
- $part->filename($filename);
- $msg[] = (string)$part;
- $msg[] = '';
- }
-
- return $msg;
- }
-
- /**
- * Render the body of the email.
- *
- * @param array $content Content to render
- * @return array Email body ready to be sent
- */
- protected function _render($content)
- {
- $this->_textMessage = $this->_htmlMessage = '';
-
- $content = implode("\n", $content);
- $rendered = $this->_renderTemplates($content);
-
- $this->_createBoundary();
- $msg = [];
-
- $contentIds = array_filter((array)Hash::extract($this->_attachments, '{s}.contentId'));
- $hasInlineAttachments = count($contentIds) > 0;
- $hasAttachments = !empty($this->_attachments);
- $hasMultipleTypes = count($rendered) > 1;
- $multiPart = ($hasAttachments || $hasMultipleTypes);
-
- $boundary = $relBoundary = $textBoundary = $this->_boundary;
-
- if ($hasInlineAttachments) {
- $msg[] = '--' . $boundary;
- $msg[] = 'Content-Type: multipart/related; boundary="rel-' . $boundary . '"';
- $msg[] = '';
- $relBoundary = $textBoundary = 'rel-' . $boundary;
- }
-
- if ($hasMultipleTypes && $hasAttachments) {
- $msg[] = '--' . $relBoundary;
- $msg[] = 'Content-Type: multipart/alternative; boundary="alt-' . $boundary . '"';
- $msg[] = '';
- $textBoundary = 'alt-' . $boundary;
- }
-
- if (isset($rendered['text'])) {
- if ($multiPart) {
- $msg[] = '--' . $textBoundary;
- $msg[] = 'Content-Type: text/plain; charset=' . $this->_getContentTypeCharset();
- $msg[] = 'Content-Transfer-Encoding: ' . $this->_getContentTransferEncoding();
- $msg[] = '';
- }
- $this->_textMessage = $rendered['text'];
- $content = explode("\n", $this->_textMessage);
- $msg = array_merge($msg, $content);
- $msg[] = '';
- }
-
- if (isset($rendered['html'])) {
- if ($multiPart) {
- $msg[] = '--' . $textBoundary;
- $msg[] = 'Content-Type: text/html; charset=' . $this->_getContentTypeCharset();
- $msg[] = 'Content-Transfer-Encoding: ' . $this->_getContentTransferEncoding();
- $msg[] = '';
- }
- $this->_htmlMessage = $rendered['html'];
- $content = explode("\n", $this->_htmlMessage);
- $msg = array_merge($msg, $content);
- $msg[] = '';
- }
-
- if ($textBoundary !== $relBoundary) {
- $msg[] = '--' . $textBoundary . '--';
- $msg[] = '';
- }
-
- if ($hasInlineAttachments) {
- $attachments = $this->_attachInlineFiles($relBoundary);
- $msg = array_merge($msg, $attachments);
- $msg[] = '';
- $msg[] = '--' . $relBoundary . '--';
- $msg[] = '';
- }
-
- if ($hasAttachments) {
- $attachments = $this->_attachFiles($boundary);
- $msg = array_merge($msg, $attachments);
- }
- if ($hasAttachments || $hasMultipleTypes) {
- $msg[] = '';
- $msg[] = '--' . $boundary . '--';
- $msg[] = '';
- }
-
- return $msg;
- }
-
- /**
- * Gets the text body types that are in this email message
- *
- * @return array Array of types. Valid types are 'text' and 'html'
- */
- protected function _getTypes()
- {
- $types = [$this->_emailFormat];
- if ($this->_emailFormat === 'both') {
- $types = ['html', 'text'];
- }
-
- return $types;
- }
-
- /**
- * Build and set all the view properties needed to render the templated emails.
- * If there is no template set, the $content will be returned in a hash
- * of the text content types for the email.
- *
- * @param string $content The content passed in from send() in most cases.
- * @return array The rendered content with html and text keys.
- */
- protected function _renderTemplates($content)
- {
- $types = $this->_getTypes();
- $rendered = [];
- $template = $this->viewBuilder()->getTemplate();
- if (empty($template)) {
- foreach ($types as $type) {
- $rendered[$type] = $this->_encodeString($content, $this->charset);
- }
-
- return $rendered;
- }
-
- $View = $this->createView();
-
- list($templatePlugin) = pluginSplit($View->getTemplate());
- list($layoutPlugin) = pluginSplit($View->getLayout());
- if ($templatePlugin) {
- $View->setPlugin($templatePlugin);
- } elseif ($layoutPlugin) {
- $View->setPlugin($layoutPlugin);
- }
-
- if ($View->get('content') === null) {
- $View->set('content', $content);
- }
-
- foreach ($types as $type) {
- $View->hasRendered = false;
- $View->setTemplatePath('Email' . DIRECTORY_SEPARATOR . $type);
- $View->setLayoutPath('Email' . DIRECTORY_SEPARATOR . $type);
-
- $render = $View->render();
- $render = str_replace(["\r\n", "\r"], "\n", $render);
- $rendered[$type] = $this->_encodeString($render, $this->charset);
- }
-
- foreach ($rendered as $type => $content) {
- $rendered[$type] = $this->_wrap($content);
- $rendered[$type] = implode("\n", $rendered[$type]);
- $rendered[$type] = rtrim($rendered[$type], "\n");
- }
-
- return $rendered;
- }
-
- /**
- * Return the Content-Transfer Encoding value based
- * on the set transferEncoding or set charset.
- *
- * @return string
- */
- protected function _getContentTransferEncoding()
- {
- if ($this->transferEncoding) {
- return $this->transferEncoding;
- }
-
- $charset = strtoupper($this->charset);
- if (in_array($charset, $this->_charset8bit)) {
- return '8bit';
- }
-
- return '7bit';
- }
-
- /**
- * Return charset value for Content-Type.
- *
- * Checks fallback/compatibility types which include workarounds
- * for legacy japanese character sets.
- *
- * @return string
- */
- protected function _getContentTypeCharset()
- {
- $charset = strtoupper($this->charset);
- if (array_key_exists($charset, $this->_contentTypeCharset)) {
- return strtoupper($this->_contentTypeCharset[$charset]);
- }
-
- return strtoupper($this->charset);
- }
-
/**
* Serializes the email object to a value that can be natively serialized and re-used
* to clone this email instance.
*
- * It has certain limitations for viewVars that are good to know:
- *
- * - ORM\Query executed and stored as resultset
- * - SimpleXMLElements stored as associative array
- * - Exceptions stored as strings
- * - Resources, \Closure and \PDO are not supported.
- *
* @return array Serializable array of configuration properties.
* @throws \Exception When a view var object can not be properly serialized.
*/
- public function jsonSerialize()
- {
- $properties = [
- '_to', '_from', '_sender', '_replyTo', '_cc', '_bcc', '_subject',
- '_returnPath', '_readReceipt', '_emailFormat', '_emailPattern', '_domain',
- '_attachments', '_messageId', '_headers', '_appCharset', 'viewVars', 'charset', 'headerCharset',
- ];
-
- $array = ['viewConfig' => $this->viewBuilder()->jsonSerialize()];
-
- foreach ($properties as $property) {
- $array[$property] = $this->{$property};
- }
-
- array_walk($array['_attachments'], function (&$item, $key) {
- if (!empty($item['file'])) {
- $item['data'] = $this->_readFile($item['file']);
- unset($item['file']);
- }
- });
-
- array_walk_recursive($array['viewVars'], [$this, '_checkViewVars']);
-
- return array_filter($array, function ($i) {
- return !is_array($i) && strlen($i) || !empty($i);
- });
- }
-
- /**
- * Iterates through hash to clean up and normalize.
- *
- * @param mixed $item Reference to the view var value.
- * @param string $key View var key.
- * @return void
- */
- protected function _checkViewVars(&$item, $key)
+ public function jsonSerialize(): array
{
- if ($item instanceof Exception) {
- $item = (string)$item;
- }
+ $array = $this->message->jsonSerialize();
+ $array['viewConfig'] = $this->getRenderer()->viewBuilder()->jsonSerialize();
- if (
- is_resource($item) ||
- $item instanceof Closure ||
- $item instanceof PDO
- ) {
- throw new RuntimeException(sprintf(
- 'Failed serializing the `%s` %s in the `%s` view var',
- is_resource($item) ? get_resource_type($item) : get_class($item),
- is_resource($item) ? 'resource' : 'object',
- $key
- ));
- }
+ return $array;
}
/**
@@ -2859,16 +563,17 @@ protected function _checkViewVars(&$item, $key)
* @param array $config Email configuration array.
* @return $this Configured email instance.
*/
- public function createFromArray($config)
+ public function createFromArray(array $config)
{
if (isset($config['viewConfig'])) {
- $this->viewBuilder()->createFromArray($config['viewConfig']);
+ $this->getRenderer()->viewBuilder()->createFromArray($config['viewConfig']);
unset($config['viewConfig']);
}
- foreach ($config as $property => $value) {
- $this->{$property} = $value;
+ if ($this->message === null) {
+ $this->message = new $this->messageClass();
}
+ $this->message->createFromArray($config);
return $this;
}
@@ -2878,10 +583,10 @@ public function createFromArray($config)
*
* @return string
*/
- public function serialize()
+ public function serialize(): string
{
$array = $this->jsonSerialize();
- array_walk_recursive($array, function (&$item, $key) {
+ array_walk_recursive($array, function (&$item, $key): void {
if ($item instanceof SimpleXMLElement) {
$item = json_decode(json_encode((array)$item), true);
}
@@ -2894,10 +599,22 @@ public function serialize()
* Unserializes the Email object.
*
* @param string $data Serialized string.
- * @return static Configured email instance.
+ * @return void
+ */
+ public function unserialize($data): void
+ {
+ $this->createFromArray(unserialize($data));
+ }
+
+ /**
+ * Proxy all static method calls (for methods provided by StaticConfigTrat) to Mailer.
+ *
+ * @param string $name Method name.
+ * @param array $arguments Method argument.
+ * @return mixed
*/
- public function unserialize($data)
+ public static function __callStatic($name, $arguments)
{
- return $this->createFromArray(unserialize($data));
+ return call_user_func_array([Mailer::class, $name], $arguments);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Exception/MissingActionException.php b/app/vendor/cakephp/cakephp/src/Mailer/Exception/MissingActionException.php
index 25bc6fc7e..9c6d3f88f 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Exception/MissingActionException.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Exception/MissingActionException.php
@@ -1,4 +1,6 @@
'onRegistration',
* ];
* }
*
- * public function onRegistration(Event $event, Entity $entity, ArrayObject $options)
+ * public function onRegistration(EventInterface $event, EntityInterface $entity, ArrayObject $options)
* {
* if ($entity->isNew()) {
* $this->send('welcome', [$entity]);
@@ -79,89 +87,52 @@
* Our mailer could either be registered in the application bootstrap, or
* in the Table class' initialize() hook.
*
- * @method \Cake\Mailer\Mailer setTo($email, $name = null)
- * @method array getTo()
- * @method \Cake\Mailer\Mailer to($email = null, $name = null)
- * @method \Cake\Mailer\Mailer setFrom($email, $name = null)
- * @method array getFrom()
- * @method \Cake\Mailer\Mailer from($email = null, $name = null)
- * @method \Cake\Mailer\Mailer setSender($email, $name = null)
- * @method array getSender()
- * @method \Cake\Mailer\Mailer sender($email = null, $name = null)
- * @method \Cake\Mailer\Mailer setReplyTo($email, $name = null)
- * @method array getReplyTo()
- * @method \Cake\Mailer\Mailer replyTo($email = null, $name = null)
- * @method \Cake\Mailer\Mailer setReadReceipt($email, $name = null)
- * @method array getReadReceipt()
- * @method \Cake\Mailer\Mailer readReceipt($email = null, $name = null)
- * @method \Cake\Mailer\Mailer setReturnPath($email, $name = null)
- * @method array getReturnPath()
- * @method \Cake\Mailer\Mailer returnPath($email = null, $name = null)
- * @method \Cake\Mailer\Mailer addTo($email, $name = null)
- * @method \Cake\Mailer\Mailer setCc($email, $name = null)
- * @method array getCc()
- * @method \Cake\Mailer\Mailer cc($email = null, $name = null)
- * @method \Cake\Mailer\Mailer addCc($email, $name = null)
- * @method \Cake\Mailer\Mailer setBcc($email, $name = null)
- * @method array getBcc()
- * @method \Cake\Mailer\Mailer bcc($email = null, $name = null)
- * @method \Cake\Mailer\Mailer addBcc($email, $name = null)
- * @method \Cake\Mailer\Mailer setCharset($charset)
- * @method string getCharset()
- * @method \Cake\Mailer\Mailer charset($charset = null)
- * @method \Cake\Mailer\Mailer setHeaderCharset($charset)
- * @method string getHeaderCharset()
- * @method \Cake\Mailer\Mailer headerCharset($charset = null)
- * @method \Cake\Mailer\Mailer setSubject($subject)
- * @method string getSubject()
- * @method \Cake\Mailer\Mailer subject($subject = null)
- * @method \Cake\Mailer\Mailer setHeaders(array $headers)
- * @method \Cake\Mailer\Mailer addHeaders(array $headers)
- * @method \Cake\Mailer\Mailer getHeaders(array $include = [])
- * @method \Cake\Mailer\Mailer setTemplate($template)
- * @method string getTemplate()
- * @method \Cake\Mailer\Mailer setLayout($layout)
- * @method string getLayout()
- * @method \Cake\Mailer\Mailer template($template = false, $layout = false)
- * @method \Cake\Mailer\Mailer setViewRenderer($viewClass)
- * @method string getViewRenderer()
- * @method \Cake\Mailer\Mailer viewRender($viewClass = null)
- * @method \Cake\Mailer\Mailer setViewVars($viewVars)
- * @method array getViewVars()
- * @method \Cake\Mailer\Mailer viewVars($viewVars = null)
- * @method \Cake\Mailer\Mailer setTheme($theme)
- * @method string getTheme()
- * @method \Cake\Mailer\Mailer theme($theme = null)
- * @method \Cake\Mailer\Mailer setHelpers(array $helpers)
- * @method array getHelpers()
- * @method \Cake\Mailer\Mailer helpers($helpers = null)
- * @method \Cake\Mailer\Mailer setEmailFormat($format)
- * @method string getEmailFormat()
- * @method \Cake\Mailer\Mailer emailFormat($format = null)
- * @method \Cake\Mailer\Mailer setTransport($name)
- * @method \Cake\Mailer\AbstractTransport getTransport()
- * @method \Cake\Mailer\Mailer transport($name = null)
- * @method \Cake\Mailer\Mailer setMessageId($message)
- * @method bool|string getMessageId()
- * @method \Cake\Mailer\Mailer messageId($message = null)
- * @method \Cake\Mailer\Mailer setDomain($domain)
- * @method string getDomain()
- * @method \Cake\Mailer\Mailer domain($domain = null)
- * @method \Cake\Mailer\Mailer setAttachments($attachments)
- * @method array getAttachments()
- * @method \Cake\Mailer\Mailer attachments($attachments = null)
- * @method \Cake\Mailer\Mailer addAttachments($attachments)
- * @method \Cake\Mailer\Mailer message($type = null)
- * @method \Cake\Mailer\Mailer setProfile($config)
- * @method string|array getProfile()
- * @method \Cake\Mailer\Mailer profile($config = null)
- * @method \Cake\Mailer\Mailer setEmailPattern($regex)
- * @method string getEmailPattern()
- * @method \Cake\Mailer\Mailer emailPattern($regex = null)
+ * @method $this setTo($email, $name = null) Sets "to" address. {@see \Cake\Mailer\Message::setTo()}
+ * @method array getTo() Gets "to" address. {@see \Cake\Mailer\Message::getTo()}
+ * @method $this setFrom($email, $name = null) Sets "from" address. {@see \Cake\Mailer\Message::setFrom()}
+ * @method array getFrom() Gets "from" address. {@see \Cake\Mailer\Message::getFrom()}
+ * @method $this setSender($email, $name = null) Sets "sender" address. {@see \Cake\Mailer\Message::setSender()}
+ * @method array getSender() Gets "sender" address. {@see \Cake\Mailer\Message::getSender()}
+ * @method $this setReplyTo($email, $name = null) Sets "Reply-To" address. {@see \Cake\Mailer\Message::setReplyTo()}
+ * @method array getReplyTo() Gets "Reply-To" address. {@see \Cake\Mailer\Message::getReplyTo()}
+ * @method $this setReadReceipt($email, $name = null) Sets Read Receipt (Disposition-Notification-To header).
+ * {@see \Cake\Mailer\Message::setReadReceipt()}
+ * @method array getReadReceipt() Gets Read Receipt (Disposition-Notification-To header).
+ * {@see \Cake\Mailer\Message::getReadReceipt()}
+ * @method $this setReturnPath($email, $name = null) Sets return path. {@see \Cake\Mailer\Message::setReturnPath()}
+ * @method array getReturnPath() Gets return path. {@see \Cake\Mailer\Message::getReturnPath()}
+ * @method $this addTo($email, $name = null) Add "To" address. {@see \Cake\Mailer\Message::addTo()}
+ * @method $this setCc($email, $name = null) Sets "cc" address. {@see \Cake\Mailer\Message::setCc()}
+ * @method array getCc() Gets "cc" address. {@see \Cake\Mailer\Message::getCc()}
+ * @method $this addCc($email, $name = null) Add "cc" address. {@see \Cake\Mailer\Message::addCc()}
+ * @method $this setBcc($email, $name = null) Sets "bcc" address. {@see \Cake\Mailer\Message::setBcc()}
+ * @method array getBcc() Gets "bcc" address. {@see \Cake\Mailer\Message::getBcc()}
+ * @method $this addBcc($email, $name = null) Add "bcc" address. {@see \Cake\Mailer\Message::addBcc()}
+ * @method $this setCharset($charset) Charset setter. {@see \Cake\Mailer\Message::setCharset()}
+ * @method string getCharset() Charset getter. {@see \Cake\Mailer\Message::getCharset()}
+ * @method $this setHeaderCharset($charset) HeaderCharset setter. {@see \Cake\Mailer\Message::setHeaderCharset()}
+ * @method string getHeaderCharset() HeaderCharset getter. {@see \Cake\Mailer\Message::getHeaderCharset()}
+ * @method $this setSubject($subject) Sets subject. {@see \Cake\Mailer\Message::setSubject()}
+ * @method string getSubject() Gets subject. {@see \Cake\Mailer\Message::getSubject()}
+ * @method $this setHeaders(array $headers) Sets headers for the message. {@see \Cake\Mailer\Message::setHeaders()}
+ * @method $this addHeaders(array $headers) Add header for the message. {@see \Cake\Mailer\Message::addHeaders()}
+ * @method $this getHeaders(array $include = []) Get list of headers. {@see \Cake\Mailer\Message::getHeaders()}
+ * @method $this setEmailFormat($format) Sets email format. {@see \Cake\Mailer\Message::getHeaders()}
+ * @method string getEmailFormat() Gets email format. {@see \Cake\Mailer\Message::getEmailFormat()}
+ * @method $this setMessageId($message) Sets message ID. {@see \Cake\Mailer\Message::setMessageId()}
+ * @method bool|string getMessageId() Gets message ID. {@see \Cake\Mailer\Message::getMessageId()}
+ * @method $this setDomain($domain) Sets domain. {@see \Cake\Mailer\Message::setDomain()}
+ * @method string getDomain() Gets domain. {@see \Cake\Mailer\Message::getDomain()}
+ * @method $this setAttachments($attachments) Add attachments to the email message. {@see \Cake\Mailer\Message::setAttachments()}
+ * @method array getAttachments() Gets attachments to the email message. {@see \Cake\Mailer\Message::getAttachments()}
+ * @method $this addAttachments($attachments) Add attachments. {@see \Cake\Mailer\Message::addAttachments()}
+ * @method string|array getBody(?string $type = null) Get generated message body as array.
+ * {@see \Cake\Mailer\Message::getBody()}
*/
-abstract class Mailer implements EventListenerInterface
+class Mailer implements EventListenerInterface
{
use ModelAwareTrait;
+ use StaticConfigTrait;
/**
* Mailer's name.
@@ -171,91 +142,147 @@ abstract class Mailer implements EventListenerInterface
public static $name;
/**
- * Email instance.
+ * The transport instance to use for sending mail.
+ *
+ * @var \Cake\Mailer\AbstractTransport|null
+ */
+ protected $transport;
+
+ /**
+ * Message class name.
*
- * @var \Cake\Mailer\Email
+ * @var string
+ * @psalm-var class-string<\Cake\Mailer\Message>
*/
- protected $_email;
+ protected $messageClass = Message::class;
/**
- * Cloned Email instance for restoring instance after email is sent by
- * mailer action.
+ * Message instance.
*
- * @var \Cake\Mailer\Email
+ * @var \Cake\Mailer\Message
+ */
+ protected $message;
+
+ /**
+ * Email Renderer
+ *
+ * @var \Cake\Mailer\Renderer|null
+ */
+ protected $renderer;
+
+ /**
+ * Hold message, renderer and transport instance for restoring after runnning
+ * a mailer action.
+ *
+ * @var array
+ */
+ protected $clonedInstances = [
+ 'message' => null,
+ 'renderer' => null,
+ 'transport' => null,
+ ];
+
+ /**
+ * Mailer driver class map.
+ *
+ * @var array
+ * @psalm-var array
+ */
+ protected static $_dsnClassMap = [];
+
+ /**
+ * @var array|null
*/
- protected $_clonedEmail;
+ protected $logConfig = null;
/**
- * Constructor.
+ * Constructor
*
- * @param \Cake\Mailer\Email|null $email Email instance.
+ * @param array|string|null $config Array of configs, or string to load configs from app.php
*/
- public function __construct(Email $email = null)
+ public function __construct($config = null)
{
- if ($email === null) {
- $email = new Email();
+ $this->message = new $this->messageClass();
+
+ if ($config === null) {
+ $config = static::getConfig('default');
}
- $this->_email = $email;
- $this->_clonedEmail = clone $email;
+ if ($config) {
+ $this->setProfile($config);
+ }
}
/**
- * Returns the mailer's name.
+ * Get the view builder.
*
- * @return string
+ * @return \Cake\View\ViewBuilder
*/
- public function getName()
+ public function viewBuilder(): ViewBuilder
{
- if (!static::$name) {
- static::$name = str_replace(
- 'Mailer',
- '',
- implode('', array_slice(explode('\\', get_class($this)), -1))
- );
+ return $this->getRenderer()->viewBuilder();
+ }
+
+ /**
+ * Get email renderer.
+ *
+ * @return \Cake\Mailer\Renderer
+ */
+ public function getRenderer(): Renderer
+ {
+ if ($this->renderer === null) {
+ $this->renderer = new Renderer();
}
- return static::$name;
+ return $this->renderer;
}
/**
- * Sets layout to use.
+ * Set email renderer.
*
- * @deprecated 3.4.0 Use setLayout() which sets the layout on the email class instead.
- * @param string $layout Name of the layout to use.
+ * @param \Cake\Mailer\Renderer $renderer Render instance.
* @return $this
*/
- public function layout($layout)
+ public function setRenderer(Renderer $renderer)
{
- deprecationWarning(
- 'Mailer::layout() is deprecated. Use $mailer->viewBuilder()->setLayout() instead.'
- );
-
- $this->_email->viewBuilder()->setLayout($layout);
+ $this->renderer = $renderer;
return $this;
}
/**
- * Get Email instance's view builder.
+ * Get message instance.
*
- * @return \Cake\View\ViewBuilder
+ * @return \Cake\Mailer\Message
+ */
+ public function getMessage(): Message
+ {
+ return $this->message;
+ }
+
+ /**
+ * Set message instance.
+ *
+ * @param \Cake\Mailer\Message $message Message instance.
+ * @return $this
*/
- public function viewBuilder()
+ public function setMessage(Message $message)
{
- return $this->_email->viewBuilder();
+ $this->message = $message;
+
+ return $this;
}
/**
- * Magic method to forward method class to Email instance.
+ * Magic method to forward method class to Message instance.
*
* @param string $method Method name.
* @param array $args Method arguments
* @return $this|mixed
*/
- public function __call($method, $args)
+ public function __call(string $method, array $args)
{
- $result = $this->_email->$method(...$args);
+ $result = $this->message->$method(...$args);
if (strpos($method, 'get') === 0) {
return $result;
}
@@ -269,10 +296,23 @@ public function __call($method, $args)
* @param string|array $key Variable name or hash of view variables.
* @param mixed $value View variable value.
* @return $this
+ * @deprecated 4.0.0 Use {@link Mailer::setViewVars()} instead.
*/
public function set($key, $value = null)
{
- $this->_email->setViewVars(is_string($key) ? [$key => $value] : $key);
+ return $this->setViewVars($key, $value);
+ }
+
+ /**
+ * Sets email view vars.
+ *
+ * @param string|array $key Variable name or hash of view variables.
+ * @param mixed $value View variable value.
+ * @return $this
+ */
+ public function setViewVars($key, $value = null)
+ {
+ $this->getRenderer()->set($key, $value);
return $this;
}
@@ -280,56 +320,292 @@ public function set($key, $value = null)
/**
* Sends email.
*
- * @param string $action The name of the mailer action to trigger.
+ * @param string|null $action The name of the mailer action to trigger.
+ * If no action is specified then all other method arguments will be ignored.
* @param array $args Arguments to pass to the triggered mailer action.
* @param array $headers Headers to set.
* @return array
* @throws \Cake\Mailer\Exception\MissingActionException
* @throws \BadMethodCallException
+ * @psalm-return array{headers: string, message: string}
*/
- public function send($action, $args = [], $headers = [])
+ public function send(?string $action = null, array $args = [], array $headers = []): array
{
- try {
- if (!method_exists($this, $action)) {
- throw new MissingActionException([
- 'mailer' => $this->getName() . 'Mailer',
- 'action' => $action,
- ]);
- }
+ if ($action === null) {
+ return $this->deliver();
+ }
- $this->_email->setHeaders($headers);
- if (!$this->_email->viewBuilder()->getTemplate()) {
- $this->_email->viewBuilder()->setTemplate($action);
- }
+ if (!method_exists($this, $action)) {
+ throw new MissingActionException([
+ 'mailer' => static::class,
+ 'action' => $action,
+ ]);
+ }
+
+ $this->clonedInstances['message'] = clone $this->message;
+ $this->clonedInstances['renderer'] = clone $this->getRenderer();
+ if ($this->transport !== null) {
+ $this->clonedInstances['transport'] = clone $this->transport;
+ }
+
+ $this->getMessage()->setHeaders($headers);
+ if (!$this->viewBuilder()->getTemplate()) {
+ $this->viewBuilder()->setTemplate($action);
+ }
+ try {
$this->$action(...$args);
- $result = $this->_email->send();
+ $result = $this->deliver();
} finally {
- $this->reset();
+ $this->restore();
}
return $result;
}
/**
- * Reset email instance.
+ * Render content and set message body.
*
+ * @param string $content Content.
* @return $this
*/
- protected function reset()
+ public function render(string $content = '')
{
- $this->_email = clone $this->_clonedEmail;
+ $content = $this->getRenderer()->render(
+ $content,
+ $this->message->getBodyTypes()
+ );
+
+ $this->message->setBody($content);
return $this;
}
+ /**
+ * Render content and send email using configured transport.
+ *
+ * @param string $content Content.
+ * @return array
+ * @psalm-return array{headers: string, message: string}
+ */
+ public function deliver(string $content = '')
+ {
+ $this->render($content);
+
+ $result = $this->getTransport()->send($this->message);
+ $this->logDelivery($result);
+
+ return $result;
+ }
+
+ /**
+ * Sets the configuration profile to use for this instance.
+ *
+ * @param string|array $config String with configuration name, or
+ * an array with config.
+ * @return $this
+ */
+ public function setProfile($config)
+ {
+ if (is_string($config)) {
+ $name = $config;
+ $config = static::getConfig($name);
+ if (empty($config)) {
+ throw new InvalidArgumentException(sprintf('Unknown email configuration "%s".', $name));
+ }
+ unset($name);
+ }
+
+ $simpleMethods = [
+ 'transport',
+ ];
+ foreach ($simpleMethods as $method) {
+ if (isset($config[$method])) {
+ $this->{'set' . ucfirst($method)}($config[$method]);
+ unset($config[$method]);
+ }
+ }
+
+ $viewBuilderMethods = [
+ 'template', 'layout', 'theme',
+ ];
+ foreach ($viewBuilderMethods as $method) {
+ if (array_key_exists($method, $config)) {
+ $this->viewBuilder()->{'set' . ucfirst($method)}($config[$method]);
+ unset($config[$method]);
+ }
+ }
+
+ if (array_key_exists('helpers', $config)) {
+ $this->viewBuilder()->setHelpers($config['helpers'], false);
+ unset($config['helpers']);
+ }
+ if (array_key_exists('viewRenderer', $config)) {
+ $this->viewBuilder()->setClassName($config['viewRenderer']);
+ unset($config['viewRenderer']);
+ }
+ if (array_key_exists('viewVars', $config)) {
+ $this->viewBuilder()->setVars($config['viewVars']);
+ unset($config['viewVars']);
+ }
+
+ if (isset($config['log'])) {
+ $this->setLogConfig($config['log']);
+ }
+
+ $this->message->setConfig($config);
+
+ return $this;
+ }
+
+ /**
+ * Sets the transport.
+ *
+ * When setting the transport you can either use the name
+ * of a configured transport or supply a constructed transport.
+ *
+ * @param string|\Cake\Mailer\AbstractTransport $name Either the name of a configured
+ * transport, or a transport instance.
+ * @return $this
+ * @throws \LogicException When the chosen transport lacks a send method.
+ * @throws \InvalidArgumentException When $name is neither a string nor an object.
+ */
+ public function setTransport($name)
+ {
+ if (is_string($name)) {
+ $transport = TransportFactory::get($name);
+ } elseif (is_object($name)) {
+ $transport = $name;
+ if (!$transport instanceof AbstractTransport) {
+ throw new Exception('Transport class must extend Cake\Mailer\AbstractTransport');
+ }
+ } else {
+ throw new InvalidArgumentException(sprintf(
+ 'The value passed for the "$name" argument must be either a string, or an object, %s given.',
+ gettype($name)
+ ));
+ }
+
+ $this->transport = $transport;
+
+ return $this;
+ }
+
+ /**
+ * Gets the transport.
+ *
+ * @return \Cake\Mailer\AbstractTransport
+ */
+ public function getTransport(): AbstractTransport
+ {
+ if ($this->transport === null) {
+ throw new BadMethodCallException(
+ 'Transport was not defined. '
+ . 'You must set on using setTransport() or set `transport` option in your mailer profile.'
+ );
+ }
+
+ return $this->transport;
+ }
+
+ /**
+ * Restore message, renderer, transport instances to state before an action was run.
+ *
+ * @return $this
+ */
+ protected function restore()
+ {
+ foreach (array_keys($this->clonedInstances) as $key) {
+ if ($this->clonedInstances[$key] === null) {
+ $this->{$key} = null;
+ } else {
+ $this->{$key} = clone $this->clonedInstances[$key];
+ $this->clonedInstances[$key] = null;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Reset all the internal variables to be able to send out a new email.
+ *
+ * @return $this
+ */
+ public function reset()
+ {
+ $this->message->reset();
+ $this->getRenderer()->reset();
+ $this->transport = null;
+ $this->clonedInstances = [
+ 'message' => null,
+ 'renderer' => null,
+ 'transport' => null,
+ ];
+
+ return $this;
+ }
+
+ /**
+ * Log the email message delivery.
+ *
+ * @param array $contents The content with 'headers' and 'message' keys.
+ * @return void
+ * @psalm-param array{headers: string, message: string} $contents
+ */
+ protected function logDelivery(array $contents): void
+ {
+ if (empty($this->logConfig)) {
+ return;
+ }
+
+ Log::write(
+ $this->logConfig['level'],
+ PHP_EOL . $this->flatten($contents['headers']) . PHP_EOL . PHP_EOL . $this->flatten($contents['message']),
+ $this->logConfig['scope']
+ );
+ }
+
+ /**
+ * Set logging config.
+ *
+ * @param string|array|true $log Log config.
+ * @return void
+ */
+ protected function setLogConfig($log)
+ {
+ $config = [
+ 'level' => 'debug',
+ 'scope' => 'email',
+ ];
+ if ($log !== true) {
+ if (!is_array($log)) {
+ $log = ['level' => $log];
+ }
+ $config = $log + $config;
+ }
+
+ $this->logConfig = $config;
+ }
+
+ /**
+ * Converts given value to string
+ *
+ * @param string|array $value The value to convert
+ * @return string
+ */
+ protected function flatten($value): string
+ {
+ return is_array($value) ? implode(';', $value) : $value;
+ }
+
/**
* Implemented events.
*
* @return array
*/
- public function implementedEvents()
+ public function implementedEvents(): array
{
return [];
}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/MailerAwareTrait.php b/app/vendor/cakephp/cakephp/src/Mailer/MailerAwareTrait.php
index 402e18beb..19b43b5f6 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/MailerAwareTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/MailerAwareTrait.php
@@ -1,4 +1,6 @@
'ISO-2022-JP',
+ ];
+
+ /**
+ * Regex for email validation
+ *
+ * If null, filter_var() will be used. Use the emailPattern() method
+ * to set a custom pattern.'
+ *
+ * @var string|null
+ */
+ protected $emailPattern = self::EMAIL_PATTERN;
+
+ /**
+ * Constructor
+ *
+ * @param array|null $config Array of configs, or string to load configs from app.php
+ */
+ public function __construct(?array $config = null)
+ {
+ $this->appCharset = Configure::read('App.encoding');
+ if ($this->appCharset !== null) {
+ $this->charset = $this->appCharset;
+ }
+ $this->domain = preg_replace('/\:\d+$/', '', (string)env('HTTP_HOST'));
+ if (empty($this->domain)) {
+ $this->domain = php_uname('n');
+ }
+
+ if ($config) {
+ $this->setConfig($config);
+ }
+ }
+
+ /**
+ * Sets "from" address.
+ *
+ * @param string|array $email Null to get, String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setFrom($email, ?string $name = null)
+ {
+ return $this->setEmailSingle('from', $email, $name, 'From requires only 1 email address.');
+ }
+
+ /**
+ * Gets "from" address.
+ *
+ * @return array
+ */
+ public function getFrom(): array
+ {
+ return $this->from;
+ }
+
+ /**
+ * Sets "sender" address.
+ *
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setSender($email, ?string $name = null)
+ {
+ return $this->setEmailSingle('sender', $email, $name, 'Sender requires only 1 email address.');
+ }
+
+ /**
+ * Gets "sender" address.
+ *
+ * @return array
+ */
+ public function getSender(): array
+ {
+ return $this->sender;
+ }
+
+ /**
+ * Sets "Reply-To" address.
+ *
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setReplyTo($email, ?string $name = null)
+ {
+ return $this->setEmailSingle('replyTo', $email, $name, 'Reply-To requires only 1 email address.');
+ }
+
+ /**
+ * Gets "Reply-To" address.
+ *
+ * @return array
+ */
+ public function getReplyTo(): array
+ {
+ return $this->replyTo;
+ }
+
+ /**
+ * Sets Read Receipt (Disposition-Notification-To header).
+ *
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setReadReceipt($email, ?string $name = null)
+ {
+ return $this->setEmailSingle(
+ 'readReceipt',
+ $email,
+ $name,
+ 'Disposition-Notification-To requires only 1 email address.'
+ );
+ }
+
+ /**
+ * Gets Read Receipt (Disposition-Notification-To header).
+ *
+ * @return array
+ */
+ public function getReadReceipt(): array
+ {
+ return $this->readReceipt;
+ }
+
+ /**
+ * Sets return path.
+ *
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setReturnPath($email, ?string $name = null)
+ {
+ return $this->setEmailSingle('returnPath', $email, $name, 'Return-Path requires only 1 email address.');
+ }
+
+ /**
+ * Gets return path.
+ *
+ * @return array
+ */
+ public function getReturnPath(): array
+ {
+ return $this->returnPath;
+ }
+
+ /**
+ * Sets "to" address.
+ *
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ */
+ public function setTo($email, ?string $name = null)
+ {
+ return $this->setEmail('to', $email, $name);
+ }
+
+ /**
+ * Gets "to" address
+ *
+ * @return array
+ */
+ public function getTo(): array
+ {
+ return $this->to;
+ }
+
+ /**
+ * Add "To" address.
+ *
+ * @param string|array $email Null to get, String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ */
+ public function addTo($email, ?string $name = null)
+ {
+ return $this->addEmail('to', $email, $name);
+ }
+
+ /**
+ * Sets "cc" address.
+ *
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ */
+ public function setCc($email, ?string $name = null)
+ {
+ return $this->setEmail('cc', $email, $name);
+ }
+
+ /**
+ * Gets "cc" address.
+ *
+ * @return array
+ */
+ public function getCc(): array
+ {
+ return $this->cc;
+ }
+
+ /**
+ * Add "cc" address.
+ *
+ * @param string|array $email Null to get, String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ */
+ public function addCc($email, ?string $name = null)
+ {
+ return $this->addEmail('cc', $email, $name);
+ }
+
+ /**
+ * Sets "bcc" address.
+ *
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ */
+ public function setBcc($email, ?string $name = null)
+ {
+ return $this->setEmail('bcc', $email, $name);
+ }
+
+ /**
+ * Gets "bcc" address.
+ *
+ * @return array
+ */
+ public function getBcc(): array
+ {
+ return $this->bcc;
+ }
+
+ /**
+ * Add "bcc" address.
+ *
+ * @param string|array $email Null to get, String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ */
+ public function addBcc($email, ?string $name = null)
+ {
+ return $this->addEmail('bcc', $email, $name);
+ }
+
+ /**
+ * Charset setter.
+ *
+ * @param string $charset Character set.
+ * @return $this
+ */
+ public function setCharset(string $charset)
+ {
+ $this->charset = $charset;
+
+ return $this;
+ }
+
+ /**
+ * Charset getter.
+ *
+ * @return string Charset
+ */
+ public function getCharset(): string
+ {
+ return $this->charset;
+ }
+
+ /**
+ * HeaderCharset setter.
+ *
+ * @param string|null $charset Character set.
+ * @return $this
+ */
+ public function setHeaderCharset(?string $charset)
+ {
+ $this->headerCharset = $charset;
+
+ return $this;
+ }
+
+ /**
+ * HeaderCharset getter.
+ *
+ * @return string Charset
+ */
+ public function getHeaderCharset(): string
+ {
+ return $this->headerCharset ?: $this->charset;
+ }
+
+ /**
+ * TransferEncoding setter.
+ *
+ * @param string|null $encoding Encoding set.
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setTransferEncoding(?string $encoding)
+ {
+ if ($encoding !== null) {
+ $encoding = strtolower($encoding);
+ if (!in_array($encoding, $this->transferEncodingAvailable, true)) {
+ throw new InvalidArgumentException(
+ sprintf(
+ 'Transfer encoding not available. Can be : %s.',
+ implode(', ', $this->transferEncodingAvailable)
+ )
+ );
+ }
+ }
+
+ $this->transferEncoding = $encoding;
+
+ return $this;
+ }
+
+ /**
+ * TransferEncoding getter.
+ *
+ * @return string|null Encoding
+ */
+ public function getTransferEncoding(): ?string
+ {
+ return $this->transferEncoding;
+ }
+
+ /**
+ * EmailPattern setter/getter
+ *
+ * @param string|null $regex The pattern to use for email address validation,
+ * null to unset the pattern and make use of filter_var() instead.
+ * @return $this
+ */
+ public function setEmailPattern(?string $regex)
+ {
+ $this->emailPattern = $regex;
+
+ return $this;
+ }
+
+ /**
+ * EmailPattern setter/getter
+ *
+ * @return string|null
+ */
+ public function getEmailPattern(): ?string
+ {
+ return $this->emailPattern;
+ }
+
+ /**
+ * Set email
+ *
+ * @param string $varName Property name
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ protected function setEmail(string $varName, $email, ?string $name)
+ {
+ if (!is_array($email)) {
+ $this->validateEmail($email, $varName);
+ $this->{$varName} = [$email => $name ?? $email];
+
+ return $this;
+ }
+ $list = [];
+ foreach ($email as $key => $value) {
+ if (is_int($key)) {
+ $key = $value;
+ }
+ $this->validateEmail($key, $varName);
+ $list[$key] = $value ?? $key;
+ }
+ $this->{$varName} = $list;
+
+ return $this;
+ }
+
+ /**
+ * Validate email address
+ *
+ * @param string $email Email address to validate
+ * @param string $context Which property was set
+ * @return void
+ * @throws \InvalidArgumentException If email address does not validate
+ */
+ protected function validateEmail(string $email, string $context): void
+ {
+ if ($this->emailPattern === null) {
+ if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
+ return;
+ }
+ } elseif (preg_match($this->emailPattern, (string)$email)) {
+ return;
+ }
+
+ $context = ltrim($context, '_');
+ if ($email === '') {
+ throw new InvalidArgumentException(sprintf('The email set for "%s" is empty.', $context));
+ }
+ throw new InvalidArgumentException(sprintf('Invalid email set for "%s". You passed "%s".', $context, $email));
+ }
+
+ /**
+ * Set only 1 email
+ *
+ * @param string $varName Property name
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @param string $throwMessage Exception message
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ protected function setEmailSingle(string $varName, $email, ?string $name, string $throwMessage)
+ {
+ if ($email === []) {
+ $this->{$varName} = $email;
+
+ return $this;
+ }
+
+ $current = $this->{$varName};
+ $this->setEmail($varName, $email, $name);
+ if (count($this->{$varName}) !== 1) {
+ $this->{$varName} = $current;
+ throw new InvalidArgumentException($throwMessage);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add email
+ *
+ * @param string $varName Property name
+ * @param string|array $email String with email,
+ * Array with email as key, name as value or email as value (without name)
+ * @param string|null $name Name
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ protected function addEmail(string $varName, $email, ?string $name)
+ {
+ if (!is_array($email)) {
+ $this->validateEmail($email, $varName);
+ if ($name === null) {
+ $name = $email;
+ }
+ $this->{$varName}[$email] = $name;
+
+ return $this;
+ }
+ $list = [];
+ foreach ($email as $key => $value) {
+ if (is_int($key)) {
+ $key = $value;
+ }
+ $this->validateEmail($key, $varName);
+ $list[$key] = $value;
+ }
+ $this->{$varName} = array_merge($this->{$varName}, $list);
+
+ return $this;
+ }
+
+ /**
+ * Sets subject.
+ *
+ * @param string $subject Subject string.
+ * @return $this
+ */
+ public function setSubject(string $subject)
+ {
+ $this->subject = $this->encodeForHeader($subject);
+
+ return $this;
+ }
+
+ /**
+ * Gets subject.
+ *
+ * @return string
+ */
+ public function getSubject(): string
+ {
+ return $this->subject;
+ }
+
+ /**
+ * Get original subject without encoding
+ *
+ * @return string Original subject
+ */
+ public function getOriginalSubject(): string
+ {
+ return $this->decodeForHeader($this->subject);
+ }
+
+ /**
+ * Sets headers for the message
+ *
+ * @param array $headers Associative array containing headers to be set.
+ * @return $this
+ */
+ public function setHeaders(array $headers)
+ {
+ $this->headers = $headers;
+
+ return $this;
+ }
+
+ /**
+ * Add header for the message
+ *
+ * @param array $headers Headers to set.
+ * @return $this
+ */
+ public function addHeaders(array $headers)
+ {
+ $this->headers = Hash::merge($this->headers, $headers);
+
+ return $this;
+ }
+
+ /**
+ * Get list of headers
+ *
+ * ### Includes:
+ *
+ * - `from`
+ * - `replyTo`
+ * - `readReceipt`
+ * - `returnPath`
+ * - `to`
+ * - `cc`
+ * - `bcc`
+ * - `subject`
+ *
+ * @param string[] $include List of headers.
+ * @return string[]
+ */
+ public function getHeaders(array $include = []): array
+ {
+ $this->createBoundary();
+
+ if ($include === array_values($include)) {
+ $include = array_fill_keys($include, true);
+ }
+ $defaults = array_fill_keys(
+ [
+ 'from', 'sender', 'replyTo', 'readReceipt', 'returnPath',
+ 'to', 'cc', 'bcc', 'subject',
+ ],
+ false
+ );
+ $include += $defaults;
+
+ $headers = [];
+ $relation = [
+ 'from' => 'From',
+ 'replyTo' => 'Reply-To',
+ 'readReceipt' => 'Disposition-Notification-To',
+ 'returnPath' => 'Return-Path',
+ ];
+ foreach ($relation as $var => $header) {
+ if ($include[$var]) {
+ $headers[$header] = (string)current($this->formatAddress($this->{$var}));
+ }
+ }
+ if ($include['sender']) {
+ if (key($this->sender) === key($this->from)) {
+ $headers['Sender'] = '';
+ } else {
+ $headers['Sender'] = (string)current($this->formatAddress($this->sender));
+ }
+ }
+
+ foreach (['to', 'cc', 'bcc'] as $var) {
+ if ($include[$var]) {
+ $headers[ucfirst($var)] = implode(', ', $this->formatAddress($this->{$var}));
+ }
+ }
+
+ $headers += $this->headers;
+ if (!isset($headers['Date'])) {
+ $headers['Date'] = date(DATE_RFC2822);
+ }
+ if ($this->messageId !== false) {
+ if ($this->messageId === true) {
+ $this->messageId = '<' . str_replace('-', '', Text::uuid()) . '@' . $this->domain . '>';
+ }
+
+ $headers['Message-ID'] = $this->messageId;
+ }
+
+ if ($this->priority) {
+ $headers['X-Priority'] = (string)$this->priority;
+ }
+
+ if ($include['subject']) {
+ $headers['Subject'] = $this->subject;
+ }
+
+ $headers['MIME-Version'] = '1.0';
+ if ($this->attachments) {
+ $headers['Content-Type'] = 'multipart/mixed; boundary="' . (string)$this->boundary . '"';
+ } elseif ($this->emailFormat === static::MESSAGE_BOTH) {
+ $headers['Content-Type'] = 'multipart/alternative; boundary="' . (string)$this->boundary . '"';
+ } elseif ($this->emailFormat === static::MESSAGE_TEXT) {
+ $headers['Content-Type'] = 'text/plain; charset=' . $this->getContentTypeCharset();
+ } elseif ($this->emailFormat === static::MESSAGE_HTML) {
+ $headers['Content-Type'] = 'text/html; charset=' . $this->getContentTypeCharset();
+ }
+ $headers['Content-Transfer-Encoding'] = $this->getContentTransferEncoding();
+
+ return $headers;
+ }
+
+ /**
+ * Get headers as string.
+ *
+ * @param string[] $include List of headers.
+ * @param string $eol End of line string for concatenating headers.
+ * @param \Closure $callback Callback to run each header value through before stringifying.
+ * @return string
+ * @see Message::getHeaders()
+ */
+ public function getHeadersString(array $include = [], string $eol = "\r\n", ?Closure $callback = null): string
+ {
+ $lines = $this->getHeaders($include);
+
+ if ($callback) {
+ $lines = array_map($callback, $lines);
+ }
+
+ $headers = [];
+ foreach ($lines as $key => $value) {
+ if (empty($value) && $value !== '0') {
+ continue;
+ }
+
+ foreach ((array)$value as $val) {
+ $headers[] = $key . ': ' . $val;
+ }
+ }
+
+ return implode($eol, $headers);
+ }
+
+ /**
+ * Format addresses
+ *
+ * If the address contains non alphanumeric/whitespace characters, it will
+ * be quoted as characters like `:` and `,` are known to cause issues
+ * in address header fields.
+ *
+ * @param array $address Addresses to format.
+ * @return array
+ */
+ protected function formatAddress(array $address): array
+ {
+ $return = [];
+ foreach ($address as $email => $alias) {
+ if ($email === $alias) {
+ $return[] = $email;
+ } else {
+ $encoded = $this->encodeForHeader($alias);
+ if ($encoded === $alias && preg_match('/[^a-z0-9 ]/i', $encoded)) {
+ $encoded = '"' . str_replace('"', '\"', $encoded) . '"';
+ }
+ $return[] = sprintf('%s <%s>', $encoded, $email);
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Sets email format.
+ *
+ * @param string $format Formatting string.
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setEmailFormat(string $format)
+ {
+ if (!in_array($format, $this->emailFormatAvailable, true)) {
+ throw new InvalidArgumentException('Format not available.');
+ }
+ $this->emailFormat = $format;
+
+ return $this;
+ }
+
+ /**
+ * Gets email format.
+ *
+ * @return string
+ */
+ public function getEmailFormat(): string
+ {
+ return $this->emailFormat;
+ }
+
+ /**
+ * Gets the body types that are in this email message
+ *
+ * @return array Array of types. Valid types are Email::MESSAGE_TEXT and Email::MESSAGE_HTML
+ */
+ public function getBodyTypes(): array
+ {
+ $format = $this->emailFormat;
+
+ if ($format === static::MESSAGE_BOTH) {
+ return [static::MESSAGE_HTML, static::MESSAGE_TEXT];
+ }
+
+ return [$format];
+ }
+
+ /**
+ * Sets message ID.
+ *
+ * @param bool|string $message True to generate a new Message-ID, False to ignore (not send in email),
+ * String to set as Message-ID.
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setMessageId($message)
+ {
+ if (is_bool($message)) {
+ $this->messageId = $message;
+ } else {
+ if (!preg_match('/^\<.+@.+\>$/', $message)) {
+ throw new InvalidArgumentException(
+ 'Invalid format to Message-ID. The text should be something like ""'
+ );
+ }
+ $this->messageId = $message;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Gets message ID.
+ *
+ * @return bool|string
+ */
+ public function getMessageId()
+ {
+ return $this->messageId;
+ }
+
+ /**
+ * Sets domain.
+ *
+ * Domain as top level (the part after @).
+ *
+ * @param string $domain Manually set the domain for CLI mailing.
+ * @return $this
+ */
+ public function setDomain(string $domain)
+ {
+ $this->domain = $domain;
+
+ return $this;
+ }
+
+ /**
+ * Gets domain.
+ *
+ * @return string
+ */
+ public function getDomain(): string
+ {
+ return $this->domain;
+ }
+
+ /**
+ * Add attachments to the email message
+ *
+ * Attachments can be defined in a few forms depending on how much control you need:
+ *
+ * Attach a single file:
+ *
+ * ```
+ * $this->setAttachments('path/to/file');
+ * ```
+ *
+ * Attach a file with a different filename:
+ *
+ * ```
+ * $this->setAttachments(['custom_name.txt' => 'path/to/file.txt']);
+ * ```
+ *
+ * Attach a file and specify additional properties:
+ *
+ * ```
+ * $this->setAttachments(['custom_name.png' => [
+ * 'file' => 'path/to/file',
+ * 'mimetype' => 'image/png',
+ * 'contentId' => 'abc123',
+ * 'contentDisposition' => false
+ * ]
+ * ]);
+ * ```
+ *
+ * Attach a file from string and specify additional properties:
+ *
+ * ```
+ * $this->setAttachments(['custom_name.png' => [
+ * 'data' => file_get_contents('path/to/file'),
+ * 'mimetype' => 'image/png'
+ * ]
+ * ]);
+ * ```
+ *
+ * The `contentId` key allows you to specify an inline attachment. In your email text, you
+ * can use `
` to display the image inline.
+ *
+ * The `contentDisposition` key allows you to disable the `Content-Disposition` header, this can improve
+ * attachment compatibility with outlook email clients.
+ *
+ * @param array $attachments Array of filenames.
+ * @return $this
+ * @throws \InvalidArgumentException
+ */
+ public function setAttachments(array $attachments)
+ {
+ $attach = [];
+ foreach ($attachments as $name => $fileInfo) {
+ if (!is_array($fileInfo)) {
+ $fileInfo = ['file' => $fileInfo];
+ }
+ if (!isset($fileInfo['file'])) {
+ if (!isset($fileInfo['data'])) {
+ throw new InvalidArgumentException('No file or data specified.');
+ }
+ if (is_int($name)) {
+ throw new InvalidArgumentException('No filename specified.');
+ }
+ $fileInfo['data'] = chunk_split(base64_encode($fileInfo['data']), 76, "\r\n");
+ } elseif ($fileInfo['file'] instanceof UploadedFileInterface) {
+ $fileInfo['mimetype'] = $fileInfo['file']->getClientMediaType();
+ if (is_int($name)) {
+ /** @var string $name */
+ $name = $fileInfo['file']->getClientFilename();
+ }
+ } elseif (is_string($fileInfo['file'])) {
+ $fileName = $fileInfo['file'];
+ $fileInfo['file'] = realpath($fileInfo['file']);
+ if ($fileInfo['file'] === false || !file_exists($fileInfo['file'])) {
+ throw new InvalidArgumentException(sprintf('File not found: "%s"', $fileName));
+ }
+ if (is_int($name)) {
+ $name = basename($fileInfo['file']);
+ }
+ } else {
+ throw new InvalidArgumentException(sprintf(
+ 'File must be a filepath or UploadedFileInterface instance. Found `%s` instead.',
+ gettype($fileInfo['file'])
+ ));
+ }
+ if (
+ !isset($fileInfo['mimetype'])
+ && isset($fileInfo['file'])
+ && is_string($fileInfo['file'])
+ && function_exists('mime_content_type')
+ ) {
+ $fileInfo['mimetype'] = mime_content_type($fileInfo['file']);
+ }
+ if (!isset($fileInfo['mimetype'])) {
+ $fileInfo['mimetype'] = 'application/octet-stream';
+ }
+ $attach[$name] = $fileInfo;
+ }
+ $this->attachments = $attach;
+
+ return $this;
+ }
+
+ /**
+ * Gets attachments to the email message.
+ *
+ * @return array Array of attachments.
+ */
+ public function getAttachments(): array
+ {
+ return $this->attachments;
+ }
+
+ /**
+ * Add attachments
+ *
+ * @param array $attachments Array of filenames.
+ * @return $this
+ * @throws \InvalidArgumentException
+ * @see \Cake\Mailer\Email::setAttachments()
+ */
+ public function addAttachments(array $attachments)
+ {
+ $current = $this->attachments;
+ $this->setAttachments($attachments);
+ $this->attachments = array_merge($current, $this->attachments);
+
+ return $this;
+ }
+
+ /**
+ * Get generated message body as array.
+ *
+ * @return array
+ */
+ public function getBody()
+ {
+ if (empty($this->message)) {
+ $this->message = $this->generateMessage();
+ }
+
+ return $this->message;
+ }
+
+ /**
+ * Get generated body as string.
+ *
+ * @param string $eol End of line string for imploding.
+ * @return string
+ * @see Message::getBody()
+ */
+ public function getBodyString(string $eol = "\r\n"): string
+ {
+ $lines = $this->getBody();
+
+ return implode($eol, $lines);
+ }
+
+ /**
+ * Create unique boundary identifier
+ *
+ * @return void
+ */
+ protected function createBoundary(): void
+ {
+ if (
+ $this->boundary === null &&
+ (
+ $this->attachments ||
+ $this->emailFormat === static::MESSAGE_BOTH
+ )
+ ) {
+ $this->boundary = md5(Security::randomBytes(16));
+ }
+ }
+
+ /**
+ * Generate full message.
+ *
+ * @return string[]
+ */
+ protected function generateMessage(): array
+ {
+ $this->createBoundary();
+ $msg = [];
+
+ $contentIds = array_filter((array)Hash::extract($this->attachments, '{s}.contentId'));
+ $hasInlineAttachments = count($contentIds) > 0;
+ $hasAttachments = !empty($this->attachments);
+ $hasMultipleTypes = $this->emailFormat === static::MESSAGE_BOTH;
+ $multiPart = ($hasAttachments || $hasMultipleTypes);
+
+ /** @var string $boundary */
+ $boundary = $this->boundary;
+ $relBoundary = $textBoundary = $boundary;
+
+ if ($hasInlineAttachments) {
+ $msg[] = '--' . $boundary;
+ $msg[] = 'Content-Type: multipart/related; boundary="rel-' . $boundary . '"';
+ $msg[] = '';
+ $relBoundary = $textBoundary = 'rel-' . $boundary;
+ }
+
+ if ($hasMultipleTypes && $hasAttachments) {
+ $msg[] = '--' . $relBoundary;
+ $msg[] = 'Content-Type: multipart/alternative; boundary="alt-' . $boundary . '"';
+ $msg[] = '';
+ $textBoundary = 'alt-' . $boundary;
+ }
+
+ if (
+ $this->emailFormat === static::MESSAGE_TEXT
+ || $this->emailFormat === static::MESSAGE_BOTH
+ ) {
+ if ($multiPart) {
+ $msg[] = '--' . $textBoundary;
+ $msg[] = 'Content-Type: text/plain; charset=' . $this->getContentTypeCharset();
+ $msg[] = 'Content-Transfer-Encoding: ' . $this->getContentTransferEncoding();
+ $msg[] = '';
+ }
+ $content = explode("\n", $this->textMessage);
+ $msg = array_merge($msg, $content);
+ $msg[] = '';
+ $msg[] = '';
+ }
+
+ if (
+ $this->emailFormat === static::MESSAGE_HTML
+ || $this->emailFormat === static::MESSAGE_BOTH
+ ) {
+ if ($multiPart) {
+ $msg[] = '--' . $textBoundary;
+ $msg[] = 'Content-Type: text/html; charset=' . $this->getContentTypeCharset();
+ $msg[] = 'Content-Transfer-Encoding: ' . $this->getContentTransferEncoding();
+ $msg[] = '';
+ }
+ $content = explode("\n", $this->htmlMessage);
+ $msg = array_merge($msg, $content);
+ $msg[] = '';
+ $msg[] = '';
+ }
+
+ if ($textBoundary !== $relBoundary) {
+ $msg[] = '--' . $textBoundary . '--';
+ $msg[] = '';
+ }
+
+ if ($hasInlineAttachments) {
+ $attachments = $this->attachInlineFiles($relBoundary);
+ $msg = array_merge($msg, $attachments);
+ $msg[] = '';
+ $msg[] = '--' . $relBoundary . '--';
+ $msg[] = '';
+ }
+
+ if ($hasAttachments) {
+ $attachments = $this->attachFiles($boundary);
+ $msg = array_merge($msg, $attachments);
+ }
+ if ($hasAttachments || $hasMultipleTypes) {
+ $msg[] = '';
+ $msg[] = '--' . $boundary . '--';
+ $msg[] = '';
+ }
+
+ return $msg;
+ }
+
+ /**
+ * Attach non-embedded files by adding file contents inside boundaries.
+ *
+ * @param string|null $boundary Boundary to use. If null, will default to $this->boundary
+ * @return string[] An array of lines to add to the message
+ */
+ protected function attachFiles(?string $boundary = null): array
+ {
+ if ($boundary === null) {
+ /** @var string $boundary */
+ $boundary = $this->boundary;
+ }
+
+ $msg = [];
+ foreach ($this->attachments as $filename => $fileInfo) {
+ if (!empty($fileInfo['contentId'])) {
+ continue;
+ }
+ $data = $fileInfo['data'] ?? $this->readFile($fileInfo['file']);
+ $hasDisposition = (
+ !isset($fileInfo['contentDisposition']) ||
+ $fileInfo['contentDisposition']
+ );
+ $part = new FormDataPart('', $data, '', $this->getHeaderCharset());
+
+ if ($hasDisposition) {
+ $part->disposition('attachment');
+ $part->filename($filename);
+ }
+ $part->transferEncoding('base64');
+ $part->type($fileInfo['mimetype']);
+
+ $msg[] = '--' . $boundary;
+ $msg[] = (string)$part;
+ $msg[] = '';
+ }
+
+ return $msg;
+ }
+
+ /**
+ * Attach inline/embedded files to the message.
+ *
+ * @param string|null $boundary Boundary to use. If null, will default to $this->boundary
+ * @return string[] An array of lines to add to the message
+ */
+ protected function attachInlineFiles(?string $boundary = null): array
+ {
+ if ($boundary === null) {
+ /** @var string $boundary */
+ $boundary = $this->boundary;
+ }
+
+ $msg = [];
+ foreach ($this->getAttachments() as $filename => $fileInfo) {
+ if (empty($fileInfo['contentId'])) {
+ continue;
+ }
+ $data = $fileInfo['data'] ?? $this->readFile($fileInfo['file']);
+
+ $msg[] = '--' . $boundary;
+ $part = new FormDataPart('', $data, 'inline', $this->getHeaderCharset());
+ $part->type($fileInfo['mimetype']);
+ $part->transferEncoding('base64');
+ $part->contentId($fileInfo['contentId']);
+ $part->filename($filename);
+ $msg[] = (string)$part;
+ $msg[] = '';
+ }
+
+ return $msg;
+ }
+
+ /**
+ * Sets priority.
+ *
+ * @param int|null $priority 1 (highest) to 5 (lowest)
+ * @return $this
+ */
+ public function setPriority(?int $priority)
+ {
+ $this->priority = $priority;
+
+ return $this;
+ }
+
+ /**
+ * Gets priority.
+ *
+ * @return int|null
+ */
+ public function getPriority(): ?int
+ {
+ return $this->priority;
+ }
+
+ /**
+ * Sets the configuration for this instance.
+ *
+ * @param array $config Config array.
+ * @return $this
+ */
+ public function setConfig(array $config)
+ {
+ $simpleMethods = [
+ 'from', 'sender', 'to', 'replyTo', 'readReceipt', 'returnPath',
+ 'cc', 'bcc', 'messageId', 'domain', 'subject', 'attachments',
+ 'emailFormat', 'emailPattern', 'charset', 'headerCharset',
+ ];
+ foreach ($simpleMethods as $method) {
+ if (isset($config[$method])) {
+ $this->{'set' . ucfirst($method)}($config[$method]);
+ }
+ }
+
+ if (isset($config['headers'])) {
+ $this->setHeaders($config['headers']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set message body.
+ *
+ * @param array $content Content array with keys "text" and/or "html" with
+ * content string of respective type.
+ * @return $this
+ */
+ public function setBody(array $content)
+ {
+ foreach ($content as $type => $text) {
+ if (!in_array($type, $this->emailFormatAvailable, true)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid message type: "%s". Valid types are: "text", "html".',
+ $type
+ ));
+ }
+
+ $text = str_replace(["\r\n", "\r"], "\n", $text);
+ $text = $this->encodeString($text, $this->getCharset());
+ $text = $this->wrap($text);
+ $text = implode("\n", $text);
+ $text = rtrim($text, "\n");
+
+ $property = "{$type}Message";
+ $this->$property = $text;
+ }
+
+ $this->boundary = null;
+ $this->message = [];
+
+ return $this;
+ }
+
+ /**
+ * Set text body for message.
+ *
+ * @param string $content Content string
+ * @return $this
+ */
+ public function setBodyText(string $content)
+ {
+ $this->setBody([static::MESSAGE_TEXT => $content]);
+
+ return $this;
+ }
+
+ /**
+ * Set HTML body for message.
+ *
+ * @param string $content Content string
+ * @return $this
+ */
+ public function setBodyHtml(string $content)
+ {
+ $this->setBody([static::MESSAGE_HTML => $content]);
+
+ return $this;
+ }
+
+ /**
+ * Get text body of message.
+ *
+ * @return string
+ */
+ public function getBodyText()
+ {
+ return $this->textMessage;
+ }
+
+ /**
+ * Get HTML body of message.
+ *
+ * @return string
+ */
+ public function getBodyHtml()
+ {
+ return $this->htmlMessage;
+ }
+
+ /**
+ * Translates a string for one charset to another if the App.encoding value
+ * differs and the mb_convert_encoding function exists
+ *
+ * @param string $text The text to be converted
+ * @param string $charset the target encoding
+ * @return string
+ */
+ protected function encodeString(string $text, string $charset): string
+ {
+ if ($this->appCharset === $charset) {
+ return $text;
+ }
+
+ if ($this->appCharset === null) {
+ return mb_convert_encoding($text, $charset);
+ }
+
+ return mb_convert_encoding($text, $charset, $this->appCharset);
+ }
+
+ /**
+ * Wrap the message to follow the RFC 2822 - 2.1.1
+ *
+ * @param string|null $message Message to wrap
+ * @param int $wrapLength The line length
+ * @return array Wrapped message
+ */
+ protected function wrap(?string $message = null, int $wrapLength = self::LINE_LENGTH_MUST): array
+ {
+ if ($message === null || strlen($message) === 0) {
+ return [''];
+ }
+ $message = str_replace(["\r\n", "\r"], "\n", $message);
+ $lines = explode("\n", $message);
+ $formatted = [];
+ $cut = ($wrapLength === static::LINE_LENGTH_MUST);
+
+ foreach ($lines as $line) {
+ if (empty($line) && $line !== '0') {
+ $formatted[] = '';
+ continue;
+ }
+ if (strlen($line) < $wrapLength) {
+ $formatted[] = $line;
+ continue;
+ }
+ if (!preg_match('/<[a-z]+.*>/i', $line)) {
+ $formatted = array_merge(
+ $formatted,
+ explode("\n", Text::wordWrap($line, $wrapLength, "\n", $cut))
+ );
+ continue;
+ }
+
+ $tagOpen = false;
+ $tmpLine = $tag = '';
+ $tmpLineLength = 0;
+ for ($i = 0, $count = strlen($line); $i < $count; $i++) {
+ $char = $line[$i];
+ if ($tagOpen) {
+ $tag .= $char;
+ if ($char === '>') {
+ $tagLength = strlen($tag);
+ if ($tagLength + $tmpLineLength < $wrapLength) {
+ $tmpLine .= $tag;
+ $tmpLineLength += $tagLength;
+ } else {
+ if ($tmpLineLength > 0) {
+ $formatted = array_merge(
+ $formatted,
+ explode("\n", Text::wordWrap(trim($tmpLine), $wrapLength, "\n", $cut))
+ );
+ $tmpLine = '';
+ $tmpLineLength = 0;
+ }
+ if ($tagLength > $wrapLength) {
+ $formatted[] = $tag;
+ } else {
+ $tmpLine = $tag;
+ $tmpLineLength = $tagLength;
+ }
+ }
+ $tag = '';
+ $tagOpen = false;
+ }
+ continue;
+ }
+ if ($char === '<') {
+ $tagOpen = true;
+ $tag = '<';
+ continue;
+ }
+ if ($char === ' ' && $tmpLineLength >= $wrapLength) {
+ $formatted[] = $tmpLine;
+ $tmpLineLength = 0;
+ continue;
+ }
+ $tmpLine .= $char;
+ $tmpLineLength++;
+ if ($tmpLineLength === $wrapLength) {
+ $nextChar = $line[$i + 1] ?? '';
+ if ($nextChar === ' ' || $nextChar === '<') {
+ $formatted[] = trim($tmpLine);
+ $tmpLine = '';
+ $tmpLineLength = 0;
+ if ($nextChar === ' ') {
+ $i++;
+ }
+ } else {
+ $lastSpace = strrpos($tmpLine, ' ');
+ if ($lastSpace === false) {
+ continue;
+ }
+ $formatted[] = trim(substr($tmpLine, 0, $lastSpace));
+ $tmpLine = substr($tmpLine, $lastSpace + 1);
+
+ $tmpLineLength = strlen($tmpLine);
+ }
+ }
+ }
+ if (!empty($tmpLine)) {
+ $formatted[] = $tmpLine;
+ }
+ }
+ $formatted[] = '';
+
+ return $formatted;
+ }
+
+ /**
+ * Reset all the internal variables to be able to send out a new email.
+ *
+ * @return $this
+ */
+ public function reset()
+ {
+ $this->to = [];
+ $this->from = [];
+ $this->sender = [];
+ $this->replyTo = [];
+ $this->readReceipt = [];
+ $this->returnPath = [];
+ $this->cc = [];
+ $this->bcc = [];
+ $this->messageId = true;
+ $this->subject = '';
+ $this->headers = [];
+ $this->textMessage = '';
+ $this->htmlMessage = '';
+ $this->message = [];
+ $this->emailFormat = static::MESSAGE_TEXT;
+ $this->priority = null;
+ $this->charset = 'utf-8';
+ $this->headerCharset = null;
+ $this->transferEncoding = null;
+ $this->attachments = [];
+ $this->emailPattern = static::EMAIL_PATTERN;
+
+ return $this;
+ }
+
+ /**
+ * Encode the specified string using the current charset
+ *
+ * @param string $text String to encode
+ * @return string Encoded string
+ */
+ protected function encodeForHeader(string $text): string
+ {
+ if ($this->appCharset === null) {
+ return $text;
+ }
+
+ /** @var string $restore */
+ $restore = mb_internal_encoding();
+ mb_internal_encoding($this->appCharset);
+ $return = mb_encode_mimeheader($text, $this->getHeaderCharset(), 'B');
+ mb_internal_encoding($restore);
+
+ return $return;
+ }
+
+ /**
+ * Decode the specified string
+ *
+ * @param string $text String to decode
+ * @return string Decoded string
+ */
+ protected function decodeForHeader(string $text): string
+ {
+ if ($this->appCharset === null) {
+ return $text;
+ }
+
+ /** @var string $restore */
+ $restore = mb_internal_encoding();
+ mb_internal_encoding($this->appCharset);
+ $return = mb_decode_mimeheader($text);
+ mb_internal_encoding($restore);
+
+ return $return;
+ }
+
+ /**
+ * Read the file contents and return a base64 version of the file contents.
+ *
+ * @param string|\Psr\Http\Message\UploadedFileInterface $file The absolute path to the file to read
+ * or UploadedFileInterface instance.
+ * @return string File contents in base64 encoding
+ */
+ protected function readFile($file): string
+ {
+ if (is_string($file)) {
+ $content = (string)file_get_contents($file);
+ } else {
+ $content = (string)$file->getStream();
+ }
+
+ return chunk_split(base64_encode($content));
+ }
+
+ /**
+ * Return the Content-Transfer Encoding value based
+ * on the set transferEncoding or set charset.
+ *
+ * @return string
+ */
+ public function getContentTransferEncoding(): string
+ {
+ if ($this->transferEncoding) {
+ return $this->transferEncoding;
+ }
+
+ $charset = strtoupper($this->charset);
+ if (in_array($charset, $this->charset8bit, true)) {
+ return '8bit';
+ }
+
+ return '7bit';
+ }
+
+ /**
+ * Return charset value for Content-Type.
+ *
+ * Checks fallback/compatibility types which include workarounds
+ * for legacy japanese character sets.
+ *
+ * @return string
+ */
+ public function getContentTypeCharset(): string
+ {
+ $charset = strtoupper($this->charset);
+ if (array_key_exists($charset, $this->contentTypeCharset)) {
+ return strtoupper($this->contentTypeCharset[$charset]);
+ }
+
+ return strtoupper($this->charset);
+ }
+
+ /**
+ * Serializes the email object to a value that can be natively serialized and re-used
+ * to clone this email instance.
+ *
+ * @return array Serializable array of configuration properties.
+ * @throws \Exception When a view var object can not be properly serialized.
+ */
+ public function jsonSerialize(): array
+ {
+ $properties = [
+ 'to', 'from', 'sender', 'replyTo', 'cc', 'bcc', 'subject',
+ 'returnPath', 'readReceipt', 'emailFormat', 'emailPattern', 'domain',
+ 'attachments', 'messageId', 'headers', 'appCharset', 'charset', 'headerCharset',
+ ];
+
+ $array = [];
+ foreach ($properties as $property) {
+ $array[$property] = $this->{$property};
+ }
+
+ array_walk($array['attachments'], function (&$item, $key): void {
+ if (!empty($item['file'])) {
+ $item['data'] = $this->readFile($item['file']);
+ unset($item['file']);
+ }
+ });
+
+ return array_filter($array, function ($i) {
+ return $i !== null && !is_array($i) && !is_bool($i) && strlen($i) || !empty($i);
+ });
+ }
+
+ /**
+ * Configures an email instance object from serialized config.
+ *
+ * @param array $config Email configuration array.
+ * @return $this Configured email instance.
+ */
+ public function createFromArray(array $config)
+ {
+ foreach ($config as $property => $value) {
+ $this->{$property} = $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Serializes the Email object.
+ *
+ * @return string
+ */
+ public function serialize(): string
+ {
+ $array = $this->jsonSerialize();
+ array_walk_recursive($array, function (&$item, $key): void {
+ if ($item instanceof SimpleXMLElement) {
+ $item = json_decode(json_encode((array)$item), true);
+ }
+ });
+
+ return serialize($array);
+ }
+
+ /**
+ * Unserializes the Email object.
+ *
+ * @param string $data Serialized string.
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ $array = unserialize($data);
+ if (!is_array($array)) {
+ throw new Exception('Unable to unserialize message.');
+ }
+
+ $this->createFromArray($array);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Renderer.php b/app/vendor/cakephp/cakephp/src/Mailer/Renderer.php
new file mode 100644
index 000000000..566418d1b
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Renderer.php
@@ -0,0 +1,120 @@
+reset();
+ }
+
+ /**
+ * Render text/HTML content.
+ *
+ * If there is no template set, the $content will be returned in a hash
+ * of the specified content types for the email.
+ *
+ * @param string $content The content.
+ * @param string[] $types Content types to render. Valid array values are Message::MESSAGE_HTML, Message::MESSAGE_TEXT.
+ * @return array The rendered content with "html" and/or "text" keys.
+ * @psalm-param (\Cake\Mailer\Message::MESSAGE_HTML|\Cake\Mailer\Message::MESSAGE_TEXT)[] $types
+ * @psalm-return array{html?: string, text?: string}
+ */
+ public function render(string $content, array $types = []): array
+ {
+ $rendered = [];
+ $template = $this->viewBuilder()->getTemplate();
+ if (empty($template)) {
+ foreach ($types as $type) {
+ $rendered[$type] = $content;
+ }
+
+ return $rendered;
+ }
+
+ $view = $this->createView();
+
+ [$templatePlugin] = pluginSplit($view->getTemplate());
+ [$layoutPlugin] = pluginSplit((string)$view->getLayout());
+ if ($templatePlugin) {
+ $view->setPlugin($templatePlugin);
+ } elseif ($layoutPlugin) {
+ $view->setPlugin($layoutPlugin);
+ }
+
+ if ($view->get('content') === null) {
+ $view->set('content', $content);
+ }
+
+ foreach ($types as $type) {
+ $view->setTemplatePath(static::TEMPLATE_FOLDER . DIRECTORY_SEPARATOR . $type);
+ $view->setLayoutPath(static::TEMPLATE_FOLDER . DIRECTORY_SEPARATOR . $type);
+
+ $rendered[$type] = $view->render();
+ }
+
+ return $rendered;
+ }
+
+ /**
+ * Reset view builder to defaults.
+ *
+ * @return $this
+ */
+ public function reset()
+ {
+ $this->_viewBuilder = null;
+
+ $this->viewBuilder()
+ ->setClassName(View::class)
+ ->setLayout('default')
+ ->setHelpers(['Html'], false);
+
+ return $this;
+ }
+
+ /**
+ * Clone ViewBuilder instance when renderer is cloned.
+ *
+ * @return void
+ */
+ public function __clone()
+ {
+ if ($this->_viewBuilder !== null) {
+ $this->_viewBuilder = clone $this->_viewBuilder;
+ }
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Transport/DebugTransport.php b/app/vendor/cakephp/cakephp/src/Mailer/Transport/DebugTransport.php
index e93f6be47..b73ce77bd 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Transport/DebugTransport.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Transport/DebugTransport.php
@@ -1,6 +1,8 @@
getHeaders(['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'subject']);
- $headers = $this->_headersToString($headers);
- $message = implode("\r\n", (array)$email->message());
+ $headers = $message->getHeadersString(
+ ['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'subject']
+ );
+ $message = implode("\r\n", (array)$message->getBody());
return ['headers' => $headers, 'message' => $message];
}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Transport/MailTransport.php b/app/vendor/cakephp/cakephp/src/Mailer/Transport/MailTransport.php
index 1916a3cf9..391985828 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Transport/MailTransport.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Transport/MailTransport.php
@@ -1,4 +1,6 @@
_config['eol'])) {
- $eol = $this->_config['eol'];
- }
- $headers = $email->getHeaders(['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc']);
- $to = $headers['To'];
- unset($headers['To']);
- foreach ($headers as $key => $header) {
- $headers[$key] = str_replace(["\r", "\n"], '', $header);
- }
- $headers = $this->_headersToString($headers, $eol);
- $subject = str_replace(["\r", "\n"], '', $email->getSubject());
- $to = str_replace(["\r", "\n"], '', $to);
+ $this->checkRecipient($message);
- $message = implode($eol, $email->message());
+ // https://github.com/cakephp/cakephp/issues/2209
+ // https://bugs.php.net/bug.php?id=47983
+ $subject = str_replace("\r\n", '', $message->getSubject());
- $params = isset($this->_config['additionalParameters']) ? $this->_config['additionalParameters'] : null;
+ $to = $message->getHeaders(['to'])['To'];
+ $to = str_replace("\r\n", '', $to);
+
+ $eol = $this->getConfig('eol', PHP_EOL);
+ $headers = $message->getHeadersString(
+ [
+ 'from',
+ 'sender',
+ 'replyTo',
+ 'readReceipt',
+ 'returnPath',
+ 'cc',
+ 'bcc',
+ ],
+ $eol,
+ function ($val) {
+ return str_replace("\r\n", '', $val);
+ }
+ );
+
+ $message = $message->getBodyString($eol);
+
+ $params = $this->getConfig('additionalParameters', '');
$this->_mail($to, $subject, $message, $headers, $params);
$headers .= $eol . 'To: ' . $to;
@@ -65,18 +76,23 @@ public function send(Email $email)
* @param string $subject email's subject
* @param string $message email's body
* @param string $headers email's custom headers
- * @param string|null $params additional params for sending email
+ * @param string $params additional params for sending email
* @throws \Cake\Network\Exception\SocketException if mail could not be sent
* @return void
*/
- protected function _mail($to, $subject, $message, $headers, $params = null)
- {
- //@codingStandardsIgnoreStart
+ protected function _mail(
+ string $to,
+ string $subject,
+ string $message,
+ string $headers = '',
+ string $params = ''
+ ): void {
+ // phpcs:disable
if (!@mail($to, $subject, $message, $headers, $params)) {
$error = error_get_last();
- $msg = 'Could not send email: ' . (isset($error['message']) ? $error['message'] : 'unknown');
- throw new SocketException($msg);
+ $msg = 'Could not send email: ' . ($error['message'] ?? 'unknown');
+ throw new Exception($msg);
}
- //@codingStandardsIgnoreEnd
+ // phpcs:enable
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php b/app/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php
index 4df6382e1..2ea6dcd77 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php
@@ -1,4 +1,6 @@
_socket = null;
}
@@ -97,7 +99,7 @@ public function __wakeup()
*
* @return void
*/
- public function connect()
+ public function connect(): void
{
if (!$this->connected()) {
$this->_connect();
@@ -110,7 +112,7 @@ public function connect()
*
* @return bool
*/
- public function connected()
+ public function connected(): bool
{
return $this->_socket !== null && $this->_socket->connected;
}
@@ -123,11 +125,13 @@ public function connected()
*
* @return void
*/
- public function disconnect()
+ public function disconnect(): void
{
- if ($this->connected()) {
- $this->_disconnect();
+ if (!$this->connected()) {
+ return;
}
+
+ $this->_disconnect();
}
/**
@@ -155,7 +159,7 @@ public function disconnect()
*
* @return array
*/
- public function getLastResponse()
+ public function getLastResponse(): array
{
return $this->_lastResponse;
}
@@ -163,12 +167,15 @@ public function getLastResponse()
/**
* Send mail
*
- * @param \Cake\Mailer\Email $email Email instance
+ * @param \Cake\Mailer\Message $message Message instance
* @return array
* @throws \Cake\Network\Exception\SocketException
+ * @psalm-return array{headers: string, message: string}
*/
- public function send(Email $email)
+ public function send(Message $message): array
{
+ $this->checkRecipient($message);
+
if (!$this->connected()) {
$this->_connect();
$this->_auth();
@@ -176,8 +183,8 @@ public function send(Email $email)
$this->_smtpSend('RSET');
}
- $this->_sendRcpt($email);
- $this->_sendData($email);
+ $this->_sendRcpt($message);
+ $this->_sendData($message);
if (!$this->_config['keepAlive']) {
$this->_disconnect();
@@ -192,14 +199,14 @@ public function send(Email $email)
* @param string[] $responseLines Response lines to parse.
* @return void
*/
- protected function _bufferResponseLines(array $responseLines)
+ protected function _bufferResponseLines(array $responseLines): void
{
$response = [];
foreach ($responseLines as $responseLine) {
if (preg_match('/^(\d{3})(?:[ -]+(.*))?$/', $responseLine, $match)) {
$response[] = [
'code' => $match[1],
- 'message' => isset($match[2]) ? $match[2] : null,
+ 'message' => $match[2] ?? null,
];
}
}
@@ -212,34 +219,41 @@ protected function _bufferResponseLines(array $responseLines)
* @return void
* @throws \Cake\Network\Exception\SocketException
*/
- protected function _connect()
+ protected function _connect(): void
{
$this->_generateSocket();
- if (!$this->_socket->connect()) {
+ if (!$this->_socket()->connect()) {
throw new SocketException('Unable to connect to SMTP server.');
}
$this->_smtpSend(null, '220');
$config = $this->_config;
+ $host = 'localhost';
if (isset($config['client'])) {
$host = $config['client'];
- } elseif ($httpHost = env('HTTP_HOST')) {
- list($host) = explode(':', $httpHost);
} else {
- $host = 'localhost';
+ /** @var string $httpHost */
+ $httpHost = env('HTTP_HOST');
+ if ($httpHost) {
+ [$host] = explode(':', $httpHost);
+ }
}
try {
$this->_smtpSend("EHLO {$host}", '250');
if ($config['tls']) {
$this->_smtpSend('STARTTLS', '220');
- $this->_socket->enableCrypto('tls');
+ $this->_socket()->enableCrypto('tls');
$this->_smtpSend("EHLO {$host}", '250');
}
} catch (SocketException $e) {
if ($config['tls']) {
- throw new SocketException('SMTP server did not accept the connection or trying to connect to non TLS SMTP server using TLS.', null, $e);
+ throw new SocketException(
+ 'SMTP server did not accept the connection or trying to connect to non TLS SMTP server using TLS.',
+ null,
+ $e
+ );
}
try {
$this->_smtpSend("HELO {$host}", '250');
@@ -255,7 +269,7 @@ protected function _connect()
* @return void
* @throws \Cake\Network\Exception\SocketException
*/
- protected function _auth()
+ protected function _auth(): void
{
if (!isset($this->_config['username'], $this->_config['password'])) {
return;
@@ -279,7 +293,7 @@ protected function _auth()
* @param string $password Password.
* @return string|null Response code for the command.
*/
- protected function _authPlain($username, $password)
+ protected function _authPlain(string $username, string $password): ?string
{
return $this->_smtpSend(
sprintf(
@@ -297,7 +311,7 @@ protected function _authPlain($username, $password)
* @param string $password Password.
* @return void
*/
- protected function _authLogin($username, $password)
+ protected function _authLogin(string $username, string $password): void
{
$replyCode = $this->_smtpSend('AUTH LOGIN', '334|500|502|504');
if ($replyCode === '334') {
@@ -323,36 +337,36 @@ protected function _authLogin($username, $password)
/**
* Prepares the `MAIL FROM` SMTP command.
*
- * @param string $email The email address to send with the command.
+ * @param string $message The email address to send with the command.
* @return string
*/
- protected function _prepareFromCmd($email)
+ protected function _prepareFromCmd(string $message): string
{
- return 'MAIL FROM:<' . $email . '>';
+ return 'MAIL FROM:<' . $message . '>';
}
/**
* Prepares the `RCPT TO` SMTP command.
*
- * @param string $email The email address to send with the command.
+ * @param string $message The email address to send with the command.
* @return string
*/
- protected function _prepareRcptCmd($email)
+ protected function _prepareRcptCmd(string $message): string
{
- return 'RCPT TO:<' . $email . '>';
+ return 'RCPT TO:<' . $message . '>';
}
/**
* Prepares the `from` email address.
*
- * @param \Cake\Mailer\Email $email Email instance
+ * @param \Cake\Mailer\Message $message Message instance
* @return array
*/
- protected function _prepareFromAddress($email)
+ protected function _prepareFromAddress(Message $message): array
{
- $from = $email->getReturnPath();
+ $from = $message->getReturnPath();
if (empty($from)) {
- $from = $email->getFrom();
+ $from = $message->getFrom();
}
return $from;
@@ -361,38 +375,27 @@ protected function _prepareFromAddress($email)
/**
* Prepares the recipient email addresses.
*
- * @param \Cake\Mailer\Email $email Email instance
+ * @param \Cake\Mailer\Message $message Message instance
* @return array
*/
- protected function _prepareRecipientAddresses($email)
+ protected function _prepareRecipientAddresses(Message $message): array
{
- $to = $email->getTo();
- $cc = $email->getCc();
- $bcc = $email->getBcc();
+ $to = $message->getTo();
+ $cc = $message->getCc();
+ $bcc = $message->getBcc();
return array_merge(array_keys($to), array_keys($cc), array_keys($bcc));
}
- /**
- * Prepares the message headers.
- *
- * @param \Cake\Mailer\Email $email Email instance
- * @return array
- */
- protected function _prepareMessageHeaders($email)
- {
- return $email->getHeaders(['from', 'sender', 'replyTo', 'readReceipt', 'to', 'cc', 'subject', 'returnPath']);
- }
-
/**
* Prepares the message body.
*
- * @param \Cake\Mailer\Email $email Email instance
+ * @param \Cake\Mailer\Message $message Message instance
* @return string
*/
- protected function _prepareMessage($email)
+ protected function _prepareMessage(Message $message): string
{
- $lines = $email->message();
+ $lines = $message->getBody();
$messages = [];
foreach ($lines as $line) {
if (!empty($line) && ($line[0] === '.')) {
@@ -408,17 +411,17 @@ protected function _prepareMessage($email)
/**
* Send emails
*
- * @return void
- * @param \Cake\Mailer\Email $email Cake Email
+ * @param \Cake\Mailer\Message $message Message message
* @throws \Cake\Network\Exception\SocketException
+ * @return void
*/
- protected function _sendRcpt($email)
+ protected function _sendRcpt(Message $message): void
{
- $from = $this->_prepareFromAddress($email);
+ $from = $this->_prepareFromAddress($message);
$this->_smtpSend($this->_prepareFromCmd(key($from)));
- $emails = $this->_prepareRecipientAddresses($email);
- foreach ($emails as $mail) {
+ $messages = $this->_prepareRecipientAddresses($message);
+ foreach ($messages as $mail) {
$this->_smtpSend($this->_prepareRcptCmd($mail));
}
}
@@ -426,16 +429,25 @@ protected function _sendRcpt($email)
/**
* Send Data
*
- * @param \Cake\Mailer\Email $email Email instance
+ * @param \Cake\Mailer\Message $message Message message
* @return void
* @throws \Cake\Network\Exception\SocketException
*/
- protected function _sendData($email)
+ protected function _sendData(Message $message): void
{
$this->_smtpSend('DATA', '354');
- $headers = $this->_headersToString($this->_prepareMessageHeaders($email));
- $message = $this->_prepareMessage($email);
+ $headers = $message->getHeadersString([
+ 'from',
+ 'sender',
+ 'replyTo',
+ 'readReceipt',
+ 'to',
+ 'cc',
+ 'subject',
+ 'returnPath',
+ ]);
+ $message = $this->_prepareMessage($message);
$this->_smtpSend($headers . "\r\n\r\n" . $message . "\r\n\r\n\r\n.");
$this->_content = ['headers' => $headers, 'message' => $message];
@@ -447,10 +459,10 @@ protected function _sendData($email)
* @return void
* @throws \Cake\Network\Exception\SocketException
*/
- protected function _disconnect()
+ protected function _disconnect(): void
{
$this->_smtpSend('QUIT', false);
- $this->_socket->disconnect();
+ $this->_socket()->disconnect();
}
/**
@@ -459,7 +471,7 @@ protected function _disconnect()
* @return void
* @throws \Cake\Network\Exception\SocketException
*/
- protected function _generateSocket()
+ protected function _generateSocket(): void
{
$this->_socket = new Socket($this->_config);
}
@@ -472,12 +484,12 @@ protected function _generateSocket()
* @return string|null The matched code, or null if nothing matched
* @throws \Cake\Network\Exception\SocketException
*/
- protected function _smtpSend($data, $checkCode = '250')
+ protected function _smtpSend(?string $data, $checkCode = '250'): ?string
{
$this->_lastResponse = [];
if ($data !== null) {
- $this->_socket->write($data . "\r\n");
+ $this->_socket()->write($data . "\r\n");
}
$timeout = $this->_config['timeout'];
@@ -485,15 +497,17 @@ protected function _smtpSend($data, $checkCode = '250')
while ($checkCode !== false) {
$response = '';
$startTime = time();
- while (substr($response, -2) !== "\r\n" && ((time() - $startTime) < $timeout)) {
- $bytes = $this->_socket->read();
- if ($bytes === false || $bytes === null) {
+ while (substr($response, -2) !== "\r\n" && (time() - $startTime < $timeout)) {
+ $bytes = $this->_socket()->read();
+ if ($bytes === null) {
break;
}
$response .= $bytes;
}
+ // Catch empty or malformed responses.
if (substr($response, -2) !== "\r\n") {
- throw new SocketException('SMTP timeout.');
+ // Use response message or assume operation timed out.
+ throw new SocketException($response ?: 'SMTP timeout.');
}
$responseLines = explode("\r\n", rtrim($response, "\r\n"));
$response = end($responseLines);
@@ -509,5 +523,22 @@ protected function _smtpSend($data, $checkCode = '250')
}
throw new SocketException(sprintf('SMTP Error: %s', $response));
}
+
+ return null;
+ }
+
+ /**
+ * Get socket instance.
+ *
+ * @return \Cake\Network\Socket
+ * @throws \RuntimeException If socket is not set.
+ */
+ protected function _socket(): Socket
+ {
+ if ($this->_socket === null) {
+ throw new \RuntimeException('Socket is null, but must be set.');
+ }
+
+ return $this->_socket;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/TransportFactory.php b/app/vendor/cakephp/cakephp/src/Mailer/TransportFactory.php
index 633289ad8..f90fc12c6 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/TransportFactory.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/TransportFactory.php
@@ -1,4 +1,6 @@
*/
protected static $_dsnClassMap = [
- 'debug' => 'Cake\Mailer\Transport\DebugTransport',
- 'mail' => 'Cake\Mailer\Transport\MailTransport',
- 'smtp' => 'Cake\Mailer\Transport\SmtpTransport',
+ 'debug' => Transport\DebugTransport::class,
+ 'mail' => Transport\MailTransport::class,
+ 'smtp' => Transport\SmtpTransport::class,
];
/**
@@ -47,9 +50,9 @@ class TransportFactory
*
* @return \Cake\Mailer\TransportRegistry
*/
- public static function getRegistry()
+ public static function getRegistry(): TransportRegistry
{
- if (!static::$_registry) {
+ if (static::$_registry === null) {
static::$_registry = new TransportRegistry();
}
@@ -64,7 +67,7 @@ public static function getRegistry()
* @param \Cake\Mailer\TransportRegistry $registry Injectable registry object.
* @return void
*/
- public static function setRegistry(TransportRegistry $registry)
+ public static function setRegistry(TransportRegistry $registry): void
{
static::$_registry = $registry;
}
@@ -76,7 +79,7 @@ public static function setRegistry(TransportRegistry $registry)
* @return void
* @throws \InvalidArgumentException When a tranport cannot be created.
*/
- protected static function _buildTransport($name)
+ protected static function _buildTransport(string $name): void
{
if (!isset(static::$_config[$name])) {
throw new InvalidArgumentException(
@@ -99,7 +102,7 @@ protected static function _buildTransport($name)
* @param string $name Config name.
* @return \Cake\Mailer\AbstractTransport
*/
- public static function get($name)
+ public static function get(string $name): AbstractTransport
{
$registry = static::getRegistry();
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/TransportRegistry.php b/app/vendor/cakephp/cakephp/src/Mailer/TransportRegistry.php
index a2ededa03..cba1594e9 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/TransportRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/TransportRegistry.php
@@ -1,4 +1,6 @@
*/
class TransportRegistry extends ObjectRegistry
{
@@ -29,27 +33,13 @@ class TransportRegistry extends ObjectRegistry
*
* Part of the template method for Cake\Core\ObjectRegistry::load()
*
- * @param string|\Cake\Mailer\AbstractTransport $class Partial classname to resolve or transport instance.
- * @return string|false Either the correct classname or false.
+ * @param string $class Partial classname to resolve or transport instance.
+ * @return string|null Either the correct classname or null.
+ * @psalm-return class-string|null
*/
- protected function _resolveClassName($class)
+ protected function _resolveClassName(string $class): ?string
{
- if (is_object($class)) {
- return $class;
- }
-
- $className = App::className($class, 'Mailer/Transport', 'Transport');
-
- if (!$className) {
- $className = App::className($class, 'Network/Email', 'Transport');
- if ($className) {
- deprecationWarning(
- 'Transports in "Network/Email" are deprecated, use "Mailer/Transport" instead.'
- );
- }
- }
-
- return $className;
+ return App::className($class, 'Mailer/Transport', 'Transport');
}
/**
@@ -62,7 +52,7 @@ protected function _resolveClassName($class)
* @return void
* @throws \BadMethodCallException
*/
- protected function _throwMissingClassError($class, $plugin)
+ protected function _throwMissingClassError(string $class, ?string $plugin): void
{
throw new BadMethodCallException(sprintf('Mailer transport %s is not available.', $class));
}
@@ -78,15 +68,11 @@ protected function _throwMissingClassError($class, $plugin)
* @return \Cake\Mailer\AbstractTransport The constructed transport class.
* @throws \RuntimeException when an object doesn't implement the correct interface.
*/
- protected function _create($class, $alias, $config)
+ protected function _create($class, string $alias, array $config): AbstractTransport
{
- $instance = null;
-
if (is_object($class)) {
$instance = $class;
- }
-
- if (!$instance) {
+ } else {
$instance = new $class($config);
}
@@ -105,7 +91,7 @@ protected function _create($class, $alias, $config)
* @param string $name The adapter name.
* @return $this
*/
- public function unload($name)
+ public function unload(string $name)
{
unset($this->_loaded[$name]);
diff --git a/app/vendor/cakephp/cakephp/src/Network/CorsBuilder.php b/app/vendor/cakephp/cakephp/src/Network/CorsBuilder.php
deleted file mode 100644
index 57ce28b9d..000000000
--- a/app/vendor/cakephp/cakephp/src/Network/CorsBuilder.php
+++ /dev/null
@@ -1,4 +0,0 @@
- STREAM_CRYPTO_METHOD_SSLv2_CLIENT,
- // @deprecated Will be removed in 4.0.0
- 'sslv3_client' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
+ // phpcs:disable
'sslv23_client' => STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
'tls_client' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
'tlsv10_client' => STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT,
'tlsv11_client' => STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT,
'tlsv12_client' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
- // @deprecated Will be removed in 4.0.0
- 'sslv2_server' => STREAM_CRYPTO_METHOD_SSLv2_SERVER,
- // @deprecated Will be removed in 4.0.0
- 'sslv3_server' => STREAM_CRYPTO_METHOD_SSLv3_SERVER,
'sslv23_server' => STREAM_CRYPTO_METHOD_SSLv23_SERVER,
'tls_server' => STREAM_CRYPTO_METHOD_TLS_SERVER,
'tlsv10_server' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER,
'tlsv11_server' => STREAM_CRYPTO_METHOD_TLSv1_1_SERVER,
'tlsv12_server' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
- // @codingStandardsIgnoreEnd
+ // phpcs:enable
];
/**
@@ -134,7 +126,7 @@ public function __construct(array $config = [])
* @return bool Success
* @throws \Cake\Network\Exception\SocketException
*/
- public function connect()
+ public function connect(): bool
{
if ($this->connection) {
$this->disconnect();
@@ -142,7 +134,7 @@ public function connect()
$hasProtocol = strpos($this->_config['host'], '://') !== false;
if ($hasProtocol) {
- list($this->_config['protocol'], $this->_config['host']) = explode('://', $this->_config['host']);
+ [$this->_config['protocol'], $this->_config['host']] = explode('://', $this->_config['host']);
}
$scheme = null;
if (!empty($this->_config['protocol'])) {
@@ -161,6 +153,7 @@ public function connect()
$connectAs |= STREAM_CLIENT_PERSISTENT;
}
+ /** @psalm-suppress InvalidArgument */
set_error_handler([$this, '_connectionErrorHandler']);
$remoteSocketTarget = $scheme . $this->_config['host'];
$port = (int)$this->_config['port'];
@@ -168,6 +161,8 @@ public function connect()
$remoteSocketTarget .= ':' . $port;
}
+ $errNum = 0;
+ $errStr = '';
$this->connection = $this->_getStreamSocketClient(
$remoteSocketTarget,
$errNum,
@@ -178,18 +173,19 @@ public function connect()
);
restore_error_handler();
- if (!empty($errNum) || !empty($errStr)) {
+ if ($this->connection === null && (!$errNum || !$errStr)) {
$this->setLastError($errNum, $errStr);
throw new SocketException($errStr, $errNum);
}
- if (!$this->connection && $this->_connectionErrors) {
+ if ($this->connection === null && $this->_connectionErrors) {
$message = implode("\n", $this->_connectionErrors);
throw new SocketException($message, E_WARNING);
}
$this->connected = is_resource($this->connection);
if ($this->connected) {
+ /** @psalm-suppress PossiblyNullArgument */
stream_set_timeout($this->connection, $this->_config['timeout']);
}
@@ -205,11 +201,11 @@ public function connect()
* @param int $timeout timeout
* @param int $connectAs flags
* @param resource $context context
- * @return bool|resource
+ * @return resource|null
*/
protected function _getStreamSocketClient($remoteSocketTarget, &$errNum, &$errStr, $timeout, $connectAs, $context)
{
- return stream_socket_client(
+ $resource = stream_socket_client(
$remoteSocketTarget,
$errNum,
$errStr,
@@ -217,6 +213,12 @@ protected function _getStreamSocketClient($remoteSocketTarget, &$errNum, &$errSt
$connectAs,
$context
);
+
+ if ($resource) {
+ return $resource;
+ }
+
+ return null;
}
/**
@@ -225,7 +227,7 @@ protected function _getStreamSocketClient($remoteSocketTarget, &$errNum, &$errSt
* @param string $host The host name being connected to.
* @return void
*/
- protected function _setSslContext($host)
+ protected function _setSslContext(string $host): void
{
foreach ($this->_config as $key => $value) {
if (substr($key, 0, 4) !== 'ssl_') {
@@ -244,9 +246,7 @@ protected function _setSslContext($host)
$this->_config['context']['ssl']['peer_name'] = $host;
}
if (empty($this->_config['context']['ssl']['cafile'])) {
- $dir = dirname(dirname(__DIR__));
- $this->_config['context']['ssl']['cafile'] = $dir . DIRECTORY_SEPARATOR .
- 'config' . DIRECTORY_SEPARATOR . 'cacert.pem';
+ $this->_config['context']['ssl']['cafile'] = CaBundle::getBundledCaBundlePath();
}
if (!empty($this->_config['context']['ssl']['verify_host'])) {
$this->_config['context']['ssl']['CN_match'] = $host;
@@ -264,7 +264,7 @@ protected function _setSslContext($host)
* @param string $message Message.
* @return void
*/
- protected function _connectionErrorHandler($code, $message)
+ protected function _connectionErrorHandler(int $code, string $message): void
{
$this->_connectionErrors[] = $message;
}
@@ -274,7 +274,7 @@ protected function _connectionErrorHandler($code, $message)
*
* @return array|null Null when there is no connection, an array when there is.
*/
- public function context()
+ public function context(): ?array
{
if (!$this->connection) {
return null;
@@ -288,7 +288,7 @@ public function context()
*
* @return string Host name
*/
- public function host()
+ public function host(): string
{
if (Validation::ip($this->_config['host'])) {
return gethostbyaddr($this->_config['host']);
@@ -302,7 +302,7 @@ public function host()
*
* @return string IP address
*/
- public function address()
+ public function address(): string
{
if (Validation::ip($this->_config['host'])) {
return $this->_config['host'];
@@ -316,7 +316,7 @@ public function address()
*
* @return array IP addresses
*/
- public function addresses()
+ public function addresses(): array
{
if (Validation::ip($this->_config['host'])) {
return [$this->_config['host']];
@@ -330,7 +330,7 @@ public function addresses()
*
* @return string|null Last error
*/
- public function lastError()
+ public function lastError(): ?string
{
if (!empty($this->lastError)) {
return $this->lastError['num'] . ': ' . $this->lastError['str'];
@@ -342,11 +342,11 @@ public function lastError()
/**
* Set the last error.
*
- * @param int $errNum Error code
+ * @param int|null $errNum Error code
* @param string $errStr Error string
* @return void
*/
- public function setLastError($errNum, $errStr)
+ public function setLastError(?int $errNum, string $errStr): void
{
$this->lastError = ['num' => $errNum, 'str' => $errStr];
}
@@ -354,20 +354,18 @@ public function setLastError($errNum, $errStr)
/**
* Write data to the socket.
*
- * The bool false return value is deprecated and will be int 0 in the next major.
- * Please code respectively to be future proof.
- *
* @param string $data The data to write to the socket.
- * @return int|false Bytes written.
+ * @return int Bytes written.
*/
- public function write($data)
+ public function write(string $data): int
{
if (!$this->connected && !$this->connect()) {
- return false;
+ return 0;
}
$totalBytes = strlen($data);
$written = 0;
while ($written < $totalBytes) {
+ /** @psalm-suppress PossiblyNullArgument */
$rv = fwrite($this->connection, substr($data, $written));
if ($rv === false || $rv === 0) {
return $written;
@@ -379,34 +377,32 @@ public function write($data)
}
/**
- * Read data from the socket. Returns false if no data is available or no connection could be
+ * Read data from the socket. Returns null if no data is available or no connection could be
* established.
*
- * The bool false return value is deprecated and will be null in the next major.
- * Please code respectively to be future proof.
- *
* @param int $length Optional buffer length to read; defaults to 1024
- * @return mixed Socket data
+ * @return string|null Socket data
*/
- public function read($length = 1024)
+ public function read(int $length = 1024): ?string
{
if (!$this->connected && !$this->connect()) {
- return false;
+ return null;
}
+ /** @psalm-suppress PossiblyNullArgument */
if (!feof($this->connection)) {
$buffer = fread($this->connection, $length);
$info = stream_get_meta_data($this->connection);
if ($info['timed_out']) {
$this->setLastError(E_WARNING, 'Connection timed out');
- return false;
+ return null;
}
return $buffer;
}
- return false;
+ return null;
}
/**
@@ -414,13 +410,14 @@ public function read($length = 1024)
*
* @return bool Success
*/
- public function disconnect()
+ public function disconnect(): bool
{
if (!is_resource($this->connection)) {
$this->connected = false;
return true;
}
+ /** @psalm-suppress InvalidPropertyAssignmentValue */
$this->connected = !fclose($this->connection);
if (!$this->connected) {
@@ -442,14 +439,14 @@ public function __destruct()
* Resets the state of this Socket instance to it's initial state (before Object::__construct got executed)
*
* @param array|null $state Array with key and values to reset
- * @return bool True on success
+ * @return void
*/
- public function reset($state = null)
+ public function reset(?array $state = null): void
{
if (empty($state)) {
static $initalState = [];
if (empty($initalState)) {
- $initalState = get_class_vars(__CLASS__);
+ $initalState = get_class_vars(self::class);
}
$state = $initalState;
}
@@ -457,8 +454,6 @@ public function reset($state = null)
foreach ($state as $property => $value) {
$this->{$property} = $value;
}
-
- return true;
}
/**
@@ -467,33 +462,23 @@ public function reset($state = null)
* @param string $type can be one of 'ssl2', 'ssl3', 'ssl23' or 'tls'
* @param string $clientOrServer can be one of 'client', 'server'. Default is 'client'
* @param bool $enable enable or disable encryption. Default is true (enable)
- * @return bool True on success
+ * @return void
* @throws \InvalidArgumentException When an invalid encryption scheme is chosen.
* @throws \Cake\Network\Exception\SocketException When attempting to enable SSL/TLS fails
* @see stream_socket_enable_crypto
*/
- public function enableCrypto($type, $clientOrServer = 'client', $enable = true)
+ public function enableCrypto(string $type, string $clientOrServer = 'client', bool $enable = true): void
{
if (!array_key_exists($type . '_' . $clientOrServer, $this->_encryptMethods)) {
throw new InvalidArgumentException('Invalid encryption scheme chosen');
}
$method = $this->_encryptMethods[$type . '_' . $clientOrServer];
- // Prior to PHP 5.6.7 TLS_CLIENT was any version of TLS. This was changed in 5.6.7
- // to fix backwards compatibility issues, and now only resolves to TLS1.0
- //
- // See https://github.com/php/php-src/commit/10bc5fd4c4c8e1dd57bd911b086e9872a56300a0
- if (version_compare(PHP_VERSION, '5.6.7', '>=')) {
- if ($method == STREAM_CRYPTO_METHOD_TLS_CLIENT) {
- // @codingStandardsIgnoreStart
- $method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
- // @codingStandardsIgnoreEnd
- }
- if ($method == STREAM_CRYPTO_METHOD_TLS_SERVER) {
- // @codingStandardsIgnoreStart
- $method |= STREAM_CRYPTO_METHOD_TLSv1_1_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER;
- // @codingStandardsIgnoreEnd
- }
+ if ($method === STREAM_CRYPTO_METHOD_TLS_CLIENT) {
+ $method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
+ }
+ if ($method === STREAM_CRYPTO_METHOD_TLS_SERVER) {
+ $method |= STREAM_CRYPTO_METHOD_TLSv1_1_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER;
}
try {
@@ -505,11 +490,13 @@ public function enableCrypto($type, $clientOrServer = 'client', $enable = true)
$this->setLastError(null, $e->getMessage());
throw new SocketException($e->getMessage(), null, $e);
}
+
if ($enableCryptoResult === true) {
$this->encrypted = $enable;
- return true;
+ return;
}
+
$errorMessage = 'Unable to perform enableCrypto operation on the current socket';
$this->setLastError(null, $errorMessage);
throw new SocketException($errorMessage);
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association.php b/app/vendor/cakephp/cakephp/src/ORM/Association.php
index 96d945807..41bcf4861 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association.php
@@ -1,4 +1,6 @@
_className) && strpos($alias, '.')) {
+ if (empty($this->_className)) {
$this->_className = $alias;
}
- list(, $name) = pluginSplit($alias);
+ [, $name] = pluginSplit($alias);
$this->_name = $name;
$this->_options($options);
@@ -245,12 +247,16 @@ public function __construct($alias, array $options = [])
* @param string $name Name to be assigned
* @return $this
*/
- public function setName($name)
+ public function setName(string $name)
{
if ($this->_targetTable !== null) {
$alias = $this->_targetTable->getAlias();
if ($alias !== $name) {
- throw new InvalidArgumentException('Association name does not match target table alias.');
+ throw new InvalidArgumentException(sprintf(
+ 'Association name "%s" does not match target table alias "%s".',
+ $name,
+ $alias
+ ));
}
}
@@ -265,38 +271,18 @@ public function setName($name)
*
* @return string
*/
- public function getName()
+ public function getName(): string
{
return $this->_name;
}
- /**
- * Sets the name for this association.
- *
- * @deprecated 3.4.0 Use setName()/getName() instead.
- * @param string|null $name Name to be assigned
- * @return string
- */
- public function name($name = null)
- {
- deprecationWarning(
- get_called_class() . '::name() is deprecated. ' .
- 'Use setName()/getName() instead.'
- );
- if ($name !== null) {
- $this->setName($name);
- }
-
- return $this->getName();
- }
-
/**
* Sets whether or not cascaded deletes should also fire callbacks.
*
* @param bool $cascadeCallbacks cascade callbacks switch value
* @return $this
*/
- public function setCascadeCallbacks($cascadeCallbacks)
+ public function setCascadeCallbacks(bool $cascadeCallbacks)
{
$this->_cascadeCallbacks = $cascadeCallbacks;
@@ -308,32 +294,11 @@ public function setCascadeCallbacks($cascadeCallbacks)
*
* @return bool
*/
- public function getCascadeCallbacks()
+ public function getCascadeCallbacks(): bool
{
return $this->_cascadeCallbacks;
}
- /**
- * Sets whether or not cascaded deletes should also fire callbacks. If no
- * arguments are passed, the current configured value is returned
- *
- * @deprecated 3.4.0 Use setCascadeCallbacks()/getCascadeCallbacks() instead.
- * @param bool|null $cascadeCallbacks cascade callbacks switch value
- * @return bool
- */
- public function cascadeCallbacks($cascadeCallbacks = null)
- {
- deprecationWarning(
- get_called_class() . '::cascadeCallbacks() is deprecated. ' .
- 'Use setCascadeCallbacks()/getCascadeCallbacks() instead.'
- );
- if ($cascadeCallbacks !== null) {
- $this->setCascadeCallbacks($cascadeCallbacks);
- }
-
- return $this->getCascadeCallbacks();
- }
-
/**
* Sets the class name of the target table object.
*
@@ -342,15 +307,17 @@ public function cascadeCallbacks($cascadeCallbacks = null)
* @throws \InvalidArgumentException In case the class name is set after the target table has been
* resolved, and it doesn't match the target table's class name.
*/
- public function setClassName($className)
+ public function setClassName(string $className)
{
if (
$this->_targetTable !== null &&
get_class($this->_targetTable) !== App::className($className, 'Model/Table', 'Table')
) {
- throw new InvalidArgumentException(
- 'The class name doesn\'t match the target table\'s class name.'
- );
+ throw new InvalidArgumentException(sprintf(
+ 'The class name "%s" doesn\'t match the target table class name of "%s".',
+ $className,
+ get_class($this->_targetTable)
+ ));
}
$this->_className = $className;
@@ -363,27 +330,11 @@ public function setClassName($className)
*
* @return string
*/
- public function getClassName()
+ public function getClassName(): string
{
return $this->_className;
}
- /**
- * The class name of the target table object
- *
- * @deprecated 3.7.0 Use getClassName() instead.
- * @return string
- */
- public function className()
- {
- deprecationWarning(
- get_called_class() . '::className() is deprecated. ' .
- 'Use getClassName() instead.'
- );
-
- return $this->getClassName();
- }
-
/**
* Sets the table instance for the source side of the association.
*
@@ -402,32 +353,11 @@ public function setSource(Table $table)
*
* @return \Cake\ORM\Table
*/
- public function getSource()
+ public function getSource(): Table
{
return $this->_sourceTable;
}
- /**
- * Sets the table instance for the source side of the association. If no arguments
- * are passed, the current configured table instance is returned
- *
- * @deprecated 3.4.0 Use setSource()/getSource() instead.
- * @param \Cake\ORM\Table|null $table the instance to be assigned as source side
- * @return \Cake\ORM\Table
- */
- public function source(Table $table = null)
- {
- deprecationWarning(
- get_called_class() . '::source() is deprecated. ' .
- 'Use setSource()/getSource() instead.'
- );
- if ($table === null) {
- return $this->_sourceTable;
- }
-
- return $this->_sourceTable = $table;
- }
-
/**
* Sets the table instance for the target side of the association.
*
@@ -446,12 +376,12 @@ public function setTarget(Table $table)
*
* @return \Cake\ORM\Table
*/
- public function getTarget()
+ public function getTarget(): Table
{
- if (!$this->_targetTable) {
+ if ($this->_targetTable === null) {
if (strpos($this->_className, '.')) {
- list($plugin) = pluginSplit($this->_className, true);
- $registryAlias = $plugin . $this->_name;
+ [$plugin] = pluginSplit($this->_className, true);
+ $registryAlias = (string)$plugin . $this->_name;
} else {
$registryAlias = $this->_name;
}
@@ -466,18 +396,19 @@ public function getTarget()
$this->_targetTable = $tableLocator->get($registryAlias, $config);
if ($exists) {
- $className = $this->_getClassName($registryAlias, ['className' => $this->_className]);
+ $className = App::className($this->_className, 'Model/Table', 'Table') ?: Table::class;
if (!$this->_targetTable instanceof $className) {
$errorMessage = '%s association "%s" of type "%s" to "%s" doesn\'t match the expected class "%s". ';
- $errorMessage .= 'You can\'t have an association of the same name with a different target "className" option anywhere in your app.';
+ $errorMessage .= 'You can\'t have an association of the same name with a different target ';
+ $errorMessage .= '"className" option anywhere in your app.';
throw new RuntimeException(sprintf(
$errorMessage,
- $this->_sourceTable ? get_class($this->_sourceTable) : 'null',
+ $this->_sourceTable === null ? 'null' : get_class($this->_sourceTable),
$this->getName(),
$this->type(),
- $this->_targetTable ? get_class($this->_targetTable) : 'null',
+ get_class($this->_targetTable),
$className
));
}
@@ -487,34 +418,13 @@ public function getTarget()
return $this->_targetTable;
}
- /**
- * Sets the table instance for the target side of the association. If no arguments
- * are passed, the current configured table instance is returned
- *
- * @deprecated 3.4.0 Use setTarget()/getTarget() instead.
- * @param \Cake\ORM\Table|null $table the instance to be assigned as target side
- * @return \Cake\ORM\Table
- */
- public function target(Table $table = null)
- {
- deprecationWarning(
- get_called_class() . '::target() is deprecated. ' .
- 'Use setTarget()/getTarget() instead.'
- );
- if ($table !== null) {
- $this->setTarget($table);
- }
-
- return $this->getTarget();
- }
-
/**
* Sets a list of conditions to be always included when fetching records from
* the target association.
*
- * @param array|callable $conditions list of conditions to be used
+ * @param array|\Closure $conditions list of conditions to be used
* @see \Cake\Database\Query::where() for examples on the format of the array
- * @return $this
+ * @return \Cake\ORM\Association
*/
public function setConditions($conditions)
{
@@ -528,35 +438,13 @@ public function setConditions($conditions)
* the target association.
*
* @see \Cake\Database\Query::where() for examples on the format of the array
- * @return array|callable
+ * @return array|\Closure
*/
public function getConditions()
{
return $this->_conditions;
}
- /**
- * Sets a list of conditions to be always included when fetching records from
- * the target association. If no parameters are passed the current list is returned
- *
- * @deprecated 3.4.0 Use setConditions()/getConditions() instead.
- * @param array|null $conditions list of conditions to be used
- * @see \Cake\Database\Query::where() for examples on the format of the array
- * @return array|callable
- */
- public function conditions($conditions = null)
- {
- deprecationWarning(
- get_called_class() . '::conditions() is deprecated. ' .
- 'Use setConditions()/getConditions() instead.'
- );
- if ($conditions !== null) {
- $this->setConditions($conditions);
- }
-
- return $this->getConditions();
- }
-
/**
* Sets the name of the field representing the binding field with the target table.
* When not manually specified the primary key of the owning side table is used.
@@ -588,29 +476,6 @@ public function getBindingKey()
return $this->_bindingKey;
}
- /**
- * Sets the name of the field representing the binding field with the target table.
- * When not manually specified the primary key of the owning side table is used.
- *
- * If no parameters are passed the current field is returned
- *
- * @deprecated 3.4.0 Use setBindingKey()/getBindingKey() instead.
- * @param string|null $key the table field to be used to link both tables together
- * @return string|array
- */
- public function bindingKey($key = null)
- {
- deprecationWarning(
- get_called_class() . '::bindingKey() is deprecated. ' .
- 'Use setBindingKey()/getBindingKey() instead.'
- );
- if ($key !== null) {
- $this->setBindingKey($key);
- }
-
- return $this->getBindingKey();
- }
-
/**
* Gets the name of the field representing the foreign key to the target table.
*
@@ -634,27 +499,6 @@ public function setForeignKey($key)
return $this;
}
- /**
- * Sets the name of the field representing the foreign key to the target table.
- * If no parameters are passed the current field is returned
- *
- * @deprecated 3.4.0 Use setForeignKey()/getForeignKey() instead.
- * @param string|null $key the key to be used to link both tables together
- * @return string|array
- */
- public function foreignKey($key = null)
- {
- deprecationWarning(
- get_called_class() . '::foreignKey() is deprecated. ' .
- 'Use setForeignKey()/getForeignKey() instead.'
- );
- if ($key !== null) {
- $this->setForeignKey($key);
- }
-
- return $this->getForeignKey();
- }
-
/**
* Sets whether the records on the target table are dependent on the source table.
*
@@ -666,7 +510,7 @@ public function foreignKey($key = null)
* @param bool $dependent Set the dependent mode. Use null to read the current state.
* @return $this
*/
- public function setDependent($dependent)
+ public function setDependent(bool $dependent)
{
$this->_dependent = $dependent;
@@ -681,47 +525,22 @@ public function setDependent($dependent)
*
* @return bool
*/
- public function getDependent()
+ public function getDependent(): bool
{
return $this->_dependent;
}
- /**
- * Sets whether the records on the target table are dependent on the source table.
- *
- * This is primarily used to indicate that records should be removed if the owning record in
- * the source table is deleted.
- *
- * If no parameters are passed the current setting is returned.
- *
- * @deprecated 3.4.0 Use setDependent()/getDependent() instead.
- * @param bool|null $dependent Set the dependent mode. Use null to read the current state.
- * @return bool
- */
- public function dependent($dependent = null)
- {
- deprecationWarning(
- get_called_class() . '::dependent() is deprecated. ' .
- 'Use setDependent()/getDependent() instead.'
- );
- if ($dependent !== null) {
- $this->setDependent($dependent);
- }
-
- return $this->getDependent();
- }
-
/**
* Whether this association can be expressed directly in a query join
*
* @param array $options custom options key that could alter the return value
* @return bool
*/
- public function canBeJoined(array $options = [])
+ public function canBeJoined(array $options = []): bool
{
- $strategy = isset($options['strategy']) ? $options['strategy'] : $this->getStrategy();
+ $strategy = $options['strategy'] ?? $this->getStrategy();
- return $strategy == $this::STRATEGY_JOIN;
+ return $strategy === $this::STRATEGY_JOIN;
}
/**
@@ -730,7 +549,7 @@ public function canBeJoined(array $options = [])
* @param string $type the join type to be used (e.g. INNER)
* @return $this
*/
- public function setJoinType($type)
+ public function setJoinType(string $type)
{
$this->_joinType = $type;
@@ -742,32 +561,11 @@ public function setJoinType($type)
*
* @return string
*/
- public function getJoinType()
+ public function getJoinType(): string
{
return $this->_joinType;
}
- /**
- * Sets the type of join to be used when adding the association to a query.
- * If no arguments are passed, the currently configured type is returned.
- *
- * @deprecated 3.4.0 Use setJoinType()/getJoinType() instead.
- * @param string|null $type the join type to be used (e.g. INNER)
- * @return string
- */
- public function joinType($type = null)
- {
- deprecationWarning(
- get_called_class() . '::joinType() is deprecated. ' .
- 'Use setJoinType()/getJoinType() instead.'
- );
- if ($type !== null) {
- $this->setJoinType($type);
- }
-
- return $this->getJoinType();
- }
-
/**
* Sets the property name that should be filled with data from the target table
* in the source table record.
@@ -775,7 +573,7 @@ public function joinType($type = null)
* @param string $name The name of the association property. Use null to read the current value.
* @return $this
*/
- public function setProperty($name)
+ public function setProperty(string $name)
{
$this->_propertyName = $name;
@@ -788,11 +586,11 @@ public function setProperty($name)
*
* @return string
*/
- public function getProperty()
+ public function getProperty(): string
{
if (!$this->_propertyName) {
$this->_propertyName = $this->_propertyName();
- if (in_array($this->_propertyName, $this->_sourceTable->getSchema()->columns())) {
+ if (in_array($this->_propertyName, $this->_sourceTable->getSchema()->columns(), true)) {
$msg = 'Association property name "%s" clashes with field of same name of table "%s".' .
' You should explicitly specify the "propertyName" option.';
trigger_error(
@@ -805,36 +603,14 @@ public function getProperty()
return $this->_propertyName;
}
- /**
- * Sets the property name that should be filled with data from the target table
- * in the source table record.
- * If no arguments are passed, the currently configured type is returned.
- *
- * @deprecated 3.4.0 Use setProperty()/getProperty() instead.
- * @param string|null $name The name of the association property. Use null to read the current value.
- * @return string
- */
- public function property($name = null)
- {
- deprecationWarning(
- get_called_class() . '::property() is deprecated. ' .
- 'Use setProperty()/getProperty() instead.'
- );
- if ($name !== null) {
- $this->setProperty($name);
- }
-
- return $this->getProperty();
- }
-
/**
* Returns default property name based on association name.
*
* @return string
*/
- protected function _propertyName()
+ protected function _propertyName(): string
{
- list(, $name) = pluginSplit($this->_name);
+ [, $name] = pluginSplit($this->_name);
return Inflector::underscore($name);
}
@@ -848,12 +624,14 @@ protected function _propertyName()
* @return $this
* @throws \InvalidArgumentException When an invalid strategy is provided.
*/
- public function setStrategy($name)
+ public function setStrategy(string $name)
{
- if (!in_array($name, $this->_validStrategies)) {
- throw new InvalidArgumentException(
- sprintf('Invalid strategy "%s" was provided', $name)
- );
+ if (!in_array($name, $this->_validStrategies, true)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid strategy "%s" was provided. Valid options are (%s).',
+ $name,
+ implode(', ', $this->_validStrategies)
+ ));
}
$this->_strategy = $name;
@@ -867,35 +645,11 @@ public function setStrategy($name)
*
* @return string
*/
- public function getStrategy()
+ public function getStrategy(): string
{
return $this->_strategy;
}
- /**
- * Sets the strategy name to be used to fetch associated records. Keep in mind
- * that some association types might not implement but a default strategy,
- * rendering any changes to this setting void.
- * If no arguments are passed, the currently configured strategy is returned.
- *
- * @deprecated 3.4.0 Use setStrategy()/getStrategy() instead.
- * @param string|null $name The strategy type. Use null to read the current value.
- * @return string
- * @throws \InvalidArgumentException When an invalid strategy is provided.
- */
- public function strategy($name = null)
- {
- deprecationWarning(
- get_called_class() . '::strategy() is deprecated. ' .
- 'Use setStrategy()/getStrategy() instead.'
- );
- if ($name !== null) {
- $this->setStrategy($name);
- }
-
- return $this->getStrategy();
- }
-
/**
* Gets the default finder to use for fetching rows from the target table.
*
@@ -919,28 +673,6 @@ public function setFinder($finder)
return $this;
}
- /**
- * Sets the default finder to use for fetching rows from the target table.
- * If no parameters are passed, it will return the currently configured
- * finder name.
- *
- * @deprecated 3.4.0 Use setFinder()/getFinder() instead.
- * @param string|null $finder the finder name to use
- * @return string|array
- */
- public function finder($finder = null)
- {
- deprecationWarning(
- get_called_class() . '::finder() is deprecated. ' .
- 'Use setFinder()/getFinder() instead.'
- );
- if ($finder !== null) {
- $this->setFinder($finder);
- }
-
- return $this->getFinder();
- }
-
/**
* Override this function to initialize any concrete association class, it will
* get passed the original list of options used in the constructor
@@ -948,7 +680,7 @@ public function finder($finder = null)
* @param array $options List of options used for initialization
* @return void
*/
- protected function _options(array $options)
+ protected function _options(array $options): void
{
}
@@ -981,7 +713,7 @@ protected function _options(array $options)
* @throws \RuntimeException if the query builder passed does not return a query
* object
*/
- public function attachTo(Query $query, array $options = [])
+ public function attachTo(Query $query, array $options = []): void
{
$target = $this->getTarget();
$joinType = empty($options['joinType']) ? $this->getJoinType() : $options['joinType'];
@@ -1004,7 +736,7 @@ public function attachTo(Query $query, array $options = [])
}
}
- list($finder, $opts) = $this->_extractFinder($options['finder']);
+ [$finder, $opts] = $this->_extractFinder($options['finder']);
$dummy = $this
->find($finder, $opts)
->eagerLoaded(true);
@@ -1019,6 +751,16 @@ public function attachTo(Query $query, array $options = [])
}
}
+ if (
+ !empty($options['matching']) &&
+ $this->_strategy === static::STRATEGY_JOIN &&
+ $dummy->getContain()
+ ) {
+ throw new RuntimeException(
+ "`{$this->getName()}` association cannot contain() associations when using JOIN strategy."
+ );
+ }
+
$dummy->where($options['conditions']);
$this->_dispatchBeforeFind($dummy);
@@ -1036,11 +778,11 @@ public function attachTo(Query $query, array $options = [])
* Conditionally adds a condition to the passed Query that will make it find
* records where there is no match with this association.
*
- * @param \Cake\Datasource\QueryInterface $query The query to modify
+ * @param \Cake\ORM\Query $query The query to modify
* @param array $options Options array containing the `negateMatch` key.
* @return void
*/
- protected function _appendNotMatching($query, $options)
+ protected function _appendNotMatching(Query $query, array $options): void
{
$target = $this->_targetTable;
if (!empty($options['negateMatch'])) {
@@ -1066,7 +808,7 @@ protected function _appendNotMatching($query, $options)
* data shuld be nested in. Will use the default one if not provided.
* @return array
*/
- public function transformRow($row, $nestKey, $joined, $targetProperty = null)
+ public function transformRow(array $row, string $nestKey, bool $joined, ?string $targetProperty = null): array
{
$sourceAlias = $this->getSource()->getAlias();
$nestKey = $nestKey ?: $this->_name;
@@ -1089,7 +831,7 @@ public function transformRow($row, $nestKey, $joined, $targetProperty = null)
* with this association
* @return array
*/
- public function defaultRowValue($row, $joined)
+ public function defaultRowValue(array $row, bool $joined): array
{
$sourceAlias = $this->getSource()->getAlias();
if (isset($row[$sourceAlias])) {
@@ -1110,10 +852,10 @@ public function defaultRowValue($row, $joined)
* @see \Cake\ORM\Table::find()
* @return \Cake\ORM\Query
*/
- public function find($type = null, array $options = [])
+ public function find($type = null, array $options = []): Query
{
$type = $type ?: $this->getFinder();
- list($type, $opts) = $this->_extractFinder($type);
+ [$type, $opts] = $this->_extractFinder($type);
return $this->getTarget()
->find($type, $options + $opts)
@@ -1124,18 +866,16 @@ public function find($type = null, array $options = [])
* Proxies the operation to the target table's exists method after
* appending the default conditions for this association
*
- * @param array|callable|\Cake\Database\ExpressionInterface $conditions The conditions to use
+ * @param array|\Closure|\Cake\Database\ExpressionInterface $conditions The conditions to use
* for checking if any record matches.
* @see \Cake\ORM\Table::exists()
* @return bool
*/
- public function exists($conditions)
+ public function exists($conditions): bool
{
- if ($this->_conditions) {
- $conditions = $this
- ->find('all', ['conditions' => $conditions])
- ->clause('where');
- }
+ $conditions = $this->find()
+ ->where($conditions)
+ ->clause('where');
return $this->getTarget()->exists($conditions);
}
@@ -1149,15 +889,13 @@ public function exists($conditions)
* @see \Cake\ORM\Table::updateAll()
* @return int Count Returns the affected rows.
*/
- public function updateAll($fields, $conditions)
+ public function updateAll(array $fields, $conditions): int
{
- $target = $this->getTarget();
- $expression = $target->query()
- ->where($this->getConditions())
+ $expression = $this->find()
->where($conditions)
->clause('where');
- return $target->updateAll($fields, $expression);
+ return $this->getTarget()->updateAll($fields, $expression);
}
/**
@@ -1168,15 +906,13 @@ public function updateAll($fields, $conditions)
* @return int Returns the number of affected rows.
* @see \Cake\ORM\Table::deleteAll()
*/
- public function deleteAll($conditions)
+ public function deleteAll($conditions): int
{
- $target = $this->getTarget();
- $expression = $target->query()
- ->where($this->getConditions())
+ $expression = $this->find()
->where($conditions)
->clause('where');
- return $target->deleteAll($expression);
+ return $this->getTarget()->deleteAll($expression);
}
/**
@@ -1186,9 +922,9 @@ public function deleteAll($conditions)
* @param array $options The options containing the strategy to be used.
* @return bool true if a list of keys will be required
*/
- public function requiresKeys(array $options = [])
+ public function requiresKeys(array $options = []): bool
{
- $strategy = isset($options['strategy']) ? $options['strategy'] : $this->getStrategy();
+ $strategy = $options['strategy'] ?? $this->getStrategy();
return $strategy === static::STRATEGY_SELECT;
}
@@ -1200,7 +936,7 @@ public function requiresKeys(array $options = [])
* @param \Cake\ORM\Query $query the query this association is attaching itself to
* @return void
*/
- protected function _dispatchBeforeFind($query)
+ protected function _dispatchBeforeFind(Query $query): void
{
$query->triggerBeforeFind();
}
@@ -1214,7 +950,7 @@ protected function _dispatchBeforeFind($query)
* @param array $options options passed to the method `attachTo`
* @return void
*/
- protected function _appendFields($query, $surrogate, $options)
+ protected function _appendFields(Query $query, Query $surrogate, array $options): void
{
if ($query->getEagerLoader()->isAutoFieldsEnabled() === false) {
return;
@@ -1254,7 +990,7 @@ protected function _appendFields($query, $surrogate, $options)
* @param array $options options passed to the method `attachTo`
* @return void
*/
- protected function _formatAssociationResults($query, $surrogate, $options)
+ protected function _formatAssociationResults(Query $query, Query $surrogate, array $options): void
{
$formatters = $surrogate->getResultFormatters();
@@ -1308,7 +1044,7 @@ protected function _formatAssociationResults($query, $surrogate, $options)
* @param array $options options passed to the method `attachTo`
* @return void
*/
- protected function _bindNewAssociations($query, $surrogate, $options)
+ protected function _bindNewAssociations(Query $query, Query $surrogate, array $options): void
{
$loader = $surrogate->getEagerLoader();
$contain = $loader->getContain();
@@ -1346,7 +1082,7 @@ protected function _bindNewAssociations($query, $surrogate, $options)
* @throws \RuntimeException if the number of columns in the foreignKey do not
* match the number of columns in the source table primaryKey
*/
- protected function _joinCondition($options)
+ protected function _joinCondition(array $options): array
{
$conditions = [];
$tAlias = $this->_name;
@@ -1398,7 +1134,7 @@ protected function _joinCondition($options)
* and options as value.
* @return array
*/
- protected function _extractFinder($finderData)
+ protected function _extractFinder($finderData): array
{
$finderData = (array)$finderData;
@@ -1409,24 +1145,6 @@ protected function _extractFinder($finderData)
return [key($finderData), current($finderData)];
}
- /**
- * Gets the table class name.
- *
- * @param string $alias The alias name you want to get.
- * @param array $options Table options array.
- * @return string
- */
- protected function _getClassName($alias, array $options = [])
- {
- if (empty($options['className'])) {
- $options['className'] = Inflector::camelize($alias);
- }
-
- $className = App::className($options['className'], 'Model/Table', 'Table') ?: 'Cake\ORM\Table';
-
- return ltrim($className, '\\');
- }
-
/**
* Proxies property retrieval to the target table. This is handy for getting this
* association's associations
@@ -1470,7 +1188,7 @@ public function __call($method, $argument)
*
* @return string Constant of either ONE_TO_ONE, MANY_TO_ONE, ONE_TO_MANY or MANY_TO_MANY.
*/
- abstract public function type();
+ abstract public function type(): string;
/**
* Eager loads a list of records in the target table that are related to another
@@ -1502,7 +1220,7 @@ abstract public function type();
* @param array $options The options for eager loading.
* @return \Closure
*/
- abstract public function eagerLoader(array $options);
+ abstract public function eagerLoader(array $options): Closure;
/**
* Handles cascading a delete from an associated model.
@@ -1514,7 +1232,7 @@ abstract public function eagerLoader(array $options);
* @param array $options The options for the original delete.
* @return bool Success
*/
- abstract public function cascadeDelete(EntityInterface $entity, array $options = []);
+ abstract public function cascadeDelete(EntityInterface $entity, array $options = []): bool;
/**
* Returns whether or not the passed table is the owning side for this
@@ -1524,7 +1242,7 @@ abstract public function cascadeDelete(EntityInterface $entity, array $options =
* @param \Cake\ORM\Table $side The potential Table with ownership
* @return bool
*/
- abstract public function isOwningSide(Table $side);
+ abstract public function isOwningSide(Table $side): bool;
/**
* Extract the target's association data our from the passed entity and proxies
@@ -1532,7 +1250,7 @@ abstract public function isOwningSide(Table $side);
*
* @param \Cake\Datasource\EntityInterface $entity the data to be saved
* @param array $options The options for saving associated data.
- * @return \Cake\Datasource\EntityInterface|false False if $entity could not be saved, otherwise it returns
+ * @return \Cake\Datasource\EntityInterface|false false if $entity could not be saved, otherwise it returns
* the saved entity
* @see \Cake\ORM\Table::save()
*/
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsTo.php b/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsTo.php
index dac887d80..fb3541489 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsTo.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsTo.php
@@ -1,4 +1,6 @@
_name);
+ [, $name] = pluginSplit($this->_name);
return Inflector::underscore(Inflector::singularize($name));
}
@@ -88,7 +91,7 @@ protected function _propertyName()
* @param \Cake\ORM\Table $side The potential Table with ownership
* @return bool
*/
- public function isOwningSide(Table $side)
+ public function isOwningSide(Table $side): bool
{
return $side === $this->getTarget();
}
@@ -98,7 +101,7 @@ public function isOwningSide(Table $side)
*
* @return string
*/
- public function type()
+ public function type(): string
{
return self::MANY_TO_ONE;
}
@@ -111,7 +114,7 @@ public function type()
*
* @param \Cake\Datasource\EntityInterface $entity an entity from the source table
* @param array $options options to be passed to the save method in the target table
- * @return \Cake\Datasource\EntityInterface|false False if $entity could not be saved, otherwise it returns
+ * @return \Cake\Datasource\EntityInterface|false false if $entity could not be saved, otherwise it returns
* the saved entity
* @see \Cake\ORM\Table::save()
*/
@@ -146,7 +149,7 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
* @throws \RuntimeException if the number of columns in the foreignKey do not
* match the number of columns in the target table primaryKey
*/
- protected function _joinCondition($options)
+ protected function _joinCondition(array $options): array
{
$conditions = [];
$tAlias = $this->_name;
@@ -179,11 +182,9 @@ protected function _joinCondition($options)
}
/**
- * {@inheritDoc}
- *
- * @return \Closure
+ * @inheritDoc
*/
- public function eagerLoader(array $options)
+ public function eagerLoader(array $options): Closure
{
$loader = new SelectLoader([
'alias' => $this->getAlias(),
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php b/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php
index aad0f83c9..9423783c4 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php
@@ -1,4 +1,6 @@
_targetForeignKey;
}
- /**
- * Sets the name of the field representing the foreign key to the target table.
- * If no parameters are passed current field is returned
- *
- * @deprecated 3.4.0 Use setTargetForeignKey()/getTargetForeignKey() instead.
- * @param string|null $key the key to be used to link both tables together
- * @return string
- */
- public function targetForeignKey($key = null)
- {
- deprecationWarning(
- 'BelongToMany::targetForeignKey() is deprecated. ' .
- 'Use setTargetForeignKey()/getTargetForeignKey() instead.'
- );
- if ($key !== null) {
- $this->setTargetForeignKey($key);
- }
-
- return $this->getTargetForeignKey();
- }
-
/**
* Whether this association can be expressed directly in a query join
*
@@ -212,7 +192,7 @@ public function targetForeignKey($key = null)
* @return bool if the 'matching' key in $option is true then this function
* will return true, false otherwise
*/
- public function canBeJoined(array $options = [])
+ public function canBeJoined(array $options = []): bool
{
return !empty($options['matching']);
}
@@ -255,30 +235,9 @@ public function getSort()
}
/**
- * Sets the sort order in which target records should be returned.
- * If no arguments are passed the currently configured value is returned
- *
- * @deprecated 3.5.0 Use setSort()/getSort() instead.
- * @param mixed $sort A find() compatible order clause
- * @return mixed
- */
- public function sort($sort = null)
- {
- deprecationWarning(
- 'BelongToMany::sort() is deprecated. ' .
- 'Use setSort()/getSort() instead.'
- );
- if ($sort !== null) {
- $this->setSort($sort);
- }
-
- return $this->getSort();
- }
-
- /**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function defaultRowValue($row, $joined)
+ public function defaultRowValue(array $row, bool $joined): array
{
$sourceAlias = $this->getSource()->getAlias();
if (isset($row[$sourceAlias])) {
@@ -295,9 +254,9 @@ public function defaultRowValue($row, $joined)
* @param string|\Cake\ORM\Table|null $table Name or instance for the join table
* @return \Cake\ORM\Table
*/
- public function junction($table = null)
+ public function junction($table = null): Table
{
- if ($table === null && $this->_junctionTable) {
+ if ($table === null && $this->_junctionTable !== null) {
return $this->_junctionTable;
}
@@ -349,21 +308,14 @@ public function junction($table = null)
* @param \Cake\ORM\Table $target The target table.
* @return void
*/
- protected function _generateTargetAssociations($junction, $source, $target)
+ protected function _generateTargetAssociations(Table $junction, Table $source, Table $target): void
{
$junctionAlias = $junction->getAlias();
$sAlias = $source->getAlias();
- $tAlias = $target->getAlias();
-
- $targetBindingKey = null;
- if ($junction->hasAssociation($tAlias)) {
- $targetBindingKey = $junction->getAssociation($tAlias)->getBindingKey();
- }
if (!$target->hasAssociation($junctionAlias)) {
$target->hasMany($junctionAlias, [
'targetTable' => $junction,
- 'bindingKey' => $targetBindingKey,
'foreignKey' => $this->getTargetForeignKey(),
'strategy' => $this->_strategy,
]);
@@ -395,20 +347,12 @@ protected function _generateTargetAssociations($junction, $source, $target)
* @param \Cake\ORM\Table $source The source table.
* @return void
*/
- protected function _generateSourceAssociations($junction, $source)
+ protected function _generateSourceAssociations(Table $junction, Table $source): void
{
$junctionAlias = $junction->getAlias();
- $sAlias = $source->getAlias();
-
- $sourceBindingKey = null;
- if ($junction->hasAssociation($sAlias)) {
- $sourceBindingKey = $junction->getAssociation($sAlias)->getBindingKey();
- }
-
if (!$source->hasAssociation($junctionAlias)) {
$source->hasMany($junctionAlias, [
'targetTable' => $junction,
- 'bindingKey' => $sourceBindingKey,
'foreignKey' => $this->getForeignKey(),
'strategy' => $this->_strategy,
]);
@@ -431,7 +375,7 @@ protected function _generateSourceAssociations($junction, $source)
* @param \Cake\ORM\Table $target The target table.
* @return void
*/
- protected function _generateJunctionAssociations($junction, $source, $target)
+ protected function _generateJunctionAssociations(Table $junction, Table $source, Table $target): void
{
$tAlias = $target->getAlias();
$sAlias = $source->getAlias();
@@ -467,7 +411,7 @@ protected function _generateJunctionAssociations($junction, $source, $target)
* @param array $options Any extra options or overrides to be taken in account
* @return void
*/
- public function attachTo(Query $query, array $options = [])
+ public function attachTo(Query $query, array $options = []): void
{
if (!empty($options['negateMatch'])) {
$this->_appendNotMatching($query, $options);
@@ -504,9 +448,9 @@ public function attachTo(Query $query, array $options = [])
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- protected function _appendNotMatching($query, $options)
+ protected function _appendNotMatching(Query $query, array $options): void
{
if (empty($options['negateMatch'])) {
return;
@@ -520,18 +464,13 @@ protected function _appendNotMatching($query, $options)
$subquery = $this->find()
->select(array_values($conds))
- ->where($options['conditions'])
- ->andWhere($this->junctionConditions());
+ ->where($options['conditions']);
if (!empty($options['queryBuilder'])) {
$subquery = $options['queryBuilder']($subquery);
}
- $assoc = $junction->getAssociation($this->getTarget()->getAlias());
- $conditions = $assoc->_joinCondition([
- 'foreignKey' => $this->getTargetForeignKey(),
- ]);
- $subquery = $this->_appendJunctionJoin($subquery, $conditions);
+ $subquery = $this->_appendJunctionJoin($subquery);
$query
->andWhere(function (QueryExpression $exp) use ($subquery, $conds) {
@@ -555,7 +494,7 @@ protected function _appendNotMatching($query, $options)
*
* @return string
*/
- public function type()
+ public function type(): string
{
return self::MANY_TO_MANY;
}
@@ -564,19 +503,17 @@ public function type()
* Return false as join conditions are defined in the junction table
*
* @param array $options list of options passed to attachTo method
- * @return bool false
+ * @return array
*/
- protected function _joinCondition($options)
+ protected function _joinCondition(array $options): array
{
- return false;
+ return [];
}
/**
- * {@inheritDoc}
- *
- * @return \Closure
+ * @inheritDoc
*/
- public function eagerLoader(array $options)
+ public function eagerLoader(array $options): Closure
{
$name = $this->_junctionAssociationName();
$loader = new SelectWithPivotLoader([
@@ -607,7 +544,7 @@ public function eagerLoader(array $options)
* @param array $options The options for the original delete.
* @return bool Success.
*/
- public function cascadeDelete(EntityInterface $entity, array $options = [])
+ public function cascadeDelete(EntityInterface $entity, array $options = []): bool
{
if (!$this->getDependent()) {
return true;
@@ -630,7 +567,12 @@ public function cascadeDelete(EntityInterface $entity, array $options = [])
return true;
}
- $conditions = array_merge($conditions, $hasMany->getConditions());
+ $assocConditions = $hasMany->getConditions();
+ if (is_array($assocConditions)) {
+ $conditions = array_merge($conditions, $assocConditions);
+ } else {
+ $conditions[] = $assocConditions;
+ }
$table->deleteAll($conditions);
@@ -644,7 +586,7 @@ public function cascadeDelete(EntityInterface $entity, array $options = [])
* @param \Cake\ORM\Table $side The potential Table with ownership
* @return bool
*/
- public function isOwningSide(Table $side)
+ public function isOwningSide(Table $side): bool
{
return true;
}
@@ -656,9 +598,9 @@ public function isOwningSide(Table $side)
* @throws \InvalidArgumentException if an invalid strategy name is passed
* @return $this
*/
- public function setSaveStrategy($strategy)
+ public function setSaveStrategy(string $strategy)
{
- if (!in_array($strategy, [self::SAVE_APPEND, self::SAVE_REPLACE])) {
+ if (!in_array($strategy, [self::SAVE_APPEND, self::SAVE_REPLACE], true)) {
$msg = sprintf('Invalid save strategy "%s"', $strategy);
throw new InvalidArgumentException($msg);
}
@@ -673,33 +615,11 @@ public function setSaveStrategy($strategy)
*
* @return string the strategy to be used for saving
*/
- public function getSaveStrategy()
+ public function getSaveStrategy(): string
{
return $this->_saveStrategy;
}
- /**
- * Sets the strategy that should be used for saving. If called with no
- * arguments, it will return the currently configured strategy
- *
- * @deprecated 3.4.0 Use setSaveStrategy()/getSaveStrategy() instead.
- * @param string|null $strategy the strategy name to be used
- * @throws \InvalidArgumentException if an invalid strategy name is passed
- * @return string the strategy to be used for saving
- */
- public function saveStrategy($strategy = null)
- {
- deprecationWarning(
- 'BelongsToMany::saveStrategy() is deprecated. ' .
- 'Use setSaveStrategy()/getSaveStrategy() instead.'
- );
- if ($strategy !== null) {
- $this->setSaveStrategy($strategy);
- }
-
- return $this->getSaveStrategy();
- }
-
/**
* Takes an entity from the source table and looks if there is a field
* matching the property name for this association. The found entity will be
@@ -719,7 +639,7 @@ public function saveStrategy($strategy = null)
* @param array $options options to be passed to the save method in the target table
* @throws \InvalidArgumentException if the property representing the association
* in the parent entity cannot be traversed
- * @return \Cake\Datasource\EntityInterface|false False if $entity could not be saved, otherwise it returns
+ * @return \Cake\Datasource\EntityInterface|false false if $entity could not be saved, otherwise it returns
* the saved entity
* @see \Cake\ORM\Table::save()
* @see \Cake\ORM\Association\BelongsToMany::replaceLinks()
@@ -754,7 +674,7 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
*
* @param \Cake\Datasource\EntityInterface $parentEntity the source entity containing the target
* entities to be saved.
- * @param array|\Traversable $entities list of entities to persist in target table and to
+ * @param array $entities list of entities to persist in target table and to
* link to the parent entity
* @param array $options list of options accepted by `Table::save()`
* @throws \InvalidArgumentException if the property representing the association
@@ -762,7 +682,7 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
* @return \Cake\Datasource\EntityInterface|false The parent entity after all links have been
* created if no errors happened, false otherwise
*/
- protected function _saveTarget(EntityInterface $parentEntity, $entities, $options)
+ protected function _saveTarget(EntityInterface $parentEntity, array $entities, $options)
{
$joinAssociations = false;
if (!empty($options['associated'][$this->_junctionProperty]['associated'])) {
@@ -770,12 +690,6 @@ protected function _saveTarget(EntityInterface $parentEntity, $entities, $option
}
unset($options['associated'][$this->_junctionProperty]);
- if (!(is_array($entities) || $entities instanceof Traversable)) {
- $name = $this->getProperty();
- $message = sprintf('Could not save %s, it cannot be traversed', $name);
- throw new InvalidArgumentException($message);
- }
-
$table = $this->getTarget();
$original = $entities;
$persisted = [];
@@ -801,7 +715,7 @@ protected function _saveTarget(EntityInterface $parentEntity, $entities, $option
if (!empty($options['atomic'])) {
$original[$k]->setErrors($entity->getErrors());
}
- if (!$saved) {
+ if ($saved === false) {
return false;
}
}
@@ -829,7 +743,7 @@ protected function _saveTarget(EntityInterface $parentEntity, $entities, $option
* @param array $options list of options accepted by `Table::save()`
* @return bool success
*/
- protected function _saveLinks(EntityInterface $sourceEntity, $targetEntities, $options)
+ protected function _saveLinks(EntityInterface $sourceEntity, array $targetEntities, array $options): bool
{
$target = $this->getTarget();
$junction = $this->junction();
@@ -837,7 +751,7 @@ protected function _saveLinks(EntityInterface $sourceEntity, $targetEntities, $o
$belongsTo = $junction->getAssociation($target->getAlias());
$foreignKey = (array)$this->getForeignKey();
$assocForeignKey = (array)$belongsTo->getForeignKey();
- $targetBindingKey = (array)$belongsTo->getBindingKey();
+ $targetPrimaryKey = (array)$target->getPrimaryKey();
$bindingKey = (array)$this->getBindingKey();
$jointProperty = $this->_junctionProperty;
$junctionRegistryAlias = $junction->getRegistryAlias();
@@ -848,7 +762,7 @@ protected function _saveLinks(EntityInterface $sourceEntity, $targetEntities, $o
$joint = new $entityClass([], ['markNew' => true, 'source' => $junctionRegistryAlias]);
}
$sourceKeys = array_combine($foreignKey, $sourceEntity->extract($bindingKey));
- $targetKeys = array_combine($assocForeignKey, $e->extract($targetBindingKey));
+ $targetKeys = array_combine($assocForeignKey, $e->extract($targetPrimaryKey));
$changedKeys = (
$sourceKeys !== $joint->extract($foreignKey) ||
@@ -860,7 +774,7 @@ protected function _saveLinks(EntityInterface $sourceEntity, $targetEntities, $o
// or if we are updating an existing link.
if ($changedKeys) {
$joint->setNew(true);
- $joint->unsetProperty($junction->getPrimaryKey())
+ $joint->unset($junction->getPrimaryKey())
->set(array_merge($sourceKeys, $targetKeys), ['guard' => false]);
}
$saved = $junction->save($joint, $options);
@@ -905,7 +819,7 @@ protected function _saveLinks(EntityInterface $sourceEntity, $targetEntities, $o
* detected to not be already persisted
* @return bool true on success, false otherwise
*/
- public function link(EntityInterface $sourceEntity, array $targetEntities, array $options = [])
+ public function link(EntityInterface $sourceEntity, array $targetEntities, array $options = []): bool
{
$this->_checkPersistenceStatus($sourceEntity, $targetEntities);
$property = $this->getProperty();
@@ -956,7 +870,7 @@ function () use ($sourceEntity, $targetEntities, $options) {
* any of them is lacking a primary key value.
* @return bool Success
*/
- public function unlink(EntityInterface $sourceEntity, array $targetEntities, $options = [])
+ public function unlink(EntityInterface $sourceEntity, array $targetEntities, $options = []): bool
{
if (is_bool($options)) {
$options = [
@@ -970,7 +884,7 @@ public function unlink(EntityInterface $sourceEntity, array $targetEntities, $op
$property = $this->getProperty();
$this->junction()->getConnection()->transactional(
- function () use ($sourceEntity, $targetEntities, $options) {
+ function () use ($sourceEntity, $targetEntities, $options): void {
$links = $this->_collectJointEntities($sourceEntity, $targetEntities);
foreach ($links as $entity) {
$this->_junctionTable->delete($entity, $options);
@@ -1001,7 +915,7 @@ function () use ($sourceEntity, $targetEntities, $options) {
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function setConditions($conditions)
{
@@ -1072,7 +986,7 @@ protected function targetConditions()
*
* @return array
*/
- protected function junctionConditions()
+ protected function junctionConditions(): array
{
if ($this->_junctionConditions !== null) {
return $this->_junctionConditions;
@@ -1090,7 +1004,7 @@ protected function junctionConditions()
}
// Assume that operators contain junction conditions.
// Trying to manage complex conditions could result in incorrect queries.
- if ($isString && in_array(strtoupper($field), ['OR', 'NOT', 'AND', 'XOR'])) {
+ if ($isString && in_array(strtoupper($field), ['OR', 'NOT', 'AND', 'XOR'], true)) {
$matching[$field] = $value;
}
}
@@ -1103,7 +1017,7 @@ protected function junctionConditions()
* and modifies the query accordingly based of this association
* configuration.
*
- * If your association includes conditions, the junction table will be
+ * If your association includes conditions or a finder, the junction table will be
* included in the query's contained associations.
*
* @param string|array|null $type the type of query to perform, if an array is passed,
@@ -1112,37 +1026,39 @@ protected function junctionConditions()
* @see \Cake\ORM\Table::find()
* @return \Cake\ORM\Query
*/
- public function find($type = null, array $options = [])
+ public function find($type = null, array $options = []): Query
{
$type = $type ?: $this->getFinder();
- list($type, $opts) = $this->_extractFinder($type);
+ [$type, $opts] = $this->_extractFinder($type);
$query = $this->getTarget()
->find($type, $options + $opts)
->where($this->targetConditions())
->addDefaultTypes($this->getTarget());
- if (!$this->junctionConditions()) {
- return $query;
+ if ($this->junctionConditions()) {
+ return $this->_appendJunctionJoin($query);
}
- $belongsTo = $this->junction()->getAssociation($this->getTarget()->getAlias());
- $conditions = $belongsTo->_joinCondition([
- 'foreignKey' => $this->getTargetForeignKey(),
- ]);
- $conditions += $this->junctionConditions();
-
- return $this->_appendJunctionJoin($query, $conditions);
+ return $query;
}
/**
* Append a join to the junction table.
*
* @param \Cake\ORM\Query $query The query to append.
- * @param string|array $conditions The query conditions to use.
+ * @param array|null $conditions The query conditions to use.
* @return \Cake\ORM\Query The modified query.
*/
- protected function _appendJunctionJoin($query, $conditions)
+ protected function _appendJunctionJoin(Query $query, ?array $conditions = null): Query
{
+ if ($conditions === null) {
+ $belongsTo = $this->junction()->getAssociation($this->getTarget()->getAlias());
+ $conditions = $belongsTo->_joinCondition([
+ 'foreignKey' => $this->getTargetForeignKey(),
+ ]);
+ $conditions += $this->junctionConditions();
+ }
+
$name = $this->_junctionAssociationName();
/** @var array $joins */
$joins = $query->clause('join');
@@ -1150,7 +1066,7 @@ protected function _appendJunctionJoin($query, $conditions)
$name => [
'table' => $this->junction()->getTable(),
'conditions' => $conditions,
- 'type' => QueryInterface::JOIN_TYPE_INNER,
+ 'type' => Query::JOIN_TYPE_INNER,
],
];
@@ -1211,7 +1127,7 @@ protected function _appendJunctionJoin($query, $conditions)
* any of them is lacking a primary key value
* @return bool success
*/
- public function replaceLinks(EntityInterface $sourceEntity, array $targetEntities, array $options = [])
+ public function replaceLinks(EntityInterface $sourceEntity, array $targetEntities, array $options = []): bool
{
$bindingKey = (array)$this->getBindingKey();
$primaryValue = $sourceEntity->extract($bindingKey);
@@ -1223,17 +1139,27 @@ public function replaceLinks(EntityInterface $sourceEntity, array $targetEntitie
return $this->junction()->getConnection()->transactional(
function () use ($sourceEntity, $targetEntities, $primaryValue, $options) {
- $foreignKey = array_map([$this->_junctionTable, 'aliasField'], (array)$this->getForeignKey());
- $hasMany = $this->getSource()->getAssociation($this->_junctionTable->getAlias());
- $existing = $hasMany->find('all')
- ->where(array_combine($foreignKey, $primaryValue));
-
- $associationConditions = $this->getConditions();
- if ($associationConditions) {
- $existing->contain($this->getTarget()->getAlias());
- $existing->andWhere($associationConditions);
+ $junction = $this->junction();
+ $target = $this->getTarget();
+
+ $foreignKey = (array)$this->getForeignKey();
+ $prefixedForeignKey = array_map([$junction, 'aliasField'], $foreignKey);
+
+ $junctionPrimaryKey = (array)$junction->getPrimaryKey();
+ $assocForeignKey = (array)$junction->getAssociation($target->getAlias())->getForeignKey();
+
+ $keys = array_combine($foreignKey, $prefixedForeignKey);
+ foreach (array_merge($assocForeignKey, $junctionPrimaryKey) as $key) {
+ $keys[$key] = $junction->aliasField($key);
}
+ // Find existing rows so that we can diff with new entities.
+ // Only hydrate primary/foreign key columns to save time.
+ $existing = $this->find()
+ ->select($keys)
+ ->where(array_combine($prefixedForeignKey, $primaryValue));
+ $existing = $this->_appendJunctionJoin($existing);
+
$jointEntities = $this->_collectJointEntities($sourceEntity, $targetEntities);
$inserts = $this->_diffLinks($existing, $jointEntities, $targetEntities, $options);
@@ -1247,7 +1173,7 @@ function () use ($sourceEntity, $targetEntities, $primaryValue, $options) {
$inserted = array_combine(
array_keys($inserts),
(array)$sourceEntity->get($property)
- );
+ ) ?: [];
$targetEntities = $inserted + $targetEntities;
}
@@ -1272,8 +1198,12 @@ function () use ($sourceEntity, $targetEntities, $primaryValue, $options) {
* @param array $options list of options accepted by `Table::delete()`
* @return array
*/
- protected function _diffLinks($existing, $jointEntities, $targetEntities, $options = [])
- {
+ protected function _diffLinks(
+ Query $existing,
+ array $jointEntities,
+ array $targetEntities,
+ array $options = []
+ ): array {
$junction = $this->junction();
$target = $this->getTarget();
$belongsTo = $junction->getAssociation($target->getAlias());
@@ -1338,7 +1268,7 @@ protected function _diffLinks($existing, $jointEntities, $targetEntities, $optio
* @return bool
* @throws \InvalidArgumentException
*/
- protected function _checkPersistenceStatus($sourceEntity, array $targetEntities)
+ protected function _checkPersistenceStatus(EntityInterface $sourceEntity, array $targetEntities): bool
{
if ($sourceEntity->isNew()) {
$error = 'Source entity needs to be persisted before links can be created or removed.';
@@ -1367,7 +1297,7 @@ protected function _checkPersistenceStatus($sourceEntity, array $targetEntities)
* key value
* @return \Cake\Datasource\EntityInterface[]
*/
- protected function _collectJointEntities($sourceEntity, $targetEntities)
+ protected function _collectJointEntities(EntityInterface $sourceEntity, array $targetEntities): array
{
$target = $this->getTarget();
$source = $this->getSource();
@@ -1399,14 +1329,20 @@ protected function _collectJointEntities($sourceEntity, $targetEntities)
$belongsTo = $junction->getAssociation($target->getAlias());
$hasMany = $source->getAssociation($junction->getAlias());
$foreignKey = (array)$this->getForeignKey();
+ $foreignKey = array_map(function ($key) {
+ return $key . ' IS';
+ }, $foreignKey);
$assocForeignKey = (array)$belongsTo->getForeignKey();
+ $assocForeignKey = array_map(function ($key) {
+ return $key . ' IS';
+ }, $assocForeignKey);
$sourceKey = $sourceEntity->extract((array)$source->getPrimaryKey());
$unions = [];
foreach ($missing as $key) {
- $unions[] = $hasMany->find('all')
+ $unions[] = $hasMany->find()
->where(array_combine($foreignKey, $sourceKey))
- ->andWhere(array_combine($assocForeignKey, $key));
+ ->where(array_combine($assocForeignKey, $key));
}
$query = array_shift($unions);
@@ -1424,7 +1360,7 @@ protected function _collectJointEntities($sourceEntity, $targetEntities)
*
* @return string
*/
- protected function _junctionAssociationName()
+ protected function _junctionAssociationName(): string
{
if (!$this->_junctionAssociationName) {
$this->_junctionAssociationName = $this->getTarget()
@@ -1443,7 +1379,7 @@ protected function _junctionAssociationName()
* @param string|null $name The name of the junction table.
* @return string
*/
- protected function _junctionTableName($name = null)
+ protected function _junctionTableName(?string $name = null): string
{
if ($name === null) {
if (empty($this->_junctionTableName)) {
@@ -1467,7 +1403,7 @@ protected function _junctionTableName($name = null)
* @param array $opts original list of options passed in constructor
* @return void
*/
- protected function _options(array $opts)
+ protected function _options(array $opts): void
{
if (!empty($opts['targetForeignKey'])) {
$this->setTargetForeignKey($opts['targetForeignKey']);
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteHelper.php b/app/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteHelper.php
index 7e395c56b..9b6c5161a 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteHelper.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteHelper.php
@@ -1,4 +1,6 @@
getDependent()) {
return true;
}
$table = $association->getTarget();
+ /** @psalm-suppress InvalidArgument */
$foreignKey = array_map([$association, 'aliasField'], (array)$association->getForeignKey());
$bindingKey = (array)$association->getBindingKey();
$conditions = array_combine($foreignKey, $entity->extract($bindingKey));
@@ -51,8 +54,7 @@ public function cascadeDelete(Association $association, EntityInterface $entity,
return true;
}
- $conditions = array_merge($conditions, $association->getConditions());
- return (bool)$table->deleteAll($conditions);
+ return (bool)$association->deleteAll($conditions);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteTrait.php b/app/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteTrait.php
deleted file mode 100644
index 16d30d746..000000000
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteTrait.php
+++ /dev/null
@@ -1,48 +0,0 @@
-cascadeDelete($this, $entity, $options);
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/HasMany.php b/app/vendor/cakephp/cakephp/src/ORM/Association/HasMany.php
index f8c238849..235017b7e 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/HasMany.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/HasMany.php
@@ -1,4 +1,6 @@
getSource();
}
@@ -106,7 +108,7 @@ public function isOwningSide(Table $side)
* @throws \InvalidArgumentException if an invalid strategy name is passed
* @return $this
*/
- public function setSaveStrategy($strategy)
+ public function setSaveStrategy(string $strategy)
{
if (!in_array($strategy, [self::SAVE_APPEND, self::SAVE_REPLACE], true)) {
$msg = sprintf('Invalid save strategy "%s"', $strategy);
@@ -123,33 +125,11 @@ public function setSaveStrategy($strategy)
*
* @return string the strategy to be used for saving
*/
- public function getSaveStrategy()
+ public function getSaveStrategy(): string
{
return $this->_saveStrategy;
}
- /**
- * Sets the strategy that should be used for saving. If called with no
- * arguments, it will return the currently configured strategy
- *
- * @deprecated 3.4.0 Use setSaveStrategy()/getSaveStrategy() instead.
- * @param string|null $strategy the strategy name to be used
- * @throws \InvalidArgumentException if an invalid strategy name is passed
- * @return string the strategy to be used for saving
- */
- public function saveStrategy($strategy = null)
- {
- deprecationWarning(
- 'HasMany::saveStrategy() is deprecated. ' .
- 'Use setSaveStrategy()/getSaveStrategy() instead.'
- );
- if ($strategy !== null) {
- $this->setSaveStrategy($strategy);
- }
-
- return $this->getSaveStrategy();
- }
-
/**
* Takes an entity from the source table and looks if there is a field
* matching the property name for this association. The found entity will be
@@ -158,7 +138,7 @@ public function saveStrategy($strategy = null)
*
* @param \Cake\Datasource\EntityInterface $entity an entity from the source table
* @param array $options options to be passed to the save method in the target table
- * @return \Cake\Datasource\EntityInterface|false False if $entity could not be saved, otherwise it returns
+ * @return \Cake\Datasource\EntityInterface|false false if $entity could not be saved, otherwise it returns
* the saved entity
* @see \Cake\ORM\Table::save()
* @throws \InvalidArgumentException when the association data cannot be traversed.
@@ -179,10 +159,7 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
$targetEntities = [];
}
- if (
- !is_array($targetEntities) &&
- !($targetEntities instanceof Traversable)
- ) {
+ if (!is_iterable($targetEntities)) {
$name = $this->getProperty();
$message = sprintf('Could not save %s, it cannot be traversed', $name);
throw new InvalidArgumentException($message);
@@ -202,6 +179,9 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
return false;
}
+ if (!is_array($targetEntities)) {
+ $targetEntities = iterator_to_array($targetEntities);
+ }
if (!$this->_saveTarget($foreignKeyReference, $entity, $targetEntities, $options)) {
return false;
}
@@ -217,13 +197,17 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
* target entity, and the parent entity.
* @param \Cake\Datasource\EntityInterface $parentEntity The source entity containing the target
* entities to be saved.
- * @param array|\Traversable $entities list of entities to persist in target table and to
- * link to the parent entity
+ * @param array $entities list of entities
+ * to persist in target table and to link to the parent entity
* @param array $options list of options accepted by `Table::save()`.
* @return bool `true` on success, `false` otherwise.
*/
- protected function _saveTarget(array $foreignKeyReference, EntityInterface $parentEntity, $entities, array $options)
- {
+ protected function _saveTarget(
+ array $foreignKeyReference,
+ EntityInterface $parentEntity,
+ array $entities,
+ array $options
+ ): bool {
$foreignKey = array_keys($foreignKeyReference);
$table = $this->getTarget();
$original = $entities;
@@ -248,7 +232,9 @@ protected function _saveTarget(array $foreignKeyReference, EntityInterface $pare
if (!empty($options['atomic'])) {
$original[$k]->setErrors($entity->getErrors());
- $entity->set($this->getProperty(), $original);
+ if ($entity instanceof InvalidPropertyInterface) {
+ $original[$k]->setInvalid($entity->getInvalid());
+ }
return false;
}
@@ -284,7 +270,7 @@ protected function _saveTarget(array $foreignKeyReference, EntityInterface $pare
* @param array $options list of options to be passed to the internal `save` call
* @return bool true on success, false otherwise
*/
- public function link(EntityInterface $sourceEntity, array $targetEntities, array $options = [])
+ public function link(EntityInterface $sourceEntity, array $targetEntities, array $options = []): bool
{
$saveStrategy = $this->getSaveStrategy();
$this->setSaveStrategy(self::SAVE_APPEND);
@@ -349,12 +335,13 @@ public function link(EntityInterface $sourceEntity, array $targetEntities, array
* this association
* @param array $targetEntities list of entities persisted in the target table for
* this association
- * @param array $options list of options to be passed to the internal `delete` call
+ * @param array|bool $options list of options to be passed to the internal `delete` call.
+ * If boolean it will be used a value for "cleanProperty" option.
* @throws \InvalidArgumentException if non persisted entities are passed or if
* any of them is lacking a primary key value
* @return void
*/
- public function unlink(EntityInterface $sourceEntity, array $targetEntities, $options = [])
+ public function unlink(EntityInterface $sourceEntity, array $targetEntities, $options = []): void
{
if (is_bool($options)) {
$options = [
@@ -443,7 +430,7 @@ function ($assoc) use ($targetEntities) {
* any of them is lacking a primary key value
* @return bool success
*/
- public function replace(EntityInterface $sourceEntity, array $targetEntities, array $options = [])
+ public function replace(EntityInterface $sourceEntity, array $targetEntities, array $options = []): bool
{
$property = $this->getProperty();
$sourceEntity->set($property, $targetEntities);
@@ -461,19 +448,24 @@ public function replace(EntityInterface $sourceEntity, array $targetEntities, ar
}
/**
- * Deletes/sets null the related objects according to the dependency between source and targets and foreign key nullability
- * Skips deleting records present in $remainingEntities
+ * Deletes/sets null the related objects according to the dependency between source and targets
+ * and foreign key nullability. Skips deleting records present in $remainingEntities
*
* @param array $foreignKeyReference The foreign key reference defining the link between the
* target entity, and the parent entity.
* @param \Cake\Datasource\EntityInterface $entity the entity which should have its associated entities unassigned
* @param \Cake\ORM\Table $target The associated table
- * @param array $remainingEntities Entities that should not be deleted
+ * @param iterable $remainingEntities Entities that should not be deleted
* @param array $options list of options accepted by `Table::delete()`
* @return bool success
*/
- protected function _unlinkAssociated(array $foreignKeyReference, EntityInterface $entity, Table $target, array $remainingEntities = [], array $options = [])
- {
+ protected function _unlinkAssociated(
+ array $foreignKeyReference,
+ EntityInterface $entity,
+ Table $target,
+ iterable $remainingEntities = [],
+ array $options = []
+ ): bool {
$primaryKey = (array)$target->getPrimaryKey();
$exclusions = new Collection($remainingEntities);
$exclusions = $exclusions->map(
@@ -505,7 +497,9 @@ function ($v) {
/**
* Deletes/sets null the related objects matching $conditions.
- * The action which is taken depends on the dependency between source and targets and also on foreign key nullability
+ *
+ * The action which is taken depends on the dependency between source and
+ * targets and also on foreign key nullability.
*
* @param array $foreignKey array of foreign key properties
* @param \Cake\ORM\Table $target The associated table
@@ -513,19 +507,22 @@ function ($v) {
* @param array $options list of options accepted by `Table::delete()`
* @return bool success
*/
- protected function _unlink(array $foreignKey, Table $target, array $conditions = [], array $options = [])
+ protected function _unlink(array $foreignKey, Table $target, array $conditions = [], array $options = []): bool
{
$mustBeDependent = (!$this->_foreignKeyAcceptsNull($target, $foreignKey) || $this->getDependent());
if ($mustBeDependent) {
if ($this->_cascadeCallbacks) {
$conditions = new QueryExpression($conditions);
- $conditions->traverse(function ($entry) use ($target) {
+ $conditions->traverse(function ($entry) use ($target): void {
if ($entry instanceof FieldInterface) {
- $entry->setField($target->aliasField($entry->getField()));
+ $field = $entry->getField();
+ if (is_string($field)) {
+ $entry->setField($target->aliasField($field));
+ }
}
});
- $query = $this->find('all')->where($conditions);
+ $query = $this->find()->where($conditions);
$ok = true;
foreach ($query as $assoc) {
$ok = $ok && $target->delete($assoc, $options);
@@ -533,6 +530,7 @@ protected function _unlink(array $foreignKey, Table $target, array $conditions =
return $ok;
}
+
$this->deleteAll($conditions);
return true;
@@ -551,7 +549,7 @@ protected function _unlink(array $foreignKey, Table $target, array $conditions =
* @param array $properties the list of fields that compose the foreign key
* @return bool
*/
- protected function _foreignKeyAcceptsNull(Table $table, array $properties)
+ protected function _foreignKeyAcceptsNull(Table $table, array $properties): bool
{
return !in_array(
false,
@@ -569,7 +567,7 @@ function ($prop) use ($table) {
*
* @return string
*/
- public function type()
+ public function type(): string
{
return self::ONE_TO_MANY;
}
@@ -581,7 +579,7 @@ public function type()
* @return bool if the 'matching' key in $option is true then this function
* will return true, false otherwise
*/
- public function canBeJoined(array $options = [])
+ public function canBeJoined(array $options = []): bool
{
return !empty($options['matching']);
}
@@ -589,7 +587,7 @@ public function canBeJoined(array $options = [])
/**
* Gets the name of the field representing the foreign key to the source table.
*
- * @return string
+ * @return string|string[]
*/
public function getForeignKey()
{
@@ -624,30 +622,9 @@ public function getSort()
}
/**
- * Sets the sort order in which target records should be returned.
- * If no arguments are passed the currently configured value is returned
- *
- * @deprecated 3.4.0 Use setSort()/getSort() instead.
- * @param mixed $sort A find() compatible order clause
- * @return mixed
+ * @inheritDoc
*/
- public function sort($sort = null)
- {
- deprecationWarning(
- 'HasMany::sort() is deprecated. ' .
- 'Use setSort()/getSort() instead.'
- );
- if ($sort !== null) {
- $this->setSort($sort);
- }
-
- return $this->getSort();
- }
-
- /**
- * {@inheritDoc}
- */
- public function defaultRowValue($row, $joined)
+ public function defaultRowValue(array $row, bool $joined): array
{
$sourceAlias = $this->getSource()->getAlias();
if (isset($row[$sourceAlias])) {
@@ -663,7 +640,7 @@ public function defaultRowValue($row, $joined)
* @param array $opts original list of options passed in constructor
* @return void
*/
- protected function _options(array $opts)
+ protected function _options(array $opts): void
{
if (!empty($opts['saveStrategy'])) {
$this->setSaveStrategy($opts['saveStrategy']);
@@ -674,11 +651,9 @@ protected function _options(array $opts)
}
/**
- * {@inheritDoc}
- *
- * @return \Closure
+ * @inheritDoc
*/
- public function eagerLoader(array $options)
+ public function eagerLoader(array $options): Closure
{
$loader = new SelectLoader([
'alias' => $this->getAlias(),
@@ -696,9 +671,9 @@ public function eagerLoader(array $options)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function cascadeDelete(EntityInterface $entity, array $options = [])
+ public function cascadeDelete(EntityInterface $entity, array $options = []): bool
{
$helper = new DependentDeleteHelper();
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/HasOne.php b/app/vendor/cakephp/cakephp/src/ORM/Association/HasOne.php
index 14efa63e0..bd10694b7 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/HasOne.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/HasOne.php
@@ -1,4 +1,6 @@
_name);
+ [, $name] = pluginSplit($this->_name);
return Inflector::underscore(Inflector::singularize($name));
}
@@ -73,7 +75,7 @@ protected function _propertyName()
* @param \Cake\ORM\Table $side The potential Table with ownership
* @return bool
*/
- public function isOwningSide(Table $side)
+ public function isOwningSide(Table $side): bool
{
return $side === $this->getSource();
}
@@ -83,7 +85,7 @@ public function isOwningSide(Table $side)
*
* @return string
*/
- public function type()
+ public function type(): string
{
return self::ONE_TO_ONE;
}
@@ -96,7 +98,7 @@ public function type()
*
* @param \Cake\Datasource\EntityInterface $entity an entity from the source table
* @param array $options options to be passed to the save method in the target table
- * @return \Cake\Datasource\EntityInterface|false False if $entity could not be saved, otherwise it returns
+ * @return \Cake\Datasource\EntityInterface|false false if $entity could not be saved, otherwise it returns
* the saved entity
* @see \Cake\ORM\Table::save()
*/
@@ -114,7 +116,7 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
$targetEntity->set($properties, ['guard' => false]);
if (!$this->getTarget()->save($targetEntity, $options)) {
- $targetEntity->unsetProperty(array_keys($properties));
+ $targetEntity->unset(array_keys($properties));
return false;
}
@@ -123,11 +125,9 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
}
/**
- * {@inheritDoc}
- *
- * @return \Closure
+ * @inheritDoc
*/
- public function eagerLoader(array $options)
+ public function eagerLoader(array $options): Closure
{
$loader = new SelectLoader([
'alias' => $this->getAlias(),
@@ -144,9 +144,9 @@ public function eagerLoader(array $options)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function cascadeDelete(EntityInterface $entity, array $options = [])
+ public function cascadeDelete(EntityInterface $entity, array $options = []): bool
{
$helper = new DependentDeleteHelper();
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/Loader/SelectLoader.php b/app/vendor/cakephp/cakephp/src/ORM/Association/Loader/SelectLoader.php
index dabcd497e..421baa087 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/Loader/SelectLoader.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/Loader/SelectLoader.php
@@ -1,4 +1,6 @@
bindingKey = $options['bindingKey'];
$this->finder = $options['finder'];
$this->associationType = $options['associationType'];
- $this->sort = isset($options['sort']) ? $options['sort'] : null;
+ $this->sort = $options['sort'] ?? null;
}
/**
@@ -117,7 +121,7 @@ public function __construct(array $options)
* @param array $options Same options as `Association::eagerLoader()`
* @return \Closure
*/
- public function buildEagerLoader(array $options)
+ public function buildEagerLoader(array $options): Closure
{
$options += $this->_defaultOptions();
$fetchQuery = $this->_buildQuery($options);
@@ -131,7 +135,7 @@ public function buildEagerLoader(array $options)
*
* @return array
*/
- protected function _defaultOptions()
+ protected function _defaultOptions(): array
{
return [
'foreignKey' => $this->foreignKey,
@@ -151,7 +155,7 @@ protected function _defaultOptions()
* @return \Cake\ORM\Query
* @throws \InvalidArgumentException When a key is required for associations but not selected.
*/
- protected function _buildQuery($options)
+ protected function _buildQuery(array $options): Query
{
$key = $this->_linkField($options);
$filter = $options['keys'];
@@ -165,7 +169,7 @@ protected function _buildQuery($options)
/** @var \Cake\ORM\Query $query */
$query = $finder();
if (isset($options['finder'])) {
- list($finderName, $opts) = $this->_extractFinder($options['finder']);
+ [$finderName, $opts] = $this->_extractFinder($options['finder']);
$query = $query->find($finderName, $opts);
}
@@ -215,7 +219,7 @@ protected function _buildQuery($options)
* and options as value.
* @return array
*/
- protected function _extractFinder($finderData)
+ protected function _extractFinder($finderData): array
{
$finderData = (array)$finderData;
@@ -236,7 +240,7 @@ protected function _extractFinder($finderData)
* @return void
* @throws \InvalidArgumentException
*/
- protected function _assertFieldsPresent($fetchQuery, $key)
+ protected function _assertFieldsPresent(Query $fetchQuery, array $key): void
{
$select = $fetchQuery->aliasFields($fetchQuery->clause('select'));
if (empty($select)) {
@@ -279,7 +283,7 @@ protected function _assertFieldsPresent($fetchQuery, $key)
* @param \Cake\ORM\Query $subquery The Subquery to use for filtering
* @return \Cake\ORM\Query
*/
- protected function _addFilteringJoin($query, $key, $subquery)
+ protected function _addFilteringJoin(Query $query, $key, $subquery): Query
{
$filter = [];
$aliasedTable = $this->sourceAlias;
@@ -293,15 +297,13 @@ protected function _addFilteringJoin($query, $key, $subquery)
}
$subquery->select($filter, true);
- $conditions = null;
if (is_array($key)) {
$conditions = $this->_createTupleCondition($query, $key, $filter, '=');
} else {
$filter = current($filter);
+ $conditions = $query->newExpr([$key => $filter]);
}
- $conditions = $conditions ?: $query->newExpr([$key => $filter]);
-
return $query->innerJoin(
[$aliasedTable => $subquery],
$conditions
@@ -317,14 +319,14 @@ protected function _addFilteringJoin($query, $key, $subquery)
* @param mixed $filter The value that should be used to match for $key
* @return \Cake\ORM\Query
*/
- protected function _addFilteringCondition($query, $key, $filter)
+ protected function _addFilteringCondition(Query $query, $key, $filter): Query
{
if (is_array($key)) {
$conditions = $this->_createTupleCondition($query, $key, $filter, 'IN');
+ } else {
+ $conditions = [$key . ' IN' => $filter];
}
- $conditions = isset($conditions) ? $conditions : [$key . ' IN' => $filter];
-
return $query->andWhere($conditions);
}
@@ -338,7 +340,7 @@ protected function _addFilteringCondition($query, $key, $filter)
* @param string $operator The operator for comparing the tuples
* @return \Cake\Database\Expression\TupleComparison
*/
- protected function _createTupleCondition($query, $keys, $filter, $operator)
+ protected function _createTupleCondition(Query $query, array $keys, $filter, $operator): TupleComparison
{
$types = [];
$defaults = $query->getDefaultTypes();
@@ -359,7 +361,7 @@ protected function _createTupleCondition($query, $keys, $filter, $operator)
* @return string|string[]
* @throws \RuntimeException
*/
- protected function _linkField($options)
+ protected function _linkField(array $options)
{
$links = [];
$name = $this->alias;
@@ -370,7 +372,7 @@ protected function _linkField($options)
throw new RuntimeException($msg);
}
- $keys = in_array($this->associationType, [Association::ONE_TO_ONE, Association::ONE_TO_MANY]) ?
+ $keys = in_array($this->associationType, [Association::ONE_TO_ONE, Association::ONE_TO_MANY], true) ?
$this->foreignKey :
$this->bindingKey;
@@ -393,7 +395,7 @@ protected function _linkField($options)
* @param \Cake\ORM\Query $query the original query used to load source records
* @return \Cake\ORM\Query
*/
- protected function _buildSubquery($query)
+ protected function _buildSubquery(Query $query): Query
{
$filterQuery = clone $query;
$filterQuery->disableAutoFields();
@@ -424,7 +426,7 @@ protected function _buildSubquery($query)
* @param \Cake\ORM\Query $query The query to get fields from.
* @return array The list of fields for the subquery.
*/
- protected function _subqueryFields($query)
+ protected function _subqueryFields(Query $query): array
{
$keys = (array)$this->bindingKey;
@@ -438,7 +440,7 @@ protected function _subqueryFields($query)
$order = $query->clause('order');
if ($order) {
$columns = $query->clause('select');
- $order->iterateParts(function ($direction, $field) use (&$fields, $columns) {
+ $order->iterateParts(function ($direction, $field) use (&$fields, $columns): void {
if (isset($columns[$field])) {
$fields[$field] = $columns[$field];
}
@@ -456,7 +458,7 @@ protected function _subqueryFields($query)
* @param array $options The options passed to the eager loader
* @return array
*/
- protected function _buildResultMap($fetchQuery, $options)
+ protected function _buildResultMap(Query $fetchQuery, array $options): array
{
$resultMap = [];
$singleResult = in_array($this->associationType, [Association::MANY_TO_ONE, Association::ONE_TO_ONE], true);
@@ -490,7 +492,7 @@ protected function _buildResultMap($fetchQuery, $options)
* @param array $options The options passed to the eagerLoader method
* @return \Closure
*/
- protected function _resultInjector($fetchQuery, $resultMap, $options)
+ protected function _resultInjector(Query $fetchQuery, array $resultMap, array $options): Closure
{
$keys = $this->associationType === Association::MANY_TO_ONE ?
$this->foreignKey :
@@ -528,7 +530,7 @@ protected function _resultInjector($fetchQuery, $resultMap, $options)
* @param string $nestKey The key under which results should be nested
* @return \Closure
*/
- protected function _multiKeysInjector($resultMap, $sourceKeys, $nestKey)
+ protected function _multiKeysInjector(array $resultMap, array $sourceKeys, string $nestKey): Closure
{
return function ($row) use ($resultMap, $sourceKeys, $nestKey) {
$values = [];
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/Loader/SelectWithPivotLoader.php b/app/vendor/cakephp/cakephp/src/ORM/Association/Loader/SelectWithPivotLoader.php
index df9c81955..128f52f51 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/Loader/SelectWithPivotLoader.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/Loader/SelectWithPivotLoader.php
@@ -1,4 +1,6 @@
junctionAssociationName;
$assoc = $this->junctionAssoc;
@@ -129,7 +132,7 @@ protected function _buildQuery($options)
/**
* @inheritDoc
*/
- protected function _assertFieldsPresent($fetchQuery, $key)
+ protected function _assertFieldsPresent(Query $fetchQuery, array $key): void
{
// _buildQuery() manually adds in required fields from junction table
}
@@ -141,7 +144,7 @@ protected function _assertFieldsPresent($fetchQuery, $key)
* @param array $options the options to use for getting the link field.
* @return string|string[]
*/
- protected function _linkField($options)
+ protected function _linkField(array $options)
{
$links = [];
$name = $this->junctionAssociationName;
@@ -166,7 +169,7 @@ protected function _linkField($options)
* @return array
* @throws \RuntimeException when the association property is not part of the results set.
*/
- protected function _buildResultMap($fetchQuery, $options)
+ protected function _buildResultMap(Query $fetchQuery, array $options): array
{
$resultMap = [];
$key = (array)$options['foreignKey'];
diff --git a/app/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php b/app/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php
index 7ac3f7b83..8bfe8a384 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php
@@ -1,4 +1,6 @@
_tableLocator = $tableLocator;
@@ -64,9 +67,9 @@ public function __construct(LocatorInterface $tableLocator = null)
* @param \Cake\ORM\Association $association The association to add.
* @return \Cake\ORM\Association The association object being added.
*/
- public function add($alias, Association $association)
+ public function add(string $alias, Association $association): Association
{
- list(, $alias) = pluginSplit($alias);
+ [, $alias] = pluginSplit($alias);
return $this->_items[strtolower($alias)] = $association;
}
@@ -80,7 +83,7 @@ public function add($alias, Association $association)
* @return \Cake\ORM\Association
* @throws \InvalidArgumentException
*/
- public function load($className, $associated, array $options = [])
+ public function load(string $className, string $associated, array $options = []): Association
{
$options += [
'tableLocator' => $this->getTableLocator(),
@@ -88,7 +91,11 @@ public function load($className, $associated, array $options = [])
$association = new $className($associated, $options);
if (!$association instanceof Association) {
- $message = sprintf('The association must extend `%s` class, `%s` given.', Association::class, get_class($association));
+ $message = sprintf(
+ 'The association must extend `%s` class, `%s` given.',
+ Association::class,
+ get_class($association)
+ );
throw new InvalidArgumentException($message);
}
@@ -101,7 +108,7 @@ public function load($className, $associated, array $options = [])
* @param string $alias The association alias to get.
* @return \Cake\ORM\Association|null Either the association or null.
*/
- public function get($alias)
+ public function get(string $alias): ?Association
{
$alias = strtolower($alias);
if (isset($this->_items[$alias])) {
@@ -117,7 +124,7 @@ public function get($alias)
* @param string $prop The property to find an association by.
* @return \Cake\ORM\Association|null Either the association or null.
*/
- public function getByProperty($prop)
+ public function getByProperty(string $prop): ?Association
{
foreach ($this->_items as $assoc) {
if ($assoc->getProperty() === $prop) {
@@ -134,7 +141,7 @@ public function getByProperty($prop)
* @param string $alias The association alias to get.
* @return bool Whether or not the association exists.
*/
- public function has($alias)
+ public function has(string $alias): bool
{
return isset($this->_items[strtolower($alias)]);
}
@@ -144,7 +151,7 @@ public function has($alias)
*
* @return string[]
*/
- public function keys()
+ public function keys(): array
{
return array_keys($this->_items);
}
@@ -154,33 +161,15 @@ public function keys()
*
* @param string|array $class The type of associations you want.
* For example 'BelongsTo' or array like ['BelongsTo', 'HasOne']
- * @return array An array of Association objects.
- * @deprecated 3.5.3 Use getByType() instead.
- */
- public function type($class)
- {
- deprecationWarning(
- 'AssociationCollection::type() is deprecated. ' .
- 'Use getByType() instead.'
- );
-
- return $this->getByType($class);
- }
-
- /**
- * Get an array of associations matching a specific type.
- *
- * @param string|string[] $class The type of associations you want.
- * For example 'BelongsTo' or array like ['BelongsTo', 'HasOne']
- * @return array An array of Association objects.
+ * @return \Cake\ORM\Association[] An array of Association objects.
* @since 3.5.3
*/
- public function getByType($class)
+ public function getByType($class): array
{
$class = array_map('strtolower', (array)$class);
$out = array_filter($this->_items, function ($assoc) use ($class) {
- list(, $name) = namespaceSplit(get_class($assoc));
+ [, $name] = namespaceSplit(get_class($assoc));
return in_array(strtolower($name), $class, true);
});
@@ -196,7 +185,7 @@ public function getByType($class)
* @param string $alias The alias name.
* @return void
*/
- public function remove($alias)
+ public function remove(string $alias): void
{
unset($this->_items[strtolower($alias)]);
}
@@ -208,7 +197,7 @@ public function remove($alias)
*
* @return void
*/
- public function removeAll()
+ public function removeAll(): void
{
foreach ($this->_items as $alias => $object) {
$this->remove($alias);
@@ -228,7 +217,7 @@ public function removeAll()
* @param array $options The options for the save operation.
* @return bool Success
*/
- public function saveParents(Table $table, EntityInterface $entity, $associations, array $options = [])
+ public function saveParents(Table $table, EntityInterface $entity, array $associations, array $options = []): bool
{
if (empty($associations)) {
return true;
@@ -250,7 +239,7 @@ public function saveParents(Table $table, EntityInterface $entity, $associations
* @param array $options The options for the save operation.
* @return bool Success
*/
- public function saveChildren(Table $table, EntityInterface $entity, array $associations, array $options)
+ public function saveChildren(Table $table, EntityInterface $entity, array $associations, array $options): bool
{
if (empty($associations)) {
return true;
@@ -271,8 +260,13 @@ public function saveChildren(Table $table, EntityInterface $entity, array $assoc
* @return bool Success
* @throws \InvalidArgumentException When an unknown alias is used.
*/
- protected function _saveAssociations($table, $entity, $associations, $options, $owningSide)
- {
+ protected function _saveAssociations(
+ Table $table,
+ EntityInterface $entity,
+ array $associations,
+ array $options,
+ bool $owningSide
+ ): bool {
unset($options['associated']);
foreach ($associations as $alias => $nested) {
if (is_int($alias)) {
@@ -308,8 +302,12 @@ protected function _saveAssociations($table, $entity, $associations, $options, $
* @param array $options Original options
* @return bool Success
*/
- protected function _save($association, $entity, $nested, $options)
- {
+ protected function _save(
+ Association $association,
+ EntityInterface $entity,
+ array $nested,
+ array $options
+ ): bool {
if (!$entity->isDirty($association->getProperty())) {
return true;
}
@@ -328,7 +326,7 @@ protected function _save($association, $entity, $nested, $options)
* @param array $options The options used in the delete operation.
* @return void
*/
- public function cascadeDelete(EntityInterface $entity, array $options)
+ public function cascadeDelete(EntityInterface $entity, array $options): void
{
$noCascade = $this->_getNoCascadeItems($entity, $options);
foreach ($noCascade as $assoc) {
@@ -343,7 +341,7 @@ public function cascadeDelete(EntityInterface $entity, array $options)
* @param array $options The options used in the delete operation.
* @return \Cake\ORM\Association[]
*/
- protected function _getNoCascadeItems($entity, $options)
+ protected function _getNoCascadeItems(EntityInterface $entity, array $options): array
{
$noCascade = [];
foreach ($this->_items as $assoc) {
@@ -365,7 +363,7 @@ protected function _getNoCascadeItems($entity, $options)
* @param bool|array $keys the list of association names to normalize
* @return array
*/
- public function normalizeKeys($keys)
+ public function normalizeKeys($keys): array
{
if ($keys === true) {
$keys = $this->keys();
@@ -381,9 +379,10 @@ public function normalizeKeys($keys)
/**
* Allow looping through the associations
*
- * @return \ArrayIterator
+ * @return \Cake\ORM\Association[]
+ * @psalm-return \Traversable
*/
- public function getIterator()
+ public function getIterator(): Traversable
{
return new ArrayIterator($this->_items);
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/AssociationsNormalizerTrait.php b/app/vendor/cakephp/cakephp/src/ORM/AssociationsNormalizerTrait.php
index 8c96e4dbc..6d6ba4504 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/AssociationsNormalizerTrait.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/AssociationsNormalizerTrait.php
@@ -1,4 +1,6 @@
$options) {
- $pointer =& $result;
+ $pointer = &$result;
if (is_int($table)) {
$table = $options;
@@ -47,20 +49,20 @@ protected function _normalizeAssociations($associations)
$table = array_pop($path);
$first = array_shift($path);
$pointer += [$first => []];
- $pointer =& $pointer[$first];
+ $pointer = &$pointer[$first];
$pointer += ['associated' => []];
foreach ($path as $t) {
$pointer += ['associated' => []];
$pointer['associated'] += [$t => []];
$pointer['associated'][$t] += ['associated' => []];
- $pointer =& $pointer['associated'][$t];
+ $pointer = &$pointer['associated'][$t];
}
$pointer['associated'] += [$table => []];
$pointer['associated'][$table] = $options + $pointer['associated'][$table];
}
- return isset($result['associated']) ? $result['associated'] : $result;
+ return $result['associated'] ?? $result;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior.php
index 57513505a..d1562d0be 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior.php
@@ -1,4 +1,6 @@
_table;
}
@@ -196,7 +198,7 @@ public function getTable()
* @param array $config The customized method mappings.
* @return array A de-duped list of config data.
*/
- protected function _resolveMethodAliases($key, $defaults, $config)
+ protected function _resolveMethodAliases(string $key, array $defaults, array $config): array
{
if (!isset($defaults[$key], $config[$key])) {
return $config;
@@ -229,7 +231,7 @@ protected function _resolveMethodAliases($key, $defaults, $config)
* @return void
* @throws \Cake\Core\Exception\Exception if config are invalid
*/
- public function verifyConfig()
+ public function verifyConfig(): void
{
$keys = ['implementedFinders', 'implementedMethods'];
foreach ($keys as $key) {
@@ -239,7 +241,11 @@ public function verifyConfig()
foreach ($this->_config[$key] as $method) {
if (!is_callable([$this, $method])) {
- throw new Exception(sprintf('The method %s is not callable on class %s', $method, get_class($this)));
+ throw new Exception(sprintf(
+ 'The method %s is not callable on class %s',
+ $method,
+ static::class
+ ));
}
}
}
@@ -256,11 +262,10 @@ public function verifyConfig()
*
* @return array
*/
- public function implementedEvents()
+ public function implementedEvents(): array
{
$eventMap = [
'Model.beforeMarshal' => 'beforeMarshal',
- 'Model.afterMarshal' => 'afterMarshal',
'Model.beforeFind' => 'beforeFind',
'Model.beforeSave' => 'beforeSave',
'Model.afterSave' => 'afterSave',
@@ -274,7 +279,7 @@ public function implementedEvents()
'Model.afterRules' => 'afterRules',
];
$config = $this->getConfig();
- $priority = isset($config['priority']) ? $config['priority'] : null;
+ $priority = $config['priority'] ?? null;
$events = [];
foreach ($eventMap as $event => $method) {
@@ -316,7 +321,7 @@ public function implementedEvents()
* @return array
* @throws \ReflectionException
*/
- public function implementedFinders()
+ public function implementedFinders(): array
{
$methods = $this->getConfig('implementedFinders');
if (isset($methods)) {
@@ -334,12 +339,12 @@ public function implementedFinders()
* ```
* [
* 'method' => 'method',
- * 'aliasedmethod' => 'somethingElse'
+ * 'aliasedMethod' => 'somethingElse'
* ]
* ```
*
- * With the above example, a call to `$Table->method()` will call `$Behavior->method()`
- * and a call to `$Table->aliasedmethod()` will call `$Behavior->somethingElse()`
+ * With the above example, a call to `$table->method()` will call `$behavior->method()`
+ * and a call to `$table->aliasedMethod()` will call `$behavior->somethingElse()`
*
* It is recommended, though not required, to define implementedFinders in the config property
* of child classes such that it is not necessary to use reflections to derive the available
@@ -348,7 +353,7 @@ public function implementedFinders()
* @return array
* @throws \ReflectionException
*/
- public function implementedMethods()
+ public function implementedMethods(): array
{
$methods = $this->getConfig('implementedMethods');
if (isset($methods)) {
@@ -368,16 +373,16 @@ public function implementedMethods()
* @return array
* @throws \ReflectionException
*/
- protected function _reflectionCache()
+ protected function _reflectionCache(): array
{
- $class = get_class($this);
+ $class = static::class;
if (isset(self::$_reflectionCache[$class])) {
return self::$_reflectionCache[$class];
}
$events = $this->implementedEvents();
$eventMethods = [];
- foreach ($events as $e => $binding) {
+ foreach ($events as $binding) {
if (is_array($binding) && isset($binding['callable'])) {
/** @var string $callable */
$callable = $binding['callable'];
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/CounterCacheBehavior.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/CounterCacheBehavior.php
index f9b63de3e..68746fb06 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior/CounterCacheBehavior.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/CounterCacheBehavior.php
@@ -1,4 +1,6 @@
[
- * 'posts_published' => function (Event $event, EntityInterface $entity, Table $table) {
+ * 'posts_published' => function (EventInterface $event, EntityInterface $entity, Table $table) {
* $query = $table->find('all')->where([
* 'published' => true,
* 'user_id' => $entity->get('user_id')
@@ -112,12 +115,12 @@ class CounterCacheBehavior extends Behavior
*
* Check if a field, which should be ignored, is dirty
*
- * @param \Cake\Event\Event $event The beforeSave event that was fired
+ * @param \Cake\Event\EventInterface $event The beforeSave event that was fired
* @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved
* @param \ArrayObject $options The options for the query
* @return void
*/
- public function beforeSave(Event $event, EntityInterface $entity, $options)
+ public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
{
if (isset($options['ignoreCounterCache']) && $options['ignoreCounterCache'] === true) {
return;
@@ -150,12 +153,12 @@ public function beforeSave(Event $event, EntityInterface $entity, $options)
*
* Makes sure to update counter cache when a new record is created or updated.
*
- * @param \Cake\Event\Event $event The afterSave event that was fired.
+ * @param \Cake\Event\EventInterface $event The afterSave event that was fired.
* @param \Cake\Datasource\EntityInterface $entity The entity that was saved.
* @param \ArrayObject $options The options for the query
* @return void
*/
- public function afterSave(Event $event, EntityInterface $entity, $options)
+ public function afterSave(EventInterface $event, EntityInterface $entity, ArrayObject $options): void
{
if (isset($options['ignoreCounterCache']) && $options['ignoreCounterCache'] === true) {
return;
@@ -170,12 +173,12 @@ public function afterSave(Event $event, EntityInterface $entity, $options)
*
* Makes sure to update counter cache when a record is deleted.
*
- * @param \Cake\Event\Event $event The afterDelete event that was fired.
+ * @param \Cake\Event\EventInterface $event The afterDelete event that was fired.
* @param \Cake\Datasource\EntityInterface $entity The entity that was deleted.
* @param \ArrayObject $options The options for the query
* @return void
*/
- public function afterDelete(Event $event, EntityInterface $entity, $options)
+ public function afterDelete(EventInterface $event, EntityInterface $entity, ArrayObject $options)
{
if (isset($options['ignoreCounterCache']) && $options['ignoreCounterCache'] === true) {
return;
@@ -187,11 +190,11 @@ public function afterDelete(Event $event, EntityInterface $entity, $options)
/**
* Iterate all associations and update counter caches.
*
- * @param \Cake\Event\Event $event Event instance.
+ * @param \Cake\Event\EventInterface $event Event instance.
* @param \Cake\Datasource\EntityInterface $entity Entity.
* @return void
*/
- protected function _processAssociations(Event $event, EntityInterface $entity)
+ protected function _processAssociations(EventInterface $event, EntityInterface $entity): void
{
foreach ($this->_config as $assoc => $settings) {
$assoc = $this->_table->getAssociation($assoc);
@@ -202,21 +205,33 @@ protected function _processAssociations(Event $event, EntityInterface $entity)
/**
* Updates counter cache for a single association
*
- * @param \Cake\Event\Event $event Event instance.
+ * @param \Cake\Event\EventInterface $event Event instance.
* @param \Cake\Datasource\EntityInterface $entity Entity
* @param \Cake\ORM\Association $assoc The association object
* @param array $settings The settings for for counter cache for this association
* @return void
* @throws \RuntimeException If invalid callable is passed.
*/
- protected function _processAssociation(Event $event, EntityInterface $entity, Association $assoc, array $settings)
- {
+ protected function _processAssociation(
+ EventInterface $event,
+ EntityInterface $entity,
+ Association $assoc,
+ array $settings
+ ): void {
$foreignKeys = (array)$assoc->getForeignKey();
- $primaryKeys = (array)$assoc->getBindingKey();
$countConditions = $entity->extract($foreignKeys);
+
+ foreach ($countConditions as $field => $value) {
+ if ($value === null) {
+ $countConditions[$field . ' IS'] = $value;
+ unset($countConditions[$field]);
+ }
+ }
+
+ $primaryKeys = (array)$assoc->getBindingKey();
$updateConditions = array_combine($primaryKeys, $countConditions);
- $countOriginalConditions = $entity->extractOriginalChanged($foreignKeys);
+ $countOriginalConditions = $entity->extractOriginalChanged($foreignKeys);
if ($countOriginalConditions !== []) {
$updateOriginalConditions = array_combine($primaryKeys, $countOriginalConditions);
}
@@ -234,23 +249,19 @@ protected function _processAssociation(Event $event, EntityInterface $entity, As
continue;
}
- if (is_callable($config)) {
- if (is_string($config)) {
- throw new RuntimeException('You must not use a string as callable.');
+ if ($this->_shouldUpdateCount($updateConditions)) {
+ if ($config instanceof Closure) {
+ $count = $config($event, $entity, $this->_table, false);
+ } else {
+ $count = $this->_getCount($config, $countConditions);
+ }
+ if ($count !== false) {
+ $assoc->getTarget()->updateAll([$field => $count], $updateConditions);
}
- $count = $config($event, $entity, $this->_table, false);
- } else {
- $count = $this->_getCount($config, $countConditions);
- }
- if ($count !== false) {
- $assoc->getTarget()->updateAll([$field => $count], $updateConditions);
}
- if (isset($updateOriginalConditions)) {
- if (is_callable($config)) {
- if (is_string($config)) {
- throw new RuntimeException('You must not use a string as callable.');
- }
+ if (isset($updateOriginalConditions) && $this->_shouldUpdateCount($updateOriginalConditions)) {
+ if ($config instanceof Closure) {
$count = $config($event, $entity, $this->_table, true);
} else {
$count = $this->_getCount($config, $countOriginalConditions);
@@ -262,6 +273,19 @@ protected function _processAssociation(Event $event, EntityInterface $entity, As
}
}
+ /**
+ * Checks if the count should be updated given a set of conditions.
+ *
+ * @param array $conditions Conditions to update count.
+ * @return bool True if the count update should happen, false otherwise.
+ */
+ protected function _shouldUpdateCount(array $conditions)
+ {
+ return !empty(array_filter($conditions, function ($value) {
+ return $value !== null;
+ }));
+ }
+
/**
* Fetches and returns the count for a single field in an association
*
@@ -269,7 +293,7 @@ protected function _processAssociation(Event $event, EntityInterface $entity, As
* @param array $conditions Additional conditions given to the query
* @return int The number of relations matching the given config and conditions
*/
- protected function _getCount(array $config, array $conditions)
+ protected function _getCount(array $config, array $conditions): int
{
$finder = 'all';
if (!empty($config['finder'])) {
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TimestampBehavior.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TimestampBehavior.php
index 71a8e8bd2..dfeb29137 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TimestampBehavior.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TimestampBehavior.php
@@ -1,4 +1,6 @@
setConfig('events', $config['events'], false);
@@ -83,13 +87,13 @@ public function initialize(array $config)
/**
* There is only one event handler, it can be configured to be called for any event
*
- * @param \Cake\Event\Event $event Event instance.
+ * @param \Cake\Event\EventInterface $event Event instance.
* @param \Cake\Datasource\EntityInterface $entity Entity instance.
* @throws \UnexpectedValueException if a field's when value is misdefined
* @return true Returns true irrespective of the behavior logic, the save will not be prevented.
* @throws \UnexpectedValueException When the value for an event is not 'always', 'new' or 'existing'
*/
- public function handleEvent(Event $event, EntityInterface $entity)
+ public function handleEvent(EventInterface $event, EntityInterface $entity): bool
{
$eventName = $event->getName();
$events = $this->_config['events'];
@@ -98,15 +102,22 @@ public function handleEvent(Event $event, EntityInterface $entity)
$refresh = $this->_config['refreshTimestamp'];
foreach ($events[$eventName] as $field => $when) {
- if (!in_array($when, ['always', 'new', 'existing'])) {
- throw new UnexpectedValueException(
- sprintf('When should be one of "always", "new" or "existing". The passed value "%s" is invalid', $when)
- );
+ if (!in_array($when, ['always', 'new', 'existing'], true)) {
+ throw new UnexpectedValueException(sprintf(
+ 'When should be one of "always", "new" or "existing". The passed value "%s" is invalid',
+ $when
+ ));
}
if (
$when === 'always' ||
- ($when === 'new' && $new) ||
- ($when === 'existing' && !$new)
+ (
+ $when === 'new' &&
+ $new
+ ) ||
+ (
+ $when === 'existing' &&
+ !$new
+ )
) {
$this->_updateField($entity, $field, $refresh);
}
@@ -122,7 +133,7 @@ public function handleEvent(Event $event, EntityInterface $entity)
*
* @return array
*/
- public function implementedEvents()
+ public function implementedEvents(): array
{
return array_fill_keys(array_keys($this->_config['events']), 'handleEvent');
}
@@ -134,11 +145,11 @@ public function implementedEvents()
* If an explicit date time is passed, the config option `refreshTimestamp` is
* automatically set to false.
*
- * @param \DateTime|null $ts Timestamp
+ * @param \DateTimeInterface|null $ts Timestamp
* @param bool $refreshTimestamp If true timestamp is refreshed.
* @return \Cake\I18n\Time
*/
- public function timestamp(DateTime $ts = null, $refreshTimestamp = false)
+ public function timestamp(?DateTimeInterface $ts = null, bool $refreshTimestamp = false): DateTimeInterface
{
if ($ts) {
if ($this->_config['refreshTimestamp']) {
@@ -163,7 +174,7 @@ public function timestamp(DateTime $ts = null, $refreshTimestamp = false)
* @param string $eventName Event name.
* @return bool true if a field is updated, false if no action performed
*/
- public function touch(EntityInterface $entity, $eventName = 'Model.beforeSave')
+ public function touch(EntityInterface $entity, string $eventName = 'Model.beforeSave'): bool
{
$events = $this->_config['events'];
if (empty($events[$eventName])) {
@@ -192,7 +203,7 @@ public function touch(EntityInterface $entity, $eventName = 'Model.beforeSave')
* @param bool $refreshTimestamp Whether to refresh timestamp.
* @return void
*/
- protected function _updateField($entity, $field, $refreshTimestamp)
+ protected function _updateField(EntityInterface $entity, string $field, bool $refreshTimestamp): void
{
if ($entity->isDirty($field)) {
return;
@@ -206,13 +217,10 @@ protected function _updateField($entity, $field, $refreshTimestamp)
}
/** @var \Cake\Database\Type\DateTimeType $type */
- $type = Type::build($columnType);
-
- if (!$type instanceof Type\DateTimeType) {
- deprecationWarning('TimestampBehavior support for column types other than DateTimeType will be removed in 4.0.');
- $entity->set($field, (string)$ts);
+ $type = TypeFactory::build($columnType);
- return;
+ if (!$type instanceof DateTimeType) {
+ throw new RuntimeException('TimestampBehavior only supports columns of type DateTimeType.');
}
$class = $type->getDateTimeClassName();
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/EavStrategy.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/EavStrategy.php
new file mode 100644
index 000000000..5c33edfb9
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/EavStrategy.php
@@ -0,0 +1,510 @@
+ [],
+ 'translationTable' => 'I18n',
+ 'defaultLocale' => null,
+ 'referenceName' => null,
+ 'allowEmptyTranslations' => true,
+ 'onlyTranslated' => false,
+ 'strategy' => 'subquery',
+ 'tableLocator' => null,
+ 'validator' => false,
+ ];
+
+ /**
+ * Constructor
+ *
+ * @param \Cake\ORM\Table $table The table this strategy is attached to.
+ * @param array $config The config for this strategy.
+ */
+ public function __construct(Table $table, array $config = [])
+ {
+ if (isset($config['tableLocator'])) {
+ $this->_tableLocator = $config['tableLocator'];
+ }
+
+ $this->setConfig($config);
+ $this->table = $table;
+ $this->translationTable = $this->getTableLocator()->get($this->_config['translationTable']);
+
+ $this->setupAssociations();
+ }
+
+ /**
+ * Creates the associations between the bound table and every field passed to
+ * this method.
+ *
+ * Additionally it creates a `i18n` HasMany association that will be
+ * used for fetching all translations for each record in the bound table.
+ *
+ * @return void
+ */
+ protected function setupAssociations()
+ {
+ $fields = $this->_config['fields'];
+ $table = $this->_config['translationTable'];
+ $model = $this->_config['referenceName'];
+ $strategy = $this->_config['strategy'];
+ $filter = $this->_config['onlyTranslated'];
+
+ $targetAlias = $this->translationTable->getAlias();
+ $alias = $this->table->getAlias();
+ $tableLocator = $this->getTableLocator();
+
+ foreach ($fields as $field) {
+ $name = $alias . '_' . $field . '_translation';
+
+ if (!$tableLocator->exists($name)) {
+ $fieldTable = $tableLocator->get($name, [
+ 'className' => $table,
+ 'alias' => $name,
+ 'table' => $this->translationTable->getTable(),
+ ]);
+ } else {
+ $fieldTable = $tableLocator->get($name);
+ }
+
+ $conditions = [
+ $name . '.model' => $model,
+ $name . '.field' => $field,
+ ];
+ if (!$this->_config['allowEmptyTranslations']) {
+ $conditions[$name . '.content !='] = '';
+ }
+
+ $this->table->hasOne($name, [
+ 'targetTable' => $fieldTable,
+ 'foreignKey' => 'foreign_key',
+ 'joinType' => $filter ? Query::JOIN_TYPE_INNER : Query::JOIN_TYPE_LEFT,
+ 'conditions' => $conditions,
+ 'propertyName' => $field . '_translation',
+ ]);
+ }
+
+ $conditions = ["$targetAlias.model" => $model];
+ if (!$this->_config['allowEmptyTranslations']) {
+ $conditions["$targetAlias.content !="] = '';
+ }
+
+ $this->table->hasMany($targetAlias, [
+ 'className' => $table,
+ 'foreignKey' => 'foreign_key',
+ 'strategy' => $strategy,
+ 'conditions' => $conditions,
+ 'propertyName' => '_i18n',
+ 'dependent' => true,
+ ]);
+ }
+
+ /**
+ * Callback method that listens to the `beforeFind` event in the bound
+ * table. It modifies the passed query by eager loading the translated fields
+ * and adding a formatter to copy the values into the main table records.
+ *
+ * @param \Cake\Event\EventInterface $event The beforeFind event that was fired.
+ * @param \Cake\ORM\Query $query Query
+ * @param \ArrayObject $options The options for the query
+ * @return void
+ */
+ public function beforeFind(EventInterface $event, Query $query, ArrayObject $options)
+ {
+ $locale = $this->getLocale();
+
+ if ($locale === $this->getConfig('defaultLocale')) {
+ return;
+ }
+
+ $conditions = function ($field, $locale, $query, $select) {
+ return function ($q) use ($field, $locale, $query, $select) {
+ $q->where([$q->getRepository()->aliasField('locale') => $locale]);
+
+ if (
+ $query->isAutoFieldsEnabled() ||
+ in_array($field, $select, true) ||
+ in_array($this->table->aliasField($field), $select, true)
+ ) {
+ $q->select(['id', 'content']);
+ }
+
+ return $q;
+ };
+ };
+
+ $contain = [];
+ $fields = $this->_config['fields'];
+ $alias = $this->table->getAlias();
+ $select = $query->clause('select');
+
+ $changeFilter = isset($options['filterByCurrentLocale']) &&
+ $options['filterByCurrentLocale'] !== $this->_config['onlyTranslated'];
+
+ foreach ($fields as $field) {
+ $name = $alias . '_' . $field . '_translation';
+
+ $contain[$name]['queryBuilder'] = $conditions(
+ $field,
+ $locale,
+ $query,
+ $select
+ );
+
+ if ($changeFilter) {
+ $filter = $options['filterByCurrentLocale']
+ ? Query::JOIN_TYPE_INNER
+ : Query::JOIN_TYPE_LEFT;
+ $contain[$name]['joinType'] = $filter;
+ }
+ }
+
+ $query->contain($contain);
+ $query->formatResults(function ($results) use ($locale) {
+ return $this->rowMapper($results, $locale);
+ }, $query::PREPEND);
+ }
+
+ /**
+ * Modifies the entity before it is saved so that translated fields are persisted
+ * in the database too.
+ *
+ * @param \Cake\Event\EventInterface $event The beforeSave event that was fired
+ * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved
+ * @param \ArrayObject $options the options passed to the save method
+ * @return void
+ */
+ public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
+ {
+ $locale = $entity->get('_locale') ?: $this->getLocale();
+ $newOptions = [$this->translationTable->getAlias() => ['validate' => false]];
+ $options['associated'] = $newOptions + $options['associated'];
+
+ // Check early if empty translations are present in the entity.
+ // If this is the case, unset them to prevent persistence.
+ // This only applies if $this->_config['allowEmptyTranslations'] is false
+ if ($this->_config['allowEmptyTranslations'] === false) {
+ $this->unsetEmptyFields($entity);
+ }
+
+ $this->bundleTranslatedFields($entity);
+ $bundled = $entity->get('_i18n') ?: [];
+ $noBundled = count($bundled) === 0;
+
+ // No additional translation records need to be saved,
+ // as the entity is in the default locale.
+ if ($noBundled && $locale === $this->getConfig('defaultLocale')) {
+ return;
+ }
+
+ $values = $entity->extract($this->_config['fields'], true);
+ $fields = array_keys($values);
+ $noFields = empty($fields);
+
+ // If there are no fields and no bundled translations, or both fields
+ // in the default locale and bundled translations we can
+ // skip the remaining logic as its not necessary.
+ if ($noFields && $noBundled || ($fields && $bundled)) {
+ return;
+ }
+
+ $primaryKey = (array)$this->table->getPrimaryKey();
+ $key = $entity->get(current($primaryKey));
+
+ // When we have no key and bundled translations, we
+ // need to mark the entity dirty so the root
+ // entity persists.
+ if ($noFields && $bundled && !$key) {
+ foreach ($this->_config['fields'] as $field) {
+ $entity->setDirty($field, true);
+ }
+
+ return;
+ }
+
+ if ($noFields) {
+ return;
+ }
+
+ $model = $this->_config['referenceName'];
+
+ $preexistent = [];
+ if ($key) {
+ /** @psalm-suppress UndefinedClass */
+ $preexistent = $this->translationTable->find()
+ ->select(['id', 'field'])
+ ->where([
+ 'field IN' => $fields,
+ 'locale' => $locale,
+ 'foreign_key' => $key,
+ 'model' => $model,
+ ])
+ ->disableBufferedResults()
+ ->all()
+ ->indexBy('field');
+ }
+
+ $modified = [];
+ foreach ($preexistent as $field => $translation) {
+ $translation->set('content', $values[$field]);
+ $modified[$field] = $translation;
+ }
+
+ $new = array_diff_key($values, $modified);
+ foreach ($new as $field => $content) {
+ $new[$field] = new Entity(compact('locale', 'field', 'content', 'model'), [
+ 'useSetters' => false,
+ 'markNew' => true,
+ ]);
+ }
+
+ $entity->set('_i18n', array_merge($bundled, array_values($modified + $new)));
+ $entity->set('_locale', $locale, ['setter' => false]);
+ $entity->setDirty('_locale', false);
+
+ foreach ($fields as $field) {
+ $entity->setDirty($field, false);
+ }
+ }
+
+ /**
+ * Returns a fully aliased field name for translated fields.
+ *
+ * If the requested field is configured as a translation field, the `content`
+ * field with an alias of a corresponding association is returned. Table-aliased
+ * field name is returned for all other fields.
+ *
+ * @param string $field Field name to be aliased.
+ * @return string
+ */
+ public function translationField(string $field): string
+ {
+ $table = $this->table;
+ if ($this->getLocale() === $this->getConfig('defaultLocale')) {
+ return $table->aliasField($field);
+ }
+ $associationName = $table->getAlias() . '_' . $field . '_translation';
+
+ if ($table->associations()->has($associationName)) {
+ return $associationName . '.content';
+ }
+
+ return $table->aliasField($field);
+ }
+
+ /**
+ * Modifies the results from a table find in order to merge the translated fields
+ * into each entity for a given locale.
+ *
+ * @param \Cake\Datasource\ResultSetInterface $results Results to map.
+ * @param string $locale Locale string
+ * @return \Cake\Collection\CollectionInterface
+ */
+ protected function rowMapper($results, $locale)
+ {
+ return $results->map(function ($row) use ($locale) {
+ /** @var \Cake\Datasource\EntityInterface|array|null $row */
+ if ($row === null) {
+ return $row;
+ }
+ $hydrated = !is_array($row);
+
+ foreach ($this->_config['fields'] as $field) {
+ $name = $field . '_translation';
+ $translation = $row[$name] ?? null;
+
+ if ($translation === null || $translation === false) {
+ unset($row[$name]);
+ continue;
+ }
+
+ $content = $translation['content'] ?? null;
+ if ($content !== null) {
+ $row[$field] = $content;
+ }
+
+ unset($row[$name]);
+ }
+
+ $row['_locale'] = $locale;
+ if ($hydrated) {
+ $row->clean();
+ }
+
+ return $row;
+ });
+ }
+
+ /**
+ * Modifies the results from a table find in order to merge full translation
+ * records into each entity under the `_translations` key.
+ *
+ * @param \Cake\Datasource\ResultSetInterface $results Results to modify.
+ * @return \Cake\Collection\CollectionInterface
+ */
+ public function groupTranslations($results): CollectionInterface
+ {
+ return $results->map(function ($row) {
+ if (!$row instanceof EntityInterface) {
+ return $row;
+ }
+ $translations = (array)$row->get('_i18n');
+ if (empty($translations) && $row->get('_translations')) {
+ return $row;
+ }
+ $grouped = new Collection($translations);
+
+ $result = [];
+ foreach ($grouped->combine('field', 'content', 'locale') as $locale => $keys) {
+ $entityClass = $this->table->getEntityClass();
+ $translation = new $entityClass($keys + ['locale' => $locale], [
+ 'markNew' => false,
+ 'useSetters' => false,
+ 'markClean' => true,
+ ]);
+ $result[$locale] = $translation;
+ }
+
+ $options = ['setter' => false, 'guard' => false];
+ $row->set('_translations', $result, $options);
+ unset($row['_i18n']);
+ $row->clean();
+
+ return $row;
+ });
+ }
+
+ /**
+ * Helper method used to generated multiple translated field entities
+ * out of the data found in the `_translations` property in the passed
+ * entity. The result will be put into its `_i18n` property.
+ *
+ * @param \Cake\Datasource\EntityInterface $entity Entity
+ * @return void
+ */
+ protected function bundleTranslatedFields($entity)
+ {
+ $translations = (array)$entity->get('_translations');
+
+ if (empty($translations) && !$entity->isDirty('_translations')) {
+ return;
+ }
+
+ $fields = $this->_config['fields'];
+ $primaryKey = (array)$this->table->getPrimaryKey();
+ $key = $entity->get(current($primaryKey));
+ $find = [];
+ $contents = [];
+
+ foreach ($translations as $lang => $translation) {
+ foreach ($fields as $field) {
+ if (!$translation->isDirty($field)) {
+ continue;
+ }
+ $find[] = ['locale' => $lang, 'field' => $field, 'foreign_key IS' => $key];
+ $contents[] = new Entity(['content' => $translation->get($field)], [
+ 'useSetters' => false,
+ ]);
+ }
+ }
+
+ if (empty($find)) {
+ return;
+ }
+
+ $results = $this->findExistingTranslations($find);
+
+ foreach ($find as $i => $translation) {
+ if (!empty($results[$i])) {
+ $contents[$i]->set('id', $results[$i], ['setter' => false]);
+ $contents[$i]->setNew(false);
+ } else {
+ $translation['model'] = $this->_config['referenceName'];
+ $contents[$i]->set($translation, ['setter' => false, 'guard' => false]);
+ $contents[$i]->setNew(true);
+ }
+ }
+
+ $entity->set('_i18n', $contents);
+ }
+
+ /**
+ * Returns the ids found for each of the condition arrays passed for the
+ * translations table. Each records is indexed by the corresponding position
+ * to the conditions array.
+ *
+ * @param array $ruleSet An array of array of conditions to be used for finding each
+ * @return array
+ */
+ protected function findExistingTranslations($ruleSet)
+ {
+ $association = $this->table->getAssociation($this->translationTable->getAlias());
+
+ $query = $association->find()
+ ->select(['id', 'num' => 0])
+ ->where(current($ruleSet))
+ ->disableHydration()
+ ->disableBufferedResults();
+
+ unset($ruleSet[0]);
+ foreach ($ruleSet as $i => $conditions) {
+ $q = $association->find()
+ ->select(['id', 'num' => $i])
+ ->where($conditions);
+ $query->unionAll($q);
+ }
+
+ return $query->all()->combine('num', 'id')->toArray();
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/ShadowTableStrategy.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/ShadowTableStrategy.php
new file mode 100644
index 000000000..4365a7f73
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/ShadowTableStrategy.php
@@ -0,0 +1,596 @@
+ [],
+ 'defaultLocale' => null,
+ 'referenceName' => null,
+ 'allowEmptyTranslations' => true,
+ 'onlyTranslated' => false,
+ 'strategy' => 'subquery',
+ 'tableLocator' => null,
+ 'validator' => false,
+ ];
+
+ /**
+ * Constructor
+ *
+ * @param \Cake\ORM\Table $table Table instance.
+ * @param array $config Configuration.
+ */
+ public function __construct(Table $table, array $config = [])
+ {
+ $tableAlias = $table->getAlias();
+ [$plugin] = pluginSplit($table->getRegistryAlias(), true);
+ $tableReferenceName = $config['referenceName'];
+
+ $config += [
+ 'mainTableAlias' => $tableAlias,
+ 'translationTable' => $plugin . $tableReferenceName . 'Translations',
+ 'hasOneAlias' => $tableAlias . 'Translation',
+ ];
+
+ if (isset($config['tableLocator'])) {
+ $this->_tableLocator = $config['tableLocator'];
+ }
+
+ $this->setConfig($config);
+ $this->table = $table;
+ $this->translationTable = $this->getTableLocator()->get($this->_config['translationTable']);
+
+ $this->setupAssociations();
+ }
+
+ /**
+ * Create a hasMany association for all records.
+ *
+ * Don't create a hasOne association here as the join conditions are modified
+ * in before find - so create/modify it there.
+ *
+ * @return void
+ */
+ protected function setupAssociations()
+ {
+ $config = $this->getConfig();
+
+ $this->table->hasMany($config['translationTable'], [
+ 'className' => $config['translationTable'],
+ 'foreignKey' => 'id',
+ 'strategy' => $config['strategy'],
+ 'propertyName' => '_i18n',
+ 'dependent' => true,
+ ]);
+ }
+
+ /**
+ * Callback method that listens to the `beforeFind` event in the bound
+ * table. It modifies the passed query by eager loading the translated fields
+ * and adding a formatter to copy the values into the main table records.
+ *
+ * @param \Cake\Event\EventInterface $event The beforeFind event that was fired.
+ * @param \Cake\ORM\Query $query Query.
+ * @param \ArrayObject $options The options for the query.
+ * @return void
+ */
+ public function beforeFind(EventInterface $event, Query $query, ArrayObject $options)
+ {
+ $locale = $this->getLocale();
+
+ if ($locale === $this->getConfig('defaultLocale')) {
+ return;
+ }
+
+ $config = $this->getConfig();
+
+ if (isset($options['filterByCurrentLocale'])) {
+ $joinType = $options['filterByCurrentLocale'] ? 'INNER' : 'LEFT';
+ } else {
+ $joinType = $config['onlyTranslated'] ? 'INNER' : 'LEFT';
+ }
+
+ $this->table->hasOne($config['hasOneAlias'], [
+ 'foreignKey' => ['id'],
+ 'joinType' => $joinType,
+ 'propertyName' => 'translation',
+ 'className' => $config['translationTable'],
+ 'conditions' => [
+ $config['hasOneAlias'] . '.locale' => $locale,
+ ],
+ ]);
+
+ $fieldsAdded = $this->addFieldsToQuery($query, $config);
+ $orderByTranslatedField = $this->iterateClause($query, 'order', $config);
+ $filteredByTranslatedField = $this->traverseClause($query, 'where', $config);
+
+ if (!$fieldsAdded && !$orderByTranslatedField && !$filteredByTranslatedField) {
+ return;
+ }
+
+ $query->contain([$config['hasOneAlias']]);
+
+ $query->formatResults(function ($results) use ($locale) {
+ return $this->rowMapper($results, $locale);
+ }, $query::PREPEND);
+ }
+
+ /**
+ * Add translation fields to query.
+ *
+ * If the query is using autofields (directly or implicitly) add the
+ * main table's fields to the query first.
+ *
+ * Only add translations for fields that are in the main table, always
+ * add the locale field though.
+ *
+ * @param \Cake\ORM\Query $query The query to check.
+ * @param array $config The config to use for adding fields.
+ * @return bool Whether a join to the translation table is required.
+ */
+ protected function addFieldsToQuery($query, array $config)
+ {
+ if ($query->isAutoFieldsEnabled()) {
+ return true;
+ }
+
+ $select = array_filter($query->clause('select'), function ($field) {
+ return is_string($field);
+ });
+
+ if (!$select) {
+ return true;
+ }
+
+ $alias = $config['mainTableAlias'];
+ $joinRequired = false;
+ foreach ($this->translatedFields() as $field) {
+ if (array_intersect($select, [$field, "$alias.$field"])) {
+ $joinRequired = true;
+ $query->select($query->aliasField($field, $config['hasOneAlias']));
+ }
+ }
+
+ if ($joinRequired) {
+ $query->select($query->aliasField('locale', $config['hasOneAlias']));
+ }
+
+ return $joinRequired;
+ }
+
+ /**
+ * Iterate over a clause to alias fields.
+ *
+ * The objective here is to transparently prevent ambiguous field errors by
+ * prefixing fields with the appropriate table alias. This method currently
+ * expects to receive an order clause only.
+ *
+ * @param \Cake\ORM\Query $query the query to check.
+ * @param string $name The clause name.
+ * @param array $config The config to use for adding fields.
+ * @return bool Whether a join to the translation table is required.
+ */
+ protected function iterateClause($query, $name = '', $config = []): bool
+ {
+ $clause = $query->clause($name);
+ if (!$clause || !$clause->count()) {
+ return false;
+ }
+
+ $alias = $config['hasOneAlias'];
+ $fields = $this->translatedFields();
+ $mainTableAlias = $config['mainTableAlias'];
+ $mainTableFields = $this->mainFields();
+ $joinRequired = false;
+
+ $clause->iterateParts(
+ function ($c, &$field) use ($fields, $alias, $mainTableAlias, $mainTableFields, &$joinRequired) {
+ if (!is_string($field) || strpos($field, '.')) {
+ return $c;
+ }
+
+ if (in_array($field, $fields, true)) {
+ $joinRequired = true;
+ $field = "$alias.$field";
+ } elseif (in_array($field, $mainTableFields, true)) {
+ $field = "$mainTableAlias.$field";
+ }
+
+ return $c;
+ }
+ );
+
+ return $joinRequired;
+ }
+
+ /**
+ * Traverse over a clause to alias fields.
+ *
+ * The objective here is to transparently prevent ambiguous field errors by
+ * prefixing fields with the appropriate table alias. This method currently
+ * expects to receive a where clause only.
+ *
+ * @param \Cake\ORM\Query $query the query to check.
+ * @param string $name The clause name.
+ * @param array $config The config to use for adding fields.
+ * @return bool Whether a join to the translation table is required.
+ */
+ protected function traverseClause($query, $name = '', $config = []): bool
+ {
+ $clause = $query->clause($name);
+ if (!$clause || !$clause->count()) {
+ return false;
+ }
+
+ $alias = $config['hasOneAlias'];
+ $fields = $this->translatedFields();
+ $mainTableAlias = $config['mainTableAlias'];
+ $mainTableFields = $this->mainFields();
+ $joinRequired = false;
+
+ $clause->traverse(
+ function ($expression) use ($fields, $alias, $mainTableAlias, $mainTableFields, &$joinRequired) {
+ if (!($expression instanceof FieldInterface)) {
+ return;
+ }
+ $field = $expression->getField();
+ if (!is_string($field) || strpos($field, '.')) {
+ return;
+ }
+
+ if (in_array($field, $fields, true)) {
+ $joinRequired = true;
+ $expression->setField("$alias.$field");
+
+ return;
+ }
+
+ if (in_array($field, $mainTableFields, true)) {
+ $expression->setField("$mainTableAlias.$field");
+ }
+ }
+ );
+
+ return $joinRequired;
+ }
+
+ /**
+ * Modifies the entity before it is saved so that translated fields are persisted
+ * in the database too.
+ *
+ * @param \Cake\Event\EventInterface $event The beforeSave event that was fired.
+ * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved.
+ * @param \ArrayObject $options the options passed to the save method.
+ * @return void
+ */
+ public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
+ {
+ $locale = $entity->get('_locale') ?: $this->getLocale();
+ $newOptions = [$this->translationTable->getAlias() => ['validate' => false]];
+ $options['associated'] = $newOptions + $options['associated'];
+
+ // Check early if empty translations are present in the entity.
+ // If this is the case, unset them to prevent persistence.
+ // This only applies if $this->_config['allowEmptyTranslations'] is false
+ if ($this->_config['allowEmptyTranslations'] === false) {
+ $this->unsetEmptyFields($entity);
+ }
+
+ $this->bundleTranslatedFields($entity);
+ $bundled = $entity->get('_i18n') ?: [];
+ $noBundled = count($bundled) === 0;
+
+ // No additional translation records need to be saved,
+ // as the entity is in the default locale.
+ if ($noBundled && $locale === $this->getConfig('defaultLocale')) {
+ return;
+ }
+
+ $values = $entity->extract($this->translatedFields(), true);
+ $fields = array_keys($values);
+ $noFields = empty($fields);
+
+ // If there are no fields and no bundled translations, or both fields
+ // in the default locale and bundled translations we can
+ // skip the remaining logic as its not necessary.
+ if ($noFields && $noBundled || ($fields && $bundled)) {
+ return;
+ }
+
+ $primaryKey = (array)$this->table->getPrimaryKey();
+ $id = $entity->get(current($primaryKey));
+
+ // When we have no key and bundled translations, we
+ // need to mark the entity dirty so the root
+ // entity persists.
+ if ($noFields && $bundled && !$id) {
+ foreach ($this->translatedFields() as $field) {
+ $entity->setDirty($field, true);
+ }
+
+ return;
+ }
+
+ if ($noFields) {
+ return;
+ }
+
+ $where = ['locale' => $locale];
+ $translation = null;
+ if ($id) {
+ $where['id'] = $id;
+
+ /** @var \Cake\Datasource\EntityInterface|null $translation */
+ $translation = $this->translationTable->find()
+ ->select(array_merge(['id', 'locale'], $fields))
+ ->where($where)
+ ->disableBufferedResults()
+ ->first();
+ }
+
+ if ($translation) {
+ $translation->set($values);
+ } else {
+ $translation = $this->translationTable->newEntity(
+ $where + $values,
+ [
+ 'useSetters' => false,
+ 'markNew' => true,
+ ]
+ );
+ }
+
+ $entity->set('_i18n', array_merge($bundled, [$translation]));
+ $entity->set('_locale', $locale, ['setter' => false]);
+ $entity->setDirty('_locale', false);
+
+ foreach ($fields as $field) {
+ $entity->setDirty($field, false);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function buildMarshalMap(Marshaller $marshaller, array $map, array $options): array
+ {
+ $this->translatedFields();
+
+ return $this->_buildMarshalMap($marshaller, $map, $options);
+ }
+
+ /**
+ * Returns a fully aliased field name for translated fields.
+ *
+ * If the requested field is configured as a translation field, field with
+ * an alias of a corresponding association is returned. Table-aliased
+ * field name is returned for all other fields.
+ *
+ * @param string $field Field name to be aliased.
+ * @return string
+ */
+ public function translationField(string $field): string
+ {
+ if ($this->getLocale() === $this->getConfig('defaultLocale')) {
+ return $this->table->aliasField($field);
+ }
+
+ $translatedFields = $this->translatedFields();
+ if (in_array($field, $translatedFields, true)) {
+ return $this->getConfig('hasOneAlias') . '.' . $field;
+ }
+
+ return $this->table->aliasField($field);
+ }
+
+ /**
+ * Modifies the results from a table find in order to merge the translated
+ * fields into each entity for a given locale.
+ *
+ * @param \Cake\Datasource\ResultSetInterface $results Results to map.
+ * @param string $locale Locale string
+ * @return \Cake\Collection\CollectionInterface
+ */
+ protected function rowMapper($results, $locale)
+ {
+ $allowEmpty = $this->_config['allowEmptyTranslations'];
+
+ return $results->map(function ($row) use ($allowEmpty) {
+ /** @var \Cake\Datasource\EntityInterface|array|null $row */
+ if ($row === null) {
+ return $row;
+ }
+
+ $hydrated = !is_array($row);
+
+ if (empty($row['translation'])) {
+ $row['_locale'] = $this->getLocale();
+ unset($row['translation']);
+
+ if ($hydrated) {
+ $row->clean();
+ }
+
+ return $row;
+ }
+
+ /** @var \Cake\ORM\Entity|array $translation */
+ $translation = $row['translation'];
+
+ /**
+ * @psalm-suppress PossiblyInvalidMethodCall
+ * @psalm-suppress PossiblyInvalidArgument
+ */
+ $keys = $hydrated ? $translation->getVisible() : array_keys($translation);
+
+ foreach ($keys as $field) {
+ if ($field === 'locale') {
+ $row['_locale'] = $translation[$field];
+ continue;
+ }
+
+ if ($translation[$field] !== null) {
+ if ($allowEmpty || $translation[$field] !== '') {
+ $row[$field] = $translation[$field];
+ }
+ }
+ }
+
+ unset($row['translation']);
+
+ if ($hydrated) {
+ $row->clean();
+ }
+
+ return $row;
+ });
+ }
+
+ /**
+ * Modifies the results from a table find in order to merge full translation
+ * records into each entity under the `_translations` key.
+ *
+ * @param \Cake\Datasource\ResultSetInterface $results Results to modify.
+ * @return \Cake\Collection\CollectionInterface
+ */
+ public function groupTranslations($results): CollectionInterface
+ {
+ return $results->map(function ($row) {
+ $translations = (array)$row['_i18n'];
+ if (empty($translations) && $row->get('_translations')) {
+ return $row;
+ }
+
+ $result = [];
+ foreach ($translations as $translation) {
+ unset($translation['id']);
+ $result[$translation['locale']] = $translation;
+ }
+
+ $row['_translations'] = $result;
+ unset($row['_i18n']);
+ if ($row instanceof EntityInterface) {
+ $row->clean();
+ }
+
+ return $row;
+ });
+ }
+
+ /**
+ * Helper method used to generated multiple translated field entities
+ * out of the data found in the `_translations` property in the passed
+ * entity. The result will be put into its `_i18n` property.
+ *
+ * @param \Cake\Datasource\EntityInterface $entity Entity.
+ * @return void
+ */
+ protected function bundleTranslatedFields($entity)
+ {
+ $translations = (array)$entity->get('_translations');
+
+ if (empty($translations) && !$entity->isDirty('_translations')) {
+ return;
+ }
+
+ $primaryKey = (array)$this->table->getPrimaryKey();
+ $key = $entity->get(current($primaryKey));
+
+ foreach ($translations as $lang => $translation) {
+ if (!$translation->id) {
+ $update = [
+ 'id' => $key,
+ 'locale' => $lang,
+ ];
+ $translation->set($update, ['guard' => false]);
+ }
+ }
+
+ $entity->set('_i18n', $translations);
+ }
+
+ /**
+ * Lazy define and return the main table fields.
+ *
+ * @return array
+ */
+ protected function mainFields()
+ {
+ $fields = $this->getConfig('mainTableFields');
+
+ if ($fields) {
+ return $fields;
+ }
+
+ $fields = $this->table->getSchema()->columns();
+
+ $this->setConfig('mainTableFields', $fields);
+
+ return $fields;
+ }
+
+ /**
+ * Lazy define and return the translation table fields.
+ *
+ * @return array
+ */
+ protected function translatedFields()
+ {
+ $fields = $this->getConfig('fields');
+
+ if ($fields) {
+ return $fields;
+ }
+
+ $table = $this->translationTable;
+ $fields = $table->getSchema()->columns();
+ $fields = array_values(array_diff($fields, ['id', 'locale']));
+
+ $this->setConfig('fields', $fields);
+
+ return $fields;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/TranslateStrategyInterface.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/TranslateStrategyInterface.php
new file mode 100644
index 000000000..9f8d9a200
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/TranslateStrategyInterface.php
@@ -0,0 +1,118 @@
+translationTable;
+ }
+
+ /**
+ * Sets the locale to be used.
+ *
+ * When fetching records, the content for the locale set via this method,
+ * and likewise when saving data, it will save the data in that locale.
+ *
+ * Note that in case an entity has a `_locale` property set, that locale
+ * will win over the locale set via this method (and over the globally
+ * configured one for that matter)!
+ *
+ * @param string|null $locale The locale to use for fetching and saving
+ * records. Pass `null` in order to unset the current locale, and to make
+ * the behavior fall back to using the globally configured locale.
+ * @return $this
+ */
+ public function setLocale(?string $locale)
+ {
+ $this->locale = $locale;
+
+ return $this;
+ }
+
+ /**
+ * Returns the current locale.
+ *
+ * If no locale has been explicitly set via `setLocale()`, this method will return
+ * the currently configured global locale.
+ *
+ * @return string
+ * @see \Cake\I18n\I18n::getLocale()
+ * @see \Cake\ORM\Behavior\TranslateBehavior::setLocale()
+ */
+ public function getLocale(): string
+ {
+ return $this->locale ?: I18n::getLocale();
+ }
+
+ /**
+ * Unset empty translations to avoid persistence.
+ *
+ * Should only be called if $this->_config['allowEmptyTranslations'] is false.
+ *
+ * @param \Cake\Datasource\EntityInterface $entity The entity to check for empty translations fields inside.
+ * @return void
+ */
+ protected function unsetEmptyFields($entity)
+ {
+ /** @var \Cake\ORM\Entity[] $translations */
+ $translations = (array)$entity->get('_translations');
+ foreach ($translations as $locale => $translation) {
+ $fields = $translation->extract($this->_config['fields'], false);
+ foreach ($fields as $field => $value) {
+ if (strlen($value) === 0) {
+ $translation->unset($field);
+ }
+ }
+
+ $translation = $translation->extract($this->_config['fields']);
+
+ // If now, the current locale property is empty,
+ // unset it completely.
+ if (empty(array_filter($translation))) {
+ unset($entity->get('_translations')[$locale]);
+ }
+ }
+
+ // If now, the whole _translations property is empty,
+ // unset it completely and return
+ if (empty($entity->get('_translations'))) {
+ $entity->unset('_translations');
+ }
+ }
+
+ /**
+ * Build a set of properties that should be included in the marshalling process.
+
+ * Add in `_translations` marshalling handlers. You can disable marshalling
+ * of translations by setting `'translations' => false` in the options
+ * provided to `Table::newEntity()` or `Table::patchEntity()`.
+ *
+ * @param \Cake\ORM\Marshaller $marshaller The marhshaller of the table the behavior is attached to.
+ * @param array $map The property map being built.
+ * @param array $options The options array used in the marshalling call.
+ * @return array A map of `[property => callable]` of additional properties to marshal.
+ */
+ public function buildMarshalMap(Marshaller $marshaller, array $map, array $options): array
+ {
+ if (isset($options['translations']) && !$options['translations']) {
+ return [];
+ }
+
+ return [
+ '_translations' => function ($value, $entity) use ($marshaller, $options) {
+ /** @var \Cake\Datasource\EntityInterface $entity */
+ $translations = $entity->get('_translations');
+ foreach ($this->_config['fields'] as $field) {
+ $options['validate'] = $this->_config['validator'];
+ $errors = [];
+ if (!is_array($value)) {
+ return null;
+ }
+ foreach ($value as $language => $fields) {
+ if (!isset($translations[$language])) {
+ $translations[$language] = $this->table->newEmptyEntity();
+ }
+ $marshaller->merge($translations[$language], $fields, $options);
+ /** @var \Cake\Datasource\EntityInterface $translation */
+ $translation = $translations[$language];
+ if ((bool)$translation->getErrors()) {
+ $errors[$language] = $translation->getErrors();
+ }
+ }
+ // Set errors into the root entity, so validation errors
+ // match the original form data position.
+ $entity->setErrors($errors);
+ }
+
+ return $translations;
+ },
+ ];
+ }
+
+ /**
+ * Unsets the temporary `_i18n` property after the entity has been saved
+ *
+ * @param \Cake\Event\EventInterface $event The beforeSave event that was fired
+ * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved
+ * @return void
+ */
+ public function afterSave(EventInterface $event, EntityInterface $entity)
+ {
+ $entity->unset('_i18n');
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/TranslateTrait.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/TranslateTrait.php
index 9ce6126e0..23670a313 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/TranslateTrait.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/TranslateTrait.php
@@ -1,4 +1,6 @@
get('_locale')) {
return $this;
@@ -46,7 +48,7 @@ public function translation($language)
}
if ($created || empty($i18n[$language]) || !($i18n[$language] instanceof EntityInterface)) {
- $className = get_class($this);
+ $className = static::class;
$i18n[$language] = new $className();
$created = true;
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php
index c44083793..d8c0d049f 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php
@@ -1,4 +1,6 @@
[
'setLocale' => 'setLocale',
'getLocale' => 'getLocale',
- 'locale' => 'locale',
'translationField' => 'translationField',
],
'fields' => [],
- 'translationTable' => 'I18n',
- 'defaultLocale' => '',
+ 'defaultLocale' => null,
'referenceName' => '',
'allowEmptyTranslations' => true,
'onlyTranslated' => false,
@@ -92,9 +64,44 @@ class TranslateBehavior extends Behavior implements PropertyMarshalInterface
'validator' => false,
];
+ /**
+ * Default strategy class name.
+ *
+ * @var string
+ * @psalm-var class-string<\Cake\ORM\Behavior\Translate\TranslateStrategyInterface>
+ */
+ protected static $defaultStrategyClass = EavStrategy::class;
+
+ /**
+ * Translation strategy instance.
+ *
+ * @var \Cake\ORM\Behavior\Translate\TranslateStrategyInterface|null
+ */
+ protected $strategy;
+
/**
* Constructor
*
+ * ### Options
+ *
+ * - `fields`: List of fields which need to be translated. Providing this fields
+ * list is mandatory when using `EavStrategy`. If the fields list is empty when
+ * using `ShadowTableStrategy` then the list will be auto generated based on
+ * shadow table schema.
+ * - `defaultLocale`: The locale which is treated as default by the behavior.
+ * Fields values for defaut locale will be stored in the primary table itself
+ * and the rest in translation table. If not explicitly set the value of
+ * `I18n::getDefaultLocale()` will be used to get default locale.
+ * If you do not want any default locale and want translated fields
+ * for all locales to be stored in translation table then set this config
+ * to empty string `''`.
+ * - `allowEmptyTranslations`: By default if a record has been translated and
+ * stored as an empty string the translate behavior will take and use this
+ * value to overwrite the original field value. If you don't want this behavior
+ * then set this option to `false`.
+ * - `validator`: The validator that should be used when translation records
+ * are created/modified. Default `null`.
+ *
* @param \Cake\ORM\Table $table The table this behavior is attached to.
* @param array $config The config for this behavior.
*/
@@ -102,15 +109,10 @@ public function __construct(Table $table, array $config = [])
{
$config += [
'defaultLocale' => I18n::getDefaultLocale(),
- 'referenceName' => $this->_referenceName($table),
+ 'referenceName' => $this->referenceName($table),
+ 'tableLocator' => $table->associations()->getTableLocator(),
];
- if (isset($config['tableLocator'])) {
- $this->_tableLocator = $config['tableLocator'];
- } else {
- $this->_tableLocator = $table->associations()->getTableLocator();
- }
-
parent::__construct($table, $config);
}
@@ -120,256 +122,95 @@ public function __construct(Table $table, array $config = [])
* @param array $config The config for this behavior.
* @return void
*/
- public function initialize(array $config)
+ public function initialize(array $config): void
{
- $this->_translationTable = $this->getTableLocator()->get($this->_config['translationTable']);
-
- $this->setupFieldAssociations(
- $this->_config['fields'],
- $this->_config['translationTable'],
- $this->_config['referenceName'],
- $this->_config['strategy']
- );
+ $this->getStrategy();
}
/**
- * Creates the associations between the bound table and every field passed to
- * this method.
+ * Set default strategy class name.
*
- * Additionally it creates a `i18n` HasMany association that will be
- * used for fetching all translations for each record in the bound table
- *
- * @param array $fields list of fields to create associations for
- * @param string $table the table name to use for storing each field translation
- * @param string $model the model field value
- * @param string $strategy the strategy used in the _i18n association
+ * @param string $class Class name.
* @return void
+ * @since 4.0.0
+ * @psalm-param class-string<\Cake\ORM\Behavior\Translate\TranslateStrategyInterface> $class
*/
- public function setupFieldAssociations($fields, $table, $model, $strategy)
+ public static function setDefaultStrategyClass(string $class)
{
- $targetAlias = $this->_translationTable->getAlias();
- $alias = $this->_table->getAlias();
- $filter = $this->_config['onlyTranslated'];
- $tableLocator = $this->getTableLocator();
-
- foreach ($fields as $field) {
- $name = $alias . '_' . $field . '_translation';
-
- if (!$tableLocator->exists($name)) {
- $fieldTable = $tableLocator->get($name, [
- 'className' => $table,
- 'alias' => $name,
- 'table' => $this->_translationTable->getTable(),
- ]);
- } else {
- $fieldTable = $tableLocator->get($name);
- }
-
- $conditions = [
- $name . '.model' => $model,
- $name . '.field' => $field,
- ];
- if (!$this->_config['allowEmptyTranslations']) {
- $conditions[$name . '.content !='] = '';
- }
-
- $this->_table->hasOne($name, [
- 'targetTable' => $fieldTable,
- 'foreignKey' => 'foreign_key',
- 'joinType' => $filter ? QueryInterface::JOIN_TYPE_INNER : QueryInterface::JOIN_TYPE_LEFT,
- 'conditions' => $conditions,
- 'propertyName' => $field . '_translation',
- ]);
- }
-
- $conditions = ["$targetAlias.model" => $model];
- if (!$this->_config['allowEmptyTranslations']) {
- $conditions["$targetAlias.content !="] = '';
- }
-
- $this->_table->hasMany($targetAlias, [
- 'className' => $table,
- 'foreignKey' => 'foreign_key',
- 'strategy' => $strategy,
- 'conditions' => $conditions,
- 'propertyName' => '_i18n',
- 'dependent' => true,
- ]);
+ static::$defaultStrategyClass = $class;
}
/**
- * Callback method that listens to the `beforeFind` event in the bound
- * table. It modifies the passed query by eager loading the translated fields
- * and adding a formatter to copy the values into the main table records.
+ * Get default strategy class name.
*
- * @param \Cake\Event\Event $event The beforeFind event that was fired.
- * @param \Cake\ORM\Query $query Query
- * @param \ArrayObject $options The options for the query
- * @return void
+ * @return string
+ * @since 4.0.0
+ * @psalm-return class-string<\Cake\ORM\Behavior\Translate\TranslateStrategyInterface>
*/
- public function beforeFind(Event $event, Query $query, $options)
+ public static function getDefaultStrategyClass(): string
{
- $locale = $this->getLocale();
-
- if ($locale === $this->getConfig('defaultLocale')) {
- return;
- }
-
- $conditions = function ($field, $locale, $query, $select) {
- return function ($q) use ($field, $locale, $query, $select) {
- /** @var \Cake\Datasource\QueryInterface $q */
- $q->where([$q->getRepository()->aliasField('locale') => $locale]);
-
- /** @var \Cake\ORM\Query $query */
- if (
- $query->isAutoFieldsEnabled() ||
- in_array($field, $select, true) ||
- in_array($this->_table->aliasField($field), $select, true)
- ) {
- $q->select(['id', 'content']);
- }
-
- return $q;
- };
- };
-
- $contain = [];
- $fields = $this->_config['fields'];
- $alias = $this->_table->getAlias();
- $select = $query->clause('select');
-
- $changeFilter = isset($options['filterByCurrentLocale']) &&
- $options['filterByCurrentLocale'] !== $this->_config['onlyTranslated'];
-
- foreach ($fields as $field) {
- $name = $alias . '_' . $field . '_translation';
-
- $contain[$name]['queryBuilder'] = $conditions(
- $field,
- $locale,
- $query,
- $select
- );
-
- if ($changeFilter) {
- $filter = $options['filterByCurrentLocale'] ? QueryInterface::JOIN_TYPE_INNER : QueryInterface::JOIN_TYPE_LEFT;
- $contain[$name]['joinType'] = $filter;
- }
- }
-
- $query->contain($contain);
- $query->formatResults(function ($results) use ($locale) {
- return $this->_rowMapper($results, $locale);
- }, $query::PREPEND);
+ return static::$defaultStrategyClass;
}
/**
- * Modifies the entity before it is saved so that translated fields are persisted
- * in the database too.
+ * Get strategy class instance.
*
- * @param \Cake\Event\Event $event The beforeSave event that was fired
- * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved
- * @param \ArrayObject $options the options passed to the save method
- * @return void
+ * @return \Cake\ORM\Behavior\Translate\TranslateStrategyInterface
+ * @since 4.0.0
*/
- public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options)
+ public function getStrategy(): TranslateStrategyInterface
{
- $locale = $entity->get('_locale') ?: $this->getLocale();
- $newOptions = [$this->_translationTable->getAlias() => ['validate' => false]];
- $options['associated'] = $newOptions + $options['associated'];
-
- // Check early if empty translations are present in the entity.
- // If this is the case, unset them to prevent persistence.
- // This only applies if $this->_config['allowEmptyTranslations'] is false
- if ($this->_config['allowEmptyTranslations'] === false) {
- $this->_unsetEmptyFields($entity);
- }
-
- $this->_bundleTranslatedFields($entity);
- $bundled = $entity->get('_i18n') ?: [];
- $noBundled = count($bundled) === 0;
-
- // No additional translation records need to be saved,
- // as the entity is in the default locale.
- if ($noBundled && $locale === $this->getConfig('defaultLocale')) {
- return;
+ if ($this->strategy !== null) {
+ return $this->strategy;
}
- $values = $entity->extract($this->_config['fields'], true);
- $fields = array_keys($values);
- $noFields = empty($fields);
-
- // If there are no fields and no bundled translations, or both fields
- // in the default locale and bundled translations we can
- // skip the remaining logic as its not necessary.
- if ($noFields && $noBundled || ($fields && $bundled)) {
- return;
- }
-
- $primaryKey = (array)$this->_table->getPrimaryKey();
- $key = $entity->get(current($primaryKey));
-
- // When we have no key and bundled translations, we
- // need to mark the entity dirty so the root
- // entity persists.
- if ($noFields && $bundled && !$key) {
- foreach ($this->_config['fields'] as $field) {
- $entity->setDirty($field, true);
- }
-
- return;
- }
-
- if ($noFields) {
- return;
- }
-
- $model = $this->_config['referenceName'];
- $preexistent = $this->_translationTable->find()
- ->select(['id', 'field'])
- ->where([
- 'field IN' => $fields,
- 'locale' => $locale,
- 'foreign_key' => $key,
- 'model' => $model,
- ])
- ->disableBufferedResults()
- ->all()
- ->indexBy('field');
+ return $this->strategy = $this->createStrategy();
+ }
- $modified = [];
- foreach ($preexistent as $field => $translation) {
- $translation->set('content', $values[$field]);
- $modified[$field] = $translation;
- }
+ /**
+ * Create strategy instance.
+ *
+ * @return \Cake\ORM\Behavior\Translate\TranslateStrategyInterface
+ * @since 4.0.0
+ */
+ protected function createStrategy()
+ {
+ $config = array_diff_key(
+ $this->_config,
+ ['implementedFinders', 'implementedMethods', 'strategyClass']
+ );
+ /** @var class-string<\Cake\ORM\Behavior\Translate\TranslateStrategyInterface> $className */
+ $className = $this->getConfig('strategyClass', static::$defaultStrategyClass);
- $new = array_diff_key($values, $modified);
- foreach ($new as $field => $content) {
- $new[$field] = new Entity(compact('locale', 'field', 'content', 'model'), [
- 'useSetters' => false,
- 'markNew' => true,
- ]);
- }
+ return new $className($this->_table, $config);
+ }
- $entity->set('_i18n', array_merge($bundled, array_values($modified + $new)));
- $entity->set('_locale', $locale, ['setter' => false]);
- $entity->setDirty('_locale', false);
+ /**
+ * Set strategy class instance.
+ *
+ * @param \Cake\ORM\Behavior\Translate\TranslateStrategyInterface $strategy Strategy class instance.
+ * @return $this
+ * @since 4.0.0
+ */
+ public function setStrategy(TranslateStrategyInterface $strategy)
+ {
+ $this->strategy = $strategy;
- foreach ($fields as $field) {
- $entity->setDirty($field, false);
- }
+ return $this;
}
/**
- * Unsets the temporary `_i18n` property after the entity has been saved
+ * Gets the Model callbacks this behavior is interested in.
*
- * @param \Cake\Event\Event $event The beforeSave event that was fired
- * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved
- * @return void
+ * @return array
*/
- public function afterSave(Event $event, EntityInterface $entity)
+ public function implementedEvents(): array
{
- $entity->unsetProperty('_i18n');
+ return [
+ 'Model.beforeFind' => 'beforeFind',
+ 'Model.beforeSave' => 'beforeSave',
+ 'Model.afterSave' => 'afterSave',
+ ];
}
/**
@@ -378,40 +219,15 @@ public function afterSave(Event $event, EntityInterface $entity)
* Add in `_translations` marshalling handlers. You can disable marshalling
* of translations by setting `'translations' => false` in the options
* provided to `Table::newEntity()` or `Table::patchEntity()`.
+ *
+ * @param \Cake\ORM\Marshaller $marshaller The marhshaller of the table the behavior is attached to.
+ * @param array $map The property map being built.
+ * @param array $options The options array used in the marshalling call.
+ * @return array A map of `[property => callable]` of additional properties to marshal.
*/
- public function buildMarshalMap($marshaller, $map, $options)
+ public function buildMarshalMap(Marshaller $marshaller, array $map, array $options): array
{
- if (isset($options['translations']) && !$options['translations']) {
- return [];
- }
-
- return [
- '_translations' => function ($value, $entity) use ($marshaller, $options) {
- /** @var \Cake\Datasource\EntityInterface $entity */
- $translations = $entity->get('_translations');
- foreach ($this->_config['fields'] as $field) {
- $options['validate'] = $this->_config['validator'];
- $errors = [];
- if (!is_array($value)) {
- return null;
- }
- foreach ($value as $language => $fields) {
- if (!isset($translations[$language])) {
- $translations[$language] = $this->_table->newEntity();
- }
- $marshaller->merge($translations[$language], $fields, $options);
- if ((bool)$translations[$language]->getErrors()) {
- $errors[$language] = $translations[$language]->getErrors();
- }
- }
- // Set errors into the root entity, so validation errors
- // match the original form data position.
- $entity->setErrors($errors);
- }
-
- return $translations;
- },
- ];
+ return $this->getStrategy()->buildMarshalMap($marshaller, $map, $options);
}
/**
@@ -431,12 +247,12 @@ public function buildMarshalMap($marshaller, $map, $options)
* globally configured locale.
* @return $this
* @see \Cake\ORM\Behavior\TranslateBehavior::getLocale()
- * @link https://book.cakephp.org/3/en/orm/behaviors/translate.html#retrieving-one-language-without-using-i18n-locale
- * @link https://book.cakephp.org/3/en/orm/behaviors/translate.html#saving-in-another-language
+ * @link https://book.cakephp.org/4/en/orm/behaviors/translate.html#retrieving-one-language-without-using-i18n-locale
+ * @link https://book.cakephp.org/4/en/orm/behaviors/translate.html#saving-in-another-language
*/
- public function setLocale($locale)
+ public function setLocale(?string $locale)
{
- $this->_locale = $locale;
+ $this->getStrategy()->setLocale($locale);
return $this;
}
@@ -451,32 +267,9 @@ public function setLocale($locale)
* @see \Cake\I18n\I18n::getLocale()
* @see \Cake\ORM\Behavior\TranslateBehavior::setLocale()
*/
- public function getLocale()
+ public function getLocale(): string
{
- return $this->_locale ?: I18n::getLocale();
- }
-
- /**
- * Sets all future finds for the bound table to also fetch translated fields for
- * the passed locale. If no value is passed, it returns the currently configured
- * locale
- *
- * @deprecated 3.6.0 Use setLocale()/getLocale() instead.
- * @param string|null $locale The locale to use for fetching translated records
- * @return string
- */
- public function locale($locale = null)
- {
- deprecationWarning(
- get_called_class() . '::locale() is deprecated. ' .
- 'Use setLocale()/getLocale() instead.'
- );
-
- if ($locale !== null) {
- $this->setLocale($locale);
- }
-
- return $this->getLocale();
+ return $this->getStrategy()->getLocale();
}
/**
@@ -489,19 +282,9 @@ public function locale($locale = null)
* @param string $field Field name to be aliased.
* @return string
*/
- public function translationField($field)
+ public function translationField(string $field): string
{
- $table = $this->_table;
- if ($this->getLocale() === $this->getConfig('defaultLocale')) {
- return $table->aliasField($field);
- }
- $associationName = $table->getAlias() . '_' . $field . '_translation';
-
- if ($table->associations()->has($associationName)) {
- return $associationName . '.content';
- }
-
- return $table->aliasField($field);
+ return $this->getStrategy()->translationField($field);
}
/**
@@ -526,21 +309,33 @@ public function translationField($field)
* @param array $options Options
* @return \Cake\ORM\Query
*/
- public function findTranslations(Query $query, array $options)
+ public function findTranslations(Query $query, array $options): Query
{
- $locales = isset($options['locales']) ? $options['locales'] : [];
- $targetAlias = $this->_translationTable->getAlias();
+ $locales = $options['locales'] ?? [];
+ $targetAlias = $this->getStrategy()->getTranslationTable()->getAlias();
return $query
->contain([$targetAlias => function ($query) use ($locales, $targetAlias) {
+ /** @var \Cake\Datasource\QueryInterface $query */
if ($locales) {
- /** @var \Cake\Datasource\QueryInterface $query */
$query->where(["$targetAlias.locale IN" => $locales]);
}
return $query;
}])
- ->formatResults([$this, 'groupTranslations'], $query::PREPEND);
+ ->formatResults([$this->getStrategy(), 'groupTranslations'], $query::PREPEND);
+ }
+
+ /**
+ * Proxy method calls to strategy class instance.
+ *
+ * @param string $method Method name.
+ * @param array $args Method arguments.
+ * @return mixed
+ */
+ public function __call($method, $args)
+ {
+ return call_user_func_array([$this->strategy, $method], $args);
}
/**
@@ -554,7 +349,7 @@ public function findTranslations(Query $query, array $options)
* @param \Cake\ORM\Table $table The table class to get a reference name for.
* @return string
*/
- protected function _referenceName(Table $table)
+ protected function referenceName(Table $table): string
{
$name = namespaceSplit(get_class($table));
$name = substr(end($name), 0, -5);
@@ -565,203 +360,4 @@ protected function _referenceName(Table $table)
return $name;
}
-
- /**
- * Modifies the results from a table find in order to merge the translated fields
- * into each entity for a given locale.
- *
- * @param \Cake\Datasource\ResultSetInterface $results Results to map.
- * @param string $locale Locale string
- * @return \Cake\Collection\CollectionInterface
- */
- protected function _rowMapper($results, $locale)
- {
- return $results->map(function ($row) use ($locale) {
- if ($row === null) {
- return $row;
- }
- $hydrated = !is_array($row);
-
- foreach ($this->_config['fields'] as $field) {
- $name = $field . '_translation';
- $translation = isset($row[$name]) ? $row[$name] : null;
-
- if ($translation === null || $translation === false) {
- unset($row[$name]);
- continue;
- }
-
- $content = isset($translation['content']) ? $translation['content'] : null;
- if ($content !== null) {
- $row[$field] = $content;
- }
-
- unset($row[$name]);
- }
-
- $row['_locale'] = $locale;
- if ($hydrated) {
- /** @var \Cake\Datasource\EntityInterface $row */
- $row->clean();
- }
-
- return $row;
- });
- }
-
- /**
- * Modifies the results from a table find in order to merge full translation records
- * into each entity under the `_translations` key
- *
- * @param \Cake\Datasource\ResultSetInterface $results Results to modify.
- * @return \Cake\Collection\CollectionInterface
- */
- public function groupTranslations($results)
- {
- return $results->map(function ($row) {
- if (!$row instanceof EntityInterface) {
- return $row;
- }
- $translations = (array)$row->get('_i18n');
- if (empty($translations) && $row->get('_translations')) {
- return $row;
- }
- $grouped = new Collection($translations);
-
- $result = [];
- foreach ($grouped->combine('field', 'content', 'locale') as $locale => $keys) {
- $entityClass = $this->_table->getEntityClass();
- $translation = new $entityClass($keys + ['locale' => $locale], [
- 'markNew' => false,
- 'useSetters' => false,
- 'markClean' => true,
- ]);
- $result[$locale] = $translation;
- }
-
- $options = ['setter' => false, 'guard' => false];
- $row->set('_translations', $result, $options);
- unset($row['_i18n']);
- $row->clean();
-
- return $row;
- });
- }
-
- /**
- * Helper method used to generated multiple translated field entities
- * out of the data found in the `_translations` property in the passed
- * entity. The result will be put into its `_i18n` property
- *
- * @param \Cake\Datasource\EntityInterface $entity Entity
- * @return void
- */
- protected function _bundleTranslatedFields($entity)
- {
- $translations = (array)$entity->get('_translations');
-
- if (empty($translations) && !$entity->isDirty('_translations')) {
- return;
- }
-
- $fields = $this->_config['fields'];
- $primaryKey = (array)$this->_table->getPrimaryKey();
- $key = $entity->get(current($primaryKey));
- $find = [];
- $contents = [];
-
- foreach ($translations as $lang => $translation) {
- foreach ($fields as $field) {
- if (!$translation->isDirty($field)) {
- continue;
- }
- $find[] = ['locale' => $lang, 'field' => $field, 'foreign_key' => $key];
- $contents[] = new Entity(['content' => $translation->get($field)], [
- 'useSetters' => false,
- ]);
- }
- }
-
- if (empty($find)) {
- return;
- }
-
- $results = $this->_findExistingTranslations($find);
-
- foreach ($find as $i => $translation) {
- if (!empty($results[$i])) {
- $contents[$i]->set('id', $results[$i], ['setter' => false]);
- $contents[$i]->isNew(false);
- } else {
- $translation['model'] = $this->_config['referenceName'];
- $contents[$i]->set($translation, ['setter' => false, 'guard' => false]);
- $contents[$i]->isNew(true);
- }
- }
-
- $entity->set('_i18n', $contents);
- }
-
- /**
- * Unset empty translations to avoid persistence.
- *
- * Should only be called if $this->_config['allowEmptyTranslations'] is false.
- *
- * @param \Cake\Datasource\EntityInterface $entity The entity to check for empty translations fields inside.
- * @return void
- */
- protected function _unsetEmptyFields(EntityInterface $entity)
- {
- $translations = (array)$entity->get('_translations');
- foreach ($translations as $locale => $translation) {
- $fields = $translation->extract($this->_config['fields'], false);
- foreach ($fields as $field => $value) {
- if (strlen($value) === 0) {
- $translation->unsetProperty($field);
- }
- }
-
- $translation = $translation->extract($this->_config['fields']);
-
- // If now, the current locale property is empty,
- // unset it completely.
- if (empty(array_filter($translation))) {
- unset($entity->get('_translations')[$locale]);
- }
- }
-
- // If now, the whole _translations property is empty,
- // unset it completely and return
- if (empty($entity->get('_translations'))) {
- $entity->unsetProperty('_translations');
- }
- }
-
- /**
- * Returns the ids found for each of the condition arrays passed for the translations
- * table. Each records is indexed by the corresponding position to the conditions array
- *
- * @param array $ruleSet an array of arary of conditions to be used for finding each
- * @return array
- */
- protected function _findExistingTranslations($ruleSet)
- {
- $association = $this->_table->getAssociation($this->_translationTable->getAlias());
-
- $query = $association->find()
- ->select(['id', 'num' => 0])
- ->where(current($ruleSet))
- ->disableHydration()
- ->disableBufferedResults();
-
- unset($ruleSet[0]);
- foreach ($ruleSet as $i => $conditions) {
- $q = $association->find()
- ->select(['id', 'num' => $i])
- ->where($conditions);
- $query->unionAll($q);
- }
-
- return $query->all()->combine('num', 'id')->toArray();
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php
index d37d0a227..66971c4a4 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php
@@ -1,4 +1,6 @@
_config['leftField'] = new IdentifierExpression($this->_config['left']);
$this->_config['rightField'] = new IdentifierExpression($this->_config['right']);
@@ -88,12 +91,12 @@ public function initialize(array $config)
* Transparently manages setting the lft and rght fields if the parent field is
* included in the parameters to be saved.
*
- * @param \Cake\Event\Event $event The beforeSave event that was fired
+ * @param \Cake\Event\EventInterface $event The beforeSave event that was fired
* @param \Cake\Datasource\EntityInterface $entity the entity that is going to be saved
* @return void
* @throws \RuntimeException if the parent to set for the node is invalid
*/
- public function beforeSave(Event $event, EntityInterface $entity)
+ public function beforeSave(EventInterface $event, EntityInterface $entity)
{
$isNew = $entity->isNew();
$config = $this->getConfig();
@@ -102,7 +105,7 @@ public function beforeSave(Event $event, EntityInterface $entity)
$dirty = $entity->isDirty($config['parent']);
$level = $config['level'];
- if ($parent && $entity->get($primaryKey) == $parent) {
+ if ($parent && $entity->get($primaryKey) === $parent) {
throw new RuntimeException("Cannot set a node's parent as itself");
}
@@ -157,11 +160,11 @@ public function beforeSave(Event $event, EntityInterface $entity)
*
* Manages updating level of descendants of currently saved entity.
*
- * @param \Cake\Event\Event $event The afterSave event that was fired
+ * @param \Cake\Event\EventInterface $event The afterSave event that was fired
* @param \Cake\Datasource\EntityInterface $entity the entity that is going to be saved
* @return void
*/
- public function afterSave(Event $event, EntityInterface $entity)
+ public function afterSave(EventInterface $event, EntityInterface $entity)
{
if (!$this->_config['level'] || $entity->isNew()) {
return;
@@ -176,7 +179,7 @@ public function afterSave(Event $event, EntityInterface $entity)
* @param \Cake\Datasource\EntityInterface $entity The entity whose descendants need to be updated.
* @return void
*/
- protected function _setChildrenLevel($entity)
+ protected function _setChildrenLevel(EntityInterface $entity): void
{
$config = $this->getConfig();
@@ -210,11 +213,11 @@ protected function _setChildrenLevel($entity)
/**
* Also deletes the nodes in the subtree of the entity to be delete
*
- * @param \Cake\Event\Event $event The beforeDelete event that was fired
+ * @param \Cake\Event\EventInterface $event The beforeDelete event that was fired
* @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved
* @return void
*/
- public function beforeDelete(Event $event, EntityInterface $entity)
+ public function beforeDelete(EventInterface $event, EntityInterface $entity)
{
$config = $this->getConfig();
$this->_ensureFields($entity);
@@ -248,7 +251,7 @@ public function beforeDelete(Event $event, EntityInterface $entity)
* @return void
* @throws \RuntimeException if the parent to set to the entity is not valid
*/
- protected function _setParent($entity, $parent)
+ protected function _setParent(EntityInterface $entity, $parent): void
{
$config = $this->getConfig();
$parentNode = $this->_getNode($parent);
@@ -308,7 +311,7 @@ protected function _setParent($entity, $parent)
* @param \Cake\Datasource\EntityInterface $entity The entity to set as a new root
* @return void
*/
- protected function _setAsRoot($entity)
+ protected function _setAsRoot(EntityInterface $entity): void
{
$config = $this->getConfig();
$edge = $this->_getMax();
@@ -341,7 +344,7 @@ protected function _setAsRoot($entity)
*
* @return void
*/
- protected function _unmarkInternalTree()
+ protected function _unmarkInternalTree(): void
{
$config = $this->getConfig();
$this->_table->updateAll(
@@ -372,14 +375,14 @@ function ($exp) use ($config) {
* @return \Cake\ORM\Query
* @throws \InvalidArgumentException If the 'for' key is missing in options
*/
- public function findPath(Query $query, array $options)
+ public function findPath(Query $query, array $options): Query
{
if (empty($options['for'])) {
throw new InvalidArgumentException("The 'for' key is required for find('path')");
}
$config = $this->getConfig();
- list($left, $right) = array_map(
+ [$left, $right] = array_map(
function ($field) {
return $this->_table->aliasField($field);
},
@@ -404,7 +407,7 @@ function ($field) {
* direct children
* @return int Number of children nodes.
*/
- public function childCount(EntityInterface $node, $direct = false)
+ public function childCount(EntityInterface $node, bool $direct = false): int
{
$config = $this->getConfig();
$parent = $this->_table->aliasField($config['parent']);
@@ -436,18 +439,18 @@ public function childCount(EntityInterface $node, $direct = false)
* @return \Cake\ORM\Query
* @throws \InvalidArgumentException When the 'for' key is not passed in $options
*/
- public function findChildren(Query $query, array $options)
+ public function findChildren(Query $query, array $options): Query
{
$config = $this->getConfig();
$options += ['for' => null, 'direct' => false];
- list($parent, $left, $right) = array_map(
+ [$parent, $left, $right] = array_map(
function ($field) {
return $this->_table->aliasField($field);
},
[$config['parent'], $config['left'], $config['right']]
);
- list($for, $direct) = [$options['for'], $options['direct']];
+ [$for, $direct] = [$options['for'], $options['direct']];
if (empty($for)) {
throw new InvalidArgumentException("The 'for' key is required for find('children')");
@@ -487,7 +490,7 @@ function ($field) {
* @param array $options Array of options as described above.
* @return \Cake\ORM\Query
*/
- public function findTreeList(Query $query, array $options)
+ public function findTreeList(Query $query, array $options): Query
{
$left = $this->_table->aliasField($this->getConfig('left'));
@@ -517,19 +520,19 @@ public function findTreeList(Query $query, array $options)
* @param array $options Array of options as described above.
* @return \Cake\ORM\Query Augmented query.
*/
- public function formatTreeList(Query $query, array $options = [])
+ public function formatTreeList(Query $query, array $options = []): Query
{
- return $query->formatResults(function ($results) use ($options) {
- /** @var \Cake\Collection\CollectionTrait $results */
+ return $query->formatResults(function (CollectionInterface $results) use ($options) {
$options += [
'keyPath' => $this->_getPrimaryKey(),
'valuePath' => $this->_table->getDisplayField(),
'spacer' => '_',
];
- return $results
- ->listNested()
- ->printer($options['valuePath'], $options['keyPath'], $options['spacer']);
+ /** @var \Cake\Collection\Iterator\TreeIterator $nested */
+ $nested = $results->listNested();
+
+ return $nested->printer($options['valuePath'], $options['keyPath'], $options['spacer']);
});
}
@@ -560,7 +563,7 @@ public function removeFromTree(EntityInterface $node)
* @return \Cake\Datasource\EntityInterface|false the node after being removed from the tree or
* false on error
*/
- protected function _removeFromTree($node)
+ protected function _removeFromTree(EntityInterface $node)
{
$config = $this->getConfig();
$left = $node->get($config['left']);
@@ -569,7 +572,7 @@ protected function _removeFromTree($node)
$node->set($config['parent'], null);
- if ($right - $left == 1) {
+ if ($right - $left === 1) {
return $this->_table->save($node);
}
@@ -601,7 +604,7 @@ protected function _removeFromTree($node)
* this method will return false
*
* @param \Cake\Datasource\EntityInterface $node The node to move
- * @param int|bool $number How many places to move the node, or true to move to first position
+ * @param int|true $number How many places to move the node, or true to move to first position
* @throws \Cake\Datasource\Exception\RecordNotFoundException When node was not found
* @return \Cake\Datasource\EntityInterface|false $node The node after being moved or false on failure
*/
@@ -622,18 +625,19 @@ public function moveUp(EntityInterface $node, $number = 1)
* Helper function used with the actual code for moveUp
*
* @param \Cake\Datasource\EntityInterface $node The node to move
- * @param int|bool $number How many places to move the node, or true to move to first position
+ * @param int|true $number How many places to move the node, or true to move to first position
+ * @return \Cake\Datasource\EntityInterface $node The node after being moved or false on failure
* @throws \Cake\Datasource\Exception\RecordNotFoundException When node was not found
- * @return \Cake\Datasource\EntityInterface|false $node The node after being moved or false on failure
*/
- protected function _moveUp($node, $number)
+ protected function _moveUp(EntityInterface $node, $number): EntityInterface
{
$config = $this->getConfig();
- list($parent, $left, $right) = [$config['parent'], $config['left'], $config['right']];
- list($nodeParent, $nodeLeft, $nodeRight) = array_values($node->extract([$parent, $left, $right]));
+ [$parent, $left, $right] = [$config['parent'], $config['left'], $config['right']];
+ [$nodeParent, $nodeLeft, $nodeRight] = array_values($node->extract([$parent, $left, $right]));
$targetNode = null;
if ($number !== true) {
+ /** @var \Cake\Datasource\EntityInterface|null $targetNode */
$targetNode = $this->_scope($this->_table->find())
->select([$left, $right])
->where(["$parent IS" => $nodeParent])
@@ -647,6 +651,7 @@ protected function _moveUp($node, $number)
->first();
}
if (!$targetNode) {
+ /** @var \Cake\Datasource\EntityInterface|null $targetNode */
$targetNode = $this->_scope($this->_table->find())
->select([$left, $right])
->where(["$parent IS" => $nodeParent])
@@ -663,7 +668,7 @@ protected function _moveUp($node, $number)
}
}
- list($targetLeft) = array_values($targetNode->extract([$left, $right]));
+ [$targetLeft] = array_values($targetNode->extract([$left, $right]));
$edge = $this->_getMax();
$leftBoundary = $targetLeft;
$rightBoundary = $nodeLeft - 1;
@@ -676,7 +681,7 @@ protected function _moveUp($node, $number)
$this->_sync($nodeToHole, '-', "> {$edge}");
$node->set($left, $targetLeft);
- $node->set($right, $targetLeft + ($nodeRight - $nodeLeft));
+ $node->set($right, $targetLeft + $nodeRight - $nodeLeft);
$node->setDirty($left, false);
$node->setDirty($right, false);
@@ -691,7 +696,7 @@ protected function _moveUp($node, $number)
* this method will return false
*
* @param \Cake\Datasource\EntityInterface $node The node to move
- * @param int|bool $number How many places to move the node or true to move to last position
+ * @param int|true $number How many places to move the node or true to move to last position
* @throws \Cake\Datasource\Exception\RecordNotFoundException When node was not found
* @return \Cake\Datasource\EntityInterface|false the entity after being moved or false on failure
*/
@@ -712,18 +717,19 @@ public function moveDown(EntityInterface $node, $number = 1)
* Helper function used with the actual code for moveDown
*
* @param \Cake\Datasource\EntityInterface $node The node to move
- * @param int|bool $number How many places to move the node, or true to move to last position
+ * @param int|true $number How many places to move the node, or true to move to last position
+ * @return \Cake\Datasource\EntityInterface $node The node after being moved or false on failure
* @throws \Cake\Datasource\Exception\RecordNotFoundException When node was not found
- * @return \Cake\Datasource\EntityInterface|false $node The node after being moved or false on failure
*/
- protected function _moveDown($node, $number)
+ protected function _moveDown(EntityInterface $node, $number): EntityInterface
{
$config = $this->getConfig();
- list($parent, $left, $right) = [$config['parent'], $config['left'], $config['right']];
- list($nodeParent, $nodeLeft, $nodeRight) = array_values($node->extract([$parent, $left, $right]));
+ [$parent, $left, $right] = [$config['parent'], $config['left'], $config['right']];
+ [$nodeParent, $nodeLeft, $nodeRight] = array_values($node->extract([$parent, $left, $right]));
$targetNode = null;
if ($number !== true) {
+ /** @var \Cake\Datasource\EntityInterface|null $targetNode */
$targetNode = $this->_scope($this->_table->find())
->select([$left, $right])
->where(["$parent IS" => $nodeParent])
@@ -737,6 +743,7 @@ protected function _moveDown($node, $number)
->first();
}
if (!$targetNode) {
+ /** @var \Cake\Datasource\EntityInterface|null $targetNode */
$targetNode = $this->_scope($this->_table->find())
->select([$left, $right])
->where(["$parent IS" => $nodeParent])
@@ -753,7 +760,7 @@ protected function _moveDown($node, $number)
}
}
- list(, $targetRight) = array_values($targetNode->extract([$left, $right]));
+ [, $targetRight] = array_values($targetNode->extract([$left, $right]));
$edge = $this->_getMax();
$leftBoundary = $nodeRight + 1;
$rightBoundary = $targetRight;
@@ -780,11 +787,12 @@ protected function _moveDown($node, $number)
* @param mixed $id Record id.
* @return \Cake\Datasource\EntityInterface
* @throws \Cake\Datasource\Exception\RecordNotFoundException When node was not found
+ * @psalm-suppress InvalidReturnType
*/
- protected function _getNode($id)
+ protected function _getNode($id): EntityInterface
{
$config = $this->getConfig();
- list($parent, $left, $right) = [$config['parent'], $config['left'], $config['right']];
+ [$parent, $left, $right] = [$config['parent'], $config['left'], $config['right']];
$primaryKey = $this->_getPrimaryKey();
$fields = [$parent, $left, $right];
if ($config['level']) {
@@ -800,6 +808,7 @@ protected function _getNode($id)
throw new RecordNotFoundException("Node \"{$id}\" was not found in the tree.");
}
+ /** @psalm-suppress InvalidReturnStatement */
return $node;
}
@@ -809,9 +818,9 @@ protected function _getNode($id)
*
* @return void
*/
- public function recover()
+ public function recover(): void
{
- $this->_table->getConnection()->transactional(function () {
+ $this->_table->getConnection()->transactional(function (): void {
$this->_recoverTree();
});
}
@@ -819,41 +828,47 @@ public function recover()
/**
* Recursive method used to recover a single level of the tree
*
- * @param int $lftRght The starting lft/rght value
+ * @param int $counter The Last left column value that was assigned
* @param mixed $parentId the parent id of the level to be recovered
* @param int $level Node level
- * @return int The next lftRght value
+ * @return int The next value to use for the left column
*/
- protected function _recoverTree($lftRght = 1, $parentId = null, $level = 0)
+ protected function _recoverTree(int $counter = 0, $parentId = null, $level = -1): int
{
$config = $this->getConfig();
- list($parent, $left, $right) = [$config['parent'], $config['left'], $config['right']];
+ [$parent, $left, $right] = [$config['parent'], $config['left'], $config['right']];
$primaryKey = $this->_getPrimaryKey();
- $order = $config['recoverOrder'] ?: $primaryKey;
+ $aliasedPrimaryKey = $this->_table->aliasField($primaryKey);
+ $order = $config['recoverOrder'] ?: $aliasedPrimaryKey;
- $nodes = $this->_scope($this->_table->query())
- ->select($primaryKey)
- ->where([$parent . ' IS' => $parentId])
+ $query = $this->_scope($this->_table->query())
+ ->select([$aliasedPrimaryKey])
+ ->where([$this->_table->aliasField($parent) . ' IS' => $parentId])
->order($order)
- ->disableHydration()
- ->all();
+ ->disableHydration();
- foreach ($nodes as $node) {
- $nodeLft = $lftRght++;
- $lftRght = $this->_recoverTree($lftRght, $node[$primaryKey], $level + 1);
+ $leftCounter = $counter;
+ $nextLevel = $level + 1;
+ foreach ($query as $row) {
+ $counter++;
+ $counter = $this->_recoverTree($counter, $row[$primaryKey], $nextLevel);
+ }
- $fields = [$left => $nodeLft, $right => $lftRght++];
- if ($config['level']) {
- $fields[$config['level']] = $level;
- }
+ if ($parentId === null) {
+ return $counter;
+ }
- $this->_table->updateAll(
- $fields,
- [$primaryKey => $node[$primaryKey]]
- );
+ $fields = [$left => $leftCounter, $right => $counter + 1];
+ if ($config['level']) {
+ $fields[$config['level']] = $level;
}
- return $lftRght;
+ $this->_table->updateAll(
+ $fields,
+ [$primaryKey => $parentId]
+ );
+
+ return $counter + 1;
}
/**
@@ -861,7 +876,7 @@ protected function _recoverTree($lftRght = 1, $parentId = null, $level = 0)
*
* @return int
*/
- protected function _getMax()
+ protected function _getMax(): int
{
$field = $this->_config['right'];
$rightField = $this->_config['rightField'];
@@ -874,7 +889,7 @@ protected function _getMax()
return 0;
}
- return $edge->{$field};
+ return $edge[$field];
}
/**
@@ -889,7 +904,7 @@ protected function _getMax()
* modified by future calls to this function.
* @return void
*/
- protected function _sync($shift, $dir, $conditions, $mark = false)
+ protected function _sync(int $shift, string $dir, string $conditions, bool $mark = false): void
{
$config = $this->_config;
@@ -923,7 +938,7 @@ protected function _sync($shift, $dir, $conditions, $mark = false)
* @param \Cake\ORM\Query $query the Query to modify
* @return \Cake\ORM\Query
*/
- protected function _scope($query)
+ protected function _scope(Query $query): Query
{
$scope = $this->getConfig('scope');
@@ -944,7 +959,7 @@ protected function _scope($query)
* @param \Cake\Datasource\EntityInterface $entity The entity to ensure fields for
* @return void
*/
- protected function _ensureFields($entity)
+ protected function _ensureFields(EntityInterface $entity): void
{
$config = $this->getConfig();
$fields = [$config['left'], $config['right']];
@@ -966,7 +981,7 @@ protected function _ensureFields($entity)
*
* @return string
*/
- protected function _getPrimaryKey()
+ protected function _getPrimaryKey(): string
{
if (!$this->_primaryKey) {
$primaryKey = (array)$this->_table->getPrimaryKey();
diff --git a/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php b/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
index d5c7f84d0..772145a0e 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
@@ -1,4 +1,6 @@
setTable($table);
@@ -73,13 +75,10 @@ public function __construct($table = null)
* @param \Cake\ORM\Table $table The table this registry is attached to.
* @return void
*/
- public function setTable(Table $table)
+ public function setTable(Table $table): void
{
$this->_table = $table;
- $eventManager = $table->getEventManager();
- if ($eventManager !== null) {
- $this->setEventManager($eventManager);
- }
+ $this->setEventManager($table->getEventManager());
}
/**
@@ -87,16 +86,12 @@ public function setTable(Table $table)
*
* @param string $class Partial classname to resolve.
* @return string|null Either the correct classname or null.
- * @since 3.5.7
+ * @psalm-return class-string|null
*/
- public static function className($class)
+ public static function className(string $class): ?string
{
- $result = App::className($class, 'Model/Behavior', 'Behavior');
- if (!$result) {
- $result = App::className($class, 'ORM/Behavior', 'Behavior');
- }
-
- return $result ?: null;
+ return App::className($class, 'Model/Behavior', 'Behavior')
+ ?: App::className($class, 'ORM/Behavior', 'Behavior');
}
/**
@@ -105,11 +100,12 @@ public static function className($class)
* Part of the template method for Cake\Core\ObjectRegistry::load()
*
* @param string $class Partial classname to resolve.
- * @return string|false Either the correct classname or false.
+ * @return string|null Either the correct class name or null.
+ * @psalm-return class-string|null
*/
- protected function _resolveClassName($class)
+ protected function _resolveClassName(string $class): ?string
{
- return static::className($class) ?: false;
+ return static::className($class);
}
/**
@@ -123,7 +119,7 @@ protected function _resolveClassName($class)
* @return void
* @throws \Cake\ORM\Exception\MissingBehaviorException
*/
- protected function _throwMissingClassError($class, $plugin)
+ protected function _throwMissingClassError(string $class, ?string $plugin): void
{
throw new MissingBehaviorException([
'class' => $class . 'Behavior',
@@ -141,11 +137,13 @@ protected function _throwMissingClassError($class, $plugin)
* @param string $alias The alias of the object.
* @param array $config An array of config to use for the behavior.
* @return \Cake\ORM\Behavior The constructed behavior class.
+ * @psalm-suppress MoreSpecificImplementedParamType
*/
- protected function _create($class, $alias, $config)
+ protected function _create($class, string $alias, array $config): Behavior
{
+ /** @var \Cake\ORM\Behavior $instance */
$instance = new $class($this->_table, $config);
- $enable = isset($config['enabled']) ? $config['enabled'] : true;
+ $enable = $config['enabled'] ?? true;
if ($enable) {
$this->getEventManager()->on($instance);
}
@@ -169,7 +167,7 @@ protected function _create($class, $alias, $config)
* @return array A list of implemented finders and methods.
* @throws \LogicException when duplicate methods are connected.
*/
- protected function _getMethods(Behavior $instance, $class, $alias)
+ protected function _getMethods(Behavior $instance, string $class, string $alias): array
{
$finders = array_change_key_case($instance->implementedFinders());
$methods = array_change_key_case($instance->implementedMethods());
@@ -214,7 +212,7 @@ protected function _getMethods(Behavior $instance, $class, $alias)
* @param string $method The method to check for.
* @return bool
*/
- public function hasMethod($method)
+ public function hasMethod(string $method): bool
{
$method = strtolower($method);
@@ -230,7 +228,7 @@ public function hasMethod($method)
* @param string $method The method to check for.
* @return bool
*/
- public function hasFinder($method)
+ public function hasFinder(string $method): bool
{
$method = strtolower($method);
@@ -245,11 +243,11 @@ public function hasFinder($method)
* @return mixed The return value depends on the underlying behavior method.
* @throws \BadMethodCallException When the method is unknown.
*/
- public function call($method, array $args = [])
+ public function call(string $method, array $args = [])
{
$method = strtolower($method);
if ($this->hasMethod($method) && $this->has($this->_methodMap[$method][0])) {
- list($behavior, $callMethod) = $this->_methodMap[$method];
+ [$behavior, $callMethod] = $this->_methodMap[$method];
return call_user_func_array([$this->_loaded[$behavior], $callMethod], $args);
}
@@ -264,15 +262,15 @@ public function call($method, array $args = [])
*
* @param string $type The finder type to invoke.
* @param array $args The arguments you want to invoke the method with.
- * @return mixed The return value depends on the underlying behavior method.
+ * @return \Cake\ORM\Query The return value depends on the underlying behavior method.
* @throws \BadMethodCallException When the method is unknown.
*/
- public function callFinder($type, array $args = [])
+ public function callFinder(string $type, array $args = []): Query
{
$type = strtolower($type);
if ($this->hasFinder($type) && $this->has($this->_finderMap[$type][0])) {
- list($behavior, $callMethod) = $this->_finderMap[$type];
+ [$behavior, $callMethod] = $this->_finderMap[$type];
return call_user_func_array([$this->_loaded[$behavior], $callMethod], $args);
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/EagerLoadable.php b/app/vendor/cakephp/cakephp/src/ORM/EagerLoadable.php
index b01e6809e..820f9fcbf 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/EagerLoadable.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/EagerLoadable.php
@@ -1,4 +1,6 @@
_name = $name;
$allowed = [
@@ -147,7 +149,7 @@ public function __construct($name, array $config = [])
* @param \Cake\ORM\EagerLoadable $association The association to load.
* @return void
*/
- public function addAssociation($name, EagerLoadable $association)
+ public function addAssociation(string $name, EagerLoadable $association): void
{
$this->_associations[$name] = $association;
}
@@ -155,9 +157,9 @@ public function addAssociation($name, EagerLoadable $association)
/**
* Returns the Association class instance to use for loading the records.
*
- * @return array
+ * @return \Cake\ORM\EagerLoadable[]
*/
- public function associations()
+ public function associations(): array
{
return $this->_associations;
}
@@ -165,10 +167,15 @@ public function associations()
/**
* Gets the Association class instance to use for loading the records.
*
- * @return \Cake\ORM\Association|null
+ * @return \Cake\ORM\Association
+ * @throws \RuntimeException
*/
- public function instance()
+ public function instance(): Association
{
+ if ($this->_instance === null) {
+ throw new \RuntimeException('No instance set.');
+ }
+
return $this->_instance;
}
@@ -176,9 +183,9 @@ public function instance()
* Gets a dot separated string representing the path of associations
* that should be followed to fetch this level.
*
- * @return string|null
+ * @return string
*/
- public function aliasPath()
+ public function aliasPath(): string
{
return $this->_aliasPath;
}
@@ -197,7 +204,7 @@ public function aliasPath()
*
* @return string|null
*/
- public function propertyPath()
+ public function propertyPath(): ?string
{
return $this->_propertyPath;
}
@@ -208,7 +215,7 @@ public function propertyPath()
* @param bool $possible The value to set.
* @return $this
*/
- public function setCanBeJoined($possible)
+ public function setCanBeJoined(bool $possible)
{
$this->_canBeJoined = (bool)$possible;
@@ -218,22 +225,10 @@ public function setCanBeJoined($possible)
/**
* Gets whether or not this level can be fetched using a join.
*
- * If called with arguments it sets the value.
- * As of 3.4.0 the setter part is deprecated, use setCanBeJoined() instead.
- *
- * @param bool|null $possible The value to set.
* @return bool
*/
- public function canBeJoined($possible = null)
+ public function canBeJoined(): bool
{
- if ($possible !== null) {
- deprecationWarning(
- 'Using EagerLoadable::canBeJoined() as a setter is deprecated. ' .
- 'Use setCanBeJoined() instead.'
- );
- $this->setCanBeJoined($possible);
- }
-
return $this->_canBeJoined;
}
@@ -257,42 +252,18 @@ public function setConfig(array $config)
*
* @return array
*/
- public function getConfig()
+ public function getConfig(): array
{
return $this->_config;
}
- /**
- * Sets the list of options to pass to the association object for loading
- * the records.
- *
- * If called with no arguments it returns the current
- * value.
- *
- * @deprecated 3.4.0 Use setConfig()/getConfig() instead.
- * @param array|null $config The value to set.
- * @return array
- */
- public function config(array $config = null)
- {
- deprecationWarning(
- 'EagerLoadable::config() is deprecated. ' .
- 'Use setConfig()/getConfig() instead.'
- );
- if ($config !== null) {
- $this->setConfig($config);
- }
-
- return $this->getConfig();
- }
-
/**
* Gets whether or not this level was meant for a
* "matching" fetch operation.
*
* @return bool|null
*/
- public function forMatching()
+ public function forMatching(): ?bool
{
return $this->_forMatching;
}
@@ -311,7 +282,7 @@ public function forMatching()
*
* @return string|null
*/
- public function targetProperty()
+ public function targetProperty(): ?string
{
return $this->_targetProperty;
}
@@ -322,7 +293,7 @@ public function targetProperty()
*
* @return array
*/
- public function asContainArray()
+ public function asContainArray(): array
{
$associations = [];
foreach ($this->_associations as $assoc) {
diff --git a/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php b/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
index 55eb4a08f..252673123 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
@@ -1,4 +1,6 @@
getContain();
- }
-
if ($queryBuilder) {
if (!is_string($associations)) {
throw new InvalidArgumentException(
@@ -174,7 +165,7 @@ public function contain($associations = [], callable $queryBuilder = null)
*
* @return array Containments.
*/
- public function getContain()
+ public function getContain(): array
{
return $this->_containments;
}
@@ -187,7 +178,7 @@ public function getContain()
*
* @return void
*/
- public function clearContain()
+ public function clearContain(): void
{
$this->_containments = [];
$this->_normalized = null;
@@ -201,9 +192,9 @@ public function clearContain()
* @param bool $enable The value to set.
* @return $this
*/
- public function enableAutoFields($enable = true)
+ public function enableAutoFields(bool $enable = true)
{
- $this->_autoFields = (bool)$enable;
+ $this->_autoFields = $enable;
return $this;
}
@@ -225,31 +216,11 @@ public function disableAutoFields()
*
* @return bool The current value.
*/
- public function isAutoFieldsEnabled()
+ public function isAutoFieldsEnabled(): bool
{
return $this->_autoFields;
}
- /**
- * Sets/Gets whether or not contained associations will load fields automatically.
- *
- * @deprecated 3.4.0 Use enableAutoFields()/isAutoFieldsEnabled() instead.
- * @param bool|null $enable The value to set.
- * @return bool The current value.
- */
- public function autoFields($enable = null)
- {
- deprecationWarning(
- 'EagerLoader::autoFields() is deprecated. ' .
- 'Use enableAutoFields()/isAutoFieldsEnabled() instead.'
- );
- if ($enable !== null) {
- $this->enableAutoFields($enable);
- }
-
- return $this->isAutoFieldsEnabled();
- }
-
/**
* Adds a new association to the list that will be used to filter the results of
* any given query based on the results of finding records for that association.
@@ -258,6 +229,7 @@ public function autoFields($enable = null)
* `matching` option.
*
* ### Options
+ *
* - 'joinType': INNER, OUTER, ...
* - 'fields': Fields to contain
*
@@ -267,26 +239,27 @@ public function autoFields($enable = null)
* @param array $options Extra options for the association matching.
* @return $this
*/
- public function setMatching($assoc, callable $builder = null, $options = [])
+ public function setMatching(string $assoc, ?callable $builder = null, array $options = [])
{
if ($this->_matching === null) {
$this->_matching = new static();
}
if (!isset($options['joinType'])) {
- $options['joinType'] = QueryInterface::JOIN_TYPE_INNER;
+ $options['joinType'] = Query::JOIN_TYPE_INNER;
}
$assocs = explode('.', $assoc);
$last = array_pop($assocs);
$containments = [];
- $pointer =& $containments;
+ $pointer = &$containments;
$opts = ['matching' => true] + $options;
+ /** @psalm-suppress InvalidArrayOffset */
unset($opts['negateMatch']);
foreach ($assocs as $name) {
$pointer[$name] = $opts;
- $pointer =& $pointer[$name];
+ $pointer = &$pointer[$name];
}
$pointer[$last] = ['queryBuilder' => $builder, 'matching' => true] + $options;
@@ -301,7 +274,7 @@ public function setMatching($assoc, callable $builder = null, $options = [])
*
* @return array The resulting containments array
*/
- public function getMatching()
+ public function getMatching(): array
{
if ($this->_matching === null) {
$this->_matching = new static();
@@ -310,37 +283,6 @@ public function getMatching()
return $this->_matching->getContain();
}
- /**
- * Adds a new association to the list that will be used to filter the results of
- * any given query based on the results of finding records for that association.
- * You can pass a dot separated path of associations to this method as its first
- * parameter, this will translate in setting all those associations with the
- * `matching` option.
- *
- * If called with no arguments it will return the current tree of associations to
- * be matched.
- *
- * @deprecated 3.4.0 Use setMatching()/getMatching() instead.
- * @param string|null $assoc A single association or a dot separated path of associations.
- * @param callable|null $builder the callback function to be used for setting extra
- * options to the filtering query
- * @param array $options Extra options for the association matching, such as 'joinType'
- * and 'fields'
- * @return array The resulting containments array
- */
- public function matching($assoc = null, callable $builder = null, $options = [])
- {
- deprecationWarning(
- 'EagerLoader::matching() is deprecated. ' .
- 'Use setMatch()/getMatching() instead.'
- );
- if ($assoc !== null) {
- $this->setMatching($assoc, $builder, $options);
- }
-
- return $this->getMatching();
- }
-
/**
* Returns the fully normalized array of associations that should be eagerly
* loaded for a table. The normalized array will restructure the original array
@@ -357,7 +299,7 @@ public function matching($assoc = null, callable $builder = null, $options = [])
* will be normalized
* @return array
*/
- public function normalized(Table $repository)
+ public function normalized(Table $repository): array
{
if ($this->_normalized !== null || empty($this->_containments)) {
return (array)$this->_normalized;
@@ -390,12 +332,12 @@ public function normalized(Table $repository)
* with the new one
* @return array
*/
- protected function _reformatContain($associations, $original)
+ protected function _reformatContain(array $associations, array $original): array
{
$result = $original;
foreach ((array)$associations as $table => $options) {
- $pointer =& $result;
+ $pointer = &$result;
if (is_int($table)) {
$table = $options;
$options = [];
@@ -417,7 +359,7 @@ protected function _reformatContain($associations, $original)
$table = array_pop($path);
foreach ($path as $t) {
$pointer += [$t => []];
- $pointer =& $pointer[$t];
+ $pointer = &$pointer[$t];
}
}
@@ -427,7 +369,7 @@ protected function _reformatContain($associations, $original)
$options;
$options = $this->_reformatContain(
$options,
- isset($pointer[$table]) ? $pointer[$table] : []
+ $pointer[$table] ?? []
);
}
@@ -468,7 +410,7 @@ protected function _reformatContain($associations, $original)
* per association in the containments array
* @return void
*/
- public function attachAssociations(Query $query, Table $repository, $includeFields)
+ public function attachAssociations(Query $query, Table $repository, bool $includeFields): void
{
if (empty($this->_containments) && $this->_matching === null) {
return;
@@ -499,9 +441,9 @@ public function attachAssociations(Query $query, Table $repository, $includeFiel
*
* @param \Cake\ORM\Table $repository The table containing the associations to be
* attached
- * @return array
+ * @return \Cake\ORM\EagerLoadable[]
*/
- public function attachableAssociations(Table $repository)
+ public function attachableAssociations(Table $repository): array
{
$contain = $this->normalized($repository);
$matching = $this->_matching ? $this->_matching->normalized($repository) : [];
@@ -519,7 +461,7 @@ public function attachableAssociations(Table $repository)
* to be loaded
* @return \Cake\ORM\EagerLoadable[]
*/
- public function externalAssociations(Table $repository)
+ public function externalAssociations(Table $repository): array
{
if ($this->_loadExternal) {
return $this->_loadExternal;
@@ -544,15 +486,10 @@ public function externalAssociations(Table $repository)
* @return \Cake\ORM\EagerLoadable Object with normalized associations
* @throws \InvalidArgumentException When containments refer to associations that do not exist.
*/
- protected function _normalizeContain(Table $parent, $alias, $options, $paths)
+ protected function _normalizeContain(Table $parent, string $alias, array $options, array $paths): EagerLoadable
{
$defaults = $this->_containOptions;
$instance = $parent->getAssociation($alias);
- if (!$instance) {
- throw new InvalidArgumentException(
- sprintf('%s is not associated with %s', $parent->getAlias(), $alias)
- );
- }
$paths += ['aliasPath' => '', 'propertyPath' => '', 'root' => $alias];
$paths['aliasPath'] .= '.' . $alias;
@@ -605,7 +542,7 @@ protected function _normalizeContain(Table $parent, $alias, $options, $paths)
*
* @return void
*/
- protected function _fixStrategies()
+ protected function _fixStrategies(): void
{
foreach ($this->_aliasList as $aliases) {
foreach ($aliases as $configs) {
@@ -629,11 +566,10 @@ protected function _fixStrategies()
* @param \Cake\ORM\EagerLoadable $loadable The association config
* @return void
*/
- protected function _correctStrategy($loadable)
+ protected function _correctStrategy(EagerLoadable $loadable): void
{
$config = $loadable->getConfig();
- $currentStrategy = isset($config['strategy']) ?
- $config['strategy'] :
+ $currentStrategy = $config['strategy'] ??
'join';
if (!$loadable->canBeJoined() || $currentStrategy !== 'join') {
@@ -649,11 +585,11 @@ protected function _correctStrategy($loadable)
* Helper function used to compile a list of all associations that can be
* joined in the query.
*
- * @param array $associations list of associations from which to obtain joins.
- * @param array $matching list of associations that should be forcibly joined.
- * @return array
+ * @param \Cake\ORM\EagerLoadable[] $associations list of associations from which to obtain joins.
+ * @param \Cake\ORM\EagerLoadable[] $matching list of associations that should be forcibly joined.
+ * @return \Cake\ORM\EagerLoadable[]
*/
- protected function _resolveJoins($associations, $matching = [])
+ protected function _resolveJoins(array $associations, array $matching = []): array
{
$result = [];
foreach ($matching as $table => $loadable) {
@@ -687,16 +623,24 @@ protected function _resolveJoins($associations, $matching = [])
* associations
* @param \Cake\Database\StatementInterface $statement The statement created after executing the $query
* @return \Cake\Database\StatementInterface statement modified statement with extra loaders
+ * @throws \RuntimeException
*/
- public function loadExternal($query, $statement)
+ public function loadExternal(Query $query, StatementInterface $statement): StatementInterface
{
- $external = $this->externalAssociations($query->getRepository());
+ /** @var \Cake\ORM\Table $table */
+ $table = $query->getRepository();
+ $external = $this->externalAssociations($table);
if (empty($external)) {
return $statement;
}
$driver = $query->getConnection()->getDriver();
- list($collected, $statement) = $this->_collectKeys($external, $query, $statement);
+ [$collected, $statement] = $this->_collectKeys($external, $query, $statement);
+
+ // No records found, skip trying to attach associations.
+ if (empty($collected) && $statement->count() === 0) {
+ return $statement;
+ }
foreach ($external as $meta) {
$contain = $meta->associations();
@@ -706,11 +650,26 @@ public function loadExternal($query, $statement)
$path = $meta->aliasPath();
$requiresKeys = $instance->requiresKeys($config);
- if ($requiresKeys && empty($collected[$path][$alias])) {
- continue;
+ if ($requiresKeys) {
+ // If the path or alias has no key the required association load will fail.
+ // Nested paths are not subject to this condition because they could
+ // be attached to joined associations.
+ if (
+ strpos($path, '.') === false &&
+ (!array_key_exists($path, $collected) || !array_key_exists($alias, $collected[$path]))
+ ) {
+ $message = "Unable to load `{$path}` association. Ensure foreign key in `{$alias}` is selected.";
+ throw new InvalidArgumentException($message);
+ }
+
+ // If the association foreign keys are missing skip loading
+ // as the association could be optional.
+ if (empty($collected[$path][$alias])) {
+ continue;
+ }
}
- $keys = isset($collected[$path][$alias]) ? $collected[$path][$alias] : null;
+ $keys = $collected[$path][$alias] ?? null;
$f = $instance->eagerLoader(
$config + [
'query' => $query,
@@ -740,7 +699,7 @@ public function loadExternal($query, $statement)
* will be normalized
* @return array
*/
- public function associationsMap($table)
+ public function associationsMap(Table $table): array
{
$map = [];
@@ -748,6 +707,7 @@ public function associationsMap($table)
return $map;
}
+ /** @psalm-suppress PossiblyNullReference */
$map = $this->_buildAssociationsMap($map, $this->_matching->normalized($table), true);
$map = $this->_buildAssociationsMap($map, $this->normalized($table));
$map = $this->_buildAssociationsMap($map, $this->_joinsMap);
@@ -760,13 +720,12 @@ public function associationsMap($table)
* associationsMap() method.
*
* @param array $map An initial array for the map.
- * @param array $level An array of EagerLoadable instances.
+ * @param \Cake\ORM\EagerLoadable[] $level An array of EagerLoadable instances.
* @param bool $matching Whether or not it is an association loaded through `matching()`.
* @return array
*/
- protected function _buildAssociationsMap($map, $level, $matching = false)
+ protected function _buildAssociationsMap(array $map, array $level, bool $matching = false): array
{
- /** @var \Cake\ORM\EagerLoadable $meta */
foreach ($level as $assoc => $meta) {
$canBeJoined = $meta->canBeJoined();
$instance = $meta->instance();
@@ -778,7 +737,7 @@ protected function _buildAssociationsMap($map, $level, $matching = false)
'canBeJoined' => $canBeJoined,
'entityClass' => $instance->getTarget()->getEntityClass(),
'nestKey' => $canBeJoined ? $assoc : $meta->aliasPath(),
- 'matching' => $forMatching !== null ? $forMatching : $matching,
+ 'matching' => $forMatching ?? $matching,
'targetProperty' => $meta->targetProperty(),
];
if ($canBeJoined && $associations) {
@@ -803,8 +762,12 @@ protected function _buildAssociationsMap($map, $level, $matching = false)
* If not passed, the default property for the association will be used.
* @return void
*/
- public function addToJoinsMap($alias, Association $assoc, $asMatching = false, $targetProperty = null)
- {
+ public function addToJoinsMap(
+ string $alias,
+ Association $assoc,
+ bool $asMatching = false,
+ ?string $targetProperty = null
+ ): void {
$this->_joinsMap[$alias] = new EagerLoadable($alias, [
'aliasPath' => $alias,
'instance' => $assoc,
@@ -818,15 +781,14 @@ public function addToJoinsMap($alias, Association $assoc, $asMatching = false, $
* Helper function used to return the keys from the query records that will be used
* to eagerly load associations.
*
- * @param array $external the list of external associations to be loaded
+ * @param \Cake\ORM\EagerLoadable[] $external the list of external associations to be loaded
* @param \Cake\ORM\Query $query The query from which the results where generated
- * @param \Cake\Database\Statement\BufferedStatement $statement The statement to work on
+ * @param \Cake\Database\StatementInterface $statement The statement to work on
* @return array
*/
- protected function _collectKeys($external, $query, $statement)
+ protected function _collectKeys(array $external, Query $query, $statement): array
{
$collectKeys = [];
- /** @var \Cake\ORM\EagerLoadable $meta */
foreach ($external as $meta) {
$instance = $meta->instance();
if (!$instance->requiresKeys($meta->getConfig())) {
@@ -845,7 +807,6 @@ protected function _collectKeys($external, $query, $statement)
}
$collectKeys[$meta->aliasPath()] = [$alias, $pkFields, count($pkFields) === 1];
}
-
if (empty($collectKeys)) {
return [[], $statement];
}
@@ -865,18 +826,25 @@ protected function _collectKeys($external, $query, $statement)
* @param array $collectKeys The keys to collect
* @return array
*/
- protected function _groupKeys($statement, $collectKeys)
+ protected function _groupKeys(BufferedStatement $statement, array $collectKeys): array
{
$keys = [];
- while ($result = $statement->fetch('assoc')) {
+ foreach (($statement->fetchAll('assoc') ?: []) as $result) {
foreach ($collectKeys as $nestKey => $parts) {
- // Missed joins will have null in the results.
- if ($parts[2] === true && !isset($result[$parts[1][0]])) {
- continue;
- }
if ($parts[2] === true) {
- $value = $result[$parts[1][0]];
- $keys[$nestKey][$parts[0]][$value] = $value;
+ // Missed joins will have null in the results.
+ if (!array_key_exists($parts[1][0], $result)) {
+ continue;
+ }
+ // Assign empty array to avoid not found association when optional.
+ if (!isset($result[$parts[1][0]])) {
+ if (!isset($keys[$nestKey][$parts[0]])) {
+ $keys[$nestKey][$parts[0]] = [];
+ }
+ } else {
+ $value = $result[$parts[1][0]];
+ $keys[$nestKey][$parts[0]][$value] = $value;
+ }
continue;
}
@@ -888,7 +856,6 @@ protected function _groupKeys($statement, $collectKeys)
$keys[$nestKey][$parts[0]][implode(';', $collected)] = $collected;
}
}
-
$statement->rewind();
return $keys;
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Entity.php b/app/vendor/cakephp/cakephp/src/ORM/Entity.php
index 980273a1d..a71678754 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Entity.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Entity.php
@@ -1,4 +1,6 @@
_properties = $properties;
+ $this->_fields = $properties;
return;
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Exception/MissingBehaviorException.php b/app/vendor/cakephp/cakephp/src/ORM/Exception/MissingBehaviorException.php
index 3925742a3..eaaf511ad 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Exception/MissingBehaviorException.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Exception/MissingBehaviorException.php
@@ -1,4 +1,6 @@
_entity = $entity;
if (is_array($message)) {
@@ -63,7 +66,7 @@ public function __construct(EntityInterface $entity, $message, $code = null, $pr
*
* @return \Cake\Datasource\EntityInterface
*/
- public function getEntity()
+ public function getEntity(): EntityInterface
{
return $this->_entity;
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Exception/RolledbackTransactionException.php b/app/vendor/cakephp/cakephp/src/ORM/Exception/RolledbackTransactionException.php
index dd15821ea..ebabcd79d 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Exception/RolledbackTransactionException.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Exception/RolledbackTransactionException.php
@@ -1,4 +1,6 @@
getPrimaryKey();
$method = is_string($primaryKey) ? 'get' : 'extract';
@@ -75,21 +78,22 @@ protected function _getQuery($objects, $contain, $source)
return $entity->{$method}($primaryKey);
});
- /** @var \Cake\ORM\Query $query */
$query = $source
->find()
->select((array)$primaryKey)
->where(function ($exp, $q) use ($primaryKey, $keys, $source) {
+ /**
+ * @var \Cake\Database\Expression\QueryExpression $exp
+ * @var \Cake\ORM\Query $q
+ */
if (is_array($primaryKey) && count($primaryKey) === 1) {
$primaryKey = current($primaryKey);
}
if (is_string($primaryKey)) {
- /** @var \Cake\Database\Expression\QueryExpression $exp */
return $exp->in($source->aliasField($primaryKey), $keys->toList());
}
- /** @var \Cake\ORM\Query $q */
$types = array_intersect_key($q->getDefaultTypes(), array_flip($primaryKey));
$primaryKey = array_map([$source, 'aliasField'], $primaryKey);
@@ -113,13 +117,14 @@ protected function _getQuery($objects, $contain, $source)
*
* @param \Cake\ORM\Table $source The table having the top level associations
* @param string[] $associations The name of the top level associations
- * @return array
+ * @return string[]
*/
- protected function _getPropertyMap($source, $associations)
+ protected function _getPropertyMap(Table $source, array $associations): array
{
$map = [];
$container = $source->associations();
foreach ($associations as $assoc) {
+ /** @psalm-suppress PossiblyNullReference */
$map[$assoc] = $container->get($assoc)->getProperty();
}
@@ -131,12 +136,12 @@ protected function _getPropertyMap($source, $associations)
* entities.
*
* @param \Cake\Datasource\EntityInterface[]|\Traversable $objects The original list of entities
- * @param \Cake\Collection\CollectionInterface|\Cake\Database\Query $results The loaded results
+ * @param \Cake\Collection\CollectionInterface|\Cake\ORM\Query $results The loaded results
* @param string[] $associations The top level associations that were loaded
* @param \Cake\ORM\Table $source The table where the entities came from
* @return array
*/
- protected function _injectResults($objects, $results, $associations, $source)
+ protected function _injectResults(iterable $objects, $results, array $associations, Table $source): array
{
$injected = [];
$properties = $this->_getPropertyMap($source, $associations);
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Locator/LocatorAwareTrait.php b/app/vendor/cakephp/cakephp/src/ORM/Locator/LocatorAwareTrait.php
index 53e09ae7b..203d78b0a 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Locator/LocatorAwareTrait.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Locator/LocatorAwareTrait.php
@@ -1,4 +1,6 @@
setTableLocator($tableLocator);
- }
-
- return $this->getTableLocator();
- }
-
/**
* Sets the table locator.
*
@@ -67,7 +48,7 @@ public function setTableLocator(LocatorInterface $tableLocator)
*
* @return \Cake\ORM\Locator\LocatorInterface
*/
- public function getTableLocator()
+ public function getTableLocator(): LocatorInterface
{
if ($this->_tableLocator === null) {
$this->_tableLocator = TableRegistry::getTableLocator();
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Locator/LocatorInterface.php b/app/vendor/cakephp/cakephp/src/ORM/Locator/LocatorInterface.php
index 3bd075891..7559e87f3 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Locator/LocatorInterface.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Locator/LocatorInterface.php
@@ -1,4 +1,6 @@
_config;
}
- return isset($this->_config[$alias]) ? $this->_config[$alias] : [];
- }
-
- /**
- * Stores a list of options to be used when instantiating an object
- * with a matching alias.
- *
- * The options that can be stored are those that are recognized by `get()`
- * If second argument is omitted, it will return the current settings
- * for $alias.
- *
- * If no arguments are passed it will return the full configuration array for
- * all aliases
- *
- * @deprecated 3.4.0 Use setConfig()/getConfig() instead.
- * @param string|array|null $alias Name of the alias
- * @param array|null $options list of options for the alias
- * @return array The config data.
- * @throws \RuntimeException When you attempt to configure an existing table instance.
- */
- public function config($alias = null, $options = null)
- {
- deprecationWarning(
- 'TableLocator::config() is deprecated. ' .
- 'Use getConfig()/setConfig() instead.'
- );
- if ($alias !== null) {
- if (is_string($alias) && $options === null) {
- return $this->getConfig($alias);
- }
-
- $this->setConfig($alias, $options);
- }
-
- return $this->getConfig($alias);
+ return $this->_config[$alias] ?? [];
}
/**
@@ -177,25 +145,25 @@ public function config($alias = null, $options = null)
* `App\Model\Table\UsersTable` being used. If this class does not exist,
* then the default `Cake\ORM\Table` class will be used. By setting the `className`
* option you can define the specific class to use. The className option supports
- * plugin short class references {@link Cake\Core\App::shortName()}.
+ * plugin short class references {@link \Cake\Core\App::shortName()}.
* - `table` Define the table name to use. If undefined, this option will default to the underscored
* version of the alias name.
* - `connection` Inject the specific connection object to use. If this option and `connectionName` are undefined,
* The table class' `defaultConnectionName()` method will be invoked to fetch the connection name.
* - `connectionName` Define the connection name to use. The named connection will be fetched from
- * Cake\Datasource\ConnectionManager.
+ * {@link \Cake\Datasource\ConnectionManager}.
*
* *Note* If your `$alias` uses plugin syntax only the name part will be used as
* key in the registry. This means that if two plugins, or a plugin and app provide
* the same alias, the registry will only store the first instance.
*
- * @param string $alias The alias name you want to get.
+ * @param string $alias The alias name you want to get. Should be in CamelCase format.
* @param array $options The options you want to build the table with.
* If a table has already been loaded the options will be ignored.
* @return \Cake\ORM\Table
* @throws \RuntimeException When you try to configure an alias that already exists.
*/
- public function get($alias, array $options = [])
+ public function get(string $alias, array $options = []): Table
{
if (isset($this->_instances[$alias])) {
if (!empty($options) && $this->_options[$alias] !== $options) {
@@ -209,7 +177,7 @@ public function get($alias, array $options = [])
}
$this->_options[$alias] = $options;
- list(, $classAlias) = pluginSplit($alias);
+ [, $classAlias] = pluginSplit($alias);
$options = ['alias' => $classAlias] + $options;
if (isset($this->_config[$alias])) {
@@ -221,13 +189,13 @@ public function get($alias, array $options = [])
$options['className'] = $className;
} else {
if (empty($options['className'])) {
- $options['className'] = Inflector::camelize($alias);
+ $options['className'] = $alias;
}
if (!isset($options['table']) && strpos($options['className'], '\\') === false) {
- list(, $table) = pluginSplit($options['className']);
+ [, $table] = pluginSplit($options['className']);
$options['table'] = Inflector::underscore($table);
}
- $options['className'] = 'Cake\ORM\Table';
+ $options['className'] = Table::class;
}
if (empty($options['connection'])) {
@@ -248,7 +216,7 @@ public function get($alias, array $options = [])
$options['registryAlias'] = $alias;
$this->_instances[$alias] = $this->_create($options);
- if ($options['className'] === 'Cake\ORM\Table') {
+ if ($options['className'] === Table::class) {
$this->_fallbacked[$alias] = $this->_instances[$alias];
}
@@ -258,14 +226,14 @@ public function get($alias, array $options = [])
/**
* Gets the table class name.
*
- * @param string $alias The alias name you want to get.
+ * @param string $alias The alias name you want to get. Should be in CamelCase format.
* @param array $options Table options array.
- * @return string|false
+ * @return string|null
*/
- protected function _getClassName($alias, array $options = [])
+ protected function _getClassName(string $alias, array $options = []): ?string
{
if (empty($options['className'])) {
- $options['className'] = Inflector::camelize($alias);
+ $options['className'] = $alias;
}
if (strpos($options['className'], '\\') !== false && class_exists($options['className'])) {
@@ -274,12 +242,12 @@ protected function _getClassName($alias, array $options = [])
foreach ($this->locations as $location) {
$class = App::className($options['className'], $location, 'Table');
- if ($class !== false) {
+ if ($class !== null) {
return $class;
}
}
- return false;
+ return null;
}
/**
@@ -288,31 +256,33 @@ protected function _getClassName($alias, array $options = [])
* @param array $options The alias to check for.
* @return \Cake\ORM\Table
*/
- protected function _create(array $options)
+ protected function _create(array $options): Table
{
+ // phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.InvalidFormat
+ /** @var \Cake\ORM\Table */
return new $options['className']($options);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function exists($alias)
+ public function exists(string $alias): bool
{
return isset($this->_instances[$alias]);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function set($alias, Table $object)
+ public function set(string $alias, Table $object): Table
{
return $this->_instances[$alias] = $object;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function clear()
+ public function clear(): void
{
$this->_instances = [];
$this->_config = [];
@@ -328,15 +298,15 @@ public function clear()
*
* @return \Cake\ORM\Table[]
*/
- public function genericInstances()
+ public function genericInstances(): array
{
return $this->_fallbacked;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function remove($alias)
+ public function remove(string $alias): void
{
unset(
$this->_instances[$alias],
@@ -352,7 +322,7 @@ public function remove($alias)
* @return $this
* @since 3.8.0
*/
- public function addLocation($location)
+ public function addLocation(string $location)
{
$location = str_replace('\\', '/', $location);
$this->locations[] = trim($location, '/');
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Marshaller.php b/app/vendor/cakephp/cakephp/src/ORM/Marshaller.php
index f3c4dbf20..5586b4b17 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Marshaller.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Marshaller.php
@@ -1,4 +1,6 @@
_table->getSchema();
@@ -72,7 +75,7 @@ protected function _buildPropertyMap($data, $options)
$columnType = $schema->getColumnType($prop);
if ($columnType) {
$map[$prop] = function ($value, $entity) use ($columnType) {
- return Type::build($columnType)->marshal($value);
+ return TypeFactory::build($columnType)->marshal($value);
};
}
}
@@ -91,9 +94,9 @@ protected function _buildPropertyMap($data, $options)
// it is a missing association that we should error on.
if (!$this->_table->hasAssociation($key)) {
if (substr($key, 0, 1) !== '_') {
- throw new \InvalidArgumentException(sprintf(
+ throw new InvalidArgumentException(sprintf(
'Cannot marshal data for "%s" association. It is not associated with "%s".',
- $key,
+ (string)$key,
$this->_table->getAlias()
));
}
@@ -140,7 +143,6 @@ protected function _buildPropertyMap($data, $options)
* - validate: Set to false to disable validation. Can also be a string of the validator ruleset to be applied.
* Defaults to true/default.
* - associated: Associations listed here will be marshalled as well. Defaults to null.
- * - fieldList: (deprecated) Since 3.4.0. Use fields instead.
* - fields: A whitelist of fields to be assigned to the entity. If not present,
* the accessible fields list in the entity will be used. Defaults to null.
* - accessibleFields: A list of fields to allow or deny in entity accessible fields. Defaults to null
@@ -172,9 +174,9 @@ protected function _buildPropertyMap($data, $options)
* @see \Cake\ORM\Table::newEntity()
* @see \Cake\ORM\Entity::$_accessible
*/
- public function one(array $data, array $options = [])
+ public function one(array $data, array $options = []): EntityInterface
{
- list($data, $options) = $this->_prepareDataAndOptions($data, $options);
+ [$data, $options] = $this->_prepareDataAndOptions($data, $options);
$primaryKey = (array)$this->_table->getPrimaryKey();
$entityClass = $this->_table->getEntityClass();
@@ -230,7 +232,6 @@ public function one(array $data, array $options = [])
}
$entity->setErrors($errors);
- $this->dispatchAfterMarshal($entity, $data, $options);
return $entity;
}
@@ -244,7 +245,7 @@ public function one(array $data, array $options = [])
* @return array The list of validation errors.
* @throws \RuntimeException If no validator can be created.
*/
- protected function _validate($data, $options, $isNew)
+ protected function _validate(array $data, array $options, bool $isNew): array
{
if (!$options['validate']) {
return [];
@@ -276,18 +277,10 @@ protected function _validate($data, $options, $isNew)
* @param array $options The options passed to this marshaller.
* @return array An array containing prepared data and options.
*/
- protected function _prepareDataAndOptions($data, $options)
+ protected function _prepareDataAndOptions(array $data, array $options): array
{
$options += ['validate' => true];
- if (!isset($options['fields']) && isset($options['fieldList'])) {
- deprecationWarning(
- 'The `fieldList` option for marshalling is deprecated. Use the `fields` option instead.'
- );
- $options['fields'] = $options['fieldList'];
- unset($options['fieldList']);
- }
-
$tableName = $this->_table->getAlias();
if (isset($data[$tableName])) {
$data += $data[$tableName];
@@ -305,11 +298,11 @@ protected function _prepareDataAndOptions($data, $options)
* Create a new sub-marshaller and marshal the associated data.
*
* @param \Cake\ORM\Association $assoc The association to marshall
- * @param array $value The data to hydrate
+ * @param mixed $value The data to hydrate. If not an array, this method will return null.
* @param array $options List of options.
* @return \Cake\Datasource\EntityInterface|\Cake\Datasource\EntityInterface[]|null
*/
- protected function _marshalAssociation($assoc, $value, $options)
+ protected function _marshalAssociation(Association $assoc, $value, array $options)
{
if (!is_array($value)) {
return null;
@@ -347,7 +340,6 @@ protected function _marshalAssociation($assoc, $value, $options)
* - validate: Set to false to disable validation. Can also be a string of the validator ruleset to be applied.
* Defaults to true/default.
* - associated: Associations listed here will be marshalled as well. Defaults to null.
- * - fieldList: (deprecated) Since 3.4.0. Use fields instead
* - fields: A whitelist of fields to be assigned to the entity. If not present,
* the accessible fields list in the entity will be used. Defaults to null.
* - accessibleFields: A list of fields to allow or deny in entity accessible fields. Defaults to null
@@ -361,7 +353,7 @@ protected function _marshalAssociation($assoc, $value, $options)
* @see \Cake\ORM\Table::newEntities()
* @see \Cake\ORM\Entity::$_accessible
*/
- public function many(array $data, array $options = [])
+ public function many(array $data, array $options = []): array
{
$output = [];
foreach ($data as $record) {
@@ -388,10 +380,10 @@ public function many(array $data, array $options = [])
* @throws \InvalidArgumentException
* @throws \RuntimeException
*/
- protected function _belongsToMany(BelongsToMany $assoc, array $data, $options = [])
+ protected function _belongsToMany(BelongsToMany $assoc, array $data, array $options = []): array
{
- $associated = isset($options['associated']) ? $options['associated'] : [];
- $forceNew = isset($options['forceNew']) ? $options['forceNew'] : false;
+ $associated = $options['associated'] ?? [];
+ $forceNew = $options['forceNew'] ?? false;
$data = array_values($data);
@@ -399,7 +391,6 @@ protected function _belongsToMany(BelongsToMany $assoc, array $data, $options =
$primaryKey = array_flip((array)$target->getPrimaryKey());
$records = $conditions = [];
$primaryCount = count($primaryKey);
- $conditions = [];
foreach ($data as $i => $row) {
if (!is_array($row)) {
@@ -480,7 +471,7 @@ protected function _belongsToMany(BelongsToMany $assoc, array $data, $options =
* @param array $ids The list of ids to load.
* @return \Cake\Datasource\EntityInterface[] An array of entities.
*/
- protected function _loadAssociatedByIds($assoc, $ids)
+ protected function _loadAssociatedByIds(Association $assoc, array $ids): array
{
if (empty($ids)) {
return [];
@@ -496,12 +487,7 @@ protected function _loadAssociatedByIds($assoc, $ids)
if (!is_array($first) || count($first) !== count($primaryKey)) {
return [];
}
- $type = [];
- $schema = $target->getSchema();
- foreach ((array)$target->getPrimaryKey() as $column) {
- $type[] = $schema->getColumnType($column);
- }
- $filter = new TupleComparison($primaryKey, $ids, $type, 'IN');
+ $filter = new TupleComparison($primaryKey, $ids, [], 'IN');
} else {
$filter = [$primaryKey[0] . ' IN' => $ids];
}
@@ -509,23 +495,6 @@ protected function _loadAssociatedByIds($assoc, $ids)
return $target->find()->where($filter)->toArray();
}
- /**
- * Loads a list of belongs to many from ids.
- *
- * @param \Cake\ORM\Association $assoc The association class for the belongsToMany association.
- * @param array $ids The list of ids to load.
- * @return \Cake\Datasource\EntityInterface[] An array of entities.
- * @deprecated Use _loadAssociatedByIds()
- */
- protected function _loadBelongsToMany($assoc, $ids)
- {
- deprecationWarning(
- 'Marshaller::_loadBelongsToMany() is deprecated. Use _loadAssociatedByIds() instead.'
- );
-
- return $this->_loadAssociatedByIds($assoc, $ids);
- }
-
/**
* Merges `$data` into `$entity` and recursively does the same for each one of
* the association names passed in `$options`. When merging associations, if an
@@ -542,7 +511,6 @@ protected function _loadBelongsToMany($assoc, $ids)
* - associated: Associations listed here will be marshalled as well.
* - validate: Whether or not to validate data before hydrating the entities. Can
* also be set to a string to use a specific validator. Defaults to true/default.
- * - fieldList: (deprecated) Since 3.4.0. Use fields instead
* - fields: A whitelist of fields to be assigned to the entity. If not present
* the accessible fields list in the entity will be used.
* - accessibleFields: A list of fields to allow or deny in entity accessible fields.
@@ -564,9 +532,9 @@ protected function _loadBelongsToMany($assoc, $ids)
* @return \Cake\Datasource\EntityInterface
* @see \Cake\ORM\Entity::$_accessible
*/
- public function merge(EntityInterface $entity, array $data, array $options = [])
+ public function merge(EntityInterface $entity, array $data, array $options = []): EntityInterface
{
- list($data, $options) = $this->_prepareDataAndOptions($data, $options);
+ [$data, $options] = $this->_prepareDataAndOptions($data, $options);
$isNew = $entity->isNew();
$keys = [];
@@ -602,9 +570,19 @@ public function merge(EntityInterface $entity, array $data, array $options = [])
// the original/updated list could contain references to the
// same objects, even though those objects may have changed internally.
if (
- (is_scalar($value) && $original === $value) ||
- ($value === null && $original === $value) ||
- (is_object($value) && !($value instanceof EntityInterface) && $original == $value)
+ (
+ is_scalar($value)
+ && $original === $value
+ )
+ || (
+ $value === null
+ && $original === $value
+ )
+ || (
+ is_object($value)
+ && !($value instanceof EntityInterface)
+ && $original === $value
+ )
) {
continue;
}
@@ -621,7 +599,6 @@ public function merge(EntityInterface $entity, array $data, array $options = [])
$entity->setDirty($field, $value->isDirty());
}
}
- $this->dispatchAfterMarshal($entity, $data, $options);
return $entity;
}
@@ -635,7 +612,6 @@ public function merge(EntityInterface $entity, array $data, array $options = [])
$entity->setDirty($field, $properties[$field]->isDirty());
}
}
- $this->dispatchAfterMarshal($entity, $data, $options);
return $entity;
}
@@ -660,19 +636,19 @@ public function merge(EntityInterface $entity, array $data, array $options = [])
* - validate: Whether or not to validate data before hydrating the entities. Can
* also be set to a string to use a specific validator. Defaults to true/default.
* - associated: Associations listed here will be marshalled as well.
- * - fieldList: (deprecated) Since 3.4.0. Use fields instead
* - fields: A whitelist of fields to be assigned to the entity. If not present,
* the accessible fields list in the entity will be used.
* - accessibleFields: A list of fields to allow or deny in entity accessible fields.
*
- * @param \Cake\Datasource\EntityInterface[]|\Traversable $entities the entities that will get the
+ * @param iterable<\Cake\Datasource\EntityInterface> $entities the entities that will get the
* data merged in
* @param array $data list of arrays to be merged into the entities
* @param array $options List of options.
* @return \Cake\Datasource\EntityInterface[]
* @see \Cake\ORM\Entity::$_accessible
+ * @psalm-suppress NullArrayOffset
*/
- public function mergeMany($entities, array $data, array $options = [])
+ public function mergeMany(iterable $entities, array $data, array $options = []): array
{
$primary = (array)$this->_table->getPrimaryKey();
@@ -680,7 +656,7 @@ public function mergeMany($entities, array $data, array $options = [])
->groupBy(function ($el) use ($primary) {
$keys = [];
foreach ($primary as $key) {
- $keys[] = isset($el[$key]) ? $el[$key] : '';
+ $keys[] = $el[$key] ?? '';
}
return implode(';', $keys);
@@ -690,7 +666,8 @@ public function mergeMany($entities, array $data, array $options = [])
})
->toArray();
- $new = isset($indexed[null]) ? $indexed[null] : [];
+ $new = $indexed[null] ?? [];
+ /** @psalm-suppress PossiblyNullArrayOffset */
unset($indexed[null]);
$output = [];
@@ -700,7 +677,7 @@ public function mergeMany($entities, array $data, array $options = [])
}
$key = implode(';', $entity->extract($primary));
- if ($key === null || !isset($indexed[$key])) {
+ if (!isset($indexed[$key])) {
continue;
}
@@ -710,7 +687,7 @@ public function mergeMany($entities, array $data, array $options = [])
$conditions = (new Collection($indexed))
->map(function ($data, $key) {
- return explode(';', $key);
+ return explode(';', (string)$key);
})
->filter(function ($keys) use ($primary) {
return count(array_filter($keys, 'strlen')) === count($primary);
@@ -748,11 +725,11 @@ public function mergeMany($entities, array $data, array $options = [])
*
* @param \Cake\Datasource\EntityInterface|\Cake\Datasource\EntityInterface[] $original The original entity
* @param \Cake\ORM\Association $assoc The association to merge
- * @param array $value The data to hydrate
+ * @param mixed $value The array of data to hydrate. If not an array, this method will return null.
* @param array $options List of options.
* @return \Cake\Datasource\EntityInterface|\Cake\Datasource\EntityInterface[]|null
*/
- protected function _mergeAssociation($original, $assoc, $value, $options)
+ protected function _mergeAssociation($original, Association $assoc, $value, array $options)
{
if (!$original) {
return $this->_marshalAssociation($assoc, $value, $options);
@@ -785,6 +762,7 @@ protected function _mergeAssociation($original, $assoc, $value, $options)
}
}
+ /** @psalm-suppress PossiblyInvalidArgument */
return $marshaller->mergeMany($original, $value, (array)$options);
}
@@ -792,15 +770,15 @@ protected function _mergeAssociation($original, $assoc, $value, $options)
* Creates a new sub-marshaller and merges the associated data for a BelongstoMany
* association.
*
- * @param \Cake\Datasource\EntityInterface $original The original entity
- * @param \Cake\ORM\Association $assoc The association to marshall
+ * @param \Cake\Datasource\EntityInterface[] $original The original entities list.
+ * @param \Cake\ORM\Association\BelongsToMany $assoc The association to marshall
* @param array $value The data to hydrate
* @param array $options List of options.
* @return \Cake\Datasource\EntityInterface[]
*/
- protected function _mergeBelongsToMany($original, $assoc, $value, $options)
+ protected function _mergeBelongsToMany(array $original, BelongsToMany $assoc, array $value, array $options): array
{
- $associated = isset($options['associated']) ? $options['associated'] : [];
+ $associated = $options['associated'] ?? [];
$hasIds = array_key_exists('_ids', $value);
$onlyIds = array_key_exists('onlyIds', $options) && $options['onlyIds'];
@@ -822,15 +800,15 @@ protected function _mergeBelongsToMany($original, $assoc, $value, $options)
/**
* Merge the special _joinData property into the entity set.
*
- * @param \Cake\Datasource\EntityInterface $original The original entity
+ * @param \Cake\Datasource\EntityInterface[] $original The original entities list.
* @param \Cake\ORM\Association\BelongsToMany $assoc The association to marshall
* @param array $value The data to hydrate
* @param array $options List of options.
* @return \Cake\Datasource\EntityInterface[] An array of entities
*/
- protected function _mergeJoinData($original, $assoc, $value, $options)
+ protected function _mergeJoinData(array $original, BelongsToMany $assoc, array $value, array $options): array
{
- $associated = isset($options['associated']) ? $options['associated'] : [];
+ $associated = $options['associated'] ?? [];
$extra = [];
foreach ($original as $entity) {
// Mark joinData as accessible so we can marshal it properly.
@@ -864,14 +842,14 @@ protected function _mergeJoinData($original, $assoc, $value, $options)
// Scalar data can't be handled
if (!is_array($value)) {
- $record->unsetProperty('_joinData');
+ $record->unset('_joinData');
continue;
}
// Marshal data into the old object, or make a new joinData object.
if (isset($extra[$hash])) {
$record->set('_joinData', $marshaller->merge($extra[$hash], $value, $nested));
- } elseif (is_array($value)) {
+ } else {
$joinData = $marshaller->one($value, $nested);
$record->set('_joinData', $joinData);
}
@@ -879,19 +857,4 @@ protected function _mergeJoinData($original, $assoc, $value, $options)
return $records;
}
-
- /**
- * dispatch Model.afterMarshal event.
- *
- * @param \Cake\Datasource\EntityInterface $entity The entity that was marshaled.
- * @param array $data readOnly $data to use.
- * @param array $options List of options that are readOnly.
- * @return void
- */
- protected function dispatchAfterMarshal(EntityInterface $entity, array $data, array $options)
- {
- $data = new ArrayObject($data);
- $options = new ArrayObject($options);
- $this->_table->dispatchEvent('Model.afterMarshal', compact('entity', 'data', 'options'));
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/PropertyMarshalInterface.php b/app/vendor/cakephp/cakephp/src/ORM/PropertyMarshalInterface.php
index bf2c6d565..f52ce7494 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/PropertyMarshalInterface.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/PropertyMarshalInterface.php
@@ -1,4 +1,6 @@
callable]` of additional properties to marshal.
*/
- public function buildMarshalMap($marshaller, $map, $options);
+ public function buildMarshalMap(Marshaller $marshaller, array $map, array $options): array;
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Query.php b/app/vendor/cakephp/cakephp/src/ORM/Query.php
index 0dd1db232..de6ac1033 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Query.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Query.php
@@ -1,4 +1,6 @@
repository($table);
- if ($this->_repository) {
+ if ($this->_repository !== null) {
$this->addDefaultTypes($this->_repository);
}
}
@@ -203,12 +213,12 @@ public function __construct($connection, $table)
* all the fields in the schema of the table or the association will be added to
* the select clause.
*
- * @param array|\Cake\Database\ExpressionInterface|callable|string|\Cake\ORM\Table|\Cake\ORM\Association $fields fields
+ * @param array|\Cake\Database\ExpressionInterface|callable|string|\Cake\ORM\Table|\Cake\ORM\Association $fields Fields
* to be added to the list.
* @param bool $overwrite whether to reset fields with passed list or not
* @return $this
*/
- public function select($fields = [], $overwrite = false)
+ public function select($fields = [], bool $overwrite = false)
{
if ($fields instanceof Association) {
$fields = $fields->getTarget();
@@ -231,17 +241,17 @@ public function select($fields = [], $overwrite = false)
* @param \Cake\ORM\Table|\Cake\ORM\Association $table The table to use to get an array of columns
* @param string[] $excludedFields The un-aliased column names you do not want selected from $table
* @param bool $overwrite Whether to reset/remove previous selected fields
- * @return Query
+ * @return $this
* @throws \InvalidArgumentException If Association|Table is not passed in first argument
*/
- public function selectAllExcept($table, array $excludedFields, $overwrite = false)
+ public function selectAllExcept($table, array $excludedFields, bool $overwrite = false)
{
if ($table instanceof Association) {
$table = $table->getTarget();
}
if (!($table instanceof Table)) {
- throw new \InvalidArgumentException('You must provide either an Association or a Table object');
+ throw new InvalidArgumentException('You must provide either an Association or a Table object');
}
$fields = array_diff($table->getSchema()->columns(), $excludedFields);
@@ -293,7 +303,7 @@ public function setEagerLoader(EagerLoader $instance)
*
* @return \Cake\ORM\EagerLoader
*/
- public function getEagerLoader()
+ public function getEagerLoader(): EagerLoader
{
if ($this->_eagerLoader === null) {
$this->_eagerLoader = new EagerLoader();
@@ -302,29 +312,6 @@ public function getEagerLoader()
return $this->_eagerLoader;
}
- /**
- * Sets the instance of the eager loader class to use for loading associations
- * and storing containments. If called with no arguments, it will return the
- * currently configured instance.
- *
- * @deprecated 3.4.0 Use setEagerLoader()/getEagerLoader() instead.
- * @param \Cake\ORM\EagerLoader|null $instance The eager loader to use. Pass null
- * to get the current eagerloader.
- * @return \Cake\ORM\EagerLoader|$this
- */
- public function eagerLoader(EagerLoader $instance = null)
- {
- deprecationWarning(
- 'Query::eagerLoader() is deprecated. ' .
- 'Use setEagerLoader()/getEagerLoader() instead.'
- );
- if ($instance !== null) {
- return $this->setEagerLoader($instance);
- }
-
- return $this->getEagerLoader();
- }
-
/**
* Sets the list of associations that should be eagerly loaded along with this
* query. The list of associated tables passed must have been previously set as
@@ -431,36 +418,23 @@ public function eagerLoader(EagerLoader $instance = null)
* ]);
* ```
*
- * If called with no arguments, this function will return an array with
- * with the list of previously configured associations to be contained in the
- * result. This getter part is deprecated as of 3.6.0. Use getContain() instead.
- *
* If called with an empty first argument and `$override` is set to true, the
* previous list will be emptied.
*
- * @param array|string|null $associations List of table aliases to be queried.
+ * @param array|string $associations List of table aliases to be queried.
* @param callable|bool $override The query builder for the association, or
* if associations is an array, a bool on whether to override previous list
* with the one passed
* defaults to merging previous list with the new one.
- * @return array|$this
+ * @return $this
*/
- public function contain($associations = null, $override = false)
+ public function contain($associations, $override = false)
{
$loader = $this->getEagerLoader();
if ($override === true) {
$this->clearContain();
}
- if ($associations === null) {
- deprecationWarning(
- 'Using Query::contain() as getter is deprecated. ' .
- 'Use getContain() instead.'
- );
-
- return $loader->getContain();
- }
-
$queryBuilder = null;
if (is_callable($override)) {
$queryBuilder = $override;
@@ -481,7 +455,7 @@ public function contain($associations = null, $override = false)
/**
* @return array
*/
- public function getContain()
+ public function getContain(): array
{
return $this->getEagerLoader()->getContain();
}
@@ -509,7 +483,7 @@ public function clearContain()
* @param array $associations The nested tree of associations to walk.
* @return void
*/
- protected function _addAssociationsToTypeMap($table, $typeMap, $associations)
+ protected function _addAssociationsToTypeMap(Table $table, TypeMap $typeMap, array $associations): void
{
foreach ($associations as $name => $nested) {
if (!$table->hasAssociation($name)) {
@@ -577,7 +551,7 @@ protected function _addAssociationsToTypeMap($table, $typeMap, $associations)
* that can be used to add custom conditions or selecting some fields
* @return $this
*/
- public function matching($assoc, callable $builder = null)
+ public function matching(string $assoc, ?callable $builder = null)
{
$result = $this->getEagerLoader()->setMatching($assoc, $builder)->getMatching();
$this->_addAssociationsToTypeMap($this->getRepository(), $this->getTypeMap(), $result);
@@ -601,7 +575,7 @@ public function matching($assoc, callable $builder = null)
* ->select(['total_articles' => $query->func()->count('Articles.id')])
* ->leftJoinWith('Articles')
* ->group(['Users.id'])
- * ->enableAutoFields(true);
+ * ->enableAutoFields();
* ```
*
* You can also customize the conditions passed to the LEFT JOIN:
@@ -614,7 +588,7 @@ public function matching($assoc, callable $builder = null)
* return $q->where(['Articles.votes >=' => 5]);
* })
* ->group(['Users.id'])
- * ->enableAutoFields(true);
+ * ->enableAutoFields();
* ```
*
* This will create the following SQL:
@@ -649,11 +623,11 @@ public function matching($assoc, callable $builder = null)
* that can be used to add custom conditions or selecting some fields
* @return $this
*/
- public function leftJoinWith($assoc, callable $builder = null)
+ public function leftJoinWith(string $assoc, ?callable $builder = null)
{
$result = $this->getEagerLoader()
->setMatching($assoc, $builder, [
- 'joinType' => QueryInterface::JOIN_TYPE_LEFT,
+ 'joinType' => Query::JOIN_TYPE_LEFT,
'fields' => false,
])
->getMatching();
@@ -698,11 +672,11 @@ public function leftJoinWith($assoc, callable $builder = null)
* @return $this
* @see \Cake\ORM\Query::matching()
*/
- public function innerJoinWith($assoc, callable $builder = null)
+ public function innerJoinWith(string $assoc, ?callable $builder = null)
{
$result = $this->getEagerLoader()
->setMatching($assoc, $builder, [
- 'joinType' => QueryInterface::JOIN_TYPE_INNER,
+ 'joinType' => Query::JOIN_TYPE_INNER,
'fields' => false,
])
->getMatching();
@@ -762,11 +736,11 @@ public function innerJoinWith($assoc, callable $builder = null)
* that can be used to add custom conditions or selecting some fields
* @return $this
*/
- public function notMatching($assoc, callable $builder = null)
+ public function notMatching(string $assoc, ?callable $builder = null)
{
$result = $this->getEagerLoader()
->setMatching($assoc, $builder, [
- 'joinType' => QueryInterface::JOIN_TYPE_LEFT,
+ 'joinType' => Query::JOIN_TYPE_LEFT,
'fields' => false,
'negateMatch' => true,
])
@@ -778,8 +752,6 @@ public function notMatching($assoc, callable $builder = null)
}
/**
- * {@inheritDoc}
- *
* Populates or adds parts to current query clauses using an array.
* This is handy for passing all query clauses at once. The option array accepts:
*
@@ -814,6 +786,9 @@ public function notMatching($assoc, callable $builder = null)
* ->where(['created >=' => '2013-01-01'])
* ->limit(10)
* ```
+ *
+ * @param array $options the options to be applied
+ * @return $this
*/
public function applyOptions(array $options)
{
@@ -857,38 +832,25 @@ public function applyOptions(array $options)
*
* This method creates query clones that are useful when working with subqueries.
*
- * @return \Cake\ORM\Query
+ * @return static
*/
public function cleanCopy()
{
$clone = clone $this;
$clone->setEagerLoader(clone $this->getEagerLoader());
$clone->triggerBeforeFind();
- $clone->enableAutoFields(false);
+ $clone->disableAutoFields();
$clone->limit(null);
$clone->order([], true);
$clone->offset(null);
$clone->mapReduce(null, null, true);
- $clone->formatResults(null, true);
+ $clone->formatResults(null, self::OVERWRITE);
$clone->setSelectTypeMap(new TypeMap());
$clone->decorateResults(null, true);
return $clone;
}
- /**
- * Clears the internal result cache and the internal count value from the current
- * query object.
- *
- * @return $this
- */
- public function clearResult()
- {
- $this->_dirty();
-
- return $this;
- }
-
/**
* Object clone hook.
*
@@ -899,7 +861,7 @@ public function clearResult()
public function __clone()
{
parent::__clone();
- if ($this->_eagerLoader) {
+ if ($this->_eagerLoader !== null) {
$this->_eagerLoader = clone $this->_eagerLoader;
}
}
@@ -910,8 +872,10 @@ public function __clone()
* Returns the COUNT(*) for the query. If the query has not been
* modified, and the count has already been performed the cached
* value is returned
+ *
+ * @return int
*/
- public function count()
+ public function count(): int
{
if ($this->_resultsCount === null) {
$this->_resultsCount = $this->_performCount();
@@ -925,11 +889,11 @@ public function count()
*
* @return int
*/
- protected function _performCount()
+ protected function _performCount(): int
{
$query = $this->cleanCopy();
$counter = $this->_counter;
- if ($counter) {
+ if ($counter !== null) {
$query->counter(null);
return (int)$counter($query);
@@ -960,10 +924,10 @@ protected function _performCount()
$count = ['count' => $query->func()->count('*')];
if (!$complex) {
- $query->getEagerLoader()->enableAutoFields(false);
+ $query->getEagerLoader()->disableAutoFields();
$statement = $query
->select($count, true)
- ->enableAutoFields(false)
+ ->disableAutoFields()
->execute();
} else {
$statement = $this->getConnection()->newQuery()
@@ -972,10 +936,14 @@ protected function _performCount()
->execute();
}
- $result = $statement->fetch('assoc')['count'];
+ $result = $statement->fetch('assoc');
$statement->closeCursor();
- return (int)$result;
+ if ($result === false) {
+ return 0;
+ }
+
+ return (int)$result['count'];
}
/**
@@ -996,7 +964,7 @@ protected function _performCount()
* @param callable|null $counter The counter value
* @return $this
*/
- public function counter($counter)
+ public function counter(?callable $counter)
{
$this->_counter = $counter;
@@ -1011,10 +979,10 @@ public function counter($counter)
* @param bool $enable Use a boolean to set the hydration mode.
* @return $this
*/
- public function enableHydration($enable = true)
+ public function enableHydration(bool $enable = true)
{
$this->_dirty();
- $this->_hydrate = (bool)$enable;
+ $this->_hydrate = $enable;
return $this;
}
@@ -1040,37 +1008,18 @@ public function disableHydration()
*
* @return bool
*/
- public function isHydrationEnabled()
+ public function isHydrationEnabled(): bool
{
return $this->_hydrate;
}
- /**
- * Toggle hydrating entities.
- *
- * If set to false array results will be returned.
- *
- * @deprecated 3.4.0 Use enableHydration()/isHydrationEnabled() instead.
- * @param bool|null $enable Use a boolean to set the hydration mode.
- * Null will fetch the current hydration mode.
- * @return bool|$this A boolean when reading, and $this when setting the mode.
- */
- public function hydrate($enable = null)
- {
- deprecationWarning(
- 'Query::hydrate() is deprecated. ' .
- 'Use enableHydration()/isHydrationEnabled() instead.'
- );
- if ($enable === null) {
- return $this->isHydrationEnabled();
- }
-
- return $this->enableHydration($enable);
- }
-
/**
* {@inheritDoc}
*
+ * @param \Closure|string|false $key Either the cache key or a function to generate the cache key.
+ * When using a function, this query instance will be supplied as an argument.
+ * @param string|\Cake\Cache\CacheEngine $config Either the name of the cache config to use, or
+ * a cache config instance.
* @return $this
* @throws \RuntimeException When you attempt to cache a non-select query.
*/
@@ -1086,9 +1035,10 @@ public function cache($key, $config = 'default')
/**
* {@inheritDoc}
*
+ * @return \Cake\Datasource\ResultSetInterface
* @throws \RuntimeException if this method is called on a non-select Query.
*/
- public function all()
+ public function all(): ResultSetInterface
{
if ($this->_type !== 'select' && $this->_type !== null) {
throw new RuntimeException(
@@ -1106,7 +1056,7 @@ public function all()
*
* @return void
*/
- public function triggerBeforeFind()
+ public function triggerBeforeFind(): void
{
if (!$this->_beforeFindFired && $this->_type === 'select') {
$this->_beforeFindFired = true;
@@ -1122,12 +1072,9 @@ public function triggerBeforeFind()
}
/**
- * Converts the Node into a SQL string fragment.
- *
- * @param \Cake\Database\ValueBinder|null $generator Placeholder generator object
- * @return string
+ * @inheritDoc
*/
- public function sql(ValueBinder $generator = null)
+ public function sql(?ValueBinder $generator = null): string
{
$this->triggerBeforeFind();
@@ -1141,9 +1088,9 @@ public function sql(ValueBinder $generator = null)
* This will also setup the correct statement class in order to eager load deep
* associations.
*
- * @return \Cake\ORM\ResultSet
+ * @return \Cake\Datasource\ResultSetInterface
*/
- protected function _execute()
+ protected function _execute(): ResultSetInterface
{
$this->triggerBeforeFind();
if ($this->_results) {
@@ -1169,7 +1116,7 @@ protected function _execute()
* @see \Cake\Database\Query::execute()
* @return void
*/
- protected function _transformQuery()
+ protected function _transformQuery(): void
{
if (!$this->_dirty || $this->_type !== 'select') {
return;
@@ -1192,7 +1139,7 @@ protected function _transformQuery()
*
* @return void
*/
- protected function _addDefaultFields()
+ protected function _addDefaultFields(): void
{
$select = $this->clause('select');
$this->_hasFields = true;
@@ -1215,7 +1162,7 @@ protected function _addDefaultFields()
*
* @return void
*/
- protected function _addDefaultSelectTypes()
+ protected function _addDefaultSelectTypes(): void
{
$typeMap = $this->getTypeMap()->getDefaults();
$select = $this->clause('select');
@@ -1239,13 +1186,17 @@ protected function _addDefaultSelectTypes()
/**
* {@inheritDoc}
*
- * @see \Cake\ORM\Table::find()
+ * @param string $finder The finder method to use.
+ * @param array $options The options for the finder.
+ * @return static Returns a modified query.
+ * @psalm-suppress MoreSpecificReturnType
*/
- public function find($finder, array $options = [])
+ public function find(string $finder, array $options = [])
{
/** @var \Cake\ORM\Table $table */
$table = $this->getRepository();
+ /** @psalm-suppress LessSpecificReturnStatement */
return $table->callFinder($finder, $this, $options);
}
@@ -1255,7 +1206,7 @@ public function find($finder, array $options = [])
*
* @return void
*/
- protected function _dirty()
+ protected function _dirty(): void
{
$this->_results = null;
$this->_resultsCount = null;
@@ -1268,7 +1219,7 @@ protected function _dirty()
* This changes the query type to be 'update'.
* Can be combined with set() and where() methods to create update queries.
*
- * @param string|null $table Unused parameter.
+ * @param string|\Cake\Database\ExpressionInterface|null $table Unused parameter.
* @return $this
*/
public function update($table = null)
@@ -1291,7 +1242,7 @@ public function update($table = null)
* @param string|null $table Unused parameter.
* @return $this
*/
- public function delete($table = null)
+ public function delete(?string $table = null)
{
/** @var \Cake\ORM\Table $repository */
$repository = $this->getRepository();
@@ -1327,23 +1278,26 @@ public function insert(array $columns, array $types = [])
/**
* {@inheritDoc}
*
+ * @param string $method the method to call
+ * @param array $arguments list of arguments for the method to call
+ * @return mixed
* @throws \BadMethodCallException if the method is called for a non-select query
*/
- public function __call($method, $arguments)
+ public function __call(string $method, array $arguments)
{
if ($this->type() === 'select') {
return $this->_call($method, $arguments);
}
- throw new \BadMethodCallException(
+ throw new BadMethodCallException(
sprintf('Cannot call method "%s" on a "%s" query', $method, $this->type())
);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$eagerLoader = $this->getEagerLoader();
@@ -1352,8 +1306,8 @@ public function __debugInfo()
'buffered' => $this->_useBufferedResults,
'formatters' => count($this->_formatters),
'mapReducers' => count($this->_mapReduce),
- 'contain' => $eagerLoader ? $eagerLoader->getContain() : [],
- 'matching' => $eagerLoader ? $eagerLoader->getMatching() : [],
+ 'contain' => $eagerLoader->getContain(),
+ 'matching' => $eagerLoader->getMatching(),
'extraOptions' => $this->_options,
'repository' => $this->_repository,
];
@@ -1366,7 +1320,7 @@ public function __debugInfo()
*
* @return \Cake\Datasource\ResultSetInterface The data to convert to JSON.
*/
- public function jsonSerialize()
+ public function jsonSerialize(): ResultSetInterface
{
return $this->all();
}
@@ -1380,9 +1334,9 @@ public function jsonSerialize()
* @param bool $value Set true to enable, false to disable.
* @return $this
*/
- public function enableAutoFields($value = true)
+ public function enableAutoFields(bool $value = true)
{
- $this->_autoFields = (bool)$value;
+ $this->_autoFields = $value;
return $this;
}
@@ -1407,46 +1361,24 @@ public function disableAutoFields()
*
* @return bool|null The current value. Returns null if neither enabled or disabled yet.
*/
- public function isAutoFieldsEnabled()
+ public function isAutoFieldsEnabled(): ?bool
{
return $this->_autoFields;
}
- /**
- * Get/Set whether or not the ORM should automatically append fields.
- *
- * By default calling select() will disable auto-fields. You can re-enable
- * auto-fields with this method.
- *
- * @deprecated 3.4.0 Use enableAutoFields()/isAutoFieldsEnabled() instead.
- * @param bool|null $value The value to set or null to read the current value.
- * @return bool|null|$this Either the current value or the query object.
- */
- public function autoFields($value = null)
- {
- deprecationWarning(
- 'Query::autoFields() is deprecated. ' .
- 'Use enableAutoFields()/isAutoFieldsEnabled() instead.'
- );
- if ($value === null) {
- return $this->isAutoFieldsEnabled();
- }
-
- return $this->enableAutoFields($value);
- }
-
/**
* Decorates the results iterator with MapReduce routines and formatters
*
* @param \Traversable $result Original results
* @return \Cake\Datasource\ResultSetInterface
*/
- protected function _decorateResults($result)
+ protected function _decorateResults(Traversable $result): ResultSetInterface
{
$result = $this->_applyDecorators($result);
if (!($result instanceof ResultSet) && $this->isBufferedResultsEnabled()) {
$class = $this->_decoratorClass();
+ /** @var \Cake\Datasource\ResultSetInterface $result */
$result = new $class($result->buffered());
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/README.md b/app/vendor/cakephp/cakephp/src/ORM/README.md
index 0e51ff4c0..077b5fd5c 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/README.md
+++ b/app/vendor/cakephp/cakephp/src/ORM/README.md
@@ -27,8 +27,8 @@ specify a driver to use:
use Cake\Datasource\ConnectionManager;
ConnectionManager::setConfig('default', [
- 'className' => 'Cake\Database\Connection',
- 'driver' => 'Cake\Database\Driver\Mysql',
+ 'className' => \Cake\Database\Connection::class,
+ 'driver' => \Cake\Database\Driver\Mysql::class,
'database' => 'test',
'username' => 'root',
'password' => 'secret',
@@ -59,7 +59,7 @@ use Cake\ORM\Locator\LocatorAwareTrait;
$articles = $this->getTableLocator()->get('Articles');
```
-By default, classes using `LocatorAwareTrait` will share a global locator instance.
+By default classes using `LocatorAwareTrait` will share a global locator instance.
You can inject your own locator instance into the object:
```php
@@ -78,12 +78,12 @@ In your table classes you can define the relations between your tables. CakePHP'
supports 4 association types out of the box:
* belongsTo - E.g. Many articles belong to a user.
-* hasOne - E.g. A user has one profile.
-* hasMany - E.g. A user has many articles.
+* hasOne - E.g. A user has one profile
+* hasMany - E.g. A user has many articles
* belongsToMany - E.g. An article belongsToMany tags.
You define associations in your table's `initialize()` method. See the
-[documentation](https://book.cakephp.org/3/en/orm/associations.html) for
+[documentation](https://book.cakephp.org/4/en/orm/associations.html) for
complete examples.
## Reading Data
@@ -99,8 +99,8 @@ foreach ($articles->find() as $article) {
}
```
-You can use the [query builder](https://book.cakephp.org/3/en/orm/query-builder.html) to create
-complex queries, and a [variety of methods](https://book.cakephp.org/3/en/orm/retrieving-data-and-resultsets.html)
+You can use the [query builder](https://book.cakephp.org/4/en/orm/query-builder.html) to create
+complex queries, and a [variety of methods](https://book.cakephp.org/4/en/orm/retrieving-data-and-resultsets.html)
to access your data.
## Saving Data
@@ -134,7 +134,7 @@ $articles->save($article, [
```
The above shows how you can easily marshal and save an entity and its
-associations in a simple & powerful way. Consult the [ORM documentation](https://book.cakephp.org/3/en/orm/saving-data.html)
+associations in a simple & powerful way. Consult the [ORM documentation](https://book.cakephp.org/4/en/orm/saving-data.html)
for more in-depth examples.
## Deleting Data
@@ -149,8 +149,9 @@ $articles->delete($article);
## Meta Data Cache
-It is recommended to enable metadata cache for production systems to avoid performance issues.
+It is recommended to enable meta data cache for production systems to avoid performance issues.
For e.g. file system strategy your bootstrap file could look like this:
+
```php
use Cake\Cache\Engine\FileEngine;
@@ -159,10 +160,12 @@ $cacheConfig = [
'duration' => '+1 year',
'serialize' => true,
'prefix' => 'orm_',
-],
+];
Cache::setConfig('_cake_model_', $cacheConfig);
```
+Cache configs are optional so you must require ``cachephp/cache`` to add one.
+
## Creating Custom Table and Entity Classes
By default, the Cake ORM uses the `\Cake\ORM\Table` and `\Cake\ORM\Entity` classes to
@@ -234,5 +237,5 @@ Configure::write('App.namespace', 'My\Log\SubNamespace');
## Additional Documentation
-Consult [the CakePHP ORM documentation](https://book.cakephp.org/3/en/orm.html)
+Consult [the CakePHP ORM documentation](https://book.cakephp.org/4/en/orm.html)
for more in-depth documentation.
diff --git a/app/vendor/cakephp/cakephp/src/ORM/ResultSet.php b/app/vendor/cakephp/cakephp/src/ORM/ResultSet.php
index 7cdb4e277..b5b0333bb 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/ResultSet.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/ResultSet.php
@@ -1,4 +1,6 @@
getRepository();
$this->_statement = $statement;
$this->_driver = $query->getConnection()->getDriver();
- $this->_defaultTable = $query->getRepository();
+ $this->_defaultTable = $repository;
$this->_calculateAssociationMap($query);
$this->_hydrate = $query->isHydrationEnabled();
$this->_entityClass = $repository->getEntityClass();
@@ -213,7 +197,7 @@ public function current()
*
* @return int
*/
- public function key()
+ public function key(): int
{
return $this->_index;
}
@@ -225,7 +209,7 @@ public function key()
*
* @return void
*/
- public function next()
+ public function next(): void
{
$this->_index++;
}
@@ -238,14 +222,15 @@ public function next()
* @throws \Cake\Database\Exception
* @return void
*/
- public function rewind()
+ public function rewind(): void
{
- if ($this->_index == 0) {
+ if ($this->_index === 0) {
return;
}
if (!$this->_useBuffering) {
- $msg = 'You cannot rewind an un-buffered ResultSet. Use Query::bufferResults() to get a buffered ResultSet.';
+ $msg = 'You cannot rewind an un-buffered ResultSet. '
+ . 'Use Query::bufferResults() to get a buffered ResultSet.';
throw new Exception($msg);
}
@@ -259,7 +244,7 @@ public function rewind()
*
* @return bool
*/
- public function valid()
+ public function valid(): bool
{
if ($this->_useBuffering) {
$valid = $this->_index < $this->_count;
@@ -291,17 +276,19 @@ public function valid()
*
* This method will also close the underlying statement cursor.
*
- * @return array|object
+ * @return array|object|null
*/
public function first()
{
foreach ($this as $result) {
- if ($this->_statement && !$this->_useBuffering) {
+ if ($this->_statement !== null && !$this->_useBuffering) {
$this->_statement->closeCursor();
}
return $result;
}
+
+ return null;
}
/**
@@ -311,10 +298,11 @@ public function first()
*
* @return string Serialized object
*/
- public function serialize()
+ public function serialize(): string
{
if (!$this->_useBuffering) {
- $msg = 'You cannot serialize an un-buffered ResultSet. Use Query::bufferResults() to get a buffered ResultSet.';
+ $msg = 'You cannot serialize an un-buffered ResultSet. '
+ . 'Use Query::bufferResults() to get a buffered ResultSet.';
throw new Exception($msg);
}
@@ -352,12 +340,12 @@ public function unserialize($serialized)
*
* @return int
*/
- public function count()
+ public function count(): int
{
if ($this->_count !== null) {
return $this->_count;
}
- if ($this->_statement) {
+ if ($this->_statement !== null) {
return $this->_count = $this->_statement->rowCount();
}
@@ -377,7 +365,7 @@ public function count()
* @param \Cake\ORM\Query $query The query from where to derive the associations
* @return void
*/
- protected function _calculateAssociationMap($query)
+ protected function _calculateAssociationMap(Query $query): void
{
$map = $query->getEagerLoader()->associationsMap($this->_defaultTable);
$this->_matchingMap = (new Collection($map))
@@ -398,7 +386,7 @@ protected function _calculateAssociationMap($query)
* @param \Cake\ORM\Query $query The query from where to derive the column map
* @return void
*/
- protected function _calculateColumnMap($query)
+ protected function _calculateColumnMap(Query $query): void
{
$map = [];
foreach ($query->clause('select') as $key => $field) {
@@ -424,53 +412,6 @@ protected function _calculateColumnMap($query)
$this->_map = $map;
}
- /**
- * Creates a map of Type converter classes for each of the columns that should
- * be fetched by this object.
- *
- * @deprecated 3.2.0 Not used anymore. Type casting is done at the statement level
- * @return void
- */
- protected function _calculateTypeMap()
- {
- deprecationWarning('ResultSet::_calculateTypeMap() is deprecated, and will be removed in 4.0.0.');
- }
-
- /**
- * Returns the Type classes for each of the passed fields belonging to the
- * table.
- *
- * @param \Cake\ORM\Table $table The table from which to get the schema
- * @param array $fields The fields whitelist to use for fields in the schema.
- * @return array
- * @deprecated 3.2.0 Not used anymore. Type casting is done at the statement level
- */
- protected function _getTypes($table, $fields)
- {
- $types = [];
- $schema = $table->getSchema();
- $map = array_keys((array)Type::getMap() + ['string' => 1, 'text' => 1, 'boolean' => 1]);
- $typeMap = array_combine(
- $map,
- array_map(['Cake\Database\Type', 'build'], $map)
- );
-
- foreach (['string', 'text'] as $t) {
- if (get_class($typeMap[$t]) === 'Cake\Database\Type') {
- unset($typeMap[$t]);
- }
- }
-
- foreach (array_intersect($fields, $schema->columns()) as $col) {
- $typeName = $schema->getColumnType($col);
- if (isset($typeMap[$typeName])) {
- $types[$col] = $typeMap[$typeName];
- }
- }
-
- return $types;
- }
-
/**
* Helper function to fetch the next result from the statement or
* seeded results.
@@ -479,7 +420,7 @@ protected function _getTypes($table, $fields)
*/
protected function _fetchResult()
{
- if (!$this->_statement) {
+ if ($this->_statement === null) {
return false;
}
@@ -495,9 +436,9 @@ protected function _fetchResult()
* Correctly nests results keys including those coming from associations
*
* @param array $row Array containing columns and values or false if there is no results
- * @return array Results
+ * @return array|\Cake\Datasource\EntityInterface Results
*/
- protected function _groupResult($row)
+ protected function _groupResult(array $row)
{
$defaultAlias = $this->_defaultAlias;
$results = $presentAliases = [];
@@ -605,22 +546,6 @@ protected function _groupResult($row)
return $results;
}
- /**
- * Casts all values from a row brought from a table to the correct
- * PHP type.
- *
- * @param string $alias The table object alias
- * @param array $values The values to cast
- * @deprecated 3.2.0 Not used anymore. Type casting is done at the statement level
- * @return array
- */
- protected function _castValues($alias, $values)
- {
- deprecationWarning('ResultSet::_castValues() is deprecated, and will be removed in 4.0.0.');
-
- return $values;
- }
-
/**
* Returns an array that can be used to describe the internal state of this
* object.
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Rule/ExistsIn.php b/app/vendor/cakephp/cakephp/src/ORM/Rule/ExistsIn.php
index 104f9a86a..6494b2a5b 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Rule/ExistsIn.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Rule/ExistsIn.php
@@ -1,4 +1,6 @@
_repository)) {
if (!$options['repository']->hasAssociation($this->_repository)) {
@@ -93,9 +96,13 @@ public function __invoke(EntityInterface $entity, array $options)
$fields = $this->_fields;
$source = $target = $this->_repository;
- $isAssociation = $target instanceof Association;
- $bindingKey = $isAssociation ? (array)$target->getBindingKey() : (array)$target->getPrimaryKey();
- $realTarget = $isAssociation ? $target->getTarget() : $target;
+ if ($target instanceof Association) {
+ $bindingKey = (array)$target->getBindingKey();
+ $realTarget = $target->getTarget();
+ } else {
+ $bindingKey = (array)$target->getPrimaryKey();
+ $realTarget = $target;
+ }
if (!empty($options['_sourceTable']) && $realTarget === $options['_sourceTable']) {
return true;
@@ -126,7 +133,9 @@ public function __invoke(EntityInterface $entity, array $options)
}
$primary = array_map(
- [$target, 'aliasField'],
+ function ($key) use ($target) {
+ return $target->aliasField($key) . ' IS';
+ },
$bindingKey
);
$conditions = array_combine(
@@ -144,7 +153,7 @@ public function __invoke(EntityInterface $entity, array $options)
* @param \Cake\ORM\Table $source The table to use schema from.
* @return bool
*/
- protected function _fieldsAreNull($entity, $source)
+ protected function _fieldsAreNull(EntityInterface $entity, Table $source): bool
{
$nulls = 0;
$schema = $source->getSchema();
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Rule/IsUnique.php b/app/vendor/cakephp/cakephp/src/ORM/Rule/IsUnique.php
index 9d1524b13..76ea4a015 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Rule/IsUnique.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Rule/IsUnique.php
@@ -1,4 +1,6 @@
_fields = $fields;
- $this->_options = $options + ['allowMultipleNulls' => true];
}
/**
@@ -61,18 +55,17 @@ public function __construct(array $fields, array $options = [])
* @param array $options Options passed to the check,
* @return bool
*/
- public function __invoke(EntityInterface $entity, array $options)
+ public function __invoke(EntityInterface $entity, array $options): bool
{
if (!$entity->extract($this->_fields, true)) {
return true;
}
- $allowMultipleNulls = $this->_options['allowMultipleNulls'];
$alias = $options['repository']->getAlias();
- $conditions = $this->_alias($alias, $entity->extract($this->_fields), $allowMultipleNulls);
+ $conditions = $this->_alias($alias, $entity->extract($this->_fields));
if ($entity->isNew() === false) {
$keys = (array)$options['repository']->getPrimaryKey();
- $keys = $this->_alias($alias, $entity->extract($keys), $allowMultipleNulls);
+ $keys = $this->_alias($alias, $entity->extract($keys));
if (array_filter($keys, 'strlen')) {
$conditions['NOT'] = $keys;
}
@@ -84,23 +77,15 @@ public function __invoke(EntityInterface $entity, array $options)
/**
* Add a model alias to all the keys in a set of conditions.
*
- * Null values will be omitted from the generated conditions,
- * as SQL UNIQUE indexes treat `NULL != NULL`
- *
* @param string $alias The alias to add.
* @param array $conditions The conditions to alias.
- * @param bool $multipleNulls Whether or not to allow multiple nulls.
* @return array
*/
- protected function _alias($alias, $conditions, $multipleNulls)
+ protected function _alias(string $alias, array $conditions): array
{
$aliased = [];
foreach ($conditions as $key => $value) {
- if ($multipleNulls) {
- $aliased["$alias.$key"] = $value;
- } else {
- $aliased["$alias.$key IS"] = $value;
- }
+ $aliased["$alias.$key IS"] = $value;
}
return $aliased;
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Rule/LinkConstraint.php b/app/vendor/cakephp/cakephp/src/ORM/Rule/LinkConstraint.php
new file mode 100644
index 000000000..6a25ba239
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/ORM/Rule/LinkConstraint.php
@@ -0,0 +1,196 @@
+_association = $association;
+ $this->_requiredLinkState = $requiredLinkStatus;
+ }
+
+ /**
+ * Callable handler.
+ *
+ * Performs the actual link check.
+ *
+ * @param \Cake\Datasource\EntityInterface $entity The entity involved in the operation.
+ * @param array $options Options passed from the rules checker.
+ * @return bool Whether the check was successful.
+ */
+ public function __invoke(EntityInterface $entity, array $options): bool
+ {
+ $table = $options['repository'] ?? null;
+ if (!($table instanceof Table)) {
+ throw new \InvalidArgumentException(
+ 'Argument 2 is expected to have a `repository` key that holds an instance of `\Cake\ORM\Table`.'
+ );
+ }
+
+ $association = $this->_association;
+ if (!$association instanceof Association) {
+ $association = $table->getAssociation($association);
+ }
+
+ $count = $this->_countLinks($association, $entity);
+
+ if (
+ (
+ $this->_requiredLinkState === static::STATUS_LINKED &&
+ $count < 1
+ ) ||
+ (
+ $this->_requiredLinkState === static::STATUS_NOT_LINKED &&
+ $count !== 0
+ )
+ ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Alias fields.
+ *
+ * @param array $fields The fields that should be aliased.
+ * @param \Cake\ORM\Table $source The object to use for aliasing.
+ * @return array The aliased fields
+ */
+ protected function _aliasFields(array $fields, Table $source): array
+ {
+ foreach ($fields as $key => $value) {
+ $fields[$key] = $source->aliasField($value);
+ }
+
+ return $fields;
+ }
+
+ /**
+ * Build conditions.
+ *
+ * @param array $fields The condition fields.
+ * @param array $values The condition values.
+ * @return array A conditions array combined from the passed fields and values.
+ */
+ protected function _buildConditions(array $fields, array $values): array
+ {
+ if (count($fields) !== count($values)) {
+ throw new \InvalidArgumentException(sprintf(
+ 'The number of fields is expected to match the number of values, got %d field(s) and %d value(s).',
+ count($fields),
+ count($values)
+ ));
+ }
+
+ return array_combine($fields, $values);
+ }
+
+ /**
+ * Count links.
+ *
+ * @param \Cake\ORM\Association $association The association for which to count links.
+ * @param \Cake\Datasource\EntityInterface $entity The entity involved in the operation.
+ * @return int The number of links.
+ */
+ protected function _countLinks(Association $association, EntityInterface $entity): int
+ {
+ $source = $association->getSource();
+
+ $primaryKey = (array)$source->getPrimaryKey();
+ if (!$entity->has($primaryKey)) {
+ throw new \RuntimeException(sprintf(
+ 'LinkConstraint rule on `%s` requires all primary key values for building the counting ' .
+ 'conditions, expected values for `(%s)`, got `(%s)`.',
+ $source->getAlias(),
+ implode(', ', $primaryKey),
+ implode(', ', $entity->extract($primaryKey))
+ ));
+ }
+
+ $aliasedPrimaryKey = $this->_aliasFields($primaryKey, $source);
+ $conditions = $this->_buildConditions(
+ $aliasedPrimaryKey,
+ $entity->extract($primaryKey)
+ );
+
+ return $source
+ ->find()
+ ->matching($association->getName())
+ ->where($conditions)
+ ->count();
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Rule/ValidCount.php b/app/vendor/cakephp/cakephp/src/ORM/Rule/ValidCount.php
index 33696ad7c..f7e23521a 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Rule/ValidCount.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Rule/ValidCount.php
@@ -1,4 +1,6 @@
_field = $field;
}
@@ -47,7 +49,7 @@ public function __construct($field)
* @param array $options Options passed to the check.
* @return bool True if successful, else false.
*/
- public function __invoke(EntityInterface $entity, array $options)
+ public function __invoke(EntityInterface $entity, array $options): bool
{
$value = $entity->{$this->_field};
if (!is_array($value) && !$value instanceof Countable) {
diff --git a/app/vendor/cakephp/cakephp/src/ORM/RulesChecker.php b/app/vendor/cakephp/cakephp/src/ORM/RulesChecker.php
index 1457f6768..bb12b95da 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/RulesChecker.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/RulesChecker.php
@@ -1,4 +1,6 @@
null];
- $message = $options['message'];
- unset($options['message']);
- }
if (!$message) {
if ($this->_useI18n) {
$message = __d('cake', 'This value is already in use');
@@ -61,7 +60,7 @@ public function isUnique(array $fields, $message = null)
$errorField = current($fields);
- return $this->_addError(new IsUnique($fields, $options), '_isUnique', compact('errorField', 'message'));
+ return $this->_addError(new IsUnique($fields), '_isUnique', compact('errorField', 'message'));
}
/**
@@ -84,12 +83,12 @@ public function isUnique(array $fields, $message = null)
*
* @param string|string[] $field The field or list of fields to check for existence by
* primary key lookup in the other table.
- * @param object|string $table The table name where the fields existence will be checked.
+ * @param \Cake\ORM\Table|\Cake\ORM\Association|string $table The table name where the fields existence will be checked.
* @param string|array|null $message The error message to show in case the rule does not pass. Can
* also be an array of options. When an array, the 'message' key can be used to provide a message.
- * @return callable
+ * @return \Cake\Datasource\RuleInvoker
*/
- public function existsIn($field, $table, $message = null)
+ public function existsIn($field, $table, $message = null): RuleInvoker
{
$options = [];
if (is_array($message)) {
@@ -111,6 +110,138 @@ public function existsIn($field, $table, $message = null)
return $this->_addError(new ExistsIn($field, $table, $options), '_existsIn', compact('errorField', 'message'));
}
+ /**
+ * Validates whether links to the given association exist.
+ *
+ * ### Example:
+ *
+ * ```
+ * $rules->addUpdate($rules->isLinkedTo('Articles', 'article'));
+ * ```
+ *
+ * On a `Comments` table that has a `belongsTo Articles` association, this check would ensure that comments
+ * can only be edited as long as they are associated to an existing article.
+ *
+ * @param \Cake\ORM\Association|string $association The association to check for links.
+ * @param string|null $field The name of the association property. When supplied, this is the name used to set
+ * possible errors. When absent, the name is inferred from `$association`.
+ * @param string|null $message The error message to show in case the rule does not pass.
+ * @return \Cake\Datasource\RuleInvoker
+ * @since 4.0.0
+ */
+ public function isLinkedTo($association, ?string $field = null, ?string $message = null): RuleInvoker
+ {
+ return $this->_addLinkConstraintRule(
+ $association,
+ $field,
+ $message,
+ LinkConstraint::STATUS_LINKED,
+ '_isLinkedTo'
+ );
+ }
+
+ /**
+ * Validates whether links to the given association do not exist.
+ *
+ * ### Example:
+ *
+ * ```
+ * $rules->addDelete($rules->isNotLinkedTo('Comments', 'comments'));
+ * ```
+ *
+ * On a `Articles` table that has a `hasMany Comments` association, this check would ensure that articles
+ * can only be deleted when no associated comments exist.
+ *
+ * @param \Cake\ORM\Association|string $association The association to check for links.
+ * @param string|null $field The name of the association property. When supplied, this is the name used to set
+ * possible errors. When absent, the name is inferred from `$association`.
+ * @param string|null $message The error message to show in case the rule does not pass.
+ * @return \Cake\Datasource\RuleInvoker
+ * @since 4.0.0
+ */
+ public function isNotLinkedTo($association, ?string $field = null, ?string $message = null): RuleInvoker
+ {
+ return $this->_addLinkConstraintRule(
+ $association,
+ $field,
+ $message,
+ LinkConstraint::STATUS_NOT_LINKED,
+ '_isNotLinkedTo'
+ );
+ }
+
+ /**
+ * Adds a link constraint rule.
+ *
+ * @param \Cake\ORM\Association|string $association The association to check for links.
+ * @param string|null $errorField The name of the property to use for setting possible errors. When absent,
+ * the name is inferred from `$association`.
+ * @param string|null $message The error message to show in case the rule does not pass.
+ * @param string $linkStatus The ink status required for the check to pass.
+ * @param string $ruleName The alias/name of the rule.
+ * @return \Cake\Datasource\RuleInvoker
+ * @throws \InvalidArgumentException In case the `$association` argument is of an invalid type.
+ * @since 4.0.0
+ * @see \Cake\ORM\RulesChecker::isLinkedTo()
+ * @see \Cake\ORM\RulesChecker::isNotLinkedTo()
+ * @see \Cake\ORM\Rule\LinkConstraint::STATUS_LINKED
+ * @see \Cake\ORM\Rule\LinkConstraint::STATUS_NOT_LINKED
+ */
+ protected function _addLinkConstraintRule(
+ $association,
+ ?string $errorField,
+ ?string $message,
+ string $linkStatus,
+ string $ruleName
+ ): RuleInvoker {
+ if ($association instanceof Association) {
+ $associationAlias = $association->getName();
+
+ if ($errorField === null) {
+ $errorField = $association->getProperty();
+ }
+ } elseif (is_string($association)) {
+ $associationAlias = $association;
+
+ if ($errorField === null) {
+ $repository = $this->_options['repository'] ?? null;
+ if ($repository instanceof Table) {
+ $association = $repository->getAssociation($association);
+ $errorField = $association->getProperty();
+ } else {
+ $errorField = Inflector::underscore($association);
+ }
+ }
+ } else {
+ throw new \InvalidArgumentException(sprintf(
+ 'Argument 1 is expected to be of type `\Cake\ORM\Association|string`, `%s` given.',
+ getTypeName($association)
+ ));
+ }
+
+ if (!$message) {
+ if ($this->_useI18n) {
+ $message = __d(
+ 'cake',
+ 'Cannot modify row: a constraint for the `{0}` association fails.',
+ $associationAlias
+ );
+ } else {
+ $message = sprintf(
+ 'Cannot modify row: a constraint for the `%s` association fails.',
+ $associationAlias
+ );
+ }
+ }
+
+ $rule = new LinkConstraint(
+ $association,
+ $linkStatus
+ );
+
+ return $this->_addError($rule, $ruleName, compact('errorField', 'message'));
+ }
+
/**
* Validates the count of associated records.
*
@@ -118,10 +249,14 @@ public function existsIn($field, $table, $message = null)
* @param int $count The expected count.
* @param string $operator The operator for the count comparison.
* @param string|null $message The error message to show in case the rule does not pass.
- * @return callable
+ * @return \Cake\Datasource\RuleInvoker
*/
- public function validCount($field, $count = 0, $operator = '>', $message = null)
- {
+ public function validCount(
+ string $field,
+ int $count = 0,
+ string $operator = '>',
+ ?string $message = null
+ ): RuleInvoker {
if (!$message) {
if ($this->_useI18n) {
$message = __d('cake', 'The count does not match {0}{1}', [$operator, $count]);
diff --git a/app/vendor/cakephp/cakephp/src/ORM/SaveOptionsBuilder.php b/app/vendor/cakephp/cakephp/src/ORM/SaveOptionsBuilder.php
index 470ed5023..5553e4e48 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/SaveOptionsBuilder.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/SaveOptionsBuilder.php
@@ -1,4 +1,6 @@
$value) {
$this->{$key}($value);
@@ -79,7 +81,7 @@ public function parseArrayOptions($array)
* Set associated options.
*
* @param string|array $associated String or array of associations.
- * @return \Cake\ORM\SaveOptionsBuilder
+ * @return $this
*/
public function associated($associated)
{
@@ -97,7 +99,7 @@ public function associated($associated)
* @param array $associations An associations array.
* @return void
*/
- protected function _associated(Table $table, array $associations)
+ protected function _associated(Table $table, array $associations): void
{
foreach ($associations as $key => $associated) {
if (is_int($key)) {
@@ -120,10 +122,14 @@ protected function _associated(Table $table, array $associations)
* @param string $association Association name.
* @return void
*/
- protected function _checkAssociation(Table $table, $association)
+ protected function _checkAssociation(Table $table, string $association): void
{
if (!$table->associations()->has($association)) {
- throw new RuntimeException(sprintf('Table `%s` is not associated with `%s`', get_class($table), $association));
+ throw new RuntimeException(sprintf(
+ 'Table `%s` is not associated with `%s`',
+ get_class($table),
+ $association
+ ));
}
}
@@ -131,9 +137,9 @@ protected function _checkAssociation(Table $table, $association)
* Set the guard option.
*
* @param bool $guard Guard the properties or not.
- * @return \Cake\ORM\SaveOptionsBuilder
+ * @return $this
*/
- public function guard($guard)
+ public function guard(bool $guard)
{
$this->_options['guard'] = (bool)$guard;
@@ -144,9 +150,9 @@ public function guard($guard)
* Set the validation rule set to use.
*
* @param string $validate Name of the validation rule set to use.
- * @return \Cake\ORM\SaveOptionsBuilder
+ * @return $this
*/
- public function validate($validate)
+ public function validate(string $validate)
{
$this->_table->getValidator($validate);
$this->_options['validate'] = $validate;
@@ -158,9 +164,9 @@ public function validate($validate)
* Set check existing option.
*
* @param bool $checkExisting Guard the properties or not.
- * @return \Cake\ORM\SaveOptionsBuilder
+ * @return $this
*/
- public function checkExisting($checkExisting)
+ public function checkExisting(bool $checkExisting)
{
$this->_options['checkExisting'] = (bool)$checkExisting;
@@ -171,9 +177,9 @@ public function checkExisting($checkExisting)
* Option to check the rules.
*
* @param bool $checkRules Check the rules or not.
- * @return \Cake\ORM\SaveOptionsBuilder
+ * @return $this
*/
- public function checkRules($checkRules)
+ public function checkRules(bool $checkRules)
{
$this->_options['checkRules'] = (bool)$checkRules;
@@ -184,9 +190,9 @@ public function checkRules($checkRules)
* Sets the atomic option.
*
* @param bool $atomic Atomic or not.
- * @return \Cake\ORM\SaveOptionsBuilder
+ * @return $this
*/
- public function atomic($atomic)
+ public function atomic(bool $atomic)
{
$this->_options['atomic'] = (bool)$atomic;
@@ -196,7 +202,7 @@ public function atomic($atomic)
/**
* @return array
*/
- public function toArray()
+ public function toArray(): array
{
return $this->_options;
}
@@ -206,9 +212,9 @@ public function toArray()
*
* @param string $option Option key.
* @param mixed $value Option value.
- * @return \Cake\ORM\SaveOptionsBuilder
+ * @return $this
*/
- public function set($option, $value)
+ public function set(string $option, $value)
{
if (method_exists($this, $option)) {
return $this->{$option}($value);
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Table.php b/app/vendor/cakephp/cakephp/src/ORM/Table.php
index 45fc47a35..890777559 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Table.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Table.php
@@ -1,4 +1,6 @@
*/
protected $_entityClass;
/**
* Registry key used to create this table object
*
- * @var string
+ * @var string|null
*/
protected $_registryAlias;
@@ -241,7 +260,7 @@ class Table implements RepositoryInterface, EventListenerInterface, EventDispatc
* - connection: The connection instance to use
* - entityClass: The fully namespaced class name of the entity class that will
* represent rows in this table.
- * - schema: A \Cake\Database\Schema\TableSchema object or an array that can be
+ * - schema: A \Cake\Database\Schema\TableSchemaInterface object or an array that can be
* passed to it.
* - eventManager: An instance of an event manager to use for internal events
* - behaviors: A BehaviorRegistry. Generally not used outside of tests.
@@ -310,7 +329,7 @@ public function __construct(array $config = [])
* @return string
* @see \Cake\ORM\Locator\TableLocator::get()
*/
- public static function defaultConnectionName()
+ public static function defaultConnectionName(): string
{
return 'default';
}
@@ -333,7 +352,7 @@ public static function defaultConnectionName()
* @param array $config Configuration options passed to the constructor
* @return void
*/
- public function initialize(array $config)
+ public function initialize(array $config): void
{
}
@@ -346,7 +365,7 @@ public function initialize(array $config)
* @param string $table Table name.
* @return $this
*/
- public function setTable($table)
+ public function setTable(string $table)
{
$this->_table = $table;
@@ -360,10 +379,10 @@ public function setTable($table)
*
* @return string
*/
- public function getTable()
+ public function getTable(): string
{
if ($this->_table === null) {
- $table = namespaceSplit(get_class($this));
+ $table = namespaceSplit(static::class);
$table = substr(end($table), 0, -5);
if (!$table) {
$table = $this->getAlias();
@@ -374,33 +393,13 @@ public function getTable()
return $this->_table;
}
- /**
- * Returns the database table name or sets a new one.
- *
- * @deprecated 3.4.0 Use setTable()/getTable() instead.
- * @param string|null $table the new table name
- * @return string
- */
- public function table($table = null)
- {
- deprecationWarning(
- get_called_class() . '::table() is deprecated. ' .
- 'Use setTable()/getTable() instead.'
- );
- if ($table !== null) {
- $this->setTable($table);
- }
-
- return $this->getTable();
- }
-
/**
* Sets the table alias.
*
* @param string $alias Table alias
* @return $this
*/
- public function setAlias($alias)
+ public function setAlias(string $alias)
{
$this->_alias = $alias;
@@ -412,10 +411,10 @@ public function setAlias($alias)
*
* @return string
*/
- public function getAlias()
+ public function getAlias(): string
{
if ($this->_alias === null) {
- $alias = namespaceSplit(get_class($this));
+ $alias = namespaceSplit(static::class);
$alias = substr(end($alias), 0, -5) ?: $this->_table;
$this->_alias = $alias;
}
@@ -423,24 +422,6 @@ public function getAlias()
return $this->_alias;
}
- /**
- * {@inheritDoc}
- *
- * @deprecated 3.4.0 Use setAlias()/getAlias() instead.
- */
- public function alias($alias = null)
- {
- deprecationWarning(
- get_called_class() . '::alias() is deprecated. ' .
- 'Use setAlias()/getAlias() instead.'
- );
- if ($alias !== null) {
- $this->setAlias($alias);
- }
-
- return $this->getAlias();
- }
-
/**
* Alias a field with the table's current alias.
*
@@ -449,7 +430,7 @@ public function alias($alias = null)
* @param string $field The field to alias.
* @return string The field prefixed with the table alias.
*/
- public function aliasField($field)
+ public function aliasField(string $field): string
{
if (strpos($field, '.') !== false) {
return $field;
@@ -464,7 +445,7 @@ public function aliasField($field)
* @param string $registryAlias The key used to access this object.
* @return $this
*/
- public function setRegistryAlias($registryAlias)
+ public function setRegistryAlias(string $registryAlias)
{
$this->_registryAlias = $registryAlias;
@@ -476,7 +457,7 @@ public function setRegistryAlias($registryAlias)
*
* @return string
*/
- public function getRegistryAlias()
+ public function getRegistryAlias(): string
{
if ($this->_registryAlias === null) {
$this->_registryAlias = $this->getAlias();
@@ -485,33 +466,13 @@ public function getRegistryAlias()
return $this->_registryAlias;
}
- /**
- * Returns the table registry key used to create this table instance or sets one.
- *
- * @deprecated 3.4.0 Use setRegistryAlias()/getRegistryAlias() instead.
- * @param string|null $registryAlias the key used to access this object
- * @return string
- */
- public function registryAlias($registryAlias = null)
- {
- deprecationWarning(
- get_called_class() . '::registryAlias() is deprecated. ' .
- 'Use setRegistryAlias()/getRegistryAlias() instead.'
- );
- if ($registryAlias !== null) {
- $this->setRegistryAlias($registryAlias);
- }
-
- return $this->getRegistryAlias();
- }
-
/**
* Sets the connection instance.
*
* @param \Cake\Database\Connection $connection The connection instance
* @return $this
*/
- public function setConnection(ConnectionInterface $connection)
+ public function setConnection(Connection $connection)
{
$this->_connection = $connection;
@@ -523,41 +484,23 @@ public function setConnection(ConnectionInterface $connection)
*
* @return \Cake\Database\Connection
*/
- public function getConnection()
+ public function getConnection(): Connection
{
if (!$this->_connection) {
- $this->_connection = ConnectionManager::get(static::defaultConnectionName());
+ /** @var \Cake\Database\Connection $connection */
+ $connection = ConnectionManager::get(static::defaultConnectionName());
+ $this->_connection = $connection;
}
return $this->_connection;
}
- /**
- * Returns the connection instance or sets a new one
- *
- * @deprecated 3.4.0 Use setConnection()/getConnection() instead.
- * @param \Cake\Datasource\ConnectionInterface|null $connection The new connection instance
- * @return \Cake\Datasource\ConnectionInterface
- */
- public function connection(ConnectionInterface $connection = null)
- {
- deprecationWarning(
- get_called_class() . '::connection() is deprecated. ' .
- 'Use setConnection()/getConnection() instead.'
- );
- if ($connection !== null) {
- $this->setConnection($connection);
- }
-
- return $this->getConnection();
- }
-
/**
* Returns the schema table object describing this table's properties.
*
- * @return \Cake\Database\Schema\TableSchema
+ * @return \Cake\Database\Schema\TableSchemaInterface
*/
- public function getSchema()
+ public function getSchema(): TableSchemaInterface
{
if ($this->_schema === null) {
$this->_schema = $this->_initializeSchema(
@@ -565,6 +508,9 @@ public function getSchema()
->getSchemaCollection()
->describe($this->getTable())
);
+ if (Configure::read('debug')) {
+ $this->checkAliasLengths();
+ }
}
return $this->_schema;
@@ -573,10 +519,10 @@ public function getSchema()
/**
* Sets the schema table object describing this table's properties.
*
- * If an array is passed, a new TableSchema will be constructed
+ * If an array is passed, a new TableSchemaInterface will be constructed
* out of it and used as the schema for this table.
*
- * @param array|\Cake\Database\Schema\TableSchema $schema Schema to be used for this table
+ * @param array|\Cake\Database\Schema\TableSchemaInterface $schema Schema to be used for this table
* @return $this
*/
public function setSchema($schema)
@@ -597,34 +543,46 @@ public function setSchema($schema)
}
$this->_schema = $schema;
+ if (Configure::read('debug')) {
+ $this->checkAliasLengths();
+ }
return $this;
}
/**
- * Returns the schema table object describing this table's properties.
+ * Checks if all table name + column name combinations used for
+ * queries fit into the max length allowed by database driver.
*
- * If a TableSchema is passed, it will be used for this table
- * instead of the default one.
- *
- * If an array is passed, a new TableSchema will be constructed
- * out of it and used as the schema for this table.
- *
- * @deprecated 3.4.0 Use setSchema()/getSchema() instead.
- * @param array|\Cake\Database\Schema\TableSchema|null $schema New schema to be used for this table
- * @return \Cake\Database\Schema\TableSchema
+ * @return void
+ * @throws \RuntimeException When an alias combination is too long
*/
- public function schema($schema = null)
+ protected function checkAliasLengths(): void
{
- deprecationWarning(
- get_called_class() . '::schema() is deprecated. ' .
- 'Use setSchema()/getSchema() instead.'
- );
- if ($schema !== null) {
- $this->setSchema($schema);
+ if ($this->_schema === null) {
+ throw new RuntimeException("Unable to check max alias lengths for `{$this->getAlias()}` without schema.");
+ }
+
+ $maxLength = null;
+ if (method_exists($this->getConnection()->getDriver(), 'getMaxAliasLength')) {
+ $maxLength = $this->getConnection()->getDriver()->getMaxAliasLength();
+ }
+ if ($maxLength === null) {
+ return;
}
- return $this->getSchema();
+ $table = $this->getAlias();
+ foreach ($this->_schema->columns() as $name) {
+ if (strlen($table . '__' . $name) > $maxLength) {
+ $nameLength = $maxLength - 2;
+ throw new RuntimeException(
+ 'ORM queries generate field aliases using the table name/alias and column name. ' .
+ "The table alias `{$table}` and column `{$name}` create an alias longer than ({$nameLength}). " .
+ 'You must change the table schema in the database and shorten either the table or column ' .
+ 'identifier so they fit within the database alias limits.'
+ );
+ }
+ }
}
/**
@@ -637,16 +595,16 @@ public function schema($schema = null)
* ### Example:
*
* ```
- * protected function _initializeSchema(\Cake\Database\Schema\TableSchema $schema) {
+ * protected function _initializeSchema(\Cake\Database\Schema\TableSchemaInterface $schema) {
* $schema->setColumnType('preferences', 'json');
* return $schema;
* }
* ```
*
- * @param \Cake\Database\Schema\TableSchema $schema The table definition fetched from database.
- * @return \Cake\Database\Schema\TableSchema the altered schema
+ * @param \Cake\Database\Schema\TableSchemaInterface $schema The table definition fetched from database.
+ * @return \Cake\Database\Schema\TableSchemaInterface the altered schema
*/
- protected function _initializeSchema(TableSchema $schema)
+ protected function _initializeSchema(TableSchemaInterface $schema): TableSchemaInterface
{
return $schema;
}
@@ -660,7 +618,7 @@ protected function _initializeSchema(TableSchema $schema)
* @param string $field The field to check for.
* @return bool True if the field exists, false if it does not.
*/
- public function hasField($field)
+ public function hasField(string $field): bool
{
$schema = $this->getSchema();
@@ -688,7 +646,7 @@ public function setPrimaryKey($key)
public function getPrimaryKey()
{
if ($this->_primaryKey === null) {
- $key = (array)$this->getSchema()->primaryKey();
+ $key = (array)$this->getSchema()->getPrimaryKey();
if (count($key) === 1) {
$key = $key[0];
}
@@ -698,35 +656,15 @@ public function getPrimaryKey()
return $this->_primaryKey;
}
- /**
- * Returns the primary key field name or sets a new one
- *
- * @deprecated 3.4.0 Use setPrimaryKey()/getPrimaryKey() instead.
- * @param string|string[]|null $key Sets a new name to be used as primary key
- * @return string|string[]
- */
- public function primaryKey($key = null)
- {
- deprecationWarning(
- get_called_class() . '::primaryKey() is deprecated. ' .
- 'Use setPrimaryKey()/getPrimaryKey() instead.'
- );
- if ($key !== null) {
- $this->setPrimaryKey($key);
- }
-
- return $this->getPrimaryKey();
- }
-
/**
* Sets the display field.
*
- * @param string $key Name to be used as display field.
+ * @param string|string[] $field Name to be used as display field.
* @return $this
*/
- public function setDisplayField($key)
+ public function setDisplayField($field)
{
- $this->_displayField = $key;
+ $this->_displayField = $field;
return $this;
}
@@ -734,7 +672,7 @@ public function setDisplayField($key)
/**
* Returns the display field.
*
- * @return string
+ * @return string|string[]|null
*/
public function getDisplayField()
{
@@ -753,41 +691,20 @@ public function getDisplayField()
return $this->_displayField;
}
- /**
- * Returns the display field or sets a new one
- *
- * @deprecated 3.4.0 Use setDisplayField()/getDisplayField() instead.
- * @param string|null $key sets a new name to be used as display field
- * @return string
- */
- public function displayField($key = null)
- {
- deprecationWarning(
- get_called_class() . '::displayField() is deprecated. ' .
- 'Use setDisplayField()/getDisplayField() instead.'
- );
- if ($key !== null) {
- $this->setDisplayField($key);
-
- return $key;
- }
-
- return $this->getDisplayField();
- }
-
/**
* Returns the class used to hydrate rows for this table.
*
* @return string
+ * @psalm-return class-string<\Cake\Datasource\EntityInterface>
*/
- public function getEntityClass()
+ public function getEntityClass(): string
{
if (!$this->_entityClass) {
$default = Entity::class;
- $self = get_called_class();
+ $self = static::class;
$parts = explode('\\', $self);
- if ($self === __CLASS__ || count($parts) < 3) {
+ if ($self === self::class || count($parts) < 3) {
return $this->_entityClass = $default;
}
@@ -797,6 +714,7 @@ public function getEntityClass()
return $this->_entityClass = $default;
}
+ /** @var class-string<\Cake\Datasource\EntityInterface>|null $class */
$class = App::className($name, 'Model/Entity');
if (!$class) {
throw new MissingEntityException([$name]);
@@ -815,10 +733,11 @@ public function getEntityClass()
* @throws \Cake\ORM\Exception\MissingEntityException when the entity class cannot be found
* @return $this
*/
- public function setEntityClass($name)
+ public function setEntityClass(string $name)
{
+ /** @psalm-var class-string<\Cake\Datasource\EntityInterface>|null */
$class = App::className($name, 'Model/Entity');
- if (!$class) {
+ if ($class === null) {
throw new MissingEntityException([$name]);
}
@@ -827,28 +746,6 @@ public function setEntityClass($name)
return $this;
}
- /**
- * Returns the class used to hydrate rows for this table or sets
- * a new one
- *
- * @deprecated 3.4.0 Use setEntityClass()/getEntityClass() instead.
- * @param string|null $name The name of the class to use
- * @throws \Cake\ORM\Exception\MissingEntityException when the entity class cannot be found
- * @return string
- */
- public function entityClass($name = null)
- {
- deprecationWarning(
- get_called_class() . '::entityClass() is deprecated. ' .
- 'Use setEntityClass()/getEntityClass() instead.'
- );
- if ($name !== null) {
- $this->setEntityClass($name);
- }
-
- return $this->getEntityClass();
- }
-
/**
* Add a behavior.
*
@@ -873,7 +770,7 @@ public function entityClass($name = null)
* @throws \RuntimeException If a behavior is being reloaded.
* @see \Cake\ORM\Behavior
*/
- public function addBehavior($name, array $options = [])
+ public function addBehavior(string $name, array $options = [])
{
$this->_behaviors->load($name, $options);
@@ -925,7 +822,7 @@ public function addBehaviors(array $behaviors)
* @return $this
* @see \Cake\ORM\Behavior
*/
- public function removeBehavior($name)
+ public function removeBehavior(string $name)
{
$this->_behaviors->unload($name);
@@ -937,7 +834,7 @@ public function removeBehavior($name)
*
* @return \Cake\ORM\BehaviorRegistry The BehaviorRegistry instance.
*/
- public function behaviors()
+ public function behaviors(): BehaviorRegistry
{
return $this->_behaviors;
}
@@ -949,18 +846,19 @@ public function behaviors()
* @return \Cake\ORM\Behavior
* @throws \InvalidArgumentException If the behavior does not exist.
*/
- public function getBehavior($name)
+ public function getBehavior(string $name): Behavior
{
- /** @var \Cake\ORM\Behavior $behavior */
- $behavior = $this->_behaviors->get($name);
- if ($behavior === null) {
+ if (!$this->_behaviors->has($name)) {
throw new InvalidArgumentException(sprintf(
'The %s behavior is not defined on %s.',
$name,
- get_class($this)
+ static::class
));
}
+ /** @var \Cake\ORM\Behavior $behavior */
+ $behavior = $this->_behaviors->get($name);
+
return $behavior;
}
@@ -970,25 +868,11 @@ public function getBehavior($name)
* @param string $name The behavior alias to check.
* @return bool Whether or not the behavior exists.
*/
- public function hasBehavior($name)
+ public function hasBehavior(string $name): bool
{
return $this->_behaviors->has($name);
}
- /**
- * Returns an association object configured for the specified alias if any.
- *
- * @deprecated 3.6.0 Use getAssociation() and Table::hasAssociation() instead.
- * @param string $name the alias used for the association.
- * @return \Cake\ORM\Association|null Either the association or null.
- */
- public function association($name)
- {
- deprecationWarning('Use Table::getAssociation() and Table::hasAssociation() instead.');
-
- return $this->findAssociation($name);
- }
-
/**
* Returns an association object configured for the specified alias.
*
@@ -1006,7 +890,7 @@ public function association($name)
* @return \Cake\ORM\Association The association.
* @throws \InvalidArgumentException
*/
- public function getAssociation($name)
+ public function getAssociation(string $name): Association
{
$association = $this->findAssociation($name);
if (!$association) {
@@ -1028,7 +912,7 @@ public function getAssociation($name)
* @param string $name The alias used for the association.
* @return bool
*/
- public function hasAssociation($name)
+ public function hasAssociation(string $name): bool
{
return $this->findAssociation($name) !== null;
}
@@ -1045,14 +929,17 @@ public function hasAssociation($name)
* @param string $name The alias used for the association.
* @return \Cake\ORM\Association|null Either the association or null.
*/
- protected function findAssociation($name)
+ protected function findAssociation(string $name): ?Association
{
if (strpos($name, '.') === false) {
return $this->_associations->get($name);
}
- list($name, $next) = array_pad(explode('.', $name, 2), 2, null);
- $result = $this->_associations->get($name);
+ $result = null;
+ [$name, $next] = array_pad(explode('.', $name, 2), 2, null);
+ if ($name !== null) {
+ $result = $this->_associations->get($name);
+ }
if ($result !== null && $next !== null) {
$result = $result->getTarget()->getAssociation($next);
@@ -1064,9 +951,9 @@ protected function findAssociation($name)
/**
* Get the associations collection for this table.
*
- * @return \Cake\ORM\AssociationCollection|\Cake\ORM\Association[] The collection of association objects.
+ * @return \Cake\ORM\AssociationCollection The collection of association objects.
*/
- public function associations()
+ public function associations(): AssociationCollection
{
return $this->_associations;
}
@@ -1135,12 +1022,6 @@ public function addAssociations(array $params)
* - finder: The finder method to use when loading records from this association.
* Defaults to 'all'. When the strategy is 'join', only the fields, containments,
* and where conditions will be used from the finder.
- * - propertyName: The property name that should be filled with data from the
- * associated table into the source table results. By default this is the underscored
- * & singular name of the association. For an association of ProductCategories it would
- * be product_category.
- * - bindingKey: The name of the column in the other table used to match 'foreignKey'.
- * The default value is the primary key of the other table.
*
* This method will return the association object that was built.
*
@@ -1149,7 +1030,7 @@ public function addAssociations(array $params)
* @param array $options list of options to configure the association definition
* @return \Cake\ORM\Association\BelongsTo
*/
- public function belongsTo($associated, array $options = [])
+ public function belongsTo(string $associated, array $options = []): BelongsTo
{
$options += ['sourceTable' => $this];
@@ -1187,12 +1068,6 @@ public function belongsTo($associated, array $options = [])
* - finder: The finder method to use when loading records from this association.
* Defaults to 'all'. When the strategy is 'join', only the fields, containments,
* and where conditions will be used from the finder.
- * - propertyName: The property name that should be filled with data from the
- * associated table into the source table results. By default this is the underscored
- * & singular name of the association. For an association of ProductCategories it would
- * be product_category.
- * - bindingKey: The name of the column in the other table used to match 'foreignKey'.
- * The default value is the primary key of the other table.
*
* This method will return the association object that was built.
*
@@ -1201,7 +1076,7 @@ public function belongsTo($associated, array $options = [])
* @param array $options list of options to configure the association definition
* @return \Cake\ORM\Association\HasOne
*/
- public function hasOne($associated, array $options = [])
+ public function hasOne(string $associated, array $options = []): HasOne
{
$options += ['sourceTable' => $this];
@@ -1245,12 +1120,6 @@ public function hasOne($associated, array $options = [])
* target table.
* - finder: The finder method to use when loading records from this association.
* Defaults to 'all'.
- * - propertyName: The property name that should be filled with data from the
- * associated table into the source table results. By default this is the underscored
- * & singular name of the association. For an association of ProductCategories it would
- * be product_category.
- * - bindingKey: The name of the column in the other table used to match 'foreignKey'.
- * The default value is the primary key of the other table.
*
* This method will return the association object that was built.
*
@@ -1259,7 +1128,7 @@ public function hasOne($associated, array $options = [])
* @param array $options list of options to configure the association definition
* @return \Cake\ORM\Association\HasMany
*/
- public function hasMany($associated, array $options = [])
+ public function hasMany(string $associated, array $options = []): HasMany
{
$options += ['sourceTable' => $this];
@@ -1305,12 +1174,6 @@ public function hasMany($associated, array $options = [])
* - strategy: The loading strategy to use. 'select' and 'subquery' are supported.
* - finder: The finder method to use when loading records from this association.
* Defaults to 'all'.
- * - propertyName: The property name that should be filled with data from the
- * associated table into the source table results. By default this is the underscored
- * & singular name of the association. For an association of ProductCategories it would
- * be product_category.
- * - bindingKey: The name of the column in the other table used to match 'foreignKey'.
- * The default value is the primary key of the other table.
*
* This method will return the association object that was built.
*
@@ -1319,7 +1182,7 @@ public function hasMany($associated, array $options = [])
* @param array $options list of options to configure the association definition
* @return \Cake\ORM\Association\BelongsToMany
*/
- public function belongsToMany($associated, array $options = [])
+ public function belongsToMany(string $associated, array $options = []): BelongsToMany
{
$options += ['sourceTable' => $this];
@@ -1384,10 +1247,10 @@ public function belongsToMany($associated, array $options = [])
* Would invoke the `findPublished` method.
*
* @param string $type the type of query to perform
- * @param array|\ArrayAccess $options An array that will be passed to Query::applyOptions()
+ * @param array $options An array that will be passed to Query::applyOptions()
* @return \Cake\ORM\Query The query builder
*/
- public function find($type = 'all', $options = [])
+ public function find(string $type = 'all', array $options = []): Query
{
$query = $this->query();
$query->select();
@@ -1405,7 +1268,7 @@ public function find($type = 'all', $options = [])
* @param array $options The options to use for the find
* @return \Cake\ORM\Query The query builder
*/
- public function findAll(Query $query, array $options)
+ public function findAll(Query $query, array $options): Query
{
return $query;
}
@@ -1467,7 +1330,7 @@ public function findAll(Query $query, array $options)
* @param array $options The options for the find
* @return \Cake\ORM\Query The query builder
*/
- public function findList(Query $query, array $options)
+ public function findList(Query $query, array $options): Query
{
$options += [
'keyField' => $this->getPrimaryKey(),
@@ -1475,12 +1338,6 @@ public function findList(Query $query, array $options)
'groupField' => null,
];
- if (isset($options['idField'])) {
- $options['keyField'] = $options['idField'];
- unset($options['idField']);
- deprecationWarning('Option "idField" is deprecated, use "keyField" instead.');
- }
-
if (
!$query->clause('select') &&
!is_object($options['keyField']) &&
@@ -1537,7 +1394,7 @@ public function findList(Query $query, array $options)
* @param array $options The options to find with
* @return \Cake\ORM\Query The query builder
*/
- public function findThreaded(Query $query, array $options)
+ public function findThreaded(Query $query, array $options): Query
{
$options += [
'keyField' => $this->getPrimaryKey(),
@@ -1545,12 +1402,6 @@ public function findThreaded(Query $query, array $options)
'nestingKey' => 'children',
];
- if (isset($options['idField'])) {
- $options['keyField'] = $options['idField'];
- unset($options['idField']);
- deprecationWarning('Option "idField" is deprecated, use "keyField" instead.');
- }
-
$options = $this->_setFieldMatchers($options, ['keyField', 'parentField']);
return $query->formatResults(function ($results) use ($options) {
@@ -1568,11 +1419,11 @@ public function findThreaded(Query $query, array $options)
* composite keys when comparing values.
*
* @param array $options the original options passed to a finder
- * @param array $keys the keys to check in $options to build matchers from
+ * @param string[] $keys the keys to check in $options to build matchers from
* the associated value
* @return array
*/
- protected function _setFieldMatchers($options, $keys)
+ protected function _setFieldMatchers(array $options, array $keys): array
{
foreach ($keys as $field) {
if (!is_array($options[$field])) {
@@ -1609,10 +1460,17 @@ protected function _setFieldMatchers($options, $keys)
* $article = $articles->get(1, ['contain' => ['Users', 'Comments']]);
* ```
*
- * @throws \Cake\Datasource\Exception\InvalidPrimaryKeyException When the given `$primaryKey`
- * was not found in the table.
+ * @param mixed $primaryKey primary key value to find
+ * @param array $options options accepted by `Table::find()`
+ * @return \Cake\Datasource\EntityInterface
+ * @throws \Cake\Datasource\Exception\RecordNotFoundException if the record with such id
+ * could not be found
+ * @throws \Cake\Datasource\Exception\InvalidPrimaryKeyException When $primaryKey has an
+ * incorrect number of elements.
+ * @see \Cake\Datasource\RepositoryInterface::find()
+ * @psalm-suppress InvalidReturnType
*/
- public function get($primaryKey, $options = [])
+ public function get($primaryKey, array $options = []): EntityInterface
{
$key = (array)$this->getPrimaryKey();
$alias = $this->getAlias();
@@ -1634,9 +1492,9 @@ public function get($primaryKey, $options = [])
}
$conditions = array_combine($key, $primaryKey);
- $cacheConfig = isset($options['cache']) ? $options['cache'] : false;
- $cacheKey = isset($options['key']) ? $options['key'] : false;
- $finder = isset($options['finder']) ? $options['finder'] : 'all';
+ $cacheConfig = $options['cache'] ?? false;
+ $cacheKey = $options['key'] ?? false;
+ $finder = $options['finder'] ?? 'all';
unset($options['key'], $options['cache'], $options['finder']);
$query = $this->find($finder, $options)->where($conditions);
@@ -1653,6 +1511,7 @@ public function get($primaryKey, $options = [])
$query->cache($cacheKey, $cacheConfig);
}
+ /** @psalm-suppress InvalidReturnStatement */
return $query->firstOrFail();
}
@@ -1663,7 +1522,7 @@ public function get($primaryKey, $options = [])
* @param bool $atomic Whether to execute the worker inside a database transaction.
* @return mixed
*/
- protected function _executeTransaction(callable $worker, $atomic = true)
+ protected function _executeTransaction(callable $worker, bool $atomic = true)
{
if ($atomic) {
return $this->getConnection()->transactional(function () use ($worker) {
@@ -1681,9 +1540,9 @@ protected function _executeTransaction(callable $worker, $atomic = true)
* @param bool $primary True if a primary was used.
* @return bool Returns true if a transaction was committed.
*/
- protected function _transactionCommitted($atomic, $primary)
+ protected function _transactionCommitted(bool $atomic, bool $primary): bool
{
- return !$this->getConnection()->inTransaction() && ($atomic || (!$atomic && $primary));
+ return !$this->getConnection()->inTransaction() && ($atomic || $primary);
}
/**
@@ -1720,7 +1579,7 @@ protected function _transactionCommitted($atomic, $primary)
* @return \Cake\Datasource\EntityInterface An entity.
* @throws \Cake\ORM\Exception\PersistenceFailedException When the entity couldn't be saved
*/
- public function findOrCreate($search, callable $callback = null, $options = [])
+ public function findOrCreate($search, ?callable $callback = null, $options = []): EntityInterface
{
$options = new ArrayObject($options + [
'atomic' => true,
@@ -1747,18 +1606,20 @@ public function findOrCreate($search, callable $callback = null, $options = [])
* created entities. This callback will be called *before* the entity
* is persisted.
* @param array $options The options to use when saving.
- * @return \Cake\Datasource\EntityInterface An entity.
+ * @return \Cake\Datasource\EntityInterface|array An entity.
* @throws \Cake\ORM\Exception\PersistenceFailedException When the entity couldn't be saved
+ * @throws \InvalidArgumentException
*/
- protected function _processFindOrCreate($search, callable $callback = null, $options = [])
+ protected function _processFindOrCreate($search, ?callable $callback = null, $options = [])
{
$query = $this->_getFindOrCreateQuery($search);
+
$row = $query->first();
if ($row !== null) {
return $row;
}
- $entity = $this->newEntity();
+ $entity = $this->newEmptyEntity();
if ($options['defaults'] && is_array($search)) {
$accessibleFields = array_combine(array_keys($search), array_fill(0, count($search), true));
$entity = $this->patchEntity($entity, $search, ['accessibleFields' => $accessibleFields]);
@@ -1783,7 +1644,7 @@ protected function _processFindOrCreate($search, callable $callback = null, $opt
* @param array|callable|\Cake\ORM\Query $search The criteria to find existing records by.
* @return \Cake\ORM\Query
*/
- protected function _getFindOrCreateQuery($search)
+ protected function _getFindOrCreateQuery($search): Query
{
if (is_callable($search)) {
$query = $this->find();
@@ -1793,7 +1654,10 @@ protected function _getFindOrCreateQuery($search)
} elseif ($search instanceof Query) {
$query = $search;
} else {
- throw new InvalidArgumentException('Search criteria must be an array, callable or Query');
+ throw new InvalidArgumentException(sprintf(
+ 'Search criteria must be an array, callable or Query. Got "%s"',
+ getTypeName($search)
+ ));
}
return $query;
@@ -1804,15 +1668,15 @@ protected function _getFindOrCreateQuery($search)
*
* @return \Cake\ORM\Query
*/
- public function query()
+ public function query(): Query
{
return new Query($this->getConnection(), $this);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function updateAll($fields, $conditions)
+ public function updateAll($fields, $conditions): int
{
$query = $this->query();
$query->update()
@@ -1825,9 +1689,9 @@ public function updateAll($fields, $conditions)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function deleteAll($conditions)
+ public function deleteAll($conditions): int
{
$query = $this->query()
->delete()
@@ -1839,9 +1703,9 @@ public function deleteAll($conditions)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function exists($conditions)
+ public function exists($conditions): bool
{
return (bool)count(
$this->find('all')
@@ -1934,8 +1798,8 @@ public function exists($conditions)
* $articles->save($entity, ['associated' => false]);
* ```
*
- * @param \Cake\Datasource\EntityInterface $entity
- * @param \Cake\ORM\SaveOptionsBuilder|array $options
+ * @param \Cake\Datasource\EntityInterface $entity the entity to be saved
+ * @param array|\ArrayAccess|\Cake\ORM\SaveOptionsBuilder $options The options to use when saving.
* @return \Cake\Datasource\EntityInterface|false
* @throws \Cake\ORM\Exception\RolledbackTransactionException If the transaction is aborted in the afterSave event.
*/
@@ -1953,7 +1817,7 @@ public function save(EntityInterface $entity, $options = [])
'_primary' => true,
]);
- if ($entity->hasErrors($options['associated'])) {
+ if ($entity->hasErrors((bool)$options['associated'])) {
return false;
}
@@ -1989,7 +1853,7 @@ public function save(EntityInterface $entity, $options = [])
* @throws \Cake\ORM\Exception\PersistenceFailedException When the entity couldn't be saved
* @see \Cake\ORM\Table::save()
*/
- public function saveOrFail(EntityInterface $entity, $options = [])
+ public function saveOrFail(EntityInterface $entity, $options = []): EntityInterface
{
$saved = $this->save($entity, $options);
if ($saved === false) {
@@ -2009,7 +1873,7 @@ public function saveOrFail(EntityInterface $entity, $options = [])
* @throws \Cake\ORM\Exception\RolledbackTransactionException If the transaction
* is aborted in the afterSave event.
*/
- protected function _processSave($entity, $options)
+ protected function _processSave(EntityInterface $entity, ArrayObject $options)
{
$primaryColumns = (array)$this->getPrimaryKey();
@@ -2031,7 +1895,19 @@ protected function _processSave($entity, $options)
$event = $this->dispatchEvent('Model.beforeSave', compact('entity', 'options'));
if ($event->isStopped()) {
- return $event->getResult();
+ $result = $event->getResult();
+ if ($result === null) {
+ return false;
+ }
+
+ if ($result !== false && !($result instanceof EntityInterface)) {
+ throw new RuntimeException(sprintf(
+ 'The beforeSave callback must return `false` or `EntityInterface` instance. Got `%s` instead.',
+ getTypeName($result)
+ ));
+ }
+
+ return $result;
}
$saved = $this->_associations->saveParents(
@@ -2059,7 +1935,7 @@ protected function _processSave($entity, $options)
}
if (!$success && $isNew) {
- $entity->unsetProperty($this->getPrimaryKey());
+ $entity->unset($this->getPrimaryKey());
$entity->setNew(true);
}
@@ -2076,7 +1952,7 @@ protected function _processSave($entity, $options)
* @throws \Cake\ORM\Exception\RolledbackTransactionException If the transaction
* is aborted in the afterSave event.
*/
- protected function _onSaveSuccess($entity, $options)
+ protected function _onSaveSuccess(EntityInterface $entity, ArrayObject $options): bool
{
$success = $this->_associations->saveChildren(
$this,
@@ -2092,7 +1968,7 @@ protected function _onSaveSuccess($entity, $options)
$this->dispatchEvent('Model.afterSave', compact('entity', 'options'));
if ($options['atomic'] && !$this->getConnection()->inTransaction()) {
- throw new RolledbackTransactionException(['table' => get_class($this)]);
+ throw new RolledbackTransactionException(['table' => static::class]);
}
if (!$options['atomic'] && !$options['_primary']) {
@@ -2113,7 +1989,7 @@ protected function _onSaveSuccess($entity, $options)
* @throws \RuntimeException if not all the primary keys where supplied or could
* be generated when the table has composite primary keys. Or when the table has no primary key.
*/
- protected function _insert($entity, $data)
+ protected function _insert(EntityInterface $entity, array $data)
{
$primary = (array)$this->getPrimaryKey();
if (empty($primary)) {
@@ -2127,7 +2003,7 @@ protected function _insert($entity, $data)
$id = (array)$this->_newId($primary) + $keys;
// Generate primary keys preferring values in $data.
- $primary = array_combine($primary, $id);
+ $primary = array_combine($primary, $id) ?: [];
$primary = array_intersect_key($data, $primary) + $primary;
$filteredKeys = array_filter($primary, function ($v) {
@@ -2167,8 +2043,9 @@ protected function _insert($entity, $data)
foreach ($primary as $key => $v) {
if (!isset($data[$key])) {
$id = $statement->lastInsertId($this->getTable(), $key);
+ /** @var string $type */
$type = $schema->getColumnType($key);
- $entity->set($key, Type::build($type)->toPHP($id, $driver));
+ $entity->set($key, TypeFactory::build($type)->toPHP($id, $driver));
break;
}
}
@@ -2191,13 +2068,14 @@ protected function _insert($entity, $data)
* @param string[] $primary The primary key columns to get a new ID for.
* @return string|null Either null or the primary key value or a list of primary key values.
*/
- protected function _newId($primary)
+ protected function _newId(array $primary)
{
if (!$primary || count((array)$primary) > 1) {
return null;
}
+ /** @var string $typeName */
$typeName = $this->getSchema()->getColumnType($primary[0]);
- $type = Type::build($typeName);
+ $type = TypeFactory::build($typeName);
return $type->newId();
}
@@ -2210,7 +2088,7 @@ protected function _newId($primary)
* @return \Cake\Datasource\EntityInterface|false
* @throws \InvalidArgumentException When primary key data is missing.
*/
- protected function _update($entity, $data)
+ protected function _update(EntityInterface $entity, array $data)
{
$primaryColumns = (array)$this->getPrimaryKey();
$primaryKey = $entity->extract($primaryColumns);
@@ -2256,11 +2134,11 @@ protected function _update($entity, $data)
* error.
*
* @param \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface $entities Entities to save.
- * @param array|\ArrayAccess $options Options used when calling Table::save() for each entity.
- * @return bool|\Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface False on failure, entities list on success.
+ * @param array|\ArrayAccess|\Cake\ORM\SaveOptionsBuilder $options Options used when calling Table::save() for each entity.
+ * @return \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface|false False on failure, entities list on success.
* @throws \Exception
*/
- public function saveMany($entities, $options = [])
+ public function saveMany(iterable $entities, $options = [])
{
try {
return $this->_saveMany($entities, $options);
@@ -2282,26 +2160,27 @@ public function saveMany($entities, $options = [])
* @throws \Exception
* @throws \Cake\ORM\Exception\PersistenceFailedException If an entity couldn't be saved.
*/
- public function saveManyOrFail($entities, $options = [])
+ public function saveManyOrFail(iterable $entities, $options = []): iterable
{
return $this->_saveMany($entities, $options);
}
/**
* @param \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface $entities Entities to save.
- * @param array|\ArrayAccess $options Options used when calling Table::save() for each entity.
- * @return \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface Entities list.
+ * @param array|\ArrayAccess|\Cake\ORM\SaveOptionsBuilder $options Options used when calling Table::save() for each entity.
* @throws \Cake\ORM\Exception\PersistenceFailedException If an entity couldn't be saved.
+ * @throws \Exception If an entity couldn't be saved.
+ * @return \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface Entities list.
*/
- protected function _saveMany($entities, $options = [])
+ protected function _saveMany(iterable $entities, $options = []): iterable
{
/** @var bool[] $isNew */
$isNew = [];
- $cleanup = function ($entities) use (&$isNew) {
+ $cleanup = function ($entities) use (&$isNew): void {
/** @var \Cake\Datasource\EntityInterface[] $entities */
foreach ($entities as $key => $entity) {
if (isset($isNew[$key]) && $isNew[$key]) {
- $entity->unsetProperty($this->getPrimaryKey());
+ $entity->unset($this->getPrimaryKey());
$entity->setNew(true);
}
}
@@ -2361,8 +2240,12 @@ protected function _saveMany($entities, $options = [])
* The options argument will be converted into an \ArrayObject instance
* for the duration of the callbacks, this allows listeners to modify
* the options used in the delete operation.
+ *
+ * @param \Cake\Datasource\EntityInterface $entity The entity to remove.
+ * @param array|\ArrayAccess $options The options for the delete.
+ * @return bool success
*/
- public function delete(EntityInterface $entity, $options = [])
+ public function delete(EntityInterface $entity, $options = []): bool
{
$options = new ArrayObject((array)$options + [
'atomic' => true,
@@ -2384,26 +2267,6 @@ public function delete(EntityInterface $entity, $options = [])
return $success;
}
- /**
- * Try to delete an entity or throw a PersistenceFailedException if the entity is new,
- * has no primary key value, application rules checks failed or the delete was aborted by a callback.
- *
- * @param \Cake\Datasource\EntityInterface $entity The entity to remove.
- * @param array|\ArrayAccess $options The options for the delete.
- * @return bool success
- * @throws \Cake\ORM\Exception\PersistenceFailedException
- * @see \Cake\ORM\Table::delete()
- */
- public function deleteOrFail(EntityInterface $entity, $options = [])
- {
- $deleted = $this->delete($entity, $options);
- if ($deleted === false) {
- throw new PersistenceFailedException($entity, ['delete']);
- }
-
- return $deleted;
- }
-
/**
* Deletes multiple entities of a table.
*
@@ -2413,12 +2276,11 @@ public function deleteOrFail(EntityInterface $entity, $options = [])
*
* @param \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface $entities Entities to delete.
* @param array|\ArrayAccess $options Options used when calling Table::save() for each entity.
- * @return bool|\Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface
- * False on failure, entities list on success.
- * @throws \Exception
+ * @return \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface|false Entities list
+ * on success, false on failure.
* @see \Cake\ORM\Table::delete() for options and events related to this method.
*/
- public function deleteMany($entities, $options = [])
+ public function deleteMany(iterable $entities, $options = [])
{
$failed = $this->_deleteMany($entities, $options);
@@ -2439,11 +2301,10 @@ public function deleteMany($entities, $options = [])
* @param \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface $entities Entities to delete.
* @param array|\ArrayAccess $options Options used when calling Table::save() for each entity.
* @return \Cake\Datasource\EntityInterface[]|\Cake\Datasource\ResultSetInterface Entities list.
- * @throws \Exception
* @throws \Cake\ORM\Exception\PersistenceFailedException
* @see \Cake\ORM\Table::delete() for options and events related to this method.
*/
- public function deleteManyOrFail($entities, $options = [])
+ public function deleteManyOrFail(iterable $entities, $options = []): iterable
{
$failed = $this->_deleteMany($entities, $options);
@@ -2459,7 +2320,7 @@ public function deleteManyOrFail($entities, $options = [])
* @param array|\ArrayAccess $options Options used.
* @return \Cake\Datasource\EntityInterface|null
*/
- protected function _deleteMany($entities, $options = [])
+ protected function _deleteMany(iterable $entities, $options = []): ?EntityInterface
{
$options = new ArrayObject((array)$options + [
'atomic' => true,
@@ -2489,6 +2350,26 @@ protected function _deleteMany($entities, $options = [])
return $failed;
}
+ /**
+ * Try to delete an entity or throw a PersistenceFailedException if the entity is new,
+ * has no primary key value, application rules checks failed or the delete was aborted by a callback.
+ *
+ * @param \Cake\Datasource\EntityInterface $entity The entity to remove.
+ * @param array|\ArrayAccess $options The options for the delete.
+ * @return true
+ * @throws \Cake\ORM\Exception\PersistenceFailedException
+ * @see \Cake\ORM\Table::delete()
+ */
+ public function deleteOrFail(EntityInterface $entity, $options = []): bool
+ {
+ $deleted = $this->delete($entity, $options);
+ if ($deleted === false) {
+ throw new PersistenceFailedException($entity, ['delete']);
+ }
+
+ return $deleted;
+ }
+
/**
* Perform the delete operation.
*
@@ -2501,7 +2382,7 @@ protected function _deleteMany($entities, $options = [])
* passed entity
* @return bool success
*/
- protected function _processDelete($entity, $options)
+ protected function _processDelete(EntityInterface $entity, ArrayObject $options): bool
{
if ($entity->isNew()) {
return false;
@@ -2523,7 +2404,7 @@ protected function _processDelete($entity, $options)
]);
if ($event->isStopped()) {
- return $event->getResult();
+ return (bool)$event->getResult();
}
$this->_associations->cascadeDelete(
@@ -2556,11 +2437,11 @@ protected function _processDelete($entity, $options)
* @param string $type name of finder to check
* @return bool
*/
- public function hasFinder($type)
+ public function hasFinder(string $type): bool
{
$finder = 'find' . $type;
- return method_exists($this, $finder) || ($this->_behaviors && $this->_behaviors->hasFinder($type));
+ return method_exists($this, $finder) || $this->_behaviors->hasFinder($type);
}
/**
@@ -2573,7 +2454,7 @@ public function hasFinder($type)
* @return \Cake\ORM\Query
* @throws \BadMethodCallException
*/
- public function callFinder($type, Query $query, array $options = [])
+ public function callFinder(string $type, Query $query, array $options = []): Query
{
$query->applyOptions($options);
$options = $query->getOptions();
@@ -2582,25 +2463,27 @@ public function callFinder($type, Query $query, array $options = [])
return $this->{$finder}($query, $options);
}
- if ($this->_behaviors && $this->_behaviors->hasFinder($type)) {
+ if ($this->_behaviors->hasFinder($type)) {
return $this->_behaviors->callFinder($type, [$query, $options]);
}
- throw new BadMethodCallException(
- sprintf('Unknown finder method "%s"', $type)
- );
+ throw new BadMethodCallException(sprintf(
+ 'Unknown finder method "%s" on %s.',
+ $type,
+ static::class
+ ));
}
/**
- * Provides the dynamic findBy and findAllBy methods.
+ * Provides the dynamic findBy and findByAll methods.
*
* @param string $method The method name that was fired.
* @param array $args List of arguments passed to the function.
- * @return mixed
+ * @return \Cake\ORM\Query
* @throws \BadMethodCallException when there are missing arguments, or when
* and & or are combined.
*/
- protected function _dynamicFinder($method, $args)
+ protected function _dynamicFinder(string $method, array $args)
{
$method = Inflector::underscore($method);
preg_match('/^find_([\w]+)_by_/', $method, $matches);
@@ -2643,9 +2526,9 @@ protected function _dynamicFinder($method, $args)
} elseif ($hasOr !== false) {
$fields = explode('_or_', $fields);
$conditions = [
- 'OR' => $makeConditions($fields, $args),
+ 'OR' => $makeConditions($fields, $args),
];
- } elseif ($hasAnd !== false) {
+ } else {
$fields = explode('_and_', $fields);
$conditions = $makeConditions($fields, $args);
}
@@ -2668,7 +2551,7 @@ protected function _dynamicFinder($method, $args)
*/
public function __call($method, $args)
{
- if ($this->_behaviors && $this->_behaviors->hasMethod($method)) {
+ if ($this->_behaviors->hasMethod($method)) {
return $this->_behaviors->call($method, $args);
}
if (preg_match('/^find(?:\w+)?By/', $method) > 0) {
@@ -2676,7 +2559,7 @@ public function __call($method, $args)
}
throw new BadMethodCallException(
- sprintf('Unknown method "%s"', $method)
+ sprintf('Unknown method "%s" called on %s', $method, static::class)
);
}
@@ -2725,11 +2608,23 @@ public function __isset($property)
* @return \Cake\ORM\Marshaller
* @see \Cake\ORM\Marshaller
*/
- public function marshaller()
+ public function marshaller(): Marshaller
{
return new Marshaller($this);
}
+ /**
+ * {@inheritDoc}
+ *
+ * @return \Cake\Datasource\EntityInterface
+ */
+ public function newEmptyEntity(): EntityInterface
+ {
+ $class = $this->getEntityClass();
+
+ return new $class([], ['source' => $this->getRegistryAlias()]);
+ }
+
/**
* {@inheritDoc}
*
@@ -2783,14 +2678,13 @@ public function marshaller()
*
* You can use the `Model.beforeMarshal` event to modify request data
* before it is converted into entities.
+ *
+ * @param array $data The data to build an entity with.
+ * @param array $options A list of options for the object hydration.
+ * @return \Cake\Datasource\EntityInterface
*/
- public function newEntity($data = null, array $options = [])
+ public function newEntity(array $data, array $options = []): EntityInterface
{
- if ($data === null) {
- $class = $this->getEntityClass();
-
- return new $class([], ['source' => $this->getRegistryAlias()]);
- }
if (!isset($options['associated'])) {
$options['associated'] = $this->_associations->keys();
}
@@ -2826,8 +2720,12 @@ public function newEntity($data = null, array $options = [])
*
* You can use the `Model.beforeMarshal` event to modify request data
* before it is converted into entities.
+ *
+ * @param array $data The data to build an entity with.
+ * @param array $options A list of options for the objects hydration.
+ * @return \Cake\Datasource\EntityInterface[] An array of hydrated records.
*/
- public function newEntities(array $data, array $options = [])
+ public function newEntities(array $data, array $options = []): array
{
if (!isset($options['associated'])) {
$options['associated'] = $this->_associations->keys();
@@ -2855,6 +2753,14 @@ public function newEntities(array $data, array $options = [])
* );
* ```
*
+ * ```
+ * $article = $this->Articles->patchEntity($article, $this->request->getData(), [
+ * 'associated' => [
+ * 'Tags' => ['accessibleFields' => ['*' => true]]
+ * ]
+ * ]);
+ * ```
+ *
* By default, the data is validated before being passed to the entity. In
* the case of invalid fields, those will not be assigned to the entity.
* The `validate` option can be used to disable validation on the passed data:
@@ -2872,8 +2778,14 @@ public function newEntities(array $data, array $options = [])
* presently has an identical value, the setter will not be called, and the
* property will not be marked as dirty. This is an optimization to prevent unnecessary field
* updates when persisting entities.
+ *
+ * @param \Cake\Datasource\EntityInterface $entity the entity that will get the
+ * data merged in
+ * @param array $data key value list of fields to be merged into the entity
+ * @param array $options A list of options for the object hydration.
+ * @return \Cake\Datasource\EntityInterface
*/
- public function patchEntity(EntityInterface $entity, array $data, array $options = [])
+ public function patchEntity(EntityInterface $entity, array $data, array $options = []): EntityInterface
{
if (!isset($options['associated'])) {
$options['associated'] = $this->_associations->keys();
@@ -2907,8 +2819,14 @@ public function patchEntity(EntityInterface $entity, array $data, array $options
*
* You can use the `Model.beforeMarshal` event to modify request data
* before it is converted into entities.
+ *
+ * @param \Cake\Datasource\EntityInterface[]|\Traversable $entities the entities that will get the
+ * data merged in
+ * @param array $data list of arrays to be merged into the entities
+ * @param array $options A list of options for the objects hydration.
+ * @return \Cake\Datasource\EntityInterface[]
*/
- public function patchEntities($entities, array $data, array $options = [])
+ public function patchEntities(iterable $entities, array $data, array $options = []): array
{
if (!isset($options['associated'])) {
$options['associated'] = $this->_associations->keys();
@@ -2952,7 +2870,7 @@ public function patchEntities($entities, array $data, array $options = [])
* @param array|null $context Either the validation context or null.
* @return bool True if the value is unique, or false if a non-scalar, non-unique value was given.
*/
- public function validateUnique($value, array $options, array $context = null)
+ public function validateUnique($value, array $options, ?array $context = null): bool
{
if ($context === null) {
$context = $options;
@@ -2976,6 +2894,7 @@ public function validateUnique($value, array $options, array $context = null)
}
}
$class = static::IS_UNIQUE_CLASS;
+ /** @var \Cake\ORM\Rule\IsUnique $rule */
$rule = new $class($fields, $options);
return $rule($entity, ['repository' => $this]);
@@ -2993,7 +2912,6 @@ public function validateUnique($value, array $options, array $context = null)
* The conventional method map is:
*
* - Model.beforeMarshal => beforeMarshal
- * - Model.afterMarshal => afterMarshal
* - Model.buildValidator => buildValidator
* - Model.beforeFind => beforeFind
* - Model.beforeSave => beforeSave
@@ -3007,11 +2925,10 @@ public function validateUnique($value, array $options, array $context = null)
*
* @return array
*/
- public function implementedEvents()
+ public function implementedEvents(): array
{
$eventMap = [
'Model.beforeMarshal' => 'beforeMarshal',
- 'Model.afterMarshal' => 'afterMarshal',
'Model.buildValidator' => 'buildValidator',
'Model.beforeFind' => 'beforeFind',
'Model.beforeSave' => 'beforeSave',
@@ -3041,7 +2958,7 @@ public function implementedEvents()
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
- public function buildRules(RulesChecker $rules)
+ public function buildRules(RulesChecker $rules): RulesChecker
{
return $rules;
}
@@ -3052,7 +2969,7 @@ public function buildRules(RulesChecker $rules)
* @param array $options Options to parse by the builder.
* @return \Cake\ORM\SaveOptionsBuilder
*/
- public function getSaveOptionsBuilder(array $options = [])
+ public function getSaveOptionsBuilder(array $options = []): SaveOptionsBuilder
{
return new SaveOptionsBuilder($this, $options);
}
@@ -3082,10 +2999,10 @@ public function getSaveOptionsBuilder(array $options = [])
*
* The properties for the associations to be loaded will be overwritten on each entity.
*
- * @param \Cake\Datasource\EntityInterface|array $entities a single entity or list of entities
+ * @param \Cake\Datasource\EntityInterface|\Cake\Datasource\EntityInterface[] $entities a single entity or list of entities
* @param array $contain A `contain()` compatible array.
* @see \Cake\ORM\Query::contain()
- * @return \Cake\Datasource\EntityInterface|array
+ * @return \Cake\Datasource\EntityInterface|\Cake\Datasource\EntityInterface[]
*/
public function loadInto($entities, array $contain)
{
@@ -3093,9 +3010,9 @@ public function loadInto($entities, array $contain)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- protected function validationMethodExists($name)
+ protected function validationMethodExists(string $name): bool
{
return method_exists($this, $name) || $this->behaviors()->hasMethod($name);
}
@@ -3109,18 +3026,16 @@ protected function validationMethodExists($name)
public function __debugInfo()
{
$conn = $this->getConnection();
- $associations = $this->_associations;
- $behaviors = $this->_behaviors;
return [
'registryAlias' => $this->getRegistryAlias(),
'table' => $this->getTable(),
'alias' => $this->getAlias(),
'entityClass' => $this->getEntityClass(),
- 'associations' => $associations ? $associations->keys() : false,
- 'behaviors' => $behaviors ? $behaviors->loaded() : false,
+ 'associations' => $this->_associations->keys(),
+ 'behaviors' => $this->_behaviors->loaded(),
'defaultConnection' => static::defaultConnectionName(),
- 'connectionName' => $conn ? $conn->configName() : null,
+ 'connectionName' => $conn->configName(),
];
}
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/TableRegistry.php b/app/vendor/cakephp/cakephp/src/ORM/TableRegistry.php
index 1cb465dfc..779003100 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/TableRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/TableRegistry.php
@@ -1,4 +1,6 @@
*/
- protected static $_defaultLocatorClass = 'Cake\ORM\Locator\TableLocator';
-
- /**
- * Sets and returns a singleton instance of LocatorInterface implementation.
- *
- * @param \Cake\ORM\Locator\LocatorInterface|null $locator Instance of a locator to use.
- * @return \Cake\ORM\Locator\LocatorInterface
- * @deprecated 3.5.0 Use getTableLocator()/setTableLocator() instead.
- */
- public static function locator(LocatorInterface $locator = null)
- {
- deprecationWarning(
- 'TableRegistry::locator() is deprecated. ' .
- 'Use setTableLocator()/getTableLocator() instead.'
- );
- if ($locator) {
- static::setTableLocator($locator);
- }
-
- return static::getTableLocator();
- }
+ protected static $_defaultLocatorClass = Locator\TableLocator::class;
/**
* Returns a singleton instance of LocatorInterface implementation.
*
* @return \Cake\ORM\Locator\LocatorInterface
*/
- public static function getTableLocator()
+ public static function getTableLocator(): LocatorInterface
{
- if (!static::$_locator) {
+ if (static::$_locator === null) {
static::$_locator = new static::$_defaultLocatorClass();
}
@@ -109,30 +92,11 @@ public static function getTableLocator()
* @param \Cake\ORM\Locator\LocatorInterface $tableLocator Instance of a locator to use.
* @return void
*/
- public static function setTableLocator(LocatorInterface $tableLocator)
+ public static function setTableLocator(LocatorInterface $tableLocator): void
{
static::$_locator = $tableLocator;
}
- /**
- * Stores a list of options to be used when instantiating an object
- * with a matching alias.
- *
- * @param string|null $alias Name of the alias
- * @param array|null $options list of options for the alias
- * @return array The config data.
- * @deprecated 3.6.0 Use \Cake\ORM\Locator\TableLocator::getConfig()/setConfig() instead.
- */
- public static function config($alias = null, $options = null)
- {
- deprecationWarning(
- 'TableRegistry::config() is deprecated. ' .
- 'Use \Cake\ORM\Locator\TableLocator::getConfig()/setConfig() instead.'
- );
-
- return static::getTableLocator()->config($alias, $options);
- }
-
/**
* Get a table instance from the registry.
*
@@ -141,9 +105,9 @@ public static function config($alias = null, $options = null)
* @param string $alias The alias name you want to get.
* @param array $options The options you want to build the table with.
* @return \Cake\ORM\Table
- * @deprecated 3.6.0 Use \Cake\ORM\Locator\TableLocator::get() instead.
+ * @deprecated 3.6.0 Use {@link \Cake\ORM\Locator\TableLocator::get()} instead. Will be removed in 5.0.
*/
- public static function get($alias, array $options = [])
+ public static function get(string $alias, array $options = []): Table
{
return static::getTableLocator()->get($alias, $options);
}
@@ -153,9 +117,9 @@ public static function get($alias, array $options = [])
*
* @param string $alias The alias to check for.
* @return bool
- * @deprecated 3.6.0 Use \Cake\ORM\Locator\TableLocator::exists() instead.
+ * @deprecated 3.6.0 Use {@link \Cake\ORM\Locator\TableLocator::exists()} instead. Will be removed in 5.0
*/
- public static function exists($alias)
+ public static function exists(string $alias): bool
{
return static::getTableLocator()->exists($alias);
}
@@ -166,9 +130,9 @@ public static function exists($alias)
* @param string $alias The alias to set.
* @param \Cake\ORM\Table $object The table to set.
* @return \Cake\ORM\Table
- * @deprecated 3.6.0 Use \Cake\ORM\Locator\TableLocator::set() instead.
+ * @deprecated 3.6.0 Use {@link \Cake\ORM\Locator\TableLocator::set()} instead. Will be removed in 5.0
*/
- public static function set($alias, Table $object)
+ public static function set(string $alias, Table $object): Table
{
return static::getTableLocator()->set($alias, $object);
}
@@ -178,9 +142,9 @@ public static function set($alias, Table $object)
*
* @param string $alias The alias to remove.
* @return void
- * @deprecated 3.6.0 Use \Cake\ORM\Locator\TableLocator::remove() instead.
+ * @deprecated 3.6.0 Use {@link \Cake\ORM\Locator\TableLocator::remove()} instead. Will be removed in 5.0
*/
- public static function remove($alias)
+ public static function remove(string $alias): void
{
static::getTableLocator()->remove($alias);
}
@@ -189,27 +153,10 @@ public static function remove($alias)
* Clears the registry of configuration and instances.
*
* @return void
- * @deprecated 3.6.0 Use \Cake\ORM\Locator\TableLocator::clear() instead.
+ * @deprecated 3.6.0 Use {@link \Cake\ORM\Locator\TableLocator::clear()} instead. Will be removed in 5.0
*/
- public static function clear()
+ public static function clear(): void
{
static::getTableLocator()->clear();
}
-
- /**
- * Proxy for static calls on a locator.
- *
- * @param string $name Method name.
- * @param array $arguments Method arguments.
- * @return mixed
- */
- public static function __callStatic($name, $arguments)
- {
- deprecationWarning(
- 'TableRegistry::' . $name . '() is deprecated. ' .
- 'Use \Cake\ORM\Locator\TableLocator::' . $name . '() instead.'
- );
-
- return static::getTableLocator()->$name(...$arguments);
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/composer.json b/app/vendor/cakephp/cakephp/src/ORM/composer.json
index 0ebc7f748..c0f2675d5 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/composer.json
+++ b/app/vendor/cakephp/cakephp/src/ORM/composer.json
@@ -23,17 +23,18 @@
"source": "https://github.com/cakephp/orm"
},
"require": {
- "php": ">=5.6.0,<8.0.0",
- "cakephp/collection": "^3.6.0",
- "cakephp/core": "^3.6.0",
- "cakephp/datasource": "^3.6.0",
- "cakephp/database": "^3.6.0",
- "cakephp/event": "^3.6.0",
- "cakephp/utility": "^3.6.0",
- "cakephp/validation": "^3.6.0"
+ "php": ">=7.2.0",
+ "cakephp/collection": "^4.0",
+ "cakephp/core": "^4.0",
+ "cakephp/datasource": "^4.0",
+ "cakephp/database": "^4.0",
+ "cakephp/event": "^4.0",
+ "cakephp/utility": "^4.0",
+ "cakephp/validation": "^4.0"
},
"suggest": {
- "cakephp/i18n": "If you are using Translate / Timestamp Behavior."
+ "cakephp/cache": "If you decide to use Query caching.",
+ "cakephp/i18n": "If you are using Translate/TimestampBehavior or Chronos types."
},
"autoload": {
"psr-4": {
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Asset.php b/app/vendor/cakephp/cakephp/src/Routing/Asset.php
new file mode 100644
index 000000000..eac796eaa
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Routing/Asset.php
@@ -0,0 +1,365 @@
+ null];
+ $requestWebroot = static::requestWebroot();
+
+ $asset = explode('?', $file);
+ $asset[1] = isset($asset[1]) ? '?' . $asset[1] : '';
+ $webPath = $requestWebroot . $asset[0];
+ $file = $asset[0];
+
+ $themeName = $options['theme'];
+ if ($themeName) {
+ $file = trim($file, '/');
+ $theme = static::inflectString($themeName) . '/';
+
+ if (DIRECTORY_SEPARATOR === '\\') {
+ $file = str_replace('/', '\\', $file);
+ }
+
+ if (file_exists(Configure::read('App.wwwRoot') . $theme . $file)) {
+ $webPath = $requestWebroot . $theme . $asset[0];
+ } else {
+ $themePath = Plugin::path($themeName);
+ $path = $themePath . 'webroot/' . $file;
+ if (file_exists($path)) {
+ $webPath = $requestWebroot . $theme . $asset[0];
+ }
+ }
+ }
+ if (strpos($webPath, '//') !== false) {
+ return str_replace('//', '/', $webPath . $asset[1]);
+ }
+
+ return $webPath . $asset[1];
+ }
+
+ /**
+ * Inflect the theme/plugin name to type set using `Asset::setInflectionType()`.
+ *
+ * @param string $string String inflected.
+ * @return string Inflected name of the theme
+ */
+ protected static function inflectString(string $string): string
+ {
+ return Inflector::{static::$inflectionType}($string);
+ }
+
+ /**
+ * Get webroot from request.
+ *
+ * @return string
+ */
+ protected static function requestWebroot(): string
+ {
+ $request = Router::getRequest();
+ if ($request === null) {
+ return '/';
+ }
+
+ return $request->getAttribute('webroot');
+ }
+
+ /**
+ * Splits a dot syntax plugin name into its plugin and filename.
+ * If $name does not have a dot, then index 0 will be null.
+ * It checks if the plugin is loaded, else filename will stay unchanged for filenames containing dot.
+ *
+ * @param string $name The name you want to plugin split.
+ * @return array Array with 2 indexes. 0 => plugin name, 1 => filename.
+ * @psalm-return array{string|null, string}
+ */
+ protected static function pluginSplit(string $name): array
+ {
+ $plugin = null;
+ [$first, $second] = pluginSplit($name);
+ if ($first && Plugin::isLoaded($first)) {
+ $name = $second;
+ $plugin = $first;
+ }
+
+ return [$plugin, $name];
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Dispatcher.php b/app/vendor/cakephp/cakephp/src/Routing/Dispatcher.php
deleted file mode 100644
index df29aa638..000000000
--- a/app/vendor/cakephp/cakephp/src/Routing/Dispatcher.php
+++ /dev/null
@@ -1,98 +0,0 @@
-getEventManager(), $this->_filters);
- $response = $actionDispatcher->dispatch($request, $response);
- if ($request->getParam('return', null) !== null) {
- return $response->body();
- }
-
- return $response->send();
- }
-
- /**
- * Add a filter to this dispatcher.
- *
- * The added filter will be attached to the event manager used
- * by this dispatcher.
- *
- * @param \Cake\Event\EventListenerInterface $filter The filter to connect. Can be
- * any EventListenerInterface. Typically an instance of \Cake\Routing\DispatcherFilter.
- * @return void
- */
- public function addFilter(EventListenerInterface $filter)
- {
- $this->_filters[] = $filter;
- }
-
- /**
- * Get the list of connected filters.
- *
- * @return \Cake\Event\EventListenerInterface[]
- */
- public function filters()
- {
- return $this->_filters;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/DispatcherFactory.php b/app/vendor/cakephp/cakephp/src/Routing/DispatcherFactory.php
deleted file mode 100644
index 4b178fd5c..000000000
--- a/app/vendor/cakephp/cakephp/src/Routing/DispatcherFactory.php
+++ /dev/null
@@ -1,112 +0,0 @@
-addFilter($middleware);
- }
-
- return $dispatcher;
- }
-
- /**
- * Get the connected dispatcher filters.
- *
- * @return \Cake\Routing\DispatcherFilter[]
- */
- public static function filters()
- {
- return static::$_stack;
- }
-
- /**
- * Clear the middleware stack.
- *
- * @return void
- */
- public static function clear()
- {
- static::$_stack = [];
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/DispatcherFilter.php b/app/vendor/cakephp/cakephp/src/Routing/DispatcherFilter.php
deleted file mode 100644
index 7b4f9d88c..000000000
--- a/app/vendor/cakephp/cakephp/src/Routing/DispatcherFilter.php
+++ /dev/null
@@ -1,214 +0,0 @@
- '/blog']);
- * ```
- *
- * When the above filter is connected to a dispatcher it will only fire
- * its `beforeDispatch` and `afterDispatch` methods on requests that start with `/blog`.
- *
- * The for condition can also be a regular expression by using the `preg:` prefix:
- *
- * ```
- * $filter = new BlogFilter(['for' => 'preg:#^/blog/\d+$#']);
- * ```
- *
- * ### Limiting filters based on conditions
- *
- * In addition to simple path based matching you can use a closure to match on arbitrary request
- * or response conditions. For example:
- *
- * ```
- * $cookieMonster = new CookieFilter([
- * 'when' => function ($req, $res) {
- * // Custom code goes here.
- * }
- * ]);
- * ```
- *
- * If your when condition returns `true` the before/after methods will be called.
- *
- * When using the `for` or `when` matchers, conditions will be re-checked on the before and after
- * callback as the conditions could change during the dispatch cycle.
- */
-class DispatcherFilter implements EventListenerInterface
-{
- use InstanceConfigTrait;
-
- /**
- * Default priority for all methods in this filter
- *
- * @var int
- */
- protected $_priority = 10;
-
- /**
- * Default config
- *
- * These are merged with user-provided config when the class is used.
- * The when and for options allow you to define conditions that are checked before
- * your filter is called.
- *
- * @var array
- */
- protected $_defaultConfig = [
- 'when' => null,
- 'for' => null,
- 'priority' => null,
- ];
-
- /**
- * Constructor.
- *
- * @param array $config Settings for the filter.
- * @throws \InvalidArgumentException When 'when' conditions are not callable.
- */
- public function __construct($config = [])
- {
- if (!isset($config['priority'])) {
- $config['priority'] = $this->_priority;
- }
- $this->setConfig($config);
- if (isset($config['when']) && !is_callable($config['when'])) {
- throw new InvalidArgumentException('"when" conditions must be a callable.');
- }
- }
-
- /**
- * Returns the list of events this filter listens to.
- * Dispatcher notifies 2 different events `Dispatcher.before` and `Dispatcher.after`.
- * By default this class will attach `preDispatch` and `postDispatch` method respectively.
- *
- * Override this method at will to only listen to the events you are interested in.
- *
- * @return array
- */
- public function implementedEvents()
- {
- return [
- 'Dispatcher.beforeDispatch' => [
- 'callable' => 'handle',
- 'priority' => $this->_config['priority'],
- ],
- 'Dispatcher.afterDispatch' => [
- 'callable' => 'handle',
- 'priority' => $this->_config['priority'],
- ],
- ];
- }
-
- /**
- * Handler method that applies conditions and resolves the correct method to call.
- *
- * @param \Cake\Event\Event $event The event instance.
- * @return mixed
- */
- public function handle(Event $event)
- {
- $name = $event->getName();
- list(, $method) = explode('.', $name);
- if (empty($this->_config['for']) && empty($this->_config['when'])) {
- return $this->{$method}($event);
- }
- if ($this->matches($event)) {
- return $this->{$method}($event);
- }
- }
-
- /**
- * Check to see if the incoming request matches this filter's criteria.
- *
- * @param \Cake\Event\Event $event The event to match.
- * @return bool
- */
- public function matches(Event $event)
- {
- /** @var \Cake\Http\ServerRequest $request */
- $request = $event->getData('request');
- $pass = true;
- if (!empty($this->_config['for'])) {
- $len = strlen('preg:');
- $for = $this->_config['for'];
- $url = $request->getRequestTarget();
- if (substr($for, 0, $len) === 'preg:') {
- $pass = (bool)preg_match(substr($for, $len), $url);
- } else {
- $pass = strpos($url, $for) === 0;
- }
- }
- if ($pass && !empty($this->_config['when'])) {
- $response = $event->getData('response');
- $pass = $this->_config['when']($request, $response);
- }
-
- return $pass;
- }
-
- /**
- * Method called before the controller is instantiated and called to serve a request.
- * If used with default priority, it will be called after the Router has parsed the
- * URL and set the routing params into the request object.
- *
- * If a Cake\Http\Response object instance is returned, it will be served at the end of the
- * event cycle, not calling any controller as a result. This will also have the effect of
- * not calling the after event in the dispatcher.
- *
- * If false is returned, the event will be stopped and no more listeners will be notified.
- * Alternatively you can call `$event->stopPropagation()` to achieve the same result.
- *
- * @param \Cake\Event\Event $event container object having the `request`, `response` and `additionalParams`
- * keys in the data property.
- * @return void
- */
- public function beforeDispatch(Event $event)
- {
- }
-
- /**
- * Method called after the controller served a request and generated a response.
- * It is possible to alter the response object at this point as it is not sent to the
- * client yet.
- *
- * If false is returned, the event will be stopped and no more listeners will be notified.
- * Alternatively you can call `$event->stopPropagation()` to achieve the same result.
- *
- * @param \Cake\Event\Event $event container object having the `request` and `response`
- * keys in the data property.
- * @return void
- */
- public function afterDispatch(Event $event)
- {
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Exception/DuplicateNamedRouteException.php b/app/vendor/cakephp/cakephp/src/Routing/Exception/DuplicateNamedRouteException.php
index 253d1b885..93372e0c2 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Exception/DuplicateNamedRouteException.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Exception/DuplicateNamedRouteException.php
@@ -1,4 +1,6 @@
_messageTemplate = $message['message'];
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Exception/MissingControllerException.php b/app/vendor/cakephp/cakephp/src/Routing/Exception/MissingControllerException.php
index dfbdada1d..e6456fea4 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Exception/MissingControllerException.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Exception/MissingControllerException.php
@@ -1,35 +1,10 @@
_cacheTime = $config['cacheTime'];
- }
- parent::__construct($config);
- }
-
- /**
- * Checks if a requested asset exists and sends it to the browser
- *
- * @param \Cake\Event\Event $event Event containing the request and response object
- * @return \Cake\Http\Response|null If the client is requesting a recognized asset, null otherwise
- * @throws \Cake\Http\Exception\NotFoundException When asset not found
- */
- public function beforeDispatch(Event $event)
- {
- /** @var \Cake\Http\ServerRequest $request */
- $request = $event->getData('request');
-
- $url = urldecode($request->getUri()->getPath());
- if (strpos($url, '..') !== false || strpos($url, '.') === false) {
- return null;
- }
-
- $assetFile = $this->_getAssetFile($url);
- if ($assetFile === null || !file_exists($assetFile)) {
- return null;
- }
- /** @var \Cake\Http\Response $response */
- $response = $event->getData('response');
- $event->stopPropagation();
-
- $response = $response->withModified(filemtime($assetFile));
- if ($response->checkNotModified($request)) {
- return $response;
- }
-
- $pathSegments = explode('.', $url);
- $ext = array_pop($pathSegments);
-
- return $this->_deliverAsset($request, $response, $assetFile, $ext);
- }
-
- /**
- * Builds asset file path based off url
- *
- * @param string $url Asset URL
- * @return string Absolute path for asset file
- */
- protected function _getAssetFile($url)
- {
- $parts = explode('/', ltrim($url, '/'));
- $pluginPart = [];
- for ($i = 0; $i < 2; $i++) {
- if (!isset($parts[$i])) {
- break;
- }
- $pluginPart[] = Inflector::camelize($parts[$i]);
- $plugin = implode('/', $pluginPart);
- if ($plugin && Plugin::isLoaded($plugin)) {
- $parts = array_slice($parts, $i + 1);
- $fileFragment = implode(DIRECTORY_SEPARATOR, $parts);
- $pluginWebroot = Plugin::path($plugin) . 'webroot' . DIRECTORY_SEPARATOR;
-
- return $pluginWebroot . $fileFragment;
- }
- }
- }
-
- /**
- * Sends an asset file to the client
- *
- * @param \Cake\Http\ServerRequest $request The request object to use.
- * @param \Cake\Http\Response $response The response object to use.
- * @param string $assetFile Path to the asset file in the file system
- * @param string $ext The extension of the file to determine its mime type
- * @return \Cake\Http\Response The updated response.
- */
- protected function _deliverAsset(ServerRequest $request, Response $response, $assetFile, $ext)
- {
- $compressionEnabled = $response->compress();
- if ($response->getType() === $ext) {
- $contentType = 'application/octet-stream';
- $agent = $request->getEnv('HTTP_USER_AGENT');
- if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent) || preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) {
- $contentType = 'application/octetstream';
- }
- $response = $response->withType($contentType);
- }
- if (!$compressionEnabled) {
- $response = $response->withHeader('Content-Length', filesize($assetFile));
- }
- $response = $response->withCache(filemtime($assetFile), $this->_cacheTime)
- ->withFile($assetFile);
-
- return $response;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Filter/ControllerFactoryFilter.php b/app/vendor/cakephp/cakephp/src/Routing/Filter/ControllerFactoryFilter.php
deleted file mode 100644
index aec14df8b..000000000
--- a/app/vendor/cakephp/cakephp/src/Routing/Filter/ControllerFactoryFilter.php
+++ /dev/null
@@ -1,65 +0,0 @@
-getData('request');
- $response = $event->getData('response');
- $event->setData('controller', $this->_getController($request, $response));
- }
-
- /**
- * Gets controller to use, either plugin or application controller.
- *
- * @param \Cake\Http\ServerRequest $request Request object
- * @param \Cake\Http\Response $response Response for the controller.
- * @return \Cake\Controller\Controller
- * @throws \ReflectionException
- */
- protected function _getController($request, $response)
- {
- $factory = new ControllerFactory();
-
- return $factory->create($request, $response);
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Filter/LocaleSelectorFilter.php b/app/vendor/cakephp/cakephp/src/Routing/Filter/LocaleSelectorFilter.php
deleted file mode 100644
index a65384ac5..000000000
--- a/app/vendor/cakephp/cakephp/src/Routing/Filter/LocaleSelectorFilter.php
+++ /dev/null
@@ -1,70 +0,0 @@
-_locales = $config['locales'];
- }
- }
-
- /**
- * Inspects the request for the Accept-Language header and sets the
- * Locale for the current runtime if it matches the list of valid locales
- * as passed in the configuration.
- *
- * @param \Cake\Event\Event $event The event instance.
- * @return void
- */
- public function beforeDispatch(Event $event)
- {
- /** @var \Cake\Http\ServerRequest $request */
- $request = $event->getData('request');
- $locale = Locale::acceptFromHttp($request->getHeaderLine('Accept-Language'));
-
- if (!$locale || (!empty($this->_locales) && !in_array($locale, $this->_locales))) {
- return;
- }
-
- I18n::setLocale($locale);
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Filter/RoutingFilter.php b/app/vendor/cakephp/cakephp/src/Routing/Filter/RoutingFilter.php
deleted file mode 100644
index 509e73f2b..000000000
--- a/app/vendor/cakephp/cakephp/src/Routing/Filter/RoutingFilter.php
+++ /dev/null
@@ -1,72 +0,0 @@
-getData('request');
- if (Router::getRequest(true) !== $request) {
- Router::setRequestInfo($request);
- }
-
- try {
- if (!$request->getParam('controller')) {
- $params = Router::parseRequest($request);
- $request->addParams($params);
- }
-
- return null;
- } catch (RedirectException $e) {
- $event->stopPropagation();
- /** @var \Cake\Http\Response $response */
- $response = $event->getData('response');
- $response = $response->withStatus($e->getCode())
- ->withLocation($e->getMessage());
-
- return $response;
- }
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Middleware/AssetMiddleware.php b/app/vendor/cakephp/cakephp/src/Routing/Middleware/AssetMiddleware.php
index 035f9355e..c9ed66f5a 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Middleware/AssetMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Middleware/AssetMiddleware.php
@@ -1,4 +1,6 @@
'text/css',
- 'json' => 'application/json',
- 'js' => 'application/javascript',
- 'ico' => 'image/x-icon',
- 'eot' => 'application/vnd.ms-fontobject',
- 'svg' => 'image/svg+xml',
- 'html' => 'text/html',
- 'rss' => 'application/rss+xml',
- 'xml' => 'application/xml',
- ];
-
/**
* Constructor.
*
@@ -68,62 +52,61 @@ public function __construct(array $options = [])
if (!empty($options['cacheTime'])) {
$this->cacheTime = $options['cacheTime'];
}
- if (!empty($options['types'])) {
- $this->typeMap = array_merge($this->typeMap, $options['types']);
- }
}
/**
* Serve assets if the path matches one.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @param \Psr\Http\Message\ResponseInterface $response The response.
- * @param callable $next Callback to invoke the next middleware.
- * @return \Psr\Http\Message\ResponseInterface A response
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
+ * @return \Psr\Http\Message\ResponseInterface A response.
*/
- public function __invoke($request, $response, $next)
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$url = $request->getUri()->getPath();
if (strpos($url, '..') !== false || strpos($url, '.') === false) {
- return $next($request, $response);
+ return $handler->handle($request);
}
if (strpos($url, '/.') !== false) {
- return $next($request, $response);
+ return $handler->handle($request);
}
$assetFile = $this->_getAssetFile($url);
if ($assetFile === null || !file_exists($assetFile)) {
- return $next($request, $response);
+ return $handler->handle($request);
}
- $file = new File($assetFile);
- $modifiedTime = $file->lastChange();
+ $file = new SplFileInfo($assetFile);
+ $modifiedTime = $file->getMTime();
if ($this->isNotModified($request, $file)) {
- $headers = $response->getHeaders();
- $headers['Last-Modified'] = date(DATE_RFC850, $modifiedTime);
-
- return new Response('php://memory', 304, $headers);
+ return (new Response())
+ ->withStringBody('')
+ ->withStatus(304)
+ ->withHeader(
+ 'Last-Modified',
+ date(DATE_RFC850, $modifiedTime)
+ );
}
- return $this->deliverAsset($request, $response, $file);
+ return $this->deliverAsset($request, $file);
}
/**
* Check the not modified header.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request to check.
- * @param \Cake\Filesystem\File $file The file object to compare.
+ * @param \SplFileInfo $file The file object to compare.
* @return bool
*/
- protected function isNotModified($request, $file)
+ protected function isNotModified(ServerRequestInterface $request, SplFileInfo $file): bool
{
$modifiedSince = $request->getHeaderLine('If-Modified-Since');
if (!$modifiedSince) {
return false;
}
- return strtotime($modifiedSince) === $file->lastChange();
+ return strtotime($modifiedSince) === $file->getMTime();
}
/**
@@ -132,7 +115,7 @@ protected function isNotModified($request, $file)
* @param string $url Asset URL
* @return string|null Absolute path for asset file, null on failure
*/
- protected function _getAssetFile($url)
+ protected function _getAssetFile(string $url): ?string
{
$parts = explode('/', ltrim($url, '/'));
$pluginPart = [];
@@ -142,7 +125,7 @@ protected function _getAssetFile($url)
}
$pluginPart[] = Inflector::camelize($parts[$i]);
$plugin = implode('/', $pluginPart);
- if ($plugin && Plugin::isLoaded($plugin)) {
+ if (Plugin::isLoaded($plugin)) {
$parts = array_slice($parts, $i + 1);
$fileFragment = implode(DIRECTORY_SEPARATOR, $parts);
$pluginWebroot = Plugin::path($plugin) . 'webroot' . DIRECTORY_SEPARATOR;
@@ -158,40 +141,25 @@ protected function _getAssetFile($url)
* Sends an asset file to the client
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request object to use.
- * @param \Psr\Http\Message\ResponseInterface $response The response object to use.
- * @param \Cake\Filesystem\File $file The file wrapper for the file.
- * @return \Psr\Http\Message\ResponseInterface The response with the file & headers.
+ * @param \SplFileInfo $file The file wrapper for the file.
+ * @return \Cake\Http\Response The response with the file & headers.
*/
- protected function deliverAsset(ServerRequestInterface $request, ResponseInterface $response, $file)
+ protected function deliverAsset(ServerRequestInterface $request, SplFileInfo $file): Response
{
- $contentType = $this->getType($file);
- $modified = $file->lastChange();
+ $stream = new Stream(fopen($file->getPathname(), 'rb'));
+
+ $response = new Response(['stream' => $stream]);
+
+ $contentType = $response->getMimeType($file->getExtension()) ?: 'application/octet-stream';
+ $modified = $file->getMTime();
$expire = strtotime($this->cacheTime);
$maxAge = $expire - time();
- $stream = new Stream(fopen($file->path, 'rb'));
-
- return $response->withBody($stream)
+ return $response
->withHeader('Content-Type', $contentType)
->withHeader('Cache-Control', 'public,max-age=' . $maxAge)
- ->withHeader('Date', gmdate('D, d M Y H:i:s \G\M\T', time()))
- ->withHeader('Last-Modified', gmdate('D, d M Y H:i:s \G\M\T', $modified))
- ->withHeader('Expires', gmdate('D, d M Y H:i:s \G\M\T', $expire));
- }
-
- /**
- * Return the type from a File object
- *
- * @param File $file The file from which you get the type
- * @return string
- */
- protected function getType($file)
- {
- $extension = $file->ext();
- if (isset($this->typeMap[$extension])) {
- return $this->typeMap[$extension];
- }
-
- return $file->mime() ?: 'application/octet-stream';
+ ->withHeader('Date', gmdate('D, j M Y G:i:s \G\M\T', time()))
+ ->withHeader('Last-Modified', gmdate('D, j M Y G:i:s \G\M\T', $modified))
+ ->withHeader('Expires', gmdate('D, j M Y G:i:s \G\M\T', $expire));
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Middleware/RoutingMiddleware.php b/app/vendor/cakephp/cakephp/src/Routing/Middleware/RoutingMiddleware.php
index d47c42bc8..04ddeef8f 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Middleware/RoutingMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Middleware/RoutingMiddleware.php
@@ -1,4 +1,6 @@
app = $app;
$this->cacheConfig = $cacheConfig;
}
@@ -80,12 +79,8 @@ public function __construct(HttpApplicationInterface $app = null, $cacheConfig =
*
* @return void
*/
- protected function loadRoutes()
+ protected function loadRoutes(): void
{
- if (!$this->app) {
- return;
- }
-
$routeCollection = $this->buildRouteCollection();
Router::setRouteCollection($routeCollection);
}
@@ -95,7 +90,7 @@ protected function loadRoutes()
*
* @return \Cake\Routing\RouteCollection
*/
- protected function buildRouteCollection()
+ protected function buildRouteCollection(): RouteCollection
{
if (Cache::enabled() && $this->cacheConfig !== null) {
return Cache::remember(static::ROUTE_COLLECTION_CACHE_KEY, function () {
@@ -111,7 +106,7 @@ protected function buildRouteCollection()
*
* @return \Cake\Routing\RouteCollection
*/
- protected function prepareRouteCollection()
+ protected function prepareRouteCollection(): RouteCollection
{
$builder = Router::createRouteBuilder('/');
$this->app->routes($builder);
@@ -129,20 +124,20 @@ protected function prepareRouteCollection()
* invoked.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @param \Psr\Http\Message\ResponseInterface $response The response.
- * @param callable $next The next middleware to call.
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
* @return \Psr\Http\Message\ResponseInterface A response.
*/
- public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->loadRoutes();
try {
- Router::setRequestContext($request);
+ Router::setRequest($request);
$params = (array)$request->getAttribute('params', []);
$middleware = [];
if (empty($params['controller'])) {
$parsedBody = $request->getParsedBody();
if (is_array($parsedBody) && isset($parsedBody['_method'])) {
+ /** @var \Cake\Http\ServerRequest $request */
$request = $request->withMethod($parsedBody['_method']);
}
$params = Router::parseRequest($request) + $params;
@@ -150,23 +145,24 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res
$middleware = $params['_middleware'];
unset($params['_middleware']);
}
+ /** @var \Cake\Http\ServerRequest $request */
$request = $request->withAttribute('params', $params);
+ Router::setRequest($request);
}
} catch (RedirectException $e) {
return new RedirectResponse(
$e->getMessage(),
- (int)$e->getCode(),
- $response->getHeaders()
+ (int)$e->getCode()
);
}
$matching = Router::getRouteCollection()->getMiddleware($middleware);
if (!$matching) {
- return $next($request, $response);
+ return $handler->handle($request);
}
- $matching[] = $next;
+
$middleware = new MiddlewareQueue($matching);
$runner = new Runner();
- return $runner->run($middleware, $request, $response);
+ return $runner->run($middleware, $request, $handler);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/RequestActionTrait.php b/app/vendor/cakephp/cakephp/src/Routing/RequestActionTrait.php
deleted file mode 100644
index 4c7fd4e76..000000000
--- a/app/vendor/cakephp/cakephp/src/Routing/RequestActionTrait.php
+++ /dev/null
@@ -1,186 +0,0 @@
-requestAction('/articles/popular');
- * ```
- *
- * A basic example of request action to fetch a rendered page without the layout.
- *
- * ```
- * $viewHtml = $this->requestAction('/articles/popular', ['return']);
- * ```
- *
- * You can also pass the URL as an array:
- *
- * ```
- * $vars = $this->requestAction(['controller' => 'articles', 'action' => 'popular']);
- * ```
- *
- * ### Passing other request data
- *
- * You can pass POST, GET, COOKIE and other data into the request using the appropriate keys.
- * Cookies can be passed using the `cookies` key. Get parameters can be set with `query` and post
- * data can be sent using the `post` key.
- *
- * ```
- * $vars = $this->requestAction('/articles/popular', [
- * 'query' => ['page' => 1],
- * 'cookies' => ['remember_me' => 1],
- * ]);
- * ```
- *
- * ### Sending environment or header values
- *
- * By default actions dispatched with this method will use the global $_SERVER and $_ENV
- * values. If you want to override those values for a request action, you can specify the values:
- *
- * ```
- * $vars = $this->requestAction('/articles/popular', [
- * 'environment' => ['CONTENT_TYPE' => 'application/json']
- * ]);
- * ```
- *
- * ### Transmitting the session
- *
- * By default actions dispatched with this method will use the standard session object.
- * If you want a particular session instance to be used, you need to specify it.
- *
- * ```
- * $vars = $this->requestAction('/articles/popular', [
- * 'session' => new Session($someSessionConfig)
- * ]);
- * ```
- *
- * @param string|array $url String or array-based url. Unlike other url arrays in CakePHP, this
- * url will not automatically handle passed arguments in the $url parameter.
- * @param array $extra if array includes the key "return" it sets the autoRender to true. Can
- * also be used to submit GET/POST data, and passed arguments.
- * @return mixed Boolean true or false on success/failure, or contents
- * of rendered action if 'return' is set in $extra.
- * @deprecated 3.3.0 You should refactor your code to use View Cells instead of this method.
- */
- public function requestAction($url, array $extra = [])
- {
- deprecationWarning(
- 'RequestActionTrait::requestAction() is deprecated. ' .
- 'You should refactor to use View Cells or Components instead.'
- );
- if (empty($url)) {
- return false;
- }
- $isReturn = array_search('return', $extra, true);
- if ($isReturn !== false) {
- $extra['return'] = 0;
- $extra['autoRender'] = 1;
- unset($extra[$isReturn]);
- }
- $extra += ['autoRender' => 0, 'return' => 1, 'bare' => 1, 'requested' => 1];
-
- $baseUrl = Configure::read('App.fullBaseUrl');
- if (is_string($url) && strpos($url, $baseUrl) === 0) {
- $url = Router::normalize(str_replace($baseUrl, '', $url));
- }
- if (is_string($url)) {
- $params = [
- 'url' => $url,
- ];
- } elseif (is_array($url)) {
- $defaultParams = ['plugin' => null, 'controller' => null, 'action' => null];
- $params = [
- 'params' => $url + $defaultParams,
- 'base' => false,
- 'url' => Router::reverse($url),
- ];
- if (empty($params['params']['pass'])) {
- $params['params']['pass'] = [];
- }
- }
- $current = Router::getRequest();
- if ($current) {
- $params['base'] = $current->getAttribute('base');
- $params['webroot'] = $current->getAttribute('webroot');
- }
-
- $params['post'] = $params['query'] = [];
- if (isset($extra['post'])) {
- $params['post'] = $extra['post'];
- }
- if (isset($extra['query'])) {
- $params['query'] = $extra['query'];
- }
- if (isset($extra['cookies'])) {
- $params['cookies'] = $extra['cookies'];
- }
- if (isset($extra['environment'])) {
- $params['environment'] = $extra['environment'] + $_SERVER + $_ENV;
- }
- unset($extra['environment'], $extra['post'], $extra['query']);
-
- $params['session'] = isset($extra['session']) ? $extra['session'] : new Session();
-
- $request = new ServerRequest($params);
- $request->addParams($extra);
- $dispatcher = DispatcherFactory::create();
-
- // If an application is using PSR7 middleware,
- // we need to 'fix' their missing dispatcher filters.
- $needed = [
- 'routing' => RoutingFilter::class,
- 'controller' => ControllerFactoryFilter::class,
- ];
- foreach ($dispatcher->filters() as $filter) {
- if ($filter instanceof RoutingFilter) {
- unset($needed['routing']);
- }
- if ($filter instanceof ControllerFactoryFilter) {
- unset($needed['controller']);
- }
- }
- foreach ($needed as $class) {
- $dispatcher->addFilter(new $class());
- }
- $result = $dispatcher->dispatch($request, new Response());
- Router::popRequest();
-
- return $result;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/DashedRoute.php b/app/vendor/cakephp/cakephp/src/Routing/Route/DashedRoute.php
index d21be8e14..8a0fb1383 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/DashedRoute.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/DashedRoute.php
@@ -1,4 +1,6 @@
_dasherize($url);
if (!$this->_inflectedDefaults) {
@@ -109,7 +111,7 @@ public function match(array $url, array $context = [])
* @param array $url An array of URL keys.
* @return array
*/
- protected function _dasherize($url)
+ protected function _dasherize(array $url): array
{
foreach (['controller', 'plugin', 'action'] as $element) {
if (!empty($url[$element])) {
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/EntityRoute.php b/app/vendor/cakephp/cakephp/src/Routing/Route/EntityRoute.php
index 522b7e4c0..6adaedc65 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/EntityRoute.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/EntityRoute.php
@@ -1,4 +1,6 @@
_compiledRoute)) {
$this->compile();
@@ -66,11 +68,12 @@ public function match(array $url, array $context = [])
* @param \ArrayAccess|array $entity Entity value from the URL options
* @return void
*/
- protected function _checkEntity($entity)
+ protected function _checkEntity($entity): void
{
if (!$entity instanceof ArrayAccess && !is_array($entity)) {
throw new RuntimeException(sprintf(
- 'Route `%s` expects the URL option `_entity` to be an array or object implementing \ArrayAccess, but `%s` passed.',
+ 'Route `%s` expects the URL option `_entity` to be an array or object implementing \ArrayAccess, '
+ . 'but `%s` passed.',
$this->template,
getTypeName($entity)
));
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/InflectedRoute.php b/app/vendor/cakephp/cakephp/src/Routing/Route/InflectedRoute.php
index cf5de1523..852ed07b1 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/InflectedRoute.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/InflectedRoute.php
@@ -1,4 +1,6 @@
_underscore($url);
if (!$this->_inflectedDefaults) {
@@ -88,7 +90,7 @@ public function match(array $url, array $context = [])
* @param array $url An array of URL keys.
* @return array
*/
- protected function _underscore($url)
+ protected function _underscore(array $url): array
{
if (!empty($url['controller'])) {
$url['controller'] = Inflector::underscore($url['controller']);
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/PluginShortRoute.php b/app/vendor/cakephp/cakephp/src/Routing/Route/PluginShortRoute.php
index 9b780d6ae..b3e1d6fda 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/PluginShortRoute.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/PluginShortRoute.php
@@ -1,4 +1,6 @@
defaults['controller'] = $url['controller'];
$result = parent::match($url, $context);
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/RedirectRoute.php b/app/vendor/cakephp/cakephp/src/Routing/Route/RedirectRoute.php
index 3729f54ea..3db3b4b9f 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/RedirectRoute.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/RedirectRoute.php
@@ -1,4 +1,6 @@
value array or a CakePHP array URL.
* @param array $options Array of additional options for the Route
*/
- public function __construct($template, $defaults = [], array $options = [])
+ public function __construct(string $template, array $defaults = [], array $options = [])
{
parent::__construct($template, $defaults, $options);
- if (is_array($defaults) && isset($defaults['redirect'])) {
- $defaults = $defaults['redirect'];
+ if (isset($defaults['redirect'])) {
+ $defaults = (array)$defaults['redirect'];
}
- $this->redirect = (array)$defaults;
+ $this->redirect = $defaults;
}
/**
@@ -64,18 +58,18 @@ public function __construct($template, $defaults = [], array $options = [])
*
* @param string $url The URL to parse.
* @param string $method The HTTP method being used.
- * @return bool|null False on failure. An exception is raised on a successful match.
+ * @return array|null Null on failure. An exception is raised on a successful match. Array return type is unused.
* @throws \Cake\Routing\Exception\RedirectException An exception is raised on successful match.
* This is used to halt route matching and signal to the middleware that a redirect should happen.
*/
- public function parse($url, $method = '')
+ public function parse(string $url, string $method = ''): ?array
{
$params = parent::parse($url, $method);
if (!$params) {
- return false;
+ return null;
}
$redirect = $this->redirect;
- if (count($this->redirect) === 1 && !isset($this->redirect['controller'])) {
+ if ($this->redirect && count($this->redirect) === 1 && !isset($this->redirect['controller'])) {
$redirect = $this->redirect[0];
}
if (isset($this->options['persist']) && is_array($redirect)) {
@@ -101,11 +95,11 @@ public function parse($url, $method = '')
*
* @param array $url Array of parameters to convert to a string.
* @param array $context Array of request context parameters.
- * @return bool Always false.
+ * @return string|null Always null, string return result unused.
*/
- public function match(array $url, array $context = [])
+ public function match(array $url, array $context = []): ?string
{
- return false;
+ return null;
}
/**
@@ -114,7 +108,7 @@ public function match(array $url, array $context = [])
* @param int $status The status code for this route
* @return $this
*/
- public function setStatus($status)
+ public function setStatus(int $status)
{
$this->options['status'] = $status;
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/Route.php b/app/vendor/cakephp/cakephp/src/Routing/Route/Route.php
index d9bc270c2..a70ae0cc6 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/Route.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/Route.php
@@ -1,4 +1,6 @@
template = $template;
- if (isset($defaults['[method]'])) {
- deprecationWarning('The `[method]` option is deprecated. Use `_method` instead.');
- $defaults['_method'] = $defaults['[method]'];
- unset($defaults['[method]']);
- }
- $this->defaults = (array)$defaults;
+ $this->defaults = $defaults;
$this->options = $options + ['_ext' => [], '_middleware' => []];
$this->setExtensions((array)$this->options['_ext']);
$this->setMiddleware((array)$this->options['_middleware']);
unset($this->options['_middleware']);
- }
- /**
- * Get/Set the supported extensions for this route.
- *
- * @deprecated 3.3.9 Use getExtensions/setExtensions instead.
- * @param array|string|null $extensions The extensions to set. Use null to get.
- * @return array|null The extensions or null.
- */
- public function extensions($extensions = null)
- {
- deprecationWarning(
- 'Route::extensions() is deprecated. ' .
- 'Use Route::setExtensions()/getExtensions() instead.'
- );
- if ($extensions === null) {
- return $this->_extensions;
- }
- $this->_extensions = (array)$extensions;
+ if (isset($this->defaults['_method'])) {
+ $this->defaults['_method'] = $this->normalizeAndValidateMethods($this->defaults['_method']);
+ }
}
/**
@@ -178,7 +158,7 @@ public function setExtensions(array $extensions)
*
* @return string[]
*/
- public function getExtensions()
+ public function getExtensions(): array
{
return $this->_extensions;
}
@@ -192,16 +172,31 @@ public function getExtensions()
*/
public function setMethods(array $methods)
{
- $methods = array_map('strtoupper', $methods);
- $diff = array_diff($methods, static::VALID_METHODS);
+ $this->defaults['_method'] = $this->normalizeAndValidateMethods($methods);
+
+ return $this;
+ }
+
+ /**
+ * Normalize method names to upper case and validate that they are valid HTTP methods.
+ *
+ * @param string|array $methods Methods.
+ * @return string|array
+ */
+ protected function normalizeAndValidateMethods($methods)
+ {
+ $methods = is_array($methods)
+ ? array_map('strtoupper', $methods)
+ : strtoupper($methods);
+
+ $diff = array_diff((array)$methods, static::VALID_METHODS);
if ($diff !== []) {
throw new InvalidArgumentException(
- sprintf('Invalid HTTP method received. %s is invalid.', implode(', ', $diff))
+ sprintf('Invalid HTTP method received. `%s` is invalid.', implode(', ', $diff))
);
}
- $this->defaults['_method'] = $methods;
- return $this;
+ return $methods;
}
/**
@@ -230,7 +225,7 @@ public function setPatterns(array $patterns)
* @param string $host The host name this route is bound to
* @return $this
*/
- public function setHost($host)
+ public function setHost(string $host)
{
$this->options['_host'] = $host;
@@ -277,7 +272,7 @@ public function setPersist(array $names)
*
* @return bool
*/
- public function compiled()
+ public function compiled(): bool
{
return $this->_compiledRoute !== null;
}
@@ -290,12 +285,11 @@ public function compiled()
*
* @return string Returns a string regular expression of the compiled route.
*/
- public function compile()
+ public function compile(): string
{
- if ($this->_compiledRoute) {
- return $this->_compiledRoute;
+ if ($this->_compiledRoute === null) {
+ $this->_writeRoute();
}
- $this->_writeRoute();
return $this->_compiledRoute;
}
@@ -308,7 +302,7 @@ public function compile()
*
* @return void
*/
- protected function _writeRoute()
+ protected function _writeRoute(): void
{
if (empty($this->template) || ($this->template === '/')) {
$this->_compiledRoute = '#^/*$#';
@@ -330,16 +324,18 @@ protected function _writeRoute()
foreach ($namedElements[1] as $i => $name) {
$search = preg_quote($namedElements[0][$i]);
if (isset($this->options[$name])) {
- $option = null;
+ $option = '';
if ($name !== 'plugin' && array_key_exists($name, $this->defaults)) {
$option = '?';
}
$slashParam = '/' . $search;
+ // phpcs:disable Generic.Files.LineLength
if (strpos($parsed, $slashParam) !== false) {
$routeParams[$slashParam] = '(?:/(?P<' . $name . '>' . $this->options[$name] . ')' . $option . ')' . $option;
} else {
$routeParams[$search] = '(?:(?P<' . $name . '>' . $this->options[$name] . ')' . $option . ')' . $option;
}
+ // phpcs:disable Generic.Files.LineLength
} else {
$routeParams[$search] = '(?:(?P<' . $name . '>[^/]+))';
}
@@ -377,7 +373,7 @@ protected function _writeRoute()
*
* @return string
*/
- public function getName()
+ public function getName(): string
{
if (!empty($this->_name)) {
return $this->_name;
@@ -419,16 +415,16 @@ public function getName()
* false will be returned.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The URL to attempt to parse.
- * @return array|false An array of request parameters, or false on failure.
+ * @return array|null An array of request parameters, or null on failure.
*/
- public function parseRequest(ServerRequestInterface $request)
+ public function parseRequest(ServerRequestInterface $request): ?array
{
$uri = $request->getUri();
if (isset($this->options['_host']) && !$this->hostMatches($uri->getHost())) {
- return false;
+ return null;
}
- return $this->parse($uri->getPath(), $request->getMethod());
+ return $this->parse($uri->getPath(), (string)$request->getMethod());
}
/**
@@ -439,33 +435,25 @@ public function parseRequest(ServerRequestInterface $request)
*
* @param string $url The URL to attempt to parse.
* @param string $method The HTTP method of the request being parsed.
- * @return array|false An array of request parameters, or false on failure.
- * @deprecated 3.4.0 Use/implement parseRequest() instead as it provides more flexibility/control.
+ * @return array|null An array of request parameters, or null on failure.
*/
- public function parse($url, $method = '')
+ public function parse(string $url, string $method): ?array
{
- if (empty($this->_compiledRoute)) {
- $this->compile();
+ if ($method !== '') {
+ $method = $this->normalizeAndValidateMethods($method);
}
- list($url, $ext) = $this->_parseExtension($url);
+ $compiledRoute = $this->compile();
+ [$url, $ext] = $this->_parseExtension($url);
- if (!preg_match($this->_compiledRoute, urldecode($url), $route)) {
- return false;
+ if (!preg_match($compiledRoute, urldecode($url), $route)) {
+ return null;
}
- if (isset($this->defaults['_method'])) {
- if (empty($method)) {
- deprecationWarning(
- 'Extracting the request method from global state when parsing routes is deprecated. ' .
- 'Instead adopt Route::parseRequest() which extracts the method from the passed request.'
- );
- // Deprecated reading the global state is deprecated and will be removed in 4.x
- $request = Router::getRequest(true) ?: ServerRequestFactory::fromGlobals();
- $method = $request->getMethod();
- }
- if (!in_array($method, (array)$this->defaults['_method'], true)) {
- return false;
- }
+ if (
+ isset($this->defaults['_method']) &&
+ !in_array($method, (array)$this->defaults['_method'], true)
+ ) {
+ return null;
}
array_shift($route);
@@ -488,6 +476,7 @@ public function parse($url, $method = '')
}
if (isset($route['_args_'])) {
+ /** @psalm-suppress PossiblyInvalidArgument */
$pass = $this->_parseArgs($route['_args_'], $route);
$route['pass'] = array_merge($route['pass'], $pass);
unset($route['_args_']);
@@ -511,6 +500,7 @@ public function parse($url, $method = '')
if (isset($this->options['pass'])) {
$j = count($this->options['pass']);
while ($j--) {
+ /** @psalm-suppress PossiblyInvalidArgument */
if (isset($route[$this->options['pass'][$j]])) {
array_unshift($route['pass'], $route[$this->options['pass'][$j]]);
}
@@ -530,7 +520,7 @@ public function parse($url, $method = '')
* @param string $host The request's host name
* @return bool Whether or not the host matches any conditions set in for this route.
*/
- public function hostMatches($host)
+ public function hostMatches(string $host): bool
{
$pattern = '@^' . str_replace('\*', '.*', preg_quote($this->options['_host'], '@')) . '$@';
@@ -544,7 +534,7 @@ public function hostMatches($host)
* @param string $url The url to parse.
* @return array containing url, extension
*/
- protected function _parseExtension($url)
+ protected function _parseExtension(string $url): array
{
if (count($this->_extensions) && strpos($url, '.') !== false) {
foreach ($this->_extensions as $ext) {
@@ -565,16 +555,16 @@ protected function _parseExtension($url)
* Currently implemented rule types are controller, action and match that can be combined with each other.
*
* @param string $args A string with the passed params. eg. /1/foo
- * @param string $context The current route context, which should contain controller/action keys.
- * @return array Array of passed args.
+ * @param array $context The current route context, which should contain controller/action keys.
+ * @return string[] Array of passed args.
*/
- protected function _parseArgs($args, $context)
+ protected function _parseArgs(string $args, array $context): array
{
$pass = [];
$args = explode('/', $args);
foreach ($args as $param) {
- if (empty($param) && $param !== '0' && $param !== 0) {
+ if (empty($param) && $param !== '0') {
continue;
}
$pass[] = rawurldecode($param);
@@ -592,7 +582,7 @@ protected function _parseArgs($args, $context)
* @param array $params An array of persistent values to replace persistent ones.
* @return array An array with persistent parameters applied.
*/
- protected function _persistParams(array $url, array $params)
+ protected function _persistParams(array $url, array $params): array
{
foreach ($this->options['persist'] as $persistKey) {
if (array_key_exists($persistKey, $params) && !isset($url[$persistKey])) {
@@ -614,9 +604,9 @@ protected function _persistParams(array $url, array $params)
* @param array $context An array of the current request context.
* Contains information such as the current host, scheme, port, base
* directory and other url params.
- * @return string|false Either a string URL for the parameters if they match or false.
+ * @return string|null Either a string URL for the parameters if they match or null.
*/
- public function match(array $url, array $context = [])
+ public function match(array $url, array $context = []): ?string
{
if (empty($this->_compiledRoute)) {
$this->compile();
@@ -643,8 +633,8 @@ public function match(array $url, array $context = [])
}
// The host did not match the route preferences
- if (!$this->hostMatches($hostOptions['_host'])) {
- return false;
+ if (!$this->hostMatches((string)$hostOptions['_host'])) {
+ return null;
}
}
@@ -657,7 +647,10 @@ public function match(array $url, array $context = [])
) {
$hostOptions += $context;
- if (getservbyname($hostOptions['_scheme'], 'tcp') === $hostOptions['_port']) {
+ if (
+ $hostOptions['_scheme'] &&
+ getservbyname($hostOptions['_scheme'], 'tcp') === $hostOptions['_port']
+ ) {
unset($hostOptions['_port']);
}
}
@@ -679,18 +672,18 @@ public function match(array $url, array $context = [])
// Check the method first as it is special.
if (!$this->_matchMethod($url)) {
- return false;
+ return null;
}
unset($url['_method'], $url['[method]'], $defaults['_method']);
// Missing defaults is a fail.
if (array_diff_key($defaults, $url) !== []) {
- return false;
+ return null;
}
// Defaults with different values are a fail.
if (array_intersect_key($url, $defaults) != $defaults) {
- return false;
+ return null;
}
// If this route uses pass option, and the passed elements are
@@ -707,14 +700,11 @@ public function match(array $url, array $context = [])
// check that all the key names are in the url
$keyNames = array_flip($this->keys);
if (array_intersect_key($keyNames, $url) !== $keyNames) {
- return false;
+ return null;
}
$pass = [];
foreach ($url as $key => $value) {
- // keys that exist in the defaults and have different values is a match failure.
- $defaultExists = array_key_exists($key, $defaults);
-
// If the key is a routed key, it's not different yet.
if (array_key_exists($key, $keyNames)) {
continue;
@@ -722,7 +712,7 @@ public function match(array $url, array $context = [])
// pull out passed args
$numeric = is_numeric($key);
- if ($numeric && isset($defaults[$key]) && $defaults[$key] == $value) {
+ if ($numeric && isset($defaults[$key]) && $defaults[$key] === $value) {
continue;
}
if ($numeric) {
@@ -730,24 +720,18 @@ public function match(array $url, array $context = [])
unset($url[$key]);
continue;
}
-
- // keys that don't exist are different.
- if (!$defaultExists && ($value !== null && $value !== false && $value !== '')) {
- $query[$key] = $value;
- unset($url[$key]);
- }
}
// if not a greedy route, no extra params are allowed.
if (!$this->_greedy && !empty($pass)) {
- return false;
+ return null;
}
// check patterns for routed params
if (!empty($this->options)) {
foreach ($this->options as $key => $pattern) {
if (isset($url[$key]) && !preg_match('#^' . $pattern . '$#u', (string)$url[$key])) {
- return false;
+ return null;
}
}
}
@@ -758,7 +742,7 @@ public function match(array $url, array $context = [])
(isset($keyNames['controller']) && !isset($url['controller'])) ||
(isset($keyNames['action']) && !isset($url['action']))
) {
- return false;
+ return null;
}
return $this->_writeUrl($url, $pass, $query);
@@ -770,22 +754,18 @@ public function match(array $url, array $context = [])
* @param array $url The array for the URL being generated.
* @return bool
*/
- protected function _matchMethod($url)
+ protected function _matchMethod(array $url): bool
{
if (empty($this->defaults['_method'])) {
return true;
}
- // @deprecated The `[method]` support should be removed in 4.0.0
- if (isset($url['[method]'])) {
- deprecationWarning('The `[method]` key is deprecated. Use `_method` instead.');
- $url['_method'] = $url['[method]'];
- }
if (empty($url['_method'])) {
$url['_method'] = 'GET';
}
- $methods = array_map('strtoupper', (array)$url['_method']);
+ $defaults = (array)$this->defaults['_method'];
+ $methods = (array)$this->normalizeAndValidateMethods($url['_method']);
foreach ($methods as $value) {
- if (in_array($value, (array)$this->defaults['_method'])) {
+ if (in_array($value, (array)$this->defaults['_method'], true)) {
return true;
}
}
@@ -804,7 +784,7 @@ protected function _matchMethod($url)
* @param array $query An array of parameters
* @return string Composed route string.
*/
- protected function _writeUrl($params, $pass = [], $query = [])
+ protected function _writeUrl(array $params, array $pass = [], array $query = []): string
{
$pass = implode('/', array_map('rawurlencode', $pass));
$out = $this->template;
@@ -850,7 +830,7 @@ protected function _writeUrl($params, $pass = [], $query = [])
if (isset($params['_port'])) {
$host .= ':' . $params['_port'];
}
- $scheme = isset($params['_scheme']) ? $params['_scheme'] : 'http';
+ $scheme = $params['_scheme'] ?? 'http';
$out = "{$scheme}://{$host}{$out}";
}
if (!empty($params['_ext']) || !empty($query)) {
@@ -871,7 +851,7 @@ protected function _writeUrl($params, $pass = [], $query = [])
*
* @return string
*/
- public function staticPath()
+ public function staticPath(): string
{
$routeKey = strpos($this->template, ':');
if ($routeKey !== false) {
@@ -910,7 +890,7 @@ public function setMiddleware(array $middleware)
*
* @return array
*/
- public function getMiddleware()
+ public function getMiddleware(): array
{
return $this->middleware;
}
@@ -922,11 +902,11 @@ public function getMiddleware()
* router caching.
*
* @param array $fields Key/Value of object attributes
- * @return \Cake\Routing\Route\Route A new instance of the route
+ * @return static A new instance of the route
*/
- public static function __set_state($fields)
+ public static function __set_state(array $fields)
{
- $class = get_called_class();
+ $class = static::class;
$obj = new $class('');
foreach ($fields as $field => $value) {
$obj->$field = $value;
diff --git a/app/vendor/cakephp/cakephp/src/Routing/RouteBuilder.php b/app/vendor/cakephp/cakephp/src/Routing/RouteBuilder.php
index f6a7b2f3e..426d903c7 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/RouteBuilder.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/RouteBuilder.php
@@ -1,4 +1,6 @@
controller action map.
@@ -63,7 +66,7 @@ class RouteBuilder
*
* @var string
*/
- protected $_routeClass = 'Cake\Routing\Route\Route';
+ protected $_routeClass = Route::class;
/**
* The extensions that should be set into the routes connected.
@@ -123,7 +126,7 @@ class RouteBuilder
* @param array $params The scope's routing parameters.
* @param array $options Options list.
*/
- public function __construct(RouteCollection $collection, $path, array $params = [], array $options = [])
+ public function __construct(RouteCollection $collection, string $path, array $params = [], array $options = [])
{
$this->_collection = $collection;
$this->_path = $path;
@@ -142,32 +145,13 @@ public function __construct(RouteCollection $collection, $path, array $params =
}
}
- /**
- * Get or set default route class.
- *
- * @deprecated 3.5.0 Use getRouteClass/setRouteClass instead.
- * @param string|null $routeClass Class name.
- * @return string|null
- */
- public function routeClass($routeClass = null)
- {
- deprecationWarning(
- 'RouteBuilder::routeClass() is deprecated. ' .
- 'Use RouteBuilder::setRouteClass()/getRouteClass() instead.'
- );
- if ($routeClass === null) {
- return $this->getRouteClass();
- }
- $this->setRouteClass($routeClass);
- }
-
/**
* Set default route class.
*
* @param string $routeClass Class name.
* @return $this
*/
- public function setRouteClass($routeClass)
+ public function setRouteClass(string $routeClass)
{
$this->_routeClass = $routeClass;
@@ -179,33 +163,11 @@ public function setRouteClass($routeClass)
*
* @return string
*/
- public function getRouteClass()
+ public function getRouteClass(): string
{
return $this->_routeClass;
}
- /**
- * Get or set the extensions in this route builder's scope.
- *
- * Future routes connected in through this builder will have the connected
- * extensions applied. However, setting extensions does not modify existing routes.
- *
- * @deprecated 3.5.0 Use getExtensions/setExtensions instead.
- * @param string[]|string|null $extensions Either the extensions to use or null.
- * @return string[]|null
- */
- public function extensions($extensions = null)
- {
- deprecationWarning(
- 'RouteBuilder::extensions() is deprecated. ' .
- 'Use RouteBuilder::setExtensions()/getExtensions() instead.'
- );
- if ($extensions === null) {
- return $this->getExtensions();
- }
- $this->setExtensions($extensions);
- }
-
/**
* Set the extensions in this route builder's scope.
*
@@ -227,7 +189,7 @@ public function setExtensions($extensions)
*
* @return string[]
*/
- public function getExtensions()
+ public function getExtensions(): array
{
return $this->_extensions;
}
@@ -236,12 +198,14 @@ public function getExtensions()
* Add additional extensions to what is already in current scope
*
* @param string|string[] $extensions One or more extensions to add
- * @return void
+ * @return $this
*/
public function addExtensions($extensions)
{
$extensions = array_merge($this->_extensions, (array)$extensions);
$this->_extensions = array_unique($extensions);
+
+ return $this;
}
/**
@@ -249,7 +213,7 @@ public function addExtensions($extensions)
*
* @return string
*/
- public function path()
+ public function path(): string
{
$routeKey = strpos($this->_path, ':');
if ($routeKey !== false) {
@@ -264,7 +228,7 @@ public function path()
*
* @return array
*/
- public function params()
+ public function params(): array
{
return $this->_params;
}
@@ -275,7 +239,7 @@ public function params()
* @param string $name Name.
* @return bool
*/
- public function nameExists($name)
+ public function nameExists(string $name): bool
{
return array_key_exists($name, $this->_collection->named());
}
@@ -289,7 +253,7 @@ public function nameExists($name)
* @param string|null $value Either the value to set or null.
* @return string
*/
- public function namePrefix($value = null)
+ public function namePrefix(?string $value = null): string
{
if ($value !== null) {
$this->_namePrefix = $value;
@@ -320,19 +284,19 @@ public function namePrefix($value = null)
* });
* ```
*
- * Plugins will create lower_case underscored resource routes. e.g
+ * Plugins will create lowercase dasherized resource routes. e.g
* `/comments/comments`
*
* Connect resource routes for the Articles controller in the
* Admin prefix:
*
* ```
- * Router::prefix('admin', function ($routes) {
+ * Router::prefix('Admin', function ($routes) {
* $routes->resources('Articles');
* });
* ```
*
- * Prefixes will create lower_case underscored resource routes. e.g
+ * Prefixes will create lowercase dasherized resource routes. e.g
* `/admin/posts`
*
* You can create nested resources by passing a callback in:
@@ -359,7 +323,7 @@ public function namePrefix($value = null)
* You can use the `inflect` option to change how path segments are generated:
*
* ```
- * $routes->resources('PaymentTypes', ['inflect' => 'dasherize']);
+ * $routes->resources('PaymentTypes', ['inflect' => 'underscore']);
* ```
*
* Will generate routes like `/payment-types` instead of `/payment_types`
@@ -368,7 +332,7 @@ public function namePrefix($value = null)
*
* - 'id' - The regular expression fragment to use when matching IDs. By default, matches
* integer values and UUIDs.
- * - 'inflect' - Choose the inflection method used on the resource name. Defaults to 'underscore'.
+ * - 'inflect' - Choose the inflection method used on the resource name. Defaults to 'dasherize'.
* - 'only' - Only connect the specific list of actions.
* - 'actions' - Override the method names used for connecting actions.
* - 'map' - Additional resource routes that should be connected. If you define 'only' and 'map',
@@ -383,17 +347,17 @@ public function namePrefix($value = null)
* @param array|callable $options Options to use when generating REST routes, or a callback.
* @param callable|null $callback An optional callback to be executed in a nested scope. Nested
* scopes inherit the existing path and 'id' parameter.
- * @return void
+ * @return $this
*/
- public function resources($name, $options = [], $callback = null)
+ public function resources(string $name, $options = [], $callback = null)
{
- if (is_callable($options)) {
+ if (!is_array($options)) {
$callback = $options;
$options = [];
}
$options += [
'connectOptions' => [],
- 'inflect' => 'underscore',
+ 'inflect' => 'dasherize',
'id' => static::ID . '|' . static::UUID,
'only' => [],
'actions' => [],
@@ -458,11 +422,13 @@ public function resources($name, $options = [], $callback = null)
$this->connect($url, $params, $routeOptions);
}
- if (is_callable($callback)) {
+ if ($callback !== null) {
$idName = Inflector::singularize(Inflector::underscore($name)) . '_id';
$path = '/' . $options['path'] . '/:' . $idName;
$this->scope($path, [], $callback);
}
+
+ return $this;
}
/**
@@ -474,7 +440,7 @@ public function resources($name, $options = [], $callback = null)
* @param string|null $name The name of the route.
* @return \Cake\Routing\Route\Route
*/
- public function get($template, $target, $name = null)
+ public function get(string $template, $target, ?string $name = null): Route
{
return $this->_methodRoute('GET', $template, $target, $name);
}
@@ -488,7 +454,7 @@ public function get($template, $target, $name = null)
* @param string|null $name The name of the route.
* @return \Cake\Routing\Route\Route
*/
- public function post($template, $target, $name = null)
+ public function post(string $template, $target, ?string $name = null): Route
{
return $this->_methodRoute('POST', $template, $target, $name);
}
@@ -502,7 +468,7 @@ public function post($template, $target, $name = null)
* @param string|null $name The name of the route.
* @return \Cake\Routing\Route\Route
*/
- public function put($template, $target, $name = null)
+ public function put(string $template, $target, ?string $name = null): Route
{
return $this->_methodRoute('PUT', $template, $target, $name);
}
@@ -516,7 +482,7 @@ public function put($template, $target, $name = null)
* @param string|null $name The name of the route.
* @return \Cake\Routing\Route\Route
*/
- public function patch($template, $target, $name = null)
+ public function patch(string $template, $target, ?string $name = null): Route
{
return $this->_methodRoute('PATCH', $template, $target, $name);
}
@@ -530,7 +496,7 @@ public function patch($template, $target, $name = null)
* @param string|null $name The name of the route.
* @return \Cake\Routing\Route\Route
*/
- public function delete($template, $target, $name = null)
+ public function delete(string $template, $target, ?string $name = null): Route
{
return $this->_methodRoute('DELETE', $template, $target, $name);
}
@@ -544,7 +510,7 @@ public function delete($template, $target, $name = null)
* @param string|null $name The name of the route.
* @return \Cake\Routing\Route\Route
*/
- public function head($template, $target, $name = null)
+ public function head(string $template, $target, ?string $name = null): Route
{
return $this->_methodRoute('HEAD', $template, $target, $name);
}
@@ -558,7 +524,7 @@ public function head($template, $target, $name = null)
* @param string|null $name The name of the route.
* @return \Cake\Routing\Route\Route
*/
- public function options($template, $target, $name = null)
+ public function options(string $template, $target, ?string $name = null): Route
{
return $this->_methodRoute('OPTIONS', $template, $target, $name);
}
@@ -573,7 +539,7 @@ public function options($template, $target, $name = null)
* @param string|null $name The name of the route.
* @return \Cake\Routing\Route\Route
*/
- protected function _methodRoute($method, $template, $target, $name)
+ protected function _methodRoute(string $method, string $template, $target, ?string $name): Route
{
if ($name !== null) {
$name = $this->_namePrefix . $name;
@@ -601,45 +567,23 @@ protected function _methodRoute($method, $template, $target, $name)
* the current RouteBuilder instance.
*
* @param string $name The plugin name
- * @param string $file The routes file to load. Defaults to `routes.php`. This parameter
- * is deprecated and will be removed in 4.0
- * @return void
+ * @return $this
* @throws \Cake\Core\Exception\MissingPluginException When the plugin has not been loaded.
* @throws \InvalidArgumentException When the plugin does not have a routes file.
*/
- public function loadPlugin($name, $file = 'routes.php')
+ public function loadPlugin(string $name)
{
$plugins = Plugin::getCollection();
if (!$plugins->has($name)) {
throw new MissingPluginException(['plugin' => $name]);
}
$plugin = $plugins->get($name);
-
- // @deprecated This block should be removed in 4.0
- if ($file !== 'routes.php') {
- deprecationWarning(
- 'Loading plugin routes now uses the routes() hook method on the plugin class. ' .
- 'Loading non-standard files will be removed in 4.0'
- );
-
- $path = $plugin->getConfigPath() . DIRECTORY_SEPARATOR . $file;
- if (!file_exists($path)) {
- throw new InvalidArgumentException(sprintf(
- 'Cannot load routes for the plugin named %s. The %s file does not exist.',
- $name,
- $path
- ));
- }
-
- $routes = $this;
- include $path;
-
- return;
- }
$plugin->routes($this);
// Disable the routes hook to prevent duplicate route issues.
$plugin->disable('routes');
+
+ return $this;
}
/**
@@ -709,9 +653,9 @@ public function loadPlugin($name, $file = 'routes.php')
*
* The above route will only be matched for GET requests. POST requests will fail to match this route.
*
- * @param string $route A string describing the template of the route
- * @param array|string $defaults An array describing the default route parameters. These parameters will be used by default
- * and can supply routing parameters that are not dynamic. See above.
+ * @param string|\Cake\Routing\Route\Route $route A string describing the template of the route
+ * @param array|string $defaults An array describing the default route parameters.
+ * These parameters will be used by default and can supply routing parameters that are not dynamic. See above.
* @param array $options An array matching the named elements in the route to regular expressions which that
* element should match. Also contains additional parameters such as which routed parameters should be
* shifted into the passed arguments, supplying patterns for routing parameters and supplying the name of a
@@ -720,7 +664,7 @@ public function loadPlugin($name, $file = 'routes.php')
* @throws \InvalidArgumentException
* @throws \BadMethodCallException
*/
- public function connect($route, $defaults = [], array $options = [])
+ public function connect($route, $defaults = [], array $options = []): Route
{
$defaults = $this->parseDefaults($defaults);
if (empty($options['_ext'])) {
@@ -746,35 +690,15 @@ public function connect($route, $defaults = [], array $options = [])
* Parse the defaults if they're a string
*
* @param string|array $defaults Defaults array from the connect() method.
- * @return string|array
+ * @return array
*/
- protected static function parseDefaults($defaults)
+ protected function parseDefaults($defaults): array
{
if (!is_string($defaults)) {
return $defaults;
}
- $regex = '/(?:(?[a-zA-Z0-9\/]*)\.)?(?[a-zA-Z0-9\/]*?)' .
- '(?:\/)?(?[a-zA-Z0-9]*):{2}(?[a-zA-Z0-9_]*)/i';
-
- if (preg_match($regex, $defaults, $matches)) {
- foreach ($matches as $key => $value) {
- // Remove numeric keys and empty values.
- if (is_int($key) || $value === '' || $value === '::') {
- unset($matches[$key]);
- }
- }
- $length = count($matches);
-
- if (isset($matches['prefix'])) {
- $matches['prefix'] = strtolower($matches['prefix']);
- }
-
- if ($length >= 2 || $length <= 4) {
- return $matches;
- }
- }
- throw new RuntimeException("Could not parse `{$defaults}` route destination string.");
+ return Router::parseRoutePath($defaults);
}
/**
@@ -787,11 +711,11 @@ protected static function parseDefaults($defaults)
* @throws \InvalidArgumentException when route class or route object is invalid.
* @throws \BadMethodCallException when the route to make conflicts with the current scope
*/
- protected function _makeRoute($route, $defaults, $options)
+ protected function _makeRoute($route, $defaults, $options): Route
{
if (is_string($route)) {
$routeClass = App::className($options['routeClass'], 'Routing/Route');
- if ($routeClass === false) {
+ if ($routeClass === null) {
throw new InvalidArgumentException(sprintf(
'Cannot find route class %s',
$options['routeClass']
@@ -867,10 +791,10 @@ protected function _makeRoute($route, $defaults, $options)
* shifted into the passed arguments. As well as supplying patterns for routing parameters.
* @return \Cake\Routing\Route\Route|\Cake\Routing\Route\RedirectRoute
*/
- public function redirect($route, $url, array $options = [])
+ public function redirect(string $route, $url, array $options = []): Route
{
if (!isset($options['routeClass'])) {
- $options['routeClass'] = 'Cake\Routing\Route\RedirectRoute';
+ $options['routeClass'] = RedirectRoute::class;
}
if (is_string($url)) {
$url = ['redirect' => $url];
@@ -897,8 +821,8 @@ public function redirect($route, $url, array $options = [])
* for $params argument:
*
* ```
- * $route->prefix('api', function($route) {
- * $route->prefix('v10', ['path' => '/v1.0'], function($route) {
+ * $route->prefix('Api', function($route) {
+ * $route->prefix('V10', ['path' => '/v1.0'], function($route) {
* // Translates to `Controller\Api\V10\` namespace
* });
* });
@@ -908,20 +832,17 @@ public function redirect($route, $url, array $options = [])
* @param array|callable $params An array of routing defaults to add to each connected route.
* If you have no parameters, this argument can be a callable.
* @param callable|null $callback The callback to invoke that builds the prefixed routes.
- * @return void
+ * @return $this
* @throws \InvalidArgumentException If a valid callback is not passed
*/
- public function prefix($name, $params = [], callable $callback = null)
+ public function prefix(string $name, $params = [], $callback = null)
{
- if ($callback === null) {
- if (!is_callable($params)) {
- throw new InvalidArgumentException('A valid callback is expected');
- }
+ if (!is_array($params)) {
$callback = $params;
$params = [];
}
- $name = Inflector::underscore($name);
- $path = '/' . $name;
+ $path = '/' . Inflector::dasherize($name);
+ $name = Inflector::camelize($name);
if (isset($params['path'])) {
$path = $params['path'];
unset($params['path']);
@@ -931,6 +852,8 @@ public function prefix($name, $params = [], callable $callback = null)
}
$params = array_merge($params, ['prefix' => $name]);
$this->scope($path, $params, $callback);
+
+ return $this;
}
/**
@@ -945,32 +868,24 @@ public function prefix($name, $params = [], callable $callback = null)
* Routes connected in the scoped collection will have the correct path segment
* prepended, and have a matching plugin routing key set.
*
- * ### Options
- *
- * - `path` The path prefix to use. Defaults to `Inflector::dasherize($name)`.
- * - `_namePrefix` Set a prefix used for named routes. The prefix is prepended to the
- * name of any route created in a scope callback.
- *
* @param string $name The plugin name to build routes for
- * @param array|callable $options Either the options to use, or a callback to build routes.
+ * @param array|callable $options Either the options to use, or a callback
* @param callable|null $callback The callback to invoke that builds the plugin routes
* Only required when $options is defined.
- * @return void
+ * @return $this
*/
- public function plugin($name, $options = [], $callback = null)
+ public function plugin(string $name, $options = [], $callback = null)
{
- if ($callback === null) {
+ if (!is_array($options)) {
$callback = $options;
$options = [];
}
- if (empty($options['path'])) {
- $path = '/' . Inflector::underscore($name);
- } else {
- $path = $options['path'];
- }
- unset($options['path']);
- $params = ['plugin' => $name] + $options + $this->_params;
+
+ $params = ['plugin' => $name] + $this->_params;
+ $path = $options['path'] ?? '/' . Inflector::dasherize($name);
$this->scope($path, $params, $callback);
+
+ return $this;
}
/**
@@ -980,27 +895,24 @@ public function plugin($name, $options = [], $callback = null)
* added to. This means that both the current path and parameters will be appended
* to the supplied parameters.
*
- * ### Special Keys in $params
- *
- * - `_namePrefix` Set a prefix used for named routes. The prefix is prepended to the
- * name of any route created in a scope callback.
- *
* @param string $path The path to create a scope for.
* @param array|callable $params Either the parameters to add to routes, or a callback.
* @param callable|null $callback The callback to invoke that builds the plugin routes.
* Only required when $params is defined.
- * @return void
+ * @return $this
* @throws \InvalidArgumentException when there is no callable parameter.
*/
- public function scope($path, $params, $callback = null)
+ public function scope(string $path, $params, $callback = null)
{
- if (is_callable($params)) {
+ if (!is_array($params)) {
$callback = $params;
$params = [];
}
if (!is_callable($callback)) {
- $msg = 'Need a callable function/object to connect routes.';
- throw new InvalidArgumentException($msg);
+ throw new InvalidArgumentException(sprintf(
+ 'Need a valid callable to connect routes. Got `%s` instead.',
+ getTypeName($callback)
+ ));
}
if ($this->_path !== '/') {
@@ -1020,6 +932,8 @@ public function scope($path, $params, $callback = null)
'middleware' => $this->middleware,
]);
$callback($builder);
+
+ return $this;
}
/**
@@ -1029,13 +943,15 @@ public function scope($path, $params, $callback = null)
*
* @param string|null $routeClass the route class to use, uses the default routeClass
* if not specified
- * @return void
+ * @return $this
*/
- public function fallbacks($routeClass = null)
+ public function fallbacks(?string $routeClass = null)
{
$routeClass = $routeClass ?: $this->_routeClass;
$this->connect('/{controller}', ['action' => 'index'], compact('routeClass'));
$this->connect('/{controller}/{action}/*', [], compact('routeClass'));
+
+ return $this;
}
/**
@@ -1045,11 +961,11 @@ public function fallbacks($routeClass = null)
* scope or any child scopes that share the same RouteCollection.
*
* @param string $name The name of the middleware. Used when applying middleware to a scope.
- * @param callable|string $middleware The middleware callable or class name to register.
+ * @param string|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware to register.
* @return $this
* @see \Cake\Routing\RouteCollection
*/
- public function registerMiddleware($name, $middleware)
+ public function registerMiddleware(string $name, $middleware)
{
$this->_collection->registerMiddleware($name, $middleware);
@@ -1066,7 +982,7 @@ public function registerMiddleware($name, $middleware)
* @throws \RuntimeException
* @see \Cake\Routing\RouteCollection::addMiddlewareToScope()
*/
- public function applyMiddleware(...$names)
+ public function applyMiddleware(string ...$names)
{
foreach ($names as $name) {
if (!$this->_collection->middlewareExists($name)) {
@@ -1080,6 +996,16 @@ public function applyMiddleware(...$names)
return $this;
}
+ /**
+ * Get the middleware that this builder will apply to routes.
+ *
+ * @return array
+ */
+ public function getMiddleware(): array
+ {
+ return $this->middleware;
+ }
+
/**
* Apply a set of middleware to a group
*
@@ -1087,7 +1013,7 @@ public function applyMiddleware(...$names)
* @param string[] $middlewareNames Names of the middleware
* @return $this
*/
- public function middlewareGroup($name, array $middlewareNames)
+ public function middlewareGroup(string $name, array $middlewareNames)
{
$this->_collection->middlewareGroup($name, $middlewareNames);
diff --git a/app/vendor/cakephp/cakephp/src/Routing/RouteCollection.php b/app/vendor/cakephp/cakephp/src/Routing/RouteCollection.php
index 093259319..892eec919 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/RouteCollection.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/RouteCollection.php
@@ -1,4 +1,6 @@
_routes[] = $route;
@@ -136,7 +131,7 @@ public function add(Route $route, array $options = [])
* @return array An array of request parameters parsed from the URL.
* @throws \Cake\Routing\Exception\MissingRouteException When a URL has no matching route.
*/
- public function parse($url, $method = '')
+ public function parse(string $url, string $method = ''): array
{
$decoded = urldecode($url);
@@ -149,15 +144,15 @@ public function parse($url, $method = '')
continue;
}
- $queryParameters = null;
+ $queryParameters = [];
if (strpos($url, '?') !== false) {
- list($url, $queryParameters) = explode('?', $url, 2);
- parse_str($queryParameters, $queryParameters);
+ [$url, $qs] = explode('?', $url, 2);
+ parse_str($qs, $queryParameters);
}
/** @var \Cake\Routing\Route\Route $route */
foreach ($this->_paths[$path] as $route) {
$r = $route->parse($url, $method);
- if ($r === false) {
+ if ($r === null) {
continue;
}
if ($queryParameters) {
@@ -185,7 +180,7 @@ public function parse($url, $method = '')
* @return array An array of request parameters parsed from the URL.
* @throws \Cake\Routing\Exception\MissingRouteException When a URL has no matching route.
*/
- public function parseRequest(ServerRequestInterface $request)
+ public function parseRequest(ServerRequestInterface $request): array
{
$uri = $request->getUri();
$urlPath = urldecode($uri->getPath());
@@ -202,7 +197,7 @@ public function parseRequest(ServerRequestInterface $request)
/** @var \Cake\Routing\Route\Route $route */
foreach ($this->_paths[$path] as $route) {
$r = $route->parseRequest($request);
- if ($r === false) {
+ if ($r === null) {
continue;
}
if ($uri->getQuery()) {
@@ -223,7 +218,7 @@ public function parseRequest(ServerRequestInterface $request)
* @param array $url The url to match.
* @return string[] The set of names of the url
*/
- protected function _getNames($url)
+ protected function _getNames(array $url): array
{
$plugin = false;
if (isset($url['plugin']) && $url['plugin'] !== false) {
@@ -233,7 +228,7 @@ protected function _getNames($url)
if (isset($url['prefix']) && $url['prefix'] !== false) {
$prefix = strtolower($url['prefix']);
}
- $controller = strtolower($url['controller']);
+ $controller = isset($url['controller']) ? strtolower($url['controller']) : null;
$action = strtolower($url['action']);
$names = [
@@ -310,7 +305,7 @@ protected function _getNames($url)
* @return string The URL string on match.
* @throws \Cake\Routing\Exception\MissingRouteException When no route could be matched.
*/
- public function match($url, $context)
+ public function match(array $url, array $context): string
{
// Named routes support optimization.
if (isset($url['_name'])) {
@@ -351,7 +346,7 @@ public function match($url, $context)
*
* @return \Cake\Routing\Route\Route[]
*/
- public function routes()
+ public function routes(): array
{
return $this->_routes;
}
@@ -361,40 +356,17 @@ public function routes()
*
* @return \Cake\Routing\Route\Route[]
*/
- public function named()
+ public function named(): array
{
return $this->_named;
}
- /**
- * Get/set the extensions that the route collection could handle.
- *
- * @param string[]|string|null $extensions Either the list of extensions to set,
- * or null to get.
- * @param bool $merge Whether to merge with or override existing extensions.
- * Defaults to `true`.
- * @return string[] The valid extensions.
- * @deprecated 3.5.0 Use getExtensions()/setExtensions() instead.
- */
- public function extensions($extensions = null, $merge = true)
- {
- deprecationWarning(
- 'RouteCollection::extensions() is deprecated. ' .
- 'Use RouteCollection::setExtensions()/getExtensions() instead.'
- );
- if ($extensions !== null) {
- $this->setExtensions((array)$extensions, $merge);
- }
-
- return $this->getExtensions();
- }
-
/**
* Get the extensions that can be handled.
*
* @return string[] The valid extensions.
*/
- public function getExtensions()
+ public function getExtensions(): array
{
return $this->_extensions;
}
@@ -407,7 +379,7 @@ public function getExtensions()
* Defaults to `true`.
* @return $this
*/
- public function setExtensions(array $extensions, $merge = true)
+ public function setExtensions(array $extensions, bool $merge = true)
{
if ($merge) {
$extensions = array_unique(array_merge(
@@ -427,11 +399,11 @@ public function setExtensions(array $extensions, $merge = true)
* scope or any child scopes that share the same RouteCollection.
*
* @param string $name The name of the middleware. Used when applying middleware to a scope.
- * @param callable|string $middleware The middleware callable or class name to register.
+ * @param string|\Closure|\Psr\Http\Server\MiddlewareInterface $middleware The middleware to register.
* @return $this
* @throws \RuntimeException
*/
- public function registerMiddleware($name, $middleware)
+ public function registerMiddleware(string $name, $middleware)
{
$this->_middleware[$name] = $middleware;
@@ -446,7 +418,7 @@ public function registerMiddleware($name, $middleware)
* @return $this
* @throws \RuntimeException
*/
- public function middlewareGroup($name, array $middlewareNames)
+ public function middlewareGroup(string $name, array $middlewareNames)
{
if ($this->hasMiddleware($name)) {
$message = "Cannot add middleware group '$name'. A middleware by this name has already been registered.";
@@ -471,7 +443,7 @@ public function middlewareGroup($name, array $middlewareNames)
* @param string $name The name of the middleware group to check.
* @return bool
*/
- public function hasMiddlewareGroup($name)
+ public function hasMiddlewareGroup(string $name): bool
{
return array_key_exists($name, $this->_middlewareGroups);
}
@@ -482,7 +454,7 @@ public function hasMiddlewareGroup($name)
* @param string $name The name of the middleware to check.
* @return bool
*/
- public function hasMiddleware($name)
+ public function hasMiddleware(string $name): bool
{
return isset($this->_middleware[$name]);
}
@@ -493,39 +465,11 @@ public function hasMiddleware($name)
* @param string $name The name of the middleware to check.
* @return bool
*/
- public function middlewareExists($name)
+ public function middlewareExists(string $name): bool
{
return $this->hasMiddleware($name) || $this->hasMiddlewareGroup($name);
}
- /**
- * Apply a registered middleware(s) for the provided path
- *
- * @param string $path The URL path to register middleware for.
- * @param string[] $middleware The middleware names to add for the path.
- * @return $this
- * @throws \RuntimeException
- */
- public function applyMiddleware($path, array $middleware)
- {
- foreach ($middleware as $name) {
- if (!$this->hasMiddleware($name) && !$this->hasMiddlewareGroup($name)) {
- $message = "Cannot apply '$name' middleware or middleware group to path '$path'. It has not been registered.";
- throw new RuntimeException($message);
- }
- }
- // Matches route element pattern in Cake\Routing\Route
- $path = '#^' . preg_quote($path, '#') . '#';
- $path = preg_replace('/\\\\:([a-z0-9-_]+(?_middlewarePaths[$path])) {
- $this->_middlewarePaths[$path] = [];
- }
- $this->_middlewarePaths[$path] = array_merge($this->_middlewarePaths[$path], $middleware);
-
- return $this;
- }
-
/**
* Get an array of middleware given a list of names
*
@@ -534,7 +478,7 @@ public function applyMiddleware($path, array $middleware)
* the groups middleware will be flattened into the returned list.
* @throws \RuntimeException when a requested middleware does not exist.
*/
- public function getMiddleware(array $names)
+ public function getMiddleware(array $names): array
{
$out = [];
foreach ($names as $name) {
@@ -543,8 +487,10 @@ public function getMiddleware(array $names)
continue;
}
if (!$this->hasMiddleware($name)) {
- $message = "The middleware named '$name' has not been registered. Use registerMiddleware() to define it.";
- throw new RuntimeException($message);
+ throw new RuntimeException(sprintf(
+ "The middleware named '%s' has not been registered. Use registerMiddleware() to define it.",
+ $name
+ ));
}
$out[] = $this->_middleware[$name];
}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Router.php b/app/vendor/cakephp/cakephp/src/Routing/Router.php
index 713fbdc4a..d8ff527ad 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Router.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Router.php
@@ -1,4 +1,6 @@
*/
protected static $_urlFilters = [];
@@ -164,18 +157,27 @@ class Router
*/
protected static $_defaultExtensions = [];
+ /**
+ * Cache of parsed route paths
+ *
+ * @var array
+ */
+ protected static $_routePaths = [];
+
/**
* Get or set default route class.
*
* @param string|null $routeClass Class name.
* @return string|null
*/
- public static function defaultRouteClass($routeClass = null)
+ public static function defaultRouteClass(?string $routeClass = null): ?string
{
if ($routeClass === null) {
return static::$_defaultRouteClass;
}
static::$_defaultRouteClass = $routeClass;
+
+ return null;
}
/**
@@ -184,7 +186,7 @@ public static function defaultRouteClass($routeClass = null)
* @return array Named route elements
* @see \Cake\Routing\Router::$_namedExpressions
*/
- public static function getNamedExpressions()
+ public static function getNamedExpressions(): array
{
return static::$_namedExpressions;
}
@@ -194,9 +196,9 @@ public static function getNamedExpressions()
*
* Compatibility proxy to \Cake\Routing\RouteBuilder::connect() in the `/` scope.
*
- * @param string $route A string describing the template of the route
- * @param array|string $defaults An array describing the default route parameters. These parameters will be used by default
- * and can supply routing parameters that are not dynamic. See above.
+ * @param string|\Cake\Routing\Route\Route $route A string describing the template of the route
+ * @param array|string $defaults An array describing the default route parameters.
+ * These parameters will be used by default and can supply routing parameters that are not dynamic. See above.
* @param array $options An array matching the named elements in the route to regular expressions which that
* element should match. Also contains additional parameters such as which routed parameters should be
* shifted into the passed arguments, supplying patterns for routing parameters and supplying the name of a
@@ -206,296 +208,55 @@ public static function getNamedExpressions()
* @see \Cake\Routing\RouteBuilder::connect()
* @see \Cake\Routing\Router::scope()
*/
- public static function connect($route, $defaults = [], $options = [])
+ public static function connect($route, $defaults = [], $options = []): void
{
- static::$initialized = true;
- static::scope('/', function ($routes) use ($route, $defaults, $options) {
+ static::scope('/', function ($routes) use ($route, $defaults, $options): void {
/** @var \Cake\Routing\RouteBuilder $routes */
$routes->connect($route, $defaults, $options);
});
}
- /**
- * Connects a new redirection Route in the router.
- *
- * Compatibility proxy to \Cake\Routing\RouteBuilder::redirect() in the `/` scope.
- *
- * @param string $route A string describing the template of the route
- * @param array|string $url A URL to redirect to. Can be a string or a Cake array-based URL
- * @param array $options An array matching the named elements in the route to regular expressions which that
- * element should match. Also contains additional parameters such as which routed parameters should be
- * shifted into the passed arguments. As well as supplying patterns for routing parameters.
- * @return void
- * @see \Cake\Routing\RouteBuilder::redirect()
- * @deprecated 3.3.0 Use Router::scope() and RouteBuilder::redirect() instead.
- */
- public static function redirect($route, $url, $options = [])
- {
- deprecationWarning(
- 'Router::redirect() is deprecated. ' .
- 'Use Router::scope() and RouteBuilder::redirect() instead.'
- );
- if (is_string($url)) {
- $url = ['redirect' => $url];
- }
- if (!isset($options['routeClass'])) {
- $options['routeClass'] = 'Cake\Routing\Route\RedirectRoute';
- }
- static::connect($route, $url, $options);
- }
-
- /**
- * Generate REST resource routes for the given controller(s).
- *
- * Compatibility proxy to \Cake\Routing\RouteBuilder::resources(). Additional, compatibility
- * around prefixes and plugins and prefixes is handled by this method.
- *
- * A quick way to generate a default routes to a set of REST resources (controller(s)).
- *
- * ### Usage
- *
- * Connect resource routes for an app controller:
- *
- * ```
- * Router::mapResources('Posts');
- * ```
- *
- * Connect resource routes for the Comment controller in the
- * Comments plugin:
- *
- * ```
- * Router::mapResources('Comments.Comment');
- * ```
- *
- * Plugins will create lower_case underscored resource routes. e.g
- * `/comments/comment`
- *
- * Connect resource routes for the Posts controller in the
- * Admin prefix:
- *
- * ```
- * Router::mapResources('Posts', ['prefix' => 'admin']);
- * ```
- *
- * Prefixes will create lower_case underscored resource routes. e.g
- * `/admin/posts`
- *
- * ### Options:
- *
- * - 'id' - The regular expression fragment to use when matching IDs. By default, matches
- * integer values and UUIDs.
- * - 'prefix' - Routing prefix to use for the generated routes. Defaults to ''.
- * Using this option will create prefixed routes, similar to using Routing.prefixes.
- * - 'only' - Only connect the specific list of actions.
- * - 'actions' - Override the method names used for connecting actions.
- * - 'map' - Additional resource routes that should be connected. If you define 'only' and 'map',
- * make sure that your mapped methods are also in the 'only' list.
- * - 'path' - Change the path so it doesn't match the resource name. E.g ArticlesController
- * is available at `/posts`
- *
- * @param string|array $controller A controller name or array of controller names (i.e. "Posts" or "ListItems")
- * @param array $options Options to use when generating REST routes
- * @see \Cake\Routing\RouteBuilder::resources()
- * @deprecated 3.3.0 Use Router::scope() and RouteBuilder::resources() instead.
- * @return void
- */
- public static function mapResources($controller, $options = [])
- {
- deprecationWarning(
- 'Router::mapResources() is deprecated. ' .
- 'Use Router::scope() and RouteBuilder::resources() instead.'
- );
- foreach ((array)$controller as $name) {
- list($plugin, $name) = pluginSplit($name);
-
- $prefix = $pluginUrl = false;
- if (!empty($options['prefix'])) {
- $prefix = $options['prefix'];
- unset($options['prefix']);
- }
- if ($plugin) {
- $pluginUrl = Inflector::underscore($plugin);
- }
-
- $callback = function ($routes) use ($name, $options) {
- /** @var \Cake\Routing\RouteBuilder $routes */
- $routes->resources($name, $options);
- };
-
- if ($plugin && $prefix) {
- $path = '/' . implode('/', [$prefix, $pluginUrl]);
- $params = ['prefix' => $prefix, 'plugin' => $plugin];
- static::scope($path, $params, $callback);
-
- return;
- }
-
- if ($prefix) {
- static::prefix($prefix, $callback);
-
- return;
- }
-
- if ($plugin) {
- static::plugin($plugin, $callback);
-
- return;
- }
-
- static::scope('/', $callback);
-
- return;
- }
- }
-
- /**
- * Parses given URL string. Returns 'routing' parameters for that URL.
- *
- * @param string $url URL to be parsed.
- * @param string $method The HTTP method being used.
- * @return array Parsed elements from URL.
- * @throws \Cake\Routing\Exception\MissingRouteException When a route cannot be handled
- * @deprecated 3.4.0 Use Router::parseRequest() instead.
- */
- public static function parse($url, $method = '')
- {
- deprecationWarning(
- 'Router::parse() is deprecated. ' .
- 'Use Router::parseRequest() instead. This will require adopting the Http\Server library.'
- );
- if (!static::$initialized) {
- static::_loadRoutes();
- }
- if (strpos($url, '/') !== 0) {
- $url = '/' . $url;
- }
-
- return static::$_collection->parse($url, $method);
- }
-
/**
* Get the routing parameters for the request is possible.
*
- * @param \Psr\Http\Message\ServerRequestInterface $request The request to parse request data from.
+ * @param \Cake\Http\ServerRequest $request The request to parse request data from.
* @return array Parsed elements from URL.
* @throws \Cake\Routing\Exception\MissingRouteException When a route cannot be handled
*/
- public static function parseRequest(ServerRequestInterface $request)
+ public static function parseRequest(ServerRequest $request): array
{
- if (!static::$initialized) {
- static::_loadRoutes();
- }
-
return static::$_collection->parseRequest($request);
}
/**
- * Takes parameter and path information back from the Dispatcher, sets these
- * parameters as the current request parameters that are merged with URL arrays
- * created later in the request.
+ * Set current request instance.
*
- * Nested requests will create a stack of requests. You can remove requests using
- * Router::popRequest(). This is done automatically when using Object::requestAction().
- *
- * Will accept either a Cake\Http\ServerRequest object or an array of arrays. Support for
- * accepting arrays may be removed in the future.
- *
- * @param \Cake\Http\ServerRequest|array $request Parameters and path information or a Cake\Http\ServerRequest object.
+ * @param \Cake\Http\ServerRequest $request request object.
* @return void
- * @deprecatd 3.6.0 Support for arrays will be removed in 4.0.0
*/
- public static function setRequestInfo($request)
+ public static function setRequest(ServerRequest $request): void
{
- if ($request instanceof ServerRequest) {
- static::pushRequest($request);
- } else {
- deprecationWarning(
- 'Passing an array into Router::setRequestInfo() is deprecated. ' .
- 'Pass an instance of ServerRequest instead.'
- );
-
- $requestData = $request;
- $requestData += [[], []];
- $requestData[0] += [
- 'controller' => false,
- 'action' => false,
- 'plugin' => null,
- ];
- $request = new ServerRequest([
- 'params' => $requestData[0],
- 'url' => isset($requestData[1]['here']) ? $requestData[1]['here'] : '/',
- 'base' => isset($requestData[1]['base']) ? $requestData[1]['base'] : '',
- 'webroot' => isset($requestData[1]['webroot']) ? $requestData[1]['webroot'] : '/',
- ]);
- static::pushRequest($request);
- }
- }
+ static::$_request = $request;
- /**
- * Push a request onto the request stack. Pushing a request
- * sets the request context used when generating URLs.
- *
- * @param \Cake\Http\ServerRequest $request Request instance.
- * @return void
- */
- public static function pushRequest(ServerRequest $request)
- {
- static::$_requests[] = $request;
- static::setRequestContext($request);
- }
+ static::$_requestContext['_base'] = $request->getAttribute('base');
+ static::$_requestContext['params'] = $request->getAttribute('params', []);
- /**
- * Store the request context for a given request.
- *
- * @param \Psr\Http\Message\ServerRequestInterface $request The request instance.
- * @return void
- * @throws \InvalidArgumentException When parameter is an incorrect type.
- */
- public static function setRequestContext(ServerRequestInterface $request)
- {
$uri = $request->getUri();
- static::$_requestContext = [
- '_base' => $request->getAttribute('base'),
- '_port' => $uri->getPort(),
+ static::$_requestContext += [
'_scheme' => $uri->getScheme(),
'_host' => $uri->getHost(),
+ '_port' => $uri->getPort(),
];
}
/**
- * Pops a request off of the request stack. Used when doing requestAction
- *
- * @return \Cake\Http\ServerRequest The request removed from the stack.
- * @see \Cake\Routing\Router::pushRequest()
- * @see \Cake\Routing\RequestActionTrait::requestAction()
- */
- public static function popRequest()
- {
- $removed = array_pop(static::$_requests);
- $last = end(static::$_requests);
- if ($last) {
- static::setRequestContext($last);
- reset(static::$_requests);
- }
-
- return $removed;
- }
-
- /**
- * Get the current request object, or the first one.
+ * Get the current request object.
*
- * @param bool $current True to get the current request, or false to get the first one.
* @return \Cake\Http\ServerRequest|null
*/
- public static function getRequest($current = false)
+ public static function getRequest(): ?ServerRequest
{
- if ($current) {
- $request = end(static::$_requests);
-
- return $request ?: null;
- }
-
- return isset(static::$_requests[0]) ? static::$_requests[0] : null;
+ return static::$_request;
}
/**
@@ -504,11 +265,11 @@ public static function getRequest($current = false)
*
* @return void
*/
- public static function reload()
+ public static function reload(): void
{
if (empty(static::$_initialState)) {
static::$_collection = new RouteCollection();
- static::$_initialState = get_class_vars(get_called_class());
+ static::$_initialState = get_class_vars(static::class);
return;
}
@@ -537,11 +298,10 @@ public static function reload()
* @internal
* @return void
*/
- public static function resetRoutes()
+ public static function resetRoutes(): void
{
static::$_collection = new RouteCollection();
static::$_urlFilters = [];
- static::$initialized = false;
}
/**
@@ -572,8 +332,9 @@ public static function resetRoutes()
*
* @param callable $function The function to add
* @return void
+ * @psalm-param \Closure|callable-string $function
*/
- public static function addUrlFilter(callable $function)
+ public static function addUrlFilter(callable $function): void
{
static::$_urlFilters[] = $function;
}
@@ -586,19 +347,13 @@ public static function addUrlFilter(callable $function)
* @see \Cake\Routing\Router::url()
* @see \Cake\Routing\Router::addUrlFilter()
*/
- protected static function _applyUrlFilters($url)
+ protected static function _applyUrlFilters(array $url): array
{
- $request = static::getRequest(true);
- $e = null;
+ $request = static::getRequest();
foreach (static::$_urlFilters as $filter) {
try {
$url = $filter($url, $request);
- } catch (Exception $e) {
- // fall through
} catch (Throwable $e) {
- // fall through
- }
- if ($e !== null) {
if (is_array($filter)) {
$ref = new ReflectionMethod($filter[0], $filter[1]);
} else {
@@ -610,7 +365,7 @@ protected static function _applyUrlFilters($url)
$ref->getStartLine(),
$e->getMessage()
);
- throw new RuntimeException($message, $e->getCode(), $e);
+ throw new RuntimeException($message, (int)$e->getCode(), $e);
}
}
@@ -655,10 +410,23 @@ protected static function _applyUrlFilters($url)
* @return string Full translated URL with base path.
* @throws \Cake\Core\Exception\Exception When the route name is not found
*/
- public static function url($url = null, $full = false)
+ public static function url($url = null, bool $full = false): string
{
- if (!static::$initialized) {
- static::_loadRoutes();
+ $context = static::$_requestContext;
+ $request = static::getRequest();
+
+ if (!isset($context['_base'])) {
+ $context['_base'] = Configure::read('App.base') ?: '';
+ }
+
+ if (empty($url)) {
+ $here = $request ? $request->getRequestTarget() : '/';
+ $output = $context['_base'] . $here;
+ if ($full) {
+ $output = static::fullBaseUrl() . $output;
+ }
+
+ return $output;
}
$params = [
@@ -667,30 +435,19 @@ public static function url($url = null, $full = false)
'action' => 'index',
'_ext' => null,
];
- $here = $output = $frag = null;
-
- $context = static::$_requestContext;
- // In 4.x this should be replaced with state injected via setRequestContext
- $request = static::getRequest(true);
- if ($request) {
- $params = $request->getAttribute('params');
- $here = $request->getRequestTarget();
- $context['_base'] = $request->getAttribute('base');
- } elseif (!isset($context['_base'])) {
- $context['_base'] = Configure::read('App.base');
+ if (!empty($context['params'])) {
+ $params = $context['params'];
}
- if (empty($url)) {
- $output = $context['_base'] . (isset($here) ? $here : '/');
- if ($full) {
- $output = static::fullBaseUrl() . $output;
- }
+ $frag = '';
- return $output;
- }
if (is_array($url)) {
+ if (isset($url['_path'])) {
+ $url = self::unwrapShortString($url);
+ }
+
if (isset($url['_ssl'])) {
- $url['_scheme'] = ($url['_ssl'] === true) ? 'https' : 'http';
+ $url['_scheme'] = $url['_ssl'] === true ? 'https' : 'http';
}
if (isset($url['_full']) && $url['_full'] === true) {
@@ -707,7 +464,10 @@ public static function url($url = null, $full = false)
// Copy the current action if the controller is the current one.
if (
empty($url['action']) &&
- (empty($url['controller']) || $params['controller'] === $url['controller'])
+ (
+ empty($url['controller']) ||
+ $params['controller'] === $url['controller']
+ )
) {
$url['action'] = $params['action'];
}
@@ -728,7 +488,7 @@ public static function url($url = null, $full = false)
// If a full URL is requested with a scheme the host should default
// to App.fullBaseUrl to avoid corrupt URLs
if ($full && isset($url['_scheme']) && !isset($url['_host'])) {
- $url['_host'] = parse_url(static::fullBaseUrl(), PHP_URL_HOST);
+ $url['_host'] = $context['_host'];
}
$context['params'] = $params;
@@ -752,6 +512,7 @@ public static function url($url = null, $full = false)
}
$output = $context['_base'] . $url;
}
+
$protocol = preg_match('#^[a-z][a-z0-9+\-.]*\://#i', $output);
if ($protocol === 0) {
$output = str_replace('//', '/', '/' . $output);
@@ -763,6 +524,27 @@ public static function url($url = null, $full = false)
return $output . $frag;
}
+ /**
+ * Generate URL for route path.
+ *
+ * Route path examples:
+ * - Bookmarks::view
+ * - Admin/Bookmarks::view
+ * - Cms.Articles::edit
+ * - Vendor/Cms.Management/Admin/Articles::view
+ *
+ * @param string $path Route path specifying controller and action, optionally with plugin and prefix.
+ * @param array $params An array specifying any additional parameters.
+ * Can be also any special parameters supported by `Router::url()`.
+ * @param bool $full If true, the full base URL will be prepended to the result.
+ * Default is false.
+ * @return string Full translated URL with base path.
+ */
+ public static function pathUrl(string $path, array $params = [], bool $full = false): string
+ {
+ return static::url(['_path' => $path] + $params, $full);
+ }
+
/**
* Finds URL for specified action.
*
@@ -779,10 +561,10 @@ public static function url($url = null, $full = false)
* Default is false.
* @return bool
*/
- public static function routeExists($url = null, $full = false)
+ public static function routeExists($url = null, bool $full = false): bool
{
try {
- $route = static::url($url, $full);
+ static::url($url, $full);
return true;
} catch (MissingRouteException $e) {
@@ -805,15 +587,43 @@ public static function routeExists($url = null, $full = false)
* For example: `http://example.com`
* @return string
*/
- public static function fullBaseUrl($base = null)
+ public static function fullBaseUrl(?string $base = null): string
{
+ if ($base === null && static::$_fullBaseUrl !== null) {
+ return static::$_fullBaseUrl;
+ }
+
if ($base !== null) {
static::$_fullBaseUrl = $base;
Configure::write('App.fullBaseUrl', $base);
+ } else {
+ $base = (string)Configure::read('App.fullBaseUrl');
+
+ // If App.fullBaseUrl is empty but context is set from request through setRequest()
+ if (!$base && !empty(static::$_requestContext['_host'])) {
+ $base = sprintf(
+ '%s://%s',
+ static::$_requestContext['_scheme'],
+ static::$_requestContext['_host']
+ );
+ if (!empty(static::$_requestContext['_port'])) {
+ $base .= ':' . static::$_requestContext['_port'];
+ }
+
+ Configure::write('App.fullBaseUrl', $base);
+
+ return static::$_fullBaseUrl = $base;
+ }
+
+ static::$_fullBaseUrl = $base;
}
- if (empty(static::$_fullBaseUrl)) {
- static::$_fullBaseUrl = Configure::read('App.fullBaseUrl');
- }
+
+ $parts = parse_url(static::$_fullBaseUrl);
+ static::$_requestContext = [
+ '_scheme' => $parts['scheme'] ?? null,
+ '_host' => $parts['host'] ?? null,
+ '_port' => $parts['port'] ?? null,
+ ] + static::$_requestContext;
return static::$_fullBaseUrl;
}
@@ -822,47 +632,28 @@ public static function fullBaseUrl($base = null)
* Reverses a parsed parameter array into an array.
*
* Works similarly to Router::url(), but since parsed URL's contain additional
- * 'pass' as well as 'url.url' keys. Those keys need to be specially
+ * keys like 'pass', '_matchedRoute' etc. those keys need to be specially
* handled in order to reverse a params array into a string URL.
*
- * This will strip out 'autoRender', 'bare', 'requested', and 'return' param names as those
- * are used for CakePHP internals and should not normally be part of an output URL.
- *
* @param \Cake\Http\ServerRequest|array $params The params array or
* Cake\Http\ServerRequest object that needs to be reversed.
* @return array The URL array ready to be used for redirect or HTML link.
*/
- public static function reverseToArray($params)
+ public static function reverseToArray($params): array
{
- $url = [];
if ($params instanceof ServerRequest) {
- $url = $params->getQueryParams();
+ $queryString = $params->getQueryParams();
$params = $params->getAttribute('params');
- } elseif (isset($params['url'])) {
- $url = $params['url'];
+ $params['?'] = $queryString;
}
- $pass = isset($params['pass']) ? $params['pass'] : [];
+ $pass = $params['pass'] ?? [];
unset(
$params['pass'],
- $params['paging'],
- $params['models'],
- $params['url'],
- $url['url'],
- $params['autoRender'],
- $params['bare'],
- $params['requested'],
- $params['return'],
- $params['isAjax'],
- $params['_Token'],
- $params['_csrfToken'],
$params['_matchedRoute'],
$params['_name']
);
$params = array_merge($params, $pass);
- if (!empty($url)) {
- $params['?'] = $url;
- }
return $params;
}
@@ -871,19 +662,16 @@ public static function reverseToArray($params)
* Reverses a parsed parameter array into a string.
*
* Works similarly to Router::url(), but since parsed URL's contain additional
- * 'pass' as well as 'url.url' keys. Those keys need to be specially
+ * keys like 'pass', '_matchedRoute' etc. those keys need to be specially
* handled in order to reverse a params array into a string URL.
*
- * This will strip out 'autoRender', 'bare', 'requested', and 'return' param names as those
- * are used for CakePHP internals and should not normally be part of an output URL.
- *
* @param \Cake\Http\ServerRequest|array $params The params array or
* Cake\Http\ServerRequest object that needs to be reversed.
* @param bool $full Set to true to include the full URL including the
* protocol when reversing the URL.
* @return string The string that is the reversed result of the array
*/
- public static function reverse($params, $full = false)
+ public static function reverse($params, $full = false): string
{
$params = static::reverseToArray($params);
@@ -899,7 +687,7 @@ public static function reverse($params, $full = false)
* @param array|string $url URL to normalize Either an array or a string URL.
* @return string Normalized URL
*/
- public static function normalize($url = '/')
+ public static function normalize($url = '/'): string
{
if (is_array($url)) {
$url = static::url($url);
@@ -949,14 +737,10 @@ public static function normalize($url = '/')
* Defaults to `true`.
* @return string[] Array of extensions Router is configured to parse.
*/
- public static function extensions($extensions = null, $merge = true)
+ public static function extensions($extensions = null, $merge = true): array
{
$collection = static::$_collection;
if ($extensions === null) {
- if (!static::$initialized) {
- static::_loadRoutes();
- }
-
return array_unique(array_merge(static::$_defaultExtensions, $collection->getExtensions()));
}
$extensions = (array)$extensions;
@@ -967,66 +751,6 @@ public static function extensions($extensions = null, $merge = true)
return static::$_defaultExtensions = $extensions;
}
- /**
- * Provides legacy support for named parameters on incoming URLs.
- *
- * Checks the passed parameters for elements containing `$options['separator']`
- * Those parameters are split and parsed as if they were old style named parameters.
- *
- * The parsed parameters will be moved from params['pass'] to params['named'].
- *
- * ### Options
- *
- * - `separator` The string to use as a separator. Defaults to `:`.
- *
- * @param \Cake\Http\ServerRequest $request The request object to modify.
- * @param array $options The array of options.
- * @return \Cake\Http\ServerRequest The modified request
- * @deprecated 3.3.0 Named parameter backwards compatibility will be removed in 4.0.
- */
- public static function parseNamedParams(ServerRequest $request, array $options = [])
- {
- deprecationWarning(
- 'Router::parseNamedParams() is deprecated. ' .
- '2.x backwards compatible named parameter support will be removed in 4.0'
- );
- $options += ['separator' => ':'];
- if (!$request->getParam('pass')) {
- return $request->withParam('named', []);
- }
- $named = [];
- $pass = $request->getParam('pass');
- foreach ((array)$pass as $key => $value) {
- if (strpos($value, $options['separator']) === false) {
- continue;
- }
- unset($pass[$key]);
- list($key, $value) = explode($options['separator'], $value, 2);
-
- if (preg_match_all('/\[([A-Za-z0-9_-]+)?\]/', $key, $matches, PREG_SET_ORDER)) {
- $matches = array_reverse($matches);
- $parts = explode('[', $key);
- $key = array_shift($parts);
- $arr = $value;
- foreach ($matches as $match) {
- if (empty($match[1])) {
- $arr = [$arr];
- } else {
- $arr = [
- $match[1] => $arr,
- ];
- }
- }
- $value = $arr;
- }
- $named = array_merge_recursive($named, [$key => $value]);
- }
-
- return $request
- ->withParam('pass', $pass)
- ->withParam('named', $named);
- }
-
/**
* Create a RouteBuilder for the provided path.
*
@@ -1034,7 +758,7 @@ public static function parseNamedParams(ServerRequest $request, array $options =
* @param array $options The options for the builder
* @return \Cake\Routing\RouteBuilder
*/
- public static function createRouteBuilder($path, array $options = [])
+ public static function createRouteBuilder(string $path, array $options = []): RouteBuilder
{
$defaults = [
'routeClass' => static::defaultRouteClass(),
@@ -1090,7 +814,7 @@ public static function createRouteBuilder($path, array $options = [])
* @throws \InvalidArgumentException When an invalid callable is provided.
* @return void
*/
- public static function scope($path, $params = [], $callback = null)
+ public static function scope(string $path, $params = [], $callback = null): void
{
$options = [];
if (is_array($params)) {
@@ -1108,14 +832,14 @@ public static function scope($path, $params = [], $callback = null)
* relevant prefix information.
*
* The path parameter is used to generate the routing parameter name.
- * For example a path of `admin` would result in `'prefix' => 'admin'` being
+ * For example a path of `admin` would result in `'prefix' => 'Admin'` being
* applied to all connected routes.
*
- * The prefix name will be inflected to the underscore version to create
+ * The prefix name will be inflected to the dasherized version to create
* the routing path. If you want a custom path name, use the `path` option.
*
* You can re-open a prefix as many times as necessary, as well as nest prefixes.
- * Nested prefixes will result in prefix values like `admin/api` which translates
+ * Nested prefixes will result in prefix values like `Admin/Api` which translates
* to the `Controller\Admin\Api\` namespace.
*
* @param string $name The prefix name to use.
@@ -1124,22 +848,17 @@ public static function scope($path, $params = [], $callback = null)
* @param callable|null $callback The callback to invoke that builds the prefixed routes.
* @return void
*/
- public static function prefix($name, $params = [], $callback = null)
+ public static function prefix(string $name, $params = [], $callback = null): void
{
- if ($callback === null) {
+ if (!is_array($params)) {
$callback = $params;
$params = [];
}
- $name = Inflector::underscore($name);
- if (empty($params['path'])) {
- $path = '/' . $name;
- } else {
- $path = $params['path'];
- unset($params['path']);
- }
+ $path = $params['path'] ?? '/' . Inflector::dasherize($name);
+ unset($params['path']);
- $params = array_merge($params, ['prefix' => $name]);
+ $params = array_merge($params, ['prefix' => Inflector::camelize($name)]);
static::scope($path, $params, $callback);
}
@@ -1149,7 +868,7 @@ public static function prefix($name, $params = [], $callback = null)
* This method creates a scoped route collection that includes
* relevant plugin information.
*
- * The plugin name will be inflected to the underscore version to create
+ * The plugin name will be inflected to the dasherized version to create
* the routing path. If you want a custom path name, use the `path` option.
*
* Routes connected in the scoped collection will have the correct path segment
@@ -1161,20 +880,18 @@ public static function prefix($name, $params = [], $callback = null)
* Only required when $options is defined
* @return void
*/
- public static function plugin($name, $options = [], $callback = null)
+ public static function plugin(string $name, $options = [], $callback = null): void
{
- if ($callback === null) {
+ if (!is_array($options)) {
$callback = $options;
$options = [];
}
$params = ['plugin' => $name];
- if (empty($options['path'])) {
- $options['path'] = '/' . Inflector::underscore($name);
- }
+ $path = $options['path'] ?? '/' . Inflector::dasherize($name);
if (isset($options['_namePrefix'])) {
$params['_namePrefix'] = $options['_namePrefix'];
}
- static::scope($options['path'], $params, $callback);
+ static::scope($path, $params, $callback);
}
/**
@@ -1182,12 +899,8 @@ public static function plugin($name, $options = [], $callback = null)
*
* @return \Cake\Routing\Route\Route[]
*/
- public static function routes()
+ public static function routes(): array
{
- if (!static::$initialized) {
- static::_loadRoutes();
- }
-
return static::$_collection->routes();
}
@@ -1196,7 +909,7 @@ public static function routes()
*
* @return \Cake\Routing\RouteCollection
*/
- public static function getRouteCollection()
+ public static function getRouteCollection(): RouteCollection
{
return static::$_collection;
}
@@ -1204,24 +917,82 @@ public static function getRouteCollection()
/**
* Set the RouteCollection inside the Router
*
- * @param RouteCollection $routeCollection route collection
+ * @param \Cake\Routing\RouteCollection $routeCollection route collection
* @return void
*/
- public static function setRouteCollection($routeCollection)
+ public static function setRouteCollection(RouteCollection $routeCollection): void
{
static::$_collection = $routeCollection;
- static::$initialized = true;
}
/**
- * Loads route configuration
+ * Inject route defaults from `_path` key
*
- * @deprecated 3.5.0 Routes will be loaded via the Application::routes() hook in 4.0.0
- * @return void
+ * @param array $url Route array with `_path` key
+ * @return array
+ */
+ protected static function unwrapShortString(array $url)
+ {
+ foreach (['plugin', 'prefix', 'controller', 'action'] as $key) {
+ if (array_key_exists($key, $url)) {
+ throw new InvalidArgumentException(
+ "`$key` cannot be used when defining route targets with a string route path."
+ );
+ }
+ }
+ $url += static::parseRoutePath($url['_path']);
+ $url += [
+ 'plugin' => false,
+ 'prefix' => false,
+ ];
+ unset($url['_path']);
+
+ return $url;
+ }
+
+ /**
+ * Parse a string route path
+ *
+ * String examples:
+ * - Bookmarks::view
+ * - Admin/Bookmarks::view
+ * - Cms.Articles::edit
+ * - Vendor/Cms.Management/Admin/Articles::view
+ *
+ * @param string $url Route path in [Plugin.][Prefix/]Controller::action format
+ * @return string[]
*/
- protected static function _loadRoutes()
+ public static function parseRoutePath(string $url): array
{
- static::$initialized = true;
- include CONFIG . 'routes.php';
+ if (isset(static::$_routePaths[$url])) {
+ return static::$_routePaths[$url];
+ }
+
+ $regex = '#^
+ (?:(?[a-z0-9]+(?:/[a-z0-9]+)*)\.)?
+ (?:(?[a-z0-9]+(?:/[a-z0-9]+)*)/)?
+ (?[a-z0-9]+)
+ ::
+ (?[a-z0-9_]+)
+ $#ix';
+
+ if (!preg_match($regex, $url, $matches)) {
+ throw new InvalidArgumentException("Could not parse a string route path `{$url}`.");
+ }
+
+ $defaults = [];
+
+ if ($matches['plugin'] !== '') {
+ $defaults['plugin'] = $matches['plugin'];
+ }
+ if ($matches['prefix'] !== '') {
+ $defaults['prefix'] = $matches['prefix'];
+ }
+ $defaults['controller'] = $matches['controller'];
+ $defaults['action'] = $matches['action'];
+
+ static::$_routePaths[$url] = $defaults;
+
+ return $defaults;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/RoutingApplicationInterface.php b/app/vendor/cakephp/cakephp/src/Routing/RoutingApplicationInterface.php
new file mode 100644
index 000000000..d2b98cc9f
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Routing/RoutingApplicationInterface.php
@@ -0,0 +1,33 @@
+addSubcommand('list_prefixes', [
- 'help' => 'Show a list of all defined cache prefixes.',
- ]);
- $parser->addSubcommand('clear_all', [
- 'help' => 'Clear all caches.',
- ]);
- $parser->addSubcommand('clear', [
- 'help' => 'Clear the cache for a specified prefix.',
- 'parser' => [
- 'description' => [
- 'Clear the cache for a particular prefix.',
- 'For example, `cake cache clear _cake_model_` will clear the model cache',
- 'Use `cake cache list_prefixes` to list available prefixes',
- ],
- 'arguments' => [
- 'prefix' => [
- 'help' => 'The cache prefix to be cleared.',
- 'required' => true,
- ],
- ],
- ],
- ]);
-
- return $parser;
- }
-
- /**
- * Clear metadata.
- *
- * @param string|null $prefix The cache prefix to be cleared.
- * @throws \Cake\Console\Exception\StopException
- * @return void
- */
- public function clear($prefix = null)
- {
- try {
- $engine = Cache::engine($prefix);
- Cache::clear(false, $prefix);
- if ($engine instanceof ApcuEngine) {
- $this->warn("ApcuEngine detected: Cleared $prefix CLI cache successfully " .
- "but $prefix web cache must be cleared separately.");
- } elseif ($engine instanceof WincacheEngine) {
- $this->warn("WincacheEngine detected: Cleared $prefix CLI cache successfully " .
- "but $prefix web cache must be cleared separately.");
- } else {
- $this->out("Cleared $prefix cache ");
- }
- } catch (InvalidArgumentException $e) {
- $this->abort($e->getMessage());
- }
- }
-
- /**
- * Clear metadata.
- *
- * @return void
- */
- public function clearAll()
- {
- $prefixes = Cache::configured();
- foreach ($prefixes as $prefix) {
- $this->clear($prefix);
- }
- }
-
- /**
- * Show a list of all defined cache prefixes.
- *
- * @return void
- */
- public function listPrefixes()
- {
- $prefixes = Cache::configured();
- foreach ($prefixes as $prefix) {
- $this->out($prefix);
- }
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/CommandListShell.php b/app/vendor/cakephp/cakephp/src/Shell/CommandListShell.php
deleted file mode 100644
index c00701880..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/CommandListShell.php
+++ /dev/null
@@ -1,170 +0,0 @@
-out();
- $this->out(sprintf('Welcome to CakePHP %s Console ', 'v' . Configure::version()));
- $this->hr();
- $this->out(sprintf('App : %s', APP_DIR));
- $this->out(sprintf('Path: %s', APP));
- $this->out(sprintf('PHP : %s', PHP_VERSION));
- $this->hr();
- }
-
- /**
- * startup
- *
- * @return void
- */
- public function startup()
- {
- if (!$this->param('xml') && !$this->param('version')) {
- parent::startup();
- }
- }
-
- /**
- * Main function Prints out the list of shells.
- *
- * @return void
- */
- public function main()
- {
- if (!$this->param('xml') && !$this->param('version')) {
- $this->out('Current Paths: ', 2);
- $this->out('* app: ' . APP_DIR . DIRECTORY_SEPARATOR);
- $this->out('* root: ' . ROOT . DIRECTORY_SEPARATOR);
- $this->out('* core: ' . CORE_PATH);
- $this->out('');
-
- $this->out('Available Shells: ', 2);
- }
-
- if ($this->param('version')) {
- $this->out(Configure::version());
-
- return;
- }
-
- $shellList = $this->Command->getShellList();
- if (!$shellList) {
- return;
- }
-
- if (!$this->param('xml')) {
- $this->_asText($shellList);
- } else {
- $this->_asXml($shellList);
- }
- }
-
- /**
- * Output text.
- *
- * @param array $shellList The shell list.
- * @return void
- */
- protected function _asText($shellList)
- {
- foreach ($shellList as $plugin => $commands) {
- sort($commands);
- $this->out(sprintf('[%s ] %s', $plugin, implode(', ', $commands)));
- $this->out();
- }
-
- $this->out('To run an app or core command, type `cake shell_name [args]` ');
- $this->out('To run a plugin command, type `cake Plugin.shell_name [args]` ');
- $this->out('To get help on a specific command, type `cake shell_name --help` ', 2);
- }
-
- /**
- * Output as XML
- *
- * @param array $shellList The shell list.
- * @return void
- */
- protected function _asXml($shellList)
- {
- $plugins = Plugin::loaded();
- $shells = new SimpleXMLElement(' ');
- foreach ($shellList as $plugin => $commands) {
- foreach ($commands as $command) {
- $callable = $command;
- if (in_array($plugin, $plugins)) {
- $callable = Inflector::camelize($plugin) . '.' . $command;
- }
-
- $shell = $shells->addChild('shell');
- $shell->addAttribute('name', $command);
- $shell->addAttribute('call_as', $callable);
- $shell->addAttribute('provider', $plugin);
- $shell->addAttribute('help', $callable . ' -h');
- }
- }
- $this->_io->setOutputAs(ConsoleOutput::RAW);
- $this->out($shells->saveXML());
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->setDescription(
- 'Get the list of available shells for this CakePHP application.'
- )->addOption('xml', [
- 'help' => 'Get the listing as XML.',
- 'boolean' => true,
- ])->addOption('version', [
- 'help' => 'Prints the currently installed version of CakePHP. (deprecated - use `cake --version` instead)',
- 'boolean' => true,
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/CompletionShell.php b/app/vendor/cakephp/cakephp/src/Shell/CompletionShell.php
deleted file mode 100644
index 3a9da8d7e..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/CompletionShell.php
+++ /dev/null
@@ -1,173 +0,0 @@
-out($this->getOptionParser()->help());
- }
-
- /**
- * list commands
- *
- * @return int|bool|null Returns the number of bytes returned from writing to stdout.
- */
- public function commands()
- {
- $options = $this->Command->commands();
-
- return $this->_output($options);
- }
-
- /**
- * list options for the named command
- *
- * @return int|bool|null Returns the number of bytes returned from writing to stdout.
- */
- public function options()
- {
- $commandName = $subCommandName = '';
- if (!empty($this->args[0])) {
- $commandName = $this->args[0];
- }
- if (!empty($this->args[1])) {
- $subCommandName = $this->args[1];
- }
- $options = $this->Command->options($commandName, $subCommandName);
-
- return $this->_output($options);
- }
-
- /**
- * list subcommands for the named command
- *
- * @return int|bool|null Returns the number of bytes returned from writing to stdout.
- * @throws \ReflectionException
- */
- public function subcommands()
- {
- if (!$this->args) {
- return $this->_output();
- }
-
- $options = $this->Command->subCommands($this->args[0]);
-
- return $this->_output($options);
- }
-
- /**
- * Guess autocomplete from the whole argument string
- *
- * @return int|bool|null Returns the number of bytes returned from writing to stdout.
- */
- public function fuzzy()
- {
- return $this->_output();
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->setDescription(
- 'Used by shells like bash to autocomplete command name, options and arguments'
- )->addSubcommand('commands', [
- 'help' => 'Output a list of available commands',
- 'parser' => [
- 'description' => 'List all available',
- ],
- ])->addSubcommand('subcommands', [
- 'help' => 'Output a list of available subcommands',
- 'parser' => [
- 'description' => 'List subcommands for a command',
- 'arguments' => [
- 'command' => [
- 'help' => 'The command name',
- 'required' => false,
- ],
- ],
- ],
- ])->addSubcommand('options', [
- 'help' => 'Output a list of available options',
- 'parser' => [
- 'description' => 'List options',
- 'arguments' => [
- 'command' => [
- 'help' => 'The command name',
- 'required' => false,
- ],
- 'subcommand' => [
- 'help' => 'The subcommand name',
- 'required' => false,
- ],
- ],
- ],
- ])->addSubcommand('fuzzy', [
- 'help' => 'Guess autocomplete',
- ])->setEpilog([
- 'This command is not intended to be called manually',
- ]);
-
- return $parser;
- }
-
- /**
- * Emit results as a string, space delimited
- *
- * @param array $options The options to output
- * @return int|bool|null Returns the number of bytes returned from writing to stdout.
- */
- protected function _output($options = [])
- {
- if ($options) {
- return $this->out(implode(' ', $options));
- }
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/Helper/ProgressHelper.php b/app/vendor/cakephp/cakephp/src/Shell/Helper/ProgressHelper.php
index 5522a28d4..9b49d98dd 100644
--- a/app/vendor/cakephp/cakephp/src/Shell/Helper/ProgressHelper.php
+++ b/app/vendor/cakephp/cakephp/src/Shell/Helper/ProgressHelper.php
@@ -1,4 +1,6 @@
null];
if (isset($args[0])) {
@@ -130,7 +132,7 @@ public function draw()
{
$numberLen = strlen(' 100%');
$complete = round($this->_progress / $this->_total, 2);
- $barLen = ($this->_width - $numberLen) * ($this->_progress / $this->_total);
+ $barLen = ($this->_width - $numberLen) * $this->_progress / $this->_total;
$bar = '';
if ($barLen > 1) {
$bar = str_repeat('=', (int)$barLen - 1) . '>';
diff --git a/app/vendor/cakephp/cakephp/src/Shell/Helper/TableHelper.php b/app/vendor/cakephp/cakephp/src/Shell/Helper/TableHelper.php
index ae3edeef9..8949aabba 100644
--- a/app/vendor/cakephp/cakephp/src/Shell/Helper/TableHelper.php
+++ b/app/vendor/cakephp/cakephp/src/Shell/Helper/TableHelper.php
@@ -1,4 +1,6 @@
$v) {
$columnLength = $this->_cellWidth($v);
- if ($columnLength >= (isset($widths[$k]) ? $widths[$k] : 0)) {
+ if ($columnLength >= ($widths[$k] ?? 0)) {
$widths[$k] = $columnLength;
}
}
@@ -59,7 +61,7 @@ protected function _calculateWidths($rows)
* @param string|null $text The text to calculate a width for.
* @return int The width of the textual content in visible characters.
*/
- protected function _cellWidth($text)
+ protected function _cellWidth(?string $text): int
{
if ($text === null) {
return 0;
@@ -69,7 +71,6 @@ protected function _cellWidth($text)
return mb_strwidth($text);
}
- /** @var array $styles */
$styles = $this->_io->styles();
$tags = implode('|', array_keys($styles));
$text = preg_replace('#?(?:' . $tags . ')>#', '', $text);
@@ -83,7 +84,7 @@ protected function _cellWidth($text)
* @param int[] $widths The widths of each column to output.
* @return void
*/
- protected function _rowSeparator($widths)
+ protected function _rowSeparator(array $widths): void
{
$out = '';
foreach ($widths as $column) {
@@ -101,7 +102,7 @@ protected function _rowSeparator($widths)
* @param array $options Options to be passed.
* @return void
*/
- protected function _render(array $row, $widths, $options = [])
+ protected function _render(array $row, array $widths, array $options = []): void
{
if (count($row) === 0) {
return;
@@ -128,9 +129,9 @@ protected function _render(array $row, $widths, $options = [])
* @param array $rows The data to render out.
* @return void
*/
- public function output($rows)
+ public function output(array $rows): void
{
- if (!is_array($rows) || count($rows) === 0) {
+ if (empty($rows)) {
return;
}
@@ -143,7 +144,7 @@ public function output($rows)
$this->_rowSeparator($widths);
}
- if (!$rows) {
+ if (empty($rows)) {
return;
}
@@ -165,7 +166,7 @@ public function output($rows)
* @param string $style The style to be applied
* @return string
*/
- protected function _addStyle($text, $style)
+ protected function _addStyle(string $text, string $style): string
{
return '<' . $style . '>' . $text . '' . $style . '>';
}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/I18nShell.php b/app/vendor/cakephp/cakephp/src/Shell/I18nShell.php
deleted file mode 100644
index 5e9360eff..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/I18nShell.php
+++ /dev/null
@@ -1,168 +0,0 @@
-out('I18n Shell ');
- $this->hr();
- $this->out('[E]xtract POT file from sources');
- $this->out('[I]nitialize a language from POT file');
- $this->out('[H]elp');
- $this->out('[Q]uit');
-
- $choice = strtolower($this->in('What would you like to do?', ['E', 'I', 'H', 'Q']));
- switch ($choice) {
- case 'e':
- $this->Extract->main();
- break;
- case 'i':
- $this->init();
- break;
- case 'h':
- $this->out($this->OptionParser->help());
- break;
- case 'q':
- $this->_stop();
-
- return;
- default:
- $this->out('You have made an invalid selection. Please choose a command to execute by entering E, I, H, or Q.');
- }
- $this->hr();
- $this->main();
- }
-
- /**
- * Inits PO file from POT file.
- *
- * @param string|null $language Language code to use.
- * @return void
- * @throws \Cake\Console\Exception\StopException
- */
- public function init($language = null)
- {
- if (!$language) {
- $language = $this->in('Please specify language code, e.g. `en`, `eng`, `en_US` etc.');
- }
- if (strlen($language) < 2) {
- $this->abort('Invalid language code. Valid is `en`, `eng`, `en_US` etc.');
- }
-
- $this->_paths = App::path('Locale');
- if ($this->param('plugin')) {
- $plugin = Inflector::camelize($this->param('plugin'));
- $this->_paths = App::path('Locale', $plugin);
- }
-
- $response = $this->in('What folder?', null, rtrim($this->_paths[0], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR);
- $sourceFolder = rtrim($response, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
- $targetFolder = $sourceFolder . $language . DIRECTORY_SEPARATOR;
- if (!is_dir($targetFolder)) {
- mkdir($targetFolder, 0775, true);
- }
-
- $count = 0;
- $iterator = new DirectoryIterator($sourceFolder);
- foreach ($iterator as $fileinfo) {
- if (!$fileinfo->isFile()) {
- continue;
- }
- $filename = $fileinfo->getFilename();
- $newFilename = $fileinfo->getBasename('.pot');
- $newFilename .= '.po';
-
- $this->createFile($targetFolder . $newFilename, file_get_contents($sourceFolder . $filename));
- $count++;
- }
-
- $this->out('Generated ' . $count . ' PO files in ' . $targetFolder);
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- * @throws \Cake\Console\Exception\ConsoleException
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
- $initParser = [
- 'options' => [
- 'plugin' => [
- 'help' => 'Plugin name.',
- 'short' => 'p',
- ],
- 'force' => [
- 'help' => 'Force overwriting.',
- 'short' => 'f',
- 'boolean' => true,
- ],
- ],
- 'arguments' => [
- 'language' => [
- 'help' => 'Two-letter language code.',
- ],
- ],
- ];
-
- $parser->setDescription(
- 'I18n Shell generates .pot files(s) with translations.'
- )->addSubcommand('extract', [
- 'help' => 'Extract the po translations from your application',
- 'parser' => $this->Extract->getOptionParser(),
- ])
- ->addSubcommand('init', [
- 'help' => 'Init PO language file from POT file',
- 'parser' => $initParser,
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/OrmCacheShell.php b/app/vendor/cakephp/cakephp/src/Shell/OrmCacheShell.php
deleted file mode 100644
index 03762e553..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/OrmCacheShell.php
+++ /dev/null
@@ -1,30 +0,0 @@
-out($loaded);
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->setDescription('Plugin Shell perform various tasks related to plugin.')
- ->addSubcommand('assets', [
- 'help' => 'Symlink / copy plugin assets to app\'s webroot',
- 'parser' => $this->Assets->getOptionParser(),
- ])
- ->addSubcommand('loaded', [
- 'help' => 'Lists all loaded plugins',
- 'parser' => $parser,
- ])
- ->addSubcommand('load', [
- 'help' => 'Loads a plugin',
- 'parser' => $this->Load->getOptionParser(),
- ])
- ->addSubcommand('unload', [
- 'help' => 'Unloads a plugin',
- 'parser' => $this->Unload->getOptionParser(),
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/RoutesShell.php b/app/vendor/cakephp/cakephp/src/Shell/RoutesShell.php
deleted file mode 100644
index 9f1f736c0..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/RoutesShell.php
+++ /dev/null
@@ -1,164 +0,0 @@
-options['_name']) ? $route->options['_name'] : $route->getName();
- ksort($route->defaults);
- $output[] = [$name, $route->template, json_encode($route->defaults)];
- }
- $this->helper('table')->output($output);
- $this->out();
- }
-
- /**
- * Checks a url for the route that will be applied.
- *
- * @param string $url The URL to parse
- * @return bool Success
- */
- public function check($url)
- {
- try {
- $request = new ServerRequest(['url' => $url]);
- $route = Router::parseRequest($request);
- $name = null;
- foreach (Router::routes() as $r) {
- if ($r->match($route)) {
- $name = isset($r->options['_name']) ? $r->options['_name'] : $r->getName();
- break;
- }
- }
-
- unset($route['_matchedRoute']);
- ksort($route);
-
- $output = [
- ['Route name', 'URI template', 'Defaults'],
- [$name, $url, json_encode($route)],
- ];
- $this->helper('table')->output($output);
- $this->out();
- } catch (RedirectException $e) {
- $output = [
- ['URI template', 'Redirect'],
- [$url, $e->getMessage()],
- ];
- $this->helper('table')->output($output);
- $this->out();
- } catch (MissingRouteException $e) {
- $this->warn("'$url' did not match any routes.");
- $this->out();
-
- return false;
- }
-
- return true;
- }
-
- /**
- * Generate a URL based on a set of parameters
- *
- * Takes variadic arguments of key/value pairs.
- *
- * @return bool Success
- */
- public function generate()
- {
- try {
- $args = $this->_splitArgs($this->args);
- $url = Router::url($args);
- $this->out("> $url");
- $this->out();
- } catch (MissingRouteException $e) {
- $this->err('The provided parameters do not match any routes. ');
- $this->out();
-
- return false;
- }
-
- return true;
- }
-
- /**
- * Get the option parser.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
- $parser->setDescription(
- 'Get the list of routes connected in this application. ' .
- 'This tool also lets you test URL generation and URL parsing.'
- )->addSubcommand('check', [
- 'help' => 'Check a URL string against the routes. ' .
- 'Will output the routing parameters the route resolves to.',
- ])->addSubcommand('generate', [
- 'help' => 'Check a routing array against the routes. ' .
- "Will output the URL if there is a match.\n\n" .
- 'Routing parameters should be supplied in a key:value format. ' .
- 'For example `controller:Articles action:view 2`',
- ]);
-
- return $parser;
- }
-
- /**
- * Split the CLI arguments into a hash.
- *
- * @param array $args The arguments to split.
- * @return array
- */
- protected function _splitArgs($args)
- {
- $out = [];
- foreach ($args as $arg) {
- if (strpos($arg, ':') !== false) {
- list($key, $value) = explode(':', $arg);
- if (in_array($value, ['true', 'false'])) {
- $value = $value === 'true';
- }
- $out[$key] = $value;
- } else {
- $out[] = $arg;
- }
- }
-
- return $out;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/SchemaCacheShell.php b/app/vendor/cakephp/cakephp/src/Shell/SchemaCacheShell.php
deleted file mode 100644
index b9b2658de..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/SchemaCacheShell.php
+++ /dev/null
@@ -1,114 +0,0 @@
-_getSchemaCache();
- $tables = $cache->build($name);
-
- foreach ($tables as $table) {
- $this->verbose(sprintf('Cached "%s"', $table));
- }
-
- $this->out('Cache build complete ');
-
- return true;
- }
-
- /**
- * Clear metadata.
- *
- * @param string|null $name The name of the table to clear cache data for.
- * @return bool
- */
- public function clear($name = null)
- {
- $cache = $this->_getSchemaCache();
- $tables = $cache->clear($name);
-
- foreach ($tables as $table) {
- $this->verbose(sprintf('Cleared "%s"', $table));
- }
-
- $this->out('Cache clear complete ');
-
- return true;
- }
-
- /**
- * Gets the Schema Cache instance
- *
- * @return \Cake\Database\SchemaCache
- */
- protected function _getSchemaCache()
- {
- try {
- $connection = ConnectionManager::get($this->params['connection']);
-
- return new SchemaCache($connection);
- } catch (RuntimeException $e) {
- $this->abort($e->getMessage());
- }
- }
-
- /**
- * Get the option parser for this shell.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
- $parser->addSubcommand('clear', [
- 'help' => 'Clear all metadata caches for the connection. If a ' .
- 'table name is provided, only that table will be removed.',
- ])->addSubcommand('build', [
- 'help' => 'Build all metadata caches for the connection. If a ' .
- 'table name is provided, only that table will be cached.',
- ])->addOption('connection', [
- 'help' => 'The connection to build/clear metadata cache data for.',
- 'short' => 'c',
- 'default' => 'default',
- ])->addArgument('name', [
- 'help' => 'A specific table you want to clear/refresh cached data for.',
- 'optional' => true,
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/ServerShell.php b/app/vendor/cakephp/cakephp/src/Shell/ServerShell.php
deleted file mode 100644
index 91d978b35..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/ServerShell.php
+++ /dev/null
@@ -1,180 +0,0 @@
-param('host')) {
- $this->_host = $this->param('host');
- }
- if ($this->param('port')) {
- $this->_port = (int)$this->param('port');
- }
- if ($this->param('document_root')) {
- $this->_documentRoot = $this->param('document_root');
- }
- if ($this->param('ini_path')) {
- $this->_iniPath = $this->param('ini_path');
- }
-
- // For Windows
- if (substr($this->_documentRoot, -1, 1) === DIRECTORY_SEPARATOR) {
- $this->_documentRoot = substr($this->_documentRoot, 0, strlen($this->_documentRoot) - 1);
- }
- if (preg_match("/^([a-z]:)[\\\]+(.+)$/i", $this->_documentRoot, $m)) {
- $this->_documentRoot = $m[1] . '\\' . $m[2];
- }
-
- $this->_iniPath = rtrim($this->_iniPath, DIRECTORY_SEPARATOR);
- if (preg_match("/^([a-z]:)[\\\]+(.+)$/i", $this->_iniPath, $m)) {
- $this->_iniPath = $m[1] . '\\' . $m[2];
- }
-
- parent::startup();
- }
-
- /**
- * Displays a header for the shell
- *
- * @return void
- */
- protected function _welcome()
- {
- $this->out();
- $this->out(sprintf('Welcome to CakePHP %s Console ', 'v' . Configure::version()));
- $this->hr();
- $this->out(sprintf('App : %s', APP_DIR));
- $this->out(sprintf('Path: %s', APP));
- $this->out(sprintf('DocumentRoot: %s', $this->_documentRoot));
- $this->out(sprintf('Ini Path: %s', $this->_iniPath));
- $this->hr();
- }
-
- /**
- * Override main() to handle action
- *
- * @return void
- */
- public function main()
- {
- $command = sprintf(
- 'php -S %s:%d -t %s',
- $this->_host,
- $this->_port,
- escapeshellarg($this->_documentRoot)
- );
-
- if (!empty($this->_iniPath)) {
- $command = sprintf('%s -c %s', $command, $this->_iniPath);
- }
-
- $command = sprintf('%s %s', $command, escapeshellarg($this->_documentRoot . '/index.php'));
-
- $port = ':' . $this->_port;
- $this->out(sprintf('built-in server is running in http://%s%s/', $this->_host, $port));
- $this->out(sprintf('You can exit with `CTRL-C` '));
- system($command);
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->setDescription([
- 'PHP Built-in Server for CakePHP',
- '[WARN] Don\'t use this in a production environment ',
- ])->addOption('host', [
- 'short' => 'H',
- 'help' => 'ServerHost',
- ])->addOption('port', [
- 'short' => 'p',
- 'help' => 'ListenPort',
- ])->addOption('ini_path', [
- 'short' => 'I',
- 'help' => 'php.ini path',
- ])->addOption('document_root', [
- 'short' => 'd',
- 'help' => 'DocumentRoot',
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/Task/AssetsTask.php b/app/vendor/cakephp/cakephp/src/Shell/Task/AssetsTask.php
deleted file mode 100644
index 9f26183a6..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/Task/AssetsTask.php
+++ /dev/null
@@ -1,339 +0,0 @@
-_process($this->_list($name));
- }
-
- /**
- * Copying plugin assets to app's webroot. For vendor namespaced plugin,
- * parent folder for vendor name are created if required.
- *
- * @param string|null $name Name of plugin for which to symlink assets.
- * If null all plugins will be processed.
- * @return void
- */
- public function copy($name = null)
- {
- $this->_process($this->_list($name), true, $this->param('overwrite'));
- }
-
- /**
- * Remove plugin assets from app's webroot.
- *
- * @param string|null $name Name of plugin for which to remove assets.
- * If null all plugins will be processed.
- * @return void
- * @since 3.5.12
- */
- public function remove($name = null)
- {
- $plugins = $this->_list($name);
-
- foreach ($plugins as $plugin => $config) {
- $this->out();
- $this->out('For plugin: ' . $plugin);
- $this->hr();
-
- $this->_remove($config);
- }
-
- $this->out();
- $this->out('Done');
- }
-
- /**
- * Get list of plugins to process. Plugins without a webroot directory are skipped.
- *
- * @param string|null $name Name of plugin for which to symlink assets.
- * If null all plugins will be processed.
- * @return array List of plugins with meta data.
- */
- protected function _list($name = null)
- {
- if ($name === null) {
- $pluginsList = Plugin::loaded();
- } else {
- if (!Plugin::isLoaded($name)) {
- $this->err(sprintf('Plugin %s is not loaded.', $name));
-
- return [];
- }
- $pluginsList = [$name];
- }
-
- $plugins = [];
-
- foreach ($pluginsList as $plugin) {
- $path = Plugin::path($plugin) . 'webroot';
- if (!is_dir($path)) {
- $this->verbose('', 1);
- $this->verbose(
- sprintf('Skipping plugin %s. It does not have webroot folder.', $plugin),
- 2
- );
- continue;
- }
-
- $link = Inflector::underscore($plugin);
- $dir = WWW_ROOT;
- $namespaced = false;
- if (strpos($link, '/') !== false) {
- $namespaced = true;
- $parts = explode('/', $link);
- $link = array_pop($parts);
- $dir = WWW_ROOT . implode(DIRECTORY_SEPARATOR, $parts) . DIRECTORY_SEPARATOR;
- }
-
- $plugins[$plugin] = [
- 'srcPath' => Plugin::path($plugin) . 'webroot',
- 'destDir' => $dir,
- 'link' => $link,
- 'namespaced' => $namespaced,
- ];
- }
-
- return $plugins;
- }
-
- /**
- * Process plugins
- *
- * @param array $plugins List of plugins to process
- * @param bool $copy Force copy mode. Default false.
- * @param bool $overwrite Overwrite existing files.
- * @return void
- */
- protected function _process($plugins, $copy = false, $overwrite = false)
- {
- $overwrite = (bool)$this->param('overwrite');
-
- foreach ($plugins as $plugin => $config) {
- $this->out();
- $this->out('For plugin: ' . $plugin);
- $this->hr();
-
- if (
- $config['namespaced'] &&
- !is_dir($config['destDir']) &&
- !$this->_createDirectory($config['destDir'])
- ) {
- continue;
- }
-
- $dest = $config['destDir'] . $config['link'];
-
- if (file_exists($dest)) {
- if ($overwrite && !$this->_remove($config)) {
- continue;
- } elseif (!$overwrite) {
- $this->verbose(
- $dest . ' already exists',
- 1
- );
-
- continue;
- }
- }
-
- if (!$copy) {
- $result = $this->_createSymlink(
- $config['srcPath'],
- $dest
- );
- if ($result) {
- continue;
- }
- }
-
- $this->_copyDirectory(
- $config['srcPath'],
- $dest
- );
- }
-
- $this->out();
- $this->out('Done');
- }
-
- /**
- * Remove folder/symlink.
- *
- * @param array $config Plugin config.
- * @return bool
- */
- protected function _remove($config)
- {
- if ($config['namespaced'] && !is_dir($config['destDir'])) {
- $this->verbose(
- $config['destDir'] . $config['link'] . ' does not exist',
- 1
- );
-
- return false;
- }
-
- $dest = $config['destDir'] . $config['link'];
-
- if (!file_exists($dest)) {
- $this->verbose(
- $dest . ' does not exist',
- 1
- );
-
- return false;
- }
-
- if (is_link($dest)) {
- // @codingStandardsIgnoreLine
- if (@unlink($dest)) {
- $this->out('Unlinked ' . $dest);
-
- return true;
- } else {
- $this->err('Failed to unlink ' . $dest);
-
- return false;
- }
- }
-
- $folder = new Folder($dest);
- if ($folder->delete()) {
- $this->out('Deleted ' . $dest);
-
- return true;
- } else {
- $this->err('Failed to delete ' . $dest);
-
- return false;
- }
- }
-
- /**
- * Create directory
- *
- * @param string $dir Directory name
- * @return bool
- */
- protected function _createDirectory($dir)
- {
- $old = umask(0);
- // @codingStandardsIgnoreStart
- $result = @mkdir($dir, 0755, true);
- // @codingStandardsIgnoreEnd
- umask($old);
-
- if ($result) {
- $this->out('Created directory ' . $dir);
-
- return true;
- }
-
- $this->err('Failed creating directory ' . $dir);
-
- return false;
- }
-
- /**
- * Create symlink
- *
- * @param string $target Target directory
- * @param string $link Link name
- * @return bool
- */
- protected function _createSymlink($target, $link)
- {
- // @codingStandardsIgnoreStart
- $result = @symlink($target, $link);
- // @codingStandardsIgnoreEnd
-
- if ($result) {
- $this->out('Created symlink ' . $link);
-
- return true;
- }
-
- return false;
- }
-
- /**
- * Copy directory
- *
- * @param string $source Source directory
- * @param string $destination Destination directory
- * @return bool
- */
- protected function _copyDirectory($source, $destination)
- {
- $folder = new Folder($source);
- if ($folder->copy(['to' => $destination])) {
- $this->out('Copied assets to directory ' . $destination);
-
- return true;
- }
-
- $this->err('Error copying assets to directory ' . $destination);
-
- return false;
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->addSubcommand('symlink', [
- 'help' => 'Symlink (copy as fallback) plugin assets to app\'s webroot.',
- ])->addSubcommand('copy', [
- 'help' => 'Copy plugin assets to app\'s webroot.',
- ])->addSubcommand('remove', [
- 'help' => 'Remove plugin assets from app\'s webroot.',
- ])->addArgument('name', [
- 'help' => 'A specific plugin you want to symlink assets for.',
- 'optional' => true,
- ])->addOption('overwrite', [
- 'help' => 'Overwrite existing symlink / folder / files.',
- 'default' => false,
- 'boolean' => true,
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/Task/CommandTask.php b/app/vendor/cakephp/cakephp/src/Shell/Task/CommandTask.php
index 5bc80a06c..e41434df4 100644
--- a/app/vendor/cakephp/cakephp/src/Shell/Task/CommandTask.php
+++ b/app/vendor/cakephp/cakephp/src/Shell/Task/CommandTask.php
@@ -1,4 +1,6 @@
null, 'app' => null];
- $appPath = App::path('Shell');
+ $appPath = App::classPath('Shell');
$shellList = $this->_findShells($shellList, $appPath[0], 'app', $skipFiles);
- $appPath = App::path('Command');
+ $appPath = App::classPath('Command');
$shellList = $this->_findShells($shellList, $appPath[0], 'app', $skipFiles);
$skipCore = array_merge($skipFiles, $hiddenCommands, $shellList['app']);
@@ -70,7 +71,7 @@ public function getShellList()
* @param string[] $skip A list of commands to exclude.
* @return array The updated list of shells.
*/
- protected function _findShells($shellList, $path, $key, $skip)
+ protected function _findShells(array $shellList, string $path, string $key, array $skip): array
{
$shells = $this->_scanDir($path);
@@ -86,7 +87,7 @@ protected function _findShells($shellList, $path, $key, $skip)
* @param string[] $skip List of command names to skip.
* @return array The updated $shellList
*/
- protected function _appendShells($type, $shells, $shellList, $skip)
+ protected function _appendShells(string $type, array $shells, array $shellList, array $skip): array
{
if (!isset($shellList[$type])) {
$shellList[$type] = [];
@@ -110,180 +111,22 @@ protected function _appendShells($type, $shells, $shellList, $skip)
* @param string $dir The directory to read.
* @return array The list of shell classnames based on conventions.
*/
- protected function _scanDir($dir)
- {
- $dir = new Folder($dir);
- $contents = $dir->read(true, true);
- if (empty($contents[1])) {
- return [];
- }
- $shells = [];
- foreach ($contents[1] as $file) {
- if (substr($file, -4) !== '.php') {
- continue;
- }
- $shells[] = substr($file, 0, -4);
- }
-
- return $shells;
- }
-
- /**
- * Return a list of all commands
- *
- * @return array
- */
- public function commands()
- {
- $shellList = $this->getShellList();
- $flatten = Hash::flatten($shellList);
- $duplicates = array_intersect($flatten, array_unique(array_diff_key($flatten, array_unique($flatten))));
- $duplicates = Hash::expand($duplicates);
-
- $options = [];
- foreach ($shellList as $type => $commands) {
- foreach ($commands as $shell) {
- $prefix = '';
- if (
- !in_array(strtolower($type), ['app', 'core']) &&
- isset($duplicates[$type]) &&
- in_array($shell, $duplicates[$type])
- ) {
- $prefix = $type . '.';
- }
-
- $options[] = $prefix . $shell;
- }
- }
-
- return $options;
- }
-
- /**
- * Return a list of subcommands for a given command
- *
- * @param string $commandName The command you want subcommands from.
- * @return string[]
- * @throws \ReflectionException
- */
- public function subCommands($commandName)
- {
- $Shell = $this->getShell($commandName);
-
- if (!$Shell) {
- return [];
- }
-
- $taskMap = $this->Tasks->normalizeArray((array)$Shell->tasks);
- $return = array_keys($taskMap);
- $return = array_map('Cake\Utility\Inflector::underscore', $return);
-
- $shellMethodNames = ['main', 'help', 'getOptionParser', 'initialize', 'runCommand'];
-
- $baseClasses = ['Object', 'Shell', 'AppShell'];
-
- $Reflection = new ReflectionClass($Shell);
- $methods = $Reflection->getMethods(ReflectionMethod::IS_PUBLIC);
- $methodNames = [];
- foreach ($methods as $method) {
- $declaringClass = $method->getDeclaringClass()->getShortName();
- if (!in_array($declaringClass, $baseClasses)) {
- $methodNames[] = $method->getName();
- }
- }
-
- $return = array_merge($return, array_diff($methodNames, $shellMethodNames));
- sort($return);
-
- return $return;
- }
-
- /**
- * Get Shell instance for the given command
- *
- * @param string $commandName The command you want.
- * @return \Cake\Console\Shell|false Shell instance if the command can be found, false otherwise.
- */
- public function getShell($commandName)
- {
- list($pluginDot, $name) = pluginSplit($commandName, true);
-
- if (in_array(strtolower($pluginDot), ['app.', 'core.'])) {
- $commandName = $name;
- $pluginDot = '';
- }
-
- if (!in_array($commandName, $this->commands()) && (empty($pluginDot) && !in_array($name, $this->commands()))) {
- return false;
- }
-
- if (empty($pluginDot)) {
- $shellList = $this->getShellList();
-
- if (!in_array($commandName, $shellList['app']) && !in_array($commandName, $shellList['CORE'])) {
- unset($shellList['CORE'], $shellList['app']);
- foreach ($shellList as $plugin => $commands) {
- if (in_array($commandName, $commands)) {
- $pluginDot = $plugin . '.';
- break;
- }
- }
- }
- }
-
- $name = Inflector::camelize($name);
- $pluginDot = Inflector::camelize($pluginDot);
- $class = App::className($pluginDot . $name, 'Shell', 'Shell');
- if (!$class) {
- return false;
- }
-
- /** @var \Cake\Console\Shell $Shell */
- $Shell = new $class();
- $Shell->plugin = trim($pluginDot, '.');
- $Shell->initialize();
-
- return $Shell;
- }
-
- /**
- * Get options list for the given command or subcommand
- *
- * @param string $commandName The command to get options for.
- * @param string $subCommandName The subcommand to get options for. Can be empty to get options for the command.
- * If this parameter is used, the subcommand must be a valid subcommand of the command passed
- * @return array Options list for the given command or subcommand
- */
- public function options($commandName, $subCommandName = '')
+ protected function _scanDir(string $dir): array
{
- $Shell = $this->getShell($commandName);
-
- if (!$Shell) {
+ if (!is_dir($dir)) {
return [];
}
- $parser = $Shell->getOptionParser();
+ $fs = new Filesystem();
+ $files = $fs->find($dir, '/\.php$/');
- if (!empty($subCommandName)) {
- $subCommandName = Inflector::camelize($subCommandName);
- if ($Shell->hasTask($subCommandName)) {
- $parser = $Shell->{$subCommandName}->getOptionParser();
- } else {
- return [];
- }
+ $shells = [];
+ foreach ($files as $file) {
+ $shells[] = $file->getBasename('.php');
}
- $options = [];
- $array = $parser->options();
- /** @var \Cake\Console\ConsoleInputOption $obj */
- foreach ($array as $name => $obj) {
- $options[] = "--$name";
- $short = $obj->short();
- if ($short) {
- $options[] = "-$short";
- }
- }
+ sort($shells);
- return $options;
+ return $shells;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/Task/ExtractTask.php b/app/vendor/cakephp/cakephp/src/Shell/Task/ExtractTask.php
deleted file mode 100644
index dd7c823c4..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/Task/ExtractTask.php
+++ /dev/null
@@ -1,854 +0,0 @@
-_paths) > 0 ? $this->_paths : ['None'];
- $message = sprintf(
- "Current paths: %s\nWhat is the path you would like to extract?\n[Q]uit [D]one",
- implode(', ', $currentPaths)
- );
- $response = $this->in($message, null, $defaultPath);
- if (strtoupper($response) === 'Q') {
- $this->err('Extract Aborted');
- $this->_stop();
-
- return;
- }
- if (strtoupper($response) === 'D' && count($this->_paths)) {
- $this->out();
-
- return;
- }
- if (strtoupper($response) === 'D') {
- $this->warn('No directories selected. Please choose a directory.');
- } elseif (is_dir($response)) {
- $this->_paths[] = $response;
- $defaultPath = 'D';
- } else {
- $this->err('The directory path you supplied was not found. Please try again.');
- }
- $this->out();
- }
- }
-
- /**
- * Execution method always used for tasks
- *
- * @return void
- */
- public function main()
- {
- if (!empty($this->params['exclude'])) {
- $this->_exclude = explode(',', $this->params['exclude']);
- }
- if (isset($this->params['files']) && !is_array($this->params['files'])) {
- $this->_files = explode(',', $this->params['files']);
- }
- if (isset($this->params['paths'])) {
- $this->_paths = explode(',', $this->params['paths']);
- } elseif (isset($this->params['plugin'])) {
- $plugin = Inflector::camelize($this->params['plugin']);
- if (!Plugin::isLoaded($plugin)) {
- throw new MissingPluginException(['plugin' => $plugin]);
- }
- $this->_paths = [Plugin::classPath($plugin)];
- $this->params['plugin'] = $plugin;
- } else {
- $this->_getPaths();
- }
-
- if (isset($this->params['extract-core'])) {
- $this->_extractCore = !(strtolower($this->params['extract-core']) === 'no');
- } else {
- $response = $this->in('Would you like to extract the messages from the CakePHP core?', ['y', 'n'], 'n');
- $this->_extractCore = strtolower($response) === 'y';
- }
-
- if (!empty($this->params['exclude-plugins']) && $this->_isExtractingApp()) {
- $this->_exclude = array_merge($this->_exclude, App::path('Plugin'));
- }
-
- if (!empty($this->params['validation-domain'])) {
- $this->_validationDomain = $this->params['validation-domain'];
- }
-
- if ($this->_extractCore) {
- $this->_paths[] = CAKE;
- }
-
- if (isset($this->params['output'])) {
- $this->_output = $this->params['output'];
- } elseif (isset($this->params['plugin'])) {
- $this->_output = $this->_paths[0] . 'Locale';
- } else {
- $message = "What is the path you would like to output?\n[Q]uit";
- while (true) {
- $response = $this->in($message, null, rtrim($this->_paths[0], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'Locale');
- if (strtoupper($response) === 'Q') {
- $this->err('Extract Aborted');
- $this->_stop();
-
- return;
- }
- if ($this->_isPathUsable($response)) {
- $this->_output = $response . DIRECTORY_SEPARATOR;
- break;
- }
-
- $this->err('');
- $this->err(
- 'The directory path you supplied was ' .
- 'not found. Please try again. '
- );
- $this->out();
- }
- }
-
- if (isset($this->params['merge'])) {
- $this->_merge = !(strtolower($this->params['merge']) === 'no');
- } else {
- $this->out();
- $response = $this->in('Would you like to merge all domain strings into the default.pot file?', ['y', 'n'], 'n');
- $this->_merge = strtolower($response) === 'y';
- }
-
- $this->_markerError = $this->param('marker-error');
- $this->_relativePaths = $this->param('relative-paths');
-
- if (empty($this->_files)) {
- $this->_searchFiles();
- }
-
- $this->_output = rtrim($this->_output, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
- if (!$this->_isPathUsable($this->_output)) {
- $this->err(sprintf('The output directory %s was not found or writable.', $this->_output));
- $this->_stop();
-
- return;
- }
-
- $this->_extract();
- }
-
- /**
- * Add a translation to the internal translations property
- *
- * Takes care of duplicate translations
- *
- * @param string $domain The domain
- * @param string $msgid The message string
- * @param array $details Context and plural form if any, file and line references
- * @return void
- */
- protected function _addTranslation($domain, $msgid, $details = [])
- {
- $context = isset($details['msgctxt']) ? $details['msgctxt'] : '';
-
- if (empty($this->_translations[$domain][$msgid][$context])) {
- $this->_translations[$domain][$msgid][$context] = [
- 'msgid_plural' => false,
- ];
- }
-
- if (isset($details['msgid_plural'])) {
- $this->_translations[$domain][$msgid][$context]['msgid_plural'] = $details['msgid_plural'];
- }
-
- if (isset($details['file'])) {
- $line = isset($details['line']) ? $details['line'] : 0;
- $this->_translations[$domain][$msgid][$context]['references'][$details['file']][] = $line;
- }
- }
-
- /**
- * Extract text
- *
- * @return void
- */
- protected function _extract()
- {
- $this->out();
- $this->out();
- $this->out('Extracting...');
- $this->hr();
- $this->out('Paths:');
- foreach ($this->_paths as $path) {
- $this->out(' ' . $path);
- }
- $this->out('Output Directory: ' . $this->_output);
- $this->hr();
- $this->_extractTokens();
- $this->_buildFiles();
- $this->_writeFiles();
- $this->_paths = $this->_files = $this->_storage = [];
- $this->_translations = $this->_tokens = [];
- $this->out();
- if ($this->_countMarkerError) {
- $this->err("{$this->_countMarkerError} marker error(s) detected.");
- $this->err(" => Use the --marker-error option to display errors.");
- }
-
- $this->out('Done.');
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
- $parser->setDescription(
- 'CakePHP Language String Extraction:'
- )->addOption('app', [
- 'help' => 'Directory where your application is located.',
- ])->addOption('paths', [
- 'help' => 'Comma separated list of paths.',
- ])->addOption('merge', [
- 'help' => 'Merge all domain strings into the default.po file.',
- 'choices' => ['yes', 'no'],
- ])->addOption('relative-paths', [
- 'help' => 'Use relative paths in the .pot file',
- 'boolean' => true,
- 'default' => false,
- ])->addOption('output', [
- 'help' => 'Full path to output directory.',
- ])->addOption('files', [
- 'help' => 'Comma separated list of files.',
- ])->addOption('exclude-plugins', [
- 'boolean' => true,
- 'default' => true,
- 'help' => 'Ignores all files in plugins if this command is run inside from the same app directory.',
- ])->addOption('plugin', [
- 'help' => 'Extracts tokens only from the plugin specified and puts the result in the plugin\'s Locale directory.',
- 'short' => 'p',
- ])->addOption('ignore-model-validation', [
- 'boolean' => true,
- 'default' => false,
- 'help' => 'Ignores validation messages in the $validate property.' .
- ' If this flag is not set and the command is run from the same app directory,' .
- ' all messages in model validation rules will be extracted as tokens.',
- ])->addOption('validation-domain', [
- 'help' => 'If set to a value, the localization domain to be used for model validation messages.',
- ])->addOption('exclude', [
- 'help' => 'Comma separated list of directories to exclude.' .
- ' Any path containing a path segment with the provided values will be skipped. E.g. test,vendors',
- ])->addOption('overwrite', [
- 'boolean' => true,
- 'default' => false,
- 'help' => 'Always overwrite existing .pot files.',
- ])->addOption('extract-core', [
- 'help' => 'Extract messages from the CakePHP core libs.',
- 'choices' => ['yes', 'no'],
- ])->addOption('no-location', [
- 'boolean' => true,
- 'default' => false,
- 'help' => 'Do not write file locations for each extracted message.',
- ])->addOption('marker-error', [
- 'boolean' => true,
- 'default' => false,
- 'help' => 'Do not display marker error.',
- ]);
-
- return $parser;
- }
-
- /**
- * Extract tokens out of all files to be processed
- *
- * @return void
- */
- protected function _extractTokens()
- {
- /** @var \Cake\Shell\Helper\ProgressHelper $progress */
- $progress = $this->helper('progress');
- $progress->init(['total' => count($this->_files)]);
- $isVerbose = $this->param('verbose');
-
- $functions = [
- '__' => ['singular'],
- '__n' => ['singular', 'plural'],
- '__d' => ['domain', 'singular'],
- '__dn' => ['domain', 'singular', 'plural'],
- '__x' => ['context', 'singular'],
- '__xn' => ['context', 'singular', 'plural'],
- '__dx' => ['domain', 'context', 'singular'],
- '__dxn' => ['domain', 'context', 'singular', 'plural'],
- ];
- $pattern = '/(' . implode('|', array_keys($functions)) . ')\s*\(/';
-
- foreach ($this->_files as $file) {
- $this->_file = $file;
- if ($isVerbose) {
- $this->out(sprintf('Processing %s...', $file), 1, Shell::VERBOSE);
- }
-
- $code = file_get_contents($file);
-
- if (preg_match($pattern, $code) === 1) {
- $allTokens = token_get_all($code);
-
- $this->_tokens = [];
- foreach ($allTokens as $token) {
- if (!is_array($token) || ($token[0] !== T_WHITESPACE && $token[0] !== T_INLINE_HTML)) {
- $this->_tokens[] = $token;
- }
- }
- unset($allTokens);
-
- foreach ($functions as $functionName => $map) {
- $this->_parse($functionName, $map);
- }
- }
-
- if (!$isVerbose) {
- $progress->increment(1);
- $progress->draw();
- }
- }
- }
-
- /**
- * Parse tokens
- *
- * @param string $functionName Function name that indicates translatable string (e.g: '__')
- * @param array $map Array containing what variables it will find (e.g: domain, singular, plural)
- * @return void
- */
- protected function _parse($functionName, $map)
- {
- $count = 0;
- $tokenCount = count($this->_tokens);
-
- while (($tokenCount - $count) > 1) {
- $countToken = $this->_tokens[$count];
- $firstParenthesis = $this->_tokens[$count + 1];
- if (!is_array($countToken)) {
- $count++;
- continue;
- }
-
- list($type, $string, $line) = $countToken;
- if (($type == T_STRING) && ($string === $functionName) && ($firstParenthesis === '(')) {
- $position = $count;
- $depth = 0;
-
- while (!$depth) {
- if ($this->_tokens[$position] === '(') {
- $depth++;
- } elseif ($this->_tokens[$position] === ')') {
- $depth--;
- }
- $position++;
- }
-
- $mapCount = count($map);
- $strings = $this->_getStrings($position, $mapCount);
-
- if ($mapCount === count($strings)) {
- $singular = $plural = $context = null;
- /**
- * @var string $singular
- * @var string|null $plural
- * @var string|null $context
- */
- extract(array_combine($map, $strings));
- $domain = isset($domain) ? $domain : 'default';
- $details = [
- 'file' => $this->_file,
- 'line' => $line,
- ];
- if ($this->_relativePaths) {
- $details['file'] = '.' . str_replace(ROOT, '', $details['file']);
- }
- if ($plural !== null) {
- $details['msgid_plural'] = $plural;
- }
- if ($context !== null) {
- $details['msgctxt'] = $context;
- }
- $this->_addTranslation($domain, $singular, $details);
- } else {
- $this->_markerError($this->_file, $line, $functionName, $count);
- }
- }
- $count++;
- }
- }
-
- /**
- * Build the translate template file contents out of obtained strings
- *
- * @return void
- */
- protected function _buildFiles()
- {
- $paths = $this->_paths;
- $paths[] = realpath(APP) . DIRECTORY_SEPARATOR;
-
- usort($paths, function ($a, $b) {
- return strlen($a) - strlen($b);
- });
-
- foreach ($this->_translations as $domain => $translations) {
- foreach ($translations as $msgid => $contexts) {
- foreach ($contexts as $context => $details) {
- $plural = $details['msgid_plural'];
- $files = $details['references'];
- $header = '';
-
- if (!$this->param('no-location')) {
- $occurrences = [];
- foreach ($files as $file => $lines) {
- $lines = array_unique($lines);
- foreach ($lines as $line) {
- $occurrences[] = $file . ':' . $line;
- }
- }
- $occurrences = implode("\n#: ", $occurrences);
-
- $header = '#: ' . str_replace(DIRECTORY_SEPARATOR, '/', str_replace($paths, '', $occurrences)) . "\n";
- }
-
- $sentence = '';
- if ($context !== '') {
- $sentence .= "msgctxt \"{$context}\"\n";
- }
- if ($plural === false) {
- $sentence .= "msgid \"{$msgid}\"\n";
- $sentence .= "msgstr \"\"\n\n";
- } else {
- $sentence .= "msgid \"{$msgid}\"\n";
- $sentence .= "msgid_plural \"{$plural}\"\n";
- $sentence .= "msgstr[0] \"\"\n";
- $sentence .= "msgstr[1] \"\"\n\n";
- }
-
- if ($domain !== 'default' && $this->_merge) {
- $this->_store('default', $header, $sentence);
- } else {
- $this->_store($domain, $header, $sentence);
- }
- }
- }
- }
- }
-
- /**
- * Prepare a file to be stored
- *
- * @param string $domain The domain
- * @param string $header The header content.
- * @param string $sentence The sentence to store.
- * @return void
- */
- protected function _store($domain, $header, $sentence)
- {
- if (!isset($this->_storage[$domain])) {
- $this->_storage[$domain] = [];
- }
- if (!isset($this->_storage[$domain][$sentence])) {
- $this->_storage[$domain][$sentence] = $header;
- } else {
- $this->_storage[$domain][$sentence] .= $header;
- }
- }
-
- /**
- * Write the files that need to be stored
- *
- * @return void
- */
- protected function _writeFiles()
- {
- $this->out();
- $overwriteAll = false;
- if (!empty($this->params['overwrite'])) {
- $overwriteAll = true;
- }
- foreach ($this->_storage as $domain => $sentences) {
- $output = $this->_writeHeader();
- $headerLength = strlen($output);
- foreach ($sentences as $sentence => $header) {
- $output .= $header . $sentence;
- }
-
- // Remove vendor prefix if present.
- $slashPosition = strpos($domain, '/');
- if ($slashPosition !== false) {
- $domain = substr($domain, $slashPosition + 1);
- }
-
- $filename = str_replace('/', '_', $domain) . '.pot';
- $File = new File($this->_output . $filename);
-
- if ($File->exists() && $this->_checkUnchanged($File, $headerLength, $output) === true) {
- $this->out($filename . ' is unchanged. Skipping.');
- $File->close();
- continue;
- }
-
- $response = '';
- while ($overwriteAll === false && $File->exists() && strtoupper($response) !== 'Y') {
- $this->out();
- $response = $this->in(
- sprintf('Error: %s already exists in this location. Overwrite? [Y]es, [N]o, [A]ll', $filename),
- ['y', 'n', 'a'],
- 'y'
- );
- if (strtoupper($response) === 'N') {
- $response = '';
- while (!$response) {
- $response = $this->in('What would you like to name this file?', null, 'new_' . $filename);
- $File = new File($this->_output . $response);
- $filename = $response;
- }
- } elseif (strtoupper($response) === 'A') {
- $overwriteAll = true;
- }
- }
- $File->write($output);
- $File->close();
- }
- }
-
- /**
- * Build the translation template header
- *
- * @return string Translation template header
- */
- protected function _writeHeader()
- {
- $output = "# LANGUAGE translation of CakePHP Application\n";
- $output .= "# Copyright YEAR NAME \n";
- $output .= "#\n";
- $output .= "#, fuzzy\n";
- $output .= "msgid \"\"\n";
- $output .= "msgstr \"\"\n";
- $output .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
- $output .= '"POT-Creation-Date: ' . date('Y-m-d H:iO') . "\\n\"\n";
- $output .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
- $output .= "\"Last-Translator: NAME \\n\"\n";
- $output .= "\"Language-Team: LANGUAGE \\n\"\n";
- $output .= "\"MIME-Version: 1.0\\n\"\n";
- $output .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
- $output .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
- $output .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n\n";
-
- return $output;
- }
-
- /**
- * Check whether the old and new output are the same, thus unchanged
- *
- * Compares the sha1 hashes of the old and new file without header.
- *
- * @param File $oldFile The existing file.
- * @param int $headerLength The length of the file header in bytes.
- * @param string $newFileContent The content of the new file.
- * @return bool Whether or not the old and new file are unchanged.
- */
- protected function _checkUnchanged(File $oldFile, $headerLength, $newFileContent)
- {
- $oldFileContent = $oldFile->read();
-
- $oldChecksum = sha1(substr($oldFileContent, $headerLength));
- $newChecksum = sha1(substr($newFileContent, $headerLength));
-
- return $oldChecksum === $newChecksum;
- }
-
- /**
- * Get the strings from the position forward
- *
- * @param int $position Actual position on tokens array
- * @param int $target Number of strings to extract
- * @return array Strings extracted
- */
- protected function _getStrings(&$position, $target)
- {
- $strings = [];
- $count = count($strings);
- while ($count < $target && ($this->_tokens[$position] === ',' || $this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING || $this->_tokens[$position][0] == T_LNUMBER)) {
- $count = count($strings);
- if ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING && $this->_tokens[$position + 1] === '.') {
- $string = '';
- while ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING || $this->_tokens[$position] === '.') {
- if ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING) {
- $string .= $this->_formatString($this->_tokens[$position][1]);
- }
- $position++;
- }
- $strings[] = $string;
- } elseif ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING) {
- $strings[] = $this->_formatString($this->_tokens[$position][1]);
- } elseif ($this->_tokens[$position][0] == T_LNUMBER) {
- $strings[] = $this->_tokens[$position][1];
- }
- $position++;
- }
-
- return $strings;
- }
-
- /**
- * Format a string to be added as a translatable string
- *
- * @param string $string String to format
- * @return string Formatted string
- */
- protected function _formatString($string)
- {
- $quote = substr($string, 0, 1);
- $string = substr($string, 1, -1);
- if ($quote === '"') {
- $string = stripcslashes($string);
- } else {
- $string = strtr($string, ["\\'" => "'", '\\\\' => '\\']);
- }
- $string = str_replace("\r\n", "\n", $string);
-
- return addcslashes($string, "\0..\37\\\"");
- }
-
- /**
- * Indicate an invalid marker on a processed file
- *
- * @param string $file File where invalid marker resides
- * @param int $line Line number
- * @param string $marker Marker found
- * @param int $count Count
- * @return void
- */
- protected function _markerError($file, $line, $marker, $count)
- {
- if (strpos($this->_file, CAKE_CORE_INCLUDE_PATH) === false) {
- $this->_countMarkerError++;
- }
-
- if (!$this->_markerError) {
- return;
- }
-
- $this->err(sprintf("Invalid marker content in %s:%s\n* %s(", $file, $line, $marker));
- $count += 2;
- $tokenCount = count($this->_tokens);
- $parenthesis = 1;
-
- while ((($tokenCount - $count) > 0) && $parenthesis) {
- if (is_array($this->_tokens[$count])) {
- $this->err($this->_tokens[$count][1], false);
- } else {
- $this->err($this->_tokens[$count], false);
- if ($this->_tokens[$count] === '(') {
- $parenthesis++;
- }
-
- if ($this->_tokens[$count] === ')') {
- $parenthesis--;
- }
- }
- $count++;
- }
- $this->err("\n", true);
- }
-
- /**
- * Search files that may contain translatable strings
- *
- * @return void
- */
- protected function _searchFiles()
- {
- $pattern = false;
- if (!empty($this->_exclude)) {
- $exclude = [];
- foreach ($this->_exclude as $e) {
- if (DIRECTORY_SEPARATOR !== '\\' && $e[0] !== DIRECTORY_SEPARATOR) {
- $e = DIRECTORY_SEPARATOR . $e;
- }
- $exclude[] = preg_quote($e, '/');
- }
- $pattern = '/' . implode('|', $exclude) . '/';
- }
- foreach ($this->_paths as $path) {
- $path = realpath($path) . DIRECTORY_SEPARATOR;
- $Folder = new Folder($path);
- $files = $Folder->findRecursive('.*\.(php|ctp|thtml|inc|tpl)', true);
- if (!empty($pattern)) {
- $files = preg_grep($pattern, $files, PREG_GREP_INVERT);
- $files = array_values($files);
- }
- $this->_files = array_merge($this->_files, $files);
- }
- $this->_files = array_unique($this->_files);
- }
-
- /**
- * Returns whether this execution is meant to extract string only from directories in folder represented by the
- * APP constant, i.e. this task is extracting strings from same application.
- *
- * @return bool
- */
- protected function _isExtractingApp()
- {
- return $this->_paths === [APP];
- }
-
- /**
- * Checks whether or not a given path is usable for writing.
- *
- * @param string $path Path to folder
- * @return bool true if it exists and is writable, false otherwise
- */
- protected function _isPathUsable($path)
- {
- if (!is_dir($path)) {
- mkdir($path, 0770, true);
- }
-
- return is_dir($path) && is_writable($path);
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/Task/LoadTask.php b/app/vendor/cakephp/cakephp/src/Shell/Task/LoadTask.php
deleted file mode 100644
index 3c11c70ec..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/Task/LoadTask.php
+++ /dev/null
@@ -1,174 +0,0 @@
-params['cli']) {
- $filename .= '_cli';
- }
-
- $this->bootstrap = ROOT . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . $filename . '.php';
-
- if (!$plugin) {
- $this->err('You must provide a plugin name in CamelCase format.');
- $this->err('To load an "Example" plugin, run `cake plugin load Example`.');
-
- return false;
- }
-
- $options = $this->makeOptions();
-
- $app = APP . 'Application.php';
- if (file_exists($app) && !$this->param('no_app')) {
- $this->modifyApplication($app, $plugin, $options);
-
- return true;
- }
-
- return $this->_modifyBootstrap($plugin, $options);
- }
-
- /**
- * Create options string for the load call.
- *
- * @return string
- */
- protected function makeOptions()
- {
- $autoloadString = $this->param('autoload') ? "'autoload' => true" : '';
- $bootstrapString = $this->param('bootstrap') ? "'bootstrap' => true" : '';
- $routesString = $this->param('routes') ? "'routes' => true" : '';
-
- return implode(', ', array_filter([$autoloadString, $bootstrapString, $routesString]));
- }
-
- /**
- * Modify the application class
- *
- * @param string $app The Application file to modify.
- * @param string $plugin The plugin name to add.
- * @param string $options The plugin options to add
- * @return void
- */
- protected function modifyApplication($app, $plugin, $options)
- {
- $file = new File($app, false);
- $contents = $file->read();
-
- $append = "\n \$this->addPlugin('%s', [%s]);\n";
- $insert = str_replace(', []', '', sprintf($append, $plugin, $options));
-
- if (!preg_match('/function bootstrap\(\)/m', $contents)) {
- $this->abort('Your Application class does not have a bootstrap() method. Please add one.');
- } else {
- $contents = preg_replace('/(function bootstrap\(\)(?:\s+)\{)/m', '$1' . $insert, $contents);
- }
- $file->write($contents);
-
- $this->out('');
- $this->out(sprintf('%s modified', $app));
- }
-
- /**
- * Update the applications bootstrap.php file.
- *
- * @param string $plugin Name of plugin.
- * @param string $options The options string
- * @return bool If modify passed.
- */
- protected function _modifyBootstrap($plugin, $options)
- {
- $bootstrap = new File($this->bootstrap, false);
- $contents = $bootstrap->read();
- if (!preg_match("@\n\s*Plugin::loadAll@", $contents)) {
- $append = "\nPlugin::load('%s', [%s]);\n";
-
- $bootstrap->append(str_replace(', []', '', sprintf($append, $plugin, $options)));
- $this->out('');
- $this->out(sprintf('%s modified', $this->bootstrap));
-
- return true;
- }
-
- return false;
- }
-
- /**
- * GetOptionParser method.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->addOption('bootstrap', [
- 'short' => 'b',
- 'help' => 'Will load bootstrap.php from plugin.',
- 'boolean' => true,
- 'default' => false,
- ])
- ->addOption('routes', [
- 'short' => 'r',
- 'help' => 'Will load routes.php from plugin.',
- 'boolean' => true,
- 'default' => false,
- ])
- ->addOption('autoload', [
- 'help' => 'Will autoload the plugin using CakePHP.' .
- 'Set to true if you are not using composer to autoload your plugin.',
- 'boolean' => true,
- 'default' => false,
- ])
- ->addOption('cli', [
- 'help' => 'Use the bootstrap_cli file.',
- 'boolean' => true,
- 'default' => false,
- ])
- ->addOption('no_app', [
- 'help' => 'Do not update the Application if it exist. Forces config/bootstrap.php to be updated.',
- 'boolean' => true,
- 'default' => false,
- ])
- ->addArgument('plugin', [
- 'help' => 'Name of the plugin to load.',
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Shell/Task/UnloadTask.php b/app/vendor/cakephp/cakephp/src/Shell/Task/UnloadTask.php
deleted file mode 100644
index 9904fa816..000000000
--- a/app/vendor/cakephp/cakephp/src/Shell/Task/UnloadTask.php
+++ /dev/null
@@ -1,146 +0,0 @@
-params['cli']) {
- $filename .= '_cli';
- }
-
- $this->bootstrap = ROOT . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . $filename . '.php';
-
- if (!$plugin) {
- $this->err('You must provide a plugin name in CamelCase format.');
- $this->err('To unload an "Example" plugin, run `cake plugin unload Example`.');
-
- return false;
- }
-
- $app = APP . 'Application.php';
- if (file_exists($app) && !$this->param('no_app')) {
- $this->modifyApplication($app, $plugin);
-
- return true;
- }
-
- return (bool)$this->_modifyBootstrap($plugin);
- }
-
- /**
- * Update the applications bootstrap.php file.
- *
- * @param string $app Path to the application to update.
- * @param string $plugin Name of plugin.
- * @return bool If modify passed.
- */
- protected function modifyApplication($app, $plugin)
- {
- $finder = "@\\\$this\-\>addPlugin\(\s*'$plugin'(.|.\n|)+\);+@";
-
- $content = file_get_contents($app);
- $newContent = preg_replace($finder, '', $content);
-
- if ($newContent === $content) {
- return false;
- }
-
- file_put_contents($app, $newContent);
-
- $this->out('');
- $this->out(sprintf('%s modified', $app));
-
- return true;
- }
-
- /**
- * Update the applications bootstrap.php file.
- *
- * @param string $plugin Name of plugin.
- * @return bool If modify passed.
- */
- protected function _modifyBootstrap($plugin)
- {
- $finder = "@\nPlugin::load\((.|.\n|\n\s\s|\n\t|)+'$plugin'(.|.\n|)+\);\n@";
-
- $bootstrap = new File($this->bootstrap, false);
- $content = $bootstrap->read();
-
- if (!preg_match("@\n\s*Plugin::loadAll@", $content)) {
- $newContent = preg_replace($finder, '', $content);
-
- if ($newContent === $content) {
- return false;
- }
-
- $bootstrap->write($newContent);
-
- $this->out('');
- $this->out(sprintf('%s modified', $this->bootstrap));
-
- return true;
- }
-
- return false;
- }
-
- /**
- * GetOptionParser method.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->addOption('cli', [
- 'help' => 'Use the bootstrap_cli file.',
- 'boolean' => true,
- 'default' => false,
- ])
- ->addOption('no_app', [
- 'help' => 'Do not update the Application if it exist. Forces config/bootstrap.php to be updated.',
- 'boolean' => true,
- 'default' => false,
- ])
- ->addArgument('plugin', [
- 'help' => 'Name of the plugin to load.',
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/Template/Element/auto_table_warning.ctp b/app/vendor/cakephp/cakephp/src/Template/Element/auto_table_warning.ctp
deleted file mode 100644
index 16628f16c..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Element/auto_table_warning.ctp
+++ /dev/null
@@ -1,42 +0,0 @@
-genericInstances();
-if (!$autoTables) {
- return;
-}
-?>
-Could this be caused by using Auto-Tables?
-
-Some of the Table objects in your application were created by instantiating "Cake\ORM\Table"
-instead of any other specific subclass.
-
-This could be the cause for this exception. Auto-Tables are created for you under the following circumstances:
-
- - The class for the specified table does not exist.
- - The Table was created with a typo: $this->getTableLocator()->get('Atricles');
- - The class file has a typo in the name or incorrect namespace: class Atricles extends Table
- - The file containing the class has a typo or incorrect casing: Atricles.php
- - The Table was used using associations but the association has a typo: $this->belongsTo('Atricles')
- - The table class resides in a Plugin but no plugin notation was used in the association definition.
-
-
-Please try correcting the issue for the following table aliases:
-
- $table) : ?>
- - = $alias ?>
-
-
-
diff --git a/app/vendor/cakephp/cakephp/src/Template/Element/exception_stack_trace.ctp b/app/vendor/cakephp/cakephp/src/Template/Element/exception_stack_trace.ctp
deleted file mode 100644
index 5b4bf7c63..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Element/exception_stack_trace.ctp
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-getTrace() as $i => $stack):
- $excerpt = $params = [];
-
- if (isset($stack['file'], $stack['line'])):
- $excerpt = Debugger::excerpt($stack['file'], $stack['line'], 4);
- endif;
-
- if (isset($stack['file'])):
- $file = $stack['file'];
- else:
- $file = '[internal function]';
- endif;
-
- if ($stack['function']):
- if (!empty($stack['args'])):
- foreach ((array)$stack['args'] as $arg):
- $params[] = Debugger::exportVar($arg, 4);
- endforeach;
- else:
- $params[] = 'No arguments';
- endif;
- endif;
-?>
-
-
diff --git a/app/vendor/cakephp/cakephp/src/Template/Element/exception_stack_trace_nav.ctp b/app/vendor/cakephp/cakephp/src/Template/Element/exception_stack_trace_nav.ctp
deleted file mode 100644
index 859c08940..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Element/exception_stack_trace_nav.ctp
+++ /dev/null
@@ -1,43 +0,0 @@
-
-toggle vendor stack frames
-
-
-getTrace() as $i => $stack): ?>
-
- -
-
-
-
- 〉 = h($stack['class'] . $stack['type'] . $stack['function']) ?>
-
- 〉 = h($stack['function']) ?>
-
-
-
- = h(Debugger::trimPath($stack['file'])) ?>, line = $stack['line'] ?>
-
- [internal function]
-
-
-
-
- 〉 [internal function]
-
-
-
-
diff --git a/app/vendor/cakephp/cakephp/src/Template/Element/plugin_class_error.ctp b/app/vendor/cakephp/cakephp/src/Template/Element/plugin_class_error.ctp
deleted file mode 100644
index a8a9d350e..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Element/plugin_class_error.ctp
+++ /dev/null
@@ -1,33 +0,0 @@
-
';
-
-if (!Plugin::isLoaded($plugin)):
- echo sprintf('Make sure your plugin %s is in the %s directory and was loaded.', h($plugin), $pluginPath);
-else:
- echo sprintf('Make sure your plugin was loaded from %s and Composer is able to autoload its classes, see %s and %s',
- 'config' . DIRECTORY_SEPARATOR . 'bootstrap.php',
- 'Loading a plugin',
- 'Plugins - autoloading plugin classes'
- );
-endif;
-
-?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/duplicate_named_route.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/duplicate_named_route.ctp
deleted file mode 100644
index d88d5f828..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/duplicate_named_route.ctp
+++ /dev/null
@@ -1,61 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', 'Duplicate Named Route');
-$this->assign('templateName', 'duplicate_named_route.ctp');
-
-$attributes = $error->getAttributes();
-
-$this->start('subheading');
-?>
- Error:
- = h($error->getMessage()); ?>
-end() ?>
-
-start('file') ?>
-Route names must be unique across your entire application.
-The same _name option cannot be used twice,
-even if the names occur in different routing scopes.
-Remove duplicate route names in your route configuration.
-
-
-The passed context was:
-
-= Debugger::exportVar($attributes['context']); ?>
-
-
-
-
- Duplicate Route
-
- Template Defaults Options
- ';
- printf(
- '%s %s %s ',
- h($other->template),
- h(Debugger::exportVar($other->defaults)),
- h(Debugger::exportVar($other->options))
- );
- echo '';
- ?>
-
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/fatal_error.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/fatal_error.ctp
deleted file mode 100644
index 22262746a..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/fatal_error.ctp
+++ /dev/null
@@ -1,38 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', 'Fatal Error');
-$this->assign('templateName', 'fatal_error.ctp');
-
-$this->start('subheading');
-?>
- Error:
- = h($error->getMessage()) ?>
-
-
- File
- = h($error->getFile()) ?>
-
- Line:
- = h($error->getLine()) ?>
-end() ?>
-
-start('file');
-if (extension_loaded('xdebug')):
- xdebug_print_function_stack();
-endif;
-$this->end();
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_action.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_action.ctp
deleted file mode 100644
index 243e2c3fc..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_action.ctp
+++ /dev/null
@@ -1,86 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', sprintf('Missing Method in %s', h($class)));
-$this->assign(
- 'subheading',
- sprintf('The action %s is not defined in %s', h($action), h($class))
-);
-$this->assign('templateName', 'missing_action.ctp');
-
-$this->start('file');
-?>
-
- Error:
- = sprintf('Create %s::%s() in file: %s.', h($class), h($action), $path); ?>
-
-
-
-
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_behavior.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_behavior.ctp
deleted file mode 100644
index df86b5744..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_behavior.ctp
+++ /dev/null
@@ -1,68 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('templateName', 'missing_behavior.ctp');
-
-$this->assign('title', 'Missing Behavior');
-
-$this->start('subheading');
-printf('%s could not be found.', h($pluginDot . $class));
-echo $this->element('plugin_class_error', ['pluginPath' => $pluginPath]);
-$this->end();
-
-$this->start('file');
-?>
-
- Error:
- = sprintf('Create the class %s below in file: %s', h($class), $filePath . 'Model' . DIRECTORY_SEPARATOR . 'Behavior' . DIRECTORY_SEPARATOR . h($class) . '.php'); ?>
-
-
-
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_cell_view.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_cell_view.ctp
deleted file mode 100644
index 6a721f223..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_cell_view.ctp
+++ /dev/null
@@ -1,43 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('templateName', 'missing_cell_view.ctp');
-$this->assign('title', 'Missing Cell View');
-
-$this->start('subheading');
-printf('The view for %sCell was not be found.', h($name));
-$this->end();
-
-$this->start('file');
-?>
-
- Confirm you have created the file: "= h($file) ?>"
- in one of the following paths:
-
-
-_paths($this->plugin);
- foreach ($paths as $path):
- if (strpos($path, CORE_PATH) !== false) {
- continue;
- }
- echo sprintf('- %sCell/%s/%s
', h($path), h($name), h($file));
- endforeach;
-?>
-
-end(); ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_component.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_component.ctp
deleted file mode 100644
index f00f6111d..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_component.ctp
+++ /dev/null
@@ -1,64 +0,0 @@
-layout = 'dev_error';
-$this->assign('title', 'Missing Component');
-$this->assign('templateName', 'missing_component.ctp');
-
-$this->start('subheading');
-printf('%s could not be found.', h($pluginDot . $class));
-echo $this->element('plugin_class_error', ['pluginPath' => $pluginPath]);
-$this->end();
-
-$this->start('file');
-?>
-
- Error:
- = sprintf('Create the class %s below in file: %s', h($class), $filePath . 'Controller' . DIRECTORY_SEPARATOR . 'Component' . DIRECTORY_SEPARATOR . h($class) . '.php'); ?>
-
-
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_connection.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_connection.ctp
deleted file mode 100644
index fe9ed4b9d..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_connection.ctp
+++ /dev/null
@@ -1,32 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('templateName', 'missing_connection.ctp');
-$this->assign('title', 'Missing Database Connection');
-
-
-$this->start('subheading'); ?>
-A Database connection using was missing or unable to connect.
-
-end();
-
-$this->start('file');
-echo $this->element('auto_table_warning');
-$this->end();
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_controller.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_controller.ctp
deleted file mode 100644
index 503b7e470..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_controller.ctp
+++ /dev/null
@@ -1,91 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', 'Missing Controller');
-$this->assign('templateName', 'missing_controller.ctp');
-
-?>
-start('subheading');?>
-Error:
-
- Your routing resulted in = h($originalClass) ?> as a controller name.
-
- = h($pluginDot . $class) ?>Controller could not be found.
-
-end() ?>
-
-
-start('file'); ?>
-
- The controller name = h($originalClass) ?> has not been properly inflected, and
- could not be resolved to a controller that exists in your application.
-
- Ensure that your URL = h($this->request->getUri()->getPath()) ?> is
- using the same inflection style as your routes do. By default applications use DashedRoute
- and URLs should use - to separate multi-word controller names.
-
-
- In the case you tried to access a plugin controller make sure you added it to your composer file or you use the autoload option for the plugin.
-
-
- Error:
- Create the class = h($class) ?>Controller below in file: = h($path) ?>
-
-
-
-
-
-end(); ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_datasource.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_datasource.ctp
deleted file mode 100644
index 2102d821a..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_datasource.ctp
+++ /dev/null
@@ -1,29 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', 'Missing Datasource');
-$this->assign('templateName', 'missing_datasource.ctp');
-
-$this->start('subheading');
-?>
-Error:
-Datasource class = h($pluginDot . $class) ?> could not be found.
-
- = h($message); ?>
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_datasource_config.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_datasource_config.ctp
deleted file mode 100644
index 05b0fa153..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_datasource_config.ctp
+++ /dev/null
@@ -1,29 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', 'Missing Datasource Configuration');
-$this->assign('templateName', 'missing_datasource_config.ctp');
-
-$this->start('subheading');
-?>
- Error:
-
- The datasource configuration = h($name) ?> was not found in config= DIRECTORY_SEPARATOR . 'app.php' ?>.
-
- = h($message) ?>
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_helper.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_helper.ctp
deleted file mode 100644
index a7a7850f2..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_helper.ctp
+++ /dev/null
@@ -1,65 +0,0 @@
-layout = 'dev_error';
-$this->assign('title', 'Missing Helper');
-$this->assign('templateName', 'missing_helper.ctp');
-
-$this->start('subheading');
-?>
- Error:
- = h($pluginDot . $class) ?> could not be found.
- = $this->element('plugin_class_error', ['pluginPath' => $pluginPath]) ?>
-end() ?>
-
-start('file') ?>
-
- Error:
- = sprintf('Create the class %s below in file: %s', h($class), $filePath . 'View' . DIRECTORY_SEPARATOR . 'Helper' . DIRECTORY_SEPARATOR . h($class) . '.php'); ?>
-
-
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_layout.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_layout.ctp
deleted file mode 100644
index d53649b3d..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_layout.ctp
+++ /dev/null
@@ -1,42 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', 'Missing Layout');
-$this->assign('templateName', 'missing_layout.ctp');
-
-$this->start('subheading');
-?>
- Error:
- The layout file = h($file) ?> can not be found or does not exist.
-end() ?>
-
-start('file') ?>
-
- Confirm you have created the file: = h($file) ?> in one of the following paths:
-
-
-_paths($this->plugin);
- foreach ($paths as $path):
- if (strpos($path, CORE_PATH) !== false) {
- continue;
- }
- echo sprintf('- %s%s
', h($path), h($file));
- endforeach;
-?>
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_plugin.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_plugin.ctp
deleted file mode 100644
index 73e4fb121..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_plugin.ctp
+++ /dev/null
@@ -1,49 +0,0 @@
-layout = 'dev_error';
-
-$pluginPath = Configure::read('App.paths.plugins.0');
-
-$this->assign('title', 'Missing Plugin');
-$this->assign('templateName', 'missing_plugin.ctp');
-
-$this->start('subheading');
-?>
- Error:
- The application is trying to load a file from the = h($plugin) ?> plugin.
-
-
- Make sure your plugin = h($plugin) ?> is in the = h($pluginPath) ?> directory and was loaded.
-end() ?>
-
-start('file') ?>
-addPlugin('{$plugin}');
-}
-PHP;
-
-?>
-
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_route.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_route.ctp
deleted file mode 100644
index 4a248c93e..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_route.ctp
+++ /dev/null
@@ -1,59 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', 'Missing Route');
-$this->assign('templateName', 'missing_route.ctp');
-
-$attributes = $error->getAttributes();
-
-$this->start('subheading');
-?>
- Error:
- = h($error->getMessage()); ?>
-end() ?>
-
-start('file') ?>
-None of the currently connected routes match the provided parameters.
-Add a matching route to = 'config' . DIRECTORY_SEPARATOR . 'routes.php' ?>
-
-
-The passed context was:
-
-= h(Debugger::exportVar($attributes['context'])); ?>
-
-
-
-Connected Routes
-
-Template Defaults Options
-';
- printf(
- '%s %s %s ',
- h($route->template),
- h(Debugger::exportVar($route->defaults)),
- h(Debugger::exportVar($route->options))
- );
- echo '';
-endforeach;
-?>
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_template.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_template.ctp
deleted file mode 100644
index d2529f67c..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_template.ctp
+++ /dev/null
@@ -1,55 +0,0 @@
-layout = 'dev_error';
-
-$this->assign('title', 'Missing Template');
-$this->assign('templateName', 'missing_template.ctp');
-
-$isEmail = strpos($file, 'Email/') === 0;
-
-$this->start('subheading');
-?>
-
- Error:
- = sprintf('The template %s was not found.', h($file)); ?>
-
- Error:
- = sprintf(
- 'The view for %sController::%s() was not found.',
- h(Inflector::camelize($this->request->getParam('controller'))),
- h($this->request->getParam('action'))
- ); ?>
-
-end() ?>
-
-start('file') ?>
-
- = sprintf('Confirm you have created the file: "%s"', h($file)) ?>
- in one of the following paths:
-
-
-_paths($this->plugin);
- foreach ($paths as $path):
- if (strpos($path, CORE_PATH) !== false) {
- continue;
- }
- echo sprintf('- %s%s
', h($path), h($file));
- endforeach;
-?>
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/missing_view.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/missing_view.ctp
deleted file mode 100644
index f92d51736..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/missing_view.ctp
+++ /dev/null
@@ -1,67 +0,0 @@
-layout = 'dev_error';
-$this->assign('title', 'Missing View');
-$this->assign('templateName', 'missing_view.ctp');
-
-$this->start('subheading');
-?>
- Error:
- = h($pluginDot . $class) ?> could not be found.
-
- Make sure your plugin = h($plugin) ?> is in the = h($pluginPath) ?> directory and was loaded.
-
- = $this->element('plugin_class_error', ['pluginPath' => $pluginPath]) ?>
-
-end() ?>
-
-start('file') ?>
-
- Error:
- = sprintf('Create the class %s below in file: %s', h($class), $filePath . 'View' . DIRECTORY_SEPARATOR . h($class) . '.php'); ?>
-
-
-
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Error/pdo_error.ctp b/app/vendor/cakephp/cakephp/src/Template/Error/pdo_error.ctp
deleted file mode 100644
index 154fb2538..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Error/pdo_error.ctp
+++ /dev/null
@@ -1,44 +0,0 @@
-setLayout('dev_error');
-
-$this->assign('title', 'Database Error');
-$this->assign('templateName', 'pdo_error.ctp');
-
-$this->start('subheading');
-?>
- Error:
- = h($message); ?>
-end() ?>
-
-start('file') ?>
-
- If you are using SQL keywords as table column names, you can enable identifier
- quoting for your database connection in config/app.php.
-
-queryString)) : ?>
-
- SQL Query:
-
- = h($error->queryString); ?>
-
-params)) : ?>
- SQL Query Params:
- = h(Debugger::dump($error->params)); ?>
-
-= $this->element('auto_table_warning'); ?>
-end() ?>
diff --git a/app/vendor/cakephp/cakephp/src/Template/Layout/dev_error.ctp b/app/vendor/cakephp/cakephp/src/Template/Layout/dev_error.ctp
deleted file mode 100644
index f62bf42e4..000000000
--- a/app/vendor/cakephp/cakephp/src/Template/Layout/dev_error.ctp
+++ /dev/null
@@ -1,297 +0,0 @@
-
-
-
-
- = $this->Html->charset() ?>
-
-
- Error: = h($this->fetch('title')) ?>
-
- = $this->Html->meta('icon') ?>
-
-
-
-
-
- = h($this->fetch('title')) ?>
- = get_class($error) ?>
-
-
- Documentation
- API
-
-
-
-
- fetch('subheading')): ?>
-
- = $this->fetch('subheading') ?>
-
-
-
- = $this->element('exception_stack_trace'); ?>
-
-
- = $this->fetch('file') ?>
-
-
- fetch('templateName')): ?>
-
- If you want to customize this error message, create
- = APP_DIR . DIRECTORY_SEPARATOR . 'Template' . DIRECTORY_SEPARATOR . 'Error' . DIRECTORY_SEPARATOR . $this->fetch('templateName') ?>
-
-
-
-
-
- = $this->element('exception_stack_trace_nav') ?>
-
-
-
-
-
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/ConsoleIntegrationTestCase.php b/app/vendor/cakephp/cakephp/src/TestSuite/ConsoleIntegrationTestCase.php
index 25125c27b..5e42cdeae 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/ConsoleIntegrationTestCase.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/ConsoleIntegrationTestCase.php
@@ -1,4 +1,6 @@
|null
+ */
+ protected $_appClass;
+
+ /**
+ * The customized application constructor arguments.
+ *
+ * @var array|null
+ */
+ protected $_appArgs;
+
/**
* Last exit code
*
@@ -51,21 +69,21 @@ trait ConsoleIntegrationTestTrait
/**
* Console output stub
*
- * @var \Cake\TestSuite\Stub\ConsoleOutput|\PHPUnit_Framework_MockObject_MockObject|null
+ * @var \Cake\TestSuite\Stub\ConsoleOutput
*/
protected $_out;
/**
* Console error output stub
*
- * @var \Cake\TestSuite\Stub\ConsoleOutput|\PHPUnit_Framework_MockObject_MockObject|null
+ * @var \Cake\TestSuite\Stub\ConsoleOutput
*/
protected $_err;
/**
* Console input mock
*
- * @var \Cake\Console\ConsoleInput|\PHPUnit_Framework_MockObject_MockObject|null
+ * @var \Cake\Console\ConsoleInput
*/
protected $_in;
@@ -74,15 +92,25 @@ trait ConsoleIntegrationTestTrait
*
* @param string $command Command to run
* @param array $input Input values to pass to an interactive shell
+ * @throws \Cake\TestSuite\Stub\MissingConsoleInputException
+ * @throws \RuntimeException
* @return void
*/
- public function exec($command, array $input = [])
+ public function exec(string $command, array $input = []): void
{
$runner = $this->makeRunner();
- $this->_out = new ConsoleOutput();
- $this->_err = new ConsoleOutput();
- $this->_in = new ConsoleInput($input);
+ if ($this->_out === null) {
+ $this->_out = new ConsoleOutput();
+ }
+ if ($this->_err === null) {
+ $this->_err = new ConsoleOutput();
+ }
+ if ($this->_in === null) {
+ $this->_in = new ConsoleInput($input);
+ } elseif ($input) {
+ throw new RuntimeException('You can use `$input` only if `$_in` property is null and will be reset.');
+ }
$args = $this->commandStringToArgs("cake $command");
$io = new ConsoleIo($this->_out, $this->_err, $this->_in);
@@ -105,14 +133,17 @@ public function exec($command, array $input = [])
*
* @after
* @return void
+ * @psalm-suppress PossiblyNullPropertyAssignmentValue
*/
- public function cleanupConsoleTrait()
+ public function cleanupConsoleTrait(): void
{
$this->_exitCode = null;
$this->_out = null;
$this->_err = null;
$this->_in = null;
$this->_useCommandRunner = false;
+ $this->_appClass = null;
+ $this->_appArgs = null;
}
/**
@@ -121,11 +152,25 @@ public function cleanupConsoleTrait()
*
* @return void
*/
- public function useCommandRunner()
+ public function useCommandRunner(): void
{
$this->_useCommandRunner = true;
}
+ /**
+ * Configure the application class to use in console integration tests.
+ *
+ * @param string $class The application class name.
+ * @param array|null $constructorArgs The constructor arguments for your application class.
+ * @return void
+ * @psalm-param class-string<\Cake\Core\ConsoleApplicationInterface> $class
+ */
+ public function configApplication(string $class, ?array $constructorArgs): void
+ {
+ $this->_appClass = $class;
+ $this->_appArgs = $constructorArgs;
+ }
+
/**
* Asserts shell exited with the expected code
*
@@ -133,7 +178,7 @@ public function useCommandRunner()
* @param string $message Failure message
* @return void
*/
- public function assertExitCode($expected, $message = '')
+ public function assertExitCode(int $expected, string $message = ''): void
{
$this->assertThat($expected, new ExitCode($this->_exitCode), $message);
}
@@ -166,7 +211,7 @@ public function assertExitError($message = '')
* @param string $message The message to output when the assertion fails.
* @return void
*/
- public function assertOutputEmpty($message = '')
+ public function assertOutputEmpty(string $message = ''): void
{
$this->assertThat(null, new ContentsEmpty($this->_out->messages(), 'output'), $message);
}
@@ -178,7 +223,7 @@ public function assertOutputEmpty($message = '')
* @param string $message Failure message
* @return void
*/
- public function assertOutputContains($expected, $message = '')
+ public function assertOutputContains(string $expected, string $message = ''): void
{
$this->assertThat($expected, new ContentsContain($this->_out->messages(), 'output'), $message);
}
@@ -190,7 +235,7 @@ public function assertOutputContains($expected, $message = '')
* @param string $message Failure message
* @return void
*/
- public function assertOutputNotContains($expected, $message = '')
+ public function assertOutputNotContains(string $expected, string $message = ''): void
{
$this->assertThat($expected, new ContentsNotContain($this->_out->messages(), 'output'), $message);
}
@@ -202,7 +247,7 @@ public function assertOutputNotContains($expected, $message = '')
* @param string $message Failure message
* @return void
*/
- public function assertOutputRegExp($pattern, $message = '')
+ public function assertOutputRegExp(string $pattern, string $message = ''): void
{
$this->assertThat($pattern, new ContentsRegExp($this->_out->messages(), 'output'), $message);
}
@@ -214,7 +259,7 @@ public function assertOutputRegExp($pattern, $message = '')
* @param string $message Failure message.
* @return void
*/
- protected function assertOutputContainsRow(array $row, $message = '')
+ protected function assertOutputContainsRow(array $row, string $message = ''): void
{
$this->assertThat($row, new ContentsContainRow($this->_out->messages(), 'output'), $message);
}
@@ -226,7 +271,7 @@ protected function assertOutputContainsRow(array $row, $message = '')
* @param string $message Failure message
* @return void
*/
- public function assertErrorContains($expected, $message = '')
+ public function assertErrorContains(string $expected, string $message = ''): void
{
$this->assertThat($expected, new ContentsContain($this->_err->messages(), 'error output'), $message);
}
@@ -238,7 +283,7 @@ public function assertErrorContains($expected, $message = '')
* @param string $message Failure message
* @return void
*/
- public function assertErrorRegExp($pattern, $message = '')
+ public function assertErrorRegExp(string $pattern, string $message = ''): void
{
$this->assertThat($pattern, new ContentsRegExp($this->_err->messages(), 'error output'), $message);
}
@@ -249,7 +294,7 @@ public function assertErrorRegExp($pattern, $message = '')
* @param string $message The message to output when the assertion fails.
* @return void
*/
- public function assertErrorEmpty($message = '')
+ public function assertErrorEmpty(string $message = ''): void
{
$this->assertThat(null, new ContentsEmpty($this->_err->messages(), 'error output'), $message);
}
@@ -257,14 +302,20 @@ public function assertErrorEmpty($message = '')
/**
* Builds the appropriate command dispatcher
*
- * @return CommandRunner|LegacyCommandRunner
+ * @return \Cake\Console\CommandRunner|\Cake\TestSuite\LegacyCommandRunner
*/
protected function makeRunner()
{
if ($this->_useCommandRunner) {
- $applicationClassName = Configure::read('App.namespace') . '\Application';
+ if ($this->_appClass) {
+ $appClass = $this->_appClass;
+ } else {
+ /** @psalm-var class-string<\Cake\Core\ConsoleApplicationInterface> */
+ $appClass = Configure::read('App.namespace') . '\Application';
+ }
+ $appArgs = $this->_appArgs ?: [CONFIG];
- return new CommandRunner(new $applicationClassName(CONFIG));
+ return new CommandRunner(new $appClass(...$appArgs));
}
return new LegacyCommandRunner();
@@ -274,9 +325,9 @@ protected function makeRunner()
* Creates an $argv array from a command string
*
* @param string $command Command string
- * @return array
+ * @return string[]
*/
- protected function commandStringToArgs($command)
+ protected function commandStringToArgs(string $command): array
{
$charCount = strlen($command);
$argv = [];
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsBase.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsBase.php
index c508d5ee9..f58953829 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsBase.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsBase.php
@@ -1,4 +1,6 @@
contents = implode(PHP_EOL, $contents);
$this->output = $output;
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsContain.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsContain.php
index e1cee959c..71978a6ab 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsContain.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsContain.php
@@ -1,4 +1,6 @@
contents, $other) !== false;
}
@@ -36,8 +38,8 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
- return sprintf('is in %s', $this->output);
+ return sprintf('is in %s,' . PHP_EOL . 'actual result:' . PHP_EOL . $this->contents, $this->output);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsContainRow.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsContainRow.php
index a9dabc3f9..3ee85920e 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsContainRow.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsContainRow.php
@@ -1,4 +1,6 @@
output);
}
@@ -51,8 +54,8 @@ public function toString()
* @param mixed $other Expected content
* @return string
*/
- public function failureDescription($other)
+ public function failureDescription($other): string
{
- return '`' . $this->exporter->shortenedExport($other) . '` ' . $this->toString();
+ return '`' . $this->exporter()->shortenedExport($other) . '` ' . $this->toString();
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsEmpty.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsEmpty.php
index 5b4d05e50..cbc96d2ce 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsEmpty.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsEmpty.php
@@ -1,4 +1,6 @@
contents === '';
}
@@ -36,7 +38,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return sprintf('%s is empty', $this->output);
}
@@ -47,7 +49,7 @@ public function toString()
* @param mixed $other Value
* @return string
*/
- protected function failureDescription($other)
+ protected function failureDescription($other): string
{
return $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsNotContain.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsNotContain.php
index 2cc3b7a78..9515c37d9 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsNotContain.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsNotContain.php
@@ -1,4 +1,6 @@
contents, $other) === false;
}
@@ -36,7 +38,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return sprintf('is not in %s', $this->output);
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsRegExp.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsRegExp.php
index 636e29fd0..e97b08540 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsRegExp.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ContentsRegExp.php
@@ -1,4 +1,6 @@
contents) > 0;
}
@@ -36,7 +38,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return sprintf('PCRE pattern found in %s', $this->output);
}
@@ -45,7 +47,7 @@ public function toString()
* @param mixed $other Expected
* @return string
*/
- public function failureDescription($other)
+ public function failureDescription($other): string
{
return '`' . $other . '` ' . $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ExitCode.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ExitCode.php
index 5635d18f7..660b629f3 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ExitCode.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Console/ExitCode.php
@@ -1,4 +1,6 @@
exitCode = $exitCode;
}
@@ -45,7 +45,7 @@ public function __construct($exitCode)
* @param mixed $other Constraint check
* @return bool
*/
- public function matches($other)
+ public function matches($other): bool
{
return $other === $this->exitCode;
}
@@ -55,8 +55,8 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
- return sprintf('matches exit code %d', $this->exitCode);
+ return sprintf('matches exit code %s', $this->exitCode ?? 'null');
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailConstraintBase.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailConstraintBase.php
index 157fea3e0..b9ab96ace 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailConstraintBase.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailConstraintBase.php
@@ -1,4 +1,6 @@
at = $at;
- parent::__construct();
}
/**
* Gets the email or emails to check
*
- * @return \Cake\Mailer\Email[]
+ * @return \Cake\Mailer\Message[]
*/
- public function getEmails()
+ public function getMessages()
{
- $emails = TestEmailTransport::getEmails();
+ $messages = TestEmailTransport::getMessages();
- if ($this->at !== null) {
- if (!isset($emails[$this->at])) {
+ if ($this->at) {
+ if (!isset($messages[$this->at])) {
return [];
}
- return [$emails[$this->at]];
+ return [$messages[$this->at]];
}
- return $emails;
+ return $messages;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContains.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContains.php
index 5269c270c..bbb5407c1 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContains.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContains.php
@@ -1,4 +1,6 @@
getEmails();
- foreach ($emails as $email) {
- $message = implode("\r\n", (array)$email->message($this->type));
+ $messages = $this->getMessages();
+ foreach ($messages as $message) {
+ $method = 'getBody' . ($this->type ? ucfirst($this->type) : 'String');
+ $message = $message->$method();
$other = preg_quote($other, '/');
if (preg_match("/$other/", $message) > 0) {
@@ -54,7 +57,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
if ($this->at) {
return sprintf('is in email #%d', $this->at);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsAttachment.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsAttachment.php
index 54b1c3d8d..731612482 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsAttachment.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsAttachment.php
@@ -1,4 +1,5 @@
getEmails();
+ $messages = $this->getMessages();
foreach ($messages as $message) {
foreach ($message->getAttachments() as $filename => $fileInfo) {
if ($filename === $expectedFilename && empty($expectedFileInfo)) {
@@ -52,7 +53,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
if ($this->at) {
return sprintf('is an attachment of email #%d', $this->at);
@@ -67,9 +68,9 @@ public function toString()
* @param mixed $other Value
* @return string
*/
- protected function failureDescription($other)
+ protected function failureDescription($other): string
{
- list($expectedFilename) = $other;
+ [$expectedFilename] = $other;
return '\'' . $expectedFilename . '\' ' . $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsHtml.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsHtml.php
index ef9bba312..d9a351196 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsHtml.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsHtml.php
@@ -1,4 +1,6 @@
at) {
return sprintf('is in the html message of email #%d', $this->at);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsText.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsText.php
index 4244ffa8e..a81fac490 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsText.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailContainsText.php
@@ -1,4 +1,6 @@
at) {
return sprintf('is in the text message of email #%d', $this->at);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailCount.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailCount.php
index c49beb5e8..d1242de59 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailCount.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailCount.php
@@ -1,4 +1,6 @@
getEmails()) === $other;
+ return count($this->getMessages()) === $other;
}
/**
@@ -37,7 +39,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'emails were sent';
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentFrom.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentFrom.php
index d23a2e158..6dea5243a 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentFrom.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentFrom.php
@@ -1,4 +1,6 @@
at) {
return sprintf('sent email #%d', $this->at);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentTo.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentTo.php
index a9dc6eefd..07126e3dc 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentTo.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentTo.php
@@ -1,4 +1,6 @@
at) {
return sprintf('was sent email #%d', $this->at);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentWith.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentWith.php
index f141b5f4b..46aa85fa2 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentWith.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/MailSentWith.php
@@ -1,4 +1,6 @@
method = $method;
}
+
parent::__construct($at);
}
@@ -47,48 +50,31 @@ public function __construct($at = null, $method = null)
* @param mixed $other Constraint check
* @return bool
*/
- public function matches($other)
+ public function matches($other): bool
{
- $emails = $this->getEmails();
+ $emails = $this->getMessages();
foreach ($emails as $email) {
- $value = $this->getValue($email);
- if ($value === $other) {
- return true;
- }
+ $value = $email->{'get' . ucfirst($this->method)}();
if (
- !is_array($other)
- && in_array($this->method, ['to', 'cc', 'bcc', 'from'])
+ in_array($this->method, ['to', 'cc', 'bcc', 'from', 'replyTo', 'sender'], true)
&& array_key_exists($other, $value)
) {
return true;
}
+ if ($value === $other) {
+ return true;
+ }
}
return false;
}
- /**
- * Read a value from the email
- *
- * @param \Cake\Mailer\Email $email The email to read properties from.
- * @return mixed
- */
- protected function getValue($email)
- {
- $viewBuilderMethods = ['template', 'layout', 'helpers', 'theme'];
- if (in_array($this->method, $viewBuilderMethods, true)) {
- return $email->viewBuilder()->{'get' . ucfirst($this->method)}();
- }
-
- return $email->{'get' . ucfirst($this->method)}();
- }
-
/**
* Assertion message string
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
if ($this->at) {
return sprintf('is in email #%d `%s`', $this->at, $this->method);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/NoMailSent.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/NoMailSent.php
index 159a9c6fa..0d7d48a5c 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/NoMailSent.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Email/NoMailSent.php
@@ -1,4 +1,6 @@
getEmails()) === 0;
+ return count($this->getMessages()) === 0;
}
/**
@@ -37,7 +39,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'no emails were sent';
}
@@ -48,7 +50,7 @@ public function toString()
* @param mixed $other Value
* @return string
*/
- protected function failureDescription($other)
+ protected function failureDescription($other): string
{
return $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/EventFired.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/EventFired.php
index 68658863d..dfb29f289 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/EventFired.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/EventFired.php
@@ -1,6 +1,21 @@
_eventManager = $eventManager;
if ($this->_eventManager->getEventList() === null) {
- throw new AssertionFailedError('The event manager you are asserting against is not configured to track events.');
+ throw new AssertionFailedError(
+ 'The event manager you are asserting against is not configured to track events.'
+ );
}
}
@@ -39,9 +55,11 @@ public function __construct($eventManager)
* @param mixed $other Constraint check
* @return bool
*/
- public function matches($other)
+ public function matches($other): bool
{
- return $this->_eventManager->getEventList()->hasEvent($other);
+ $list = $this->_eventManager->getEventList();
+
+ return $list === null ? false : $list->hasEvent($other);
}
/**
@@ -49,7 +67,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'was fired';
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/EventFiredWith.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/EventFiredWith.php
index d8dc42265..13ad4a171 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/EventFiredWith.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/EventFiredWith.php
@@ -1,7 +1,10 @@
_eventManager = $eventManager;
$this->_dataKey = $dataKey;
$this->_dataValue = $dataValue;
if ($this->_eventManager->getEventList() === null) {
- throw new AssertionFailedError('The event manager you are asserting against is not configured to track events.');
+ throw new AssertionFailedError(
+ 'The event manager you are asserting against is not configured to track events.'
+ );
}
}
@@ -57,18 +61,21 @@ public function __construct($eventManager, $dataKey, $dataValue)
*
* @param mixed $other Constraint check
* @return bool
+ * @throws \PHPUnit\Framework\AssertionFailedError
*/
- public function matches($other)
+ public function matches($other): bool
{
$firedEvents = [];
$list = $this->_eventManager->getEventList();
- $totalEvents = count($list);
- for ($e = 0; $e < $totalEvents; $e++) {
- $firedEvents[] = $list[$e];
+ if ($list !== null) {
+ $totalEvents = count($list);
+ for ($e = 0; $e < $totalEvents; $e++) {
+ $firedEvents[] = $list[$e];
+ }
}
$eventGroup = collection($firedEvents)
- ->groupBy(function (Event $event) {
+ ->groupBy(function (EventInterface $event): string {
return $event->getName();
})
->toArray();
@@ -77,16 +84,20 @@ public function matches($other)
return false;
}
+ /** @var \Cake\Event\EventInterface[] $events */
$events = $eventGroup[$other];
if (count($events) > 1) {
- throw new AssertionFailedError(sprintf('Event "%s" was fired %d times, cannot make data assertion', $other, count($events)));
+ throw new AssertionFailedError(sprintf(
+ 'Event "%s" was fired %d times, cannot make data assertion',
+ $other,
+ count($events)
+ ));
}
- /** @var \Cake\Event\Event $event */
$event = $events[0];
- if (array_key_exists($this->_dataKey, $event->getData()) === false) {
+ if (array_key_exists($this->_dataKey, (array)$event->getData()) === false) {
return false;
}
@@ -98,7 +109,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'was fired with ' . $this->_dataKey . ' matching ' . (string)$this->_dataValue;
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyContains.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyContains.php
index 6ab1669f9..357f6bee3 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyContains.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyContains.php
@@ -1,4 +1,6 @@
ignoreCase) {
@@ -61,7 +63,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'is in response body';
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyEmpty.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyEmpty.php
index 77eed2c03..1f74ed403 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyEmpty.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyEmpty.php
@@ -1,4 +1,6 @@
_getBodyAsString());
}
@@ -36,7 +38,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'response body is empty';
}
@@ -47,7 +49,7 @@ public function toString()
* @param mixed $other Value
* @return string
*/
- protected function failureDescription($other)
+ protected function failureDescription($other): string
{
return $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyEquals.php
index 1e785a9c0..5d8bfea56 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyEquals.php
@@ -1,4 +1,6 @@
_getBodyAsString() === $other;
}
@@ -36,7 +38,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'matches response body';
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyNotContains.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyNotContains.php
index a71f5f8d3..7914cfe3d 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyNotContains.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/BodyNotContains.php
@@ -1,4 +1,6 @@
_getBodyAsString()) > 0;
}
@@ -36,7 +38,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'PCRE pattern found in response body';
}
@@ -45,7 +47,7 @@ public function toString()
* @param mixed $other Expected
* @return string
*/
- public function failureDescription($other)
+ public function failureDescription($other): string
{
return '`' . $other . '`' . ' ' . $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ContentType.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ContentType.php
index b166f66df..93b38d912 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ContentType.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ContentType.php
@@ -1,4 +1,6 @@
response->getMimeType($other);
if ($alias !== false) {
@@ -41,7 +48,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'is set as the Content-Type (`' . $this->response->getType() . '`)';
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEncryptedEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEncryptedEquals.php
index a0e055d03..7cc9ff58c 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEncryptedEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEncryptedEquals.php
@@ -1,4 +1,6 @@
response->getCookie($this->cookieName);
- return $this->_decrypt($cookie['value'], $this->mode) === $other;
+ return $cookie !== null && $this->_decrypt($cookie['value'], $this->mode) === $other;
}
/**
@@ -70,7 +76,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return sprintf('is encrypted in cookie \'%s\'', $this->cookieName);
}
@@ -80,7 +86,7 @@ public function toString()
*
* @return string
*/
- protected function _getCookieEncryptionKey()
+ protected function _getCookieEncryptionKey(): string
{
return $this->key;
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEquals.php
index cbe7684a8..3b5ca1081 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEquals.php
@@ -1,4 +1,6 @@
response->getCookie($this->cookieName);
- return $cookie['value'] === $other;
+ return $cookie !== null && $cookie['value'] === $other;
}
/**
@@ -58,7 +65,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return sprintf('is in cookie \'%s\'', $this->cookieName);
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieNotSet.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieNotSet.php
index 1b2d30a66..bfd7fa7c6 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieNotSet.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieNotSet.php
@@ -1,4 +1,6 @@
response->getCookie($other);
@@ -38,7 +45,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'cookie is set';
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/FileSent.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/FileSent.php
index 1ddeda3fd..e11e21f0c 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/FileSent.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/FileSent.php
@@ -1,4 +1,6 @@
response->getFile() !== null;
}
@@ -36,7 +43,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'file was sent';
}
@@ -47,7 +54,7 @@ public function toString()
* @param mixed $other Value
* @return string
*/
- protected function failureDescription($other)
+ protected function failureDescription($other): string
{
return $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/FileSentAs.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/FileSentAs.php
index 0dbd5b7f6..5c995af59 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/FileSentAs.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/FileSentAs.php
@@ -1,4 +1,6 @@
response->getFile()->path === $other;
+ /** @psalm-suppress PossiblyNullReference */
+ return $this->response->getFile()->getPathName() === $other;
}
/**
@@ -36,7 +44,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return 'file was sent';
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderContains.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderContains.php
index 39cd80974..c0e1bb181 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderContains.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderContains.php
@@ -1,4 +1,6 @@
response->getHeaderLine($this->headerName), $other) !== false;
}
@@ -36,8 +38,12 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
- return sprintf('is in header \'%s\' (`%s`)', $this->headerName, $this->response->getHeaderLine($this->headerName));
+ return sprintf(
+ 'is in header \'%s\' (`%s`)',
+ $this->headerName,
+ $this->response->getHeaderLine($this->headerName)
+ );
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderEquals.php
index f3ded3130..35bace044 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderEquals.php
@@ -1,4 +1,6 @@
response->getHeaderLine($this->headerName) === $other;
}
@@ -56,7 +58,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
$responseHeader = $this->response->getHeaderLine($this->headerName);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderNotContains.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderNotContains.php
index 132acee71..51f29a923 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderNotContains.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderNotContains.php
@@ -1,4 +1,6 @@
headerName, $this->response->getHeaderLine($this->headerName));
+ return sprintf(
+ "is not in header '%s' (`%s`)",
+ $this->headerName,
+ $this->response->getHeaderLine($this->headerName)
+ );
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderNotSet.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderNotSet.php
index 2f61e3805..671090fd8 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderNotSet.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderNotSet.php
@@ -1,4 +1,6 @@
headerName);
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderSet.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderSet.php
index 4e3910627..9fc5e4843 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderSet.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/HeaderSet.php
@@ -1,4 +1,6 @@
response->hasHeader($this->headerName);
}
@@ -56,7 +58,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return sprintf('response has header \'%s\'', $this->headerName);
}
@@ -67,7 +69,7 @@ public function toString()
* @param mixed $other Value
* @return string
*/
- protected function failureDescription($other)
+ protected function failureDescription($other): string
{
return $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ResponseBase.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ResponseBase.php
index 3427bf3c9..2ba009db5 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ResponseBase.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ResponseBase.php
@@ -1,4 +1,6 @@
response->getBody();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusCode.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusCode.php
index a4f385169..c2387bc99 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusCode.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusCode.php
@@ -1,4 +1,6 @@
response->getStatusCode());
}
@@ -36,7 +38,7 @@ public function toString()
* @param mixed $other Expected code
* @return string
*/
- public function failureDescription($other)
+ public function failureDescription($other): string
{
return '`' . $other . '` ' . $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusCodeBase.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusCodeBase.php
index 4f61292ee..5e4fc70b8 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusCodeBase.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusCodeBase.php
@@ -1,4 +1,6 @@
code;
@@ -51,7 +54,7 @@ public function matches($other)
* @param int $max Max status code (inclusive)
* @return bool
*/
- protected function statusCodeBetween($min, $max)
+ protected function statusCodeBetween(int $min, int $max): bool
{
return $this->response->getStatusCode() >= $min && $this->response->getStatusCode() <= $max;
}
@@ -62,7 +65,7 @@ protected function statusCodeBetween($min, $max)
* @param mixed $other Value
* @return string
*/
- protected function failureDescription($other)
+ protected function failureDescription($other): string
{
return $this->toString();
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusError.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusError.php
index 12ccca60a..cd3e5712b 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusError.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusError.php
@@ -1,4 +1,6 @@
response->getStatusCode());
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusFailure.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusFailure.php
index 218d6f901..b77e43284 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusFailure.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusFailure.php
@@ -1,4 +1,6 @@
response->getStatusCode());
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusOk.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusOk.php
index b02d15e72..2497b08e6 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusOk.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusOk.php
@@ -1,4 +1,6 @@
response->getStatusCode());
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusSuccess.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusSuccess.php
index de16ed6dd..6752bdb6e 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusSuccess.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/StatusSuccess.php
@@ -1,4 +1,6 @@
response->getStatusCode());
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Session/FlashParamEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Session/FlashParamEquals.php
index 305e6d304..065943121 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Session/FlashParamEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Session/FlashParamEquals.php
@@ -1,4 +1,6 @@
enableRetainFlashMessages()` has been enabled for the test.';
@@ -73,11 +75,15 @@ public function __construct($session, $key, $param, $at = null)
* @param mixed $other Value to compare with
* @return bool
*/
- public function matches($other)
+ public function matches($other): bool
{
- $messages = (array)$this->session->read('Flash.' . $this->key);
+ // Server::run calls Session::close at the end of the request.
+ // Which means, that we cannot use Session object here to access the session data.
+ // Call to Session::read will start new session (and will erase the data).
+
+ $messages = (array)Hash::get($_SESSION, 'Flash.' . $this->key);
if ($this->at) {
- $messages = [$this->session->read('Flash.' . $this->key . '.' . $this->at)];
+ $messages = [Hash::get($_SESSION, 'Flash.' . $this->key . '.' . $this->at)];
}
foreach ($messages as $message) {
@@ -97,7 +103,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
if ($this->at !== null) {
return sprintf('is in \'%s\' %s #%d', $this->key, $this->param, $this->at);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Session/SessionEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Session/SessionEquals.php
index 81eb5ebd5..3df049e44 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Session/SessionEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Session/SessionEquals.php
@@ -1,4 +1,6 @@
session->read($this->path) === $other;
+ // Server::run calls Session::close at the end of the request.
+ // Which means, that we cannot use Session object here to access the session data.
+ // Call to Session::read will start new session (and will erase the data).
+ return Hash::get($_SESSION, $this->path) === $other;
}
/**
@@ -72,7 +77,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return sprintf('is in session path \'%s\'', $this->path);
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/View/LayoutFileEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/View/LayoutFileEquals.php
index ff3e2ce0b..650c4a968 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/View/LayoutFileEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/View/LayoutFileEquals.php
@@ -1,4 +1,6 @@
filename);
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/View/TemplateFileEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/View/TemplateFileEquals.php
index 3311c3a27..d55c73f4a 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/View/TemplateFileEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/View/TemplateFileEquals.php
@@ -1,4 +1,6 @@
filename = $filename;
}
@@ -45,7 +45,7 @@ public function __construct($filename)
* @param mixed $other Expected filename
* @return bool
*/
- public function matches($other)
+ public function matches($other): bool
{
return strpos($this->filename, $other) !== false;
}
@@ -55,7 +55,7 @@ public function matches($other)
*
* @return string
*/
- public function toString()
+ public function toString(): string
{
return sprintf('equals template file `%s`', $this->filename);
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/EmailAssertTrait.php b/app/vendor/cakephp/cakephp/src/TestSuite/EmailAssertTrait.php
deleted file mode 100644
index c1e1108f8..000000000
--- a/app/vendor/cakephp/cakephp/src/TestSuite/EmailAssertTrait.php
+++ /dev/null
@@ -1,292 +0,0 @@
-email(true)->send($content);
- }
-
- /**
- * Creates an email instance overriding its transport for testing purposes.
- *
- * @param bool $new Tells if new instance should forcibly be created.
- * @return \Cake\Mailer\Email
- */
- public function email($new = false)
- {
- if ($new || !$this->_email) {
- $this->_email = new Email();
- $this->_email->setProfile(['transport' => 'debug'] + $this->_email->getProfile());
- }
-
- return $this->_email;
- }
-
- /**
- * Generates mock for given mailer class.
- *
- * @param string $className The mailer's FQCN.
- * @param array $methods The methods to mock on the mailer.
- * @return \Cake\Mailer\Mailer|\PHPUnit_Framework_MockObject_MockObject
- */
- public function getMockForMailer($className, array $methods = [])
- {
- $name = current(array_slice(explode('\\', $className), -1));
-
- if (!in_array('profile', $methods, true)) {
- $methods[] = 'profile';
- }
-
- $mailer = $this->getMockBuilder($className)
- ->setMockClassName($name)
- ->setMethods($methods)
- ->setConstructorArgs([$this->email()])
- ->getMock();
-
- $mailer->expects($this->any())
- ->method('profile')
- ->willReturn($mailer);
-
- return $mailer;
- }
-
- /**
- * Asserts email content (both text and HTML) contains `$needle`.
- *
- * @param string $needle Text to look for.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailMessageContains($needle, $message = null)
- {
- $this->assertEmailHtmlMessageContains($needle, $message);
- $this->assertEmailTextMessageContains($needle, $message);
- }
-
- /**
- * Asserts HTML email content contains `$needle`.
- *
- * @param string $needle Text to look for.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailHtmlMessageContains($needle, $message = null)
- {
- $haystack = $this->email()->message('html');
- $this->assertTextContains($needle, $haystack, $message);
- }
-
- /**
- * Asserts text email content contains `$needle`.
- *
- * @param string $needle Text to look for.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailTextMessageContains($needle, $message = null)
- {
- $haystack = $this->email()->message('text');
- $this->assertTextContains($needle, $haystack, $message);
- }
-
- /**
- * Asserts email's subject contains `$expected`.
- *
- * @param string $expected Email's subject.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailSubject($expected, $message = null)
- {
- $result = $this->email()->getSubject();
- $this->assertSame($expected, $result, $message);
- }
-
- /**
- * Asserts email's sender email address and optionally name.
- *
- * @param string $email Sender's email address.
- * @param string|null $name Sender's name.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailFrom($email, $name = null, $message = null)
- {
- if ($name === null) {
- $name = $email;
- }
-
- $expected = [$email => $name];
- $result = $this->email()->getFrom();
- $this->assertSame($expected, $result, $message);
- }
-
- /**
- * Asserts email is CC'd to only one email address (and optionally name).
- *
- * @param string $email CC'd email address.
- * @param string|null $name CC'd person name.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailCc($email, $name = null, $message = null)
- {
- if ($name === null) {
- $name = $email;
- }
-
- $expected = [$email => $name];
- $result = $this->email()->getCc();
- $this->assertSame($expected, $result, $message);
- }
-
- /**
- * Asserts email CC'd addresses contain given email address (and
- * optionally name).
- *
- * @param string $email CC'd email address.
- * @param string|null $name CC'd person name.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailCcContains($email, $name = null, $message = null)
- {
- $result = $this->email()->getCc();
- $this->assertNotEmpty($result[$email], $message);
- if ($name !== null) {
- $this->assertEquals($result[$email], $name, $message);
- }
- }
-
- /**
- * Asserts email is BCC'd to only one email address (and optionally name).
- *
- * @param string $email BCC'd email address.
- * @param string|null $name BCC'd person name.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailBcc($email, $name = null, $message = null)
- {
- if ($name === null) {
- $name = $email;
- }
-
- $expected = [$email => $name];
- $result = $this->email()->getBcc();
- $this->assertSame($expected, $result, $message);
- }
-
- /**
- * Asserts email BCC'd addresses contain given email address (and
- * optionally name).
- *
- * @param string $email BCC'd email address.
- * @param string|null $name BCC'd person name.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailBccContains($email, $name = null, $message = null)
- {
- $result = $this->email()->getBcc();
- $this->assertNotEmpty($result[$email], $message);
- if ($name !== null) {
- $this->assertEquals($result[$email], $name, $message);
- }
- }
-
- /**
- * Asserts email is sent to only the given recipient's address (and
- * optionally name).
- *
- * @param string $email Recipient's email address.
- * @param string|null $name Recipient's name.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailTo($email, $name = null, $message = null)
- {
- if ($name === null) {
- $name = $email;
- }
-
- $expected = [$email => $name];
- $result = $this->email()->getTo();
- $this->assertSame($expected, $result, $message);
- }
-
- /**
- * Asserts email recipients' list contains given email address (and
- * optionally name).
- *
- * @param string $email Recipient's email address.
- * @param string|null $name Recipient's name.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailToContains($email, $name = null, $message = null)
- {
- $result = $this->email()->getTo();
- $this->assertNotEmpty($result[$email], $message);
- if ($name !== null) {
- $this->assertEquals($result[$email], $name, $message);
- }
- }
-
- /**
- * Asserts the email attachments contain the given filename (and optionally
- * file info).
- *
- * @param string $filename Expected attachment's filename.
- * @param array|null $file Expected attachment's file info.
- * @param string|null $message The failure message to define.
- * @return void
- */
- public function assertEmailAttachmentsContains($filename, array $file = null, $message = null)
- {
- $result = $this->email()->getAttachments();
- $this->assertNotEmpty($result[$filename], $message);
- if ($file === null) {
- return;
- }
- $this->assertContains($file, $result, $message);
- $this->assertEquals($file, $result[$filename], $message);
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/EmailTrait.php b/app/vendor/cakephp/cakephp/src/TestSuite/EmailTrait.php
index fabc49542..fb54ad535 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/EmailTrait.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/EmailTrait.php
@@ -1,4 +1,6 @@
assertThat($count, new MailCount(), $message);
}
@@ -73,7 +75,7 @@ public function assertMailCount($count, $message = '')
* @param string $message Message
* @return void
*/
- public function assertNoMailSent($message = '')
+ public function assertNoMailSent(string $message = ''): void
{
$this->assertThat(null, new NoMailSent(), $message);
}
@@ -86,7 +88,7 @@ public function assertNoMailSent($message = '')
* @param string $message Message
* @return void
*/
- public function assertMailSentToAt($at, $address, $message = '')
+ public function assertMailSentToAt(int $at, string $address, string $message = ''): void
{
$this->assertThat($address, new MailSentTo($at), $message);
}
@@ -95,11 +97,11 @@ public function assertMailSentToAt($at, $address, $message = '')
* Asserts an email at a specific index was sent from an address
*
* @param int $at Email index
- * @param string|array $address Email address or [$emailAddress => $displayName].
+ * @param string $address Email address
* @param string $message Message
* @return void
*/
- public function assertMailSentFromAt($at, $address, $message = '')
+ public function assertMailSentFromAt(int $at, string $address, string $message = ''): void
{
$this->assertThat($address, new MailSentFrom($at), $message);
}
@@ -112,7 +114,7 @@ public function assertMailSentFromAt($at, $address, $message = '')
* @param string $message Message
* @return void
*/
- public function assertMailContainsAt($at, $contents, $message = '')
+ public function assertMailContainsAt(int $at, string $contents, string $message = ''): void
{
$this->assertThat($contents, new MailContains($at), $message);
}
@@ -125,7 +127,7 @@ public function assertMailContainsAt($at, $contents, $message = '')
* @param string $message Message
* @return void
*/
- public function assertMailContainsHtmlAt($at, $contents, $message = '')
+ public function assertMailContainsHtmlAt(int $at, string $contents, string $message = ''): void
{
$this->assertThat($contents, new MailContainsHtml($at), $message);
}
@@ -138,7 +140,7 @@ public function assertMailContainsHtmlAt($at, $contents, $message = '')
* @param string $message Message
* @return void
*/
- public function assertMailContainsTextAt($at, $contents, $message = '')
+ public function assertMailContainsTextAt(int $at, string $contents, string $message = ''): void
{
$this->assertThat($contents, new MailContainsText($at), $message);
}
@@ -152,7 +154,7 @@ public function assertMailContainsTextAt($at, $contents, $message = '')
* @param string $message Message
* @return void
*/
- public function assertMailSentWithAt($at, $expected, $parameter, $message = '')
+ public function assertMailSentWithAt(int $at, string $expected, string $parameter, string $message = ''): void
{
$this->assertThat($expected, new MailSentWith($at, $parameter), $message);
}
@@ -164,7 +166,7 @@ public function assertMailSentWithAt($at, $expected, $parameter, $message = '')
* @param string $message Message
* @return void
*/
- public function assertMailSentTo($address, $message = '')
+ public function assertMailSentTo(string $address, string $message = ''): void
{
$this->assertThat($address, new MailSentTo(), $message);
}
@@ -172,11 +174,11 @@ public function assertMailSentTo($address, $message = '')
/**
* Asserts an email was sent from an address
*
- * @param string|array $address Email address or [$emailAddress => $displayName].
+ * @param string $address Email address
* @param string $message Message
* @return void
*/
- public function assertMailSentFrom($address, $message = '')
+ public function assertMailSentFrom(string $address, string $message = ''): void
{
$this->assertThat($address, new MailSentFrom(), $message);
}
@@ -188,7 +190,7 @@ public function assertMailSentFrom($address, $message = '')
* @param string $message Message
* @return void
*/
- public function assertMailContains($contents, $message = '')
+ public function assertMailContains(string $contents, string $message = ''): void
{
$this->assertThat($contents, new MailContains(), $message);
}
@@ -201,7 +203,7 @@ public function assertMailContains($contents, $message = '')
* @param string $message Message
* @return void
*/
- public function assertMailContainsAttachment($filename, array $file = [], $message = '')
+ public function assertMailContainsAttachment(string $filename, array $file = [], string $message = ''): void
{
$this->assertThat([$filename, $file], new MailContainsAttachment(), $message);
}
@@ -213,7 +215,7 @@ public function assertMailContainsAttachment($filename, array $file = [], $messa
* @param string $message Message
* @return void
*/
- public function assertMailContainsHtml($contents, $message = '')
+ public function assertMailContainsHtml(string $contents, string $message = ''): void
{
$this->assertThat($contents, new MailContainsHtml(), $message);
}
@@ -221,13 +223,13 @@ public function assertMailContainsHtml($contents, $message = '')
/**
* Asserts an email contains an expected text content
*
- * @param string $expectedText Expected text.
+ * @param string $expected Expected text.
* @param string $message Message to display if assertion fails.
* @return void
*/
- public function assertMailContainsText($expectedText, $message = '')
+ public function assertMailContainsText(string $expected, string $message = ''): void
{
- $this->assertThat($expectedText, new MailContainsText(), $message);
+ $this->assertThat($expected, new MailContainsText(), $message);
}
/**
@@ -238,7 +240,7 @@ public function assertMailContainsText($expectedText, $message = '')
* @param string $message Message
* @return void
*/
- public function assertMailSentWith($expected, $parameter, $message = '')
+ public function assertMailSentWith(string $expected, string $parameter, string $message = ''): void
{
$this->assertThat($expected, new MailSentWith(null, $parameter), $message);
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureInjector.php b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureInjector.php
index 2dc067d63..d858fdeee 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureInjector.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureInjector.php
@@ -1,4 +1,6 @@
_first)) {
$this->_first = $suite;
@@ -76,7 +79,7 @@ public function startTestSuite(TestSuite $suite)
* @param \PHPUnit\Framework\TestSuite $suite The test suite
* @return void
*/
- public function endTestSuite(TestSuite $suite)
+ public function endTestSuite(TestSuite $suite): void
{
if ($this->_first === $suite) {
$this->_fixtureManager->shutDown();
@@ -89,8 +92,9 @@ public function endTestSuite(TestSuite $suite)
* @param \PHPUnit\Framework\Test $test The test case
* @return void
*/
- public function startTest(Test $test)
+ public function startTest(Test $test): void
{
+ /** @psalm-suppress NoInterfaceProperties */
$test->fixtureManager = $this->_fixtureManager;
if ($test instanceof TestCase) {
$this->_fixtureManager->fixturize($test);
@@ -105,7 +109,7 @@ public function startTest(Test $test)
* @param float $time current time
* @return void
*/
- public function endTest(Test $test, $time)
+ public function endTest(Test $test, float $time): void
{
if ($test instanceof TestCase) {
$this->_fixtureManager->unload($test);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureManager.php b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureManager.php
index 88af335b3..a8bbbd1dc 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureManager.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureManager.php
@@ -1,4 +1,6 @@
_debug = $debug;
}
@@ -90,7 +94,7 @@ public function setDebug($debug)
* @param \Cake\TestSuite\TestCase $test The test case to inspect.
* @return void
*/
- public function fixturize($test)
+ public function fixturize(TestCase $test): void
{
$this->_initDb();
if (!$test->getFixtures() || !empty($this->_processed[get_class($test)])) {
@@ -103,9 +107,9 @@ public function fixturize($test)
/**
* Get the loaded fixtures.
*
- * @return array
+ * @return \Cake\Datasource\FixtureInterface[]
*/
- public function loaded()
+ public function loaded(): array
{
return $this->_loaded;
}
@@ -118,7 +122,7 @@ public function loaded()
*
* @return void
*/
- protected function _aliasConnections()
+ protected function _aliasConnections(): void
{
$connections = ConnectionManager::configured();
ConnectionManager::alias('test', 'default');
@@ -146,7 +150,7 @@ protected function _aliasConnections()
*
* @return void
*/
- protected function _initDb()
+ protected function _initDb(): void
{
if ($this->_initialized) {
return;
@@ -162,7 +166,7 @@ protected function _initDb()
* @return void
* @throws \UnexpectedValueException when a referenced fixture does not exist.
*/
- protected function _loadFixtures($test)
+ protected function _loadFixtures(TestCase $test): void
{
$fixtures = $test->getFixtures();
if (!$fixtures) {
@@ -174,7 +178,7 @@ protected function _loadFixtures($test)
}
if (strpos($fixture, '.')) {
- list($type, $pathName) = explode('.', $fixture, 2);
+ [$type, $pathName] = explode('.', $fixture, 2);
$path = explode('/', $pathName);
$name = array_pop($path);
$additionalPath = implode('\\', $path);
@@ -184,44 +188,16 @@ protected function _loadFixtures($test)
} elseif ($type === 'app') {
$baseNamespace = Configure::read('App.namespace');
} elseif ($type === 'plugin') {
- list($plugin, $name) = explode('.', $pathName);
- // Flip vendored plugin separators
- $path = str_replace('/', '\\', $plugin);
- $uninflected = $path;
- $baseNamespace = Inflector::camelize(str_replace('\\', '\ ', $path));
- if ($baseNamespace !== $uninflected) {
- deprecationWarning(sprintf(
- 'Declaring fixtures in underscored format in TestCase::$fixtures is deprecated.' . "\n" .
- 'Expected "%s" instead in "%s".',
- str_replace('\\', '/', $baseNamespace),
- get_class($test)
- ));
- }
+ [$plugin, $name] = explode('.', $pathName);
+ $baseNamespace = str_replace('/', '\\', $plugin);
$additionalPath = null;
} else {
$baseNamespace = '';
$name = $fixture;
}
- $uninflected = $name;
- // Tweak subdirectory names, so camelize() can make the correct name
if (strpos($name, '/') > 0) {
$name = str_replace('/', '\\', $name);
- $uninflected = $name;
- $name = str_replace('\\', '\ ', $name);
- }
-
- $name = Inflector::camelize($name);
- if ($name !== $uninflected) {
- deprecationWarning(sprintf(
- 'Declaring fixtures in underscored format in TestCase::$fixtures is deprecated.' . "\n" .
- 'Found "%s.%s" in "%s". Expected "%s.%s" instead.',
- $type,
- $uninflected,
- get_class($test),
- $type,
- str_replace('\\', '/', $name)
- ));
}
$nameSegments = [
@@ -230,9 +206,12 @@ protected function _loadFixtures($test)
$additionalPath,
$name . 'Fixture',
];
+ /** @psalm-var class-string<\Cake\Datasource\FixtureInterface> */
$className = implode('\\', array_filter($nameSegments));
} else {
+ /** @psalm-var class-string<\Cake\Datasource\FixtureInterface> */
$className = $fixture;
+ /** @psalm-suppress PossiblyFalseArgument */
$name = preg_replace('/Fixture\z/', '', substr(strrchr($fixture, '\\'), 1));
}
@@ -255,13 +234,17 @@ protected function _loadFixtures($test)
* Runs the drop and create commands on the fixtures if necessary.
*
* @param \Cake\Datasource\FixtureInterface $fixture the fixture object to create
- * @param \Cake\Database\Connection $db The Connection object instance to use
+ * @param \Cake\Datasource\ConnectionInterface $db The Connection object instance to use
* @param string[] $sources The existing tables in the datasource.
* @param bool $drop whether drop the fixture if it is already created or not
* @return void
*/
- protected function _setupTable($fixture, $db, array $sources, $drop = true)
- {
+ protected function _setupTable(
+ FixtureInterface $fixture,
+ ConnectionInterface $db,
+ array $sources,
+ bool $drop = true
+ ): void {
$configName = $db->configName();
$isFixtureSetup = $this->isFixtureSetup($configName, $fixture);
if ($isFixtureSetup) {
@@ -269,11 +252,11 @@ protected function _setupTable($fixture, $db, array $sources, $drop = true)
}
$table = $fixture->sourceName();
- $exists = in_array($table, $sources);
+ $exists = in_array($table, $sources, true);
$hasSchema = $fixture instanceof TableSchemaAwareInterface && $fixture->getTableSchema() instanceof TableSchema;
- if (($drop && $exists) || ($exists && !$isFixtureSetup && $hasSchema)) {
+ if (($drop && $exists) || ($exists && $hasSchema)) {
$fixture->drop($db);
$fixture->create($db);
} elseif (!$exists) {
@@ -293,15 +276,16 @@ protected function _setupTable($fixture, $db, array $sources, $drop = true)
* @throws \Cake\Core\Exception\Exception When fixture records cannot be inserted.
* @throws \RuntimeException
*/
- public function load($test)
+ public function load(TestCase $test): void
{
$fixtures = $test->getFixtures();
- if (empty($fixtures) || !$test->autoFixtures) {
+ if (!$fixtures || !$test->autoFixtures) {
return;
}
try {
- $createTables = function ($db, $fixtures) use ($test) {
+ $createTables = function (ConnectionInterface $db, array $fixtures) use ($test): void {
+ /** @var \Cake\Datasource\FixtureInterface[] $fixtures */
$tables = $db->getSchemaCollection()->listTables();
$configName = $db->configName();
if (!isset($this->_insertionMap[$configName])) {
@@ -309,7 +293,11 @@ public function load($test)
}
foreach ($fixtures as $fixture) {
- if (in_array($fixture->table, $tables)) {
+ if (!$fixture instanceof ConstraintsInterface) {
+ continue;
+ }
+
+ if (in_array($fixture->sourceName(), $tables, true)) {
try {
$fixture->dropConstraints($db);
} catch (PDOException $e) {
@@ -325,7 +313,7 @@ public function load($test)
}
foreach ($fixtures as $fixture) {
- if (!in_array($fixture, $this->_insertionMap[$configName])) {
+ if (!in_array($fixture, $this->_insertionMap[$configName], true)) {
$this->_setupTable($fixture, $db, $tables, $test->dropTables);
} else {
$fixture->truncate($db);
@@ -333,6 +321,10 @@ public function load($test)
}
foreach ($fixtures as $fixture) {
+ if (!$fixture instanceof ConstraintsInterface) {
+ continue;
+ }
+
try {
$fixture->createConstraints($db);
} catch (PDOException $e) {
@@ -349,7 +341,7 @@ public function load($test)
$this->_runOperation($fixtures, $createTables);
// Use a separate transaction because of postgres.
- $insert = function ($db, $fixtures) use ($test) {
+ $insert = function (ConnectionInterface $db, array $fixtures) use ($test): void {
foreach ($fixtures as $fixture) {
try {
$fixture->insert($db);
@@ -371,7 +363,7 @@ public function load($test)
get_class($test),
$e->getMessage()
);
- throw new Exception($msg, null, $e);
+ throw new RuntimeException($msg, 0, $e);
}
}
@@ -382,36 +374,23 @@ public function load($test)
* @param callable $operation The operation to run on each connection + fixture set.
* @return void
*/
- protected function _runOperation($fixtures, $operation)
+ protected function _runOperation(array $fixtures, callable $operation): void
{
$dbs = $this->_fixtureConnections($fixtures);
foreach ($dbs as $connection => $fixtures) {
$db = ConnectionManager::get($connection);
- $newMethods = method_exists($db, 'isQueryLoggingEnabled');
- if ($newMethods) {
- $logQueries = $db->isQueryLoggingEnabled();
- } else {
- $logQueries = $db->logQueries();
- }
+ $logQueries = $db->isQueryLoggingEnabled();
if ($logQueries && !$this->_debug) {
- if ($newMethods) {
- $db->disableQueryLogging();
- } else {
- $db->logQueries(false);
- }
+ $db->disableQueryLogging();
}
- $db->transactional(function ($db) use ($fixtures, $operation) {
- $db->disableConstraints(function ($db) use ($fixtures, $operation) {
+ $db->transactional(function (ConnectionInterface $db) use ($fixtures, $operation): void {
+ $db->disableConstraints(function (ConnectionInterface $db) use ($fixtures, $operation): void {
$operation($db, $fixtures);
});
});
if ($logQueries) {
- if ($newMethods) {
- $db->enableQueryLogging(true);
- } else {
- $db->logQueries(true);
- }
+ $db->enableQueryLogging(true);
}
}
}
@@ -422,7 +401,7 @@ protected function _runOperation($fixtures, $operation)
* @param string[] $fixtures The array of fixtures a list of connections is needed from.
* @return array An array of connection names.
*/
- protected function _fixtureConnections($fixtures)
+ protected function _fixtureConnections(array $fixtures): array
{
$dbs = [];
foreach ($fixtures as $name) {
@@ -441,17 +420,20 @@ protected function _fixtureConnections($fixtures)
* @param \Cake\TestSuite\TestCase $test The test to inspect for fixture unloading.
* @return void
*/
- public function unload($test)
+ public function unload(TestCase $test): void
{
$fixtures = $test->getFixtures();
if (!$fixtures) {
return;
}
- $truncate = function ($db, $fixtures) {
+ $truncate = function (ConnectionInterface $db, array $fixtures): void {
$configName = $db->configName();
foreach ($fixtures as $name => $fixture) {
- if ($this->isFixtureSetup($configName, $fixture)) {
+ if (
+ $this->isFixtureSetup($configName, $fixture)
+ && $fixture instanceof ConstraintsInterface
+ ) {
$fixture->dropConstraints($db);
}
}
@@ -469,12 +451,13 @@ public function unload($test)
* Creates a single fixture table and loads data into it.
*
* @param string $name of the fixture
- * @param \Cake\Datasource\ConnectionInterface|null $db Connection instance or leave null to get a Connection from the fixture
+ * @param \Cake\Datasource\ConnectionInterface|null $db Connection instance or null
+ * to get a Connection from the fixture.
* @param bool $dropTables Whether or not tables should be dropped and re-created.
* @return void
* @throws \UnexpectedValueException if $name is not a previously loaded class
*/
- public function loadSingle($name, $db = null, $dropTables = true)
+ public function loadSingle(string $name, ?ConnectionInterface $db = null, bool $dropTables = true): void
{
if (!isset($this->_fixtureMap[$name])) {
throw new UnexpectedValueException(sprintf('Referenced fixture class %s not found', $name));
@@ -491,11 +474,15 @@ public function loadSingle($name, $db = null, $dropTables = true)
}
if (!$dropTables) {
- $fixture->dropConstraints($db);
+ if ($fixture instanceof ConstraintsInterface) {
+ $fixture->dropConstraints($db);
+ }
$fixture->truncate($db);
}
- $fixture->createConstraints($db);
+ if ($fixture instanceof ConstraintsInterface) {
+ $fixture->createConstraints($db);
+ }
$fixture->insert($db);
}
@@ -504,14 +491,15 @@ public function loadSingle($name, $db = null, $dropTables = true)
*
* @return void
*/
- public function shutDown()
+ public function shutDown(): void
{
- $shutdown = function ($db, $fixtures) {
+ $shutdown = function (ConnectionInterface $db, array $fixtures): void {
$connection = $db->configName();
+ /** @var \Cake\Datasource\FixtureInterface $fixture */
foreach ($fixtures as $fixture) {
if ($this->isFixtureSetup($connection, $fixture)) {
$fixture->drop($db);
- $index = array_search($fixture, $this->_insertionMap[$connection]);
+ $index = array_search($fixture, $this->_insertionMap[$connection], true);
unset($this->_insertionMap[$connection][$index]);
}
}
@@ -526,8 +514,8 @@ public function shutDown()
* @param \Cake\Datasource\FixtureInterface $fixture The fixture to check.
* @return bool
*/
- public function isFixtureSetup($connection, $fixture)
+ public function isFixtureSetup(string $connection, FixtureInterface $fixture): bool
{
- return isset($this->_insertionMap[$connection]) && in_array($fixture, $this->_insertionMap[$connection]);
+ return isset($this->_insertionMap[$connection]) && in_array($fixture, $this->_insertionMap[$connection], true);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php
index 9ee2a3dd1..a97dc8ac1 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php
@@ -1,4 +1,6 @@
table
+ static::class
);
throw new CakeException($message);
}
@@ -113,17 +116,17 @@ public function __construct()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function connection()
+ public function connection(): string
{
return $this->connection;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function sourceName()
+ public function sourceName(): string
{
return $this->table;
}
@@ -134,7 +137,7 @@ public function sourceName()
* @return void
* @throws \Cake\ORM\Exception\MissingTableClassException When importing from a table that does not exist.
*/
- public function init()
+ public function init(): void
{
if ($this->table === null) {
$this->table = $this->_tableFromClass();
@@ -158,9 +161,9 @@ public function init()
*
* @return string
*/
- protected function _tableFromClass()
+ protected function _tableFromClass(): string
{
- list(, $class) = namespaceSplit(get_class($this));
+ [, $class] = namespaceSplit(static::class);
preg_match('/^(.*)Fixture$/', $class, $matches);
$table = $class;
@@ -176,7 +179,7 @@ protected function _tableFromClass()
*
* @return void
*/
- protected function _schemaFromFields()
+ protected function _schemaFromFields(): void
{
$connection = ConnectionManager::get($this->connection());
$this->_schema = $connection->getDriver()->newTableSchema($this->table);
@@ -211,7 +214,7 @@ protected function _schemaFromFields()
* @return void
* @throws \Cake\Core\Exception\Exception when trying to import from an empty table.
*/
- protected function _schemaFromImport()
+ protected function _schemaFromImport(): void
{
if (!is_array($this->import)) {
return;
@@ -243,7 +246,7 @@ protected function _schemaFromImport()
* @return void
* @throws \Cake\Core\Exception\Exception when trying to reflect a table that does not exist
*/
- protected function _schemaFromReflection()
+ protected function _schemaFromReflection(): void
{
$db = ConnectionManager::get($this->connection());
$schemaCollection = $db->getSchemaCollection();
@@ -252,9 +255,9 @@ protected function _schemaFromReflection()
if (!in_array($this->table, $tables, true)) {
throw new CakeException(
sprintf(
- 'Cannot describe schema for table `%s` for fixture `%s` : the table does not exist.',
+ 'Cannot describe schema for table `%s` for fixture `%s`: the table does not exist.',
$this->table,
- get_class($this)
+ static::class
)
);
}
@@ -263,29 +266,9 @@ protected function _schemaFromReflection()
}
/**
- * Gets/Sets the TableSchema instance used by this fixture.
- *
- * @param \Cake\Database\Schema\TableSchema|null $schema The table to set.
- * @return \Cake\Database\Schema\TableSchema|null
- * @deprecated 3.5.0 Use getTableSchema/setTableSchema instead.
- */
- public function schema(TableSchema $schema = null)
- {
- deprecationWarning(
- 'TestFixture::schema() is deprecated. ' .
- 'Use TestFixture::setTableSchema()/getTableSchema() instead.'
- );
- if ($schema) {
- $this->setTableSchema($schema);
- }
-
- return $this->getTableSchema();
- }
-
- /**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function create(ConnectionInterface $db)
+ public function create(ConnectionInterface $db): bool
{
if (empty($this->_schema)) {
return false;
@@ -318,9 +301,9 @@ public function create(ConnectionInterface $db)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function drop(ConnectionInterface $db)
+ public function drop(ConnectionInterface $db): bool
{
if (empty($this->_schema)) {
return false;
@@ -343,15 +326,15 @@ public function drop(ConnectionInterface $db)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function insert(ConnectionInterface $db)
{
if (isset($this->records) && !empty($this->records)) {
- list($fields, $values, $types) = $this->_getRecords();
+ [$fields, $values, $types] = $this->_getRecords();
$query = $db->newQuery()
->insert($fields, $types)
- ->into($this->table);
+ ->into($this->sourceName());
foreach ($values as $row) {
$query->values($row);
@@ -366,9 +349,9 @@ public function insert(ConnectionInterface $db)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function createConstraints(ConnectionInterface $db)
+ public function createConstraints(ConnectionInterface $db): bool
{
if (empty($this->_constraints)) {
return true;
@@ -392,9 +375,9 @@ public function createConstraints(ConnectionInterface $db)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function dropConstraints(ConnectionInterface $db)
+ public function dropConstraints(ConnectionInterface $db): bool
{
if (empty($this->_constraints)) {
return true;
@@ -422,7 +405,7 @@ public function dropConstraints(ConnectionInterface $db)
*
* @return array
*/
- protected function _getRecords()
+ protected function _getRecords(): array
{
$fields = $values = $types = [];
$columns = $this->_schema->columns();
@@ -431,7 +414,9 @@ protected function _getRecords()
}
$fields = array_values(array_unique($fields));
foreach ($fields as $field) {
- $types[$field] = $this->_schema->getColumn($field)['type'];
+ /** @var array $column */
+ $column = $this->_schema->getColumn($field);
+ $types[$field] = $column['type'];
}
$default = array_fill_keys($fields, null);
foreach ($this->records as $record) {
@@ -442,9 +427,9 @@ protected function _getRecords()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function truncate(ConnectionInterface $db)
+ public function truncate(ConnectionInterface $db): bool
{
$sql = $this->_schema->truncateSql($db);
foreach ($sql as $stmt) {
@@ -455,7 +440,7 @@ public function truncate(ConnectionInterface $db)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getTableSchema()
{
@@ -463,9 +448,9 @@ public function getTableSchema()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function setTableSchema(DatabaseTableSchemaInterface $schema)
+ public function setTableSchema($schema)
{
$this->_schema = $schema;
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestCase.php b/app/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestCase.php
index af3d0ce74..be0cfb251 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestCase.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestCase.php
@@ -1,4 +1,6 @@
|null
*/
protected $_appClass;
@@ -104,14 +100,14 @@ trait IntegrationTestTrait
/**
* The response for the most recent request.
*
- * @var \Cake\Http\Response|null
+ * @var \Psr\Http\Message\ResponseInterface
*/
protected $_response;
/**
* The exception being thrown if the case.
*
- * @var \Exception|null
+ * @var \Throwable|null
*/
protected $_exception;
@@ -132,28 +128,28 @@ trait IntegrationTestTrait
/**
* The controller used in the last request.
*
- * @var \Cake\Controller\Controller|null
+ * @var \Cake\Controller\Controller
*/
protected $_controller;
/**
* The last rendered view
*
- * @var string|null
+ * @var string
*/
protected $_viewName;
/**
* The last rendered layout
*
- * @var string|null
+ * @var string
*/
protected $_layoutName;
/**
* The session instance from the last request
*
- * @var \Cake\Http\Session|null
+ * @var \Cake\Http\Session
*/
protected $_requestSession;
@@ -200,25 +196,14 @@ trait IntegrationTestTrait
*/
protected $_unlockedFields = [];
- /**
- * Auto-detect if the HTTP middleware stack should be used.
- *
- * @before
- * @return void
- */
- public function setupServer()
- {
- $namespace = Configure::read('App.namespace');
- $this->_useHttpServer = class_exists($namespace . '\Application');
- }
-
/**
* Clears the state used for requests.
*
* @after
* @return void
+ * @psalm-suppress PossiblyNullPropertyAssignmentValue
*/
- public function cleanup()
+ public function cleanup(): void
{
$this->_request = [];
$this->_session = [];
@@ -234,31 +219,17 @@ public function cleanup()
$this->_securityToken = false;
$this->_csrfToken = false;
$this->_retainFlashMessages = false;
- $this->_useHttpServer = false;
- }
-
- /**
- * Toggle whether or not you want to use the HTTP Server stack.
- *
- * @param bool $enable Enable/disable the usage of the HTTP Stack.
- * @return void
- */
- public function useHttpServer($enable)
- {
- $this->_useHttpServer = (bool)$enable;
}
/**
* Configure the application class to use in integration tests.
*
- * Combined with `useHttpServer()` to customize the class name and constructor arguments
- * of your application class.
- *
* @param string $class The application class name.
* @param array|null $constructorArgs The constructor arguments for your application class.
* @return void
+ * @psalm-param class-string<\Cake\Core\HttpApplicationInterface> $class
*/
- public function configApplication($class, $constructorArgs)
+ public function configApplication(string $class, ?array $constructorArgs): void
{
$this->_appClass = $class;
$this->_appArgs = $constructorArgs;
@@ -271,7 +242,7 @@ public function configApplication($class, $constructorArgs)
*
* @return void
*/
- public function enableSecurityToken()
+ public function enableSecurityToken(): void
{
$this->_securityToken = true;
}
@@ -282,7 +253,7 @@ public function enableSecurityToken()
* @param string[] $unlockedFields List of fields that are excluded from field validation.
* @return void
*/
- public function setUnlockedFields(array $unlockedFields = [])
+ public function setUnlockedFields(array $unlockedFields = []): void
{
$this->_unlockedFields = $unlockedFields;
}
@@ -295,7 +266,7 @@ public function setUnlockedFields(array $unlockedFields = [])
*
* @return void
*/
- public function enableCsrfToken()
+ public function enableCsrfToken(): void
{
$this->_csrfToken = true;
}
@@ -306,7 +277,7 @@ public function enableCsrfToken()
*
* @return void
*/
- public function enableRetainFlashMessages()
+ public function enableRetainFlashMessages(): void
{
$this->_retainFlashMessages = true;
}
@@ -322,7 +293,7 @@ public function enableRetainFlashMessages()
* @param array $data The request data to use.
* @return void
*/
- public function configRequest(array $data)
+ public function configRequest(array $data): void
{
$this->_request = $data + $this->_request;
}
@@ -340,7 +311,7 @@ public function configRequest(array $data)
* @param array $data The session data to use.
* @return void
*/
- public function session(array $data)
+ public function session(array $data): void
{
$this->_session = $data + $this->_session;
}
@@ -359,7 +330,7 @@ public function session(array $data)
* @param mixed $value The value of the cookie.
* @return void
*/
- public function cookie($name, $value)
+ public function cookie(string $name, $value): void
{
$this->_cookie[$name] = $value;
}
@@ -369,7 +340,7 @@ public function cookie($name, $value)
*
* @return string
*/
- protected function _getCookieEncryptionKey()
+ protected function _getCookieEncryptionKey(): string
{
if (isset($this->_cookieEncryptionKey)) {
return $this->_cookieEncryptionKey;
@@ -386,13 +357,13 @@ protected function _getCookieEncryptionKey()
*
* @param string $name The cookie name to use.
* @param mixed $value The value of the cookie.
- * @param string|bool $encrypt Encryption mode to use.
+ * @param string|false $encrypt Encryption mode to use.
* @param string|null $key Encryption key used. Defaults
* to Security.salt.
* @return void
* @see \Cake\Utility\CookieCryptTrait::_encrypt()
*/
- public function cookieEncrypted($name, $value, $encrypt = 'aes', $key = null)
+ public function cookieEncrypted(string $name, $value, $encrypt = 'aes', $key = null): void
{
$this->_cookieEncryptionKey = $key;
$this->_cookie[$name] = $this->_encrypt($value, $encrypt);
@@ -407,9 +378,8 @@ public function cookieEncrypted($name, $value, $encrypt = 'aes', $key = null)
*
* @param string|array $url The URL to request.
* @return void
- * @throws \PHPUnit\Exception
*/
- public function get($url)
+ public function get($url): void
{
$this->_sendRequest($url, 'GET');
}
@@ -422,11 +392,10 @@ public function get($url)
* response.
*
* @param string|array $url The URL to request.
- * @param string|array|null $data The data for the request.
+ * @param string|array $data The data for the request.
* @return void
- * @throws \PHPUnit\Exception
*/
- public function post($url, $data = [])
+ public function post($url, $data = []): void
{
$this->_sendRequest($url, 'POST', $data);
}
@@ -439,11 +408,10 @@ public function post($url, $data = [])
* response.
*
* @param string|array $url The URL to request.
- * @param string|array|null $data The data for the request.
+ * @param string|array $data The data for the request.
* @return void
- * @throws \PHPUnit\Exception
*/
- public function patch($url, $data = [])
+ public function patch($url, $data = []): void
{
$this->_sendRequest($url, 'PATCH', $data);
}
@@ -456,11 +424,10 @@ public function patch($url, $data = [])
* response.
*
* @param string|array $url The URL to request.
- * @param string|array|null $data The data for the request.
+ * @param string|array $data The data for the request.
* @return void
- * @throws \PHPUnit\Exception
*/
- public function put($url, $data = [])
+ public function put($url, $data = []): void
{
$this->_sendRequest($url, 'PUT', $data);
}
@@ -474,9 +441,8 @@ public function put($url, $data = [])
*
* @param string|array $url The URL to request.
* @return void
- * @throws \PHPUnit\Exception
*/
- public function delete($url)
+ public function delete($url): void
{
$this->_sendRequest($url, 'DELETE');
}
@@ -490,9 +456,8 @@ public function delete($url)
*
* @param string|array $url The URL to request.
* @return void
- * @throws \PHPUnit\Exception
*/
- public function head($url)
+ public function head($url): void
{
$this->_sendRequest($url, 'HEAD');
}
@@ -506,9 +471,8 @@ public function head($url)
*
* @param string|array $url The URL to request.
* @return void
- * @throws \PHPUnit\Exception
*/
- public function options($url)
+ public function options($url): void
{
$this->_sendRequest($url, 'OPTIONS');
}
@@ -520,11 +484,11 @@ public function options($url)
*
* @param string|array $url The URL
* @param string $method The HTTP method
- * @param string|array|null $data The request data.
+ * @param string|array $data The request data.
* @return void
- * @throws \PHPUnit\Exception
+ * @throws \PHPUnit\Exception|\Throwable
*/
- protected function _sendRequest($url, $method, $data = [])
+ protected function _sendRequest($url, $method, $data = []): void
{
$dispatcher = $this->_makeDispatcher();
$url = $dispatcher->resolveUrl($url);
@@ -537,13 +501,9 @@ protected function _sendRequest($url, $method, $data = [])
$this->_requestSession->write('Flash', $this->_flashMessages);
}
$this->_response = $response;
- } catch (PhpUnitException $e) {
- throw $e;
- } catch (DatabaseException $e) {
+ } catch (PHPUnitException | DatabaseException $e) {
throw $e;
- } catch (LogicException $e) {
- throw $e;
- } catch (Exception $e) {
+ } catch (Throwable $e) {
$this->_exception = $e;
// Simulate the global exception handler being invoked.
$this->_handleError($e);
@@ -553,25 +513,21 @@ protected function _sendRequest($url, $method, $data = [])
/**
* Get the correct dispatcher instance.
*
- * @return \Cake\TestSuite\MiddlewareDispatcher|\Cake\TestSuite\LegacyRequestDispatcher A dispatcher instance
+ * @return \Cake\TestSuite\MiddlewareDispatcher A dispatcher instance
*/
- protected function _makeDispatcher()
+ protected function _makeDispatcher(): MiddlewareDispatcher
{
- if ($this->_useHttpServer) {
- return new MiddlewareDispatcher($this, $this->_appClass, $this->_appArgs);
- }
-
- return new LegacyRequestDispatcher($this);
+ return new MiddlewareDispatcher($this, $this->_appClass, $this->_appArgs);
}
/**
* Adds additional event spies to the controller/view event manager.
*
- * @param \Cake\Event\Event $event A dispatcher event.
+ * @param \Cake\Event\EventInterface $event A dispatcher event.
* @param \Cake\Controller\Controller|null $controller Controller instance.
* @return void
*/
- public function controllerSpy($event, $controller = null)
+ public function controllerSpy(EventInterface $event, ?Controller $controller = null): void
{
if (!$controller) {
/** @var \Cake\Controller\Controller $controller */
@@ -579,15 +535,16 @@ public function controllerSpy($event, $controller = null)
}
$this->_controller = $controller;
$events = $controller->getEventManager();
- $events->on('View.beforeRender', function ($event, $viewFile) use ($controller) {
+ $events->on('View.beforeRender', function ($event, $viewFile) use ($controller): void {
if (!$this->_viewName) {
$this->_viewName = $viewFile;
}
if ($this->_retainFlashMessages) {
+ /** @psalm-suppress PossiblyInvalidPropertyAssignmentValue */
$this->_flashMessages = $controller->getRequest()->getSession()->read('Flash');
}
});
- $events->on('View.beforeLayout', function ($event, $viewFile) {
+ $events->on('View.beforeLayout', function ($event, $viewFile): void {
$this->_layoutName = $viewFile;
});
}
@@ -598,15 +555,14 @@ public function controllerSpy($event, $controller = null)
* This method will attempt to use the configured exception renderer.
* If that class does not exist, the built-in renderer will be used.
*
- * @param \Exception $exception Exception to handle.
+ * @param \Throwable $exception Exception to handle.
* @return void
- * @throws \Exception
*/
- protected function _handleError($exception)
+ protected function _handleError(Throwable $exception): void
{
$class = Configure::read('Error.exceptionRenderer');
if (empty($class) || !class_exists($class)) {
- $class = 'Cake\Error\ExceptionRenderer';
+ $class = ExceptionRenderer::class;
}
/** @var \Cake\Error\ExceptionRenderer $instance */
$instance = new $class($exception);
@@ -616,19 +572,19 @@ protected function _handleError($exception)
/**
* Creates a request object with the configured options and parameters.
*
- * @param string|array $url The URL
+ * @param string $url The URL
* @param string $method The HTTP method
- * @param string|array|null $data The request data.
+ * @param string|array $data The request data.
* @return array The request context
*/
- protected function _buildRequest($url, $method, $data)
+ protected function _buildRequest(string $url, $method, $data = []): array
{
$sessionConfig = (array)Configure::read('Session') + [
'defaults' => 'php',
];
$session = Session::create($sessionConfig);
$session->write($this->_session);
- list($url, $query, $hostInfo) = $this->_url($url);
+ [$url, $query, $hostInfo] = $this->_url($url);
$tokenUrl = $url;
if ($query) {
@@ -636,20 +592,6 @@ protected function _buildRequest($url, $method, $data)
}
parse_str($query, $queryData);
- $props = [
- 'url' => $url,
- 'session' => $session,
- 'query' => $queryData,
- 'files' => [],
- ];
- if (is_string($data)) {
- $props['input'] = $data;
- }
- if (!isset($props['input'])) {
- $data = $this->_addTokens($tokenUrl, $data);
- $props['post'] = $this->_castToString($data);
- }
- $props['cookies'] = $this->_cookie;
$env = [
'REQUEST_METHOD' => $method,
@@ -665,14 +607,35 @@ protected function _buildRequest($url, $method, $data)
if (isset($this->_request['headers'])) {
foreach ($this->_request['headers'] as $k => $v) {
$name = strtoupper(str_replace('-', '_', $k));
- if (!in_array($name, ['CONTENT_LENGTH', 'CONTENT_TYPE'])) {
+ if (!in_array($name, ['CONTENT_LENGTH', 'CONTENT_TYPE'], true)) {
$name = 'HTTP_' . $name;
}
$env[$name] = $v;
}
unset($this->_request['headers']);
}
- $props['environment'] = $env;
+ $props = [
+ 'url' => $url,
+ 'session' => $session,
+ 'query' => $queryData,
+ 'files' => [],
+ 'environment' => $env,
+ ];
+
+ if (is_string($data)) {
+ $props['input'] = $data;
+ } elseif (
+ is_array($data) &&
+ isset($props['environment']['CONTENT_TYPE']) &&
+ $props['environment']['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'
+ ) {
+ $props['input'] = http_build_query($data);
+ } else {
+ $data = $this->_addTokens($tokenUrl, $data);
+ $props['post'] = $this->_castToString($data);
+ }
+
+ $props['cookies'] = $this->_cookie;
$props = Hash::merge($props, $this->_request);
return $props;
@@ -685,7 +648,7 @@ protected function _buildRequest($url, $method, $data)
* @param array $data The request body data.
* @return array The request body with tokens added.
*/
- protected function _addTokens($url, $data)
+ protected function _addTokens(string $url, array $data): array
{
if ($this->_securityToken === true) {
$fields = array_diff_key($data, array_flip($this->_unlockedFields));
@@ -694,15 +657,21 @@ protected function _addTokens($url, $data)
return preg_replace('/(\.\d+)+$/', '', $field);
}, array_keys(Hash::flatten($fields)));
- $tokenData = $this->_buildFieldToken($url, array_unique($keys), $this->_unlockedFields);
+ $formProtector = new FormProtector(['unlockedFields' => $this->_unlockedFields]);
+ foreach ($keys as $field) {
+ /** @psalm-suppress PossiblyNullArgument */
+ $formProtector->addField($field);
+ }
+ $tokenData = $formProtector->buildTokenData($url, 'cli');
$data['_Token'] = $tokenData;
- $data['_Token']['debug'] = 'SecurityComponent debug data would be added here';
+ $data['_Token']['debug'] = 'FormProtector debug data would be added here';
}
if ($this->_csrfToken === true) {
+ $middleware = new CsrfProtectionMiddleware();
if (!isset($this->_cookie['csrfToken'])) {
- $this->_cookie['csrfToken'] = Text::uuid();
+ $this->_cookie['csrfToken'] = $middleware->createToken();
}
if (!isset($data['_csrfToken'])) {
$data['_csrfToken'] = $this->_cookie['csrfToken'];
@@ -719,7 +688,7 @@ protected function _addTokens($url, $data)
* @param array $data POST data
* @return array
*/
- protected function _castToString($data)
+ protected function _castToString(array $data): array
{
foreach ($data as $key => $value) {
if (is_scalar($value)) {
@@ -744,10 +713,10 @@ protected function _castToString($data)
/**
* Creates a valid request url and parameter array more like Request::_url()
*
- * @param string|array $url The URL
+ * @param string $url The URL
* @return array Qualified URL, the query parameters, and host data
*/
- protected function _url($url)
+ protected function _url(string $url): array
{
$uri = new Uri($url);
$path = $uri->getPath();
@@ -769,7 +738,7 @@ protected function _url($url)
*
* @return string The response body.
*/
- protected function _getBodyAsString()
+ protected function _getBodyAsString(): string
{
if (!$this->_response) {
$this->fail('No response set, cannot assert content.');
@@ -786,16 +755,9 @@ protected function _getBodyAsString()
* @param string $name The view variable to get.
* @return mixed The view variable if set.
*/
- public function viewVariable($name)
+ public function viewVariable(string $name)
{
- if (empty($this->_controller->viewVars)) {
- $this->fail('There are no view variables, perhaps you need to run a request?');
- }
- if (isset($this->_controller->viewVars[$name])) {
- return $this->_controller->viewVars[$name];
- }
-
- return null;
+ return $this->_controller ? $this->_controller->viewBuilder()->getVar($name) : null;
}
/**
@@ -804,7 +766,7 @@ public function viewVariable($name)
* @param string $message Custom message for failure.
* @return void
*/
- public function assertResponseOk($message = null)
+ public function assertResponseOk(string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new StatusOk($this->_response), $verboseMessage);
@@ -816,7 +778,7 @@ public function assertResponseOk($message = null)
* @param string $message Custom message for failure.
* @return void
*/
- public function assertResponseSuccess($message = null)
+ public function assertResponseSuccess(string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new StatusSuccess($this->_response), $verboseMessage);
@@ -828,7 +790,7 @@ public function assertResponseSuccess($message = null)
* @param string $message Custom message for failure.
* @return void
*/
- public function assertResponseError($message = null)
+ public function assertResponseError(string $message = ''): void
{
$this->assertThat(null, new StatusError($this->_response), $message);
}
@@ -839,7 +801,7 @@ public function assertResponseError($message = null)
* @param string $message Custom message for failure.
* @return void
*/
- public function assertResponseFailure($message = null)
+ public function assertResponseFailure(string $message = ''): void
{
$this->assertThat(null, new StatusFailure($this->_response), $message);
}
@@ -851,7 +813,7 @@ public function assertResponseFailure($message = null)
* @param string $message Custom message for failure.
* @return void
*/
- public function assertResponseCode($code, $message = null)
+ public function assertResponseCode(int $code, string $message = ''): void
{
$this->assertThat($code, new StatusCode($this->_response), $message);
}
@@ -865,13 +827,17 @@ public function assertResponseCode($code, $message = null)
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertRedirect($url = null, $message = '')
+ public function assertRedirect($url = null, $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
if ($url) {
- $this->assertThat(Router::url($url, ['_full' => true]), new HeaderEquals($this->_response, 'Location'), $verboseMessage);
+ $this->assertThat(
+ Router::url($url, true),
+ new HeaderEquals($this->_response, 'Location'),
+ $verboseMessage
+ );
}
}
@@ -901,7 +867,7 @@ public function assertRedirectEquals($url = null, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertRedirectContains($url, $message = '')
+ public function assertRedirectContains(string $url, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
@@ -915,7 +881,7 @@ public function assertRedirectContains($url, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertRedirectNotContains($url, $message = '')
+ public function assertRedirectNotContains(string $url, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
@@ -928,7 +894,7 @@ public function assertRedirectNotContains($url, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertNoRedirect($message = '')
+ public function assertNoRedirect(string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new HeaderNotSet($this->_response, 'Location'), $verboseMessage);
@@ -942,7 +908,7 @@ public function assertNoRedirect($message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertHeader($header, $content, $message = '')
+ public function assertHeader(string $header, string $content, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
@@ -957,7 +923,7 @@ public function assertHeader($header, $content, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertHeaderContains($header, $content, $message = '')
+ public function assertHeaderContains(string $header, string $content, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
@@ -972,7 +938,7 @@ public function assertHeaderContains($header, $content, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertHeaderNotContains($header, $content, $message = '')
+ public function assertHeaderNotContains(string $header, string $content, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
@@ -986,7 +952,7 @@ public function assertHeaderNotContains($header, $content, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertContentType($type, $message = '')
+ public function assertContentType(string $type, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($type, new ContentType($this->_response), $verboseMessage);
@@ -999,7 +965,7 @@ public function assertContentType($type, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertResponseEquals($content, $message = '')
+ public function assertResponseEquals($content, $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($content, new BodyEquals($this->_response), $verboseMessage);
@@ -1012,7 +978,7 @@ public function assertResponseEquals($content, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertResponseNotEquals($content, $message = '')
+ public function assertResponseNotEquals($content, $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($content, new BodyNotEquals($this->_response), $verboseMessage);
@@ -1026,7 +992,7 @@ public function assertResponseNotEquals($content, $message = '')
* @param bool $ignoreCase A flag to check whether we should ignore case or not.
* @return void
*/
- public function assertResponseContains($content, $message = '', $ignoreCase = false)
+ public function assertResponseContains(string $content, string $message = '', bool $ignoreCase = false): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($content, new BodyContains($this->_response, $ignoreCase), $verboseMessage);
@@ -1040,7 +1006,7 @@ public function assertResponseContains($content, $message = '', $ignoreCase = fa
* @param bool $ignoreCase A flag to check whether we should ignore case or not.
* @return void
*/
- public function assertResponseNotContains($content, $message = '', $ignoreCase = false)
+ public function assertResponseNotContains(string $content, string $message = '', bool $ignoreCase = false): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($content, new BodyNotContains($this->_response, $ignoreCase), $verboseMessage);
@@ -1053,7 +1019,7 @@ public function assertResponseNotContains($content, $message = '', $ignoreCase =
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertResponseRegExp($pattern, $message = '')
+ public function assertResponseRegExp(string $pattern, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($pattern, new BodyRegExp($this->_response), $verboseMessage);
@@ -1066,7 +1032,7 @@ public function assertResponseRegExp($pattern, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertResponseNotRegExp($pattern, $message = '')
+ public function assertResponseNotRegExp(string $pattern, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($pattern, new BodyNotRegExp($this->_response), $verboseMessage);
@@ -1078,7 +1044,7 @@ public function assertResponseNotRegExp($pattern, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertResponseNotEmpty($message = '')
+ public function assertResponseNotEmpty(string $message = ''): void
{
$this->assertThat(null, new BodyNotEmpty($this->_response), $message);
}
@@ -1089,7 +1055,7 @@ public function assertResponseNotEmpty($message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertResponseEmpty($message = '')
+ public function assertResponseEmpty(string $message = ''): void
{
$this->assertThat(null, new BodyEmpty($this->_response), $message);
}
@@ -1101,7 +1067,7 @@ public function assertResponseEmpty($message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertTemplate($content, $message = '')
+ public function assertTemplate(string $content, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($content, new TemplateFileEquals($this->_viewName), $verboseMessage);
@@ -1114,7 +1080,7 @@ public function assertTemplate($content, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertLayout($content, $message = '')
+ public function assertLayout(string $content, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($content, new LayoutFileEquals($this->_layoutName), $verboseMessage);
@@ -1123,12 +1089,12 @@ public function assertLayout($content, $message = '')
/**
* Asserts session contents
*
- * @param string $expected The expected contents.
+ * @param mixed $expected The expected contents.
* @param string $path The session data path. Uses Hash::get() compatible notation
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertSession($expected, $path, $message = '')
+ public function assertSession($expected, string $path, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($expected, new SessionEquals($this->_requestSession, $path), $verboseMessage);
@@ -1142,7 +1108,7 @@ public function assertSession($expected, $path, $message = '')
* @param string $message Assertion failure message
* @return void
*/
- public function assertFlashMessage($expected, $key = 'flash', $message = '')
+ public function assertFlashMessage(string $expected, string $key = 'flash', string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'message'), $verboseMessage);
@@ -1157,10 +1123,14 @@ public function assertFlashMessage($expected, $key = 'flash', $message = '')
* @param string $message Assertion failure message
* @return void
*/
- public function assertFlashMessageAt($at, $expected, $key = 'flash', $message = '')
+ public function assertFlashMessageAt(int $at, string $expected, string $key = 'flash', string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
- $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'message', $at), $verboseMessage);
+ $this->assertThat(
+ $expected,
+ new FlashParamEquals($this->_requestSession, $key, 'message', $at),
+ $verboseMessage
+ );
}
/**
@@ -1171,10 +1141,14 @@ public function assertFlashMessageAt($at, $expected, $key = 'flash', $message =
* @param string $message Assertion failure message
* @return void
*/
- public function assertFlashElement($expected, $key = 'flash', $message = '')
+ public function assertFlashElement(string $expected, string $key = 'flash', string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
- $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'element'), $verboseMessage);
+ $this->assertThat(
+ $expected,
+ new FlashParamEquals($this->_requestSession, $key, 'element'),
+ $verboseMessage
+ );
}
/**
@@ -1186,21 +1160,25 @@ public function assertFlashElement($expected, $key = 'flash', $message = '')
* @param string $message Assertion failure message
* @return void
*/
- public function assertFlashElementAt($at, $expected, $key = 'flash', $message = '')
+ public function assertFlashElementAt(int $at, string $expected, string $key = 'flash', string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
- $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'element', $at), $verboseMessage);
+ $this->assertThat(
+ $expected,
+ new FlashParamEquals($this->_requestSession, $key, 'element', $at),
+ $verboseMessage
+ );
}
/**
* Asserts cookie values
*
- * @param string $expected The expected contents.
+ * @param mixed $expected The expected contents.
* @param string $name The cookie name.
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertCookie($expected, $name, $message = '')
+ public function assertCookie($expected, string $name, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($name, new CookieSet($this->_response), $verboseMessage);
@@ -1214,7 +1192,7 @@ public function assertCookie($expected, $name, $message = '')
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertCookieNotSet($cookie, $message = '')
+ public function assertCookieNotSet(string $cookie, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($cookie, new CookieNotSet($this->_response), $verboseMessage);
@@ -1229,7 +1207,7 @@ public function assertCookieNotSet($cookie, $message = '')
*
* @return void
*/
- public function disableErrorHandlerMiddleware()
+ public function disableErrorHandlerMiddleware(): void
{
Configure::write('Error.exceptionRenderer', TestExceptionRenderer::class);
}
@@ -1241,22 +1219,30 @@ public function disableErrorHandlerMiddleware()
* The difference from assertCookie() is this decrypts the cookie
* value like the CookieComponent for this assertion.
*
- * @param string $expected The expected contents.
+ * @param mixed $expected The expected contents.
* @param string $name The cookie name.
- * @param string|bool $encrypt Encryption mode to use.
+ * @param string $encrypt Encryption mode to use.
* @param string|null $key Encryption key used. Defaults
* to Security.salt.
* @param string $message The failure message that will be appended to the generated message.
* @return void
* @see \Cake\Utility\CookieCryptTrait::_encrypt()
*/
- public function assertCookieEncrypted($expected, $name, $encrypt = 'aes', $key = null, $message = '')
- {
+ public function assertCookieEncrypted(
+ $expected,
+ string $name,
+ string $encrypt = 'aes',
+ ?string $key = null,
+ string $message = ''
+ ): void {
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat($name, new CookieSet($this->_response), $verboseMessage);
$this->_cookieEncryptionKey = $key;
- $this->assertThat($expected, new CookieEncryptedEquals($this->_response, $name, $encrypt, $this->_getCookieEncryptionKey()));
+ $this->assertThat(
+ $expected,
+ new CookieEncryptedEquals($this->_response, $name, $encrypt, $this->_getCookieEncryptionKey())
+ );
}
/**
@@ -1266,7 +1252,7 @@ public function assertCookieEncrypted($expected, $name, $encrypt = 'aes', $key =
* @param string $message The failure message that will be appended to the generated message.
* @return void
*/
- public function assertFileResponse($expected, $message = '')
+ public function assertFileResponse(string $expected, string $message = ''): void
{
$verboseMessage = $this->extractVerboseMessage($message);
$this->assertThat(null, new FileSent($this->_response), $verboseMessage);
@@ -1277,18 +1263,18 @@ public function assertFileResponse($expected, $message = '')
* Inspect controller to extract possible causes of the failed assertion
*
* @param string $message Original message to use as a base
- * @return string|null
+ * @return string
*/
- protected function extractVerboseMessage($message = null)
+ protected function extractVerboseMessage(string $message): string
{
- if ($this->_exception instanceof \Exception) {
+ if ($this->_exception instanceof Exception) {
$message .= $this->extractExceptionMessage($this->_exception);
}
if ($this->_controller === null) {
return $message;
}
- $error = Hash::get($this->_controller->viewVars, 'error');
- if ($error instanceof \Exception) {
+ $error = $this->_controller->viewBuilder()->getVar('error');
+ if ($error instanceof Exception) {
$message .= $this->extractExceptionMessage($this->viewVariable('error'));
}
@@ -1301,11 +1287,19 @@ protected function extractVerboseMessage($message = null)
* @param \Exception $exception Exception to extract
* @return string
*/
- protected function extractExceptionMessage(\Exception $exception)
+ protected function extractExceptionMessage(Exception $exception): string
{
return PHP_EOL .
sprintf('Possibly related to %s: "%s" ', get_class($exception), $exception->getMessage()) .
PHP_EOL .
$exception->getTraceAsString();
}
+
+ /**
+ * @return \Cake\TestSuite\TestSession
+ */
+ protected function getSession(): TestSession
+ {
+ return new TestSession($_SESSION);
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/LegacyCommandRunner.php b/app/vendor/cakephp/cakephp/src/TestSuite/LegacyCommandRunner.php
index 9674c9f74..ce5ae9d40 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/LegacyCommandRunner.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/LegacyCommandRunner.php
@@ -1,4 +1,6 @@
_test = $test;
- }
-
- /**
- * Resolve the user provided URL into the actual request URL.
- *
- * @param array|string $url The URL array/string to resolve.
- * @return string
- */
- public function resolveUrl($url)
- {
- return Router::url($url);
- }
-
- /**
- * Run a request and get the response.
- *
- * @param array $request The request context to execute.
- * @return string|null The generated response.
- */
- public function execute($request)
- {
- $request = new ServerRequest($request);
- $response = new Response();
- $dispatcher = DispatcherFactory::create();
- $dispatcher->getEventManager()->on(
- 'Dispatcher.invokeController',
- ['priority' => 999],
- [$this->_test, 'controllerSpy']
- );
-
- return $dispatcher->dispatch($request, $response);
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/LegacyShellDispatcher.php b/app/vendor/cakephp/cakephp/src/TestSuite/LegacyShellDispatcher.php
index 404b585b0..4f987cb0d 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/LegacyShellDispatcher.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/LegacyShellDispatcher.php
@@ -1,4 +1,6 @@
_io = $io;
parent::__construct($args, $bootstrap);
}
@@ -45,11 +50,14 @@ public function __construct($args = [], $bootstrap = true, $io = null)
* @param string $shortName Short name
* @return \Cake\Console\Shell
*/
- protected function _createShell($className, $shortName)
+ protected function _createShell(string $className, string $shortName): Shell
{
- list($plugin) = pluginSplit($shortName);
+ [$plugin] = pluginSplit($shortName);
+ /** @var \Cake\Console\Shell $instance */
$instance = new $className($this->_io);
- $instance->plugin = trim($plugin, '.');
+ if ($plugin) {
+ $instance->plugin = trim($plugin, '.');
+ }
return $instance;
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/MiddlewareDispatcher.php b/app/vendor/cakephp/cakephp/src/TestSuite/MiddlewareDispatcher.php
index e25e9c4eb..c8803c175 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/MiddlewareDispatcher.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/MiddlewareDispatcher.php
@@ -1,4 +1,6 @@
*/
protected $_class;
@@ -57,36 +59,38 @@ class MiddlewareDispatcher
/**
* The application that is being dispatched.
*
- * @var \Cake\Core\HttpApplicationInterface|\Cake\Core\ConsoleApplicationInterface
+ * @var \Cake\Core\HttpApplicationInterface
*/
protected $app;
/**
* Constructor
*
- * @param \Cake\TestSuite\IntegrationTestCase $test The test case to run.
+ * @param \Cake\TestSuite\TestCase $test The test case to run.
* @param string|null $class The application class name. Defaults to App\Application.
* @param array|null $constructorArgs The constructor arguments for your application class.
* Defaults to `['./config']`
- * @param bool $disableRouterReload Disable Router::reload() call when resolving URLs. This
- * flag may be necessary if you are using Router methods in your test case setup, and using array URLs
- * when doing requests in your tests.
* @throws \LogicException If it cannot load class for use in integration testing.
+ * @psalm-param class-string<\Cake\Core\HttpApplicationInterface>|null $class
*/
- public function __construct($test, $class = null, $constructorArgs = null, $disableRouterReload = false)
- {
+ public function __construct(
+ TestCase $test,
+ ?string $class = null,
+ ?array $constructorArgs = null
+ ) {
$this->_test = $test;
- $this->_class = $class ?: Configure::read('App.namespace') . '\Application';
+ if ($class === null) {
+ /** @psalm-var class-string<\Cake\Core\HttpApplicationInterface> */
+ $class = Configure::read('App.namespace') . '\Application';
+ }
+ $this->_class = $class;
$this->_constructorArgs = $constructorArgs ?: [CONFIG];
- try {
- $reflect = new ReflectionClass($this->_class);
- /** @var \Cake\Core\HttpApplicationInterface $app */
- $app = $reflect->newInstanceArgs($this->_constructorArgs);
- $this->app = $app;
- } catch (ReflectionException $e) {
- throw new LogicException(sprintf('Cannot load `%s` for use in integration testing.', $this->_class));
+ if (!class_exists($this->_class)) {
+ throw new LogicException("Cannot load `{$this->_class}` for use in integration testing.", 0);
}
+
+ $this->app = new $this->_class(...$this->_constructorArgs);
}
/**
@@ -95,7 +99,7 @@ public function __construct($test, $class = null, $constructorArgs = null, $disa
* @param array|string $url The URL array/string to resolve.
* @return string
*/
- public function resolveUrl($url)
+ public function resolveUrl($url): string
{
// If we need to resolve a Route URL but there are no routes, load routes.
if (is_array($url) && count(Router::getRouteCollection()->routes()) === 0) {
@@ -111,7 +115,7 @@ public function resolveUrl($url)
* @param array $url The url to resolve
* @return string
*/
- protected function resolveRoute(array $url)
+ protected function resolveRoute(array $url): string
{
// Simulate application bootstrap and route loading.
// We need both to ensure plugins are loaded.
@@ -121,7 +125,7 @@ protected function resolveRoute(array $url)
}
$builder = Router::createRouteBuilder('/');
- if ($this->app instanceof HttpApplicationInterface) {
+ if ($this->app instanceof RoutingApplicationInterface) {
$this->app->routes($builder);
}
if ($this->app instanceof PluginApplicationInterface) {
@@ -138,12 +142,13 @@ protected function resolveRoute(array $url)
* Create a PSR7 request from the request spec.
*
* @param array $spec The request spec.
- * @return \Psr\Http\Message\ServerRequestInterface
+ * @return \Cake\Http\ServerRequest
*/
- protected function _createRequest($spec)
+ protected function _createRequest(array $spec): ServerRequest
{
if (isset($spec['input'])) {
$spec['post'] = [];
+ $spec['environment']['CAKEPHP_INPUT'] = $spec['input'];
}
$environment = array_merge(
array_merge($_SERVER, ['REQUEST_URI' => $spec['url']]),
@@ -161,13 +166,6 @@ protected function _createRequest($spec)
);
$request = $request->withAttribute('session', $spec['session']);
- if (isset($spec['input'])) {
- $stream = new Stream('php://memory', 'rw');
- $stream->write($spec['input']);
- $stream->rewind();
- $request = $request->withBody($stream);
- }
-
return $request;
}
@@ -176,19 +174,10 @@ protected function _createRequest($spec)
*
* @param array $requestSpec The request spec to execute.
* @return \Psr\Http\Message\ResponseInterface The generated response.
+ * @throws \LogicException
*/
- public function execute($requestSpec)
+ public function execute(array $requestSpec): ResponseInterface
{
- try {
- $reflect = new ReflectionClass($this->_class);
- $app = $reflect->newInstanceArgs($this->_constructorArgs);
- } catch (ReflectionException $e) {
- throw new LogicException(sprintf(
- 'Cannot load "%s" for use in integration testing.',
- $this->_class
- ));
- }
-
// Spy on the controller using the initialize hook instead
// of the dispatcher hooks as those will be going away one day.
EventManager::instance()->on(
@@ -196,7 +185,7 @@ public function execute($requestSpec)
[$this->_test, 'controllerSpy']
);
- $server = new Server($app);
+ $server = new Server($this->app);
return $server->run($this->_createRequest($requestSpec));
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/MockBuilder.php b/app/vendor/cakephp/cakephp/src/TestSuite/MockBuilder.php
deleted file mode 100644
index bf961ef5f..000000000
--- a/app/vendor/cakephp/cakephp/src/TestSuite/MockBuilder.php
+++ /dev/null
@@ -1,57 +0,0 @@
-_compareBasePath . $path;
@@ -60,8 +60,7 @@ public function assertSameAsFile($path, $result)
}
if ($this->_updateComparisons) {
- $file = new File($path, true);
- $file->write($result);
+ file_put_contents($path, $result);
}
$expected = file_get_contents($path);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Stub/ConsoleInput.php b/app/vendor/cakephp/cakephp/src/TestSuite/Stub/ConsoleInput.php
index bde77468c..2d03cb224 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Stub/ConsoleInput.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Stub/ConsoleInput.php
@@ -1,4 +1,6 @@
currentIndex += 1;
@@ -80,7 +81,7 @@ public function read()
* @param int $timeout An optional time to wait for data
* @return bool True for data available, false otherwise
*/
- public function dataAvailable($timeout = 0)
+ public function dataAvailable($timeout = 0): bool
{
return true;
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Stub/ConsoleOutput.php b/app/vendor/cakephp/cakephp/src/TestSuite/Stub/ConsoleOutput.php
index 33d1536ea..ac55fcca4 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Stub/ConsoleOutput.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Stub/ConsoleOutput.php
@@ -1,4 +1,6 @@
_out[] = $line;
@@ -56,6 +58,8 @@ public function write($message, $newlines = 1)
$this->_out[] = '';
$newlines--;
}
+
+ return 0;
}
/**
@@ -63,8 +67,18 @@ public function write($message, $newlines = 1)
*
* @return array
*/
- public function messages()
+ public function messages(): array
{
return $this->_out;
}
+
+ /**
+ * Get the output as a string
+ *
+ * @return string
+ */
+ public function output(): string
+ {
+ return implode("\n", $this->_out);
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Stub/MissingConsoleInputException.php b/app/vendor/cakephp/cakephp/src/TestSuite/Stub/MissingConsoleInputException.php
index 8c097884a..3055b282a 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Stub/MissingConsoleInputException.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Stub/MissingConsoleInputException.php
@@ -1,4 +1,6 @@
hasHeader('Location') && $this->_status === 200) {
- $this->statusCode(302);
- }
- $this->_setContentType($this->getType());
-
- return $this;
- }
-}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Stub/TestExceptionRenderer.php b/app/vendor/cakephp/cakephp/src/TestSuite/Stub/TestExceptionRenderer.php
index 0c6158941..3122bdac7 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Stub/TestExceptionRenderer.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Stub/TestExceptionRenderer.php
@@ -1,4 +1,6 @@
markTestSkipped($message);
@@ -98,7 +103,7 @@ public function skipIf($shouldSkip, $message = '')
* @param callable $callable callable function that will receive asserts
* @return void
*/
- public function withErrorReporting($errorLevel, $callable)
+ public function withErrorReporting(int $errorLevel, callable $callable): void
{
$default = error_reporting();
error_reporting($errorLevel);
@@ -115,7 +120,7 @@ public function withErrorReporting($errorLevel, $callable)
* @param callable $callable callable function that will receive asserts
* @return void
*/
- public function deprecated($callable)
+ public function deprecated(callable $callable): void
{
$errorLevel = error_reporting();
error_reporting(E_ALL ^ E_USER_DEPRECATED);
@@ -133,14 +138,14 @@ public function deprecated($callable)
*
* @return void
*/
- public function setUp()
+ public function setUp(): void
{
parent::setUp();
if (!$this->_configure) {
$this->_configure = Configure::read();
}
- if (class_exists('Cake\Routing\Router', false)) {
+ if (class_exists(Router::class, false)) {
Router::reload();
}
@@ -152,7 +157,7 @@ public function setUp()
*
* @return void
*/
- public function tearDown()
+ public function tearDown(): void
{
parent::tearDown();
if ($this->_configure) {
@@ -173,12 +178,12 @@ public function tearDown()
*
* @return void
* @see \Cake\TestSuite\TestCase::$autoFixtures
- * @throws \Exception when no fixture manager is available.
+ * @throws \RuntimeException when no fixture manager is available.
*/
- public function loadFixtures()
+ public function loadFixtures(): void
{
if ($this->fixtureManager === null) {
- throw new Exception('No fixture manager to load the test fixture');
+ throw new RuntimeException('No fixture manager to load the test fixture');
}
$args = func_get_args();
foreach ($args as $class) {
@@ -193,6 +198,34 @@ public function loadFixtures()
}
}
+ /**
+ * Load routes for the application.
+ *
+ * If no application class can be found an exception will be raised.
+ * Routes for plugins will *not* be loaded. Use `loadPlugins()` or use
+ * `Cake\TestSuite\IntegrationTestCaseTrait` to better simulate all routes
+ * and plugins being loaded.
+ *
+ * @param array|null $appArgs Constuctor parameters for the application class.
+ * @return void
+ * @since 4.0.1
+ */
+ public function loadRoutes(?array $appArgs = null): void
+ {
+ $appArgs = $appArgs ?? [rtrim(CONFIG, DIRECTORY_SEPARATOR)];
+ /** @psalm-var class-string */
+ $className = Configure::read('App.namespace') . '\\Application';
+ try {
+ $reflect = new ReflectionClass($className);
+ /** @var \Cake\Routing\RoutingApplicationInterface $app */
+ $app = $reflect->newInstanceArgs($appArgs);
+ } catch (ReflectionException $e) {
+ throw new LogicException(sprintf('Cannot load "%s" to load routes from.', $className), 0, $e);
+ }
+ $builder = Router::createRouteBuilder('/');
+ $app->routes($builder);
+ }
+
/**
* Load plugins into a simulated application.
*
@@ -202,7 +235,7 @@ public function loadFixtures()
* @param array $plugins List of Plugins to load.
* @return \Cake\Http\BaseApplication
*/
- public function loadPlugins(array $plugins = [])
+ public function loadPlugins(array $plugins = []): BaseApplication
{
/** @var \Cake\Http\BaseApplication $app */
$app = $this->getMockForAbstractClass(
@@ -232,7 +265,7 @@ public function loadPlugins(array $plugins = [])
* @param string[] $names A list of plugins you want to remove.
* @return void
*/
- public function removePlugins(array $names = [])
+ public function removePlugins(array $names = []): void
{
$collection = Plugin::getCollection();
foreach ($names as $name) {
@@ -247,7 +280,7 @@ public function removePlugins(array $names = [])
*
* @return void
*/
- public function clearPlugins()
+ public function clearPlugins(): void
{
Plugin::getCollection()->clear();
}
@@ -256,11 +289,11 @@ public function clearPlugins()
* Asserts that a global event was fired. You must track events in your event manager for this assertion to work
*
* @param string $name Event name
- * @param EventManager|null $eventManager Event manager to check, defaults to global event manager
+ * @param \Cake\Event\EventManager|null $eventManager Event manager to check, defaults to global event manager
* @param string $message Assertion failure message
* @return void
*/
- public function assertEventFired($name, $eventManager = null, $message = '')
+ public function assertEventFired(string $name, ?EventManager $eventManager = null, string $message = ''): void
{
if (!$eventManager) {
$eventManager = EventManager::instance();
@@ -275,13 +308,18 @@ public function assertEventFired($name, $eventManager = null, $message = '')
*
* @param string $name Event name
* @param string $dataKey Data key
- * @param string $dataValue Data value
- * @param EventManager|null $eventManager Event manager to check, defaults to global event manager
+ * @param mixed $dataValue Data value
+ * @param \Cake\Event\EventManager|null $eventManager Event manager to check, defaults to global event manager
* @param string $message Assertion failure message
* @return void
*/
- public function assertEventFiredWith($name, $dataKey, $dataValue, $eventManager = null, $message = '')
- {
+ public function assertEventFiredWith(
+ string $name,
+ string $dataKey,
+ $dataValue,
+ ?EventManager $eventManager = null,
+ string $message = ''
+ ): void {
if (!$eventManager) {
$eventManager = EventManager::instance();
}
@@ -297,7 +335,7 @@ public function assertEventFiredWith($name, $dataKey, $dataValue, $eventManager
* @param string $message The message to use for failure.
* @return void
*/
- public function assertTextNotEquals($expected, $result, $message = '')
+ public function assertTextNotEquals(string $expected, string $result, string $message = ''): void
{
$expected = str_replace(["\r\n", "\r"], "\n", $expected);
$result = str_replace(["\r\n", "\r"], "\n", $result);
@@ -313,7 +351,7 @@ public function assertTextNotEquals($expected, $result, $message = '')
* @param string $message The message to use for failure.
* @return void
*/
- public function assertTextEquals($expected, $result, $message = '')
+ public function assertTextEquals(string $expected, string $result, string $message = ''): void
{
$expected = str_replace(["\r\n", "\r"], "\n", $expected);
$result = str_replace(["\r\n", "\r"], "\n", $result);
@@ -329,7 +367,7 @@ public function assertTextEquals($expected, $result, $message = '')
* @param string $message The message to use for failure.
* @return void
*/
- public function assertTextStartsWith($prefix, $string, $message = '')
+ public function assertTextStartsWith(string $prefix, string $string, string $message = ''): void
{
$prefix = str_replace(["\r\n", "\r"], "\n", $prefix);
$string = str_replace(["\r\n", "\r"], "\n", $string);
@@ -345,7 +383,7 @@ public function assertTextStartsWith($prefix, $string, $message = '')
* @param string $message The message to use for failure.
* @return void
*/
- public function assertTextStartsNotWith($prefix, $string, $message = '')
+ public function assertTextStartsNotWith(string $prefix, string $string, string $message = ''): void
{
$prefix = str_replace(["\r\n", "\r"], "\n", $prefix);
$string = str_replace(["\r\n", "\r"], "\n", $string);
@@ -361,7 +399,7 @@ public function assertTextStartsNotWith($prefix, $string, $message = '')
* @param string $message The message to use for failure.
* @return void
*/
- public function assertTextEndsWith($suffix, $string, $message = '')
+ public function assertTextEndsWith(string $suffix, string $string, string $message = ''): void
{
$suffix = str_replace(["\r\n", "\r"], "\n", $suffix);
$string = str_replace(["\r\n", "\r"], "\n", $string);
@@ -377,7 +415,7 @@ public function assertTextEndsWith($suffix, $string, $message = '')
* @param string $message The message to use for failure.
* @return void
*/
- public function assertTextEndsNotWith($suffix, $string, $message = '')
+ public function assertTextEndsNotWith(string $suffix, string $string, string $message = ''): void
{
$suffix = str_replace(["\r\n", "\r"], "\n", $suffix);
$string = str_replace(["\r\n", "\r"], "\n", $string);
@@ -394,11 +432,20 @@ public function assertTextEndsNotWith($suffix, $string, $message = '')
* @param bool $ignoreCase Whether or not the search should be case-sensitive.
* @return void
*/
- public function assertTextContains($needle, $haystack, $message = '', $ignoreCase = false)
- {
+ public function assertTextContains(
+ string $needle,
+ string $haystack,
+ string $message = '',
+ bool $ignoreCase = false
+ ): void {
$needle = str_replace(["\r\n", "\r"], "\n", $needle);
$haystack = str_replace(["\r\n", "\r"], "\n", $haystack);
- $this->assertContains($needle, $haystack, $message, $ignoreCase);
+
+ if ($ignoreCase) {
+ $this->assertStringContainsStringIgnoringCase($needle, $haystack, $message);
+ } else {
+ $this->assertStringContainsString($needle, $haystack, $message);
+ }
}
/**
@@ -411,26 +458,20 @@ public function assertTextContains($needle, $haystack, $message = '', $ignoreCas
* @param bool $ignoreCase Whether or not the search should be case-sensitive.
* @return void
*/
- public function assertTextNotContains($needle, $haystack, $message = '', $ignoreCase = false)
- {
+ public function assertTextNotContains(
+ string $needle,
+ string $haystack,
+ string $message = '',
+ bool $ignoreCase = false
+ ): void {
$needle = str_replace(["\r\n", "\r"], "\n", $needle);
$haystack = str_replace(["\r\n", "\r"], "\n", $haystack);
- $this->assertNotContains($needle, $haystack, $message, $ignoreCase);
- }
- /**
- * Asserts HTML tags.
- *
- * @param string $string An HTML/XHTML/XML string
- * @param array $expected An array, see above
- * @param bool $fullDebug Whether or not more verbose output should be used.
- * @return void
- * @deprecated 3.0. Use assertHtml() instead.
- */
- public function assertTags($string, $expected, $fullDebug = false)
- {
- deprecationWarning('TestCase::assertTags() is deprecated. Use TestCase::assertHtml() instead.');
- $this->assertHtml($expected, $string, $fullDebug);
+ if ($ignoreCase) {
+ $this->assertStringNotContainsStringIgnoringCase($needle, $haystack, $message);
+ } else {
+ $this->assertStringNotContainsString($needle, $haystack, $message);
+ }
}
/**
@@ -477,7 +518,7 @@ public function assertTags($string, $expected, $fullDebug = false)
* @param bool $fullDebug Whether or not more verbose output should be used.
* @return bool
*/
- public function assertHtml($expected, $string, $fullDebug = false)
+ public function assertHtml(array $expected, string $string, bool $fullDebug = false): bool
{
$regex = [];
$normalized = [];
@@ -500,7 +541,7 @@ public function assertHtml($expected, $string, $fullDebug = false)
$tagsTrimmed = preg_replace('/\s+/m', '', $tags);
if (preg_match('/^\*?\//', $tags, $match) && $tagsTrimmed !== '//') {
- $prefix = [null, null];
+ $prefix = ['', ''];
if ($match[0] === '*/') {
$prefix = ['Anything, ', '.*?'];
@@ -527,6 +568,7 @@ public function assertHtml($expected, $string, $fullDebug = false)
continue;
}
foreach ($tags as $tag => $attributes) {
+ /** @psalm-suppress PossiblyFalseArgument */
$regex[] = [
sprintf('Open %s tag', $tag),
sprintf('[\s]*<%s', preg_quote($tag, '/')),
@@ -539,11 +581,12 @@ public function assertHtml($expected, $string, $fullDebug = false)
$explanations = [];
$i = 1;
foreach ($attributes as $attr => $val) {
- if (is_numeric($attr) && preg_match('/^preg\:\/(.+)\/$/i', $val, $matches)) {
+ if (is_numeric($attr) && preg_match('/^preg\:\/(.+)\/$/i', (string)$val, $matches)) {
$attrs[] = $matches[1];
$explanations[] = sprintf('Regex "%s" matches', $matches[1]);
continue;
}
+ $val = (string)$val;
$quotes = '["\']';
if (is_numeric($attr)) {
@@ -572,6 +615,7 @@ public function assertHtml($expected, $string, $fullDebug = false)
'attrs' => $attrs,
];
}
+ /** @psalm-suppress PossiblyFalseArgument */
$regex[] = [
sprintf('End %s tag', $tag),
'[\s]*\/?[\s]*>[\n\r]*',
@@ -590,8 +634,10 @@ public function assertHtml($expected, $string, $fullDebug = false)
continue;
}
- list($description, $expressions, $itemNum) = $assertion;
- $expression = null;
+ // If 'attrs' is not present then the array is just a regular int-offset one
+ /** @psalm-suppress PossiblyUndefinedArrayOffset */
+ [$description, $expressions, $itemNum] = $assertion;
+ $expression = '';
foreach ((array)$expressions as $expression) {
$expression = sprintf('/^%s/s', $expression);
if (preg_match($expression, $string, $match)) {
@@ -605,7 +651,11 @@ public function assertHtml($expected, $string, $fullDebug = false)
debug($string);
debug($regex);
}
- $this->assertRegExp($expression, $string, sprintf('Item #%d / regex #%d failed: %s', $itemNum, $i, $description));
+ $this->assertRegExp(
+ $expression,
+ $string,
+ sprintf('Item #%d / regex #%d failed: %s', $itemNum, $i, $description)
+ );
return false;
}
@@ -623,9 +673,9 @@ public function assertHtml($expected, $string, $fullDebug = false)
* @param string $string The HTML string to check.
* @param bool $fullDebug Whether or not more verbose output should be used.
* @param array|string $regex Full regexp from `assertHtml`
- * @return string|bool
+ * @return string|false
*/
- protected function _assertAttributes($assertions, $string, $fullDebug = false, $regex = '')
+ protected function _assertAttributes(array $assertions, string $string, bool $fullDebug = false, $regex = '')
{
$asserts = $assertions['attrs'];
$explains = $assertions['explains'];
@@ -660,12 +710,12 @@ protected function _assertAttributes($assertions, $string, $fullDebug = false, $
* @param string $path Path separated by "/" slash.
* @return string Normalized path separated by DIRECTORY_SEPARATOR.
*/
- protected function _normalizePath($path)
+ protected function _normalizePath(string $path): string
{
return str_replace('/', DIRECTORY_SEPARATOR, $path);
}
-// @codingStandardsIgnoreStart
+// phpcs:disable
/**
* Compatibility function to test if a value is between an acceptable range.
@@ -730,134 +780,32 @@ protected function skipUnless($condition, $message = '')
return $condition;
}
-// @codingStandardsIgnoreEnd
-
- /**
- * @inheritDoc
- */
- public function getMockBuilder($className)
- {
- return new MockBuilder($this, $className);
- }
-
- /**
- * @inheritDoc
- */
- protected function getMockClass(
- $originalClassName,
- $methods = [],
- array $arguments = [],
- $mockClassName = '',
- $callOriginalConstructor = false,
- $callOriginalClone = true,
- $callAutoload = true,
- $cloneArguments = false
- ) {
- MockBuilder::setSupressedErrorHandler();
-
- try {
- return parent::getMockClass(
- $originalClassName,
- $methods,
- $arguments,
- $mockClassName,
- $callOriginalConstructor,
- $callOriginalClone,
- $callAutoload,
- $cloneArguments
- );
- } finally {
- restore_error_handler();
- }
- }
-
- /**
- * @inheritDoc
- */
- protected function getMockForTrait(
- $traitName,
- array $arguments = [],
- $mockClassName = '',
- $callOriginalConstructor = true,
- $callOriginalClone = true,
- $callAutoload = true,
- $mockedMethods = [],
- $cloneArguments = false
- ) {
- MockBuilder::setSupressedErrorHandler();
-
- try {
- return parent::getMockForTrait(
- $traitName,
- $arguments,
- $mockClassName,
- $callOriginalConstructor,
- $callOriginalClone,
- $callAutoload,
- $mockedMethods,
- $cloneArguments
- );
- } finally {
- restore_error_handler();
- }
- }
-
- /**
- * @inheritDoc
- */
- protected function getMockForAbstractClass(
- $originalClassName,
- array $arguments = [],
- $mockClassName = '',
- $callOriginalConstructor = true,
- $callOriginalClone = true,
- $callAutoload = true,
- $mockedMethods = [],
- $cloneArguments = false
- ) {
- MockBuilder::setSupressedErrorHandler();
-
- try {
- return parent::getMockForAbstractClass(
- $originalClassName,
- $arguments,
- $mockClassName,
- $callOriginalConstructor,
- $callOriginalClone,
- $callAutoload,
- $mockedMethods,
- $cloneArguments
- );
- } finally {
- restore_error_handler();
- }
- }
+// phpcs:enable
/**
* Mock a model, maintain fixtures and table association
*
* @param string $alias The model to get a mock for.
- * @param string[]|null $methods The list of methods to mock
+ * @param string[] $methods The list of methods to mock
* @param array $options The config data for the mock's constructor.
* @throws \Cake\ORM\Exception\MissingTableClassException
- * @return \Cake\ORM\Table|\PHPUnit_Framework_MockObject_MockObject
+ * @return \Cake\ORM\Table|\PHPUnit\Framework\MockObject\MockObject
*/
- public function getMockForModel($alias, $methods = [], array $options = [])
+ public function getMockForModel(string $alias, array $methods = [], array $options = [])
{
- /** @var \Cake\ORM\Table $className */
$className = $this->_getTableClassName($alias, $options);
$connectionName = $className::defaultConnectionName();
$connection = ConnectionManager::get($connectionName);
$locator = $this->getTableLocator();
- list(, $baseClass) = pluginSplit($alias);
+ [, $baseClass] = pluginSplit($alias);
$options += ['alias' => $baseClass, 'connection' => $connection];
$options += $locator->getConfig($alias);
- /** @var \Cake\ORM\Table|\PHPUnit_Framework_MockObject_MockObject $mock */
+ /** @var \Cake\ORM\Table $mock */
$mock = $this->getMockBuilder($className)
- ->setMethods($methods)
+ ->onlyMethods($methods)
->setConstructorArgs([$options])
->getMock();
@@ -887,11 +835,13 @@ public function getMockForModel($alias, $methods = [], array $options = [])
* @param array $options The config data for the mock's constructor.
* @return string
* @throws \Cake\ORM\Exception\MissingTableClassException
+ * @psalm-return class-string<\Cake\ORM\Table>
*/
- protected function _getTableClassName($alias, array $options)
+ protected function _getTableClassName(string $alias, array $options): string
{
if (empty($options['className'])) {
$class = Inflector::camelize($alias);
+ /** @psalm-var class-string<\Cake\ORM\Table>|null */
$className = App::className($class, 'Model/Table', 'Table');
if (!$className) {
throw new MissingTableClassException([$alias]);
@@ -908,61 +858,18 @@ protected function _getTableClassName($alias, array $options)
* @param string $appNamespace The app namespace, defaults to "TestApp".
* @return void
*/
- public static function setAppNamespace($appNamespace = 'TestApp')
+ public static function setAppNamespace(string $appNamespace = 'TestApp'): void
{
Configure::write('App.namespace', $appNamespace);
}
- /**
- * Adds a fixture to this test case.
- *
- * Examples:
- * - core.Tags
- * - app.MyRecords
- * - plugin.MyPluginName.MyModelName
- *
- * Use this method inside your test cases' {@link getFixtures()} method
- * to build up the fixture list.
- *
- * @param string $fixture Fixture
- * @return $this
- */
- protected function addFixture($fixture)
- {
- if (!isset($this->fixtures)) {
- $this->fixtures = [];
- } elseif (is_string($this->fixtures)) {
- deprecationWarning(
- 'Setting fixtures as string is deprecated and will be removed in 4.0.' .
- ' Set TestCase::$fixtures as array instead.'
- );
- $this->fixtures = array_map('trim', explode(',', $this->fixtures));
- }
-
- $this->fixtures[] = $fixture;
-
- return $this;
- }
-
/**
* Gets fixtures.
*
- * @return array
+ * @return string[]
*/
- public function getFixtures()
+ public function getFixtures(): array
{
- if (!isset($this->fixtures)) {
- return [];
- }
- if (is_string($this->fixtures)) {
- deprecationWarning(
- 'Setting fixtures as string is deprecated and will be removed in 4.0.' .
- ' Set TestCase::$fixtures as array instead.'
- );
-
- return array_map('trim', explode(',', $this->fixtures));
- }
-
return $this->fixtures;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/TestEmailTransport.php b/app/vendor/cakephp/cakephp/src/TestSuite/TestEmailTransport.php
index 5361f7e6a..1843c1a02 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/TestEmailTransport.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/TestEmailTransport.php
@@ -1,4 +1,6 @@
session = $session;
+ }
+
+ /**
+ * Returns true if given variable name is set in session.
+ *
+ * @param string|null $name Variable name to check for
+ * @return bool True if variable is there
+ */
+ public function check(?string $name = null): bool
+ {
+ if ($this->session === null) {
+ return false;
+ }
+
+ if ($name === null) {
+ return (bool)$this->session;
+ }
+
+ return Hash::get($this->session, $name) !== null;
+ }
+
+ /**
+ * Returns given session variable, or all of them, if no parameters given.
+ *
+ * @param string|null $name The name of the session variable (or a path as sent to Hash.extract)
+ * @return mixed The value of the session variable, null if session not available,
+ * session not started, or provided name not found in the session.
+ */
+ public function read(?string $name = null)
+ {
+ if ($this->session === null) {
+ return null;
+ }
+
+ if ($name === null) {
+ return $this->session ?: [];
+ }
+
+ return Hash::get($this->session, $name);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/TestSuite.php b/app/vendor/cakephp/cakephp/src/TestSuite/TestSuite.php
index 88f899429..e5a18c215 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/TestSuite.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/TestSuite.php
@@ -1,4 +1,6 @@
read(true, true, true);
-
- foreach ($files as $file) {
- if (substr($file, -4) === '.php') {
- $this->addTestFile($file);
- }
+ $fs = new Filesystem();
+ $files = $fs->find($directory, '/\.php$/');
+ foreach ($files as $file => $fileInfo) {
+ $this->addTestFile($file);
}
}
@@ -50,15 +48,19 @@ public function addTestDirectory($directory = '.')
* @param string $directory The directory subtree to add tests from.
* @return void
*/
- public function addTestDirectoryRecursive($directory = '.')
+ public function addTestDirectoryRecursive(string $directory = '.'): void
{
- $Folder = new Folder($directory);
- $files = $Folder->tree(null, true, 'files');
-
- foreach ($files as $file) {
- if (substr($file, -4) === '.php') {
- $this->addTestFile($file);
+ $fs = new Filesystem();
+ $files = $fs->findRecursive($directory, function (SplFileInfo $current) {
+ $file = $current->getFilename();
+ if ($file[0] === '.' || !preg_match('/\.php$/', $file)) {
+ return false;
}
+
+ return true;
+ });
+ foreach ($files as $file => $fileInfo) {
+ $this->addTestFile($file);
}
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Utility/CookieCryptTrait.php b/app/vendor/cakephp/cakephp/src/Utility/CookieCryptTrait.php
index 4a7b1300f..390b50d43 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/CookieCryptTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/CookieCryptTrait.php
@@ -1,4 +1,6 @@
_implode($value);
@@ -58,13 +60,10 @@ protected function _encrypt($value, $encrypt, $key = null)
}
$this->_checkCipher($encrypt);
$prefix = 'Q2FrZQ==.';
- $cipher = null;
+ $cipher = '';
if ($key === null) {
$key = $this->_getCookieEncryptionKey();
}
- if ($encrypt === 'rijndael') {
- $cipher = Security::rijndael($value, $key, 'encrypt');
- }
if ($encrypt === 'aes') {
$cipher = Security::encrypt($value, $key);
}
@@ -79,9 +78,9 @@ protected function _encrypt($value, $encrypt, $key = null)
* @return void
* @throws \RuntimeException When an invalid cipher is provided.
*/
- protected function _checkCipher($encrypt)
+ protected function _checkCipher(string $encrypt): void
{
- if (!in_array($encrypt, $this->_validCiphers)) {
+ if (!in_array($encrypt, $this->_validCiphers, true)) {
$msg = sprintf(
'Invalid encryption cipher. Must be one of %s or false.',
implode(', ', $this->_validCiphers)
@@ -98,7 +97,7 @@ protected function _checkCipher($encrypt)
* @param string|null $key Used as the security salt if specified.
* @return string|array Decrypted values
*/
- protected function _decrypt($values, $mode, $key = null)
+ protected function _decrypt($values, $mode, ?string $key = null)
{
if (is_string($values)) {
return $this->_decode($values, $mode, $key);
@@ -120,7 +119,7 @@ protected function _decrypt($values, $mode, $key = null)
* @param string|null $key Used as the security salt if specified.
* @return string|array Decoded values.
*/
- protected function _decode($value, $encrypt, $key)
+ protected function _decode(string $value, $encrypt, ?string $key)
{
if (!$encrypt) {
return $this->_explode($value);
@@ -142,14 +141,11 @@ protected function _decode($value, $encrypt, $key)
if ($key === null) {
$key = $this->_getCookieEncryptionKey();
}
- if ($encrypt === 'rijndael') {
- $value = Security::rijndael($value, $key, 'decrypt');
- }
if ($encrypt === 'aes') {
$value = Security::decrypt($value, $key);
}
- if ($value === false) {
+ if ($value === null) {
return '';
}
@@ -162,7 +158,7 @@ protected function _decode($value, $encrypt, $key)
* @param array $array Map of key and values
* @return string A json encoded string.
*/
- protected function _implode(array $array)
+ protected function _implode(array $array): string
{
return json_encode($array);
}
@@ -174,13 +170,13 @@ protected function _implode(array $array)
* @param string $string A string containing JSON encoded data, or a bare string.
* @return string|array Map of key and values
*/
- protected function _explode($string)
+ protected function _explode(string $string)
{
$first = substr($string, 0, 1);
if ($first === '{' || $first === '[') {
$ret = json_decode($string, true);
- return ($ret !== null) ? $ret : $string;
+ return $ret ?? $string;
}
$array = [];
foreach (explode(',', $string) as $pair) {
diff --git a/app/vendor/cakephp/cakephp/src/Utility/Crypto/Mcrypt.php b/app/vendor/cakephp/cakephp/src/Utility/Crypto/Mcrypt.php
deleted file mode 100644
index 038d01dea..000000000
--- a/app/vendor/cakephp/cakephp/src/Utility/Crypto/Mcrypt.php
+++ /dev/null
@@ -1,124 +0,0 @@
-[^=>[><]) \s* (?P(?:\/.*?\/ | [^\]]+)) )? \])/x',
@@ -245,8 +250,8 @@ protected static function _matches($data, $selector)
foreach ($conditions as $cond) {
$attr = $cond['attr'];
- $op = isset($cond['op']) ? $cond['op'] : null;
- $val = isset($cond['val']) ? $cond['val'] : null;
+ $op = $cond['op'] ?? null;
+ $val = $cond['val'] ?? null;
// Presence test.
if (empty($op) && empty($val) && !isset($data[$attr])) {
@@ -263,7 +268,7 @@ protected static function _matches($data, $selector)
return false;
}
- $prop = null;
+ $prop = '';
if (isset($data[$attr])) {
$prop = $data[$attr];
}
@@ -281,6 +286,7 @@ protected static function _matches($data, $selector)
if (!preg_match($val, $prop)) {
return false;
}
+ // phpcs:disable
} elseif (
($op === '=' && $prop != $val) ||
($op === '!=' && $prop == $val) ||
@@ -288,6 +294,7 @@ protected static function _matches($data, $selector)
($op === '<' && $prop >= $val) ||
($op === '>=' && $prop < $val) ||
($op === '<=' && $prop > $val)
+ // phpcs:enable
) {
return false;
}
@@ -304,9 +311,9 @@ protected static function _matches($data, $selector)
* @param string $path The path to insert at.
* @param mixed $values The values to insert.
* @return array The data with $values inserted.
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::insert
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::insert
*/
- public static function insert(array $data, $path, $values = null)
+ public static function insert(array $data, string $path, $values = null): array
{
$noTokens = strpos($path, '[') === false;
if ($noTokens && strpos($path, '.') === false) {
@@ -328,7 +335,7 @@ public static function insert(array $data, $path, $values = null)
$token = array_shift($tokens);
$nextPath = implode('.', $tokens);
- list($token, $conditions) = static::_splitConditions($token);
+ [$token, $conditions] = static::_splitConditions($token);
foreach ($data as $k => $v) {
if (static::_matchToken($k, $token)) {
@@ -352,9 +359,9 @@ public static function insert(array $data, $path, $values = null)
* @param mixed $values The values to insert when doing inserts.
* @return array data.
*/
- protected static function _simpleOp($op, $data, $path, $values = null)
+ protected static function _simpleOp(string $op, array $data, array $path, $values = null): array
{
- $_list =& $data;
+ $_list = &$data;
$count = count($path);
$last = $count - 1;
@@ -368,7 +375,7 @@ protected static function _simpleOp($op, $data, $path, $values = null)
if (!isset($_list[$key])) {
$_list[$key] = [];
}
- $_list =& $_list[$key];
+ $_list = &$_list[$key];
if (!is_array($_list)) {
$_list = [];
}
@@ -383,7 +390,7 @@ protected static function _simpleOp($op, $data, $path, $values = null)
if (!isset($_list[$key])) {
return $data;
}
- $_list =& $_list[$key];
+ $_list = &$_list[$key];
}
}
@@ -398,9 +405,9 @@ protected static function _simpleOp($op, $data, $path, $values = null)
* @param array $data The data to operate on
* @param string $path A path expression to use to remove.
* @return array The modified array.
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::remove
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::remove
*/
- public static function remove(array $data, $path)
+ public static function remove(array $data, string $path): array
{
$noTokens = strpos($path, '[') === false;
$noExpansion = strpos($path, '{') === false;
@@ -420,7 +427,7 @@ public static function remove(array $data, $path)
$token = array_shift($tokens);
$nextPath = implode('.', $tokens);
- list($token, $conditions) = self::_splitConditions($token);
+ [$token, $conditions] = self::_splitConditions($token);
foreach ($data as $k => $v) {
$match = static::_matchToken($k, $token);
@@ -454,14 +461,14 @@ public static function remove(array $data, $path)
* following the path specified in `$groupPath`.
*
* @param array $data Array from where to extract keys and values
- * @param array|string|null $keyPath A dot-separated string. If null it will create a numbered array.
- * @param array|string|null $valuePath A dot-separated string.
+ * @param string|string[] $keyPath A dot-separated string.
+ * @param string|string[]|null $valuePath A dot-separated string.
* @param string|null $groupPath A dot-separated string.
* @return array Combined array
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::combine
- * @throws \RuntimeException When keys is an array, and keys and values count is unequal.
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::combine
+ * @throws \RuntimeException When keys and values count is unequal.
*/
- public static function combine(array $data, $keyPath, $valuePath = null, $groupPath = null)
+ public static function combine(array $data, $keyPath, $valuePath = null, ?string $groupPath = null): array
{
if (empty($data)) {
return [];
@@ -469,28 +476,30 @@ public static function combine(array $data, $keyPath, $valuePath = null, $groupP
if (is_array($keyPath)) {
$format = array_shift($keyPath);
+ /** @var array $keys */
$keys = static::format($data, $keyPath, $format);
- } elseif ($keyPath === null) {
- $keys = $keyPath;
} else {
+ /** @var array $keys */
$keys = static::extract($data, $keyPath);
}
- if ($keyPath !== null && empty($keys)) {
+ if (empty($keys)) {
return [];
}
$vals = null;
if (!empty($valuePath) && is_array($valuePath)) {
$format = array_shift($valuePath);
+ /** @var array $vals */
$vals = static::format($data, $valuePath, $format);
} elseif (!empty($valuePath)) {
+ /** @var array $vals */
$vals = static::extract($data, $valuePath);
}
if (empty($vals)) {
- $vals = array_fill(0, $keys === null ? count($data) : count($keys), null);
+ $vals = array_fill(0, count($keys), null);
}
- if (is_array($keys) && count($keys) !== count($vals)) {
+ if (count($keys) !== count($vals)) {
throw new RuntimeException(
'Hash::combine() needs an equal number of keys + values.'
);
@@ -499,7 +508,7 @@ public static function combine(array $data, $keyPath, $valuePath = null, $groupP
if ($groupPath !== null) {
$group = static::extract($data, $groupPath);
if (!empty($group)) {
- $c = is_array($keys) ? count($keys) : count($vals);
+ $c = count($keys);
$out = [];
for ($i = 0; $i < $c; $i++) {
if (!isset($group[$i])) {
@@ -508,11 +517,7 @@ public static function combine(array $data, $keyPath, $valuePath = null, $groupP
if (!isset($out[$group[$i]])) {
$out[$group[$i]] = [];
}
- if ($keys === null) {
- $out[$group[$i]][] = $vals[$i];
- } else {
- $out[$group[$i]][$keys[$i]] = $vals[$i];
- }
+ $out[$group[$i]][$keys[$i]] = $vals[$i];
}
return $out;
@@ -522,7 +527,7 @@ public static function combine(array $data, $keyPath, $valuePath = null, $groupP
return [];
}
- return array_combine($keys === null ? range(0, count($vals) - 1) : $keys, $vals);
+ return array_combine($keys, $vals);
}
/**
@@ -541,11 +546,11 @@ public static function combine(array $data, $keyPath, $valuePath = null, $groupP
* @param string[] $paths An array containing one or more Hash::extract()-style key paths
* @param string $format Format string into which values will be inserted, see sprintf()
* @return string[]|null An array of strings extracted from `$path` and formatted with `$format`
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::format
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::format
* @see sprintf()
* @see \Cake\Utility\Hash::extract()
*/
- public static function format(array $data, array $paths, $format)
+ public static function format(array $data, array $paths, string $format): ?array
{
$extracted = [];
$count = count($paths);
@@ -558,6 +563,7 @@ public static function format(array $data, array $paths, $format)
$extracted[] = static::extract($data, $paths[$i]);
}
$out = [];
+ /** @var array $data */
$data = $extracted;
$count = count($data[0]);
@@ -581,9 +587,9 @@ public static function format(array $data, array $paths, $format)
* @param array $data The data to search through.
* @param array $needle The values to file in $data
* @return bool true If $data contains $needle, false otherwise
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::contains
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::contains
*/
- public static function contains(array $data, array $needle)
+ public static function contains(array $data, array $needle): bool
{
if (empty($data) || empty($needle)) {
return false;
@@ -607,7 +613,7 @@ public static function contains(array $data, array $needle)
}
if (empty($needle) && !empty($stack)) {
- list($needle, $data) = array_pop($stack);
+ [$needle, $data] = array_pop($stack);
}
}
@@ -625,9 +631,9 @@ public static function contains(array $data, array $needle)
* @param string $path The path to check for.
* @return bool Existence of path.
* @see \Cake\Utility\Hash::extract()
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::check
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::check
*/
- public static function check(array $data, $path)
+ public static function check(array $data, string $path): bool
{
$results = static::extract($data, $path);
if (!is_array($results)) {
@@ -644,9 +650,9 @@ public static function check(array $data, $path)
* @param callable|array $callback A function to filter the data with. Defaults to
* `static::_filter()` Which strips out all non-zero empty values.
* @return array Filtered array
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::filter
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::filter
*/
- public static function filter(array $data, $callback = ['self', '_filter'])
+ public static function filter(array $data, $callback = ['self', '_filter']): array
{
foreach ($data as $k => $v) {
if (is_array($v)) {
@@ -663,7 +669,7 @@ public static function filter(array $data, $callback = ['self', '_filter'])
* @param mixed $var Array to filter.
* @return bool
*/
- protected static function _filter($var)
+ protected static function _filter($var): bool
{
return $var === 0 || $var === 0.0 || $var === '0' || !empty($var);
}
@@ -676,13 +682,13 @@ protected static function _filter($var)
* @param array $data Array to flatten
* @param string $separator String used to separate array key elements in a path, defaults to '.'
* @return array
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::flatten
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::flatten
*/
- public static function flatten(array $data, $separator = '.')
+ public static function flatten(array $data, string $separator = '.'): array
{
$result = [];
$stack = [];
- $path = null;
+ $path = '';
reset($data);
while (!empty($data)) {
@@ -702,7 +708,7 @@ public static function flatten(array $data, $separator = '.')
}
if (empty($data) && !empty($stack)) {
- list($data, $path) = array_pop($stack);
+ [$data, $path] = array_pop($stack);
reset($data);
}
}
@@ -720,9 +726,9 @@ public static function flatten(array $data, $separator = '.')
* @param array $data Flattened array
* @param string $separator The delimiter used
* @return array
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::expand
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::expand
*/
- public static function expand(array $data, $separator = '.')
+ public static function expand(array $data, string $separator = '.'): array
{
$result = [];
foreach ($data as $flat => $value) {
@@ -752,14 +758,14 @@ public static function expand(array $data, $separator = '.')
* Hash::merge() will behave in a recursive fashion (unlike `array_merge`). But it will not act recursively for
* keys that contain scalar values (unlike `array_merge_recursive`).
*
- * Note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
+ * This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
*
* @param array $data Array to be merged
* @param mixed $merge Array to merge with. The argument and all trailing arguments will be array cast when merged
* @return array Merged array
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::merge
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::merge
*/
- public static function merge(array $data, $merge)
+ public static function merge(array $data, $merge): array
{
$args = array_slice(func_get_args(), 1);
$return = $data;
@@ -781,16 +787,23 @@ public static function merge(array $data, $merge)
* @param array $return The return value to operate on.
* @return void
*/
- protected static function _merge($stack, &$return)
+ protected static function _merge(array $stack, array &$return): void
{
while (!empty($stack)) {
foreach ($stack as $curKey => &$curMerge) {
foreach ($curMerge[0] as $key => &$val) {
- $isArray = is_array($curMerge[1]);
- if ($isArray && !empty($curMerge[1][$key]) && (array)$curMerge[1][$key] === $curMerge[1][$key] && (array)$val === $val) {
+ if (!is_array($curMerge[1])) {
+ continue;
+ }
+
+ if (
+ !empty($curMerge[1][$key])
+ && (array)$curMerge[1][$key] === $curMerge[1][$key]
+ && (array)$val === $val
+ ) {
// Recurse into the current merge data as it is an array.
$stack[] = [&$val, &$curMerge[1][$key]];
- } elseif ((int)$key === $key && $isArray && isset($curMerge[1][$key])) {
+ } elseif ((int)$key === $key && isset($curMerge[1][$key])) {
$curMerge[1][] = $val;
} else {
$curMerge[1][$key] = $val;
@@ -807,9 +820,9 @@ protected static function _merge($stack, &$return)
*
* @param array $data The array to check.
* @return bool true if values are numeric, false otherwise
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::numeric
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::numeric
*/
- public static function numeric(array $data)
+ public static function numeric(array $data): bool
{
if (empty($data)) {
return false;
@@ -827,9 +840,9 @@ public static function numeric(array $data)
*
* @param array $data Array to count dimensions on
* @return int The number of dimensions in $data
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::dimensions
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::dimensions
*/
- public static function dimensions(array $data)
+ public static function dimensions(array $data): int
{
if (empty($data)) {
return 0;
@@ -854,12 +867,12 @@ public static function dimensions(array $data)
*
* @param array $data Array to count dimensions on
* @return int The maximum number of dimensions in $data
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::maxDimensions
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::maxDimensions
*/
- public static function maxDimensions(array $data)
+ public static function maxDimensions(array $data): int
{
$depth = [];
- if (is_array($data) && !empty($data)) {
+ if (!empty($data)) {
foreach ($data as $value) {
if (is_array($value)) {
$depth[] = static::maxDimensions($value) + 1;
@@ -880,9 +893,9 @@ public static function maxDimensions(array $data)
* @param string $path The path to extract for mapping over.
* @param callable $function The function to call on each extracted value.
* @return array An array of the modified values.
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::map
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::map
*/
- public static function map(array $data, $path, $function)
+ public static function map(array $data, string $path, callable $function): array
{
$values = (array)static::extract($data, $path);
@@ -896,9 +909,9 @@ public static function map(array $data, $path, $function)
* @param string $path The path to extract from $data.
* @param callable $function The function to call on each extracted value.
* @return mixed The reduced value.
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::reduce
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::reduce
*/
- public static function reduce(array $data, $path, $function)
+ public static function reduce(array $data, string $path, callable $function)
{
$values = (array)static::extract($data, $path);
@@ -928,9 +941,9 @@ public static function reduce(array $data, $path, $function)
* @param string $path The path to extract from $data.
* @param callable $function The function to call on each extracted value.
* @return mixed The results of the applied method.
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::apply
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::apply
*/
- public static function apply(array $data, $path, $function)
+ public static function apply(array $data, string $path, callable $function)
{
$values = (array)static::extract($data, $path);
@@ -942,8 +955,8 @@ public static function apply(array $data, $path, $function)
*
* ### Sort directions
*
- * - `asc` Sort ascending.
- * - `desc` Sort descending.
+ * - `asc` or \SORT_ASC Sort ascending.
+ * - `desc` or \SORT_DESC Sort descending.
*
* ### Sort types
*
@@ -965,12 +978,12 @@ public static function apply(array $data, $path, $function)
*
* @param array $data An array of data to sort
* @param string $path A Set-compatible path to the array value
- * @param string $dir See directions above. Defaults to 'asc'.
+ * @param string|int $dir See directions above. Defaults to 'asc'.
* @param array|string $type See direction types above. Defaults to 'regular'.
* @return array Sorted array of data
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::sort
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::sort
*/
- public static function sort(array $data, $path, $dir = 'asc', $type = 'regular')
+ public static function sort(array $data, string $path, $dir = 'asc', $type = 'regular'): array
{
if (empty($data)) {
return [];
@@ -980,6 +993,7 @@ public static function sort(array $data, $path, $dir = 'asc', $type = 'regular')
if ($numeric) {
$data = array_values($data);
}
+ /** @var array $sortValues */
$sortValues = static::extract($data, $path);
$dataCount = count($data);
@@ -996,10 +1010,18 @@ public static function sort(array $data, $path, $dir = 'asc', $type = 'regular')
$sortValues = array_pad($sortValues, $dataCount, null);
}
$result = static::_squash($sortValues);
+ /** @var array $keys */
$keys = static::extract($result, '{n}.id');
+ /** @var array $values */
$values = static::extract($result, '{n}.value');
- $dir = strtolower($dir);
+ if (is_string($dir)) {
+ $dir = strtolower($dir);
+ }
+ if (!in_array($dir, [\SORT_ASC, \SORT_DESC], true)) {
+ $dir = $dir === 'asc' ? \SORT_ASC : \SORT_DESC;
+ }
+
$ignoreCase = false;
// $type can be overloaded for case insensitive sort
@@ -1010,11 +1032,6 @@ public static function sort(array $data, $path, $dir = 'asc', $type = 'regular')
}
$type = strtolower($type);
- if ($dir === 'asc') {
- $dir = \SORT_ASC;
- } else {
- $dir = \SORT_DESC;
- }
if ($type === 'numeric') {
$type = \SORT_NUMERIC;
} elseif ($type === 'string') {
@@ -1053,10 +1070,10 @@ public static function sort(array $data, $path, $dir = 'asc', $type = 'regular')
* Squashes an array to a single hash so it can be sorted.
*
* @param array $data The data to squash.
- * @param string|null $key The key for the data.
+ * @param mixed $key The key for the data.
* @return array
*/
- protected static function _squash(array $data, $key = null)
+ protected static function _squash(array $data, $key = null): array
{
$stack = [];
foreach ($data as $k => $r) {
@@ -1083,9 +1100,9 @@ protected static function _squash(array $data, $key = null)
* @param array $compare Second value
* @return array Returns the key => value pairs that are not common in $data and $compare
* The expression for this function is ($data - $compare) + ($compare - ($data - $compare))
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::diff
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::diff
*/
- public static function diff(array $data, array $compare)
+ public static function diff(array $data, array $compare): array
{
if (empty($data)) {
return (array)$compare;
@@ -1110,9 +1127,9 @@ public static function diff(array $data, array $compare)
* @param array $data The data to append onto.
* @param array $compare The data to compare and append onto.
* @return array The merged array.
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::mergeDiff
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::mergeDiff
*/
- public static function mergeDiff(array $data, array $compare)
+ public static function mergeDiff(array $data, array $compare): array
{
if (empty($data) && !empty($compare)) {
return $compare;
@@ -1123,8 +1140,8 @@ public static function mergeDiff(array $data, array $compare)
foreach ($compare as $key => $value) {
if (!array_key_exists($key, $data)) {
$data[$key] = $value;
- } elseif (is_array($value) && is_array($data[$key])) {
- $data[$key] = static::mergeDiff($data[$key], $value);
+ } elseif (is_array($value)) {
+ $data[$key] = static::mergeDiff($data[$key], $compare[$key]);
}
}
@@ -1137,9 +1154,9 @@ public static function mergeDiff(array $data, array $compare)
* @param array $data List to normalize
* @param bool $assoc If true, $data will be converted to an associative array.
* @return array
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::normalize
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::normalize
*/
- public static function normalize(array $data, $assoc = true)
+ public static function normalize(array $data, bool $assoc = true): array
{
$keys = array_keys($data);
$count = count($keys);
@@ -1182,12 +1199,12 @@ public static function normalize(array $data, $assoc = true)
*
* @param array $data The data to nest.
* @param array $options Options are:
- * @return array of results, nested
+ * @return array[] of results, nested
* @see \Cake\Utility\Hash::extract()
* @throws \InvalidArgumentException When providing invalid data.
- * @link https://book.cakephp.org/3/en/core-libraries/hash.html#Cake\Utility\Hash::nest
+ * @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::nest
*/
- public static function nest(array $data, array $options = [])
+ public static function nest(array $data, array $options = []): array
{
if (!$data) {
return $data;
@@ -1202,6 +1219,7 @@ public static function nest(array $data, array $options = [])
];
$return = $idMap = [];
+ /** @var array $ids */
$ids = static::extract($data, $options['idPath']);
$idKeys = explode('.', $options['idPath']);
@@ -1222,9 +1240,9 @@ public static function nest(array $data, array $options = [])
$idMap[$id] = array_merge($result, [$options['children'] => []]);
}
if (!$parentId || !in_array($parentId, $ids)) {
- $return[] =& $idMap[$id];
+ $return[] = &$idMap[$id];
} else {
- $idMap[$parentId][$options['children']][] =& $idMap[$id];
+ $idMap[$parentId][$options['children']][] = &$idMap[$id];
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Utility/Inflector.php b/app/vendor/cakephp/cakephp/src/Utility/Inflector.php
index bcd3cc5fc..62abe2ca5 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/Inflector.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/Inflector.php
@@ -1,4 +1,6 @@
'\1zes',
'/^(ox)$/i' => '\1\2en',
'/([m|l])ouse$/i' => '\1ice',
- '/(matr|vert|ind)(ix|ex)$/i' => '\1ices',
+ '/(matr|vert)(ix|ex)$/i' => '\1ices',
'/(x|ch|ss|sh)$/i' => '\1es',
'/([^aeiouy]|qu)y$/i' => '\1ies',
'/(hive)$/i' => '\1s',
@@ -160,243 +162,6 @@ class Inflector
'pokemon', 'proceedings', 'research', 'sea[- ]bass', 'series', 'species', 'weather',
];
- /**
- * Default map of accented and special characters to ASCII characters
- *
- * @var array
- */
- protected static $_transliteration = [
- 'ä' => 'ae',
- 'æ' => 'ae',
- 'ǽ' => 'ae',
- 'ö' => 'oe',
- 'œ' => 'oe',
- 'ü' => 'ue',
- 'Ä' => 'Ae',
- 'Ü' => 'Ue',
- 'Ö' => 'Oe',
- 'À' => 'A',
- 'Á' => 'A',
- 'Â' => 'A',
- 'Ã' => 'A',
- 'Å' => 'A',
- 'Ǻ' => 'A',
- 'Ā' => 'A',
- 'Ă' => 'A',
- 'Ą' => 'A',
- 'Ǎ' => 'A',
- 'à' => 'a',
- 'á' => 'a',
- 'â' => 'a',
- 'ã' => 'a',
- 'å' => 'a',
- 'ǻ' => 'a',
- 'ā' => 'a',
- 'ă' => 'a',
- 'ą' => 'a',
- 'ǎ' => 'a',
- 'ª' => 'a',
- 'Ç' => 'C',
- 'Ć' => 'C',
- 'Ĉ' => 'C',
- 'Ċ' => 'C',
- 'Č' => 'C',
- 'ç' => 'c',
- 'ć' => 'c',
- 'ĉ' => 'c',
- 'ċ' => 'c',
- 'č' => 'c',
- 'Ð' => 'D',
- 'Ď' => 'D',
- 'Đ' => 'D',
- 'ð' => 'd',
- 'ď' => 'd',
- 'đ' => 'd',
- 'È' => 'E',
- 'É' => 'E',
- 'Ê' => 'E',
- 'Ë' => 'E',
- 'Ē' => 'E',
- 'Ĕ' => 'E',
- 'Ė' => 'E',
- 'Ę' => 'E',
- 'Ě' => 'E',
- 'è' => 'e',
- 'é' => 'e',
- 'ê' => 'e',
- 'ë' => 'e',
- 'ē' => 'e',
- 'ĕ' => 'e',
- 'ė' => 'e',
- 'ę' => 'e',
- 'ě' => 'e',
- 'Ĝ' => 'G',
- 'Ğ' => 'G',
- 'Ġ' => 'G',
- 'Ģ' => 'G',
- 'Ґ' => 'G',
- 'ĝ' => 'g',
- 'ğ' => 'g',
- 'ġ' => 'g',
- 'ģ' => 'g',
- 'ґ' => 'g',
- 'Ĥ' => 'H',
- 'Ħ' => 'H',
- 'ĥ' => 'h',
- 'ħ' => 'h',
- 'І' => 'I',
- 'Ì' => 'I',
- 'Í' => 'I',
- 'Î' => 'I',
- 'Ї' => 'Yi',
- 'Ï' => 'I',
- 'Ĩ' => 'I',
- 'Ī' => 'I',
- 'Ĭ' => 'I',
- 'Ǐ' => 'I',
- 'Į' => 'I',
- 'İ' => 'I',
- 'і' => 'i',
- 'ì' => 'i',
- 'í' => 'i',
- 'î' => 'i',
- 'ï' => 'i',
- 'ї' => 'yi',
- 'ĩ' => 'i',
- 'ī' => 'i',
- 'ĭ' => 'i',
- 'ǐ' => 'i',
- 'į' => 'i',
- 'ı' => 'i',
- 'Ĵ' => 'J',
- 'ĵ' => 'j',
- 'Ķ' => 'K',
- 'ķ' => 'k',
- 'Ĺ' => 'L',
- 'Ļ' => 'L',
- 'Ľ' => 'L',
- 'Ŀ' => 'L',
- 'Ł' => 'L',
- 'ĺ' => 'l',
- 'ļ' => 'l',
- 'ľ' => 'l',
- 'ŀ' => 'l',
- 'ł' => 'l',
- 'Ñ' => 'N',
- 'Ń' => 'N',
- 'Ņ' => 'N',
- 'Ň' => 'N',
- 'ñ' => 'n',
- 'ń' => 'n',
- 'ņ' => 'n',
- 'ň' => 'n',
- 'ʼn' => 'n',
- 'Ò' => 'O',
- 'Ó' => 'O',
- 'Ô' => 'O',
- 'Õ' => 'O',
- 'Ō' => 'O',
- 'Ŏ' => 'O',
- 'Ǒ' => 'O',
- 'Ő' => 'O',
- 'Ơ' => 'O',
- 'Ø' => 'O',
- 'Ǿ' => 'O',
- 'ò' => 'o',
- 'ó' => 'o',
- 'ô' => 'o',
- 'õ' => 'o',
- 'ō' => 'o',
- 'ŏ' => 'o',
- 'ǒ' => 'o',
- 'ő' => 'o',
- 'ơ' => 'o',
- 'ø' => 'o',
- 'ǿ' => 'o',
- 'º' => 'o',
- 'Ŕ' => 'R',
- 'Ŗ' => 'R',
- 'Ř' => 'R',
- 'ŕ' => 'r',
- 'ŗ' => 'r',
- 'ř' => 'r',
- 'Ś' => 'S',
- 'Ŝ' => 'S',
- 'Ş' => 'S',
- 'Ș' => 'S',
- 'Š' => 'S',
- 'ẞ' => 'SS',
- 'ś' => 's',
- 'ŝ' => 's',
- 'ş' => 's',
- 'ș' => 's',
- 'š' => 's',
- 'ſ' => 's',
- 'Ţ' => 'T',
- 'Ț' => 'T',
- 'Ť' => 'T',
- 'Ŧ' => 'T',
- 'ţ' => 't',
- 'ț' => 't',
- 'ť' => 't',
- 'ŧ' => 't',
- 'Ù' => 'U',
- 'Ú' => 'U',
- 'Û' => 'U',
- 'Ũ' => 'U',
- 'Ū' => 'U',
- 'Ŭ' => 'U',
- 'Ů' => 'U',
- 'Ű' => 'U',
- 'Ų' => 'U',
- 'Ư' => 'U',
- 'Ǔ' => 'U',
- 'Ǖ' => 'U',
- 'Ǘ' => 'U',
- 'Ǚ' => 'U',
- 'Ǜ' => 'U',
- 'ù' => 'u',
- 'ú' => 'u',
- 'û' => 'u',
- 'ũ' => 'u',
- 'ū' => 'u',
- 'ŭ' => 'u',
- 'ů' => 'u',
- 'ű' => 'u',
- 'ų' => 'u',
- 'ư' => 'u',
- 'ǔ' => 'u',
- 'ǖ' => 'u',
- 'ǘ' => 'u',
- 'ǚ' => 'u',
- 'ǜ' => 'u',
- 'Ý' => 'Y',
- 'Ÿ' => 'Y',
- 'Ŷ' => 'Y',
- 'ý' => 'y',
- 'ÿ' => 'y',
- 'ŷ' => 'y',
- 'Ŵ' => 'W',
- 'ŵ' => 'w',
- 'Ź' => 'Z',
- 'Ż' => 'Z',
- 'Ž' => 'Z',
- 'ź' => 'z',
- 'ż' => 'z',
- 'ž' => 'z',
- 'Æ' => 'AE',
- 'Ǽ' => 'AE',
- 'ß' => 'ss',
- 'IJ' => 'IJ',
- 'ij' => 'ij',
- 'Œ' => 'OE',
- 'ƒ' => 'f',
- 'Þ' => 'TH',
- 'þ' => 'th',
- 'Є' => 'Ye',
- 'є' => 'ye',
- ];
-
/**
* Method cache array.
*
@@ -419,7 +184,7 @@ class Inflector
* @param string|false $value Inflected value
* @return string|false Inflected value on cache hit or false on cache miss.
*/
- protected static function _cache($type, $key, $value = false)
+ protected static function _cache(string $type, string $key, $value = false)
{
$key = '_' . $key;
$type = '_' . $type;
@@ -441,10 +206,10 @@ protected static function _cache($type, $key, $value = false)
*
* @return void
*/
- public static function reset()
+ public static function reset(): void
{
if (empty(static::$_initialState)) {
- static::$_initialState = get_class_vars(__CLASS__);
+ static::$_initialState = get_class_vars(self::class);
return;
}
@@ -457,7 +222,7 @@ public static function reset()
/**
* Adds custom inflection $rules, of either 'plural', 'singular',
- * 'uninflected', 'irregular' or 'transliteration' $type.
+ * 'uninflected' or 'irregular' $type.
*
* ### Usage:
*
@@ -465,17 +230,16 @@ public static function reset()
* Inflector::rules('plural', ['/^(inflect)or$/i' => '\1ables']);
* Inflector::rules('irregular', ['red' => 'redlings']);
* Inflector::rules('uninflected', ['dontinflectme']);
- * Inflector::rules('transliteration', ['/å/' => 'aa']);
* ```
*
* @param string $type The type of inflection, either 'plural', 'singular',
- * 'uninflected' or 'transliteration'.
+ * or 'uninflected'.
* @param array $rules Array of rules to be added.
* @param bool $reset If true, will unset default inflections for all
* new rules that are being defined in $rules.
* @return void
*/
- public static function rules($type, $rules, $reset = false)
+ public static function rules(string $type, array $rules, bool $reset = false): void
{
$var = '_' . $type;
@@ -498,26 +262,19 @@ public static function rules($type, $rules, $reset = false)
*
* @param string $word Word in singular
* @return string Word in plural
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-plural-singular-forms
+ * @link https://book.cakephp.org/4/en/core-libraries/inflector.html#creating-plural-singular-forms
*/
- public static function pluralize($word)
+ public static function pluralize(string $word): string
{
if (isset(static::$_cache['pluralize'][$word])) {
return static::$_cache['pluralize'][$word];
}
if (!isset(static::$_cache['irregular']['pluralize'])) {
- $words = array_keys(static::$_irregular);
- static::$_cache['irregular']['pluralize'] = '/(.*?(?:\\b|_))(' . implode('|', $words) . ')$/i';
-
- $upperWords = array_map('ucfirst', $words);
- static::$_cache['irregular']['upperPluralize'] = '/(.*?(?:\\b|[a-z]))(' . implode('|', $upperWords) . ')$/';
+ static::$_cache['irregular']['pluralize'] = '(?:' . implode('|', array_keys(static::$_irregular)) . ')';
}
- if (
- preg_match(static::$_cache['irregular']['pluralize'], $word, $regs) ||
- preg_match(static::$_cache['irregular']['upperPluralize'], $word, $regs)
- ) {
+ if (preg_match('/(.*?(?:\\b|_))(' . static::$_cache['irregular']['pluralize'] . ')$/i', $word, $regs)) {
static::$_cache['pluralize'][$word] = $regs[1] . substr($regs[2], 0, 1) .
substr(static::$_irregular[strtolower($regs[2])], 1);
@@ -525,10 +282,10 @@ public static function pluralize($word)
}
if (!isset(static::$_cache['uninflected'])) {
- static::$_cache['uninflected'] = '/^(' . implode('|', static::$_uninflected) . ')$/i';
+ static::$_cache['uninflected'] = '(?:' . implode('|', static::$_uninflected) . ')';
}
- if (preg_match(static::$_cache['uninflected'], $word, $regs)) {
+ if (preg_match('/^(' . static::$_cache['uninflected'] . ')$/i', $word, $regs)) {
static::$_cache['pluralize'][$word] = $word;
return $word;
@@ -541,6 +298,8 @@ public static function pluralize($word)
return static::$_cache['pluralize'][$word];
}
}
+
+ return $word;
}
/**
@@ -548,39 +307,31 @@ public static function pluralize($word)
*
* @param string $word Word in plural
* @return string Word in singular
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-plural-singular-forms
+ * @link https://book.cakephp.org/4/en/core-libraries/inflector.html#creating-plural-singular-forms
*/
- public static function singularize($word)
+ public static function singularize(string $word): string
{
if (isset(static::$_cache['singularize'][$word])) {
return static::$_cache['singularize'][$word];
}
if (!isset(static::$_cache['irregular']['singular'])) {
- $wordList = array_values(static::$_irregular);
- static::$_cache['irregular']['singular'] = '/(.*?(?:\\b|_))(' . implode('|', $wordList) . ')$/i';
-
- $upperWordList = array_map('ucfirst', $wordList);
- static::$_cache['irregular']['singularUpper'] = '/(.*?(?:\\b|[a-z]))(' .
- implode('|', $upperWordList) .
- ')$/';
+ static::$_cache['irregular']['singular'] = '(?:' . implode('|', static::$_irregular) . ')';
}
- if (
- preg_match(static::$_cache['irregular']['singular'], $word, $regs) ||
- preg_match(static::$_cache['irregular']['singularUpper'], $word, $regs)
- ) {
- static::$_cache['singularize'][$word] = $regs[1] . substr($regs[2], 0, 1) .
- substr(array_search(strtolower($regs[2]), static::$_irregular, true), 1);
+ if (preg_match('/(.*?(?:\\b|_))(' . static::$_cache['irregular']['singular'] . ')$/i', $word, $regs)) {
+ $suffix = array_search(strtolower($regs[2]), static::$_irregular, true);
+ $suffix = $suffix ? substr($suffix, 1) : '';
+ static::$_cache['singularize'][$word] = $regs[1] . substr($regs[2], 0, 1) . $suffix;
return static::$_cache['singularize'][$word];
}
if (!isset(static::$_cache['uninflected'])) {
- static::$_cache['uninflected'] = '/^(' . implode('|', static::$_uninflected) . ')$/i';
+ static::$_cache['uninflected'] = '(?:' . implode('|', static::$_uninflected) . ')';
}
- if (preg_match(static::$_cache['uninflected'], $word, $regs)) {
+ if (preg_match('/^(' . static::$_cache['uninflected'] . ')$/i', $word, $regs)) {
static::$_cache['pluralize'][$word] = $word;
return $word;
@@ -604,9 +355,9 @@ public static function singularize($word)
* @param string $string String to camelize
* @param string $delimiter the delimiter in the input string
* @return string CamelizedStringLikeThis.
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-camelcase-and-under-scored-forms
+ * @link https://book.cakephp.org/4/en/core-libraries/inflector.html#creating-camelcase-and-under-scored-forms
*/
- public static function camelize($string, $delimiter = '_')
+ public static function camelize(string $string, string $delimiter = '_'): string
{
$cacheKey = __FUNCTION__ . $delimiter;
@@ -627,9 +378,9 @@ public static function camelize($string, $delimiter = '_')
*
* @param string $string CamelCasedString to be "underscorized"
* @return string underscore_version of the input string
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-camelcase-and-under-scored-forms
+ * @link https://book.cakephp.org/4/en/core-libraries/inflector.html#creating-camelcase-and-under-scored-forms
*/
- public static function underscore($string)
+ public static function underscore(string $string): string
{
return static::delimit(str_replace('-', '_', $string), '_');
}
@@ -642,7 +393,7 @@ public static function underscore($string)
* @param string $string The string to dasherize.
* @return string Dashed version of the input string
*/
- public static function dasherize($string)
+ public static function dasherize(string $string): string
{
return static::delimit(str_replace('_', '-', $string), '-');
}
@@ -654,9 +405,9 @@ public static function dasherize($string)
* @param string $string String to be humanized
* @param string $delimiter the character to replace with a space
* @return string Human-readable string
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-human-readable-forms
+ * @link https://book.cakephp.org/4/en/core-libraries/inflector.html#creating-human-readable-forms
*/
- public static function humanize($string, $delimiter = '_')
+ public static function humanize(string $string, string $delimiter = '_'): string
{
$cacheKey = __FUNCTION__ . $delimiter;
@@ -681,7 +432,7 @@ public static function humanize($string, $delimiter = '_')
* @param string $delimiter the character to use as a delimiter
* @return string delimited string
*/
- public static function delimit($string, $delimiter = '_')
+ public static function delimit(string $string, string $delimiter = '_'): string
{
$cacheKey = __FUNCTION__ . $delimiter;
@@ -700,9 +451,9 @@ public static function delimit($string, $delimiter = '_')
*
* @param string $className Name of class to get database table name for
* @return string Name of the database table for given class
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-table-and-class-name-forms
+ * @link https://book.cakephp.org/4/en/core-libraries/inflector.html#creating-table-and-class-name-forms
*/
- public static function tableize($className)
+ public static function tableize(string $className): string
{
$result = static::_cache(__FUNCTION__, $className);
@@ -719,9 +470,9 @@ public static function tableize($className)
*
* @param string $tableName Name of database table to get class name for
* @return string Class name
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-table-and-class-name-forms
+ * @link https://book.cakephp.org/4/en/core-libraries/inflector.html#creating-table-and-class-name-forms
*/
- public static function classify($tableName)
+ public static function classify(string $tableName): string
{
$result = static::_cache(__FUNCTION__, $tableName);
@@ -738,9 +489,9 @@ public static function classify($tableName)
*
* @param string $string String to convert.
* @return string in variable form
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-variable-names
+ * @link https://book.cakephp.org/4/en/core-libraries/inflector.html#creating-variable-names
*/
- public static function variable($string)
+ public static function variable(string $string): string
{
$result = static::_cache(__FUNCTION__, $string);
@@ -753,37 +504,4 @@ public static function variable($string)
return $result;
}
-
- /**
- * Returns a string with all spaces converted to dashes (by default), accented
- * characters converted to non-accented characters, and non word characters removed.
- *
- * @deprecated 3.2.7 Use Text::slug() instead.
- * @param string $string the string you want to slug
- * @param string $replacement will replace keys in map
- * @return string
- * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-url-safe-strings
- */
- public static function slug($string, $replacement = '-')
- {
- deprecationWarning(
- 'Inflector::slug() is deprecated. ' .
- 'Use Text::slug() instead.'
- );
- $quotedReplacement = preg_quote($replacement, '/');
-
- $map = [
- '/[^\s\p{Zs}\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]/mu' => ' ',
- '/[\s\p{Zs}]+/mu' => $replacement,
- sprintf('/^[%s]+|[%s]+$/', $quotedReplacement, $quotedReplacement) => '',
- ];
-
- $string = str_replace(
- array_keys(static::$_transliteration),
- static::$_transliteration,
- $string
- );
-
- return preg_replace(array_keys($map), array_values($map), $string);
- }
}
diff --git a/app/vendor/cakephp/cakephp/src/Utility/LICENSE.txt b/app/vendor/cakephp/cakephp/src/Utility/LICENSE.txt
index 0c4b7932c..0b3b94303 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/LICENSE.txt
+++ b/app/vendor/cakephp/cakephp/src/Utility/LICENSE.txt
@@ -1,7 +1,7 @@
The MIT License (MIT)
CakePHP(tm) : The Rapid Development PHP Framework (https://cakephp.org)
-Copyright (c) 2005-2016, Cake Software Foundation, Inc. (https://cakefoundation.org)
+Copyright (c) 2005-2019, Cake Software Foundation, Inc. (https://cakefoundation.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/vendor/cakephp/cakephp/src/Utility/MergeVariablesTrait.php b/app/vendor/cakephp/cakephp/src/Utility/MergeVariablesTrait.php
index d77264c31..803950459 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/MergeVariablesTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/MergeVariablesTrait.php
@@ -1,4 +1,6 @@
{$property};
$isAssoc = false;
if (
isset($options['associative']) &&
- in_array($property, (array)$options['associative'])
+ in_array($property, (array)$options['associative'], true)
) {
$isAssoc = true;
}
@@ -99,7 +101,7 @@ protected function _mergeProperty($property, $parentClasses, $options)
* @param bool $isAssoc Whether or not the merging should be done in associative mode.
* @return mixed The updated value.
*/
- protected function _mergePropertyData($current, $parent, $isAssoc)
+ protected function _mergePropertyData(array $current, array $parent, bool $isAssoc)
{
if (!$isAssoc) {
return array_merge($parent, $current);
diff --git a/app/vendor/cakephp/cakephp/src/Utility/README.md b/app/vendor/cakephp/cakephp/src/Utility/README.md
index 2798d2838..45601b856 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/README.md
+++ b/app/vendor/cakephp/cakephp/src/Utility/README.md
@@ -23,7 +23,7 @@ $bigPeople = Hash::extract($things, '{n}[age>21].name');
// $bigPeople will contain ['Susan', 'Lucy']
```
-Check the [official Hash class documentation](https://book.cakephp.org/3/en/core-libraries/hash.html)
+Check the [official Hash class documentation](https://book.cakephp.org/4/en/core-libraries/hash.html)
### Inflector
@@ -36,7 +36,7 @@ echo Inflector::pluralize('Apple'); // echoes Apples
echo Inflector::singularize('People'); // echoes Person
```
-Check the [official Inflector class documentation](https://book.cakephp.org/3/en/core-libraries/inflector.html)
+Check the [official Inflector class documentation](https://book.cakephp.org/4/en/core-libraries/inflector.html)
### Text
@@ -57,7 +57,7 @@ This is the song
that never ends.
```
-Check the [official Text class documentation](https://book.cakephp.org/3/en/core-libraries/text.html)
+Check the [official Text class documentation](https://book.cakephp.org/4/en/core-libraries/text.html)
### Security
@@ -70,7 +70,7 @@ $result = Security::encrypt($value, $key);
Security::decrypt($result, $key);
```
-Check the [official Security class documentation](https://book.cakephp.org/3/en/core-libraries/security.html)
+Check the [official Security class documentation](https://book.cakephp.org/4/en/core-libraries/security.html)
### Xml
@@ -88,4 +88,4 @@ $data = [
$xml = Xml::build($data);
```
-Check the [official Xml class documentation](https://book.cakephp.org/3/en/core-libraries/xml.html)
+Check the [official Xml class documentation](https://book.cakephp.org/4/en/core-libraries/xml.html)
diff --git a/app/vendor/cakephp/cakephp/src/Utility/Security.php b/app/vendor/cakephp/cakephp/src/Utility/Security.php
index f649f78e2..f5238bc9b 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/Security.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/Security.php
@@ -1,4 +1,6 @@
rijndael($text, $key, $operation);
- }
-
/**
* Encrypt a value using AES-256.
*
@@ -240,16 +189,17 @@ public static function rijndael($text, $key, $operation)
*
* @param string $plain The value to encrypt.
* @param string $key The 256 bit/32 byte key to use as a cipher key.
- * @param string|null $hmacSalt The salt to use for the HMAC process. Leave null to use Security.salt.
+ * @param string|null $hmacSalt The salt to use for the HMAC process.
+ * Leave null to use value of Security::getSalt().
* @return string Encrypted data.
* @throws \InvalidArgumentException On invalid data or key.
*/
- public static function encrypt($plain, $key, $hmacSalt = null)
+ public static function encrypt(string $plain, string $key, ?string $hmacSalt = null): string
{
self::_checkKey($key, 'encrypt()');
if ($hmacSalt === null) {
- $hmacSalt = static::$_salt;
+ $hmacSalt = static::getSalt();
}
// Generate the encryption and hmac key.
$key = mb_substr(hash('sha256', $key . $hmacSalt), 0, 32, '8bit');
@@ -269,7 +219,7 @@ public static function encrypt($plain, $key, $hmacSalt = null)
* @return void
* @throws \InvalidArgumentException When key length is not 256 bit/32 bytes
*/
- protected static function _checkKey($key, $method)
+ protected static function _checkKey(string $key, string $method): void
{
if (mb_strlen($key, '8bit') < 32) {
throw new InvalidArgumentException(
@@ -283,18 +233,19 @@ protected static function _checkKey($key, $method)
*
* @param string $cipher The ciphertext to decrypt.
* @param string $key The 256 bit/32 byte key to use as a cipher key.
- * @param string|null $hmacSalt The salt to use for the HMAC process. Leave null to use Security.salt.
- * @return string|false Decrypted data. Any trailing null bytes will be removed.
+ * @param string|null $hmacSalt The salt to use for the HMAC process.
+ * Leave null to use value of Security::getSalt().
+ * @return string|null Decrypted data. Any trailing null bytes will be removed.
* @throws \InvalidArgumentException On invalid data or key.
*/
- public static function decrypt($cipher, $key, $hmacSalt = null)
+ public static function decrypt(string $cipher, string $key, ?string $hmacSalt = null): ?string
{
self::_checkKey($key, 'decrypt()');
if (empty($cipher)) {
throw new InvalidArgumentException('The data to decrypt cannot be empty.');
}
if ($hmacSalt === null) {
- $hmacSalt = static::$_salt;
+ $hmacSalt = static::getSalt();
}
// Generate the encryption and hmac key.
@@ -307,7 +258,7 @@ public static function decrypt($cipher, $key, $hmacSalt = null)
$compareHmac = hash_hmac('sha256', $cipher, $key);
if (!static::constantEquals($hmac, $compareHmac)) {
- return false;
+ return null;
}
$crypto = static::engine();
@@ -318,31 +269,14 @@ public static function decrypt($cipher, $key, $hmacSalt = null)
/**
* A timing attack resistant comparison that prefers native PHP implementations.
*
- * @param string $original The original value.
- * @param string $compare The comparison value.
+ * @param mixed $original The original value.
+ * @param mixed $compare The comparison value.
* @return bool
- * @see https://github.com/resonantcore/php-future/
* @since 3.6.2
*/
- public static function constantEquals($original, $compare)
+ public static function constantEquals($original, $compare): bool
{
- if (!is_string($original) || !is_string($compare)) {
- return false;
- }
- if (function_exists('hash_equals')) {
- return hash_equals($original, $compare);
- }
- $originalLength = mb_strlen($original, '8bit');
- $compareLength = mb_strlen($compare, '8bit');
- if ($originalLength !== $compareLength) {
- return false;
- }
- $result = 0;
- for ($i = 0; $i < $originalLength; $i++) {
- $result |= (ord($original[$i]) ^ ord($compare[$i]));
- }
-
- return $result === 0;
+ return is_string($original) && is_string($compare) && hash_equals($original, $compare);
}
/**
@@ -351,7 +285,7 @@ public static function constantEquals($original, $compare)
*
* @return string The currently configured salt
*/
- public static function getSalt()
+ public static function getSalt(): string
{
if (static::$_salt === null) {
throw new RuntimeException(
@@ -369,29 +303,8 @@ public static function getSalt()
* @param string $salt The salt to use for encryption routines.
* @return void
*/
- public static function setSalt($salt)
- {
- static::$_salt = (string)$salt;
- }
-
- /**
- * Gets or sets the HMAC salt to be used for encryption/decryption
- * routines.
- *
- * @deprecated 3.5.0 Use getSalt()/setSalt() instead.
- * @param string|null $salt The salt to use for encryption routines. If null returns current salt.
- * @return string The currently configured salt
- */
- public static function salt($salt = null)
+ public static function setSalt(string $salt): void
{
- deprecationWarning(
- 'Security::salt() is deprecated. ' .
- 'Use Security::getSalt()/setSalt() instead.'
- );
- if ($salt === null) {
- return static::$_salt;
- }
-
- return static::$_salt = (string)$salt;
+ static::$_salt = $salt;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Utility/String.php b/app/vendor/cakephp/cakephp/src/Utility/String.php
deleted file mode 100644
index 239e03a12..000000000
--- a/app/vendor/cakephp/cakephp/src/Utility/String.php
+++ /dev/null
@@ -1,6 +0,0 @@
- ':', 'after' => null, 'escape' => '\\', 'format' => null, 'clean' => false,
+ 'before' => ':', 'after' => '', 'escape' => '\\', 'format' => null, 'clean' => false,
];
$options += $defaults;
$format = $options['format'];
- $data = (array)$data;
+ $data = $data;
if (empty($data)) {
return $options['clean'] ? static::cleanInsert($str, $options) : $str;
}
@@ -219,6 +226,7 @@ public static function insert($str, $data, array $options = [])
$dataKeys = array_keys($data);
$hashKeys = array_map('crc32', $dataKeys);
+ /** @var array $tempData */
$tempData = array_combine($dataKeys, $hashKeys);
krsort($tempData);
@@ -226,6 +234,7 @@ public static function insert($str, $data, array $options = [])
$key = sprintf($format, preg_quote($key, '/'));
$str = preg_replace($key, $hashVal, $str);
}
+ /** @var array $dataReplacements */
$dataReplacements = array_combine($hashKeys, array_values($data));
foreach ($dataReplacements as $tmpHash => $tmpValue) {
$tmpValue = is_array($tmpValue) ? '' : $tmpValue;
@@ -250,7 +259,7 @@ public static function insert($str, $data, array $options = [])
* @return string
* @see \Cake\Utility\Text::insert()
*/
- public static function cleanInsert($str, array $options)
+ public static function cleanInsert(string $str, array $options): string
{
$clean = $options['clean'];
if (!$clean) {
@@ -320,7 +329,7 @@ public static function cleanInsert($str, array $options)
* @param array|int $options Array of options to use, or an integer to wrap the text to.
* @return string Formatted text.
*/
- public static function wrap($text, $options = [])
+ public static function wrap(string $text, $options = []): string
{
if (is_numeric($options)) {
$options = ['width' => $options];
@@ -357,7 +366,7 @@ public static function wrap($text, $options = [])
* @param array|int $options Array of options to use, or an integer to wrap the text to.
* @return string Formatted text.
*/
- public static function wrapBlock($text, $options = [])
+ public static function wrapBlock(string $text, $options = []): string
{
if (is_numeric($options)) {
$options = ['width' => $options];
@@ -406,7 +415,7 @@ public static function wrapBlock($text, $options = [])
* @param bool $cut If the cut is set to true, the string is always wrapped at the specified width.
* @return string Formatted text.
*/
- public static function wordWrap($text, $width = 72, $break = "\n", $cut = false)
+ public static function wordWrap(string $text, int $width = 72, string $break = "\n", bool $cut = false): string
{
$paragraphs = explode($break, $text);
foreach ($paragraphs as &$paragraph) {
@@ -425,7 +434,7 @@ public static function wordWrap($text, $width = 72, $break = "\n", $cut = false)
* @param bool $cut If the cut is set to true, the string is always wrapped at the specified width.
* @return string Formatted text.
*/
- protected static function _wordWrap($text, $width = 72, $break = "\n", $cut = false)
+ protected static function _wordWrap(string $text, int $width = 72, string $break = "\n", bool $cut = false): string
{
if ($cut) {
$parts = [];
@@ -482,9 +491,9 @@ protected static function _wordWrap($text, $width = 72, $break = "\n", $cut = fa
* @param string|array $phrase The phrase or phrases that will be searched.
* @param array $options An array of HTML attributes and options.
* @return string The highlighted text
- * @link https://book.cakephp.org/3/en/core-libraries/text.html#highlighting-substrings
+ * @link https://book.cakephp.org/4/en/core-libraries/text.html#highlighting-substrings
*/
- public static function highlight($text, $phrase, array $options = [])
+ public static function highlight(string $text, $phrase, array $options = []): string
{
if (empty($phrase)) {
return $text;
@@ -498,57 +507,34 @@ public static function highlight($text, $phrase, array $options = [])
];
$options += $defaults;
- $html = $format = $limit = null;
- /**
- * @var bool $html
- * @var string|array $format
- * @var int $limit
- */
- extract($options);
-
if (is_array($phrase)) {
$replace = [];
$with = [];
foreach ($phrase as $key => $segment) {
$segment = '(' . preg_quote($segment, '|') . ')';
- if ($html) {
+ if ($options['html']) {
$segment = "(?![^<]+>)$segment(?![^<]+>)";
}
- $with[] = is_array($format) ? $format[$key] : $format;
+ $with[] = is_array($options['format']) ? $options['format'][$key] : $options['format'];
$replace[] = sprintf($options['regex'], $segment);
}
- return preg_replace($replace, $with, $text, $limit);
+ return preg_replace($replace, $with, $text, $options['limit']);
}
$phrase = '(' . preg_quote($phrase, '|') . ')';
- if ($html) {
+ if ($options['html']) {
$phrase = "(?![^<]+>)$phrase(?![^<]+>)";
}
- return preg_replace(sprintf($options['regex'], $phrase), $format, $text, $limit);
- }
-
- /**
- * Strips given text of all links (]*)?(>|$)#i', '', $text, -1, $count);
- } while ($count);
-
- return $text;
+ return preg_replace(
+ sprintf($options['regex'], $phrase),
+ $options['format'],
+ $text,
+ $options['limit']
+ );
}
/**
@@ -567,25 +553,20 @@ public static function stripLinks($text)
* @param array $options An array of options.
* @return string Trimmed string.
*/
- public static function tail($text, $length = 100, array $options = [])
+ public static function tail(string $text, int $length = 100, array $options = []): string
{
$default = [
'ellipsis' => '...', 'exact' => true,
];
$options += $default;
- $exact = $ellipsis = null;
- /**
- * @var string $ellipsis
- * @var bool $exact
- */
- extract($options);
+ $ellipsis = $options['ellipsis'];
if (mb_strlen($text) <= $length) {
return $text;
}
$truncate = mb_substr($text, mb_strlen($text) - $length + mb_strlen($ellipsis));
- if (!$exact) {
+ if (!$options['exact']) {
$spacepos = mb_strpos($truncate, ' ');
$truncate = $spacepos === false ? '' : trim(mb_substr($truncate, $spacepos));
}
@@ -610,14 +591,14 @@ public static function tail($text, $length = 100, array $options = [])
* @param int $length Length of returned string, including ellipsis.
* @param array $options An array of HTML attributes and options.
* @return string Trimmed string.
- * @link https://book.cakephp.org/3/en/core-libraries/text.html#truncating-text
+ * @link https://book.cakephp.org/4/en/core-libraries/text.html#truncating-text
*/
- public static function truncate($text, $length = 100, array $options = [])
+ public static function truncate(string $text, int $length = 100, array $options = []): string
{
$default = [
'ellipsis' => '...', 'exact' => true, 'html' => false, 'trimWidth' => false,
];
- if (!empty($options['html']) && strtolower(mb_internal_encoding()) === 'utf-8') {
+ if (!empty($options['html']) && strtolower((string)mb_internal_encoding()) === 'utf-8') {
$default['ellipsis'] = "\xe2\x80\xa6";
}
$options += $default;
@@ -641,6 +622,7 @@ public static function truncate($text, $length = 100, array $options = [])
}
if ($truncate === '') {
+ // phpcs:ignore Generic.Files.LineLength
if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/i', $tag[2])) {
if (preg_match('/<[\w]+[^>]*>/', $tag[0])) {
array_unshift($openTags, $tag[2]);
@@ -710,7 +692,7 @@ public static function truncate($text, $length = 100, array $options = [])
* @return string Trimmed string.
* @see \Cake\Utility\Text::truncate()
*/
- public static function truncateByWidth($text, $length = 100, array $options = [])
+ public static function truncateByWidth(string $text, int $length = 100, array $options = []): string
{
return static::truncate($text, $length, ['trimWidth' => true] + $options);
}
@@ -727,7 +709,7 @@ public static function truncateByWidth($text, $length = 100, array $options = []
* @param array $options An array of options.
* @return int
*/
- protected static function _strlen($text, array $options)
+ protected static function _strlen(string $text, array $options): int
{
if (empty($options['trimWidth'])) {
$strlen = 'mb_strlen';
@@ -763,11 +745,11 @@ function ($match) use ($strlen) {
*
* @param string $text The input string.
* @param int $start The position to begin extracting.
- * @param int $length The desired length.
+ * @param int|null $length The desired length.
* @param array $options An array of options.
* @return string
*/
- protected static function _substr($text, $start, $length, array $options)
+ protected static function _substr(string $text, int $start, ?int $length, array $options): string
{
if (empty($options['trimWidth'])) {
$substr = 'mb_substr';
@@ -827,7 +809,8 @@ protected static function _substr($text, $start, $length, array $options)
$len = self::_strlen($part, $options);
if ($offset !== 0 || $totalLength + $len > $length) {
if (
- strpos($part, '&') === 0 && preg_match($pattern, $part)
+ strpos($part, '&') === 0
+ && preg_match($pattern, $part)
&& $part !== html_entity_decode($part, ENT_HTML5 | ENT_QUOTES, 'UTF-8')
) {
// Entities cannot be passed substr.
@@ -854,12 +837,12 @@ protected static function _substr($text, $start, $length, array $options)
* @param string $text The input text
* @return string
*/
- protected static function _removeLastWord($text)
+ protected static function _removeLastWord(string $text): string
{
$spacepos = mb_strrpos($text, ' ');
if ($spacepos !== false) {
- $lastWord = mb_strrpos($text, $spacepos);
+ $lastWord = mb_substr($text, $spacepos);
// Some languages are written without word separation.
// We recognize a string as a word if it doesn't contain any full-width characters.
@@ -882,9 +865,9 @@ protected static function _removeLastWord($text)
* @param int $radius The amount of characters that will be returned on each side of the founded phrase
* @param string $ellipsis Ending that will be appended
* @return string Modified string
- * @link https://book.cakephp.org/3/en/core-libraries/text.html#extracting-an-excerpt
+ * @link https://book.cakephp.org/4/en/core-libraries/text.html#extracting-an-excerpt
*/
- public static function excerpt($text, $phrase, $radius = 100, $ellipsis = '...')
+ public static function excerpt(string $text, string $phrase, int $radius = 100, string $ellipsis = '...'): string
{
if (empty($text) || empty($phrase)) {
return static::truncate($text, $radius * 2, ['ellipsis' => $ellipsis]);
@@ -925,15 +908,15 @@ public static function excerpt($text, $phrase, $radius = 100, $ellipsis = '...')
* @param string|null $and The word used to join the last and second last items together with. Defaults to 'and'.
* @param string $separator The separator used to join all the other items together. Defaults to ', '.
* @return string The glued together string.
- * @link https://book.cakephp.org/3/en/core-libraries/text.html#converting-an-array-to-sentence-form
+ * @link https://book.cakephp.org/4/en/core-libraries/text.html#converting-an-array-to-sentence-form
*/
- public static function toList(array $list, $and = null, $separator = ', ')
+ public static function toList(array $list, ?string $and = null, string $separator = ', '): string
{
if ($and === null) {
$and = __d('cake', 'and');
}
if (count($list) > 1) {
- return implode($separator, array_slice($list, null, -1)) . ' ' . $and . ' ' . array_pop($list);
+ return implode($separator, array_slice($list, 0, -1)) . ' ' . $and . ' ' . array_pop($list);
}
return (string)array_pop($list);
@@ -945,7 +928,7 @@ public static function toList(array $list, $and = null, $separator = ', ')
* @param string $string value to test
* @return bool
*/
- public static function isMultibyte($string)
+ public static function isMultibyte(string $string): bool
{
$length = strlen($string);
@@ -966,7 +949,7 @@ public static function isMultibyte($string)
* @param string $string String to convert.
* @return array
*/
- public static function utf8($string)
+ public static function utf8(string $string): array
{
$map = [];
@@ -981,7 +964,7 @@ public static function utf8($string)
$map[] = $value;
} else {
if (empty($values)) {
- $find = ($value < 224) ? 2 : 3;
+ $find = $value < 224 ? 2 : 3;
}
$values[] = $value;
@@ -1007,7 +990,7 @@ public static function utf8($string)
* @param array $array Array
* @return string
*/
- public static function ascii(array $array)
+ public static function ascii(array $array): string
{
$ascii = '';
@@ -1034,9 +1017,9 @@ public static function ascii(array $array)
* @param mixed $default Value to be returned when invalid size was used, for example 'Unknown type'
* @return mixed Number of bytes as integer on success, `$default` on failure if not false
* @throws \InvalidArgumentException On invalid Unit type.
- * @link https://book.cakephp.org/3/en/core-libraries/text.html#Cake\Utility\Text::parseFileSize
+ * @link https://book.cakephp.org/4/en/core-libraries/text.html#Cake\Utility\Text::parseFileSize
*/
- public static function parseFileSize($size, $default = false)
+ public static function parseFileSize(string $size, $default = false)
{
if (ctype_digit($size)) {
return (int)$size;
@@ -1072,9 +1055,8 @@ public static function parseFileSize($size, $default = false)
*
* @return \Transliterator|null Either a Transliterator instance, or `null`
* in case no transliterator has been set yet.
- * @since 3.7.0
*/
- public static function getTransliterator()
+ public static function getTransliterator(): ?Transliterator
{
return static::$_defaultTransliterator;
}
@@ -1084,9 +1066,8 @@ public static function getTransliterator()
*
* @param \Transliterator $transliterator A `Transliterator` instance.
* @return void
- * @since 3.7.0
*/
- public static function setTransliterator(\Transliterator $transliterator)
+ public static function setTransliterator(Transliterator $transliterator): void
{
static::$_defaultTransliterator = $transliterator;
}
@@ -1096,7 +1077,7 @@ public static function setTransliterator(\Transliterator $transliterator)
*
* @return string Transliterator identifier.
*/
- public static function getTransliteratorId()
+ public static function getTransliteratorId(): string
{
return static::$_defaultTransliteratorId;
}
@@ -1107,7 +1088,7 @@ public static function getTransliteratorId()
* @param string $transliteratorId Transliterator identifier.
* @return void
*/
- public static function setTransliteratorId($transliteratorId)
+ public static function setTransliteratorId(string $transliteratorId): void
{
$transliterator = transliterator_create($transliteratorId);
if ($transliterator === null) {
@@ -1129,9 +1110,9 @@ public static function setTransliteratorId($transliteratorId)
* @return string
* @see https://secure.php.net/manual/en/transliterator.transliterate.php
*/
- public static function transliterate($string, $transliterator = null)
+ public static function transliterate(string $string, $transliterator = null): string
{
- if (!$transliterator) {
+ if (empty($transliterator)) {
$transliterator = static::$_defaultTransliterator ?: static::$_defaultTransliteratorId;
}
@@ -1164,7 +1145,7 @@ public static function transliterate($string, $transliterator = null)
* @see setTransliterator()
* @see setTransliteratorId()
*/
- public static function slug($string, $options = [])
+ public static function slug(string $string, $options = []): string
{
if (is_string($options)) {
$options = ['replacement' => $options];
diff --git a/app/vendor/cakephp/cakephp/src/Utility/Xml.php b/app/vendor/cakephp/cakephp/src/Utility/Xml.php
index e7cd6a3ee..17fee8d3b 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/Xml.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/Xml.php
@@ -1,4 +1,6 @@
get('http://example.com/example.xml');
- * $xml = Xml::build($response->getStringBody());
+ * $xml = Xml::build($response->body());
* ```
*
* Building from an array:
@@ -88,9 +90,8 @@ class Xml
* - `return` Can be 'simplexml' to return object of SimpleXMLElement or 'domdocument' to return DOMDocument.
* - `loadEntities` Defaults to false. Set to true to enable loading of ` 'simplexml',
'loadEntities' => false,
- 'readFile' => true,
+ 'readFile' => false,
'parseHuge' => false,
];
$options += $defaults;
@@ -114,10 +115,6 @@ public static function build($input, array $options = [])
return static::fromArray($input, $options);
}
- if (strpos($input, '<') !== false) {
- return static::_loadXml($input, $options);
- }
-
if ($options['readFile'] && file_exists($input)) {
return static::_loadXml(file_get_contents($input), $options);
}
@@ -142,11 +139,10 @@ public static function build($input, array $options = [])
* @return \SimpleXMLElement|\DOMDocument
* @throws \Cake\Utility\Exception\XmlException
*/
- protected static function _loadXml($input, $options)
+ protected static function _loadXml(string $input, array $options)
{
- $hasDisable = function_exists('libxml_disable_entity_loader');
$internalErrors = libxml_use_internal_errors(true);
- if ($hasDisable && !$options['loadEntities']) {
+ if (!$options['loadEntities']) {
libxml_disable_entity_loader(true);
}
$flags = 0;
@@ -166,7 +162,7 @@ protected static function _loadXml($input, $options)
} catch (Exception $e) {
throw new XmlException('Xml cannot be read. ' . $e->getMessage(), null, $e);
} finally {
- if ($hasDisable && !$options['loadEntities']) {
+ if (!$options['loadEntities']) {
libxml_disable_entity_loader(false);
}
libxml_use_internal_errors($internalErrors);
@@ -181,7 +177,7 @@ protected static function _loadXml($input, $options)
* @return \SimpleXMLElement|\DOMDocument
* @throws \Cake\Utility\Exception\XmlException
*/
- public static function loadHtml($input, $options = [])
+ public static function loadHtml(string $input, array $options = [])
{
$defaults = [
'return' => 'simplexml',
@@ -189,9 +185,8 @@ public static function loadHtml($input, $options = [])
];
$options += $defaults;
- $hasDisable = function_exists('libxml_disable_entity_loader');
$internalErrors = libxml_use_internal_errors(true);
- if ($hasDisable && !$options['loadEntities']) {
+ if (!$options['loadEntities']) {
libxml_disable_entity_loader(true);
}
$flags = 0;
@@ -203,7 +198,6 @@ public static function loadHtml($input, $options = [])
$xml->loadHTML($input, $flags);
if ($options['return'] === 'simplexml' || $options['return'] === 'simplexmlelement') {
- $flags |= LIBXML_NOCDATA;
$xml = simplexml_import_dom($xml);
}
@@ -211,7 +205,7 @@ public static function loadHtml($input, $options = [])
} catch (Exception $e) {
throw new XmlException('Xml cannot be read. ' . $e->getMessage(), null, $e);
} finally {
- if ($hasDisable && !$options['loadEntities']) {
+ if (!$options['loadEntities']) {
libxml_disable_entity_loader(false);
}
libxml_use_internal_errors($internalErrors);
@@ -226,8 +220,10 @@ public static function loadHtml($input, $options = [])
* - `format` If create childs ('tags') or attributes ('attributes').
* - `pretty` Returns formatted Xml when set to `true`. Defaults to `false`
* - `version` Version of XML document. Default is 1.0.
- * - `encoding` Encoding of XML document. If null remove from XML header. Default is the some of application.
- * - `return` If return object of SimpleXMLElement ('simplexml') or DOMDocument ('domdocument'). Default is SimpleXMLElement.
+ * - `encoding` Encoding of XML document. If null remove from XML header.
+ * Defaults to the application's encoding
+ * - `return` If return object of SimpleXMLElement ('simplexml')
+ * or DOMDocument ('domdocument'). Default is SimpleXMLElement.
*
* Using the following data:
*
@@ -256,7 +252,7 @@ public static function loadHtml($input, $options = [])
* @return \SimpleXMLElement|\DOMDocument SimpleXMLElement or DOMDocument
* @throws \Cake\Utility\Exception\XmlException
*/
- public static function fromArray($input, $options = [])
+ public static function fromArray($input, array $options = [])
{
if (is_object($input) && method_exists($input, 'toArray') && is_callable([$input, 'toArray'])) {
$input = call_user_func([$input, 'toArray']);
@@ -269,9 +265,6 @@ public static function fromArray($input, $options = [])
throw new XmlException('The key of input must be alphanumeric');
}
- if (!is_array($options)) {
- $options = ['format' => (string)$options];
- }
$defaults = [
'format' => 'tags',
'version' => '1.0',
@@ -305,7 +298,7 @@ public static function fromArray($input, $options = [])
* @return void
* @throws \Cake\Utility\Exception\XmlException
*/
- protected static function _fromArray($dom, $node, &$data, $format)
+ protected static function _fromArray(DOMDocument $dom, $node, &$data, $format): void
{
if (empty($data) || !is_array($data)) {
return;
@@ -324,6 +317,7 @@ protected static function _fromArray($dom, $node, &$data, $format)
}
$isNamespace = strpos($key, 'xmlns:');
if ($isNamespace !== false) {
+ /** @psalm-suppress PossiblyUndefinedMethod */
$node->setAttributeNS('http://www.w3.org/2000/xmlns/', $key, (string)$value);
continue;
}
@@ -335,7 +329,7 @@ protected static function _fromArray($dom, $node, &$data, $format)
$child = $dom->createElement($key, '');
$child->appendChild(new DOMText((string)$value));
} else {
- $child = $dom->createElement($key, $value);
+ $child = $dom->createElement($key, (string)$value);
}
$node->appendChild($child);
} else {
@@ -374,7 +368,7 @@ protected static function _fromArray($dom, $node, &$data, $format)
* @param array $data Array with information to create childs
* @return void
*/
- protected static function _createChild($data)
+ protected static function _createChild(array $data): void
{
$data += [
'dom' => null,
@@ -426,7 +420,7 @@ protected static function _createChild($data)
* @return array Array representation of the XML structure.
* @throws \Cake\Utility\Exception\XmlException
*/
- public static function toArray($obj)
+ public static function toArray($obj): array
{
if ($obj instanceof DOMNode) {
$obj = simplexml_import_dom($obj);
@@ -450,11 +444,12 @@ public static function toArray($obj)
* @param string[] $namespaces List of namespaces in XML
* @return void
*/
- protected static function _toArray($xml, &$parentData, $ns, $namespaces)
+ protected static function _toArray(SimpleXMLElement $xml, array &$parentData, string $ns, array $namespaces): void
{
$data = [];
foreach ($namespaces as $namespace) {
+ /** @psalm-suppress PossiblyNullIterator */
foreach ($xml->attributes($namespace, true) as $key => $value) {
if (!empty($namespace)) {
$key = $namespace . ':' . $key;
diff --git a/app/vendor/cakephp/cakephp/src/Utility/bootstrap.php b/app/vendor/cakephp/cakephp/src/Utility/bootstrap.php
index fbc847175..d335b754d 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/bootstrap.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/bootstrap.php
@@ -1,4 +1,6 @@
=5.6.0,<8.0.0",
- "cakephp/core": "^3.6.0"
+ "php": ">=7.2.0",
+ "cakephp/core": "^4.0"
},
"suggest": {
"ext-intl": "To use Text::transliterate() or Text::slug()",
diff --git a/app/vendor/cakephp/cakephp/src/Validation/LICENSE.txt b/app/vendor/cakephp/cakephp/src/Validation/LICENSE.txt
index 0c4b7932c..0b3b94303 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/LICENSE.txt
+++ b/app/vendor/cakephp/cakephp/src/Validation/LICENSE.txt
@@ -1,7 +1,7 @@
The MIT License (MIT)
CakePHP(tm) : The Rapid Development PHP Framework (https://cakephp.org)
-Copyright (c) 2005-2016, Cake Software Foundation, Inc. (https://cakefoundation.org)
+Copyright (c) 2005-2019, Cake Software Foundation, Inc. (https://cakefoundation.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/vendor/cakephp/cakephp/src/Validation/README.md b/app/vendor/cakephp/cakephp/src/Validation/README.md
index 45c57a77a..228e0a495 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/README.md
+++ b/app/vendor/cakephp/cakephp/src/Validation/README.md
@@ -34,4 +34,4 @@ if (!empty($errors)) {
## Documentation
-Please make sure you check the [official documentation](https://book.cakephp.org/3/en/core-libraries/validation.html)
+Please make sure you check the [official documentation](https://book.cakephp.org/4/en/core-libraries/validation.html)
diff --git a/app/vendor/cakephp/cakephp/src/Validation/RulesProvider.php b/app/vendor/cakephp/cakephp/src/Validation/RulesProvider.php
index 382c92ada..f5d8c3d53 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/RulesProvider.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/RulesProvider.php
@@ -1,4 +1,6 @@
_reflection->getMethod($method);
$argumentList = $method->getParameters();
diff --git a/app/vendor/cakephp/cakephp/src/Validation/ValidatableInterface.php b/app/vendor/cakephp/cakephp/src/Validation/ValidatableInterface.php
index 73a05297e..9defaa34a 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/ValidatableInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/ValidatableInterface.php
@@ -1,4 +1,6 @@
';
+ public const COMPARE_GREATER = '>';
/**
* Greater than or equal to comparison operator.
*
* @var string
*/
- const COMPARE_GREATER_OR_EQUAL = '>=';
+ public const COMPARE_GREATER_OR_EQUAL = '>=';
/**
* Less than comparison operator.
*
* @var string
*/
- const COMPARE_LESS = '<';
+ public const COMPARE_LESS = '<';
/**
* Less than or equal to comparison operator.
*
* @var string
*/
- const COMPARE_LESS_OR_EQUAL = '<=';
+ public const COMPARE_LESS_OR_EQUAL = '<=';
/**
* Datetime ISO8601 format
*
* @var string
*/
- const DATETIME_ISO8601 = 'iso8601';
+ public const DATETIME_ISO8601 = 'iso8601';
/**
* Some complex patterns needed in multiple places
@@ -119,24 +122,6 @@ class Validation
*/
public static $errors = [];
- /**
- * Backwards compatibility wrapper for Validation::notBlank().
- *
- * @param string $check Value to check.
- * @return bool Success.
- * @deprecated 3.0.2 Use Validation::notBlank() instead.
- * @see \Cake\Validation\Validation::notBlank()
- */
- public static function notEmpty($check)
- {
- deprecationWarning(
- 'Validation::notEmpty() is deprecated. ' .
- 'Use Validation::notBlank() instead.'
- );
-
- return static::notBlank($check);
- }
-
/**
* Checks that a string contains something other than whitespace
*
@@ -145,7 +130,7 @@ public static function notEmpty($check)
* @param mixed $check Value to check
* @return bool Success
*/
- public static function notBlank($check)
+ public static function notBlank($check): bool
{
if (empty($check) && !is_bool($check) && !is_numeric($check)) {
return false;
@@ -160,10 +145,10 @@ public static function notBlank($check)
* This method's definition of letters and integers includes unicode characters.
* Use `asciiAlphaNumeric()` if you want to exclude unicode.
*
- * @param string $check Value to check
+ * @param mixed $check Value to check
* @return bool Success
*/
- public static function alphaNumeric($check)
+ public static function alphaNumeric($check): bool
{
if ((empty($check) && $check !== '0') || !is_scalar($check)) {
return false;
@@ -181,7 +166,7 @@ public static function alphaNumeric($check)
* @param mixed $check Value to check
* @return bool Success
*/
- public static function notAlphaNumeric($check)
+ public static function notAlphaNumeric($check): bool
{
return !static::alphaNumeric($check);
}
@@ -192,7 +177,7 @@ public static function notAlphaNumeric($check)
* @param mixed $check Value to check
* @return bool Success
*/
- public static function asciiAlphaNumeric($check)
+ public static function asciiAlphaNumeric($check): bool
{
if ((empty($check) && $check !== '0') || !is_scalar($check)) {
return false;
@@ -207,7 +192,7 @@ public static function asciiAlphaNumeric($check)
* @param mixed $check Value to check
* @return bool Success
*/
- public static function notAsciiAlphaNumeric($check)
+ public static function notAsciiAlphaNumeric($check): bool
{
return !static::asciiAlphaNumeric($check);
}
@@ -222,7 +207,7 @@ public static function notAsciiAlphaNumeric($check)
* @param int $max Maximum value in range (inclusive)
* @return bool Success
*/
- public static function lengthBetween($check, $min, $max)
+ public static function lengthBetween($check, int $min, int $max): bool
{
if (!is_scalar($check)) {
return false;
@@ -232,46 +217,6 @@ public static function lengthBetween($check, $min, $max)
return $length >= $min && $length <= $max;
}
- /**
- * Returns true if field is left blank -OR- only whitespace characters are present in its value
- * Whitespace characters include Space, Tab, Carriage Return, Newline
- *
- * @param string $check Value to check
- * @return bool Success
- * @deprecated 3.0.2 Validation::blank() is deprecated.
- */
- public static function blank($check)
- {
- deprecationWarning(
- 'Validation::blank() is deprecated.'
- );
-
- return !static::_check($check, '/[^\\s]/');
- }
-
- /**
- * Backwards compatibility wrapper for Validation::creditCard().
- *
- * @param string $check credit card number to validate
- * @param string|string[] $type 'all' may be passed as a string, defaults to fast which checks format of most major credit cards
- * if an array is used only the values of the array are checked.
- * Example: ['amex', 'bankcard', 'maestro']
- * @param bool $deep set to true this will check the Luhn algorithm of the credit card.
- * @param string|null $regex A custom regex can also be passed, this will be used instead of the defined regex values
- * @return bool Success
- * @deprecated 3.7.0 Use Validation::creditCard() instead.
- * @see \Cake\Validation\Validation::creditCard()
- */
- public static function cc($check, $type = 'fast', $deep = false, $regex = null)
- {
- deprecationWarning(
- 'Validation::cc() is deprecated. ' .
- 'Use Validation::creditCard() instead.'
- );
-
- return static::creditCard($check, $type, $deep, $regex);
- }
-
/**
* Validation of credit card numbers.
* Returns true if $check is in the proper credit card format.
@@ -281,11 +226,11 @@ public static function cc($check, $type = 'fast', $deep = false, $regex = null)
* most major credit cards if an array is used only the values of the array are checked.
* Example: ['amex', 'bankcard', 'maestro']
* @param bool $deep set to true this will check the Luhn algorithm of the credit card.
- * @param string|null $regex A custom regex can also be passed, this will be used instead of the defined regex values
+ * @param string|null $regex A custom regex, this will be used instead of the defined regex values.
* @return bool Success
* @see \Cake\Validation\Validation::luhn()
*/
- public static function creditCard($check, $type = 'fast', $deep = false, $regex = null)
+ public static function creditCard($check, $type = 'fast', bool $deep = false, ?string $regex = null): bool
{
if (!(is_string($check) || is_int($check))) {
return false;
@@ -311,10 +256,12 @@ public static function creditCard($check, $type = 'fast', $deep = false, $regex
'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/',
'mc' => '/^(5[1-5]\\d{14})|(2(?:22[1-9]|2[3-9][0-9]|[3-6][0-9]{2}|7[0-1][0-9]|720)\\d{12})$/',
'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
+ // phpcs:ignore Generic.Files.LineLength
'switch' => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4][0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/',
'visa' => '/^4\\d{12}(\\d{3})?$/',
'voyager' => '/^8699[0-9]{11}$/',
],
+ // phpcs:ignore Generic.Files.LineLength
'fast' => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/',
];
@@ -355,9 +302,9 @@ public static function creditCard($check, $type = 'fast', $deep = false, $regex
* @param int $expectedCount The expected count value.
* @return bool Success
*/
- public static function numElements($check, $operator, $expectedCount)
+ public static function numElements($check, string $operator, int $expectedCount): bool
{
- if (!is_array($check) && !$check instanceof \Countable) {
+ if (!is_array($check) && !$check instanceof Countable) {
return false;
}
@@ -374,77 +321,39 @@ public static function numElements($check, $operator, $expectedCount)
* @param string|int $check2 The right value to compare.
* @return bool Success
*/
- public static function comparison($check1, $operator, $check2)
+ public static function comparison($check1, string $operator, $check2): bool
{
if ((float)$check1 != $check1) {
return false;
}
- $message = 'Operator `%s` is deprecated, use constant `Validation::%s` instead.';
-
$operator = str_replace([' ', "\t", "\n", "\r", "\0", "\x0B"], '', strtolower($operator));
switch ($operator) {
- case 'isgreater':
- /*
- * @deprecated 3.6.0 Use Validation::COMPARE_GREATER instead.
- */
- deprecationWarning(sprintf($message, $operator, 'COMPARE_GREATER'));
- // no break
case static::COMPARE_GREATER:
if ($check1 > $check2) {
return true;
}
break;
- case 'isless':
- /*
- * @deprecated 3.6.0 Use Validation::COMPARE_LESS instead.
- */
- deprecationWarning(sprintf($message, $operator, 'COMPARE_LESS'));
- // no break
case static::COMPARE_LESS:
if ($check1 < $check2) {
return true;
}
break;
- case 'greaterorequal':
- /*
- * @deprecated 3.6.0 Use Validation::COMPARE_GREATER_OR_EQUAL instead.
- */
- deprecationWarning(sprintf($message, $operator, 'COMPARE_GREATER_OR_EQUAL'));
- // no break
case static::COMPARE_GREATER_OR_EQUAL:
if ($check1 >= $check2) {
return true;
}
break;
- case 'lessorequal':
- /*
- * @deprecated 3.6.0 Use Validation::COMPARE_LESS_OR_EQUAL instead.
- */
- deprecationWarning(sprintf($message, $operator, 'COMPARE_LESS_OR_EQUAL'));
- // no break
case static::COMPARE_LESS_OR_EQUAL:
if ($check1 <= $check2) {
return true;
}
break;
- case 'equalto':
- /*
- * @deprecated 3.6.0 Use Validation::COMPARE_EQUAL instead.
- */
- deprecationWarning(sprintf($message, $operator, 'COMPARE_EQUAL'));
- // no break
case static::COMPARE_EQUAL:
if ($check1 == $check2) {
return true;
}
break;
- case 'notequal':
- /*
- * @deprecated 3.6.0 Use Validation::COMPARE_NOT_EQUAL instead.
- */
- deprecationWarning(sprintf($message, $operator, 'COMPARE_NOT_EQUAL'));
- // no break
case static::COMPARE_NOT_EQUAL:
if ($check1 != $check2) {
return true;
@@ -477,7 +386,7 @@ public static function comparison($check1, $operator, $check2)
* @param array $context The validation context.
* @return bool
*/
- public static function compareWith($check, $field, $context)
+ public static function compareWith($check, string $field, array $context): bool
{
return self::compareFields($check, $field, static::COMPARE_SAME, $context);
}
@@ -494,7 +403,7 @@ public static function compareWith($check, $field, $context)
* @return bool
* @since 3.6.0
*/
- public static function compareFields($check, $field, $operator, $context)
+ public static function compareFields($check, string $field, string $operator, array $context): bool
{
if (!isset($context['data']) || !array_key_exists($field, $context['data'])) {
return false;
@@ -508,14 +417,14 @@ public static function compareFields($check, $field, $operator, $context)
*
* Returns true if string contains at least the specified number of non-alphanumeric characters
*
- * @param string $check Value to check
+ * @param mixed $check Value to check
* @param int $count Number of non-alphanumerics to check for
* @return bool Success
- * @deprecated 3.9.0 Use notAlphaNumeric() instead. Will be removed in 5.0
+ * @deprecated 4.0.0 Use {@link notAlphaNumeric()} instead. Will be removed in 5.0
*/
- public static function containsNonAlphaNumeric($check, $count = 1)
+ public static function containsNonAlphaNumeric($check, int $count = 1): bool
{
- if (!is_scalar($check)) {
+ if (!is_string($check)) {
return false;
}
@@ -531,7 +440,7 @@ public static function containsNonAlphaNumeric($check, $count = 1)
* @param string|null $regex If $check is passed as a string, $regex must also be set to valid regular expression
* @return bool Success
*/
- public static function custom($check, $regex = null)
+ public static function custom(string $check, ?string $regex = null): bool
{
if ($regex === null) {
static::$errors[] = 'You must define a regular expression for Validation::custom()';
@@ -566,7 +475,7 @@ public static function custom($check, $regex = null)
* @param string|null $regex If a custom regular expression is used this is the only validation that will occur.
* @return bool Success
*/
- public static function date($check, $format = 'ymd', $regex = null)
+ public static function date($check, $format = 'ymd', ?string $regex = null): bool
{
if ($check instanceof DateTimeInterface) {
return true;
@@ -589,6 +498,7 @@ public static function date($check, $format = 'ymd', $regex = null)
$twoDigitYear = '(?:\d{2})';
$year = '(?:' . $fourDigitYear . '|' . $twoDigitYear . ')';
+ // phpcs:disable Generic.Files.LineLength
// 2 or 4 digit leap year sub-pattern
$leapYear = '(?:(?:(?:(?!0000)[012]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))';
// 4 digit leap year sub-pattern
@@ -613,6 +523,7 @@ public static function date($check, $format = 'ymd', $regex = null)
$regex['My'] = '%^(Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)' .
$separator . $fourDigitYear . '$%';
+ // phpcs:enable Generic.Files.LineLength
$regex['my'] = '%^(' . $month . $separator . $year . ')$%';
$regex['ym'] = '%^(' . $year . $separator . $month . ')$%';
@@ -642,7 +553,7 @@ public static function date($check, $format = 'ymd', $regex = null)
* @see \Cake\Validation\Validation::date()
* @see \Cake\Validation\Validation::time()
*/
- public static function datetime($check, $dateFormat = 'ymd', $regex = null)
+ public static function datetime($check, $dateFormat = 'ymd', ?string $regex = null): bool
{
if ($check instanceof DateTimeInterface) {
return true;
@@ -662,7 +573,7 @@ public static function datetime($check, $dateFormat = 'ymd', $regex = null)
$check = static::_getDateString($check);
$dateFormat = 'ymd';
}
- $parts = preg_split("/[\sT]+/", $check);
+ $parts = preg_split('/[\sT]+/', $check);
if (!empty($parts) && count($parts) > 1) {
$date = rtrim(array_shift($parts), ',');
$time = implode(' ', $parts);
@@ -685,7 +596,7 @@ public static function datetime($check, $dateFormat = 'ymd', $regex = null)
* @return bool True if the value is valid, false otherwise
* @see Regex credits: https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
*/
- public static function iso8601($check)
+ public static function iso8601($check): bool
{
if ($check instanceof DateTimeInterface) {
return true;
@@ -694,6 +605,7 @@ public static function iso8601($check)
return false;
}
+ // phpcs:ignore Generic.Files.LineLength
$regex = '/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/';
return static::_check($check, $regex);
@@ -701,12 +613,15 @@ public static function iso8601($check)
/**
* Time validation, determines if the string passed is a valid time.
- * Validates time as 24hr (HH:MM[:SS]) or am/pm ([H]H[:MM][:SS][a|p]m)
+ * Validates time as 24hr (HH:MM[:SS][.FFFFFF]) or am/pm ([H]H:MM[a|p]m)
*
- * @param string|\DateTimeInterface $check a valid time string/object
+ * Seconds and fractional seconds (microseconds) are allowed but optional
+ * in 24hr format.
+ *
+ * @param mixed $check a valid time string/object
* @return bool Success
*/
- public static function time($check)
+ public static function time($check): bool
{
if ($check instanceof DateTimeInterface) {
return true;
@@ -715,14 +630,21 @@ public static function time($check)
$check = static::_getDateString($check);
}
- return static::_check($check, '%^((0?[1-9]|1[012])(:[0-5]\d){0,2} ?([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){1,2}$%');
+ if (!is_scalar($check)) {
+ return false;
+ }
+
+ $meridianClockRegex = '^((0?[1-9]|1[012])(:[0-5]\d){0,2} ?([AP]M|[ap]m))$';
+ $standardClockRegex = '^([01]\d|2[0-3])((:[0-5]\d){0,2}|(:[0-5]\d){2}\.\d{0,6})$';
+
+ return static::_check($check, '%' . $meridianClockRegex . '|' . $standardClockRegex . '%');
}
/**
* Date and/or time string validation.
* Uses `I18n::Time` to parse the date. This means parsing is locale dependent.
*
- * @param string|\DateTime $check a date string or object (will always pass)
+ * @param mixed $check a date string or object (will always pass)
* @param string $type Parser type, one out of 'date', 'time', and 'datetime'
* @param string|int|null $format any format accepted by IntlDateFormatter
* @return bool Success
@@ -731,7 +653,7 @@ public static function time($check)
* @see \Cake\I18n\Time::parseTime()
* @see \Cake\I18n\Time::parseDateTime()
*/
- public static function localizedTime($check, $type = 'datetime', $format = null)
+ public static function localizedTime($check, string $type = 'datetime', $format = null): bool
{
if ($check instanceof DateTimeInterface) {
return true;
@@ -749,7 +671,7 @@ public static function localizedTime($check, $type = 'datetime', $format = null)
}
$method = $methods[$type];
- return (Time::$method($check, $format) !== null);
+ return Time::$method($check, $format) !== null;
}
/**
@@ -761,7 +683,7 @@ public static function localizedTime($check, $type = 'datetime', $format = null)
* @param array $booleanValues List of valid boolean values, defaults to `[true, false, 0, 1, '0', '1']`.
* @return bool Success.
*/
- public static function boolean($check, array $booleanValues = [])
+ public static function boolean($check, array $booleanValues = []): bool
{
if (!$booleanValues) {
$booleanValues = [true, false, 0, 1, '0', '1'];
@@ -779,7 +701,7 @@ public static function boolean($check, array $booleanValues = [])
* @param array $truthyValues List of valid truthy values, defaults to `[true, 1, '1']`.
* @return bool Success.
*/
- public static function truthy($check, array $truthyValues = [])
+ public static function truthy($check, array $truthyValues = []): bool
{
if (!$truthyValues) {
$truthyValues = [true, 1, '1'];
@@ -797,7 +719,7 @@ public static function truthy($check, array $truthyValues = [])
* @param array $falseyValues List of valid falsey values, defaults to `[false, 0, '0']`.
* @return bool Success.
*/
- public static function falsey($check, array $falseyValues = [])
+ public static function falsey($check, array $falseyValues = []): bool
{
if (!$falseyValues) {
$falseyValues = [false, 0, '0'];
@@ -820,7 +742,7 @@ public static function falsey($check, array $falseyValues = [])
* @param string|null $regex If a custom regular expression is used, this is the only validation that will occur.
* @return bool Success
*/
- public static function decimal($check, $places = null, $regex = null)
+ public static function decimal($check, $places = null, ?string $regex = null): bool
{
if (!is_scalar($check)) {
return false;
@@ -856,13 +778,11 @@ public static function decimal($check, $places = null, $regex = null)
// There are two types of non-breaking spaces - we inject a space to account for human input
if ($groupingSep == "\xc2\xa0" || $groupingSep == "\xe2\x80\xaf") {
- $check = str_replace([' ', $groupingSep, $decimalPoint], ['', '', '.'], $check);
+ $check = str_replace([' ', $groupingSep, $decimalPoint], ['', '', '.'], (string)$check);
} else {
- $check = str_replace([$groupingSep, $decimalPoint], ['', '.'], $check);
+ $check = str_replace([$groupingSep, $decimalPoint], ['', '.'], (string)$check);
}
- $check = str_replace([$groupingSep, $decimalPoint], ['', '.'], $check);
-
return static::_check($check, $regex);
}
@@ -877,13 +797,14 @@ public static function decimal($check, $places = null, $regex = null)
* @param string|null $regex Regex to use (if none it will use built in regex)
* @return bool Success
*/
- public static function email($check, $deep = false, $regex = null)
+ public static function email($check, ?bool $deep = false, ?string $regex = null): bool
{
if (!is_string($check)) {
return false;
}
if ($regex === null) {
+ // phpcs:ignore Generic.Files.LineLength
$regex = '/^[\p{L}0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[\p{L}0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . self::$_pattern['hostname'] . '$/ui';
}
$return = static::_check($check, $regex);
@@ -912,9 +833,9 @@ public static function email($check, $deep = false, $regex = null)
* @param mixed $comparedTo Value to compare
* @return bool Success
*/
- public static function equalTo($check, $comparedTo)
+ public static function equalTo($check, $comparedTo): bool
{
- return ($check === $comparedTo);
+ return $check === $comparedTo;
}
/**
@@ -924,16 +845,20 @@ public static function equalTo($check, $comparedTo)
* @param string[] $extensions file extensions to allow. By default extensions are 'gif', 'jpeg', 'png', 'jpg'
* @return bool Success
*/
- public static function extension($check, $extensions = ['gif', 'jpeg', 'png', 'jpg'])
+ public static function extension($check, array $extensions = ['gif', 'jpeg', 'png', 'jpg']): bool
{
if ($check instanceof UploadedFileInterface) {
- return static::extension($check->getClientFilename(), $extensions);
+ $check = $check->getClientFilename();
+ } elseif (is_array($check) && isset($check['name'])) {
+ $check = $check['name'];
+ } elseif (is_array($check)) {
+ return static::extension(array_shift($check), $extensions);
}
- if (is_array($check)) {
- $check = isset($check['name']) ? $check['name'] : array_shift($check);
- return static::extension($check, $extensions);
+ if (empty($check)) {
+ return false;
}
+
$extension = strtolower(pathinfo($check, PATHINFO_EXTENSION));
foreach ($extensions as $value) {
if ($extension === strtolower($value)) {
@@ -951,7 +876,7 @@ public static function extension($check, $extensions = ['gif', 'jpeg', 'png', 'j
* @param string $type The IP Protocol version to validate against
* @return bool Success
*/
- public static function ip($check, $type = 'both')
+ public static function ip($check, string $type = 'both'): bool
{
if (!is_string($check)) {
return false;
@@ -976,7 +901,7 @@ public static function ip($check, $type = 'both')
* @param int $min The minimal string length
* @return bool Success
*/
- public static function minLength($check, $min)
+ public static function minLength($check, int $min): bool
{
if (!is_scalar($check)) {
return false;
@@ -992,7 +917,7 @@ public static function minLength($check, $min)
* @param int $max The maximal string length
* @return bool Success
*/
- public static function maxLength($check, $max)
+ public static function maxLength($check, int $max): bool
{
if (!is_scalar($check)) {
return false;
@@ -1008,7 +933,7 @@ public static function maxLength($check, $max)
* @param int $min The minimal string length (in bytes)
* @return bool Success
*/
- public static function minLengthBytes($check, $min)
+ public static function minLengthBytes($check, int $min): bool
{
if (!is_scalar($check)) {
return false;
@@ -1024,7 +949,7 @@ public static function minLengthBytes($check, $min)
* @param int $max The maximal string length
* @return bool Success
*/
- public static function maxLengthBytes($check, $max)
+ public static function maxLengthBytes($check, int $max): bool
{
if (!is_scalar($check)) {
return false;
@@ -1040,7 +965,7 @@ public static function maxLengthBytes($check, $max)
* @param string $symbolPosition Where symbol is located (left/right)
* @return bool Success
*/
- public static function money($check, $symbolPosition = 'left')
+ public static function money($check, string $symbolPosition = 'left'): bool
{
$money = '(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{1,2})?';
if ($symbolPosition === 'right') {
@@ -1066,13 +991,13 @@ public static function money($check, $symbolPosition = 'left')
* @param bool $caseInsensitive Set to true for case insensitive comparison.
* @return bool Success
*/
- public static function multiple($check, array $options = [], $caseInsensitive = false)
+ public static function multiple($check, array $options = [], bool $caseInsensitive = false): bool
{
$defaults = ['in' => null, 'max' => null, 'min' => null];
$options += $defaults;
$check = array_filter((array)$check, function ($value) {
- return ($value || is_numeric($value));
+ return $value || is_numeric($value);
});
if (empty($check)) {
return false;
@@ -1107,7 +1032,7 @@ public static function multiple($check, array $options = [], $caseInsensitive =
* @param mixed $check Value to check
* @return bool Success
*/
- public static function numeric($check)
+ public static function numeric($check): bool
{
return is_numeric($check);
}
@@ -1120,7 +1045,7 @@ public static function numeric($check)
* @return bool Success
* @see https://en.wikipedia.org/wiki/Natural_number
*/
- public static function naturalNumber($check, $allowZero = false)
+ public static function naturalNumber($check, bool $allowZero = false): bool
{
$regex = $allowZero ? '/^(?:0|[1-9][0-9]*)$/' : '/^[1-9][0-9]*$/';
@@ -1134,12 +1059,12 @@ public static function naturalNumber($check, $allowZero = false)
* If they are not set, will return true if $check is a
* legal finite on this platform.
*
- * @param string $check Value to check
- * @param int|float|null $lower Lower limit
- * @param int|float|null $upper Upper limit
+ * @param mixed $check Value to check
+ * @param float|null $lower Lower limit
+ * @param float|null $upper Upper limit
* @return bool Success
*/
- public static function range($check, $lower = null, $upper = null)
+ public static function range($check, ?float $lower = null, ?float $upper = null): bool
{
if (!is_numeric($check)) {
return false;
@@ -1148,7 +1073,7 @@ public static function range($check, $lower = null, $upper = null)
return false;
}
if (isset($lower, $upper)) {
- return ($check >= $lower && $check <= $upper);
+ return $check >= $lower && $check <= $upper;
}
return is_finite((float)$check);
@@ -1172,7 +1097,7 @@ public static function range($check, $lower = null, $upper = null)
* @return bool Success
* @link https://tools.ietf.org/html/rfc3986
*/
- public static function url($check, $strict = false)
+ public static function url($check, bool $strict = false): bool
{
if (!is_string($check)) {
return false;
@@ -1186,11 +1111,13 @@ public static function url($check, $strict = false)
$subDelimiters = preg_quote('/!"$&\'()*+,-.@_:;=~[]', '/');
$path = '([' . $subDelimiters . $alpha . ']|' . $hex . ')';
$fragmentAndQuery = '([\?' . $subDelimiters . $alpha . ']|' . $hex . ')';
- $regex = '/^(?:(?:https?|ftps?|sftp|file|news|gopher):\/\/)' . (!empty($strict) ? '' : '?') .
+ // phpcs:disable Generic.Files.LineLength
+ $regex = '/^(?:(?:https?|ftps?|sftp|file|news|gopher):\/\/)' . ($strict ? '' : '?') .
'(?:' . static::$_pattern['IPv4'] . '|\[' . static::$_pattern['IPv6'] . '\]|' . static::$_pattern['hostname'] . ')(?::[1-9][0-9]{0,4})?' .
'(?:\/' . $path . '*)?' .
'(?:\?' . $fragmentAndQuery . '*)?' .
'(?:#' . $fragmentAndQuery . '*)?$/iu';
+ // phpcs:enable Generic.Files.LineLength
return static::_check($check, $regex);
}
@@ -1203,7 +1130,7 @@ public static function url($check, $strict = false)
* @param bool $caseInsensitive Set to true for case insensitive comparison.
* @return bool Success.
*/
- public static function inList($check, array $list, $caseInsensitive = false)
+ public static function inList($check, array $list, bool $caseInsensitive = false): bool
{
if (!is_scalar($check)) {
return false;
@@ -1218,33 +1145,13 @@ public static function inList($check, array $list, $caseInsensitive = false)
return in_array((string)$check, $list, true);
}
- /**
- * Runs an user-defined validation.
- *
- * @param string|array $check value that will be validated in user-defined methods.
- * @param object $object class that holds validation method
- * @param string $method class method name for validation to run
- * @param array|null $args arguments to send to method
- * @return mixed user-defined class class method returns
- * @deprecated 3.0.2 You can just set a callable for `rule` key when adding validators.
- */
- public static function userDefined($check, $object, $method, $args = null)
- {
- deprecationWarning(
- 'Validation::userDefined() is deprecated. ' .
- 'You can just set a callable for `rule` key when adding validators.'
- );
-
- return $object->$method($check, $args);
- }
-
/**
* Checks that a value is a valid UUID - https://tools.ietf.org/html/rfc4122
*
* @param mixed $check Value to check
* @return bool Success
*/
- public static function uuid($check)
+ public static function uuid($check): bool
{
$regex = '/^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[0-5][a-fA-F0-9]{3}-[089aAbB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$/';
@@ -1258,7 +1165,7 @@ public static function uuid($check)
* @param string $regex Regular expression
* @return bool Success of match
*/
- protected static function _check($check, $regex)
+ protected static function _check($check, string $regex): bool
{
return is_scalar($check) && preg_match($regex, (string)$check);
}
@@ -1270,7 +1177,7 @@ protected static function _check($check, $regex)
* @return bool Success
* @see https://en.wikipedia.org/wiki/Luhn_algorithm
*/
- public static function luhn($check)
+ public static function luhn($check): bool
{
if (!is_scalar($check) || (int)$check === 0) {
return false;
@@ -1283,12 +1190,12 @@ public static function luhn($check)
$sum += (int)$check[$position];
}
- for ($position = ($length % 2); $position < $length; $position += 2) {
+ for ($position = $length % 2; $position < $length; $position += 2) {
$number = (int)$check[$position] * 2;
- $sum += ($number < 10) ? $number : $number - 9;
+ $sum += $number < 10 ? $number : $number - 9;
}
- return ($sum % 10 === 0);
+ return $sum % 10 === 0;
}
/**
@@ -1304,7 +1211,7 @@ public static function luhn($check)
* @throws \RuntimeException when mime type can not be determined.
* @throws \LogicException when ext/fileinfo is missing
*/
- public static function mimeType($check, $mimeTypes = [])
+ public static function mimeType($check, $mimeTypes = []): bool
{
$file = static::getFilename($check);
if ($file === false) {
@@ -1326,7 +1233,7 @@ public static function mimeType($check, $mimeTypes = [])
throw new RuntimeException('Can not determine the mimetype.');
}
- list($mime) = explode(';', $finfo);
+ [$mime] = explode(';', $finfo);
if (is_string($mimeTypes)) {
return self::_check($mime, $mimeTypes);
@@ -1349,9 +1256,14 @@ public static function mimeType($check, $mimeTypes = [])
protected static function getFilename($check)
{
if ($check instanceof UploadedFileInterface) {
+ // Uploaded files throw exceptions on upload errors.
try {
- // Uploaded files throw exceptions on upload errors.
- return $check->getStream()->getMetadata('uri');
+ $uri = $check->getStream()->getMetadata('uri');
+ if (is_string($uri)) {
+ return $uri;
+ }
+
+ return false;
} catch (RuntimeException $e) {
return false;
}
@@ -1375,11 +1287,11 @@ protected static function getFilename($check)
* reported by the client.
*
* @param string|array|\Psr\Http\Message\UploadedFileInterface $check Value to check.
- * @param string|null $operator See `Validation::comparison()`.
- * @param int|string|null $size Size in bytes or human readable string like '5MB'.
+ * @param string $operator See `Validation::comparison()`.
+ * @param int|string $size Size in bytes or human readable string like '5MB'.
* @return bool Success
*/
- public static function fileSize($check, $operator = null, $size = null)
+ public static function fileSize($check, string $operator, $size): bool
{
$file = static::getFilename($check);
if ($file === false) {
@@ -1402,7 +1314,7 @@ public static function fileSize($check, $operator = null, $size = null)
* @return bool
* @see https://secure.php.net/manual/en/features.file-upload.errors.php
*/
- public static function uploadError($check, $allowNoFile = false)
+ public static function uploadError($check, bool $allowNoFile = false): bool
{
if ($check instanceof UploadedFileInterface) {
$code = $check->getError();
@@ -1438,7 +1350,7 @@ public static function uploadError($check, $allowNoFile = false)
* @param array $options An array of options for the validation.
* @return bool
*/
- public static function uploadedFile($file, array $options = [])
+ public static function uploadedFile($file, array $options = []): bool
{
$options += [
'minSize' => null,
@@ -1470,10 +1382,16 @@ public static function uploadedFile($file, array $options = [])
if ($options['optional'] && $error === UPLOAD_ERR_NO_FILE) {
return true;
}
- if (isset($options['minSize']) && !static::fileSize($file, static::COMPARE_GREATER_OR_EQUAL, $options['minSize'])) {
+ if (
+ isset($options['minSize'])
+ && !static::fileSize($file, static::COMPARE_GREATER_OR_EQUAL, $options['minSize'])
+ ) {
return false;
}
- if (isset($options['maxSize']) && !static::fileSize($file, static::COMPARE_LESS_OR_EQUAL, $options['maxSize'])) {
+ if (
+ isset($options['maxSize'])
+ && !static::fileSize($file, static::COMPARE_LESS_OR_EQUAL, $options['maxSize'])
+ ) {
return false;
}
if (isset($options['types']) && !static::mimeType($file, $options['types'])) {
@@ -1491,17 +1409,22 @@ public static function uploadedFile($file, array $options = [])
* @return bool
* @throws \InvalidArgumentException
*/
- public static function imageSize($file, $options)
+ public static function imageSize($file, array $options): bool
{
if (!isset($options['height']) && !isset($options['width'])) {
- throw new InvalidArgumentException('Invalid image size validation parameters! Missing `width` and / or `height`.');
+ throw new InvalidArgumentException(
+ 'Invalid image size validation parameters! Missing `width` and / or `height`.'
+ );
}
- $filename = static::getFilename($file);
-
- list($width, $height) = getimagesize($filename);
+ $file = static::getFilename($file);
+ if ($file === false) {
+ return false;
+ }
- $validHeight = $validWidth = null;
+ [$width, $height] = getimagesize($file);
+ $validHeight = null;
+ $validWidth = null;
if (isset($options['height'])) {
$validHeight = self::comparison($height, $options['height'][0], $options['height'][1]);
@@ -1510,7 +1433,7 @@ public static function imageSize($file, $options)
$validWidth = self::comparison($width, $options['width'][0], $options['width'][1]);
}
if ($validHeight !== null && $validWidth !== null) {
- return ($validHeight && $validWidth);
+ return $validHeight && $validWidth;
}
if ($validHeight !== null) {
return $validHeight;
@@ -1530,7 +1453,7 @@ public static function imageSize($file, $options)
* @param int $width Min or max width.
* @return bool
*/
- public static function imageWidth($file, $operator, $width)
+ public static function imageWidth(array $file, string $operator, int $width): bool
{
return self::imageSize($file, [
'width' => [
@@ -1541,14 +1464,14 @@ public static function imageWidth($file, $operator, $width)
}
/**
- * Validates the image height.
+ * Validates the image width.
*
* @param array $file The uploaded file data from PHP.
* @param string $operator Comparison operator.
- * @param int $height Min or max height.
+ * @param int $height Min or max width.
* @return bool
*/
- public static function imageHeight($file, $operator, $height)
+ public static function imageHeight(array $file, string $operator, int $height): bool
{
return self::imageSize($file, [
'height' => [
@@ -1575,7 +1498,7 @@ public static function imageHeight($file, $operator, $height)
* @param array $options Options for the validation logic.
* @return bool
*/
- public static function geoCoordinate($value, array $options = [])
+ public static function geoCoordinate($value, array $options = []): bool
{
if (!is_scalar($value)) {
return false;
@@ -1611,7 +1534,7 @@ public static function geoCoordinate($value, array $options = [])
* @link https://en.wikipedia.org/wiki/Latitude
* @see \Cake\Validation\Validation::geoCoordinate()
*/
- public static function latitude($value, array $options = [])
+ public static function latitude($value, array $options = []): bool
{
$options['format'] = 'lat';
@@ -1627,7 +1550,7 @@ public static function latitude($value, array $options = [])
* @link https://en.wikipedia.org/wiki/Longitude
* @see \Cake\Validation\Validation::geoCoordinate()
*/
- public static function longitude($value, array $options = [])
+ public static function longitude($value, array $options = []): bool
{
$options['format'] = 'long';
@@ -1642,7 +1565,7 @@ public static function longitude($value, array $options = [])
* @param mixed $value The value to check
* @return bool
*/
- public static function ascii($value)
+ public static function ascii($value): bool
{
if (!is_string($value)) {
return false;
@@ -1666,7 +1589,7 @@ public static function ascii($value)
* @param array $options An array of options. See above for the supported options.
* @return bool
*/
- public static function utf8($value, array $options = [])
+ public static function utf8($value, array $options = []): bool
{
if (!is_string($value)) {
return false;
@@ -1688,7 +1611,7 @@ public static function utf8($value, array $options = [])
* @param mixed $value The value to check
* @return bool
*/
- public static function isInteger($value)
+ public static function isInteger($value): bool
{
if (is_int($value)) {
return true;
@@ -1707,7 +1630,7 @@ public static function isInteger($value)
* @param mixed $value The value to check
* @return bool
*/
- public static function isArray($value)
+ public static function isArray($value): bool
{
return is_array($value);
}
@@ -1721,7 +1644,7 @@ public static function isArray($value)
* @param mixed $value The value to check
* @return bool
*/
- public static function isScalar($value)
+ public static function isScalar($value): bool
{
return is_scalar($value);
}
@@ -1732,7 +1655,7 @@ public static function isScalar($value)
* @param mixed $check The value to check
* @return bool Success
*/
- public static function hexColor($check)
+ public static function hexColor($check): bool
{
return static::_check($check, '/^#[0-9a-f]{6}$/iD');
}
@@ -1745,7 +1668,7 @@ public static function hexColor($check)
* @param mixed $check The value to check
* @return bool Success
*/
- public static function iban($check)
+ public static function iban($check): bool
{
if (
!is_string($check) ||
@@ -1782,12 +1705,16 @@ public static function iban($check)
* @param array $value The array representing a date or datetime.
* @return string
*/
- protected static function _getDateString($value)
+ protected static function _getDateString(array $value): string
{
$formatted = '';
if (
isset($value['year'], $value['month'], $value['day']) &&
- (is_numeric($value['year']) && is_numeric($value['month']) && is_numeric($value['day']))
+ (
+ is_numeric($value['year']) &&
+ is_numeric($value['month']) &&
+ is_numeric($value['day'])
+ )
) {
$formatted .= sprintf('%d-%02d-%02d ', $value['year'], $value['month'], $value['day']);
}
@@ -1799,9 +1726,20 @@ protected static function _getDateString($value)
if (isset($value['meridian'])) {
$value['hour'] = strtolower($value['meridian']) === 'am' ? $value['hour'] : $value['hour'] + 12;
}
- $value += ['minute' => 0, 'second' => 0];
- if (is_numeric($value['hour']) && is_numeric($value['minute']) && is_numeric($value['second'])) {
- $formatted .= sprintf('%02d:%02d:%02d', $value['hour'], $value['minute'], $value['second']);
+ $value += ['minute' => 0, 'second' => 0, 'microsecond' => 0];
+ if (
+ is_numeric($value['hour']) &&
+ is_numeric($value['minute']) &&
+ is_numeric($value['second']) &&
+ is_numeric($value['microsecond'])
+ ) {
+ $formatted .= sprintf(
+ '%02d:%02d:%02d.%06d',
+ $value['hour'],
+ $value['minute'],
+ $value['second'],
+ $value['microsecond']
+ );
}
}
@@ -1813,8 +1751,9 @@ protected static function _getDateString($value)
*
* @return void
*/
- protected static function _populateIp()
+ protected static function _populateIp(): void
{
+ // phpcs:disable Generic.Files.LineLength
if (!isset(static::$_pattern['IPv6'])) {
$pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}';
$pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})';
@@ -1837,6 +1776,7 @@ protected static function _populateIp()
$pattern = '(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])';
static::$_pattern['IPv4'] = $pattern;
}
+ // phpcs:enable Generic.Files.LineLength
}
/**
@@ -1844,7 +1784,7 @@ protected static function _populateIp()
*
* @return void
*/
- protected static function _reset()
+ protected static function _reset(): void
{
static::$errors = [];
}
diff --git a/app/vendor/cakephp/cakephp/src/Validation/ValidationRule.php b/app/vendor/cakephp/cakephp/src/Validation/ValidationRule.php
index 91a86d2f7..c98c6b2b8 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/ValidationRule.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/ValidationRule.php
@@ -1,4 +1,6 @@
_last;
}
@@ -126,10 +128,14 @@ public function process($value, array $providers, array $context = [])
}
if (!$isCallable) {
- $message = 'Unable to call method "%s" in "%s" provider for field "%s"';
- throw new InvalidArgumentException(
- sprintf($message, $this->_rule, $this->_provider, $context['field'])
+ /** @psalm-suppress PossiblyInvalidArgument */
+ $message = sprintf(
+ 'Unable to call method "%s" in "%s" provider for field "%s"',
+ $this->_rule,
+ $this->_provider,
+ $context['field']
);
+ throw new InvalidArgumentException($message);
}
if ($this->_pass) {
@@ -158,7 +164,7 @@ public function process($value, array $providers, array $context = [])
* be passed as the last argument for the validation method
* @return bool True if the ValidationRule should be skipped
*/
- protected function _skip($context)
+ protected function _skip(array $context): bool
{
if (!is_string($this->_on) && is_callable($this->_on)) {
$function = $this->_on;
@@ -168,9 +174,8 @@ protected function _skip($context)
$newRecord = $context['newRecord'];
if (!empty($this->_on)) {
- if (($this->_on === 'create' && !$newRecord) || ($this->_on === 'update' && $newRecord)) {
- return true;
- }
+ return ($this->_on === Validator::WHEN_CREATE && !$newRecord)
+ || ($this->_on === Validator::WHEN_UPDATE && $newRecord);
}
return false;
@@ -182,7 +187,7 @@ protected function _skip($context)
* @param array $validator [optional]
* @return void
*/
- protected function _addValidatorProps($validator = [])
+ protected function _addValidatorProps(array $validator = []): void
{
foreach ($validator as $key => $value) {
if (!isset($value) || empty($value)) {
@@ -204,7 +209,7 @@ protected function _addValidatorProps($validator = [])
* @param string $property The name of the property to retrieve.
* @return mixed
*/
- public function get($property)
+ public function get(string $property)
{
$property = '_' . $property;
if (isset($this->{$property})) {
diff --git a/app/vendor/cakephp/cakephp/src/Validation/ValidationSet.php b/app/vendor/cakephp/cakephp/src/Validation/ValidationSet.php
index bb6028951..4ca0a3355 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/ValidationSet.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/ValidationSet.php
@@ -1,4 +1,6 @@
_validatePresent;
- }
-
- deprecationWarning(
- 'ValidationSet::isPresenceRequired() is deprecated as a setter. ' .
- 'Use ValidationSet::requirePresence() instead.'
- );
-
- return $this->requirePresence($validatePresent);
+ return $this->_validatePresent;
}
/**
@@ -83,26 +73,13 @@ public function requirePresence($validatePresent)
}
/**
- * Sets whether a field value is allowed to be empty.
- *
- * If no argument is passed the currently set `allowEmpty` value will be returned.
+ * Returns whether or not a field can be left empty.
*
- * @param bool|string|callable|null $allowEmpty Deprecated since 3.6.0 ValidationSet::isEmptyAllowed() is deprecated as a setter.
- * Use ValidationSet::allowEmpty() instead.
* @return bool|string|callable
*/
- public function isEmptyAllowed($allowEmpty = null)
+ public function isEmptyAllowed()
{
- if ($allowEmpty === null) {
- return $this->_allowEmpty;
- }
-
- deprecationWarning(
- 'ValidationSet::isEmptyAllowed() is deprecated as a setter. ' .
- 'Use ValidationSet::allowEmpty() instead.'
- );
-
- return $this->allowEmpty($allowEmpty);
+ return $this->_allowEmpty;
}
/**
@@ -125,7 +102,7 @@ public function allowEmpty($allowEmpty)
* @param string $name The name under which the rule is set.
* @return \Cake\Validation\ValidationRule|null
*/
- public function rule($name)
+ public function rule(string $name): ?ValidationRule
{
if (!empty($this->_rules[$name])) {
return $this->_rules[$name];
@@ -139,7 +116,7 @@ public function rule($name)
*
* @return \Cake\Validation\ValidationRule[]
*/
- public function rules()
+ public function rules(): array
{
return $this->_rules;
}
@@ -159,7 +136,7 @@ public function rules()
* @param \Cake\Validation\ValidationRule|array $rule The validation rule to be set
* @return $this
*/
- public function add($name, $rule)
+ public function add(string $name, $rule)
{
if (!($rule instanceof ValidationRule)) {
$rule = new ValidationRule($rule);
@@ -183,7 +160,7 @@ public function add($name, $rule)
* @param string $name The name under which the rule should be unset
* @return $this
*/
- public function remove($name)
+ public function remove(string $name)
{
unset($this->_rules[$name]);
@@ -196,7 +173,7 @@ public function remove($name)
* @param string $index name of the rule
* @return bool
*/
- public function offsetExists($index)
+ public function offsetExists($index): bool
{
return isset($this->_rules[$index]);
}
@@ -207,7 +184,7 @@ public function offsetExists($index)
* @param string $index name of the rule
* @return \Cake\Validation\ValidationRule
*/
- public function offsetGet($index)
+ public function offsetGet($index): ValidationRule
{
return $this->_rules[$index];
}
@@ -219,7 +196,7 @@ public function offsetGet($index)
* @param \Cake\Validation\ValidationRule|array $rule Rule to add to $index
* @return void
*/
- public function offsetSet($index, $rule)
+ public function offsetSet($index, $rule): void
{
$this->add($index, $rule);
}
@@ -230,7 +207,7 @@ public function offsetSet($index, $rule)
* @param string $index name of the rule
* @return void
*/
- public function offsetUnset($index)
+ public function offsetUnset($index): void
{
unset($this->_rules[$index]);
}
@@ -238,9 +215,10 @@ public function offsetUnset($index)
/**
* Returns an iterator for each of the rules to be applied
*
- * @return \ArrayIterator
+ * @return \Cake\Validation\ValidationRule[]
+ * @psalm-return \Traversable
*/
- public function getIterator()
+ public function getIterator(): Traversable
{
return new ArrayIterator($this->_rules);
}
@@ -250,7 +228,7 @@ public function getIterator()
*
* @return int
*/
- public function count()
+ public function count(): int
{
return count($this->_rules);
}
diff --git a/app/vendor/cakephp/cakephp/src/Validation/Validator.php b/app/vendor/cakephp/cakephp/src/Validation/Validator.php
index cb24fc037..097e0129e 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/Validator.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/Validator.php
@@ -1,4 +1,6 @@
*/
protected $_fields = [];
@@ -163,11 +194,13 @@ public function __construct()
*
* @param array $data The data to be checked for errors
* @param bool $newRecord whether the data to be validated is new or to be updated.
- * @return array Array of failed fields
- * @deprecated 3.9.0 Renamed to validate()
+ * @return array[] Array of failed fields
+ * @deprecated 3.9.0 Renamed to {@link validate()}.
*/
- public function errors(array $data, $newRecord = true)
+ public function errors(array $data, bool $newRecord = true): array
{
+ deprecationWarning('`Validator::errors()` is deprecated. Use `Validator::validate()` instead.');
+
return $this->validate($data, $newRecord);
}
@@ -176,9 +209,9 @@ public function errors(array $data, $newRecord = true)
*
* @param array $data The data to be checked for errors
* @param bool $newRecord whether the data to be validated is new or to be updated.
- * @return array Array of failed fields
+ * @return array[] Array of failed fields
*/
- public function validate(array $data, $newRecord = true)
+ public function validate(array $data, bool $newRecord = true): array
{
$errors = [];
@@ -198,7 +231,7 @@ public function validate(array $data, $newRecord = true)
$canBeEmpty = $this->_canBeEmpty($field, $context);
- $flags = static::EMPTY_ALL;
+ $flags = static::EMPTY_NULL;
if (isset($this->_allowEmptyFlags[$name])) {
$flags = $this->_allowEmptyFlags[$name];
}
@@ -232,7 +265,7 @@ public function validate(array $data, $newRecord = true)
* @param \Cake\Validation\ValidationSet|null $set The set of rules for field
* @return \Cake\Validation\ValidationSet
*/
- public function field($name, ValidationSet $set = null)
+ public function field(string $name, ?ValidationSet $set = null): ValidationSet
{
if (empty($this->_fields[$name])) {
$set = $set ?: new ValidationSet();
@@ -248,7 +281,7 @@ public function field($name, ValidationSet $set = null)
* @param string $name The field name to check.
* @return bool
*/
- public function hasField($name)
+ public function hasField(string $name): bool
{
return isset($this->_fields[$name]);
}
@@ -263,7 +296,7 @@ public function hasField($name)
* @param object|string $object Provider object or class name.
* @return $this
*/
- public function setProvider($name, $object)
+ public function setProvider(string $name, $object)
{
$this->_providers[$name] = $object;
@@ -275,9 +308,8 @@ public function setProvider($name, $object)
*
* @param string $name The name under which the provider should be set.
* @return object|string|null
- * @throws \ReflectionException
*/
- public function getProvider($name)
+ public function getProvider(string $name)
{
if (isset($this->_providers[$name])) {
return $this->_providers[$name];
@@ -297,7 +329,7 @@ public function getProvider($name)
* @param string $name The name under which the provider should be retrieved.
* @return object|string|null
*/
- public static function getDefaultProvider($name)
+ public static function getDefaultProvider(string $name)
{
if (!isset(self::$_defaultProviders[$name])) {
return null;
@@ -313,7 +345,7 @@ public static function getDefaultProvider($name)
* @param object|string $object Provider object or class name.
* @return void
*/
- public static function addDefaultProvider($name, $object)
+ public static function addDefaultProvider(string $name, $object): void
{
self::$_defaultProviders[$name] = $object;
}
@@ -323,44 +355,17 @@ public static function addDefaultProvider($name, $object)
*
* @return string[]
*/
- public static function getDefaultProviders()
+ public static function getDefaultProviders(): array
{
return array_keys(self::$_defaultProviders);
}
- /**
- * Associates an object to a name so it can be used as a provider. Providers are
- * objects or class names that can contain methods used during validation of for
- * deciding whether a validation rule can be applied. All validation methods,
- * when called will receive the full list of providers stored in this validator.
- *
- * If called with no arguments, it will return the provider stored under that name if
- * it exists, otherwise it returns this instance of chaining.
- *
- * @deprecated 3.4.0 Use setProvider()/getProvider() instead.
- * @param string $name The name under which the provider should be set.
- * @param string|object|null $object Provider object or class name.
- * @return $this|object|string|null
- */
- public function provider($name, $object = null)
- {
- deprecationWarning(
- 'Validator::provider() is deprecated. ' .
- 'Use Validator::setProvider()/getProvider() instead.'
- );
- if ($object !== null) {
- return $this->setProvider($name, $object);
- }
-
- return $this->getProvider($name);
- }
-
/**
* Get the list of providers in this validator.
*
* @return string[]
*/
- public function providers()
+ public function providers(): array
{
return array_keys($this->_providers);
}
@@ -371,7 +376,7 @@ public function providers()
* @param string $field name of the field to check
* @return bool
*/
- public function offsetExists($field)
+ public function offsetExists($field): bool
{
return isset($this->_fields[$field]);
}
@@ -382,7 +387,7 @@ public function offsetExists($field)
* @param string $field name of the field to check
* @return \Cake\Validation\ValidationSet
*/
- public function offsetGet($field)
+ public function offsetGet($field): ValidationSet
{
return $this->field($field);
}
@@ -394,13 +399,14 @@ public function offsetGet($field)
* @param array|\Cake\Validation\ValidationSet $rules set of rules to apply to field
* @return void
*/
- public function offsetSet($field, $rules)
+ public function offsetSet($field, $rules): void
{
if (!$rules instanceof ValidationSet) {
$set = new ValidationSet();
- foreach ((array)$rules as $name => $rule) {
+ foreach ($rules as $name => $rule) {
$set->add($name, $rule);
}
+ $rules = $set;
}
$this->_fields[$field] = $rules;
}
@@ -411,7 +417,7 @@ public function offsetSet($field, $rules)
* @param string $field name of the field to unset
* @return void
*/
- public function offsetUnset($field)
+ public function offsetUnset($field): void
{
unset($this->_fields[$field]);
}
@@ -419,9 +425,10 @@ public function offsetUnset($field)
/**
* Returns an iterator for each of the fields to be validated
*
- * @return \ArrayIterator
+ * @return \Cake\Validation\ValidationSet[]
+ * @psalm-return \Traversable
*/
- public function getIterator()
+ public function getIterator(): Traversable
{
return new ArrayIterator($this->_fields);
}
@@ -431,7 +438,7 @@ public function getIterator()
*
* @return int
*/
- public function count()
+ public function count(): int
{
return count($this->_fields);
}
@@ -457,9 +464,10 @@ public function count()
* @param string $field The name of the field from which the rule will be added
* @param array|string $name The alias for a single rule or multiple rules array
* @param array|\Cake\Validation\ValidationRule $rule the rule to add
+ * @throws \InvalidArgumentException If numeric index cannot be resolved to a string one
* @return $this
*/
- public function add($field, $name, $rule = [])
+ public function add(string $field, $name, $rule = [])
{
$validationSet = $this->field($field);
@@ -473,6 +481,23 @@ public function add($field, $name, $rule = [])
if (is_array($rule)) {
$rule += ['rule' => $name];
}
+ if (!is_string($name)) {
+ /** @psalm-suppress PossiblyUndefinedMethod */
+ $name = $rule['rule'];
+ if (is_array($name)) {
+ $name = array_shift($name);
+ }
+
+ if ($validationSet->offsetExists($name)) {
+ $message = 'You cannot add a rule without a unique name, already existing rule found: ' . $name;
+ throw new InvalidArgumentException($message);
+ }
+
+ deprecationWarning(
+ 'Adding validation rules without a name key is deprecated. Update rules array to have string keys.'
+ );
+ }
+
$validationSet->add($name, $rule);
}
@@ -499,7 +524,7 @@ public function add($field, $name, $rule = [])
* true when the validation rule should be applied.
* @return $this
*/
- public function addNested($field, Validator $validator, $message = null, $when = null)
+ public function addNested(string $field, Validator $validator, ?string $message = null, $when = null)
{
$extra = array_filter(['message' => $message, 'on' => $when]);
@@ -509,6 +534,7 @@ public function addNested($field, Validator $validator, $message = null, $when =
return false;
}
foreach ($this->providers() as $provider) {
+ /** @psalm-suppress PossiblyNullArgument */
$validator->setProvider($provider, $this->getProvider($provider));
}
$errors = $validator->validate($value, $context['newRecord']);
@@ -541,7 +567,7 @@ public function addNested($field, Validator $validator, $message = null, $when =
* true when the validation rule should be applied.
* @return $this
*/
- public function addNestedMany($field, Validator $validator, $message = null, $when = null)
+ public function addNestedMany(string $field, Validator $validator, ?string $message = null, $when = null)
{
$extra = array_filter(['message' => $message, 'on' => $when]);
@@ -551,6 +577,7 @@ public function addNestedMany($field, Validator $validator, $message = null, $wh
return false;
}
foreach ($this->providers() as $provider) {
+ /** @psalm-suppress PossiblyNullArgument */
$validator->setProvider($provider, $this->getProvider($provider));
}
$errors = [];
@@ -587,7 +614,7 @@ public function addNestedMany($field, Validator $validator, $message = null, $wh
* @param string|null $rule the name of the rule to be removed
* @return $this
*/
- public function remove($field, $rule = null)
+ public function remove(string $field, ?string $rule = null)
{
if ($rule === null) {
unset($this->_fields[$field]);
@@ -616,7 +643,7 @@ public function remove($field, $rule = null)
* @param string|null $message The message to show if the field presence validation fails.
* @return $this
*/
- public function requirePresence($field, $mode = true, $message = null)
+ public function requirePresence($field, $mode = true, ?string $message = null)
{
$defaults = [
'mode' => $mode,
@@ -661,13 +688,13 @@ public function requirePresence($field, $mode = true, $message = null)
* $validator->allowEmpty('email');
*
* // Email can be empty on create
- * $validator->allowEmpty('email', 'create');
+ * $validator->allowEmpty('email', Validator::WHEN_CREATE);
*
* // Email can be empty on update
- * $validator->allowEmpty('email', 'update');
+ * $validator->allowEmpty('email', Validator::WHEN_UPDATE);
*
* // Email and subject can be empty on update
- * $validator->allowEmpty(['email', 'subject'], 'update');
+ * $validator->allowEmpty(['email', 'subject'], Validator::WHEN_UPDATE;
*
* // Email can be always empty, subject and content can be empty on update.
* $validator->allowEmpty(
@@ -680,7 +707,7 @@ public function requirePresence($field, $mode = true, $message = null)
* ],
* 'subject'
* ],
- * 'update'
+ * Validator::WHEN_UPDATE
* );
* ```
*
@@ -699,8 +726,8 @@ public function requirePresence($field, $mode = true, $message = null)
* Because this and `notEmpty()` modify the same internal state, the last
* method called will take precedence.
*
- * @deprecated 3.7.0 Use allowEmptyString(), allowEmptyArray(), allowEmptyFile(),
- * allowEmptyDate(), allowEmptyTime() or allowEmptyDateTime() instead.
+ * @deprecated 3.7.0 Use {@link allowEmptyString()}, {@link allowEmptyArray()}, {@link allowEmptyFile()},
+ * {@link allowEmptyDate()}, {@link allowEmptyTime()}, {@link allowEmptyDateTime()} or {@link allowEmptyFor()} instead.
* @param string|array $field the name of the field or a list of fields
* @param bool|string|callable $when Indicates when the field is allowed to be empty
* Valid values are true (always), 'create', 'update'. If a callable is passed then
@@ -710,6 +737,12 @@ public function requirePresence($field, $mode = true, $message = null)
*/
public function allowEmpty($field, $when = true, $message = null)
{
+ deprecationWarning(
+ 'allowEmpty() is deprecated. '
+ . 'Use allowEmptyString(), allowEmptyArray(), allowEmptyFile(), allowEmptyDate(), allowEmptyTime(), '
+ . 'allowEmptyDateTime() or allowEmptyFor() instead.'
+ );
+
$defaults = [
'when' => $when,
'message' => $message,
@@ -721,7 +754,12 @@ public function allowEmpty($field, $when = true, $message = null)
foreach ($field as $fieldName => $setting) {
$settings = $this->_convertValidatorToArray($fieldName, $defaults, $setting);
$fieldName = array_keys($settings)[0];
- $this->allowEmptyFor($fieldName, null, $settings[$fieldName]['when'], $settings[$fieldName]['message']);
+ $this->allowEmptyFor(
+ $fieldName,
+ static::EMPTY_ALL,
+ $settings[$fieldName]['when'],
+ $settings[$fieldName]['message']
+ );
}
return $this;
@@ -752,10 +790,10 @@ public function allowEmpty($field, $when = true, $message = null)
* $validator->allowEmptyFor('email', Validator::EMPTY_STRING);
*
* // Email can be empty on create
- * $validator->allowEmptyFor('email', Validator::EMPTY_STRING, 'create');
+ * $validator->allowEmptyFor('email', Validator::EMPTY_STRING, Validator::WHEN_CREATE);
*
* // Email can be empty on update
- * $validator->allowEmptyFor('email', Validator::EMPTY_STRING, 'update');
+ * $validator->allowEmptyFor('email', Validator::EMPTY_STRING, Validator::WHEN_UPDATE);
* ```
*
* It is possible to conditionally allow emptiness on a field by passing a callback
@@ -787,7 +825,8 @@ public function allowEmpty($field, $when = true, $message = null)
* ```
*
* @param string $field The name of the field.
- * @param int|null $flags A bitmask of EMPTY_* flags which specify what is empty
+ * @param int|null $flags A bitmask of EMPTY_* flags which specify what is empty.
+ * If no flags/bitmask is provided only `null` will be allowed as empty value.
* @param bool|string|callable $when Indicates when the field is allowed to be empty
* Valid values are true, false, 'create', 'update'. If a callable is passed then
* the field will allowed to be empty only when the callback returns true.
@@ -795,7 +834,7 @@ public function allowEmpty($field, $when = true, $message = null)
* @since 3.7.0
* @return $this
*/
- public function allowEmptyFor($field, $flags, $when = true, $message = null)
+ public function allowEmptyFor(string $field, ?int $flags = null, $when = true, ?string $message = null)
{
$this->field($field)->allowEmpty($when);
if ($message) {
@@ -808,50 +847,6 @@ public function allowEmptyFor($field, $flags, $when = true, $message = null)
return $this;
}
- /**
- * Compatibility shim for the allowEmpty* methods that enable
- * us to support both the `$when, $message` signature (deprecated)
- * and the `$message, $when` format which is preferred.
- *
- * A deprecation warning will be emitted when a deprecated form
- * is used.
- *
- * @param mixed $first The message or when to be sorted.
- * @param mixed $second The message or when to be sorted.
- * @param string $method The called method
- * @return array A list of [$message, $when]
- */
- protected function sortMessageAndWhen($first, $second, $method)
- {
- // Called with `$message, $when`. No order change necessary
- if (
- (
- in_array($second, [true, false, 'create', 'update'], true) ||
- is_callable($second)
- ) && (
- is_string($first) || $first === null
- ) && (
- $first !== 'create' && $first !== 'update'
- )
- ) {
- return [$first, $second];
- }
- deprecationWarning(
- "You are using a deprecated argument order for ${method}. " .
- "You should reverse the order of your `when` and `message` arguments " .
- "so that they are `message, when`."
- );
-
- // Called without the second argument.
- if (is_bool($second)) {
- $second = null;
- }
-
- // Called with `$when, $message`. Reverse the
- // order to match the expected return value.
- return [$second, $first];
- }
-
/**
* Allows a field to be an empty string.
*
@@ -863,13 +858,10 @@ protected function sortMessageAndWhen($first, $second, $method)
* Valid values are true, false, 'create', 'update'. If a callable is passed then
* the field will allowed to be empty only when the callback returns true.
* @return $this
- * @since 3.7.0
* @see \Cake\Validation\Validator::allowEmptyFor() For detail usage
*/
- public function allowEmptyString($field, $message = null, $when = true)
+ public function allowEmptyString(string $field, ?string $message = null, $when = true)
{
- list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
-
return $this->allowEmptyFor($field, self::EMPTY_STRING, $when, $message);
}
@@ -888,7 +880,7 @@ public function allowEmptyString($field, $message = null, $when = true)
* @see \Cake\Validation\Validator::allowEmptyString()
* @since 3.8.0
*/
- public function notEmptyString($field, $message = null, $when = false)
+ public function notEmptyString(string $field, ?string $message = null, $when = false)
{
$when = $this->invertWhenClause($when);
@@ -910,10 +902,8 @@ public function notEmptyString($field, $message = null, $when = false)
* @since 3.7.0
* @see \Cake\Validation\Validator::allowEmptyFor() for examples.
*/
- public function allowEmptyArray($field, $message = null, $when = true)
+ public function allowEmptyArray(string $field, ?string $message = null, $when = true)
{
- list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
-
return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_ARRAY, $when, $message);
}
@@ -930,9 +920,8 @@ public function allowEmptyArray($field, $message = null, $when = true)
* the callback returns true.
* @return $this
* @see \Cake\Validation\Validator::allowEmptyArray()
- * @since 3.8.0
*/
- public function notEmptyArray($field, $message = null, $when = false)
+ public function notEmptyArray(string $field, ?string $message = null, $when = false)
{
$when = $this->invertWhenClause($when);
@@ -955,10 +944,8 @@ public function notEmptyArray($field, $message = null, $when = false)
* @since 3.7.0
* @see \Cake\Validation\Validator::allowEmptyFor() For detail usage
*/
- public function allowEmptyFile($field, $message = null, $when = true)
+ public function allowEmptyFile(string $field, ?string $message = null, $when = true)
{
- list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
-
return $this->allowEmptyFor($field, self::EMPTY_FILE, $when, $message);
}
@@ -977,7 +964,7 @@ public function allowEmptyFile($field, $message = null, $when = true)
* @since 3.8.0
* @see \Cake\Validation\Validator::allowEmptyFile()
*/
- public function notEmptyFile($field, $message = null, $when = false)
+ public function notEmptyFile(string $field, ?string $message = null, $when = false)
{
$when = $this->invertWhenClause($when);
@@ -996,13 +983,10 @@ public function notEmptyFile($field, $message = null, $when = false)
* Valid values are true, false, 'create', 'update'. If a callable is passed then
* the field will allowed to be empty only when the callback returns true.
* @return $this
- * @since 3.7.0
* @see \Cake\Validation\Validator::allowEmptyFor() for examples
*/
- public function allowEmptyDate($field, $message = null, $when = true)
+ public function allowEmptyDate(string $field, ?string $message = null, $when = true)
{
- list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
-
return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_DATE, $when, $message);
}
@@ -1016,10 +1000,9 @@ public function allowEmptyDate($field, $message = null, $when = true)
* callable is passed then the field will be required to be not empty when
* the callback returns true.
* @return $this
- * @since 3.8.0
* @see \Cake\Validation\Validator::allowEmptyDate() for examples
*/
- public function notEmptyDate($field, $message = null, $when = false)
+ public function notEmptyDate(string $field, ?string $message = null, $when = false)
{
$when = $this->invertWhenClause($when);
@@ -1044,10 +1027,8 @@ public function notEmptyDate($field, $message = null, $when = false)
* @since 3.7.0
* @see \Cake\Validation\Validator::allowEmptyFor() for examples.
*/
- public function allowEmptyTime($field, $message = null, $when = true)
+ public function allowEmptyTime(string $field, ?string $message = null, $when = true)
{
- list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
-
return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_TIME, $when, $message);
}
@@ -1066,7 +1047,7 @@ public function allowEmptyTime($field, $message = null, $when = true)
* @since 3.8.0
* @see \Cake\Validation\Validator::allowEmptyTime()
*/
- public function notEmptyTime($field, $message = null, $when = false)
+ public function notEmptyTime(string $field, ?string $message = null, $when = false)
{
$when = $this->invertWhenClause($when);
@@ -1091,10 +1072,8 @@ public function notEmptyTime($field, $message = null, $when = false)
* @since 3.7.0
* @see \Cake\Validation\Validator::allowEmptyFor() for examples.
*/
- public function allowEmptyDateTime($field, $message = null, $when = true)
+ public function allowEmptyDateTime(string $field, ?string $message = null, $when = true)
{
- list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
-
return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_DATE | self::EMPTY_TIME, $when, $message);
}
@@ -1113,7 +1092,7 @@ public function allowEmptyDateTime($field, $message = null, $when = true)
* @since 3.8.0
* @see \Cake\Validation\Validator::allowEmptyDateTime()
*/
- public function notEmptyDateTime($field, $message = null, $when = false)
+ public function notEmptyDateTime(string $field, ?string $message = null, $when = false)
{
$when = $this->invertWhenClause($when);
@@ -1126,9 +1105,10 @@ public function notEmptyDateTime($field, $message = null, $when = false)
* @param int|string $fieldName name of field
* @param array $defaults default settings
* @param string|array $settings settings from data
- * @return array
+ * @return array[]
+ * @throws \InvalidArgumentException
*/
- protected function _convertValidatorToArray($fieldName, $defaults = [], $settings = [])
+ protected function _convertValidatorToArray($fieldName, array $defaults = [], $settings = []): array
{
if (is_string($settings)) {
$fieldName = $settings;
@@ -1170,10 +1150,10 @@ protected function _convertValidatorToArray($fieldName, $defaults = [], $setting
* $validator->notEmpty('email', $message, 'create');
*
* // Email can be empty on create, but required on update.
- * $validator->notEmpty('email', $message, 'update');
+ * $validator->notEmpty('email', $message, Validator::WHEN_UPDATE);
*
* // Email and title can be empty on create, but are required on update.
- * $validator->notEmpty(['email', 'title'], $message, 'update');
+ * $validator->notEmpty(['email', 'title'], $message, Validator::WHEN_UPDATE);
*
* // Email can be empty on create, title must always be not empty
* $validator->notEmpty(
@@ -1185,7 +1165,7 @@ protected function _convertValidatorToArray($fieldName, $defaults = [], $setting
* ]
* ],
* $message,
- * 'update'
+ * Validator::WHEN_UPDATE
* );
* ```
*
@@ -1202,8 +1182,8 @@ protected function _convertValidatorToArray($fieldName, $defaults = [], $setting
* Because this and `allowEmpty()` modify the same internal state, the last
* method called will take precedence.
*
- * @deprecated 3.7.0 Use notEmptyString(), notEmptyArray(), notEmptyFile(),
- * notEmptyDate(), notEmptyTime() or notEmptyDateTime() instead.
+ * @deprecated 3.7.0 Use {@link notEmptyString()}, {@link notEmptyArray()}, {@link notEmptyFile()},
+ * {@link notEmptyDate()}, {@link notEmptyTime()} or {@link notEmptyDateTime()} instead.
* @param string|array $field the name of the field or list of fields
* @param string|null $message The message to show if the field is not
* @param bool|string|callable $when Indicates when the field is not allowed
@@ -1212,8 +1192,14 @@ protected function _convertValidatorToArray($fieldName, $defaults = [], $setting
* the callback returns false.
* @return $this
*/
- public function notEmpty($field, $message = null, $when = false)
+ public function notEmpty($field, ?string $message = null, $when = false)
{
+ deprecationWarning(
+ 'notEmpty() is deprecated. '
+ . 'Use notEmptyString(), notEmptyArray(), notEmptyFile(), notEmptyDate(), notEmptyTime() '
+ . 'or notEmptyDateTime() instead.'
+ );
+
$defaults = [
'when' => $when,
'message' => $message,
@@ -1230,6 +1216,7 @@ public function notEmpty($field, $message = null, $when = false)
$whenSetting = $this->invertWhenClause($settings[$fieldName]['when']);
$this->field($fieldName)->allowEmpty($whenSetting);
+ $this->_allowEmptyFlags[$fieldName] = static::EMPTY_ALL;
if ($settings[$fieldName]['message']) {
$this->_allowEmptyMessages[$fieldName] = $settings[$fieldName]['message'];
}
@@ -1249,9 +1236,10 @@ public function notEmpty($field, $message = null, $when = false)
*/
protected function invertWhenClause($when)
{
- if ($when === 'create' || $when === 'update') {
- return $when === 'create' ? 'update' : 'create';
- } elseif (is_callable($when)) {
+ if ($when === static::WHEN_CREATE || $when === static::WHEN_UPDATE) {
+ return $when === static::WHEN_CREATE ? static::WHEN_UPDATE : static::WHEN_CREATE;
+ }
+ if (is_callable($when)) {
return function ($context) use ($when) {
return !$when($context);
};
@@ -1270,7 +1258,7 @@ protected function invertWhenClause($when)
* @see \Cake\Validation\Validation::notBlank()
* @return $this
*/
- public function notBlank($field, $message = null, $when = null)
+ public function notBlank(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1289,7 +1277,7 @@ public function notBlank($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::alphaNumeric()
* @return $this
*/
- public function alphaNumeric($field, $message = null, $when = null)
+ public function alphaNumeric(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1308,7 +1296,7 @@ public function alphaNumeric($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::notAlphaNumeric()
* @return $this
*/
- public function notAlphaNumeric($field, $message = null, $when = null)
+ public function notAlphaNumeric(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1327,7 +1315,7 @@ public function notAlphaNumeric($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::asciiAlphaNumeric()
* @return $this
*/
- public function asciiAlphaNumeric($field, $message = null, $when = null)
+ public function asciiAlphaNumeric(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1346,7 +1334,7 @@ public function asciiAlphaNumeric($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::notAlphaNumeric()
* @return $this
*/
- public function notAsciiAlphaNumeric($field, $message = null, $when = null)
+ public function notAsciiAlphaNumeric(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1365,8 +1353,9 @@ public function notAsciiAlphaNumeric($field, $message = null, $when = null)
* true when the validation rule should be applied.
* @see \Cake\Validation\Validation::alphaNumeric()
* @return $this
+ * @throws \InvalidArgumentException
*/
- public function lengthBetween($field, array $range, $message = null, $when = null)
+ public function lengthBetween(string $field, array $range, ?string $message = null, $when = null)
{
if (count($range) !== 2) {
throw new InvalidArgumentException('The $range argument requires 2 numbers');
@@ -1390,7 +1379,7 @@ public function lengthBetween($field, array $range, $message = null, $when = nul
* @see \Cake\Validation\Validation::creditCard()
* @return $this
*/
- public function creditCard($field, $type = 'all', $message = null, $when = null)
+ public function creditCard(string $field, string $type = 'all', ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1410,7 +1399,7 @@ public function creditCard($field, $type = 'all', $message = null, $when = null)
* @see \Cake\Validation\Validation::comparison()
* @return $this
*/
- public function greaterThan($field, $value, $message = null, $when = null)
+ public function greaterThan(string $field, $value, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1430,7 +1419,7 @@ public function greaterThan($field, $value, $message = null, $when = null)
* @see \Cake\Validation\Validation::comparison()
* @return $this
*/
- public function greaterThanOrEqual($field, $value, $message = null, $when = null)
+ public function greaterThanOrEqual(string $field, $value, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1450,7 +1439,7 @@ public function greaterThanOrEqual($field, $value, $message = null, $when = null
* @see \Cake\Validation\Validation::comparison()
* @return $this
*/
- public function lessThan($field, $value, $message = null, $when = null)
+ public function lessThan(string $field, $value, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1470,7 +1459,7 @@ public function lessThan($field, $value, $message = null, $when = null)
* @see \Cake\Validation\Validation::comparison()
* @return $this
*/
- public function lessThanOrEqual($field, $value, $message = null, $when = null)
+ public function lessThanOrEqual(string $field, $value, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1490,7 +1479,7 @@ public function lessThanOrEqual($field, $value, $message = null, $when = null)
* @see \Cake\Validation\Validation::comparison()
* @return $this
*/
- public function equals($field, $value, $message = null, $when = null)
+ public function equals(string $field, $value, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1510,7 +1499,7 @@ public function equals($field, $value, $message = null, $when = null)
* @see \Cake\Validation\Validation::comparison()
* @return $this
*/
- public function notEquals($field, $value, $message = null, $when = null)
+ public function notEquals(string $field, $value, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1532,7 +1521,7 @@ public function notEquals($field, $value, $message = null, $when = null)
* @see \Cake\Validation\Validation::compareFields()
* @return $this
*/
- public function sameAs($field, $secondField, $message = null, $when = null)
+ public function sameAs(string $field, string $secondField, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1553,7 +1542,7 @@ public function sameAs($field, $secondField, $message = null, $when = null)
* @return $this
* @since 3.6.0
*/
- public function notSameAs($field, $secondField, $message = null, $when = null)
+ public function notSameAs(string $field, string $secondField, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1574,7 +1563,7 @@ public function notSameAs($field, $secondField, $message = null, $when = null)
* @return $this
* @since 3.6.0
*/
- public function equalToField($field, $secondField, $message = null, $when = null)
+ public function equalToField(string $field, string $secondField, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1595,7 +1584,7 @@ public function equalToField($field, $secondField, $message = null, $when = null
* @return $this
* @since 3.6.0
*/
- public function notEqualToField($field, $secondField, $message = null, $when = null)
+ public function notEqualToField(string $field, string $secondField, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1616,7 +1605,7 @@ public function notEqualToField($field, $secondField, $message = null, $when = n
* @return $this
* @since 3.6.0
*/
- public function greaterThanField($field, $secondField, $message = null, $when = null)
+ public function greaterThanField(string $field, string $secondField, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1637,7 +1626,7 @@ public function greaterThanField($field, $secondField, $message = null, $when =
* @return $this
* @since 3.6.0
*/
- public function greaterThanOrEqualToField($field, $secondField, $message = null, $when = null)
+ public function greaterThanOrEqualToField(string $field, string $secondField, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1658,7 +1647,7 @@ public function greaterThanOrEqualToField($field, $secondField, $message = null,
* @return $this
* @since 3.6.0
*/
- public function lessThanField($field, $secondField, $message = null, $when = null)
+ public function lessThanField(string $field, string $secondField, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1679,7 +1668,7 @@ public function lessThanField($field, $secondField, $message = null, $when = nul
* @return $this
* @since 3.6.0
*/
- public function lessThanOrEqualToField($field, $secondField, $message = null, $when = null)
+ public function lessThanOrEqualToField(string $field, string $secondField, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1698,9 +1687,9 @@ public function lessThanOrEqualToField($field, $secondField, $message = null, $w
* true when the validation rule should be applied.
* @see \Cake\Validation\Validation::containsNonAlphaNumeric()
* @return $this
- * @deprecated 3.9.0 Use notAlphaNumeric() instead. Will be removed in 5.0
+ * @deprecated 4.0.0 Use {@link notAlphaNumeric()} instead. Will be removed in 5.0
*/
- public function containsNonAlphaNumeric($field, $limit = 1, $message = null, $when = null)
+ public function containsNonAlphaNumeric(string $field, int $limit = 1, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1720,7 +1709,7 @@ public function containsNonAlphaNumeric($field, $limit = 1, $message = null, $wh
* @see \Cake\Validation\Validation::date()
* @return $this
*/
- public function date($field, $formats = ['ymd'], $message = null, $when = null)
+ public function date(string $field, array $formats = ['ymd'], ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1740,7 +1729,7 @@ public function date($field, $formats = ['ymd'], $message = null, $when = null)
* @see \Cake\Validation\Validation::datetime()
* @return $this
*/
- public function dateTime($field, $formats = ['ymd'], $message = null, $when = null)
+ public function dateTime(string $field, array $formats = ['ymd'], ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1759,7 +1748,7 @@ public function dateTime($field, $formats = ['ymd'], $message = null, $when = nu
* @see \Cake\Validation\Validation::time()
* @return $this
*/
- public function time($field, $message = null, $when = null)
+ public function time(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1779,7 +1768,7 @@ public function time($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::localizedTime()
* @return $this
*/
- public function localizedTime($field, $type = 'datetime', $message = null, $when = null)
+ public function localizedTime(string $field, string $type = 'datetime', ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1798,7 +1787,7 @@ public function localizedTime($field, $type = 'datetime', $message = null, $when
* @see \Cake\Validation\Validation::boolean()
* @return $this
*/
- public function boolean($field, $message = null, $when = null)
+ public function boolean(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1818,7 +1807,7 @@ public function boolean($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::decimal()
* @return $this
*/
- public function decimal($field, $places = null, $message = null, $when = null)
+ public function decimal(string $field, ?int $places = null, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1838,7 +1827,7 @@ public function decimal($field, $places = null, $message = null, $when = null)
* @see \Cake\Validation\Validation::email()
* @return $this
*/
- public function email($field, $checkMX = false, $message = null, $when = null)
+ public function email(string $field, bool $checkMX = false, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1859,7 +1848,7 @@ public function email($field, $checkMX = false, $message = null, $when = null)
* @see \Cake\Validation\Validation::ip()
* @return $this
*/
- public function ip($field, $message = null, $when = null)
+ public function ip(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1878,7 +1867,7 @@ public function ip($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::ip()
* @return $this
*/
- public function ipv4($field, $message = null, $when = null)
+ public function ipv4(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1897,7 +1886,7 @@ public function ipv4($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::ip()
* @return $this
*/
- public function ipv6($field, $message = null, $when = null)
+ public function ipv6(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1917,7 +1906,7 @@ public function ipv6($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::minLength()
* @return $this
*/
- public function minLength($field, $min, $message = null, $when = null)
+ public function minLength(string $field, int $min, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1937,7 +1926,7 @@ public function minLength($field, $min, $message = null, $when = null)
* @see \Cake\Validation\Validation::minLengthBytes()
* @return $this
*/
- public function minLengthBytes($field, $min, $message = null, $when = null)
+ public function minLengthBytes(string $field, int $min, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1957,7 +1946,7 @@ public function minLengthBytes($field, $min, $message = null, $when = null)
* @see \Cake\Validation\Validation::maxLength()
* @return $this
*/
- public function maxLength($field, $max, $message = null, $when = null)
+ public function maxLength(string $field, int $max, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1977,7 +1966,7 @@ public function maxLength($field, $max, $message = null, $when = null)
* @see \Cake\Validation\Validation::maxLengthBytes()
* @return $this
*/
- public function maxLengthBytes($field, $max, $message = null, $when = null)
+ public function maxLengthBytes(string $field, int $max, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -1996,7 +1985,7 @@ public function maxLengthBytes($field, $max, $message = null, $when = null)
* @see \Cake\Validation\Validation::numeric()
* @return $this
*/
- public function numeric($field, $message = null, $when = null)
+ public function numeric(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2015,7 +2004,7 @@ public function numeric($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::naturalNumber()
* @return $this
*/
- public function naturalNumber($field, $message = null, $when = null)
+ public function naturalNumber(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2034,7 +2023,7 @@ public function naturalNumber($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::naturalNumber()
* @return $this
*/
- public function nonNegativeInteger($field, $message = null, $when = null)
+ public function nonNegativeInteger(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2053,8 +2042,9 @@ public function nonNegativeInteger($field, $message = null, $when = null)
* true when the validation rule should be applied.
* @see \Cake\Validation\Validation::range()
* @return $this
+ * @throws \InvalidArgumentException
*/
- public function range($field, array $range, $message = null, $when = null)
+ public function range(string $field, array $range, ?string $message = null, $when = null)
{
if (count($range) !== 2) {
throw new InvalidArgumentException('The $range argument requires 2 numbers');
@@ -2078,7 +2068,7 @@ public function range($field, array $range, $message = null, $when = null)
* @see \Cake\Validation\Validation::url()
* @return $this
*/
- public function url($field, $message = null, $when = null)
+ public function url(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2099,7 +2089,7 @@ public function url($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::url()
* @return $this
*/
- public function urlWithProtocol($field, $message = null, $when = null)
+ public function urlWithProtocol(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2119,7 +2109,7 @@ public function urlWithProtocol($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::inList()
* @return $this
*/
- public function inList($field, array $list, $message = null, $when = null)
+ public function inList(string $field, array $list, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2138,7 +2128,7 @@ public function inList($field, array $list, $message = null, $when = null)
* @see \Cake\Validation\Validation::uuid()
* @return $this
*/
- public function uuid($field, $message = null, $when = null)
+ public function uuid(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2160,7 +2150,7 @@ public function uuid($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::uploadedFile()
* @return $this
*/
- public function uploadedFile($field, array $options, $message = null, $when = null)
+ public function uploadedFile(string $field, array $options, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2181,7 +2171,7 @@ public function uploadedFile($field, array $options, $message = null, $when = nu
* @see \Cake\Validation\Validation::uuid()
* @return $this
*/
- public function latLong($field, $message = null, $when = null)
+ public function latLong(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2200,7 +2190,7 @@ public function latLong($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::latitude()
* @return $this
*/
- public function latitude($field, $message = null, $when = null)
+ public function latitude(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2219,7 +2209,7 @@ public function latitude($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::longitude()
* @return $this
*/
- public function longitude($field, $message = null, $when = null)
+ public function longitude(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2238,7 +2228,7 @@ public function longitude($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::ascii()
* @return $this
*/
- public function ascii($field, $message = null, $when = null)
+ public function ascii(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2257,7 +2247,7 @@ public function ascii($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::utf8()
* @return $this
*/
- public function utf8($field, $message = null, $when = null)
+ public function utf8(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2278,7 +2268,7 @@ public function utf8($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::utf8()
* @return $this
*/
- public function utf8Extended($field, $message = null, $when = null)
+ public function utf8Extended(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2297,7 +2287,7 @@ public function utf8Extended($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::isInteger()
* @return $this
*/
- public function integer($field, $message = null, $when = null)
+ public function integer(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2316,7 +2306,7 @@ public function integer($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::isArray()
* @return $this
*/
- public function isArray($field, $message = null, $when = null)
+ public function isArray(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2335,7 +2325,7 @@ public function isArray($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::isScalar()
* @return $this
*/
- public function scalar($field, $message = null, $when = null)
+ public function scalar(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2354,7 +2344,7 @@ public function scalar($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::hexColor()
* @return $this
*/
- public function hexColor($field, $message = null, $when = null)
+ public function hexColor(string $field, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2375,10 +2365,10 @@ public function hexColor($field, $message = null, $when = null)
* @see \Cake\Validation\Validation::multiple()
* @return $this
*/
- public function multipleOptions($field, array $options = [], $message = null, $when = null)
+ public function multipleOptions(string $field, array $options = [], ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
- $caseInsensitive = isset($options['caseInsensitive']) ? $options['caseInsensitive'] : false;
+ $caseInsensitive = $options['caseInsensitive'] ?? false;
unset($options['caseInsensitive']);
return $this->add($field, 'multipleOptions', $extra + [
@@ -2398,7 +2388,7 @@ public function multipleOptions($field, array $options = [], $message = null, $w
* @see \Cake\Validation\Validation::numElements()
* @return $this
*/
- public function hasAtLeast($field, $count, $message = null, $when = null)
+ public function hasAtLeast(string $field, int $count, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2425,7 +2415,7 @@ public function hasAtLeast($field, $count, $message = null, $when = null)
* @see \Cake\Validation\Validation::numElements()
* @return $this
*/
- public function hasAtMost($field, $count, $message = null, $when = null)
+ public function hasAtMost(string $field, int $count, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2448,7 +2438,7 @@ public function hasAtMost($field, $count, $message = null, $when = null)
* @param bool $newRecord whether the data to be validated is new or to be updated.
* @return bool
*/
- public function isEmptyAllowed($field, $newRecord)
+ public function isEmptyAllowed(string $field, bool $newRecord): bool
{
$providers = $this->_providers;
$data = [];
@@ -2465,7 +2455,7 @@ public function isEmptyAllowed($field, $newRecord)
* @param bool $newRecord Whether the data to be validated is new or to be updated.
* @return bool
*/
- public function isPresenceRequired($field, $newRecord)
+ public function isPresenceRequired(string $field, bool $newRecord): bool
{
$providers = $this->_providers;
$data = [];
@@ -2484,7 +2474,7 @@ public function isPresenceRequired($field, $newRecord)
* true when the validation rule should be applied.
* @return $this
*/
- public function regex($field, $regex, $message = null, $when = null)
+ public function regex(string $field, string $regex, ?string $message = null, $when = null)
{
$extra = array_filter(['on' => $when, 'message' => $message]);
@@ -2499,7 +2489,7 @@ public function regex($field, $regex, $message = null, $when = null)
* @param string $field Field name
* @return string|null
*/
- public function getRequiredMessage($field)
+ public function getRequiredMessage(string $field): ?string
{
if (!isset($this->_fields[$field])) {
return null;
@@ -2510,9 +2500,7 @@ public function getRequiredMessage($field)
$defaultMessage = __d('cake', 'This field is required');
}
- return isset($this->_presenceMessages[$field])
- ? $this->_presenceMessages[$field]
- : $defaultMessage;
+ return $this->_presenceMessages[$field] ?? $defaultMessage;
}
/**
@@ -2521,7 +2509,7 @@ public function getRequiredMessage($field)
* @param string $field Field name
* @return string|null
*/
- public function getNotEmptyMessage($field)
+ public function getNotEmptyMessage(string $field): ?string
{
if (!isset($this->_fields[$field])) {
return null;
@@ -2532,16 +2520,13 @@ public function getNotEmptyMessage($field)
$defaultMessage = __d('cake', 'This field cannot be left empty');
}
- $notBlankMessage = null;
foreach ($this->_fields[$field] as $rule) {
if ($rule->get('rule') === 'notBlank' && $rule->get('message')) {
return $rule->get('message');
}
}
- return isset($this->_allowEmptyMessages[$field])
- ? $this->_allowEmptyMessages[$field]
- : $defaultMessage;
+ return $this->_allowEmptyMessages[$field] ?? $defaultMessage;
}
/**
@@ -2552,7 +2537,7 @@ public function getNotEmptyMessage($field)
* @param array $context A key value list of data containing the validation context.
* @return bool
*/
- protected function _checkPresence($field, $context)
+ protected function _checkPresence(ValidationSet $field, array $context): bool
{
$required = $field->isPresenceRequired();
@@ -2561,11 +2546,9 @@ protected function _checkPresence($field, $context)
}
$newRecord = $context['newRecord'];
- if (in_array($required, ['create', 'update'], true)) {
- return (
- ($required === 'create' && !$newRecord) ||
- ($required === 'update' && $newRecord)
- );
+ if (in_array($required, [static::WHEN_CREATE, static::WHEN_UPDATE], true)) {
+ return ($required === static::WHEN_CREATE && !$newRecord) ||
+ ($required === static::WHEN_UPDATE && $newRecord);
}
return !$required;
@@ -2578,7 +2561,7 @@ protected function _checkPresence($field, $context)
* @param array $context a key value list of data containing the validation context.
* @return bool
*/
- protected function _canBeEmpty($field, $context)
+ protected function _canBeEmpty(ValidationSet $field, array $context): bool
{
$allowed = $field->isEmptyAllowed();
@@ -2587,14 +2570,12 @@ protected function _canBeEmpty($field, $context)
}
$newRecord = $context['newRecord'];
- if (in_array($allowed, ['create', 'update'], true)) {
- $allowed = (
- ($allowed === 'create' && $newRecord) ||
- ($allowed === 'update' && !$newRecord)
- );
+ if (in_array($allowed, [static::WHEN_CREATE, static::WHEN_UPDATE], true)) {
+ $allowed = ($allowed === static::WHEN_CREATE && $newRecord) ||
+ ($allowed === static::WHEN_UPDATE && !$newRecord);
}
- return $allowed;
+ return (bool)$allowed;
}
/**
@@ -2602,9 +2583,9 @@ protected function _canBeEmpty($field, $context)
*
* @param mixed $data Value to check against.
* @return bool
- * @deprecated 3.7.0 Use isEmpty() instead
+ * @deprecated 3.7.0 Use {@link isEmpty()} instead
*/
- protected function _fieldIsEmpty($data)
+ protected function _fieldIsEmpty($data): bool
{
return $this->isEmpty($data, static::EMPTY_ALL);
}
@@ -2616,7 +2597,7 @@ protected function _fieldIsEmpty($data)
* @param int $flags A bitmask of EMPTY_* flags which specify what is empty
* @return bool
*/
- protected function isEmpty($data, $flags)
+ protected function isEmpty($data, int $flags): bool
{
if ($data === null) {
return true;
@@ -2680,7 +2661,7 @@ protected function isEmpty($data, $flags)
* @param bool $newRecord whether is it a new record or an existing one
* @return array
*/
- protected function _processRules($field, ValidationSet $rules, $data, $newRecord)
+ protected function _processRules(string $field, ValidationSet $rules, array $data, bool $newRecord): array
{
$errors = [];
// Loading default provider in case there is none
@@ -2718,7 +2699,7 @@ protected function _processRules($field, ValidationSet $rules, $data, $newRecord
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$fields = [];
foreach ($this->_fields as $name => $fieldSet) {
diff --git a/app/vendor/cakephp/cakephp/src/Validation/ValidatorAwareInterface.php b/app/vendor/cakephp/cakephp/src/Validation/ValidatorAwareInterface.php
index ac3fd1315..7d2d52dfd 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/ValidatorAwareInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/ValidatorAwareInterface.php
@@ -1,4 +1,6 @@
add('email', 'valid-email', ['rule' => 'email'])
- * ->add('password', 'valid', ['rule' => 'notBlank'])
- * ->requirePresence('username');
- * }
- * ```
- *
- * Otherwise, you can build the object by yourself and store it in the Table object:
- *
- * ```
- * $validator = new \Cake\Validation\Validator($table);
- * $validator
- * ->add('email', 'valid-email', ['rule' => 'email'])
- * ->add('password', 'valid', ['rule' => 'notBlank'])
- * ->allowEmpty('bio');
- * $table->setValidator('forSubscription', $validator);
- * ```
- *
- * You can implement the method in `validationDefault` in your Table subclass
- * should you wish to have a validation set that applies in cases where no other
- * set is specified.
- *
- * @param string|null $name the name of the validation set to return
- * @param \Cake\Validation\Validator|null $validator The validator instance to store,
- * use null to get a validator.
- * @return \Cake\Validation\Validator
- * @throws \RuntimeException
- * @deprecated 3.5.0 Use getValidator/setValidator instead.
- */
- public function validator($name = null, Validator $validator = null)
- {
- deprecationWarning(
- 'ValidatorAwareTrait::validator() is deprecated. ' .
- 'Use ValidatorAwareTrait::getValidator()/setValidator() instead.'
- );
- if ($validator !== null) {
- $name = $name ?: self::DEFAULT_VALIDATOR;
- $this->setValidator($name, $validator);
- }
-
- return $this->getValidator($name);
- }
-
/**
* Returns the validation rules tagged with $name. It is possible to have
* multiple different named validation sets, this is useful when you need
@@ -143,12 +87,11 @@ public function validator($name = null, Validator $validator = null)
* @param string|null $name The name of the validation set to return.
* @return \Cake\Validation\Validator
*/
- public function getValidator($name = null)
+ public function getValidator(?string $name = null): Validator
{
- $name = $name ?: self::DEFAULT_VALIDATOR;
+ $name = $name ?: static::DEFAULT_VALIDATOR;
if (!isset($this->_validators[$name])) {
- $validator = $this->createValidator($name);
- $this->setValidator($name, $validator);
+ $this->setValidator($name, $this->createValidator($name));
}
return $this->_validators[$name];
@@ -165,23 +108,30 @@ public function getValidator($name = null)
* @return \Cake\Validation\Validator
* @throws \RuntimeException
*/
- protected function createValidator($name)
+ protected function createValidator(string $name): Validator
{
$method = 'validation' . ucfirst($name);
if (!$this->validationMethodExists($method)) {
- $message = sprintf('The %s::%s() validation method does not exists.', __CLASS__, $method);
+ $message = sprintf('The %s::%s() validation method does not exists.', static::class, $method);
throw new RuntimeException($message);
}
$validator = new $this->_validatorClass();
$validator = $this->$method($validator);
if ($this instanceof EventDispatcherInterface) {
- $event = defined(self::class . '::BUILD_VALIDATOR_EVENT') ? self::BUILD_VALIDATOR_EVENT : 'Model.buildValidator';
+ $event = defined(static::class . '::BUILD_VALIDATOR_EVENT')
+ ? static::BUILD_VALIDATOR_EVENT
+ : 'Model.buildValidator';
$this->dispatchEvent($event, compact('validator', 'name'));
}
if (!$validator instanceof Validator) {
- throw new RuntimeException(sprintf('The %s::%s() validation method must return an instance of %s.', __CLASS__, $method, Validator::class));
+ throw new RuntimeException(sprintf(
+ 'The %s::%s() validation method must return an instance of %s.',
+ static::class,
+ $method,
+ Validator::class
+ ));
}
return $validator;
@@ -205,7 +155,7 @@ protected function createValidator($name)
* @param \Cake\Validation\Validator $validator Validator object to be set.
* @return $this
*/
- public function setValidator($name, Validator $validator)
+ public function setValidator(string $name, Validator $validator)
{
$validator->setProvider(static::VALIDATOR_PROVIDER_NAME, $this);
$this->_validators[$name] = $validator;
@@ -219,7 +169,7 @@ public function setValidator($name, Validator $validator)
* @param string $name The name of a validator.
* @return bool
*/
- public function hasValidator($name)
+ public function hasValidator(string $name): bool
{
$method = 'validation' . ucfirst($name);
if ($this->validationMethodExists($method)) {
@@ -235,7 +185,7 @@ public function hasValidator($name)
* @param string $name Validation method name.
* @return bool
*/
- protected function validationMethodExists($name)
+ protected function validationMethodExists(string $name): bool
{
return method_exists($this, $name);
}
@@ -248,7 +198,7 @@ protected function validationMethodExists($name)
* add some rules to it.
* @return \Cake\Validation\Validator
*/
- public function validationDefault(Validator $validator)
+ public function validationDefault(Validator $validator): Validator
{
return $validator;
}
diff --git a/app/vendor/cakephp/cakephp/src/Validation/composer.json b/app/vendor/cakephp/cakephp/src/Validation/composer.json
index db585a33d..eceaafd2e 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/composer.json
+++ b/app/vendor/cakephp/cakephp/src/Validation/composer.json
@@ -22,9 +22,9 @@
"source": "https://github.com/cakephp/validation"
},
"require": {
- "php": ">=5.6.0,<8.0.0",
- "cakephp/core": "^3.6.0",
- "cakephp/utility": "^3.6.0",
+ "php": ">=7.2.0",
+ "cakephp/core": "^4.0",
+ "cakephp/utility": "^4.0",
"psr/http-message": "^1.0.0"
},
"suggest": {
diff --git a/app/vendor/cakephp/cakephp/src/View/AjaxView.php b/app/vendor/cakephp/cakephp/src/View/AjaxView.php
index 6648b0d07..94b08a0e1 100644
--- a/app/vendor/cakephp/cakephp/src/View/AjaxView.php
+++ b/app/vendor/cakephp/cakephp/src/View/AjaxView.php
@@ -1,4 +1,6 @@
withType('ajax');
}
diff --git a/app/vendor/cakephp/cakephp/src/View/Cell.php b/app/vendor/cakephp/cakephp/src/View/Cell.php
index cd3139aaa..1df99d70b 100644
--- a/app/vendor/cakephp/cakephp/src/View/Cell.php
+++ b/app/vendor/cakephp/cakephp/src/View/Cell.php
@@ -1,4 +1,6 @@
_cache) {
@@ -173,34 +173,41 @@ public function render($template = null)
} catch (ReflectionException $e) {
throw new BadMethodCallException(sprintf(
'Class %s does not have a "%s" method.',
- get_class($this),
+ static::class,
$this->action
));
}
- $builder = $this->viewBuilder()->setLayout(false);
+ $builder = $this->viewBuilder();
if ($template !== null) {
$builder->setTemplate($template);
}
- $className = get_class($this);
+ $className = static::class;
$namePrefix = '\View\Cell\\';
+ /** @psalm-suppress PossiblyFalseOperand */
$name = substr($className, strpos($className, $namePrefix) + strlen($namePrefix));
$name = substr($name, 0, -4);
if (!$builder->getTemplatePath()) {
- $builder->setTemplatePath('Cell' . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $name));
+ $builder->setTemplatePath(
+ static::TEMPLATE_FOLDER . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $name)
+ );
}
$template = $builder->getTemplate();
- $this->View = $this->createView();
+ $view = $this->createView();
try {
- return $this->View->render($template);
+ return $view->render($template, false);
} catch (MissingTemplateException $e) {
$attributes = $e->getAttributes();
- $attributes = ['file' => basename($attributes['file']), 'name' => $name];
-
- throw new MissingCellViewException($attributes, null, $e);
+ throw new MissingCellTemplateException(
+ $name,
+ $attributes['file'],
+ $attributes['paths'],
+ null,
+ $e
+ );
}
};
@@ -220,13 +227,13 @@ public function render($template = null)
* @param string|null $template The name of the template to be rendered.
* @return array The cache configuration.
*/
- protected function _cacheConfig($action, $template = null)
+ protected function _cacheConfig(string $action, ?string $template = null): array
{
if (empty($this->_cache)) {
return [];
}
$template = $template ?: 'default';
- $key = 'cell_' . Inflector::underscore(get_class($this)) . '_' . $action . '_' . $template;
+ $key = 'cell_' . Inflector::underscore(static::class) . '_' . $action . '_' . $template;
$key = str_replace('\\', '_', $key);
$default = [
'config' => 'default',
@@ -236,6 +243,7 @@ protected function _cacheConfig($action, $template = null)
return $default;
}
+ /** @psalm-suppress PossiblyFalseOperand */
return $this->_cache + $default;
}
@@ -250,109 +258,35 @@ protected function _cacheConfig($action, $template = null)
* @return string Rendered cell
* @throws \Error Include error details for PHP 7 fatal errors.
*/
- public function __toString()
+ public function __toString(): string
{
try {
return $this->render();
} catch (Exception $e) {
- trigger_error(sprintf('Could not render cell - %s [%s, line %d]', $e->getMessage(), $e->getFile(), $e->getLine()), E_USER_WARNING);
+ trigger_error(sprintf(
+ 'Could not render cell - %s [%s, line %d]',
+ $e->getMessage(),
+ $e->getFile(),
+ $e->getLine()
+ ), E_USER_WARNING);
return '';
} catch (Error $e) {
- throw new Error(sprintf('Could not render cell - %s [%s, line %d]', $e->getMessage(), $e->getFile(), $e->getLine()));
+ throw new Error(sprintf(
+ 'Could not render cell - %s [%s, line %d]',
+ $e->getMessage(),
+ $e->getFile(),
+ $e->getLine()
+ ), 0, $e);
}
}
- /**
- * Magic accessor for removed properties.
- *
- * @param string $name Property name
- * @return mixed
- */
- public function __get($name)
- {
- $deprecated = [
- 'template' => 'getTemplate',
- 'plugin' => 'getPlugin',
- 'helpers' => 'getHelpers',
- ];
- if (isset($deprecated[$name])) {
- $method = $deprecated[$name];
- deprecationWarning(sprintf(
- 'Cell::$%s is deprecated. Use $cell->viewBuilder()->%s() instead.',
- $name,
- $method
- ));
-
- return $this->viewBuilder()->{$method}();
- }
-
- $protected = [
- 'action',
- 'args',
- 'request',
- 'response',
- 'View',
- ];
- if (in_array($name, $protected, true)) {
- deprecationWarning(sprintf(
- 'Cell::$%s is now protected and shouldn\'t be accessed from outside a child class.',
- $name
- ));
- }
-
- return $this->{$name};
- }
-
- /**
- * Magic setter for removed properties.
- *
- * @param string $name Property name.
- * @param mixed $value Value to set.
- * @return void
- */
- public function __set($name, $value)
- {
- $deprecated = [
- 'template' => 'setTemplate',
- 'plugin' => 'setPlugin',
- 'helpers' => 'setHelpers',
- ];
- if (isset($deprecated[$name])) {
- $method = $deprecated[$name];
- deprecationWarning(sprintf(
- 'Cell::$%s is deprecated. Use $cell->viewBuilder()->%s() instead.',
- $name,
- $method
- ));
- $this->viewBuilder()->{$method}($value);
-
- return;
- }
-
- $protected = [
- 'action',
- 'args',
- 'request',
- 'response',
- 'View',
- ];
- if (in_array($name, $protected, true)) {
- deprecationWarning(sprintf(
- 'Cell::$%s is now protected and shouldn\'t be accessed from outside a child class.',
- $name
- ));
- }
-
- $this->{$name} = $value;
- }
-
/**
* Debug info.
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
return [
'action' => $this->action,
diff --git a/app/vendor/cakephp/cakephp/src/View/CellTrait.php b/app/vendor/cakephp/cakephp/src/View/CellTrait.php
index ebe26595f..16d465d5c 100644
--- a/app/vendor/cakephp/cakephp/src/View/CellTrait.php
+++ b/app/vendor/cakephp/cakephp/src/View/CellTrait.php
@@ -1,4 +1,6 @@
'v1', 'a2' => 'v2'])` maps to `View\Cell\TagCloud::smallList(v1, v2)`
* @param array $options Options for Cell's constructor
@@ -54,17 +56,17 @@ trait CellTrait
* @throws \Cake\View\Exception\MissingCellException If Cell class was not found.
* @throws \BadMethodCallException If Cell class does not specified cell action.
*/
- protected function cell($cell, array $data = [], array $options = [])
+ protected function cell(string $cell, array $data = [], array $options = []): Cell
{
$parts = explode('::', $cell);
if (count($parts) === 2) {
- list($pluginAndCell, $action) = [$parts[0], $parts[1]];
+ [$pluginAndCell, $action] = [$parts[0], $parts[1]];
} else {
- list($pluginAndCell, $action) = [$parts[0], 'display'];
+ [$pluginAndCell, $action] = [$parts[0], 'display'];
}
- list($plugin) = pluginSplit($pluginAndCell);
+ [$plugin] = pluginSplit($pluginAndCell);
$className = App::className($pluginAndCell, 'View/Cell', 'Cell');
if (!$className) {
@@ -85,11 +87,11 @@ protected function cell($cell, array $data = [], array $options = [])
*
* @param string $className The cell classname.
* @param string $action The action name.
- * @param string $plugin The plugin name.
+ * @param string|null $plugin The plugin name.
* @param array $options The constructor options for the cell.
* @return \Cake\View\Cell
*/
- protected function _createCell($className, $action, $plugin, $options)
+ protected function _createCell(string $className, string $action, ?string $plugin, array $options): Cell
{
/** @var \Cake\View\Cell $instance */
$instance = new $className($this->request, $this->response, $this->getEventManager(), $options);
@@ -109,20 +111,19 @@ protected function _createCell($className, $action, $plugin, $options)
$builder->setTheme($this->theme);
}
- $class = get_class($this);
+ $class = static::class;
$builder->setClassName($class);
- $instance->viewClass = $class;
+ $instance->viewBuilder()->setClassName($class);
return $instance;
}
if (method_exists($this, 'viewBuilder')) {
$builder->setTheme($this->viewBuilder()->getTheme());
- }
- if (isset($this->viewClass)) {
- $builder->setClassName($this->viewClass);
- $instance->viewClass = $this->viewClass;
+ if ($this->viewBuilder()->getClassName() !== null) {
+ $builder->setClassName($this->viewBuilder()->getClassName());
+ }
}
return $instance;
diff --git a/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellException.php b/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellException.php
index 938ac4da7..e28cab8ae 100644
--- a/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellException.php
+++ b/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellException.php
@@ -1,4 +1,6 @@
name = $name;
+
+ parent::__construct($file, $paths, $code, $previous);
+ }
+
+ /**
+ * Get the passed in attributes
+ *
+ * @return array
+ * @psalm-return array{name: string, file: string, paths: array}
+ */
+ public function getAttributes(): array
+ {
+ return [
+ 'name' => $this->name,
+ 'file' => $this->file,
+ 'paths' => $this->paths,
+ ];
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellViewException.php b/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellViewException.php
deleted file mode 100644
index bad1e1b27..000000000
--- a/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellViewException.php
+++ /dev/null
@@ -1,26 +0,0 @@
-file = is_array($file) ? array_pop($file) : $file;
+ $this->paths = $paths;
+
+ parent::__construct($this->formatMessage(), $code, $previous);
+ }
+
+ /**
+ * Get the formatted exception message.
+ *
+ * @return string
+ */
+ public function formatMessage(): string
+ {
+ $message = "{$this->type} file `{$this->file}` could not be found.";
+ if ($this->paths) {
+ $message .= "\n\nThe following paths were searched:\n\n";
+ foreach ($this->paths as $path) {
+ $message .= "- `{$path}{$this->file}`\n";
+ }
+ }
+
+ return $message;
+ }
+
+ /**
+ * Get the passed in attributes
+ *
+ * @return array
+ * @psalm-return array{file: string, paths: array}
*/
- protected $_messageTemplate = 'Template file "%s" is missing.';
+ public function getAttributes(): array
+ {
+ return [
+ 'file' => $this->file,
+ 'paths' => $this->paths,
+ ];
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/View/Exception/MissingViewException.php b/app/vendor/cakephp/cakephp/src/View/Exception/MissingViewException.php
index d01027d6b..69b1515ae 100644
--- a/app/vendor/cakephp/cakephp/src/View/Exception/MissingViewException.php
+++ b/app/vendor/cakephp/cakephp/src/View/Exception/MissingViewException.php
@@ -1,4 +1,6 @@
getPrimaryKey();
+ }
+
+ /**
+ * Get the fields used in the context as a primary key.
+ *
+ * @return string[]
*/
- public function primaryKey()
+ public function getPrimaryKey(): array
{
if (
empty($this->_context['schema']['_constraints']) ||
@@ -113,7 +125,7 @@ public function primaryKey()
}
foreach ($this->_context['schema']['_constraints'] as $data) {
if (isset($data['type']) && $data['type'] === 'primary') {
- return isset($data['columns']) ? (array)$data['columns'] : [];
+ return (array)($data['columns'] ?? []);
}
}
@@ -121,11 +133,11 @@ public function primaryKey()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function isPrimaryKey($field)
+ public function isPrimaryKey(string $field): bool
{
- $primaryKey = $this->primaryKey();
+ $primaryKey = $this->getPrimaryKey();
return in_array($field, $primaryKey, true);
}
@@ -139,9 +151,9 @@ public function isPrimaryKey($field)
*
* @return bool
*/
- public function isCreate()
+ public function isCreate(): bool
{
- $primary = $this->primaryKey();
+ $primary = $this->getPrimaryKey();
foreach ($primary as $column) {
if (!empty($this->_context['defaults'][$column])) {
return false;
@@ -160,13 +172,14 @@ public function isCreate()
* @param string $field A dot separated path to the field a value
* is needed for.
* @param array $options Options:
+ *
* - `default`: Default value to return if no value found in request
* data or context record.
* - `schemaDefault`: Boolean indicating whether default value from
* context's schema should be used if it's not explicitly provided.
* @return mixed
*/
- public function val($field, $options = [])
+ public function val(string $field, array $options = [])
{
$options += [
'default' => null,
@@ -198,17 +211,31 @@ public function val($field, $options = [])
* In this context class, this is simply defined by the 'required' array.
*
* @param string $field A dot separated path to check required-ness for.
- * @return bool
+ * @return bool|null
*/
- public function isRequired($field)
+ public function isRequired(string $field): ?bool
{
- return (bool)$this->getRequiredMessage($field);
+ if (!is_array($this->_context['required'])) {
+ return null;
+ }
+
+ $required = Hash::get($this->_context['required'], $field);
+
+ if ($required === null) {
+ $required = Hash::get($this->_context['required'], $this->stripNesting($field));
+ }
+
+ if (!empty($required) || $required === '0') {
+ return true;
+ }
+
+ return $required;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getRequiredMessage($field)
+ public function getRequiredMessage(string $field): ?string
{
if (!is_array($this->_context['required'])) {
return null;
@@ -223,7 +250,7 @@ public function getRequiredMessage($field)
}
if ($required === true) {
- $required = __d('cake', 'This field is required');
+ $required = __d('cake', 'This field cannot be left empty');
}
return $required;
@@ -237,7 +264,7 @@ public function getRequiredMessage($field)
* @param string $field A dot separated path to check required-ness for.
* @return int|null
*/
- public function getMaxLength($field)
+ public function getMaxLength(string $field): ?int
{
if (!is_array($this->_context['schema'])) {
return null;
@@ -247,9 +274,9 @@ public function getMaxLength($field)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function fieldNames()
+ public function fieldNames(): array
{
$schema = $this->_context['schema'];
unset($schema['_constraints'], $schema['_indexes']);
@@ -262,9 +289,9 @@ public function fieldNames()
*
* @param string $field A dot separated path to get a schema type for.
* @return string|null An abstract data type or null.
- * @see \Cake\Database\Type
+ * @see \Cake\Database\TypeFactory
*/
- public function type($field)
+ public function type(string $field): ?string
{
if (!is_array($this->_context['schema'])) {
return null;
@@ -275,7 +302,7 @@ public function type($field)
$schema = Hash::get($this->_context['schema'], $this->stripNesting($field));
}
- return isset($schema['type']) ? $schema['type'] : null;
+ return $schema['type'] ?? null;
}
/**
@@ -284,7 +311,7 @@ public function type($field)
* @param string $field A dot separated path to get additional data on.
* @return array An array of data describing the additional attributes on a field.
*/
- public function attributes($field)
+ public function attributes(string $field): array
{
if (!is_array($this->_context['schema'])) {
return [];
@@ -304,13 +331,13 @@ public function attributes($field)
* @param string $field A dot separated path to check errors on.
* @return bool Returns true if the errors for the field are not empty.
*/
- public function hasError($field)
+ public function hasError(string $field): bool
{
if (empty($this->_context['errors'])) {
return false;
}
- return (bool)Hash::check($this->_context['errors'], $field);
+ return Hash::check($this->_context['errors'], $field);
}
/**
@@ -320,7 +347,7 @@ public function hasError($field)
* @return array An array of errors, an empty array will be returned when the
* context has no errors.
*/
- public function error($field)
+ public function error(string $field): array
{
if (empty($this->_context['errors'])) {
return [];
@@ -337,7 +364,7 @@ public function error($field)
* @param string $field A dot separated path
* @return string A string with stripped numeric nesting
*/
- protected function stripNesting($field)
+ protected function stripNesting(string $field): string
{
return preg_replace('/\.\d*\./', '.', $field);
}
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/ContextFactory.php b/app/vendor/cakephp/cakephp/src/View/Form/ContextFactory.php
index bfe31524d..b0e47e45b 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/ContextFactory.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/ContextFactory.php
@@ -1,4 +1,6 @@
'a-string', 'callable' => ..]`
- * @return \Cake\View\Form\ContextFactory
+ * @return static
*/
public static function createWithDefaults(array $providers = [])
{
@@ -59,17 +60,27 @@ public static function createWithDefaults(array $providers = [])
[
'type' => 'orm',
'callable' => function ($request, $data) {
- if (is_array($data['entity']) || $data['entity'] instanceof Traversable) {
+ if ($data['entity'] instanceof EntityInterface) {
+ return new EntityContext($request, $data);
+ }
+ if (isset($data['table'])) {
+ return new EntityContext($request, $data);
+ }
+ if (is_iterable($data['entity'])) {
$pass = (new Collection($data['entity']))->first() !== null;
if ($pass) {
return new EntityContext($request, $data);
+ } else {
+ return new NullContext($request, $data);
}
}
- if ($data['entity'] instanceof EntityInterface) {
- return new EntityContext($request, $data);
- }
- if (is_array($data['entity']) && empty($data['entity']['schema'])) {
- return new EntityContext($request, $data);
+ },
+ ],
+ [
+ 'type' => 'form',
+ 'callable' => function ($request, $data) {
+ if ($data['entity'] instanceof Form) {
+ return new FormContext($request, $data);
}
},
],
@@ -82,10 +93,10 @@ public static function createWithDefaults(array $providers = [])
},
],
[
- 'type' => 'form',
+ 'type' => 'null',
'callable' => function ($request, $data) {
- if ($data['entity'] instanceof Form) {
- return new FormContext($request, $data);
+ if ($data['entity'] === null) {
+ return new NullContext($request, $data);
}
},
],
@@ -109,7 +120,7 @@ public static function createWithDefaults(array $providers = [])
* when the form context is the correct type.
* @return $this
*/
- public function addProvider($type, callable $check)
+ public function addProvider(string $type, callable $check)
{
$this->providers = [$type => ['type' => $type, 'callable' => $check]]
+ $this->providers;
@@ -125,10 +136,9 @@ public function addProvider($type, callable $check)
* @param \Cake\Http\ServerRequest $request Request instance.
* @param array $data The data to get a context provider for.
* @return \Cake\View\Form\ContextInterface Context provider.
- * @throws \RuntimeException when the context class does not implement the
- * ContextInterface.
+ * @throws \RuntimeException When a context instace cannot be generated for given entity.
*/
- public function get(ServerRequest $request, array $data = [])
+ public function get(ServerRequest $request, array $data = []): ContextInterface
{
$data += ['entity' => null];
@@ -139,14 +149,12 @@ public function get(ServerRequest $request, array $data = [])
break;
}
}
+
if (!isset($context)) {
- $context = new NullContext($request, $data);
- }
- if (!($context instanceof ContextInterface)) {
throw new RuntimeException(sprintf(
- 'Context providers must return object implementing %s. Got "%s" instead.',
- ContextInterface::class,
- getTypeName($context)
+ 'No context provider found for value of type `%s`.'
+ . ' Use `null` as 1st argument of FormHelper::create() to create a context-less form.',
+ getTypeName($data['entity'])
));
}
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/ContextInterface.php b/app/vendor/cakephp/cakephp/src/View/Form/ContextInterface.php
index 039a4ef92..314891ff2 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/ContextInterface.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/ContextInterface.php
@@ -1,4 +1,6 @@
_context['table'];
+ /** @var \Cake\Datasource\EntityInterface|iterable $entity */
$entity = $this->_context['entity'];
if (empty($table)) {
- if (is_array($entity) || $entity instanceof Traversable) {
+ if (is_iterable($entity)) {
foreach ($entity as $e) {
$entity = $e;
break;
@@ -138,20 +144,21 @@ protected function _prepare()
$isEntity = $entity instanceof EntityInterface;
if ($isEntity) {
+ /** @psalm-suppress PossiblyInvalidMethodCall */
$table = $entity->getSource();
}
- if (!$table && $isEntity && get_class($entity) !== 'Cake\ORM\Entity') {
- list(, $entityClass) = namespaceSplit(get_class($entity));
+ if (!$table && $isEntity && get_class($entity) !== Entity::class) {
+ [, $entityClass] = namespaceSplit(get_class($entity));
$table = Inflector::pluralize($entityClass);
}
}
- if (is_string($table)) {
+ if (is_string($table) && strlen($table)) {
$table = $this->getTableLocator()->get($table);
}
- if (!($table instanceof RepositoryInterface)) {
+ if (!($table instanceof Table)) {
throw new RuntimeException(
- 'Unable to find table class for current entity'
+ 'Unable to find table class for current entity.'
);
}
$this->_isCollection = (
@@ -168,20 +175,36 @@ protected function _prepare()
*
* Gets the primary key columns from the root entity's schema.
*
- * @return array
+ * @return string[]
+ * @deprecated 4.0.0 Renamed to {@link getPrimaryKey()}.
*/
- public function primaryKey()
+ public function primaryKey(): array
{
return (array)$this->_tables[$this->_rootName]->getPrimaryKey();
}
/**
- * {@inheritDoc}
+ * Get the primary key data for the context.
+ *
+ * Gets the primary key columns from the root entity's schema.
+ *
+ * @return string[]
*/
- public function isPrimaryKey($field)
+ public function getPrimaryKey(): array
+ {
+ return (array)$this->_tables[$this->_rootName]->getPrimaryKey();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function isPrimaryKey(string $field): bool
{
$parts = explode('.', $field);
$table = $this->_getTable($parts);
+ if (!$table) {
+ return false;
+ }
$primaryKey = (array)$table->getPrimaryKey();
return in_array(array_pop($parts), $primaryKey, true);
@@ -198,10 +221,10 @@ public function isPrimaryKey($field)
*
* @return bool
*/
- public function isCreate()
+ public function isCreate(): bool
{
$entity = $this->_context['entity'];
- if (is_array($entity) || $entity instanceof Traversable) {
+ if (is_iterable($entity)) {
foreach ($entity as $e) {
$entity = $e;
break;
@@ -221,13 +244,14 @@ public function isCreate()
*
* @param string $field The dot separated path to the value.
* @param array $options Options:
+ *
* - `default`: Default value to return if no value found in request
* data or entity.
* - `schemaDefault`: Boolean indicating whether default value from table
* schema should be used if it's not explicitly provided.
* @return mixed The value of the field or null on a miss.
*/
- public function val($field, $options = [])
+ public function val(string $field, array $options = [])
{
$options += [
'default' => null,
@@ -244,7 +268,7 @@ public function val($field, $options = [])
$parts = explode('.', $field);
$entity = $this->entity($parts);
- if (end($parts) === '_ids' && !empty($entity)) {
+ if ($entity && end($parts) === '_ids') {
return $this->_extractMultiple($entity, $parts);
}
@@ -267,7 +291,7 @@ public function val($field, $options = [])
if (is_array($entity) || $entity instanceof ArrayAccess) {
$key = array_pop($parts);
- return isset($entity[$key]) ? $entity[$key] : $options['default'];
+ return $entity[$key] ?? $options['default'];
}
return null;
@@ -276,13 +300,13 @@ public function val($field, $options = [])
/**
* Get default value from table schema for given entity field.
*
- * @param array $parts Each one of the parts in a path for a field name
+ * @param string[] $parts Each one of the parts in a path for a field name
* @return mixed
*/
- protected function _schemaDefault($parts)
+ protected function _schemaDefault(array $parts)
{
$table = $this->_getTable($parts);
- if ($table === false) {
+ if ($table === null) {
return null;
}
$field = end($parts);
@@ -298,13 +322,13 @@ protected function _schemaDefault($parts)
* Helper method used to extract all the primary key values out of an array, The
* primary key column is guessed out of the provided $path array
*
- * @param array|\Traversable $values The list from which to extract primary keys from
- * @param array $path Each one of the parts in a path for a field name
+ * @param mixed $values The list from which to extract primary keys from
+ * @param string[] $path Each one of the parts in a path for a field name
* @return array|null
*/
- protected function _extractMultiple($values, $path)
+ protected function _extractMultiple($values, array $path): ?array
{
- if (!(is_array($values) || $values instanceof Traversable)) {
+ if (!is_iterable($values)) {
return null;
}
$table = $this->_getTable($path, false);
@@ -323,10 +347,10 @@ protected function _extractMultiple($values, $path)
*
* @param array|null $path Each one of the parts in a path for a field name
* or null to get the entity passed in constructor context.
- * @return \Cake\Datasource\EntityInterface|\Traversable|array|false
+ * @return \Cake\Datasource\EntityInterface|iterable|null
* @throws \RuntimeException When properties cannot be read.
*/
- public function entity($path = null)
+ public function entity(?array $path = null)
{
if ($path === null) {
return $this->_context['entity'];
@@ -334,7 +358,7 @@ public function entity($path = null)
$oneElement = count($path) === 1;
if ($oneElement && $this->_isCollection) {
- return false;
+ return null;
}
$entity = $this->_context['entity'];
if ($oneElement) {
@@ -353,13 +377,13 @@ public function entity($path = null)
$isLast = ($i === $last);
if (!$isLast && $next === null && $prop !== '_ids') {
$table = $this->_getTable($path);
-
- return $table->newEntity();
+ if ($table) {
+ return $table->newEmptyEntity();
+ }
}
$isTraversable = (
- is_array($next) ||
- $next instanceof Traversable ||
+ is_iterable($next) ||
$next instanceof EntityInterface
);
if ($isLast || !$isTraversable) {
@@ -408,7 +432,6 @@ protected function leafEntity($path = null)
}
$len = count($path);
- $last = $len - 1;
$leafEntity = $entity;
for ($i = 0; $i < $len; $i++) {
$prop = $path[$i];
@@ -458,7 +481,7 @@ protected function _getProp($target, $field)
}
if ($target instanceof Traversable) {
foreach ($target as $i => $val) {
- if ($i == $field) {
+ if ((string)$i === $field) {
return $val;
}
}
@@ -471,9 +494,9 @@ protected function _getProp($target, $field)
* Check if a field should be marked as required.
*
* @param string $field The dot separated path to the field you want to check.
- * @return bool
+ * @return bool|null
*/
- public function isRequired($field)
+ public function isRequired(string $field): ?bool
{
$parts = explode('.', $field);
$entity = $this->entity($parts);
@@ -486,19 +509,19 @@ public function isRequired($field)
$validator = $this->_getValidator($parts);
$fieldName = array_pop($parts);
if (!$validator->hasField($fieldName)) {
- return false;
+ return null;
}
if ($this->type($field) !== 'boolean') {
- return $validator->isEmptyAllowed($fieldName, $isNew) === false;
+ return !$validator->isEmptyAllowed($fieldName, $isNew);
}
return false;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getRequiredMessage($field)
+ public function getRequiredMessage(string $field): ?string
{
$parts = explode('.', $field);
@@ -509,15 +532,8 @@ public function getRequiredMessage($field)
}
$ruleset = $validator->field($fieldName);
-
- $requiredMessage = $validator->getRequiredMessage($fieldName);
- $emptyMessage = $validator->getNotEmptyMessage($fieldName);
-
- if ($ruleset->isPresenceRequired() && $requiredMessage) {
- return $requiredMessage;
- }
- if (!$ruleset->isEmptyAllowed() && $emptyMessage) {
- return $emptyMessage;
+ if (!$ruleset->isEmptyAllowed()) {
+ return $validator->getNotEmptyMessage($fieldName);
}
return null;
@@ -529,20 +545,25 @@ public function getRequiredMessage($field)
* @param string $field The dot separated path to the field you want to check.
* @return int|null
*/
- public function getMaxLength($field)
+ public function getMaxLength(string $field): ?int
{
$parts = explode('.', $field);
$validator = $this->_getValidator($parts);
$fieldName = array_pop($parts);
- if (!$validator->hasField($fieldName)) {
- return null;
- }
- foreach ($validator->field($fieldName)->rules() as $rule) {
- if ($rule->get('rule') === 'maxLength') {
- return $rule->get('pass')[0];
+
+ if ($validator->hasField($fieldName)) {
+ foreach ($validator->field($fieldName)->rules() as $rule) {
+ if ($rule->get('rule') === 'maxLength') {
+ return $rule->get('pass')[0];
+ }
}
}
+ $attributes = $this->attributes($field);
+ if (!empty($attributes['length'])) {
+ return (int)$attributes['length'];
+ }
+
return null;
}
@@ -551,11 +572,14 @@ public function getMaxLength($field)
*
* If the context is for an array of entities, the 0th index will be used.
*
- * @return array Array of fieldnames in the table/entity.
+ * @return string[] Array of field names in the table/entity.
*/
- public function fieldNames()
+ public function fieldNames(): array
{
$table = $this->_getTable('0');
+ if (!$table) {
+ return [];
+ }
return $table->getSchema()->columns();
}
@@ -566,8 +590,9 @@ public function fieldNames()
*
* @param array $parts Each one of the parts in a path for a field name
* @return \Cake\Validation\Validator
+ * @throws \RuntimeException If validator cannot be retrieved based on the parts.
*/
- protected function _getValidator($parts)
+ protected function _getValidator(array $parts): Validator
{
$keyParts = array_filter(array_slice($parts, 0, -1), function ($part) {
return !is_numeric($part);
@@ -576,12 +601,16 @@ protected function _getValidator($parts)
$entity = $this->entity($parts) ?: null;
if (isset($this->_validator[$key])) {
+ /** @psalm-suppress PossiblyInvalidArgument */
$this->_validator[$key]->setProvider('entity', $entity);
return $this->_validator[$key];
}
$table = $this->_getTable($parts);
+ if (!$table) {
+ throw new RuntimeException('Validator not found: ' . $key);
+ }
$alias = $table->getAlias();
$method = 'default';
@@ -592,6 +621,7 @@ protected function _getValidator($parts)
}
$validator = $table->getValidator($method);
+ /** @psalm-suppress PossiblyInvalidArgument */
$validator->setProvider('entity', $entity);
return $this->_validator[$key] = $validator;
@@ -600,12 +630,12 @@ protected function _getValidator($parts)
/**
* Get the table instance from a property path
*
- * @param array $parts Each one of the parts in a path for a field name
+ * @param string[]|string|\Cake\Datasource\EntityInterface $parts Each one of the parts in a path for a field name
* @param bool $fallback Whether or not to fallback to the last found table
* when a non-existent field/property is being encountered.
- * @return \Cake\ORM\Table|false Table instance or false
+ * @return \Cake\ORM\Table|null Table instance or null
*/
- protected function _getTable($parts, $fallback = true)
+ protected function _getTable($parts, $fallback = true): ?Table
{
if (!is_array($parts) || count($parts) === 1) {
return $this->_tables[$this->_rootName];
@@ -628,20 +658,22 @@ protected function _getTable($parts, $fallback = true)
$assoc = null;
foreach ($normalized as $part) {
if ($part === '_joinData') {
- if ($assoc) {
+ if ($assoc !== null) {
$table = $assoc->junction();
$assoc = null;
continue;
}
} else {
- $assoc = $table->associations()->getByProperty($part);
+ $associationCollection = $table->associations();
+ $assoc = $associationCollection->getByProperty($part);
}
- if (!$assoc && $fallback) {
- break;
- }
- if (!$assoc && !$fallback) {
- return false;
+ if ($assoc === null) {
+ if ($fallback) {
+ break;
+ }
+
+ return null;
}
$table = $assoc->getTarget();
@@ -655,12 +687,15 @@ protected function _getTable($parts, $fallback = true)
*
* @param string $field A dot separated path to get a schema type for.
* @return string|null An abstract data type or null.
- * @see \Cake\Database\Type
+ * @see \Cake\Database\TypeFactory
*/
- public function type($field)
+ public function type(string $field): ?string
{
$parts = explode('.', $field);
$table = $this->_getTable($parts);
+ if (!$table) {
+ return null;
+ }
return $table->getSchema()->baseColumnType(array_pop($parts));
}
@@ -671,10 +706,14 @@ public function type($field)
* @param string $field A dot separated path to get additional data on.
* @return array An array of data describing the additional attributes on a field.
*/
- public function attributes($field)
+ public function attributes(string $field): array
{
$parts = explode('.', $field);
$table = $this->_getTable($parts);
+ if (!$table) {
+ return [];
+ }
+
$column = (array)$table->getSchema()->getColumn(array_pop($parts));
$whitelist = ['length' => null, 'precision' => null];
@@ -687,7 +726,7 @@ public function attributes($field)
* @param string $field A dot separated path to check errors on.
* @return bool Returns true if the errors for the field are not empty.
*/
- public function hasError($field)
+ public function hasError(string $field): bool
{
return $this->error($field) !== [];
}
@@ -698,11 +737,11 @@ public function hasError($field)
* @param string $field A dot separated path to check errors on.
* @return array An array of errors.
*/
- public function error($field)
+ public function error(string $field): array
{
$parts = explode('.', $field);
try {
- list($entity, $remainingParts) = $this->leafEntity($parts);
+ [$entity, $remainingParts] = $this->leafEntity($parts);
} catch (RuntimeException $e) {
return [];
}
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/FormContext.php b/app/vendor/cakephp/cakephp/src/View/Form/FormContext.php
index 169178687..f3d5291c2 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/FormContext.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/FormContext.php
@@ -1,4 +1,6 @@
null,
@@ -117,7 +124,7 @@ public function val($field, $options = [])
* @param string $field Field name.
* @return mixed
*/
- protected function _schemaDefault($field)
+ protected function _schemaDefault(string $field)
{
$field = $this->_form->schema()->field($field);
if ($field) {
@@ -128,25 +135,25 @@ protected function _schemaDefault($field)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function isRequired($field)
+ public function isRequired(string $field): ?bool
{
$validator = $this->_form->getValidator();
if (!$validator->hasField($field)) {
- return false;
+ return null;
}
if ($this->type($field) !== 'boolean') {
- return $validator->isEmptyAllowed($field, $this->isCreate()) === false;
+ return !$validator->isEmptyAllowed($field, $this->isCreate());
}
return false;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getRequiredMessage($field)
+ public function getRequiredMessage(string $field): ?string
{
$parts = explode('.', $field);
@@ -157,24 +164,17 @@ public function getRequiredMessage($field)
}
$ruleset = $validator->field($fieldName);
-
- $requiredMessage = $validator->getRequiredMessage($fieldName);
- $emptyMessage = $validator->getNotEmptyMessage($fieldName);
-
- if ($ruleset->isPresenceRequired() && $requiredMessage) {
- return $requiredMessage;
- }
- if (!$ruleset->isEmptyAllowed() && $emptyMessage) {
- return $emptyMessage;
+ if (!$ruleset->isEmptyAllowed()) {
+ return $validator->getNotEmptyMessage($fieldName);
}
return null;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getMaxLength($field)
+ public function getMaxLength(string $field): ?int
{
$validator = $this->_form->getValidator();
if (!$validator->hasField($field)) {
@@ -186,29 +186,34 @@ public function getMaxLength($field)
}
}
+ $attributes = $this->attributes($field);
+ if (!empty($attributes['length'])) {
+ return $attributes['length'];
+ }
+
return null;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function fieldNames()
+ public function fieldNames(): array
{
return $this->_form->schema()->fields();
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function type($field)
+ public function type(string $field): ?string
{
return $this->_form->schema()->fieldType($field);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function attributes($field)
+ public function attributes(string $field): array
{
$column = (array)$this->_form->schema()->field($field);
$whiteList = ['length' => null, 'precision' => null];
@@ -217,9 +222,9 @@ public function attributes($field)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function hasError($field)
+ public function hasError(string $field): bool
{
$errors = $this->error($field);
@@ -227,9 +232,9 @@ public function hasError($field)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function error($field)
+ public function error(string $field): array
{
return (array)Hash::get($this->_form->getErrors(), $field, []);
}
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/NullContext.php b/app/vendor/cakephp/cakephp/src/View/Form/NullContext.php
index 45f0da620..d78c1f3f3 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/NullContext.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/NullContext.php
@@ -1,4 +1,6 @@
_request->getData($field);
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function isRequired($field)
+ public function isRequired(string $field): ?bool
{
- return false;
+ return null;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getRequiredMessage($field)
+ public function getRequiredMessage(string $field): ?string
{
return null;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getMaxLength($field)
+ public function getMaxLength(string $field): ?int
{
return null;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function fieldNames()
+ public function fieldNames(): array
{
return [];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function type($field)
+ public function type(string $field): ?string
{
return null;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function attributes($field)
+ public function attributes(string $field): array
{
return [];
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function hasError($field)
+ public function hasError(string $field): bool
{
return false;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function error($field)
+ public function error(string $field): array
{
return [];
}
diff --git a/app/vendor/cakephp/cakephp/src/View/Helper.php b/app/vendor/cakephp/cakephp/src/View/Helper.php
index abc5cac09..73b71cdca 100644
--- a/app/vendor/cakephp/cakephp/src/View/Helper.php
+++ b/app/vendor/cakephp/cakephp/src/View/Helper.php
@@ -1,4 +1,6 @@
_View = $View;
+ $this->_View = $view;
$this->setConfig($config);
if (!empty($this->helpers)) {
- $this->_helperMap = $View->helpers()->normalizeArray($this->helpers);
+ $this->_helperMap = $view->helpers()->normalizeArray($this->helpers);
}
$this->initialize($config);
@@ -111,18 +97,18 @@ public function __construct(View $View, array $config = [])
* @param array $params Array of params for the method.
* @return mixed|void
*/
- public function __call($method, $params)
+ public function __call(string $method, array $params)
{
- trigger_error(sprintf('Method %1$s::%2$s does not exist', get_class($this), $method), E_USER_WARNING);
+ trigger_error(sprintf('Method %1$s::%2$s does not exist', static::class, $method), E_USER_WARNING);
}
/**
* Lazy loads helpers.
*
* @param string $name Name of the property being accessed.
- * @return \Cake\View\Helper|null Helper instance if helper with provided name exists
+ * @return \Cake\View\Helper|null|void Helper instance if helper with provided name exists
*/
- public function __get($name)
+ public function __get(string $name)
{
if (isset($this->_helperMap[$name]) && !isset($this->{$name})) {
$config = ['enabled' => false] + (array)$this->_helperMap[$name]['config'];
@@ -130,81 +116,6 @@ public function __get($name)
return $this->{$name};
}
-
- $removed = [
- 'theme' => 'getTheme',
- 'plugin' => 'getPlugin',
- ];
- if (isset($removed[$name])) {
- $method = $removed[$name];
- deprecationWarning(sprintf(
- 'Helper::$%s is deprecated. Use $view->%s() instead.',
- $name,
- $method
- ));
-
- return $this->_View->{$method}();
- }
-
- if ($name === 'request') {
- deprecationWarning(
- 'Helper::$request is deprecated. Use $helper->getView()->getRequest() instead.'
- );
-
- return $this->_View->getRequest();
- }
-
- if ($name === 'helpers') {
- deprecationWarning(
- 'Helper::$helpers is now protected and should not be accessed from outside a helper class.'
- );
-
- return $this->helpers;
- }
- }
-
- /**
- * Magic setter for removed properties.
- *
- * @param string $name Property name.
- * @param mixed $value Value to set.
- * @return void
- */
- public function __set($name, $value)
- {
- $removed = [
- 'theme' => 'setTheme',
- 'plugin' => 'setPlugin',
- ];
- if (isset($removed[$name])) {
- $method = $removed[$name];
- deprecationWarning(sprintf(
- 'Helper::$%s is deprecated. Use $view->%s() instead.',
- $name,
- $method
- ));
- $this->_View->{$method}($value);
-
- return;
- }
-
- if ($name === 'request') {
- deprecationWarning(
- 'Helper::$request is deprecated. Use $helper->getView()->setRequest() instead.'
- );
-
- $this->_View->setRequest($value);
-
- return;
- }
-
- if ($name === 'helpers') {
- deprecationWarning(
- 'Helper::$helpers is now protected and should not be accessed from outside a helper class.'
- );
- }
-
- $this->{$name} = $value;
}
/**
@@ -212,7 +123,7 @@ public function __set($name, $value)
*
* @return \Cake\View\View The bound view instance.
*/
- public function getView()
+ public function getView(): View
{
return $this->_View;
}
@@ -220,46 +131,24 @@ public function getView()
/**
* Returns a string to be used as onclick handler for confirm dialogs.
*
- * @param string $message Message to be displayed
* @param string $okCode Code to be executed after user chose 'OK'
* @param string $cancelCode Code to be executed after user chose 'Cancel'
- * @param array $options Array of options
- * @return string onclick JS code
- */
- protected function _confirm($message, $okCode, $cancelCode = '', $options = [])
- {
- $message = $this->_cleanConfirmMessage($message);
- $confirm = "if (confirm({$message})) { {$okCode} } {$cancelCode}";
- // We cannot change the key here in 3.x, but the behavior is inverted in this case
- $escape = isset($options['escape']) && $options['escape'] === false;
- if ($escape) {
- /** @var string $confirm */
- $confirm = h($confirm);
- }
-
- return $confirm;
- }
-
- /**
- * Returns a string read to be used in confirm()
- *
- * @param string $message The message to clean
- * @return mixed
+ * @return string "onclick" JS code
*/
- protected function _cleanConfirmMessage($message)
+ protected function _confirm(string $okCode, string $cancelCode): string
{
- return str_replace('\\\n', '\n', json_encode($message));
+ return "if (confirm(this.dataset.confirmMessage)) { {$okCode} } {$cancelCode}";
}
/**
* Adds the given class to the element options
*
* @param array $options Array options/attributes to add a class to
- * @param string|null $class The class name being added.
+ * @param string $class The class name being added.
* @param string $key the key to use for class. Defaults to `'class'`.
* @return array Array of options with $key set.
*/
- public function addClass(array $options = [], $class = null, $key = 'class')
+ public function addClass(array $options, string $class, string $key = 'class'): array
{
if (isset($options[$key]) && is_array($options[$key])) {
$options[$key][] = $class;
@@ -283,7 +172,7 @@ public function addClass(array $options = [], $class = null, $key = 'class')
*
* @return array
*/
- public function implementedEvents()
+ public function implementedEvents(): array
{
$eventMap = [
'View.beforeRenderFile' => 'beforeRenderFile',
@@ -311,7 +200,7 @@ public function implementedEvents()
* @param array $config The configuration settings provided to this helper.
* @return void
*/
- public function initialize(array $config)
+ public function initialize(array $config): void
{
}
@@ -321,7 +210,7 @@ public function initialize(array $config)
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
return [
'helpers' => $this->helpers,
diff --git a/app/vendor/cakephp/cakephp/src/View/Helper/BreadcrumbsHelper.php b/app/vendor/cakephp/cakephp/src/View/Helper/BreadcrumbsHelper.php
index 14de4dee5..93de6826f 100644
--- a/app/vendor/cakephp/cakephp/src/View/Helper/BreadcrumbsHelper.php
+++ b/app/vendor/cakephp/cakephp/src/View/Helper/BreadcrumbsHelper.php
@@ -1,4 +1,6 @@
tag by default). It accepts two special keys:
+ *
* - *innerAttrs*: An array that allows you to define attributes for the inner element of the crumb (by default, to
- * the link)
+ * the link)
* - *templateVars*: Specific template vars in case you override the templates provided.
* @return $this
*/
@@ -94,15 +99,18 @@ public function add($title, $url = null, array $options = [])
* @param string|array $title If provided as a string, it represents the title of the crumb.
* Alternatively, if you want to add multiple crumbs at once, you can provide an array, with each values being a
* single crumb. Arrays are expected to be of this form:
+ *
* - *title* The title of the crumb
* - *link* The link of the crumb. If not provided, no link will be made
* - *options* Options of the crumb. See description of params option of this method.
+ *
* @param string|array|null $url URL of the crumb. Either a string, an array of route params to pass to
* Url::build() or null / empty if the crumb does not have a link.
* @param array $options Array of options. These options will be used as attributes HTML attribute the crumb will
* be rendered in (a tag by default). It accepts two special keys:
+ *
* - *innerAttrs*: An array that allows you to define attributes for the inner element of the crumb (by default, to
- * the link)
+ * the link)
* - *templateVars*: Specific template vars in case you override the templates provided.
* @return $this
*/
@@ -137,13 +145,14 @@ public function prepend($title, $url = null, array $options = [])
* Url::build() or null / empty if the crumb does not have a link.
* @param array $options Array of options. These options will be used as attributes HTML attribute the crumb will
* be rendered in (a tag by default). It accepts two special keys:
+ *
* - *innerAttrs*: An array that allows you to define attributes for the inner element of the crumb (by default, to
- * the link)
+ * the link)
* - *templateVars*: Specific template vars in case you override the templates provided.
* @return $this
* @throws \LogicException In case the index is out of bound
*/
- public function insertAt($index, $title, $url = null, array $options = [])
+ public function insertAt(int $index, string $title, $url = null, array $options = [])
{
if (!isset($this->crumbs[$index])) {
throw new LogicException(sprintf("No crumb could be found at index '%s'", $index));
@@ -166,13 +175,14 @@ public function insertAt($index, $title, $url = null, array $options = [])
* Url::build() or null / empty if the crumb does not have a link.
* @param array $options Array of options. These options will be used as attributes HTML attribute the crumb will
* be rendered in (a tag by default). It accepts two special keys:
+ *
* - *innerAttrs*: An array that allows you to define attributes for the inner element of the crumb (by default, to
- * the link)
+ * the link)
* - *templateVars*: Specific template vars in case you override the templates provided.
* @return $this
* @throws \LogicException In case the matching crumb can not be found
*/
- public function insertBefore($matchingTitle, $title, $url = null, array $options = [])
+ public function insertBefore(string $matchingTitle, string $title, $url = null, array $options = [])
{
$key = $this->findCrumb($matchingTitle);
@@ -195,13 +205,14 @@ public function insertBefore($matchingTitle, $title, $url = null, array $options
* Url::build() or null / empty if the crumb does not have a link.
* @param array $options Array of options. These options will be used as attributes HTML attribute the crumb will
* be rendered in (a tag by default). It accepts two special keys:
+ *
* - *innerAttrs*: An array that allows you to define attributes for the inner element of the crumb (by default, to
- * the link)
+ * the link)
* - *templateVars*: Specific template vars in case you override the templates provided.
* @return $this
* @throws \LogicException In case the matching crumb can not be found.
*/
- public function insertAfter($matchingTitle, $title, $url = null, array $options = [])
+ public function insertAfter(string $matchingTitle, string $title, $url = null, array $options = [])
{
$key = $this->findCrumb($matchingTitle);
@@ -217,7 +228,7 @@ public function insertAfter($matchingTitle, $title, $url = null, array $options
*
* @return array
*/
- public function getCrumbs()
+ public function getCrumbs(): array
{
return $this->crumbs;
}
@@ -241,14 +252,16 @@ public function reset()
* allow the insertion of custom template variable in the template.
* @param array $separator Array of attributes for the `separator` template.
* Possible properties are :
+ *
* - *separator* The string to be displayed as a separator
* - *templateVars* Allows the insertion of custom template variable in the template
* - *innerAttrs* To provide attributes in case your separator is divided in two elements.
+ *
* All other properties will be converted as HTML attributes and will replace the *attrs* key in the template.
* If you use the default for this option (empty), it will not render a separator.
* @return string The breadcrumbs trail
*/
- public function render(array $attributes = [], array $separator = [])
+ public function render(array $attributes = [], array $separator = []): string
{
if (!$this->crumbs) {
return '';
@@ -291,14 +304,14 @@ public function render(array $attributes = [], array $separator = [])
'title' => $title,
'url' => $url,
'separator' => '',
- 'templateVars' => isset($options['templateVars']) ? $options['templateVars'] : [],
+ 'templateVars' => $options['templateVars'] ?? [],
];
if (!$url) {
$template = 'itemWithoutLink';
}
- if ($separatorString && $key !== ($crumbsCount - 1)) {
+ if ($separatorString && $key !== $crumbsCount - 1) {
$templateParams['separator'] = $separatorString;
}
@@ -308,7 +321,7 @@ public function render(array $attributes = [], array $separator = [])
$crumbTrail = $this->formatTemplate('wrapper', [
'content' => $crumbTrail,
'attrs' => $templater->formatAttributes($attributes, ['templateVars']),
- 'templateVars' => isset($attributes['templateVars']) ? $attributes['templateVars'] : [],
+ 'templateVars' => $attributes['templateVars'] ?? [],
]);
return $crumbTrail;
@@ -321,7 +334,7 @@ public function render(array $attributes = [], array $separator = [])
* @param string $title Title to find.
* @return int|null Index of the crumb found, or null if it can not be found.
*/
- protected function findCrumb($title)
+ protected function findCrumb(string $title): ?int
{
foreach ($this->crumbs as $key => $crumb) {
if ($crumb['title'] === $title) {
diff --git a/app/vendor/cakephp/cakephp/src/View/Helper/FlashHelper.php b/app/vendor/cakephp/cakephp/src/View/Helper/FlashHelper.php
index 91f81b9c8..9b7f96193 100644
--- a/app/vendor/cakephp/cakephp/src/View/Helper/FlashHelper.php
+++ b/app/vendor/cakephp/cakephp/src/View/Helper/FlashHelper.php
@@ -1,4 +1,6 @@
_View->getRequest()->getSession();
@@ -98,7 +100,7 @@ public function render($key = 'flash', array $options = [])
*
* @return array
*/
- public function implementedEvents()
+ public function implementedEvents(): array
{
return [];
}
diff --git a/app/vendor/cakephp/cakephp/src/View/Helper/FormHelper.php b/app/vendor/cakephp/cakephp/src/View/Helper/FormHelper.php
index f4b43ff10..8b3deb2f5 100644
--- a/app/vendor/cakephp/cakephp/src/View/Helper/FormHelper.php
+++ b/app/vendor/cakephp/cakephp/src/View/Helper/FormHelper.php
@@ -1,4 +1,6 @@
'textarea',
'uuid' => 'string',
'datetime' => 'datetime',
+ 'datetimefractional' => 'datetime',
'timestamp' => 'datetime',
+ 'timestampfractional' => 'datetime',
+ 'timestamptimezone' => 'datetime',
'date' => 'date',
'time' => 'time',
+ 'year' => 'year',
'boolean' => 'checkbox',
'float' => 'number',
'integer' => 'number',
@@ -107,8 +93,6 @@ class FormHelper extends Helper
'checkboxFormGroup' => '{{label}}',
// Wrapper container for checkboxes.
'checkboxWrapper' => '{{label}}',
- // Widget ordering for date/time/datetime pickers.
- 'dateWidget' => '{{year}}{{month}}{{day}}{{hour}}{{minute}}{{second}}{{meridian}}',
// Error message wrapper elements.
'error' => '',
// Container for error items.
@@ -167,7 +151,7 @@ class FormHelper extends Helper
'selectedClass' => 'selected',
],
// set HTML5 validation message to custom required/empty messages
- 'autoSetCustomValidity' => false,
+ 'autoSetCustomValidity' => true,
];
/**
@@ -186,23 +170,17 @@ class FormHelper extends Helper
'select' => ['SelectBox'],
'textarea' => ['Textarea'],
'datetime' => ['DateTime', 'select'],
+ 'year' => ['Year', 'select'],
'_default' => ['Basic'],
];
- /**
- * List of fields created, used with secure forms.
- *
- * @var string[]
- */
- public $fields = [];
-
/**
* Constant used internally to skip the securing process,
* and neither add the field to the hash or to the unlocked fields.
*
* @var string
*/
- const SECURE_SKIP = 'skip';
+ public const SECURE_SKIP = 'skip';
/**
* Defines the type of form being created. Set by FormHelper::create().
@@ -211,16 +189,6 @@ class FormHelper extends Helper
*/
public $requestType;
- /**
- * An array of field names that have been excluded from
- * the Token hash used by SecurityComponent's validatePost method
- *
- * @see \Cake\View\Helper\FormHelper::_secure()
- * @see \Cake\Controller\Component\SecurityComponent::validatePost()
- * @var string[]
- */
- protected $_unlockedFields = [];
-
/**
* Locator for input widgets.
*
@@ -244,7 +212,7 @@ class FormHelper extends Helper
/**
* The action attribute value of the last created form.
- * Used to make form/request specific hashes for SecurityComponent.
+ * Used to make form/request specific hashes for form tampering protection.
*
* @var string
*/
@@ -262,23 +230,25 @@ class FormHelper extends Helper
*
* @var string[]
*/
- protected $_groupedInputTypes = ['radio', 'multicheckbox', 'date', 'time', 'datetime'];
+ protected $_groupedInputTypes = ['radio', 'multicheckbox'];
+
+ /**
+ * Form protector
+ *
+ * @var \Cake\Form\FormProtector|null
+ */
+ protected $formProtector;
/**
* Construct the widgets and binds the default context providers
*
- * @param \Cake\View\View $View The View this helper is being attached to.
+ * @param \Cake\View\View $view The View this helper is being attached to.
* @param array $config Configuration settings for the helper.
*/
- public function __construct(View $View, array $config = [])
+ public function __construct(View $view, array $config = [])
{
$locator = null;
$widgets = $this->_defaultWidgets;
- if (isset($config['registry'])) {
- deprecationWarning('`registry` config key is deprecated in FormHelper, use `locator` instead.');
- $config['locator'] = $config['registry'];
- unset($config['registry']);
- }
if (isset($config['locator'])) {
$locator = $config['locator'];
unset($config['locator']);
@@ -296,7 +266,7 @@ public function __construct(View $View, array $config = [])
unset($config['groupedInputTypes']);
}
- parent::__construct($View, $config);
+ parent::__construct($view, $config);
if (!$locator) {
$locator = new WidgetLocator($this->templater(), $this->_View, $widgets);
@@ -305,33 +275,13 @@ public function __construct(View $View, array $config = [])
$this->_idPrefix = $this->getConfig('idPrefix');
}
- /**
- * Set the widget registry the helper will use.
- *
- * @param \Cake\View\Widget\WidgetLocator|null $instance The registry instance to set.
- * @param array $widgets An array of widgets
- * @return \Cake\View\Widget\WidgetLocator
- * @deprecated 3.6.0 Use FormHelper::widgetLocator() instead.
- */
- public function widgetRegistry(WidgetRegistry $instance = null, $widgets = [])
- {
- deprecationWarning('widgetRegistry is deprecated, use widgetLocator instead.');
-
- if ($instance) {
- $instance->add($widgets);
- $this->setWidgetLocator($instance);
- }
-
- return $this->getWidgetLocator();
- }
-
/**
* Get the widget locator currently used by the helper.
*
* @return \Cake\View\Widget\WidgetLocator Current locator instance
* @since 3.6.0
*/
- public function getWidgetLocator()
+ public function getWidgetLocator(): WidgetLocator
{
return $this->_locator;
}
@@ -357,7 +307,7 @@ public function setWidgetLocator(WidgetLocator $instance)
* @param array $contexts An array of context providers.
* @return \Cake\View\Form\ContextFactory
*/
- public function contextFactory(ContextFactory $instance = null, array $contexts = [])
+ public function contextFactory(?ContextFactory $instance = null, array $contexts = []): ContextFactory
{
if ($instance === null) {
if ($this->_contextFactory === null) {
@@ -379,10 +329,7 @@ public function contextFactory(ContextFactory $instance = null, array $contexts
* - `type` Form method defaults to autodetecting based on the form context. If
* the form context's isCreate() method returns false, a PUT request will be done.
* - `method` Set the form's method attribute explicitly.
- * - `action` The controller action the form submits to, (optional). Use this option if you
- * don't need to change the controller from the current request's controller. Deprecated since 3.2, use `url`.
- * - `url` The URL the form submits to. Can be a string or a URL array. If you use 'url'
- * you should leave 'action' undefined.
+ * - `url` The URL the form submits to. Can be a string or a URL array.
* - `encoding` Set the accept-charset encoding for the form. Defaults to `Configure::read('App.encoding')`
* - `enctype` Set the form encoding explicitly. By default `type => file` will set `enctype`
* to `multipart/form-data`.
@@ -397,19 +344,15 @@ public function contextFactory(ContextFactory $instance = null, array $contexts
*
* @param mixed $context The context for which the form is being defined.
* Can be a ContextInterface instance, ORM entity, ORM resultset, or an
- * array of meta data. You can use null to make a context-less form.
+ * array of meta data. You can use `null` to make a context-less form.
* @param array $options An array of html attributes and options.
* @return string An formatted opening FORM tag.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#Cake\View\Helper\FormHelper::create
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#Cake\View\Helper\FormHelper::create
*/
- public function create($context = null, array $options = [])
+ public function create($context = null, array $options = []): string
{
$append = '';
- if (is_bool($context) || is_string($context)) {
- deprecationWarning('Using `string` or `bool` for $context is deprecated, use `null` to make a context-less form.');
- }
-
if ($context instanceof ContextInterface) {
$this->context($context);
} else {
@@ -425,7 +368,6 @@ public function create($context = null, array $options = [])
$options += [
'type' => $isCreate ? 'post' : 'put',
- 'action' => null,
'url' => null,
'encoding' => strtolower(Configure::read('App.encoding')),
'templates' => null,
@@ -433,10 +375,6 @@ public function create($context = null, array $options = [])
'valueSources' => null,
];
- if (isset($options['action'])) {
- trigger_error('Using key `action` is deprecated, use `url` directly instead.', E_USER_DEPRECATED);
- }
-
if (isset($options['valueSources'])) {
$this->setValueSources($options['valueSources']);
unset($options['valueSources']);
@@ -454,7 +392,7 @@ public function create($context = null, array $options = [])
}
unset($options['templates']);
- if ($options['action'] === false || $options['url'] === false) {
+ if ($options['url'] === false) {
$url = $this->_View->getRequest()->getRequestTarget();
$action = null;
} else {
@@ -463,7 +401,7 @@ public function create($context = null, array $options = [])
}
$this->_lastAction($url);
- unset($options['url'], $options['action'], $options['idPrefix']);
+ unset($options['url'], $options['idPrefix']);
$htmlAttributes = [];
switch (strtolower($options['type'])) {
@@ -475,8 +413,6 @@ public function create($context = null, array $options = [])
$htmlAttributes['enctype'] = 'multipart/form-data';
$options['type'] = $isCreate ? 'post' : 'put';
// Move on
- case 'post':
- // Move on
case 'put':
// Move on
case 'delete':
@@ -507,8 +443,12 @@ public function create($context = null, array $options = [])
$htmlAttributes += $options;
- $this->fields = [];
if ($this->requestType !== 'get') {
+ $formTokenData = $this->_View->getRequest()->getAttribute('formTokenData');
+ if ($formTokenData !== null) {
+ $this->formProtector = $this->createFormProtector($formTokenData);
+ }
+
$append .= $this->_csrfField();
}
@@ -520,7 +460,7 @@ public function create($context = null, array $options = [])
return $this->formatTemplate('formStart', [
'attrs' => $templater->formatAttributes($htmlAttributes) . $actionAttr,
- 'templateVars' => isset($options['templateVars']) ? $options['templateVars'] : [],
+ 'templateVars' => $options['templateVars'] ?? [],
]) . $append;
}
@@ -531,25 +471,22 @@ public function create($context = null, array $options = [])
* @param array $options An array of options from create()
* @return string|array The action attribute for the form.
*/
- protected function _formUrl($context, $options)
+ protected function _formUrl(ContextInterface $context, array $options)
{
$request = $this->_View->getRequest();
- if ($options['action'] === null && $options['url'] === null) {
+ if ($options['url'] === null) {
return $request->getRequestTarget();
}
if (
is_string($options['url']) ||
- (is_array($options['url']) && isset($options['url']['_name']))
+ (is_array($options['url']) &&
+ isset($options['url']['_name']))
) {
return $options['url'];
}
- if (isset($options['action']) && empty($options['url']['action'])) {
- $options['url']['action'] = $options['action'];
- }
-
$actionDefaults = [
'plugin' => $this->_View->getPlugin(),
'controller' => $request->getParam('controller'),
@@ -558,14 +495,6 @@ protected function _formUrl($context, $options)
$action = (array)$options['url'] + $actionDefaults;
- $pk = $context->primaryKey();
- if (count($pk)) {
- $id = $this->getSourceValue($pk[0]);
- }
- if (empty($action[0]) && isset($id)) {
- $action[0] = $id;
- }
-
return $action;
}
@@ -575,7 +504,7 @@ protected function _formUrl($context, $options)
* @param string|array|null $url The URL of the last form.
* @return void
*/
- protected function _lastAction($url)
+ protected function _lastAction($url = null): void
{
$action = Router::url($url, true);
$query = parse_url($action, PHP_URL_QUERY);
@@ -587,26 +516,21 @@ protected function _lastAction($url)
/**
* Return a CSRF input if the request data is present.
- * Used to secure forms in conjunction with CsrfComponent &
- * SecurityComponent
+ * Used to secure forms in conjunction with CsrfMiddleware.
*
* @return string
*/
- protected function _csrfField()
+ protected function _csrfField(): string
{
$request = $this->_View->getRequest();
- if ($request->getParam('_Token.unlockedFields')) {
- foreach ((array)$request->getParam('_Token.unlockedFields') as $unlocked) {
- $this->_unlockedFields[] = $unlocked;
- }
- }
- if (!$request->getParam('_csrfToken')) {
+ $csrfToken = $request->getAttribute('csrfToken');
+ if (!$csrfToken) {
return '';
}
return $this->hidden('_csrfToken', [
- 'value' => $request->getParam('_csrfToken'),
+ 'value' => $csrfToken,
'secure' => static::SECURE_SKIP,
'autocomplete' => 'off',
]);
@@ -621,16 +545,14 @@ protected function _csrfField()
* @param array $secureAttributes Secure attributes which will be passed as HTML attributes
* into the hidden input elements generated for the Security Component.
* @return string A closing FORM tag.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#closing-the-form
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#closing-the-form
*/
- public function end(array $secureAttributes = [])
+ public function end(array $secureAttributes = []): string
{
$out = '';
- if ($this->requestType !== 'get' && $this->_View->getRequest()->getParam('_Token')) {
- $out .= $this->secure($this->fields, $secureAttributes);
- $this->fields = [];
- $this->_unlockedFields = [];
+ if ($this->requestType !== 'get' && $this->_View->getRequest()->getAttribute('formTokenData') !== null) {
+ $out .= $this->secure([], $secureAttributes);
}
$out .= $this->formatTemplate('formEnd', []);
@@ -639,6 +561,7 @@ public function end(array $secureAttributes = [])
$this->_context = null;
$this->_valueSources = ['context'];
$this->_idPrefix = $this->getConfig('idPrefix');
+ $this->formProtector = null;
return $out;
}
@@ -651,18 +574,27 @@ public function end(array $secureAttributes = [])
* the hidden input tags generated for the Security Component. This is
* especially useful to set HTML5 attributes like 'form'.
*
- * @param array $fields If set specifies the list of fields to use when
- * generating the hash, else $this->fields is being used.
+ * @param array $fields If set specifies the list of fields to be added to
+ * FormProtector for generating the hash.
* @param array $secureAttributes will be passed as HTML attributes into the hidden
* input elements generated for the Security Component.
* @return string A hidden input field with a security hash, or empty string when
* secured forms are not in use.
*/
- public function secure(array $fields = [], array $secureAttributes = [])
+ public function secure(array $fields = [], array $secureAttributes = []): string
{
- if (!$this->_View->getRequest()->getParam('_Token')) {
+ if (!$this->formProtector) {
return '';
}
+
+ foreach ($fields as $field => $value) {
+ if (is_int($field)) {
+ $field = $value;
+ $value = null;
+ }
+ $this->formProtector->addField($field, true, $value);
+ }
+
$debugSecurity = Configure::read('debug');
if (isset($secureAttributes['debugSecurity'])) {
$debugSecurity = $debugSecurity && $secureAttributes['debugSecurity'];
@@ -671,10 +603,9 @@ public function secure(array $fields = [], array $secureAttributes = [])
$secureAttributes['secure'] = static::SECURE_SKIP;
$secureAttributes['autocomplete'] = 'off';
- $tokenData = $this->_buildFieldToken(
+ $tokenData = $this->formProtector->buildTokenData(
$this->_lastAction,
- $fields,
- $this->_unlockedFields
+ $this->_View->getRequest()->getSession()->id()
);
$tokenFields = array_merge($secureAttributes, [
'value' => $tokenData['fields'],
@@ -686,11 +617,7 @@ public function secure(array $fields = [], array $secureAttributes = [])
$out .= $this->hidden('_Token.unlocked', $tokenUnlocked);
if ($debugSecurity) {
$tokenDebug = array_merge($secureAttributes, [
- 'value' => urlencode(json_encode([
- $this->_lastAction,
- $fields,
- $this->_unlockedFields,
- ])),
+ 'value' => $tokenData['debug'],
]);
$out .= $this->hidden('_Token.debug', $tokenDebug);
}
@@ -699,76 +626,49 @@ public function secure(array $fields = [], array $secureAttributes = [])
}
/**
- * Add to or get the list of fields that are currently unlocked.
- * Unlocked fields are not included in the field hash used by SecurityComponent
- * unlocking a field once its been added to the list of secured fields will remove
- * it from the list of fields.
+ * Add to the list of fields that are currently unlocked.
+ *
+ * Unlocked fields are not included in the form protection field hash.
*
- * @param string|null $name The dot separated name for the field.
- * @return array|null Either null, or the list of fields.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#working-with-securitycomponent
+ * @param string $name The dot separated name for the field.
+ * @return $this
*/
- public function unlockField($name = null)
+ public function unlockField(string $name)
{
- if ($name === null) {
- return $this->_unlockedFields;
- }
- if (!in_array($name, $this->_unlockedFields, true)) {
- $this->_unlockedFields[] = $name;
- }
- $index = array_search($name, $this->fields, true);
- if ($index !== false) {
- unset($this->fields[$index]);
- }
- unset($this->fields[$name]);
+ $this->getFormProtector()->unlockField($name);
+
+ return $this;
}
/**
- * Determine which fields of a form should be used for hash.
- * Populates $this->fields
+ * Create FormProtector instance.
*
- * @param bool $lock Whether this field should be part of the validation
- * or excluded as part of the unlockedFields.
- * @param string|array $field Reference to field to be secured. Can be dot
- * separated string to indicate nesting or array of fieldname parts.
- * @param mixed $value Field value, if value should not be tampered with.
- * @return void
+ * @param array $formTokenData Token data.
+ * @return \Cake\Form\FormProtector
*/
- protected function _secure($lock, $field, $value = null)
+ protected function createFormProtector(array $formTokenData): FormProtector
{
- if (empty($field) && $field !== '0') {
- return;
- }
+ $session = $this->_View->getRequest()->getSession();
+ $session->start();
- if (is_string($field)) {
- $field = Hash::filter(explode('.', $field));
- }
+ return new FormProtector(
+ $formTokenData
+ );
+ }
- foreach ($this->_unlockedFields as $unlockField) {
- $unlockParts = explode('.', $unlockField);
- if (array_values(array_intersect($field, $unlockParts)) === $unlockParts) {
- return;
- }
+ /**
+ * Get form protector instance.
+ *
+ * @return \Cake\Form\FormProtector
+ * @throws \Cake\Core\Exception\Exception
+ */
+ public function getFormProtector(): FormProtector
+ {
+ if ($this->formProtector === null) {
+ throw new Exception('FormHelper::create() must be called first for FormProtector instance to be created.');
}
- $field = implode('.', $field);
- $field = preg_replace('/(\.\d+)+$/', '', $field);
-
- if ($lock) {
- if (!in_array($field, $this->fields, true)) {
- if ($value !== null) {
- $this->fields[$field] = $value;
-
- return;
- }
- if (isset($this->fields[$field]) && $value === null) {
- unset($this->fields[$field]);
- }
- $this->fields[] = $field;
- }
- } else {
- $this->unlockField($field);
- }
+ return $this->formProtector;
}
/**
@@ -776,9 +676,9 @@ protected function _secure($lock, $field, $value = null)
*
* @param string $field This should be "modelname.fieldname"
* @return bool If there are errors this method returns true, else false.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#displaying-and-checking-errors
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#displaying-and-checking-errors
*/
- public function isFieldError($field)
+ public function isFieldError(string $field): bool
{
return $this->_getContext()->hasError($field);
}
@@ -798,9 +698,9 @@ public function isFieldError($field)
* it should be a hash of key names => messages.
* @param array $options See above.
* @return string Formatted errors or ''.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#displaying-and-checking-errors
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#displaying-and-checking-errors
*/
- public function error($field, $text = null, array $options = [])
+ public function error(string $field, $text = null, array $options = []): string
{
if (substr($field, -5) === '._ids') {
$field = substr($field, 0, -5);
@@ -909,9 +809,9 @@ public function error($field, $text = null, array $options = [])
* fieldName.
* @param array $options An array of HTML attributes.
* @return string The formatted LABEL element
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#creating-labels
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#creating-labels
*/
- public function label($fieldName, $text = null, array $options = [])
+ public function label(string $fieldName, ?string $text = null, array $options = []): string
{
if ($text === null) {
$text = $fieldName;
@@ -971,15 +871,16 @@ public function label($fieldName, $text = null, array $options = [])
* @param array $fields An array of customizations for the fields that will be
* generated. This array allows you to set custom types, labels, or other options.
* @param array $options Options array. Valid keys are:
+ *
* - `fieldset` Set to false to disable the fieldset. You can also pass an array of params to be
* applied as HTML attributes to the fieldset tag. If you pass an empty array, the fieldset will
* be enabled
* - `legend` Set to false to disable the legend for the generated control set. Or supply a string
* to customize the legend text.
* @return string Completed form controls.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#generating-entire-forms
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#generating-entire-forms
*/
- public function allControls(array $fields = [], array $options = [])
+ public function allControls(array $fields = [], array $options = []): string
{
$context = $this->_getContext();
@@ -993,32 +894,6 @@ public function allControls(array $fields = [], array $options = [])
return $this->controls($fields, $options);
}
- /**
- * Generate a set of controls for `$fields`. If $fields is empty the fields
- * of current model will be used.
- *
- * @param array $fields An array of customizations for the fields that will be
- * generated. This array allows you to set custom types, labels, or other options.
- * @param array $options Options array. Valid keys are:
- * - `fieldset` Set to false to disable the fieldset. You can also pass an array of params to be
- * applied as HTML attributes to the fieldset tag. If you pass an empty array, the fieldset will
- * be enabled
- * - `legend` Set to false to disable the legend for the generated control set. Or supply a string
- * to customize the legend text.
- * @return string Completed form controls.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#generating-entire-forms
- * @deprecated 3.4.0 Use FormHelper::allControls() instead.
- */
- public function allInputs(array $fields = [], array $options = [])
- {
- deprecationWarning(
- 'FormHelper::allInputs() is deprecated. ' .
- 'Use FormHelper::allControls() instead.'
- );
-
- return $this->allControls($fields, $options);
- }
-
/**
* Generate a set of controls for `$fields` wrapped in a fieldset element.
*
@@ -1033,15 +908,16 @@ public function allInputs(array $fields = [], array $options = [])
* @param array $fields An array of the fields to generate. This array allows
* you to set custom types, labels, or other options.
* @param array $options Options array. Valid keys are:
+ *
* - `fieldset` Set to false to disable the fieldset. You can also pass an
* array of params to be applied as HTML attributes to the fieldset tag.
* If you pass an empty array, the fieldset will be enabled.
* - `legend` Set to false to disable the legend for the generated input set.
* Or supply a string to customize the legend text.
* @return string Completed form inputs.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#generating-entire-forms
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#generating-entire-forms
*/
- public function controls(array $fields, array $options = [])
+ public function controls(array $fields, array $options = []): string
{
$fields = Hash::normalize($fields);
@@ -1057,36 +933,12 @@ public function controls(array $fields, array $options = [])
return $this->fieldset($out, $options);
}
- /**
- * Generate a set of controls for `$fields` wrapped in a fieldset element.
- *
- * @param array $fields An array of the fields to generate. This array allows
- * you to set custom types, labels, or other options.
- * @param array $options Options array. Valid keys are:
- * - `fieldset` Set to false to disable the fieldset. You can also pass an
- * array of params to be applied as HTML attributes to the fieldset tag.
- * If you pass an empty array, the fieldset will be enabled.
- * - `legend` Set to false to disable the legend for the generated input set.
- * Or supply a string to customize the legend text.
- * @return string Completed form inputs.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#generating-entire-forms
- * @deprecated 3.4.0 Use FormHelper::controls() instead.
- */
- public function inputs(array $fields, array $options = [])
- {
- deprecationWarning(
- 'FormHelper::inputs() is deprecated. ' .
- 'Use FormHelper::controls() instead.'
- );
-
- return $this->controls($fields, $options);
- }
-
/**
* Wrap a set of inputs in a fieldset
*
* @param string $fields the form inputs to wrap in a fieldset
* @param array $options Options array. Valid keys are:
+ *
* - `fieldset` Set to false to disable the fieldset. You can also pass an array of params to be
* applied as HTML attributes to the fieldset tag. If you pass an empty array, the fieldset will
* be enabled
@@ -1094,7 +946,7 @@ public function inputs(array $fields, array $options = [])
* to customize the legend text.
* @return string Completed form inputs.
*/
- public function fieldset($fields = '', array $options = [])
+ public function fieldset(string $fields = '', array $options = []): string
{
$fieldset = $legend = true;
$context = $this->_getContext();
@@ -1109,7 +961,9 @@ public function fieldset($fields = '', array $options = [])
if ($legend === true) {
$isCreate = $context->isCreate();
- $modelName = Inflector::humanize(Inflector::singularize($this->_View->getRequest()->getParam('controller')));
+ $modelName = Inflector::humanize(
+ Inflector::singularize($this->_View->getRequest()->getParam('controller'))
+ );
if (!$isCreate) {
$legend = __d('cake', 'Edit {0}', $modelName);
} else {
@@ -1145,8 +999,8 @@ public function fieldset($fields = '', array $options = [])
* - `type` - Force the type of widget you want. e.g. `type => 'select'`
* - `label` - Either a string label, or an array of options for the label. See FormHelper::label().
* - `options` - For widgets that take options e.g. radio, select.
- * - `error` - Control the error message that is produced. Set to `false` to disable any kind of error reporting (field
- * error and error messages).
+ * - `error` - Control the error message that is produced. Set to `false` to disable any kind of error reporting
+ * (field error and error messages).
* - `empty` - String or boolean to enable empty select box options.
* - `nestedInput` - Used with checkbox and radio inputs. Set to false to render inputs outside of label
* elements. Can be set to true on any input to force the input inside the label. If you
@@ -1161,9 +1015,11 @@ public function fieldset($fields = '', array $options = [])
* @param string $fieldName This should be "modelname.fieldname"
* @param array $options Each type of input takes different options.
* @return string Completed form widget.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#creating-form-inputs
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#creating-form-inputs
+ * @psalm-suppress InvalidReturnType
+ * @psalm-suppress InvalidReturnStatement
*/
- public function control($fieldName, array $options = [])
+ public function control(string $fieldName, array $options = []): string
{
$options += [
'type' => null,
@@ -1210,10 +1066,15 @@ public function control($fieldName, array $options = [])
if ($options['type'] === 'checkbox') {
$nestedInput = true;
}
- $nestedInput = isset($options['nestedInput']) ? $options['nestedInput'] : $nestedInput;
+ $nestedInput = $options['nestedInput'] ?? $nestedInput;
unset($options['nestedInput']);
- if ($nestedInput === true && $options['type'] === 'checkbox' && !array_key_exists('hiddenField', $options) && $label !== false) {
+ if (
+ $nestedInput === true
+ && $options['type'] === 'checkbox'
+ && !array_key_exists('hiddenField', $options)
+ && $label !== false
+ ) {
$options['hiddenField'] = '_split';
}
@@ -1246,32 +1107,13 @@ public function control($fieldName, array $options = [])
return $result;
}
- /**
- * Generates a form control element complete with label and wrapper div.
- *
- * @param string $fieldName This should be "modelname.fieldname"
- * @param array $options Each type of input takes different options.
- * @return string Completed form widget.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#creating-form-inputs
- * @deprecated 3.4.0 Use FormHelper::control() instead.
- */
- public function input($fieldName, array $options = [])
- {
- deprecationWarning(
- 'FormHelper::input() is deprecated. ' .
- 'Use FormHelper::control() instead.'
- );
-
- return $this->control($fieldName, $options);
- }
-
/**
* Generates an group template element
*
* @param array $options The options for group template
* @return string The generated group template
*/
- protected function _groupTemplate($options)
+ protected function _groupTemplate(array $options): string
{
$groupTemplate = $options['options']['type'] . 'FormGroup';
if (!$this->templater()->get($groupTemplate)) {
@@ -1279,10 +1121,10 @@ protected function _groupTemplate($options)
}
return $this->formatTemplate($groupTemplate, [
- 'input' => isset($options['input']) ? $options['input'] : [],
+ 'input' => $options['input'] ?? [],
'label' => $options['label'],
'error' => $options['error'],
- 'templateVars' => isset($options['options']['templateVars']) ? $options['options']['templateVars'] : [],
+ 'templateVars' => $options['options']['templateVars'] ?? [],
]);
}
@@ -1292,7 +1134,7 @@ protected function _groupTemplate($options)
* @param array $options The options for input container template
* @return string The generated input container template
*/
- protected function _inputContainerTemplate($options)
+ protected function _inputContainerTemplate(array $options): string
{
$inputContainerTemplate = $options['options']['type'] . 'Container' . $options['errorSuffix'];
if (!$this->templater()->get($inputContainerTemplate)) {
@@ -1304,7 +1146,7 @@ protected function _inputContainerTemplate($options)
'error' => $options['error'],
'required' => $options['options']['required'] ? ' required' : '',
'type' => $options['options']['type'],
- 'templateVars' => isset($options['options']['templateVars']) ? $options['options']['templateVars'] : [],
+ 'templateVars' => $options['options']['templateVars'] ?? [],
]);
}
@@ -1313,28 +1155,24 @@ protected function _inputContainerTemplate($options)
*
* @param string $fieldName the field name
* @param array $options The options for the input element
- * @return string The generated input element
+ * @return string|array The generated input element string
+ * or array if checkbox() is called with option 'hiddenField' set to '_split'.
*/
- protected function _getInput($fieldName, $options)
+ protected function _getInput(string $fieldName, array $options)
{
$label = $options['labelOptions'];
unset($options['labelOptions']);
switch (strtolower($options['type'])) {
case 'select':
- $opts = $options['options'];
- unset($options['options']);
-
- return $this->select($fieldName, $opts, $options + ['label' => $label]);
case 'radio':
- $opts = $options['options'];
- unset($options['options']);
-
- return $this->radio($fieldName, $opts, $options + ['label' => $label]);
case 'multicheckbox':
$opts = $options['options'];
+ if ($opts == null) {
+ $opts = [];
+ }
unset($options['options']);
- return $this->multiCheckbox($fieldName, $opts, $options + ['label' => $label]);
+ return $this->{$options['type']}($fieldName, $opts, $options + ['label' => $label]);
case 'input':
throw new RuntimeException("Invalid type 'input' used for field '$fieldName'");
@@ -1350,7 +1188,7 @@ protected function _getInput($fieldName, $options)
* @param array $options Options list.
* @return array Options
*/
- protected function _parseOptions($fieldName, $options)
+ protected function _parseOptions(string $fieldName, array $options): array
{
$needsMagicType = false;
if (empty($options['type'])) {
@@ -1372,7 +1210,7 @@ protected function _parseOptions($fieldName, $options)
* @param array $options the options passed to the input method
* @return string
*/
- protected function _inputType($fieldName, $options)
+ protected function _inputType(string $fieldName, array $options): string
{
$context = $this->_getContext();
@@ -1386,7 +1224,7 @@ protected function _inputType($fieldName, $options)
$internalType = $context->type($fieldName);
$map = $this->_config['typeMap'];
- $type = isset($map[$internalType]) ? $map[$internalType] : 'text';
+ $type = $map[$internalType] ?? 'text';
$fieldName = array_slice(explode('.', $fieldName), -1)[0];
switch (true) {
@@ -1394,14 +1232,16 @@ protected function _inputType($fieldName, $options)
return 'checkbox';
case isset($options['options']):
return 'select';
- case in_array($fieldName, ['passwd', 'password']):
+ case in_array($fieldName, ['passwd', 'password'], true):
return 'password';
- case in_array($fieldName, ['tel', 'telephone', 'phone']):
+ case in_array($fieldName, ['tel', 'telephone', 'phone'], true):
return 'tel';
case $fieldName === 'email':
return 'email';
case isset($options['rows']) || isset($options['cols']):
return 'textarea';
+ case $fieldName === 'year':
+ return 'year';
}
return $type;
@@ -1415,7 +1255,7 @@ protected function _inputType($fieldName, $options)
* @param array $options Options list.
* @return array
*/
- protected function _optionsOptions($fieldName, $options)
+ protected function _optionsOptions(string $fieldName, array $options): array
{
if (isset($options['options'])) {
return $options;
@@ -1434,7 +1274,7 @@ protected function _optionsOptions($fieldName, $options)
$pluralize ? Inflector::pluralize($fieldName) : $fieldName
);
$varOptions = $this->_View->get($varName);
- if (!is_array($varOptions) && !($varOptions instanceof Traversable)) {
+ if (!is_iterable($varOptions)) {
return $options;
}
if ($options['type'] !== 'radio') {
@@ -1454,84 +1294,59 @@ protected function _optionsOptions($fieldName, $options)
* overwrite the 'type' key in options.
* @return array
*/
- protected function _magicOptions($fieldName, $options, $allowOverride)
+ protected function _magicOptions(string $fieldName, array $options, bool $allowOverride): array
{
- $context = $this->_getContext();
-
$options += [
'templateVars' => [],
];
- if (!isset($options['required']) && $options['type'] !== 'hidden') {
- $options['required'] = $context->isRequired($fieldName);
- }
-
- if (method_exists($context, 'getRequiredMessage')) {
- $message = $context->getRequiredMessage($fieldName);
- $message = h($message);
-
- if ($options['required'] && $message) {
- $options['templateVars']['customValidityMessage'] = $message;
-
- if ($this->getConfig('autoSetCustomValidity')) {
- $options['oninvalid'] = "this.setCustomValidity(''); if (!this.validity.valid) this.setCustomValidity('$message')";
- $options['oninput'] = "this.setCustomValidity('')";
- }
- }
- }
-
- $type = $context->type($fieldName);
- $fieldDef = $context->attributes($fieldName);
-
- if ($options['type'] === 'number' && !isset($options['step'])) {
- if ($type === 'decimal' && isset($fieldDef['precision'])) {
- $decimalPlaces = $fieldDef['precision'];
- $options['step'] = sprintf('%.' . $decimalPlaces . 'F', pow(10, -1 * $decimalPlaces));
- } elseif ($type === 'float') {
- $options['step'] = 'any';
- }
- }
+ $options = $this->setRequiredAndCustomValidity($fieldName, $options);
$typesWithOptions = ['text', 'number', 'radio', 'select'];
- $magicOptions = (in_array($options['type'], ['radio', 'select']) || $allowOverride);
- if ($magicOptions && in_array($options['type'], $typesWithOptions)) {
+ $magicOptions = (in_array($options['type'], ['radio', 'select'], true) || $allowOverride);
+ if ($magicOptions && in_array($options['type'], $typesWithOptions, true)) {
$options = $this->_optionsOptions($fieldName, $options);
}
if ($allowOverride && substr($fieldName, -5) === '._ids') {
$options['type'] = 'select';
- if (!isset($options['multiple']) || ($options['multiple'] && $options['multiple'] != 'checkbox')) {
+ if (!isset($options['multiple']) || ($options['multiple'] && $options['multiple'] !== 'checkbox')) {
$options['multiple'] = true;
}
}
- if ($options['type'] === 'select' && array_key_exists('step', $options)) {
- unset($options['step']);
+ return $options;
+ }
+
+ /**
+ * Set required attribute and custom validity js.
+ *
+ * @param string $fieldName The name of the field to generate options for.
+ * @param array $options Options list.
+ * @return array Modified options list.
+ */
+ protected function setRequiredAndCustomValidity(string $fieldName, array $options)
+ {
+ $context = $this->_getContext();
+
+ if (!isset($options['required']) && $options['type'] !== 'hidden') {
+ $options['required'] = $context->isRequired($fieldName);
}
- $typesWithMaxLength = ['text', 'textarea', 'email', 'tel', 'url', 'search'];
- if (
- !array_key_exists('maxlength', $options)
- && in_array($options['type'], $typesWithMaxLength)
- ) {
- $maxLength = null;
- if (method_exists($context, 'getMaxLength')) {
- $maxLength = $context->getMaxLength($fieldName);
- }
+ $message = $context->getRequiredMessage($fieldName);
+ $message = h($message);
- if ($maxLength === null && !empty($fieldDef['length'])) {
- $maxLength = $fieldDef['length'];
- }
+ if ($options['required'] && $message) {
+ $options['templateVars']['customValidityMessage'] = $message;
- if ($maxLength !== null) {
- $options['maxlength'] = min($maxLength, 100000);
+ if ($this->getConfig('autoSetCustomValidity')) {
+ $options['data-validity-message'] = $message;
+ $options['oninvalid'] = "this.setCustomValidity(''); "
+ . 'if (!this.value) this.setCustomValidity(this.dataset.validityMessage)';
+ $options['oninput'] = "this.setCustomValidity('')";
}
}
- if (in_array($options['type'], ['datetime', 'date', 'time', 'select'])) {
- $options += ['empty' => false];
- }
-
return $options;
}
@@ -1540,9 +1355,9 @@ protected function _magicOptions($fieldName, $options, $allowOverride)
*
* @param string $fieldName The name of the field to generate label for.
* @param array $options Options list.
- * @return bool|string false or Generated label element
+ * @return string|false Generated label element or false.
*/
- protected function _getLabel($fieldName, $options)
+ protected function _getLabel(string $fieldName, array $options)
{
if ($options['type'] === 'hidden') {
return false;
@@ -1571,7 +1386,7 @@ protected function _getLabel($fieldName, $options)
* @param mixed $default The default option value
* @return mixed the contents of the option or default
*/
- protected function _extractOption($name, $options, $default = null)
+ protected function _extractOption(string $name, array $options, $default = null)
{
if (array_key_exists($name, $options)) {
return $options[$name];
@@ -1587,11 +1402,11 @@ protected function _extractOption($name, $options, $default = null)
* used instead of the generated values if present.
*
* @param string $fieldName The name of the field to generate label for.
- * @param string $label Label text.
+ * @param string|array|null $label Label text or array with label attributes.
* @param array $options Options for the label element.
* @return string Generated label element
*/
- protected function _inputLabel($fieldName, $label, $options)
+ protected function _inputLabel(string $fieldName, $label = null, array $options = []): string
{
$options += ['id' => null, 'input' => null, 'nestedInput' => false, 'templateVars' => []];
$labelAttributes = ['templateVars' => $options['templateVars']];
@@ -1636,10 +1451,10 @@ protected function _inputLabel($fieldName, $label, $options)
*
* @param string $fieldName Name of a field, like this "modelname.fieldname"
* @param array $options Array of HTML attributes.
- * @return string|array An HTML text input element.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#creating-checkboxes
+ * @return string[]|string An HTML text input element.
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#creating-checkboxes
*/
- public function checkbox($fieldName, array $options = [])
+ public function checkbox(string $fieldName, array $options = [])
{
$options += ['hiddenField' => true, 'value' => 1];
@@ -1653,8 +1468,10 @@ public function checkbox($fieldName, array $options = [])
if ($options['hiddenField']) {
$hiddenOptions = [
'name' => $options['name'],
- 'value' => $options['hiddenField'] !== true && $options['hiddenField'] !== '_split' ? $options['hiddenField'] : '0',
- 'form' => isset($options['form']) ? $options['form'] : null,
+ 'value' => $options['hiddenField'] !== true
+ && $options['hiddenField'] !== '_split'
+ ? $options['hiddenField'] : '0',
+ 'form' => $options['form'] ?? null,
'secure' => false,
];
if (isset($options['disabled']) && $options['disabled']) {
@@ -1690,18 +1507,18 @@ public function checkbox($fieldName, array $options = [])
* the radio label will be 'empty'. Set this option to a string to control the label value.
*
* @param string $fieldName Name of a field, like this "modelname.fieldname"
- * @param array|\Traversable $options Radio button options array.
+ * @param iterable $options Radio button options array.
* @param array $attributes Array of attributes.
* @return string Completed radio widget set.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#creating-radio-buttons
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#creating-radio-buttons
*/
- public function radio($fieldName, $options = [], array $attributes = [])
+ public function radio(string $fieldName, iterable $options = [], array $attributes = []): string
{
$attributes['options'] = $options;
$attributes['idPrefix'] = $this->_idPrefix;
$attributes = $this->_initInputField($fieldName, $attributes);
- $hiddenField = isset($attributes['hiddenField']) ? $attributes['hiddenField'] : true;
+ $hiddenField = $attributes['hiddenField'] ?? true;
unset($attributes['hiddenField']);
$radio = $this->widget('radio', $attributes);
@@ -1710,7 +1527,7 @@ public function radio($fieldName, $options = [], array $attributes = [])
if ($hiddenField) {
$hidden = $this->hidden($fieldName, [
'value' => $hiddenField === true ? '' : $hiddenField,
- 'form' => isset($attributes['form']) ? $attributes['form'] : null,
+ 'form' => $attributes['form'] ?? null,
'name' => $attributes['name'],
]);
}
@@ -1720,8 +1537,8 @@ public function radio($fieldName, $options = [], array $attributes = [])
/**
* Missing method handler - implements various simple input types. Is used to create inputs
- * of various types. e.g. `$this->Form->text();` will create `` while
- * `$this->Form->range();` will create ``
+ * of various types. e.g. `$this->Form->text();` will create `` while
+ * `$this->Form->range();` will create ``
*
* ### Usage
*
@@ -1731,7 +1548,7 @@ public function radio($fieldName, $options = [], array $attributes = [])
*
* Will make an input like:
*
- * ``
+ * ``
*
* The first argument to an input type should always be the fieldname, in `Model.field` format.
* The second argument should always be an array of attributes for the input.
@@ -1741,7 +1558,7 @@ public function radio($fieldName, $options = [], array $attributes = [])
* @return string Formatted input method.
* @throws \Cake\Core\Exception\Exception When there are no params for the method call.
*/
- public function __call($method, $params)
+ public function __call(string $method, array $params)
{
$options = [];
if (empty($params)) {
@@ -1768,9 +1585,9 @@ public function __call($method, $params)
* @param string $fieldName Name of a field, in the form "modelname.fieldname"
* @param array $options Array of HTML attributes, and special options above.
* @return string A generated HTML text input element
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#creating-textareas
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#creating-textareas
*/
- public function textarea($fieldName, array $options = [])
+ public function textarea(string $fieldName, array $options = []): string
{
$options = $this->_initInputField($fieldName, $options);
unset($options['type']);
@@ -1784,9 +1601,9 @@ public function textarea($fieldName, array $options = [])
* @param string $fieldName Name of a field, in the form of "modelname.fieldname"
* @param array $options Array of HTML attributes.
* @return string A generated hidden input
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#creating-hidden-inputs
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#creating-hidden-inputs
*/
- public function hidden($fieldName, array $options = [])
+ public function hidden(string $fieldName, array $options = []): string
{
$options += ['required' => false, 'secure' => true];
@@ -1798,8 +1615,12 @@ public function hidden($fieldName, array $options = [])
['secure' => static::SECURE_SKIP]
));
- if ($secure === true) {
- $this->_secure(true, $this->_secureFieldName($options['name']), (string)$options['val']);
+ if ($secure === true && $this->formProtector) {
+ $this->formProtector->addField(
+ $options['name'],
+ true,
+ (string)$options['val']
+ );
}
$options['type'] = 'hidden';
@@ -1813,9 +1634,9 @@ public function hidden($fieldName, array $options = [])
* @param string $fieldName Name of a field, in the form "modelname.fieldname"
* @param array $options Array of HTML attributes.
* @return string A generated file input.
- * @link https://book.cakephp.org/3/en/views/helpers/form.html#creating-file-inputs
+ * @link https://book.cakephp.org/4/en/views/helpers/form.html#creating-file-inputs
*/
- public function file($fieldName, array $options = [])
+ public function file(string $fieldName, array $options = []): string
{
$options += ['secure' => true];
$options = $this->_initInputField($fieldName, $options);
@@ -1828,28 +1649,38 @@ public function file($fieldName, array $options = [])
/**
* Creates a ` ', h($path), h($name), h($file));
+ endforeach;
+?>
+
+end(); ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_component.php b/app/vendor/cakephp/cakephp/templates/Error/missing_component.php
new file mode 100644
index 000000000..eb5b29155
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_component.php
@@ -0,0 +1,64 @@
+layout = 'dev_error';
+$this->assign('title', 'Missing Component');
+$this->assign('templateName', 'missing_component.php');
+
+$this->start('subheading');
+printf('%s could not be found.', h($pluginDot . $class));
+echo $this->element('plugin_class_error', ['pluginPath' => $pluginPath]);
+$this->end();
+
+$this->start('file');
+?>
+
+ Error
+ = sprintf('Create the class %s below in file: %s', h($class), $filePath . 'Controller' . DIRECTORY_SEPARATOR . 'Component' . DIRECTORY_SEPARATOR . h($class) . '.php'); ?>
+
+
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_connection.php b/app/vendor/cakephp/cakephp/templates/Error/missing_connection.php
new file mode 100644
index 000000000..acc58aaa8
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_connection.php
@@ -0,0 +1,24 @@
+layout = 'dev_error';
+
+$this->assign('templateName', 'missing_connection.php');
+$this->assign('title', 'Missing Database Connection');
+
+$this->assign('subheading', h($message));
+
+$this->start('file');
+echo $this->element('auto_table_warning');
+$this->end();
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_controller.php b/app/vendor/cakephp/cakephp/templates/Error/missing_controller.php
new file mode 100644
index 000000000..58da12677
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_controller.php
@@ -0,0 +1,93 @@
+layout = 'dev_error';
+
+$this->assign('title', 'Missing Controller');
+$this->assign('templateName', 'missing_controller.php');
+
+?>
+start('subheading');?>
+Error
+
+ Your routing resulted in = h($originalClass) ?> as a controller name.
+
+ = h($pluginDot . $class) ?>Controller could not be found.
+
+end() ?>
+
+
+start('file'); ?>
+
+ The controller name = h($originalClass) ?> has not been properly inflected, and
+ could not be resolved to a controller that exists in your application.
+
+ Ensure that your URL = h($this->request->getUri()->getPath()) ?> is
+ using the same inflection style as your routes do. By default applications use DashedRoute
+ and URLs should use - to separate multi-word controller names.
+
+
+ In the case you tried to access a plugin controller make sure you added it to your composer file or you use the autoload option for the plugin.
+
+
+ Suggestion
+ Create the class = h($class) ?>Controller below in file: = h($path) ?>
+
+
+
+
+
+end(); ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_datasource.php b/app/vendor/cakephp/cakephp/templates/Error/missing_datasource.php
new file mode 100644
index 000000000..f271ed74b
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_datasource.php
@@ -0,0 +1,29 @@
+layout = 'dev_error';
+
+$this->assign('title', 'Missing Datasource');
+$this->assign('templateName', 'missing_datasource.php');
+
+$this->start('subheading');
+?>
+Error
+Datasource class = h($pluginDot . $class) ?> could not be found.
+
+ = h($message); ?>
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_datasource_config.php b/app/vendor/cakephp/cakephp/templates/Error/missing_datasource_config.php
new file mode 100644
index 000000000..a18e355e0
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_datasource_config.php
@@ -0,0 +1,28 @@
+layout = 'dev_error';
+
+$this->assign('title', 'Missing Datasource Configuration');
+$this->assign('templateName', 'missing_datasource_config.php');
+
+$this->start('subheading');
+?>
+ Error
+
+ The datasource configuration = h($name) ?> was not found in config= DIRECTORY_SEPARATOR . 'app.php' ?>.
+
+ = h($message) ?>
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_helper.php b/app/vendor/cakephp/cakephp/templates/Error/missing_helper.php
new file mode 100644
index 000000000..bc0fecbc2
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_helper.php
@@ -0,0 +1,65 @@
+layout = 'dev_error';
+$this->assign('title', 'Missing Helper');
+$this->assign('templateName', 'missing_helper.php');
+
+$this->start('subheading');
+?>
+ Error
+ = h($pluginDot . $class) ?> could not be found.
+ = $this->element('plugin_class_error', ['pluginPath' => $pluginPath]) ?>
+end() ?>
+
+start('file') ?>
+
+ Suggestion
+ = sprintf('Create the class %s below in file: %s', h($class), $filePath . 'View' . DIRECTORY_SEPARATOR . 'Helper' . DIRECTORY_SEPARATOR . h($class) . '.php'); ?>
+
+
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_layout.php b/app/vendor/cakephp/cakephp/templates/Error/missing_layout.php
new file mode 100644
index 000000000..0a1b689f4
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_layout.php
@@ -0,0 +1,41 @@
+layout = 'dev_error';
+
+$this->assign('title', 'Missing Layout');
+$this->assign('templateName', 'missing_layout.php');
+
+$this->start('subheading');
+?>
+ Error
+ The layout file = h($file) ?> can not be found or does not exist.
+end() ?>
+
+start('file') ?>
+
+ Confirm you have created the file: = h($file) ?> in one of the following paths:
+
+
+%s%s', h($path), h($file));
+ endforeach;
+?>
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_plugin.php b/app/vendor/cakephp/cakephp/templates/Error/missing_plugin.php
new file mode 100644
index 000000000..1d6f3fdfa
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_plugin.php
@@ -0,0 +1,49 @@
+layout = 'dev_error';
+
+$pluginPath = Configure::read('App.paths.plugins.0');
+
+$this->assign('title', 'Missing Plugin');
+$this->assign('templateName', 'missing_plugin.php');
+
+$this->start('subheading');
+?>
+ Error
+ The application is trying to load a file from the = h($plugin) ?> plugin.
+
+
+ Make sure your plugin = h($plugin) ?> is in the = h($pluginPath) ?> directory and was loaded.
+end() ?>
+
+start('file') ?>
+addPlugin('{$plugin}');
+}
+PHP;
+
+?>
+
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_route.php b/app/vendor/cakephp/cakephp/templates/Error/missing_route.php
new file mode 100644
index 000000000..cdab9ae90
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_route.php
@@ -0,0 +1,59 @@
+layout = 'dev_error';
+
+$this->assign('title', 'Missing Route');
+$this->assign('templateName', 'missing_route.php');
+
+$attributes = $error->getAttributes();
+
+$this->start('subheading');
+?>
+ Error
+ = h($error->getMessage()); ?>
+end() ?>
+
+start('file') ?>
+None of the currently connected routes match the provided parameters.
+Add a matching route to = 'config' . DIRECTORY_SEPARATOR . 'routes.php' ?>
+
+
+The passed context was:
+
+= h(Debugger::exportVar($attributes['context'])); ?>
+
+
+
+Connected Routes
+
+Template Defaults Options
+';
+ printf(
+ '%s %s %s ',
+ h($route->template),
+ h(Debugger::exportVar($route->defaults)),
+ h(Debugger::exportVar($route->options))
+ );
+ echo '';
+endforeach;
+?>
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_template.php b/app/vendor/cakephp/cakephp/templates/Error/missing_template.php
new file mode 100644
index 000000000..b6d562524
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_template.php
@@ -0,0 +1,54 @@
+layout = 'dev_error';
+
+$this->assign('title', 'Missing Template');
+$this->assign('templateName', 'missing_template.php');
+
+$isEmail = strpos($file, 'Email/') === 0;
+
+$this->start('subheading');
+?>
+
+ Error
+ = sprintf('The template %s was not found.', h($file)); ?>
+
+ Error
+ = sprintf(
+ 'The view for %sController::%s() was not found.',
+ h(Inflector::camelize($this->request->getParam('controller', ''))),
+ h($this->request->getParam('action'))
+ ); ?>
+
+end() ?>
+
+start('file') ?>
+
+ = sprintf('Confirm you have created the file: "%s"', h($file)) ?>
+ in one of the following paths:
+
+
+%s%s', h($path), h($file));
+ endforeach;
+?>
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/missing_view.php b/app/vendor/cakephp/cakephp/templates/Error/missing_view.php
new file mode 100644
index 000000000..4916936db
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/missing_view.php
@@ -0,0 +1,68 @@
+layout = 'dev_error';
+$this->assign('title', 'Missing View');
+$this->assign('templateName', 'missing_view.php');
+
+$this->start('subheading');
+?>
+ Error
+ = h($pluginDot . $class) ?> could not be found.
+
+ Make sure your plugin = h($plugin) ?> is in the = h($pluginPath) ?> directory and was loaded.
+
+ = $this->element('plugin_class_error', ['pluginPath' => $pluginPath]) ?>
+
+end() ?>
+
+start('file') ?>
+
+ Suggestion
+ = sprintf('Create the class %s below in file: %s', h($class), $filePath . 'View' . DIRECTORY_SEPARATOR . h($class) . '.php'); ?>
+
+
+
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/Error/pdo_error.php b/app/vendor/cakephp/cakephp/templates/Error/pdo_error.php
new file mode 100644
index 000000000..e356e1820
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/Error/pdo_error.php
@@ -0,0 +1,44 @@
+setLayout('dev_error');
+
+$this->assign('title', 'Database Error');
+$this->assign('templateName', 'pdo_error.php');
+
+$this->start('subheading');
+?>
+ Error
+ = h($message); ?>
+end() ?>
+
+start('file') ?>
+
+ If you are using SQL keywords as table column names, you can enable identifier
+ quoting for your database connection in config/app.php.
+
+queryString)) : ?>
+
+ SQL Query:
+
+ = h($error->queryString); ?>
+
+params)) : ?>
+ SQL Query Params:
+ = h(Debugger::dump($error->params)); ?>
+
+= $this->element('auto_table_warning'); ?>
+end() ?>
diff --git a/app/vendor/cakephp/cakephp/templates/element/auto_table_warning.php b/app/vendor/cakephp/cakephp/templates/element/auto_table_warning.php
new file mode 100644
index 000000000..dc65ab8ee
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/element/auto_table_warning.php
@@ -0,0 +1,43 @@
+genericInstances();
+if (!$autoTables) {
+ return;
+}
+?>
+Could this be caused by using Auto-Tables?
+
+Some of the Table objects in your application were created by instantiating "Cake\ORM\Table"
+instead of any other specific subclass.
+
+This could be the cause for this exception. Auto-Tables are created for you under the following circumstances:
+
+ - The class for the specified table does not exist.
+ - The Table was created with a typo: $this->getTableLocator()->get('Atricles');
+ - The class file has a typo in the name or incorrect namespace: class Atricles extends Table
+ - The file containing the class has a typo or incorrect casing: Atricles.php
+ - The Table was used using associations but the association has a typo: $this->belongsTo('Atricles')
+ - The table class resides in a Plugin but no plugin notation was used in the association definition.
+
+
+Please try correcting the issue for the following table aliases:
+
+ $table) : ?>
+ - = $alias ?>
+
+
+
diff --git a/app/vendor/cakephp/cakephp/templates/element/exception_stack_trace.php b/app/vendor/cakephp/cakephp/templates/element/exception_stack_trace.php
new file mode 100644
index 000000000..65c884b1b
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/element/exception_stack_trace.php
@@ -0,0 +1,63 @@
+ $stack):
+ $excerpt = $params = [];
+
+ if (isset($stack['file'], $stack['line']) && is_numeric($stack['line'])):
+ $excerpt = Debugger::excerpt($stack['file'], $stack['line'], 4);
+ endif;
+
+ if (isset($stack['file'])):
+ $file = $stack['file'];
+ else:
+ $file = '[internal function]';
+ endif;
+
+ if (isset($stack['function'])):
+ if (!empty($stack['args'])):
+ foreach ((array)$stack['args'] as $arg):
+ $params[] = Debugger::exportVar($arg, 4);
+ endforeach;
+ else:
+ $params[] = 'No arguments';
+ endif;
+ endif;
+?>
+
+
+ = h($file) ?>
+ Toggle Arguments
+
+
+
+
+ $line): ?>
+
+
+ = $line ?>
+
+
+
+
+
+
+
diff --git a/app/vendor/cakephp/cakephp/templates/element/exception_stack_trace_nav.php b/app/vendor/cakephp/cakephp/templates/element/exception_stack_trace_nav.php
new file mode 100644
index 000000000..3c78b47d9
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/element/exception_stack_trace_nav.php
@@ -0,0 +1,43 @@
+
+Toggle Vendor Stack Frames
+
+
+ $stack): ?>
+
+ -
+
+
+ = h($stack['class'] . $stack['type'] . $stack['function']) ?>
+
+ = h($stack['function']) ?>
+
+
+
+ = h(Debugger::trimPath($stack['file'])) ?>:= $stack['line'] ?>
+
+ [internal function]
+
+
+
+
+
+
diff --git a/app/vendor/cakephp/cakephp/templates/element/plugin_class_error.php b/app/vendor/cakephp/cakephp/templates/element/plugin_class_error.php
new file mode 100644
index 000000000..7f8848f00
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/element/plugin_class_error.php
@@ -0,0 +1,31 @@
+
';
+
+if (!Plugin::isLoaded($plugin)):
+ echo sprintf('Make sure your plugin %s is in the %s directory and was loaded.', h($plugin), $pluginPath);
+else:
+ echo sprintf('Make sure your plugin was loaded from %s and Composer is able to autoload its classes, see %s and %s',
+ 'config' . DIRECTORY_SEPARATOR . 'bootstrap.php',
+ 'Loading a plugin',
+ 'Plugins - autoloading plugin classes'
+ );
+endif;
diff --git a/app/vendor/cakephp/cakephp/templates/layout/dev_error.php b/app/vendor/cakephp/cakephp/templates/layout/dev_error.php
new file mode 100644
index 000000000..d9cf35054
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/templates/layout/dev_error.php
@@ -0,0 +1,389 @@
+
+
+
+
+ = $this->Html->charset() ?>
+
+
+ Error: = h($this->fetch('title')) ?>
+
+ = $this->Html->meta('icon') ?>
+
+
+
+
+ fetch('title')));
+ $errorTitle = array_shift($title);
+ $errorDescription = implode("\n", $title);
+ ?>
+
+ = Debugger::formatHtmlMessage($errorTitle) ?>
+ 📋
+
+
+ = Debugger::formatHtmlMessage($errorDescription) ?>
+
+ = get_class($error) ?>
+
+
+
+ = $this->element('exception_stack_trace_nav') ?>
+
+
+ fetch('subheading')): ?>
+
+ = $this->fetch('subheading') ?>
+
+
+
+ = $this->element('exception_stack_trace'); ?>
+
+
+ = $this->fetch('file') ?>
+
+
+ fetch('templateName')): ?>
+
+ If you want to customize this error message, create
+ = 'templates' . DIRECTORY_SEPARATOR . 'Error' . DIRECTORY_SEPARATOR . $this->fetch('templateName') ?>
+
+
+
+
+
+
+
+
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/ArticlesMoreTranslationsFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/ArticlesMoreTranslationsFixture.php
new file mode 100644
index 000000000..1213a39b7
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/ArticlesMoreTranslationsFixture.php
@@ -0,0 +1,54 @@
+ ['type' => 'integer'],
+ 'locale' => ['type' => 'string', 'null' => false],
+ 'title' => ['type' => 'string', 'null' => false],
+ 'subtitle' => ['type' => 'string', 'null' => false],
+ 'body' => 'text',
+ '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id', 'locale']]],
+ ];
+
+ /**
+ * records property
+ *
+ * @var array
+ */
+ public $records = [
+ ['locale' => 'eng', 'id' => 1, 'title' => 'Title #1', 'subtitle' => 'SubTitle #1', 'body' => 'Content #1'],
+ ['locale' => 'deu', 'id' => 1, 'title' => 'Titel #1', 'subtitle' => 'SubTitel #1', 'body' => 'Inhalt #1'],
+ ['locale' => 'cze', 'id' => 1, 'title' => 'Titulek #1', 'subtitle' => 'SubTitulek #1', 'body' => 'Obsah #1'],
+ ['locale' => 'eng', 'id' => 2, 'title' => 'Title #2', 'subtitle' => 'SubTitle #2', 'body' => 'Content #2'],
+ ['locale' => 'deu', 'id' => 2, 'title' => 'Titel #2', 'subtitle' => 'SubTitel #2', 'body' => 'Inhalt #2'],
+ ['locale' => 'cze', 'id' => 2, 'title' => 'Titulek #2', 'subtitle' => 'SubTitulek #2', 'body' => 'Obsah #2'],
+ ['locale' => 'eng', 'id' => 3, 'title' => 'Title #3', 'subtitle' => 'SubTitle #3', 'body' => 'Content #3'],
+ ['locale' => 'deu', 'id' => 3, 'title' => 'Titel #3', 'subtitle' => 'SubTitel #3', 'body' => 'Inhalt #3'],
+ ['locale' => 'cze', 'id' => 3, 'title' => 'Titulek #3', 'subtitle' => 'SubTitulek #3', 'body' => 'Obsah #3'],
+ ];
+}
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/ArticlesTranslationsFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/ArticlesTranslationsFixture.php
new file mode 100644
index 000000000..ad1d95ece
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/ArticlesTranslationsFixture.php
@@ -0,0 +1,55 @@
+ ['type' => 'integer'],
+ 'locale' => ['type' => 'string', 'null' => false],
+ 'title' => ['type' => 'string', 'null' => true],
+ 'body' => 'text',
+ '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id', 'locale']]],
+ ];
+
+ /**
+ * records property
+ *
+ * @var array
+ */
+ public $records = [
+ ['locale' => 'eng', 'id' => 1, 'title' => 'Title #1', 'body' => 'Content #1'],
+ ['locale' => 'deu', 'id' => 1, 'title' => 'Titel #1', 'body' => 'Inhalt #1'],
+ ['locale' => 'cze', 'id' => 1, 'title' => 'Titulek #1', 'body' => 'Obsah #1'],
+ ['locale' => 'spa', 'id' => 1, 'title' => 'First Article', 'body' => 'Contenido #1'],
+ ['locale' => 'zzz', 'id' => 1, 'title' => '', 'body' => ''],
+ ['locale' => 'eng', 'id' => 2, 'title' => 'Title #2', 'body' => 'Content #2'],
+ ['locale' => 'deu', 'id' => 2, 'title' => 'Titel #2', 'body' => 'Inhalt #2'],
+ ['locale' => 'cze', 'id' => 2, 'title' => 'Titulek #2', 'body' => 'Obsah #2'],
+ ['locale' => 'eng', 'id' => 3, 'title' => 'Title #3', 'body' => 'Content #3'],
+ ['locale' => 'deu', 'id' => 3, 'title' => 'Titel #3', 'body' => 'Inhalt #3'],
+ ['locale' => 'cze', 'id' => 3, 'title' => 'Titulek #3', 'body' => 'Obsah #3'],
+ ];
+}
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/AssertIntegrationTestCase.php b/app/vendor/cakephp/cakephp/tests/Fixture/AssertIntegrationTestCase.php
index c6b14a8bb..aa87ac70a 100644
--- a/app/vendor/cakephp/cakephp/tests/Fixture/AssertIntegrationTestCase.php
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/AssertIntegrationTestCase.php
@@ -1,14 +1,30 @@
['type' => 'integer'],
+ 'locale' => ['type' => 'string', 'null' => false],
+ 'name' => ['type' => 'string', 'null' => false],
+ '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id', 'locale']]],
+ ];
+
+ /**
+ * records property
+ *
+ * @var array
+ */
+ public $records = [
+ ['locale' => 'eng', 'id' => 1, 'name' => 'May-rianoh'],
+ ];
+}
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/CommentsTranslationsFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/CommentsTranslationsFixture.php
new file mode 100644
index 000000000..37820761c
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/CommentsTranslationsFixture.php
@@ -0,0 +1,48 @@
+ ['type' => 'integer'],
+ 'locale' => ['type' => 'string', 'null' => false],
+ 'comment' => 'text',
+ '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id', 'locale']]],
+ ];
+
+ /**
+ * records property
+ *
+ * @var array
+ */
+ public $records = [
+ ['locale' => 'eng', 'id' => 1, 'comment' => 'Comment #1'],
+ ['locale' => 'eng', 'id' => 2, 'comment' => 'Comment #2'],
+ ['locale' => 'eng', 'id' => 3, 'comment' => 'Comment #3'],
+ ['locale' => 'eng', 'id' => 4, 'comment' => 'Comment #4'],
+ ['locale' => 'spa', 'id' => 4, 'comment' => 'Comentario #4'],
+ ];
+}
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/DatatypesFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/DatatypesFixture.php
index 1509625f7..bee22a1db 100644
--- a/app/vendor/cakephp/cakephp/tests/Fixture/DatatypesFixture.php
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/DatatypesFixture.php
@@ -26,7 +26,8 @@ class DatatypesFixture extends TestFixture
*/
public $fields = [
'id' => ['type' => 'biginteger'],
- 'cost' => ['type' => 'decimal', 'length' => 20, 'precision' => 0, 'null' => true],
+ 'cost' => ['type' => 'decimal', 'length' => 20, 'precision' => 1, 'null' => true],
+ 'fraction' => ['type' => 'decimal', 'length' => 20, 'precision' => 19, 'null' => true],
'floaty' => ['type' => 'float', 'null' => true],
'small' => ['type' => 'smallinteger', 'null' => true],
'tiny' => ['type' => 'tinyinteger', 'null' => true],
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/FixturizedTestCase.php b/app/vendor/cakephp/cakephp/tests/Fixture/FixturizedTestCase.php
index b68991626..a84a31c7e 100644
--- a/app/vendor/cakephp/cakephp/tests/Fixture/FixturizedTestCase.php
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/FixturizedTestCase.php
@@ -1,6 +1,20 @@
assertInstanceOf('Cake\TestSuite\Fixture\FixtureManager', $this->fixtureManager);
+ $this->assertInstanceOf(FixtureManager::class, $this->fixtureManager);
}
/**
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/GroupsTranslationsFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/GroupsTranslationsFixture.php
new file mode 100644
index 000000000..5d6496b17
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/GroupsTranslationsFixture.php
@@ -0,0 +1,42 @@
+ ['type' => 'integer'],
+ 'locale' => ['type' => 'string', 'null' => false],
+ 'title' => ['type' => 'string'],
+ '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id', 'locale']]],
+ ];
+
+ /**
+ * records property
+ *
+ * @var array
+ */
+ public $records = [];
+}
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/OrdersFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/OrdersFixture.php
index 43eca665b..065c31b7b 100644
--- a/app/vendor/cakephp/cakephp/tests/Fixture/OrdersFixture.php
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/OrdersFixture.php
@@ -22,7 +22,7 @@
class OrdersFixture extends TestFixture
{
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public $table = 'orders';
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/OtherArticlesFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/OtherArticlesFixture.php
index a5dc0bdc3..f5b4a60a1 100644
--- a/app/vendor/cakephp/cakephp/tests/Fixture/OtherArticlesFixture.php
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/OtherArticlesFixture.php
@@ -26,36 +26,41 @@ class OtherArticlesFixture implements FixtureInterface
{
public $table = 'other_articles';
- public function create(ConnectionInterface $db)
+ public function create(ConnectionInterface $db): bool
{
+ return true;
}
- public function drop(ConnectionInterface $db)
+ public function drop(ConnectionInterface $db): bool
{
+ return true;
}
public function insert(ConnectionInterface $db)
{
}
- public function createConstraints(ConnectionInterface $db)
+ public function createConstraints(ConnectionInterface $db): bool
{
+ return true;
}
- public function dropConstraints(ConnectionInterface $db)
+ public function dropConstraints(ConnectionInterface $db): bool
{
+ return true;
}
- public function truncate(ConnectionInterface $db)
+ public function truncate(ConnectionInterface $db): bool
{
+ return true;
}
- public function connection()
+ public function connection(): string
{
return 'other';
}
- public function sourceName()
+ public function sourceName(): string
{
return 'other_articles';
}
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/ProductsFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/ProductsFixture.php
index f770311ab..9dc14c8ce 100644
--- a/app/vendor/cakephp/cakephp/tests/Fixture/ProductsFixture.php
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/ProductsFixture.php
@@ -22,7 +22,7 @@
class ProductsFixture extends TestFixture
{
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public $table = 'products';
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/SpecialTagsTranslationsFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/SpecialTagsTranslationsFixture.php
new file mode 100644
index 000000000..99ead4dc7
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/SpecialTagsTranslationsFixture.php
@@ -0,0 +1,44 @@
+ ['type' => 'integer'],
+ 'locale' => ['type' => 'string', 'null' => false],
+ 'extra_info' => ['type' => 'string'],
+ '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id', 'locale']]],
+ ];
+
+ /**
+ * records property
+ *
+ * @var array
+ */
+ public $records = [
+ ['id' => 2, 'locale' => 'eng', 'extra_info' => 'Translated Info'],
+ ];
+}
diff --git a/app/vendor/cakephp/cakephp/tests/Fixture/TagsShadowTranslationsFixture.php b/app/vendor/cakephp/cakephp/tests/Fixture/TagsShadowTranslationsFixture.php
new file mode 100644
index 000000000..c4da12370
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/tests/Fixture/TagsShadowTranslationsFixture.php
@@ -0,0 +1,52 @@
+ ['type' => 'integer'],
+ 'locale' => ['type' => 'string', 'null' => false],
+ 'name' => ['type' => 'string', 'null' => false],
+ '_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id', 'locale']]],
+ ];
+
+ /**
+ * records property
+ *
+ * @var array
+ */
+ public $records = [
+ ['locale' => 'eng', 'id' => 1, 'name' => 'tag1 in eng'],
+ ['locale' => 'deu', 'id' => 1, 'name' => 'tag1 in deu'],
+ ['locale' => 'cze', 'id' => 1, 'name' => 'tag1 in cze'],
+ ['locale' => 'eng', 'id' => 2, 'name' => 'tag2 in eng'],
+ ['locale' => 'deu', 'id' => 2, 'name' => 'tag2 in deu'],
+ ['locale' => 'cze', 'id' => 2, 'name' => 'tag2 in cze'],
+ ['locale' => 'eng', 'id' => 3, 'name' => 'tag3 in eng'],
+ ['locale' => 'deu', 'id' => 3, 'name' => 'tag3 in deu'],
+ ['locale' => 'cze', 'id' => 3, 'name' => 'tag3 in cze'],
+ ];
+}
diff --git a/app/vendor/cakephp/cakephp/tests/bootstrap.php b/app/vendor/cakephp/cakephp/tests/bootstrap.php
index bb7ca5347..5da9a693e 100644
--- a/app/vendor/cakephp/cakephp/tests/bootstrap.php
+++ b/app/vendor/cakephp/cakephp/tests/bootstrap.php
@@ -1,4 +1,6 @@
'css/',
'paths' => [
'plugins' => [TEST_APP . 'Plugin' . DS],
- 'templates' => [APP . 'Template' . DS],
- 'locales' => [APP . 'Locale' . DS],
+ 'templates' => [TEST_APP . 'templates' . DS],
+ 'locales' => [TEST_APP . 'resources' . DS . 'locales' . DS],
],
]);
@@ -97,12 +96,12 @@
]);
// Ensure default test connection is defined
-if (!getenv('db_dsn')) {
- putenv('db_dsn=sqlite:///:memory:');
+if (!getenv('DB_DSN')) {
+ putenv('DB_DSN=sqlite:///:memory:');
}
-ConnectionManager::setConfig('test', ['url' => getenv('db_dsn')]);
-ConnectionManager::setConfig('test_custom_i18n_datasource', ['url' => getenv('db_dsn')]);
+ConnectionManager::setConfig('test', ['url' => getenv('DB_DSN')]);
+ConnectionManager::setConfig('test_custom_i18n_datasource', ['url' => getenv('DB_DSN')]);
Configure::write('Session', [
'defaults' => 'php',
@@ -129,14 +128,11 @@
]);
Chronos::setTestNow(Chronos::now());
+Security::setSalt('a-long-but-not-random-value');
ini_set('intl.default_locale', 'en_US');
ini_set('session.gc_divisor', '1');
-Security::setSalt('a-long-but-not-random-value');
-
-loadPHPUnitAliases();
-
// Fixate sessionid early on, as php7.2+
// does not allow the sessionid to be set after stdout
// has been written to.
diff --git a/app/vendor/cakephp/cakephp/tests/phpunit_aliases.php b/app/vendor/cakephp/cakephp/tests/phpunit_aliases.php
deleted file mode 100644
index aca6a057c..000000000
--- a/app/vendor/cakephp/cakephp/tests/phpunit_aliases.php
+++ /dev/null
@@ -1,23 +0,0 @@
-> php.ini
- - echo extension_dir=ext >> php.ini
- - echo extension=php_openssl.dll >> php.ini
- - cd C:\projects\chronos
- - appveyor DownloadFile https://getcomposer.org/composer.phar
- # phpstan requires php 7.0. While here used php 5.5 we can't install it
- - php composer.phar remove --dev phpstan/phpstan
- - php composer.phar install --prefer-dist --no-interaction --ansi --no-progress
-
-test_script:
- - cd C:\projects\chronos
- - vendor\bin\phpunit.bat
diff --git a/app/vendor/cakephp/chronos/README.md b/app/vendor/cakephp/chronos/README.md
index 5049973f5..e6467246d 100644
--- a/app/vendor/cakephp/chronos/README.md
+++ b/app/vendor/cakephp/chronos/README.md
@@ -1,9 +1,10 @@
# CakePHP Chronos
+
+[](https://packagist.org/packages/cakephp/chronos)
+[](https://packagist.org/packages/cakephp/chronos/stats)
+[](https://coveralls.io/r/cakephp/chronos?branch=master)
[](LICENSE)
-[](https://travis-ci.org/cakephp/chronos)
-[](https://coveralls.io/r/cakephp/chronos?branch=master)
-[](https://packagist.org/packages/cakephp/chronos)
Chronos aims to be a drop-in replacement for `nesbot/carbon`. It focuses on providing
immutable date/datetime objects. Immutable objects help ensure that datetime objects
@@ -37,16 +38,14 @@ since developers don't have to manually copy the instance every time they need a
Another important feature it offers is the `Date` class, which is used for representing dates without time (calendar dates).
Any time method called on this type of object is basically a no-op.
-A minor but still noticeable difference is that `Chronos` has no external dependencies, it is completely standalone.
-
There are other implementation changes, but one that users might not notice is ``Chronos`` considers Monday as
the start of the week instead of Sunday. This follows the ISO-8601 and current versions of PHP 5.6 and PHP 7.
+A minor but still noticeable difference is that `Chronos` has no external dependencies, it is completely standalone.
+
Finally, Chronos is faster than Carbon as it has been optimized for the creation of hundreds of instances with minimal
overhead.
-Chronos also strives for HHVM compatibility, this library can be used safely with HHVM 3.11.
-
# Migrating from Carbon
@@ -65,10 +64,12 @@ want to migrate, we could use the following to update files:
```
# Replace imports
find ./src -type f -name '*.php' -exec sed -i '' 's/use Carbon\\CarbonInterval/use Cake\\Chronos\\ChronosInterval/g' {} \;
+find ./src -type f -name '*.php' -exec sed -i '' 's/use Carbon\\CarbonImmutable/use Cake\\Chronos\\Chronos/g' {} \;
find ./src -type f -name '*.php' -exec sed -i '' 's/use Carbon\\Carbon/use Cake\\Chronos\\Chronos/g' {} \;
# Replace typehints and extensions
find ./src -type f -name '*.php' -exec sed -i '' 's/CarbonInterval/ChronosInterval/g' {} \;
+find ./src -type f -name '*.php' -exec sed -i '' 's/CarbonImmutable/Chronos/g' {} \;
find ./src -type f -name '*.php' -exec sed -i '' 's/Carbon/Chronos/g' {} \;
```
@@ -121,10 +122,11 @@ $fixed = $date->toImmutable();
# Calendar Dates
-PHP only offers datetime objects as part of the native extensions. Chronos
-adds a number of conveniences to the traditional DateTime object and introduces
-a `Date` object. `Date` instances offer compatibility with the `ChronosInterface`, but
-have their time & timezone frozen to `00:00:00 UTC`. This makes them ideal when working with
+PHP only offers datetime objects as part of the native extensions. Chronos adds
+a number of conveniences to the traditional DateTime object and introduces
+a `Date` object. `Date` instances offer compatibility with the
+`ChronosInterface`, but have their time frozen to `00:00:00` and the timezone
+set to the server default timezone. This makes them ideal when working with
calendar dates as the time components will always match.
```php
@@ -138,12 +140,12 @@ echo $today->modify('+3 hours');
// Outputs '2015-10-21'
```
-Like instances of `Chronos`, `Date` objects are also *immutable*. The `MutableDate` class provides
-a mutable variant of `Date`.
+Like instances of `Chronos`, `Date` objects are also *immutable*. The
+`MutableDate` class provides a mutable variant of `Date`.
# Documentation
-A more descriptive documentation can be found at [book.cakephp.org/chronos/1.x/en/](https://book.cakephp.org/chronos/1.x/en/).
+A more descriptive documentation can be found at [book.cakephp.org/chronos/2/en/](https://book.cakephp.org/chronos/2/en/).
# API Documentation
diff --git a/app/vendor/cakephp/chronos/composer.json b/app/vendor/cakephp/chronos/composer.json
index d63b28472..efce15054 100644
--- a/app/vendor/cakephp/chronos/composer.json
+++ b/app/vendor/cakephp/chronos/composer.json
@@ -1,62 +1,63 @@
{
- "name": "cakephp/chronos",
- "type": "library",
- "description": "A simple API extension for DateTime.",
- "keywords": [
- "date",
- "time",
- "DateTime"
- ],
- "homepage": "http://cakephp.org",
- "license": "MIT",
- "authors": [
- {
- "name": "Brian Nesbitt",
- "email": "brian@nesbot.com",
- "homepage": "http://nesbot.com"
+ "name": "cakephp/chronos",
+ "type": "library",
+ "description": "A simple API extension for DateTime.",
+ "keywords": [
+ "date",
+ "time",
+ "DateTime"
+ ],
+ "homepage": "http://cakephp.org",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "http://nesbot.com"
+ },
+ {
+ "name": "The CakePHP Team",
+ "homepage": "http://cakephp.org"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/cakephp/chronos/issues",
+ "irc": "irc://irc.freenode.org/cakephp",
+ "source": "https://github.com/cakephp/chronos"
},
- {
- "name": "The CakePHP Team",
- "homepage": "http://cakephp.org"
- }
- ],
- "support": {
- "issues": "https://github.com/cakephp/chronos/issues",
- "irc": "irc://irc.freenode.org/cakephp",
- "source": "https://github.com/cakephp/chronos"
- },
- "require": {
- "php": ">=5.6"
- },
- "require-dev": {
- "phpunit/phpunit": "<6.0 || ^7.0",
- "athletic/athletic": "~0.1",
- "cakephp/cakephp-codesniffer": "^3.0",
- "phpbench/phpbench": "@dev"
- },
- "autoload": {
- "psr-4": {
- "Cake\\Chronos\\": "src/"
+ "require": {
+ "php": ">=7.2"
},
- "files": ["src/carbon_compat.php"]
- },
- "autoload-dev": {
- "psr-4": {
- "Cake\\Chronos\\Test\\": "tests/"
+ "require-dev": {
+ "phpunit/phpunit": "^8.0 || ^9.0",
+ "cakephp/cakephp-codesniffer": "^4.5"
},
- "files": ["tests/TestCase.php"]
- },
- "scripts": {
- "check": [
- "@test",
- "@cs-check",
- "@phpstan"
- ],
- "test": "phpunit",
- "cs-check": "phpcs",
- "cs-fix": "phpcbf",
- "bench": "phpbench run",
- "phpstan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan-shim:^0.11 && mv composer.backup composer.json",
- "phpstan": "phpstan analyze -c phpstan.neon -l 3 src/"
- }
+ "autoload": {
+ "psr-4": {
+ "Cake\\Chronos\\": "src/"
+ },
+ "files": [
+ "src/carbon_compat.php"
+ ]
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Cake\\Chronos\\Test\\": "tests/"
+ }
+ },
+ "scripts": {
+ "check": [
+ "@test",
+ "@cs-check",
+ "@phpstan"
+ ],
+ "cs-check": "phpcs --colors --parallel=16 -p src/ tests/",
+ "cs-fix": "phpcbf --colors --parallel=16 -p src/ tests/",
+ "phpstan": "phpstan.phar analyse",
+ "stan": [
+ "@phpstan"
+ ],
+ "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12.54 && mv composer.backup composer.json",
+ "test": "phpunit"
+ }
}
diff --git a/app/vendor/cakephp/chronos/docs/config/all.py b/app/vendor/cakephp/chronos/docs/config/all.py
index c3103072e..4e6a657c6 100644
--- a/app/vendor/cakephp/chronos/docs/config/all.py
+++ b/app/vendor/cakephp/chronos/docs/config/all.py
@@ -10,10 +10,10 @@
#
# The full version, including alpha/beta/rc tags.
-release = '1.x'
+release = '2.x'
# The search index version.
-search_version = 'chronos-1'
+search_version = 'chronos-2'
# The marketing display name for the book.
version_name = ''
@@ -23,7 +23,8 @@
# Other versions that display in the version picker menu.
version_list = [
- {'name': '1.x', 'number': '/chronos/1.x', 'title': '1.x', 'current': True},
+ {'name': '1.x', 'number': '/chronos/1', 'title': '1.x'},
+ {'name': '2.x', 'number': '/chronos/2', 'title': '2.x', 'current': True},
]
# Languages available.
@@ -31,10 +32,10 @@
# The GitHub branch name for this version of the docs
# for edit links to point at.
-branch = 'master'
+branch = '2.x'
# Current version being built
-version = '1.x'
+version = '2.x'
# Language in use for this directory.
language = 'en'
diff --git a/app/vendor/cakephp/chronos/docs/en/index.rst b/app/vendor/cakephp/chronos/docs/en/index.rst
index 3cffdd9fc..dabb9b267 100644
--- a/app/vendor/cakephp/chronos/docs/en/index.rst
+++ b/app/vendor/cakephp/chronos/docs/en/index.rst
@@ -16,7 +16,7 @@ To install Chronos, you should use ``composer``. From your
application's ROOT directory (where composer.json file is located) run the
following::
- php composer.phar require cakephp/chronos "@stable"
+ php composer.phar require "cakephp/chronos:^2.0"
Overview
--------
@@ -111,6 +111,14 @@ methods operate at the day resolution::
// Outputs '2015-12-20'
echo $today;
+Although ``Date`` uses a fixed time zone internally, you can specify which
+time zone to use for current time such as ``now()`` or ``today()``::
+
+ use Cake\Chronos\Date:
+
+ // Takes the current date from Asia/Tokyo time zone
+ $today = Date::today('Asia/Tokyo');
+
Modifier Methods
----------------
@@ -265,19 +273,19 @@ Extracting Date Components
Getting parts of a date object can be done by directly accessing properties::
- $time = new Chronos('2015-12-31 23:59:58');
+ $time = new Chronos('2015-12-31 23:59:58.123');
$time->year; // 2015
$time->month; // 12
$time->day; // 31
$time->hour // 23
$time->minute // 59
$time->second // 58
+ $time->micro // 123
Other properties that can be accessed are:
- timezone
- timezoneName
-- micro
- dayOfWeek
- dayOfMonth
- dayOfYear
diff --git a/app/vendor/cakephp/chronos/src/Chronos.php b/app/vendor/cakephp/chronos/src/Chronos.php
index d39556327..f8ddf7384 100644
--- a/app/vendor/cakephp/chronos/src/Chronos.php
+++ b/app/vendor/cakephp/chronos/src/Chronos.php
@@ -1,4 +1,6 @@
format('Y-m-d H:i:s.u');
+ }
+
static::$_lastErrors = [];
$testNow = static::getTestNow();
if ($testNow === null) {
- parent::__construct($time === null ? 'now' : $time, $tz);
+ parent::__construct($time ?? 'now', $tz);
return;
}
@@ -106,13 +119,13 @@ public function __construct($time = 'now', $tz = null)
}
$testNow = clone $testNow;
- if ($relative) {
- $testNow = $testNow->modify($time);
+ $relativetime = static::isTimeExpression($time);
+ if (!$relativetime && $tz !== $testNow->getTimezone()) {
+ $testNow = $testNow->setTimezone($tz ?? date_default_timezone_get());
}
- $relativeTime = static::isTimeExpression($time);
- if (!$relativeTime && $tz !== $testNow->getTimezone()) {
- $testNow = $testNow->setTimezone($tz === null ? date_default_timezone_get() : $tz);
+ if ($relative) {
+ $testNow = $testNow->modify($time);
}
$time = $testNow->format('Y-m-d H:i:s.u');
@@ -124,7 +137,7 @@ public function __construct($time = 'now', $tz = null)
*
* @return \Cake\Chronos\MutableDateTime
*/
- public function toMutable()
+ public function toMutable(): MutableDateTime
{
return MutableDateTime::instance($this);
}
@@ -132,11 +145,11 @@ public function toMutable()
/**
* Get a copy of the instance
*
- * @return $this
+ * @return static
*/
- public function copy()
+ public function copy(): ChronosInterface
{
- return $this;
+ return clone $this;
}
/**
@@ -157,7 +170,7 @@ public function copy()
* @param \Cake\Chronos\ChronosInterface|string|null $testNow The instance to use for all future instances.
* @return void
*/
- public static function setTestNow($testNow = null)
+ public static function setTestNow($testNow = null): void
{
static::$testNow = is_string($testNow) ? static::parse($testNow) : $testNow;
}
@@ -166,9 +179,9 @@ public static function setTestNow($testNow = null)
* Get the ChronosInterface instance (real or mock) to be returned when a "now"
* instance is created.
*
- * @return \Cake\Chronos\ChronosInterface The current instance used for testing
+ * @return \Cake\Chronos\ChronosInterface|null The current instance used for testing
*/
- public static function getTestNow()
+ public static function getTestNow(): ?ChronosInterface
{
return static::$testNow;
}
@@ -179,7 +192,7 @@ public static function getTestNow()
*
* @return bool True if there is a test instance, otherwise false
*/
- public static function hasTestNow()
+ public static function hasTestNow(): bool
{
return static::$testNow !== null;
}
@@ -189,7 +202,7 @@ public static function hasTestNow()
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$properties = [
'hasFixedNow' => static::hasTestNow(),
diff --git a/app/vendor/cakephp/chronos/src/ChronosInterface.php b/app/vendor/cakephp/chronos/src/ChronosInterface.php
index d73c7a1cd..f074b4c15 100644
--- a/app/vendor/cakephp/chronos/src/ChronosInterface.php
+++ b/app/vendor/cakephp/chronos/src/ChronosInterface.php
@@ -1,4 +1,6 @@
and < comparison should be used or <= or >=
* @return bool
*/
- public function between(ChronosInterface $dt1, ChronosInterface $dt2, $equal = true);
+ public function between(ChronosInterface $dt1, ChronosInterface $dt2, bool $equal = true): bool;
/**
* Get the closest date from the instance.
@@ -400,7 +443,7 @@ public function between(ChronosInterface $dt1, ChronosInterface $dt2, $equal = t
* @param \Cake\Chronos\ChronosInterface $dt2 The instance to compare with.
* @return static
*/
- public function closest(ChronosInterface $dt1, ChronosInterface $dt2);
+ public function closest(ChronosInterface $dt1, ChronosInterface $dt2): self;
/**
* Get the farthest date from the instance.
@@ -409,7 +452,7 @@ public function closest(ChronosInterface $dt1, ChronosInterface $dt2);
* @param \Cake\Chronos\ChronosInterface $dt2 The instance to compare with.
* @return static
*/
- public function farthest(ChronosInterface $dt1, ChronosInterface $dt2);
+ public function farthest(ChronosInterface $dt1, ChronosInterface $dt2): self;
/**
* Get the minimum instance between a given instance (default now) and the current instance.
@@ -417,7 +460,7 @@ public function farthest(ChronosInterface $dt1, ChronosInterface $dt2);
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with.
* @return static
*/
- public function min(ChronosInterface $dt = null);
+ public function min(?ChronosInterface $dt = null): self;
/**
* Get the maximum instance between a given instance (default now) and the current instance.
@@ -425,63 +468,63 @@ public function min(ChronosInterface $dt = null);
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with.
* @return static
*/
- public function max(ChronosInterface $dt = null);
+ public function max(?ChronosInterface $dt = null): self;
/**
* Determines if the instance is a weekday
*
* @return bool
*/
- public function isWeekday();
+ public function isWeekday(): bool;
/**
* Determines if the instance is a weekend day
*
* @return bool
*/
- public function isWeekend();
+ public function isWeekend(): bool;
/**
* Determines if the instance is yesterday
*
* @return bool
*/
- public function isYesterday();
+ public function isYesterday(): bool;
/**
* Determines if the instance is today
*
* @return bool
*/
- public function isToday();
+ public function isToday(): bool;
/**
* Determines if the instance is tomorrow
*
* @return bool
*/
- public function isTomorrow();
+ public function isTomorrow(): bool;
/**
* Determines if the instance is in the future, ie. greater (after) than now
*
* @return bool
*/
- public function isFuture();
+ public function isFuture(): bool;
/**
* Determines if the instance is in the past, ie. less (before) than now
*
* @return bool
*/
- public function isPast();
+ public function isPast(): bool;
/**
* Determines if the instance is a leap year
*
* @return bool
*/
- public function isLeapYear();
+ public function isLeapYear(): bool;
/**
* Checks if the passed in date is the same day as the instance current day.
@@ -489,224 +532,271 @@ public function isLeapYear();
* @param \Cake\Chronos\ChronosInterface $dt The instance to check against.
* @return bool
*/
- public function isSameDay(ChronosInterface $dt);
+ public function isSameDay(ChronosInterface $dt): bool;
/**
* Checks if this day is a Sunday.
*
* @return bool
*/
- public function isSunday();
+ public function isSunday(): bool;
/**
* Checks if this day is a Monday.
*
* @return bool
*/
- public function isMonday();
+ public function isMonday(): bool;
/**
* Checks if this day is a Tuesday.
*
* @return bool
*/
- public function isTuesday();
+ public function isTuesday(): bool;
/**
* Checks if this day is a Wednesday.
*
* @return bool
*/
- public function isWednesday();
+ public function isWednesday(): bool;
/**
* Checks if this day is a Thursday.
*
* @return bool
*/
- public function isThursday();
+ public function isThursday(): bool;
/**
* Checks if this day is a Friday.
*
* @return bool
*/
- public function isFriday();
+ public function isFriday(): bool;
/**
* Checks if this day is a Saturday.
*
* @return bool
*/
- public function isSaturday();
+ public function isSaturday(): bool;
/**
* Returns true if this object represents a date within the current week
*
* @return bool
*/
- public function isThisWeek();
+ public function isThisWeek(): bool;
/**
* Returns true if this object represents a date within the current month
*
* @return bool
*/
- public function isThisMonth();
+ public function isThisMonth(): bool;
/**
* Returns true if this object represents a date within the current year
*
* @return bool
*/
- public function isThisYear();
+ public function isThisYear(): bool;
/**
* Add years to the instance. Positive $value travel forward while
* negative $value travel into the past.
*
+ * If the new date does not exist, the last day of the month is used
+ * instead instead of overflowing into the next month.
+ *
+ * ### Example:
+ *
+ * ```
+ * (new Chronos('2015-01-03'))->addYears(1); // Results in 2016-01-03
+ *
+ * (new Chronos('2012-02-29'))->addYears(1); // Results in 2013-02-28
+ * ```
+ *
* @param int $value The number of years to add.
* @return static
*/
- public function addYears($value);
+ public function addYears(int $value): self;
/**
* Add a year to the instance
*
+ * Has the same behavior as `addYears()`.
+ *
* @param int $value The number of years to add.
* @return static
*/
- public function addYear($value = 1);
+ public function addYear(int $value = 1): self;
/**
- * Remove a year from the instance
+ * Remove years from the instance.
+ *
+ * Has the same behavior as `addYears()`.
*
* @param int $value The number of years to remove.
* @return static
*/
- public function subYear($value = 1);
+ public function subYears(int $value): self;
/**
- * Remove years from the instance.
+ * Remove a year from the instance.
+ *
+ * Has the same behavior as `addYears()`.
*
* @param int $value The number of years to remove.
* @return static
*/
- public function subYears($value);
+ public function subYear(int $value = 1): self;
/**
- * Add months to the instance. Positive $value travels forward while
- * negative $value travels into the past.
+ * Add years with overflowing to the instance. Positive $value
+ * travels forward while negative $value travels into the past.
*
- * When adding or subtracting months, if the resulting time is a date
- * that does not exist, the result of this operation will always be the
- * last day of the intended month.
+ * If the new date does not exist, the days overflow into the next month.
*
* ### Example:
*
* ```
- * (new Chronos('2015-01-03'))->addMonths(1); // Results in 2015-02-03
- *
- * (new Chronos('2015-01-31'))->addMonths(1); // Results in 2015-02-28
+ * (new Chronos('2012-02-29'))->addYearsWithOverflow(1); // Results in 2013-03-01
* ```
*
- * @param int $value The number of months to add.
+ * @param int $value The number of years to add.
* @return static
*/
- public function addMonths($value);
+ public function addYearsWithOverflow(int $value): self;
/**
- * Add a month to the instance
+ * Add a year with overflow to the instance
*
- * When adding or subtracting months, if the resulting time is a date
- * that does not exist, the result of this operation will always be the
- * last day of the intended month.
+ * Has the same behavior as `addYearsWithOverflow()`.
*
- * ### Example:
+ * @param int $value The number of years to add.
+ * @return static
+ */
+ public function addYearWithOverflow(int $value = 1): self;
+
+ /**
+ * Remove years with overflow from the instance
*
- * ```
- * (new Chronos('2015-01-03'))->addMonth(); // Results in 2015-02-03
+ * Has the same behavior as `addYearsWithOverflow()`.
*
- * (new Chronos('2015-01-31'))->addMonth(); // Results in 2015-02-28
- * ```
+ * @param int $value The number of years to remove.
+ * @return static
+ */
+ public function subYearsWithOverflow(int $value): self;
+
+ /**
+ * Remove a year with overflow from the instance
*
- * @param int $value The number of months to add.
+ * Has the same behavior as `addYearsWithOverflow()`.
+ *
+ * @param int $value The number of years to remove.
* @return static
*/
- public function addMonth($value = 1);
+ public function subYearWithOverflow(int $value = 1): self;
/**
- * Remove a month from the instance
+ * Add months to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
*
- * When adding or subtracting months, if the resulting time is a date
- * that does not exist, the result of this operation will always be the
- * last day of the intended month.
+ * If the new date does not exist, the last day of the month is used
+ * instead instead of overflowing into the next month.
*
* ### Example:
*
* ```
- * (new Chronos('2015-03-01'))->subMonth(); // Results in 2015-02-01
+ * (new Chronos('2015-01-03'))->addMonths(1); // Results in 2015-02-03
*
- * (new Chronos('2015-03-31'))->subMonth(); // Results in 2015-02-28
+ * (new Chronos('2015-01-31'))->addMonths(1); // Results in 2015-02-28
* ```
*
- * @param int $value The number of months to remove.
+ * @param int $value The number of months to add.
* @return static
*/
- public function subMonth($value = 1);
+ public function addMonths(int $value): self;
/**
- * Remove months from the instance
+ * Add a month to the instance.
*
- * When adding or subtracting months, if the resulting time is a date
- * that does not exist, the result of this operation will always be the
- * last day of the intended month.
+ * Has the same behavior as `addMonths()`.
*
- * ### Example:
+ * @param int $value The number of months to add.
+ * @return static
+ */
+ public function addMonth(int $value = 1): self;
+
+ /**
+ * Remove a month from the instance
*
- * ```
- * (new Chronos('2015-03-01'))->subMonths(1); // Results in 2015-02-01
+ * Has the same behavior as `addMonths()`.
*
- * (new Chronos('2015-03-31'))->subMonths(1); // Results in 2015-02-28
- * ```
+ * @param int $value The number of months to remove.
+ * @return static
+ */
+ public function subMonth(int $value = 1): self;
+
+ /**
+ * Remove months from the instance.
+ *
+ * Has the same behavior as `addMonths()`.
*
* @param int $value The number of months to remove.
* @return static
*/
- public function subMonths($value);
+ public function subMonths(int $value): self;
/**
* Add months with overflowing to the instance. Positive $value
* travels forward while negative $value travels into the past.
*
+ * If the new date does not exist, the days overflow into the next month.
+ *
+ * ### Example:
+ *
+ * ```
+ * (new Chronos('2012-01-30'))->addMonthsWithOverflow(1); // Results in 2013-03-01
+ * ```
+ *
* @param int $value The number of months to add.
* @return static
*/
- public function addMonthsWithOverflow($value);
+ public function addMonthsWithOverflow(int $value): self;
/**
- * Add a month with overflow to the instance
+ * Add a month with overflow to the instance.
+ *
+ * Has the same behavior as `addMonthsWithOverflow()`.
*
* @param int $value The number of months to add.
* @return static
*/
- public function addMonthWithOverflow($value = 1);
+ public function addMonthWithOverflow(int $value = 1): self;
/**
- * Remove a month with overflow from the instance
+ * Remove months with overflow from the instance.
+ *
+ * Has the same behavior as `addMonthsWithOverflow()`.
*
* @param int $value The number of months to remove.
* @return static
*/
- public function subMonthWithOverflow($value = 1);
+ public function subMonthsWithOverflow(int $value): self;
/**
- * Remove months with overflow from the instance
+ * Remove a month with overflow from the instance.
+ *
+ * Has the same behavior as `addMonthsWithOverflow()`.
*
* @param int $value The number of months to remove.
* @return static
*/
- public function subMonthsWithOverflow($value);
+ public function subMonthWithOverflow(int $value = 1): self;
/**
* Add days to the instance. Positive $value travels forward while
@@ -715,7 +805,7 @@ public function subMonthsWithOverflow($value);
* @param int $value The number of days to add.
* @return static
*/
- public function addDays($value);
+ public function addDays(int $value): self;
/**
* Add a day to the instance
@@ -723,23 +813,23 @@ public function addDays($value);
* @param int $value The number of days to add.
* @return static
*/
- public function addDay($value = 1);
+ public function addDay(int $value = 1): self;
/**
- * Remove a day from the instance
+ * Remove days from the instance
*
* @param int $value The number of days to remove.
* @return static
*/
- public function subDay($value = 1);
+ public function subDays(int $value): self;
/**
- * Remove days from the instance
+ * Remove a day from the instance
*
* @param int $value The number of days to remove.
* @return static
*/
- public function subDays($value);
+ public function subDay(int $value = 1): self;
/**
* Add weekdays to the instance. Positive $value travels forward while
@@ -748,7 +838,7 @@ public function subDays($value);
* @param int $value The number of weekdays to add.
* @return static
*/
- public function addWeekdays($value);
+ public function addWeekdays(int $value): self;
/**
* Add a weekday to the instance
@@ -756,7 +846,7 @@ public function addWeekdays($value);
* @param int $value The number of weekdays to add.
* @return static
*/
- public function addWeekday($value = 1);
+ public function addWeekday(int $value = 1): self;
/**
* Remove a weekday from the instance
@@ -764,7 +854,7 @@ public function addWeekday($value = 1);
* @param int $value The number of weekdays to remove.
* @return static
*/
- public function subWeekday($value = 1);
+ public function subWeekday(int $value = 1): self;
/**
* Remove weekdays from the instance
@@ -772,7 +862,7 @@ public function subWeekday($value = 1);
* @param int $value The number of weekdays to remove.
* @return static
*/
- public function subWeekdays($value);
+ public function subWeekdays(int $value): self;
/**
* Add weeks to the instance. Positive $value travels forward while
@@ -781,7 +871,7 @@ public function subWeekdays($value);
* @param int $value The number of weeks to add.
* @return static
*/
- public function addWeeks($value);
+ public function addWeeks(int $value): self;
/**
* Add a week to the instance
@@ -789,7 +879,7 @@ public function addWeeks($value);
* @param int $value The number of weeks to add.
* @return static
*/
- public function addWeek($value = 1);
+ public function addWeek(int $value = 1): self;
/**
* Remove a week from the instance
@@ -797,7 +887,7 @@ public function addWeek($value = 1);
* @param int $value The number of weeks to remove.
* @return static
*/
- public function subWeek($value = 1);
+ public function subWeek(int $value = 1): self;
/**
* Remove weeks to the instance
@@ -805,7 +895,7 @@ public function subWeek($value = 1);
* @param int $value The number of weeks to remove.
* @return static
*/
- public function subWeeks($value);
+ public function subWeeks(int $value): self;
/**
* Add hours to the instance. Positive $value travels forward while
@@ -814,7 +904,7 @@ public function subWeeks($value);
* @param int $value The number of hours to add.
* @return static
*/
- public function addHours($value);
+ public function addHours(int $value): self;
/**
* Add an hour to the instance
@@ -822,7 +912,7 @@ public function addHours($value);
* @param int $value The number of hours to add.
* @return static
*/
- public function addHour($value = 1);
+ public function addHour(int $value = 1): self;
/**
* Remove an hour from the instance
@@ -830,7 +920,7 @@ public function addHour($value = 1);
* @param int $value The number of hours to remove.
* @return static
*/
- public function subHour($value = 1);
+ public function subHour(int $value = 1): self;
/**
* Remove hours from the instance
@@ -838,7 +928,7 @@ public function subHour($value = 1);
* @param int $value The number of hours to remove.
* @return static
*/
- public function subHours($value);
+ public function subHours(int $value): self;
/**
* Add minutes to the instance. Positive $value travels forward while
@@ -847,7 +937,7 @@ public function subHours($value);
* @param int $value The number of minutes to add.
* @return static
*/
- public function addMinutes($value);
+ public function addMinutes(int $value): self;
/**
* Add a minute to the instance
@@ -855,7 +945,7 @@ public function addMinutes($value);
* @param int $value The number of minutes to add.
* @return static
*/
- public function addMinute($value = 1);
+ public function addMinute(int $value = 1): self;
/**
* Remove a minute from the instance
@@ -863,7 +953,7 @@ public function addMinute($value = 1);
* @param int $value The number of minutes to remove.
* @return static
*/
- public function subMinute($value = 1);
+ public function subMinute(int $value = 1): self;
/**
* Remove minutes from the instance
@@ -871,7 +961,7 @@ public function subMinute($value = 1);
* @param int $value The number of minutes to remove.
* @return static
*/
- public function subMinutes($value);
+ public function subMinutes(int $value): self;
/**
* Add seconds to the instance. Positive $value travels forward while
@@ -880,7 +970,7 @@ public function subMinutes($value);
* @param int $value The number of seconds to add.
* @return static
*/
- public function addSeconds($value);
+ public function addSeconds(int $value): self;
/**
* Add a second to the instance
@@ -888,7 +978,7 @@ public function addSeconds($value);
* @param int $value The number of seconds to add.
* @return static
*/
- public function addSecond($value = 1);
+ public function addSecond(int $value = 1): self;
/**
* Remove a second from the instance
@@ -896,7 +986,7 @@ public function addSecond($value = 1);
* @param int $value The number of seconds to remove.
* @return static
*/
- public function subSecond($value = 1);
+ public function subSecond(int $value = 1): self;
/**
* Remove seconds from the instance
@@ -904,7 +994,7 @@ public function subSecond($value = 1);
* @param int $value The number of seconds to remove.
* @return static
*/
- public function subSeconds($value);
+ public function subSeconds(int $value): self;
/**
* Get the difference in a human readable format in the current locale.
@@ -929,7 +1019,7 @@ public function subSeconds($value);
* @param bool $absolute Removes time difference modifiers ago, after, etc
* @return string
*/
- public function diffForHumans(ChronosInterface $other = null, $absolute = false);
+ public function diffForHumans(?ChronosInterface $other = null, bool $absolute = false): string;
/**
* Get the difference in years
@@ -938,7 +1028,7 @@ public function diffForHumans(ChronosInterface $other = null, $absolute = false)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInYears(ChronosInterface $dt = null, $abs = true);
+ public function diffInYears(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in months
@@ -947,7 +1037,7 @@ public function diffInYears(ChronosInterface $dt = null, $abs = true);
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInMonths(ChronosInterface $dt = null, $abs = true);
+ public function diffInMonths(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in weeks
@@ -956,7 +1046,7 @@ public function diffInMonths(ChronosInterface $dt = null, $abs = true);
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInWeeks(ChronosInterface $dt = null, $abs = true);
+ public function diffInWeeks(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in days
@@ -965,7 +1055,7 @@ public function diffInWeeks(ChronosInterface $dt = null, $abs = true);
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInDays(ChronosInterface $dt = null, $abs = true);
+ public function diffInDays(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in days using a filter callable
@@ -975,7 +1065,7 @@ public function diffInDays(ChronosInterface $dt = null, $abs = true);
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInDaysFiltered(callable $callback, ChronosInterface $dt = null, $abs = true);
+ public function diffInDaysFiltered(callable $callback, ?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in hours using a filter callable
@@ -985,7 +1075,7 @@ public function diffInDaysFiltered(callable $callback, ChronosInterface $dt = nu
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInHoursFiltered(callable $callback, ChronosInterface $dt = null, $abs = true);
+ public function diffInHoursFiltered(callable $callback, ?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference by the given interval using a filter callable
@@ -996,7 +1086,12 @@ public function diffInHoursFiltered(callable $callback, ChronosInterface $dt = n
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffFiltered(ChronosInterval $ci, callable $callback, ChronosInterface $dt = null, $abs = true);
+ public function diffFiltered(
+ ChronosInterval $ci,
+ callable $callback,
+ ?ChronosInterface $dt = null,
+ bool $abs = true
+ ): int;
/**
* Get the difference in weekdays
@@ -1005,7 +1100,7 @@ public function diffFiltered(ChronosInterval $ci, callable $callback, ChronosInt
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInWeekdays(ChronosInterface $dt = null, $abs = true);
+ public function diffInWeekdays(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in weekend days using a filter
@@ -1014,7 +1109,7 @@ public function diffInWeekdays(ChronosInterface $dt = null, $abs = true);
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInWeekendDays(ChronosInterface $dt = null, $abs = true);
+ public function diffInWeekendDays(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in hours
@@ -1023,7 +1118,7 @@ public function diffInWeekendDays(ChronosInterface $dt = null, $abs = true);
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInHours(ChronosInterface $dt = null, $abs = true);
+ public function diffInHours(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in minutes
@@ -1032,7 +1127,7 @@ public function diffInHours(ChronosInterface $dt = null, $abs = true);
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInMinutes(ChronosInterface $dt = null, $abs = true);
+ public function diffInMinutes(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* Get the difference in seconds
@@ -1041,105 +1136,105 @@ public function diffInMinutes(ChronosInterface $dt = null, $abs = true);
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInSeconds(ChronosInterface $dt = null, $abs = true);
+ public function diffInSeconds(?ChronosInterface $dt = null, bool $abs = true): int;
/**
* The number of seconds since midnight.
*
* @return int
*/
- public function secondsSinceMidnight();
+ public function secondsSinceMidnight(): int;
/**
* The number of seconds until 23:59:59.
*
* @return int
*/
- public function secondsUntilEndOfDay();
+ public function secondsUntilEndOfDay(): int;
/**
* Resets the time to 00:00:00
*
* @return static
*/
- public function startOfDay();
+ public function startOfDay(): self;
/**
* Resets the time to 23:59:59
*
* @return static
*/
- public function endOfDay();
+ public function endOfDay(): self;
/**
* Resets the date to the first day of the month and the time to 00:00:00
*
* @return static
*/
- public function startOfMonth();
+ public function startOfMonth(): self;
/**
* Resets the date to end of the month and time to 23:59:59
*
* @return static
*/
- public function endOfMonth();
+ public function endOfMonth(): self;
/**
* Resets the date to the first day of the year and the time to 00:00:00
*
* @return static
*/
- public function startOfYear();
+ public function startOfYear(): self;
/**
* Resets the date to end of the year and time to 23:59:59
*
* @return static
*/
- public function endOfYear();
+ public function endOfYear(): self;
/**
* Resets the date to the first day of the decade and the time to 00:00:00
*
* @return static
*/
- public function startOfDecade();
+ public function startOfDecade(): self;
/**
* Resets the date to end of the decade and time to 23:59:59
*
* @return static
*/
- public function endOfDecade();
+ public function endOfDecade(): self;
/**
* Resets the date to the first day of the century and the time to 00:00:00
*
* @return static
*/
- public function startOfCentury();
+ public function startOfCentury(): self;
/**
* Resets the date to end of the century and time to 23:59:59
*
* @return static
*/
- public function endOfCentury();
+ public function endOfCentury(): self;
/**
* Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00
*
* @return static
*/
- public function startOfWeek();
+ public function startOfWeek(): self;
/**
* Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59
*
* @return static
*/
- public function endOfWeek();
+ public function endOfWeek(): self;
/**
* Modify to the next occurrence of a given day of the week.
@@ -1147,10 +1242,10 @@ public function endOfWeek();
* of the current day of the week. Use the supplied consts
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int $dayOfWeek The day of the week to move to.
+ * @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function next($dayOfWeek = null);
+ public function next(?int $dayOfWeek = null);
/**
* Modify to the previous occurrence of a given day of the week.
@@ -1158,10 +1253,10 @@ public function next($dayOfWeek = null);
* of the current day of the week. Use the supplied consts
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int $dayOfWeek The day of the week to move to.
+ * @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function previous($dayOfWeek = null);
+ public function previous(?int $dayOfWeek = null);
/**
* Modify to the first occurrence of a given day of the week
@@ -1169,10 +1264,10 @@ public function previous($dayOfWeek = null);
* first day of the current month. Use the supplied consts
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int $dayOfWeek The day of the week to move to.
+ * @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function firstOfMonth($dayOfWeek = null);
+ public function firstOfMonth(?int $dayOfWeek = null);
/**
* Modify to the last occurrence of a given day of the week
@@ -1180,10 +1275,10 @@ public function firstOfMonth($dayOfWeek = null);
* last day of the current month. Use the supplied consts
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int $dayOfWeek The day of the week to move to.
+ * @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function lastOfMonth($dayOfWeek = null);
+ public function lastOfMonth(?int $dayOfWeek = null);
/**
* Modify to the given occurrence of a given day of the week
@@ -1195,7 +1290,7 @@ public function lastOfMonth($dayOfWeek = null);
* @param int $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function nthOfMonth($nth, $dayOfWeek);
+ public function nthOfMonth(int $nth, int $dayOfWeek);
/**
* Modify to the first occurrence of a given day of the week
@@ -1203,10 +1298,10 @@ public function nthOfMonth($nth, $dayOfWeek);
* first day of the current quarter. Use the supplied consts
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int $dayOfWeek The day of the week to move to.
+ * @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function firstOfQuarter($dayOfWeek = null);
+ public function firstOfQuarter(?int $dayOfWeek = null);
/**
* Modify to the last occurrence of a given day of the week
@@ -1214,10 +1309,10 @@ public function firstOfQuarter($dayOfWeek = null);
* last day of the current quarter. Use the supplied consts
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int $dayOfWeek The day of the week to move to.
+ * @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function lastOfQuarter($dayOfWeek = null);
+ public function lastOfQuarter(?int $dayOfWeek = null);
/**
* Modify to the given occurrence of a given day of the week
@@ -1229,7 +1324,7 @@ public function lastOfQuarter($dayOfWeek = null);
* @param int $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function nthOfQuarter($nth, $dayOfWeek);
+ public function nthOfQuarter(int $nth, int $dayOfWeek);
/**
* Modify to the first occurrence of a given day of the week
@@ -1237,10 +1332,10 @@ public function nthOfQuarter($nth, $dayOfWeek);
* first day of the current year. Use the supplied consts
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int $dayOfWeek The day of the week to move to.
+ * @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function firstOfYear($dayOfWeek = null);
+ public function firstOfYear(?int $dayOfWeek = null);
/**
* Modify to the last occurrence of a given day of the week
@@ -1248,10 +1343,10 @@ public function firstOfYear($dayOfWeek = null);
* last day of the current year. Use the supplied consts
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int $dayOfWeek The day of the week to move to.
+ * @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function lastOfYear($dayOfWeek = null);
+ public function lastOfYear(?int $dayOfWeek = null);
/**
* Modify to the given occurrence of a given day of the week
@@ -1263,7 +1358,7 @@ public function lastOfYear($dayOfWeek = null);
* @param int $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function nthOfYear($nth, $dayOfWeek);
+ public function nthOfYear(int $nth, int $dayOfWeek);
/**
* Modify the current instance to the average of a given instance (default now) and the current instance.
@@ -1271,7 +1366,7 @@ public function nthOfYear($nth, $dayOfWeek);
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return static
*/
- public function average(ChronosInterface $dt = null);
+ public function average(?ChronosInterface $dt = null): self;
/**
* Check if its the birthday. Compares the date/month values of the two dates.
@@ -1279,7 +1374,7 @@ public function average(ChronosInterface $dt = null);
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
- public function isBirthday(ChronosInterface $dt);
+ public function isBirthday(ChronosInterface $dt): bool;
/**
* Returns true this instance happened within the specified interval
@@ -1288,7 +1383,7 @@ public function isBirthday(ChronosInterface $dt);
* Example of valid types: 6 hours, 2 days, 1 minute.
* @return bool
*/
- public function wasWithinLast($timeInterval);
+ public function wasWithinLast($timeInterval): bool;
/**
* Returns true this instance will happen within the specified interval
@@ -1297,12 +1392,12 @@ public function wasWithinLast($timeInterval);
* Example of valid types: 6 hours, 2 days, 1 minute.
* @return bool
*/
- public function isWithinNext($timeInterval);
+ public function isWithinNext($timeInterval): bool;
/**
* Check if instance of ChronosInterface is mutable.
*
* @return bool
*/
- public function isMutable();
+ public function isMutable(): bool;
}
diff --git a/app/vendor/cakephp/chronos/src/ChronosInterval.php b/app/vendor/cakephp/chronos/src/ChronosInterval.php
index a10d9342f..4f4464326 100644
--- a/app/vendor/cakephp/chronos/src/ChronosInterval.php
+++ b/app/vendor/cakephp/chronos/src/ChronosInterval.php
@@ -1,4 +1,6 @@
days !== false && $interval->days !== static::PHP_DAYS_FALSE);
+ return $interval->days !== false;
}
/**
@@ -104,9 +107,18 @@ protected static function wasCreatedFromDiff(DateInterval $interval)
* @param int|null $hours The hours to use.
* @param int|null $minutes The minutes to use.
* @param int|null $seconds The seconds to use.
+ * @param int|null $microseconds The microseconds to use.
*/
- public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null)
- {
+ public function __construct(
+ ?int $years = 1,
+ ?int $months = null,
+ ?int $weeks = null,
+ ?int $days = null,
+ ?int $hours = null,
+ ?int $minutes = null,
+ ?int $seconds = null,
+ ?int $microseconds = null
+ ) {
$spec = static::PERIOD_PREFIX;
$spec .= $years > 0 ? $years . static::PERIOD_YEARS : '';
@@ -116,7 +128,7 @@ public function __construct($years = 1, $months = null, $weeks = null, $days = n
$specDays += $weeks > 0 ? $weeks * ChronosInterface::DAYS_PER_WEEK : 0;
$specDays += $days > 0 ? $days : 0;
- $spec .= ($specDays > 0) ? $specDays . static::PERIOD_DAYS : '';
+ $spec .= $specDays > 0 ? $specDays . static::PERIOD_DAYS : '';
if ($spec === static::PERIOD_PREFIX) {
$spec .= '0' . static::PERIOD_YEARS;
@@ -130,6 +142,10 @@ public function __construct($years = 1, $months = null, $weeks = null, $days = n
}
parent::__construct($spec);
+
+ if ($microseconds > 0) {
+ $this->f = $microseconds / 1000000;
+ }
}
/**
@@ -145,11 +161,20 @@ public function __construct($years = 1, $months = null, $weeks = null, $days = n
* @param int|null $hours The hours to use.
* @param int|null $minutes The minutes to use.
* @param int|null $seconds The seconds to use.
+ * @param int|null $microseconds The microseconds to use.
* @return static
*/
- public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null)
- {
- return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds);
+ public static function create(
+ ?int $years = 1,
+ ?int $months = null,
+ ?int $weeks = null,
+ ?int $days = null,
+ ?int $hours = null,
+ ?int $minutes = null,
+ ?int $seconds = null,
+ ?int $microseconds = null
+ ): self {
+ return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
}
/**
@@ -168,7 +193,7 @@ public static function create($years = 1, $months = null, $weeks = null, $days =
* @param array $args Contains the value to use.
* @return static
*/
- public static function __callStatic($name, $args)
+ public static function __callStatic(string $name, array $args): self
{
$arg = count($args) === 0 ? 1 : $args[0];
@@ -201,7 +226,13 @@ public static function __callStatic($name, $args)
case 'seconds':
case 'second':
return new static(null, null, null, null, null, null, $arg);
+
+ case 'microseconds':
+ case 'microsecond':
+ return new static(null, null, null, null, null, null, null, $arg);
}
+
+ throw new BadMethodCallException(sprintf('Cannot create interval with `%s` units', $name));
}
/**
@@ -213,15 +244,16 @@ public static function __callStatic($name, $args)
* @throws \InvalidArgumentException
* @return static
*/
- public static function instance(DateInterval $di)
+ public static function instance(DateInterval $di): self
{
if (static::wasCreatedFromDiff($di)) {
throw new InvalidArgumentException(
- "Can not instance a DateInterval object created from DateTime::diff()."
+ 'Can not instance a DateInterval object created from DateTime::diff().'
);
}
$instance = new static($di->y, $di->m, 0, $di->d, $di->h, $di->i, $di->s);
+ $instance->f = $di->f;
$instance->invert = $di->invert;
$instance->days = $di->days;
@@ -235,7 +267,7 @@ public static function instance(DateInterval $di)
* @throws \InvalidArgumentException
* @return int
*/
- public function __get($name)
+ public function __get(string $name)
{
switch ($name) {
case 'years':
@@ -256,22 +288,16 @@ public function __get($name)
case 'seconds':
return $this->s;
+ case 'microseconds':
+ return (int)($this->f * 1000000);
+
case 'weeks':
return (int)floor($this->d / ChronosInterface::DAYS_PER_WEEK);
case 'daysExcludeWeeks':
case 'dayzExcludeWeeks':
return $this->dayz % ChronosInterface::DAYS_PER_WEEK;
- case 'days':
- return $this->days;
- case 'y':
- case 'm':
- case 'd':
- case 'h':
- case 'i':
- case 's':
- case 'invert':
- return parent::__get($name);
+
default:
throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
}
@@ -285,7 +311,7 @@ public function __get($name)
* @return void
* @throws \InvalidArgumentException
*/
- public function __set($name, $val)
+ public function __set(string $name, $val): void
{
switch ($name) {
case 'years':
@@ -317,6 +343,10 @@ public function __set($name, $val)
$this->s = $val;
break;
+ case 'microseconds':
+ $this->f = $val / 1000000;
+ break;
+
case 'invert':
$this->invert = $val;
break;
@@ -328,9 +358,9 @@ public function __set($name, $val)
*
* @param int $weeks Number of weeks to set
* @param int $days Number of days to set
- * @return static
+ * @return $this
*/
- public function weeksAndDays($weeks, $days)
+ public function weeksAndDays(int $weeks, int $days)
{
$this->dayz = ($weeks * ChronosInterface::DAYS_PER_WEEK) + $days;
@@ -346,9 +376,9 @@ public function weeksAndDays($weeks, $days)
* @param string $name The property name to augment. Accepts plural forms in addition
* to singular ones.
* @param array $args The value to set.
- * @return static
+ * @return $this
*/
- public function __call($name, $args)
+ public function __call(string $name, array $args)
{
$arg = count($args) === 0 ? 1 : $args[0];
@@ -388,6 +418,11 @@ public function __call($name, $args)
case 'second':
$this->seconds = $arg;
break;
+
+ case 'microseconds':
+ case 'microsecond':
+ $this->microseconds = $arg;
+ break;
}
return $this;
@@ -397,11 +432,11 @@ public function __call($name, $args)
* Add the passed interval to the current instance
*
* @param \DateInterval $interval The interval to add.
- * @return static
+ * @return $this
*/
public function add(DateInterval $interval)
{
- $sign = ($interval->invert === 1) ? -1 : 1;
+ $sign = $interval->invert === 1 ? -1 : 1;
if (static::wasCreatedFromDiff($interval)) {
$this->dayz = $this->dayz + ($interval->days * $sign);
@@ -412,6 +447,7 @@ public function add(DateInterval $interval)
$this->hours = $this->hours + ($interval->h * $sign);
$this->minutes = $this->minutes + ($interval->i * $sign);
$this->seconds = $this->seconds + ($interval->s * $sign);
+ $this->microseconds = $this->microseconds + (int)($interval->f * 1000000 * $sign);
}
return $this;
@@ -422,7 +458,7 @@ public function add(DateInterval $interval)
*
* @return string Interval as string representation
*/
- public function __toString()
+ public function __toString(): string
{
// equivalence
$oneMinuteInSeconds = 60;
diff --git a/app/vendor/cakephp/chronos/src/Date.php b/app/vendor/cakephp/chronos/src/Date.php
index 711d45230..67b44a24e 100644
--- a/app/vendor/cakephp/chronos/src/Date.php
+++ b/app/vendor/cakephp/chronos/src/Date.php
@@ -1,4 +1,6 @@
stripTime($time);
-
- parent::__construct($time, $tz);
-
- return;
+ if ($tz !== null) {
+ $tz = $tz instanceof DateTimeZone ? $tz : new DateTimeZone($tz);
}
- $relative = static::hasRelativeKeywords($time);
- if (!empty($time) && $time !== 'now' && !$relative) {
- $time = $this->stripTime($time);
-
- parent::__construct($time, $tz);
+ $testNow = Chronos::getTestNow();
+ if ($testNow === null || !static::isRelativeOnly($time)) {
+ $time = $this->stripTime($time, $tz);
+ parent::__construct($time);
return;
}
$testNow = clone $testNow;
- if ($relative) {
- $time = $this->stripRelativeTime($time);
- if (strlen($time) > 0) {
- $testNow = $testNow->modify($time);
- }
- }
-
if ($tz !== $testNow->getTimezone()) {
- $testNow = $testNow->setTimezone($tz === null ? date_default_timezone_get() : $tz);
+ $testNow = $testNow->setTimezone($tz ?? date_default_timezone_get());
+ }
+ if (!empty($time)) {
+ $testNow = $testNow->modify($time);
}
$time = $testNow->format('Y-m-d 00:00:00');
- parent::__construct($time, $tz);
+ parent::__construct($time);
}
/**
@@ -121,7 +120,7 @@ public function __construct($time = 'now')
*
* @return \Cake\Chronos\MutableDate
*/
- public function toMutable()
+ public function toMutable(): MutableDate
{
return MutableDate::instance($this);
}
@@ -131,7 +130,7 @@ public function toMutable()
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$properties = [
'hasFixedNow' => static::hasTestNow(),
diff --git a/app/vendor/cakephp/chronos/src/DifferenceFormatter.php b/app/vendor/cakephp/chronos/src/DifferenceFormatter.php
index d64db63a8..d1a47cd29 100644
--- a/app/vendor/cakephp/chronos/src/DifferenceFormatter.php
+++ b/app/vendor/cakephp/chronos/src/DifferenceFormatter.php
@@ -1,4 +1,6 @@
translate = $translate ?: new Translator();
}
@@ -47,8 +48,11 @@ public function __construct($translate = null)
* @return string The difference between the two days in a human readable format
* @see \Cake\Chronos\ChronosInterface::diffForHumans
*/
- public function diffForHumans(ChronosInterface $date, ChronosInterface $other = null, $absolute = false)
- {
+ public function diffForHumans(
+ ChronosInterface $date,
+ ?ChronosInterface $other = null,
+ bool $absolute = false
+ ): string {
$isNow = $other === null;
if ($isNow) {
$other = $date->now($date->tz);
@@ -56,15 +60,15 @@ public function diffForHumans(ChronosInterface $date, ChronosInterface $other =
$diffInterval = $date->diff($other);
switch (true) {
- case ($diffInterval->y > 0):
+ case $diffInterval->y > 0:
$unit = 'year';
$count = $diffInterval->y;
break;
- case ($diffInterval->m > 0):
+ case $diffInterval->m > 0:
$unit = 'month';
$count = $diffInterval->m;
break;
- case ($diffInterval->d > 0):
+ case $diffInterval->d > 0:
$unit = 'day';
$count = $diffInterval->d;
if ($count >= ChronosInterface::DAYS_PER_WEEK) {
@@ -72,11 +76,11 @@ public function diffForHumans(ChronosInterface $date, ChronosInterface $other =
$count = (int)($count / ChronosInterface::DAYS_PER_WEEK);
}
break;
- case ($diffInterval->h > 0):
+ case $diffInterval->h > 0:
$unit = 'hour';
$count = $diffInterval->h;
break;
- case ($diffInterval->i > 0):
+ case $diffInterval->i > 0:
$unit = 'minute';
$count = $diffInterval->i;
break;
diff --git a/app/vendor/cakephp/chronos/src/DifferenceFormatterInterface.php b/app/vendor/cakephp/chronos/src/DifferenceFormatterInterface.php
new file mode 100644
index 000000000..e94892604
--- /dev/null
+++ b/app/vendor/cakephp/chronos/src/DifferenceFormatterInterface.php
@@ -0,0 +1,35 @@
+stripTime($time);
- parent::__construct($time, $tz);
-
- return;
+ if ($tz !== null) {
+ $tz = $tz instanceof DateTimeZone ? $tz : new DateTimeZone($tz);
}
- $relative = static::hasRelativeKeywords($time);
- if (!empty($time) && $time !== 'now' && !$relative) {
- $time = $this->stripTime($time);
-
- parent::__construct($time, $tz);
+ $testNow = Chronos::getTestNow();
+ if ($testNow === null || !static::isRelativeOnly($time)) {
+ $time = $this->stripTime($time, $tz);
+ parent::__construct($time);
return;
}
$testNow = clone $testNow;
- if ($relative) {
- $time = $this->stripRelativeTime($time);
- if (strlen($time) > 0) {
- $testNow = $testNow->modify($time);
- }
- }
-
if ($tz !== $testNow->getTimezone()) {
- $testNow = $testNow->setTimezone($tz === null ? date_default_timezone_get() : $tz);
+ $testNow = $testNow->setTimezone($tz ?? date_default_timezone_get());
+ }
+ if (!empty($time)) {
+ $testNow = $testNow->modify($time);
}
$time = $testNow->format('Y-m-d 00:00:00');
- parent::__construct($time, $tz);
+ parent::__construct($time);
}
/**
@@ -120,7 +119,7 @@ public function __construct($time = 'now')
*
* @return \Cake\Chronos\Date
*/
- public function toImmutable()
+ public function toImmutable(): Date
{
return Date::instance($this);
}
@@ -130,7 +129,7 @@ public function toImmutable()
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$properties = [
'hasFixedNow' => static::hasTestNow(),
diff --git a/app/vendor/cakephp/chronos/src/MutableDateTime.php b/app/vendor/cakephp/chronos/src/MutableDateTime.php
index 4afa460c2..a01865734 100644
--- a/app/vendor/cakephp/chronos/src/MutableDateTime.php
+++ b/app/vendor/cakephp/chronos/src/MutableDateTime.php
@@ -1,4 +1,6 @@
format('Y-m-d H:i:s.u');
+ }
+
$testNow = Chronos::getTestNow();
if ($testNow === null) {
- parent::__construct($time === null ? 'now' : $time, $tz);
+ parent::__construct($time ?? 'now', $tz);
return;
}
@@ -97,14 +110,15 @@ public function __construct($time = 'now', $tz = null)
}
$testNow = clone $testNow;
+ $relativetime = static::isTimeExpression($time);
+ if (!$relativetime && $tz !== $testNow->getTimezone()) {
+ $testNow = $testNow->setTimezone($tz ?? date_default_timezone_get());
+ }
+
if ($relative) {
$testNow = $testNow->modify($time);
}
- $relativetime = static::isTimeExpression($time);
- if (!$relativetime && $tz !== $testNow->getTimezone()) {
- $testNow = $testNow->setTimezone($tz === null ? date_default_timezone_get() : $tz);
- }
$time = $testNow->format('Y-m-d H:i:s.u');
parent::__construct($time, $tz);
}
@@ -112,9 +126,9 @@ public function __construct($time = 'now', $tz = null)
/**
* Create a new immutable instance from current mutable instance.
*
- * @return Chronos
+ * @return \Cake\Chronos\Chronos
*/
- public function toImmutable()
+ public function toImmutable(): Chronos
{
return Chronos::instance($this);
}
@@ -127,7 +141,7 @@ public function toImmutable()
* @throws \InvalidArgumentException
* @return void
*/
- public function __set($name, $value)
+ public function __set(string $name, $value): void
{
switch ($name) {
case 'year':
@@ -173,7 +187,7 @@ public function __set($name, $value)
*
* @return array
*/
- public function __debugInfo()
+ public function __debugInfo(): array
{
$properties = [
'hasFixedNow' => static::hasTestNow(),
diff --git a/app/vendor/cakephp/chronos/src/Traits/ComparisonTrait.php b/app/vendor/cakephp/chronos/src/Traits/ComparisonTrait.php
index eeeb98b9a..5f076d540 100644
--- a/app/vendor/cakephp/chronos/src/Traits/ComparisonTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/ComparisonTrait.php
@@ -1,4 +1,6 @@
eq($dt);
}
@@ -100,7 +102,7 @@ public function notEquals(ChronosInterface $dt)
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
- public function gt(ChronosInterface $dt)
+ public function gt(ChronosInterface $dt): bool
{
return $this > $dt;
}
@@ -122,7 +124,7 @@ public function greaterThan(ChronosInterface $dt)
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
- public function gte(ChronosInterface $dt)
+ public function gte(ChronosInterface $dt): bool
{
return $this >= $dt;
}
@@ -144,7 +146,7 @@ public function greaterThanOrEquals(ChronosInterface $dt)
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
- public function lt(ChronosInterface $dt)
+ public function lt(ChronosInterface $dt): bool
{
return $this < $dt;
}
@@ -166,7 +168,7 @@ public function lessThan(ChronosInterface $dt)
* @param \Cake\Chronos\ChronosInterface $dt The instance to compare with.
* @return bool
*/
- public function lte(ChronosInterface $dt)
+ public function lte(ChronosInterface $dt): bool
{
return $this <= $dt;
}
@@ -190,7 +192,7 @@ public function lessThanOrEquals(ChronosInterface $dt)
* @param bool $equal Indicates if a > and < comparison should be used or <= or >=
* @return bool
*/
- public function between(ChronosInterface $dt1, ChronosInterface $dt2, $equal = true)
+ public function between(ChronosInterface $dt1, ChronosInterface $dt2, bool $equal = true): bool
{
if ($dt1->gt($dt2)) {
$temp = $dt1;
@@ -212,7 +214,7 @@ public function between(ChronosInterface $dt1, ChronosInterface $dt2, $equal = t
* @param \Cake\Chronos\ChronosInterface $dt2 The instance to compare with.
* @return \Cake\Chronos\ChronosInterface
*/
- public function closest(ChronosInterface $dt1, ChronosInterface $dt2)
+ public function closest(ChronosInterface $dt1, ChronosInterface $dt2): ChronosInterface
{
return $this->diffInSeconds($dt1) < $this->diffInSeconds($dt2) ? $dt1 : $dt2;
}
@@ -224,7 +226,7 @@ public function closest(ChronosInterface $dt1, ChronosInterface $dt2)
* @param \Cake\Chronos\ChronosInterface $dt2 The instance to compare with.
* @return \Cake\Chronos\ChronosInterface
*/
- public function farthest(ChronosInterface $dt1, ChronosInterface $dt2)
+ public function farthest(ChronosInterface $dt1, ChronosInterface $dt2): ChronosInterface
{
return $this->diffInSeconds($dt1) > $this->diffInSeconds($dt2) ? $dt1 : $dt2;
}
@@ -235,9 +237,9 @@ public function farthest(ChronosInterface $dt1, ChronosInterface $dt2)
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with.
* @return \Cake\Chronos\ChronosInterface
*/
- public function min(ChronosInterface $dt = null)
+ public function min(?ChronosInterface $dt = null): ChronosInterface
{
- $dt = ($dt === null) ? static::now($this->tz) : $dt;
+ $dt = $dt ?? static::now($this->tz);
return $this->lt($dt) ? $this : $dt;
}
@@ -248,9 +250,9 @@ public function min(ChronosInterface $dt = null)
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with.
* @return \Cake\Chronos\ChronosInterface
*/
- public function max(ChronosInterface $dt = null)
+ public function max(?ChronosInterface $dt = null): ChronosInterface
{
- $dt = ($dt === null) ? static::now($this->tz) : $dt;
+ $dt = $dt ?? static::now($this->tz);
return $this->gt($dt) ? $this : $dt;
}
@@ -260,7 +262,7 @@ public function max(ChronosInterface $dt = null)
*
* @return bool
*/
- public function isWeekday()
+ public function isWeekday(): bool
{
return !$this->isWeekend();
}
@@ -270,7 +272,7 @@ public function isWeekday()
*
* @return bool
*/
- public function isWeekend()
+ public function isWeekend(): bool
{
return in_array($this->dayOfWeek, self::$weekendDays, true);
}
@@ -280,7 +282,7 @@ public function isWeekend()
*
* @return bool
*/
- public function isYesterday()
+ public function isYesterday(): bool
{
return $this->toDateString() === static::yesterday($this->tz)->toDateString();
}
@@ -290,7 +292,7 @@ public function isYesterday()
*
* @return bool
*/
- public function isToday()
+ public function isToday(): bool
{
return $this->toDateString() === static::now($this->tz)->toDateString();
}
@@ -300,7 +302,7 @@ public function isToday()
*
* @return bool
*/
- public function isTomorrow()
+ public function isTomorrow(): bool
{
return $this->toDateString() === static::tomorrow($this->tz)->toDateString();
}
@@ -310,7 +312,7 @@ public function isTomorrow()
*
* @return bool
*/
- public function isNextWeek()
+ public function isNextWeek(): bool
{
return $this->format('W o') === static::now($this->tz)->addWeek()->format('W o');
}
@@ -320,7 +322,7 @@ public function isNextWeek()
*
* @return bool
*/
- public function isLastWeek()
+ public function isLastWeek(): bool
{
return $this->format('W o') === static::now($this->tz)->subWeek()->format('W o');
}
@@ -330,7 +332,7 @@ public function isLastWeek()
*
* @return bool
*/
- public function isNextMonth()
+ public function isNextMonth(): bool
{
return $this->format('m Y') === static::now($this->tz)->addMonth()->format('m Y');
}
@@ -340,7 +342,7 @@ public function isNextMonth()
*
* @return bool
*/
- public function isLastMonth()
+ public function isLastMonth(): bool
{
return $this->format('m Y') === static::now($this->tz)->subMonth()->format('m Y');
}
@@ -350,7 +352,7 @@ public function isLastMonth()
*
* @return bool
*/
- public function isNextYear()
+ public function isNextYear(): bool
{
return $this->year === static::now($this->tz)->addYear()->year;
}
@@ -360,7 +362,7 @@ public function isNextYear()
*
* @return bool
*/
- public function isLastYear()
+ public function isLastYear(): bool
{
return $this->year === static::now($this->tz)->subYear()->year;
}
@@ -370,7 +372,7 @@ public function isLastYear()
*
* @return bool
*/
- public function isFuture()
+ public function isFuture(): bool
{
return $this->gt(static::now($this->tz));
}
@@ -380,7 +382,7 @@ public function isFuture()
*
* @return bool
*/
- public function isPast()
+ public function isPast(): bool
{
return $this->lt(static::now($this->tz));
}
@@ -390,7 +392,7 @@ public function isPast()
*
* @return bool
*/
- public function isLeapYear()
+ public function isLeapYear(): bool
{
return $this->format('L') === '1';
}
@@ -401,7 +403,7 @@ public function isLeapYear()
* @param \Cake\Chronos\ChronosInterface $dt The instance to check against.
* @return bool
*/
- public function isSameDay(ChronosInterface $dt)
+ public function isSameDay(ChronosInterface $dt): bool
{
return $this->toDateString() === $dt->toDateString();
}
@@ -411,7 +413,7 @@ public function isSameDay(ChronosInterface $dt)
*
* @return bool
*/
- public function isSunday()
+ public function isSunday(): bool
{
return $this->dayOfWeek === ChronosInterface::SUNDAY;
}
@@ -421,7 +423,7 @@ public function isSunday()
*
* @return bool
*/
- public function isMonday()
+ public function isMonday(): bool
{
return $this->dayOfWeek === ChronosInterface::MONDAY;
}
@@ -431,7 +433,7 @@ public function isMonday()
*
* @return bool
*/
- public function isTuesday()
+ public function isTuesday(): bool
{
return $this->dayOfWeek === ChronosInterface::TUESDAY;
}
@@ -441,7 +443,7 @@ public function isTuesday()
*
* @return bool
*/
- public function isWednesday()
+ public function isWednesday(): bool
{
return $this->dayOfWeek === ChronosInterface::WEDNESDAY;
}
@@ -451,7 +453,7 @@ public function isWednesday()
*
* @return bool
*/
- public function isThursday()
+ public function isThursday(): bool
{
return $this->dayOfWeek === ChronosInterface::THURSDAY;
}
@@ -461,7 +463,7 @@ public function isThursday()
*
* @return bool
*/
- public function isFriday()
+ public function isFriday(): bool
{
return $this->dayOfWeek === ChronosInterface::FRIDAY;
}
@@ -471,7 +473,7 @@ public function isFriday()
*
* @return bool
*/
- public function isSaturday()
+ public function isSaturday(): bool
{
return $this->dayOfWeek === ChronosInterface::SATURDAY;
}
@@ -481,7 +483,7 @@ public function isSaturday()
*
* @return bool
*/
- public function isThisWeek()
+ public function isThisWeek(): bool
{
return static::now($this->getTimezone())->format('W o') === $this->format('W o');
}
@@ -491,7 +493,7 @@ public function isThisWeek()
*
* @return bool
*/
- public function isThisMonth()
+ public function isThisMonth(): bool
{
return static::now($this->getTimezone())->format('m Y') === $this->format('m Y');
}
@@ -501,7 +503,7 @@ public function isThisMonth()
*
* @return bool
*/
- public function isThisYear()
+ public function isThisYear(): bool
{
return static::now($this->getTimezone())->format('Y') === $this->format('Y');
}
@@ -512,11 +514,9 @@ public function isThisYear()
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with or null to use current day.
* @return bool
*/
- public function isBirthday(ChronosInterface $dt = null)
+ public function isBirthday(?ChronosInterface $dt = null): bool
{
- if ($dt === null) {
- $dt = static::now($this->tz);
- }
+ $dt = $dt ?? static::now($this->tz);
return $this->format('md') === $dt->format('md');
}
@@ -528,7 +528,7 @@ public function isBirthday(ChronosInterface $dt = null)
* Example of valid types: 6 hours, 2 days, 1 minute.
* @return bool
*/
- public function wasWithinLast($timeInterval)
+ public function wasWithinLast($timeInterval): bool
{
$now = new static();
$interval = $now->copy()->modify('-' . $timeInterval);
@@ -544,7 +544,7 @@ public function wasWithinLast($timeInterval)
* Example of valid types: 6 hours, 2 days, 1 minute.
* @return bool
*/
- public function isWithinNext($timeInterval)
+ public function isWithinNext($timeInterval): bool
{
$now = new static();
$interval = $now->copy()->modify('+' . $timeInterval);
@@ -558,7 +558,7 @@ public function isWithinNext($timeInterval)
*
* @return bool
*/
- public function isMutable()
+ public function isMutable(): bool
{
return $this instanceof DateTime;
}
diff --git a/app/vendor/cakephp/chronos/src/Traits/CopyTrait.php b/app/vendor/cakephp/chronos/src/Traits/CopyTrait.php
index bed0daa39..1bd8ede42 100644
--- a/app/vendor/cakephp/chronos/src/Traits/CopyTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/CopyTrait.php
@@ -1,4 +1,6 @@
tz) : $dt;
+ $diff = $this->diff($dt ?? static::now($this->tz), $abs);
- return (int)$this->diff($dt, $abs)->format('%r%y');
+ return $diff->invert ? -$diff->y : $diff->y;
}
/**
@@ -58,11 +61,35 @@ public function diffInYears(ChronosInterface $dt = null, $abs = true)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInMonths(ChronosInterface $dt = null, $abs = true)
+ public function diffInMonths(?ChronosInterface $dt = null, bool $abs = true): int
+ {
+ $diff = $this->diff($dt ?? static::now($this->tz), $abs);
+ $months = $diff->y * ChronosInterface::MONTHS_PER_YEAR + $diff->m;
+
+ return $diff->invert ? -$months : $months;
+ }
+
+ /**
+ * Get the difference in months ignoring the timezone. This means the months are calculated
+ * in the specified timezone without converting to UTC first. This prevents the day from changing
+ * which can change the month.
+ *
+ * For example, if comparing `2019-06-01 Asia/Tokyo` and `2019-10-01 Asia/Tokyo`,
+ * the result would be 4 months instead of 3 when using normal `DateTime::diff()`.
+ *
+ * @param \Cake\Chronos\ChronosInterface|null $dt The instance to difference from.
+ * @param bool $abs Get the absolute of the difference
+ * @return int
+ */
+ public function diffInMonthsIgnoreTimezone(?ChronosInterface $dt = null, bool $abs = true): int
{
- $dt = $dt === null ? static::now($this->tz) : $dt;
+ $utcTz = new DateTimeZone('UTC');
+ $source = new static($this->format('Y-m-d H:i:s.u'), $utcTz);
- return $this->diffInYears($dt, $abs) * ChronosInterface::MONTHS_PER_YEAR + (int)$this->diff($dt, $abs)->format('%r%m');
+ $dt = $dt ?? static::now($this->tz);
+ $dt = new static($dt->format('Y-m-d H:i:s.u'), $utcTz);
+
+ return $source->diffInMonths($dt, $abs);
}
/**
@@ -72,7 +99,7 @@ public function diffInMonths(ChronosInterface $dt = null, $abs = true)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInWeeks(ChronosInterface $dt = null, $abs = true)
+ public function diffInWeeks(?ChronosInterface $dt = null, bool $abs = true): int
{
return (int)($this->diffInDays($dt, $abs) / ChronosInterface::DAYS_PER_WEEK);
}
@@ -84,11 +111,11 @@ public function diffInWeeks(ChronosInterface $dt = null, $abs = true)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInDays(ChronosInterface $dt = null, $abs = true)
+ public function diffInDays(?ChronosInterface $dt = null, bool $abs = true): int
{
- $dt = $dt === null ? static::now($this->tz) : $dt;
+ $diff = $this->diff($dt ?? static::now($this->tz), $abs);
- return (int)$this->diff($dt, $abs)->format('%r%a');
+ return $diff->invert ? -$diff->days : $diff->days;
}
/**
@@ -99,7 +126,7 @@ public function diffInDays(ChronosInterface $dt = null, $abs = true)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInDaysFiltered(callable $callback, ChronosInterface $dt = null, $abs = true)
+ public function diffInDaysFiltered(callable $callback, ?ChronosInterface $dt = null, bool $abs = true): int
{
return $this->diffFiltered(ChronosInterval::day(), $callback, $dt, $abs);
}
@@ -112,7 +139,7 @@ public function diffInDaysFiltered(callable $callback, ChronosInterface $dt = nu
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInHoursFiltered(callable $callback, ChronosInterface $dt = null, $abs = true)
+ public function diffInHoursFiltered(callable $callback, ?ChronosInterface $dt = null, bool $abs = true): int
{
return $this->diffFiltered(ChronosInterval::hour(), $callback, $dt, $abs);
}
@@ -126,17 +153,16 @@ public function diffInHoursFiltered(callable $callback, ChronosInterface $dt = n
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffFiltered(ChronosInterval $ci, callable $callback, ChronosInterface $dt = null, $abs = true)
- {
+ public function diffFiltered(
+ ChronosInterval $ci,
+ callable $callback,
+ ?ChronosInterface $dt = null,
+ bool $abs = true
+ ): int {
$start = $this;
- $end = $dt === null ? static::now($this->tz) : $dt;
+ $end = $dt ?? static::now($this->tz);
$inverse = false;
- if (defined('HHVM_VERSION')) {
- $start = new DateTimeImmutable($this->toIso8601String());
- $end = new DateTimeImmutable($end->toIso8601String());
- }
-
if ($end < $start) {
$start = $end;
$end = $this;
@@ -160,7 +186,7 @@ public function diffFiltered(ChronosInterval $ci, callable $callback, ChronosInt
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInWeekdays(ChronosInterface $dt = null, $abs = true)
+ public function diffInWeekdays(?ChronosInterface $dt = null, bool $abs = true): int
{
return $this->diffInDaysFiltered(function (ChronosInterface $date) {
return $date->isWeekday();
@@ -174,7 +200,7 @@ public function diffInWeekdays(ChronosInterface $dt = null, $abs = true)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInWeekendDays(ChronosInterface $dt = null, $abs = true)
+ public function diffInWeekendDays(?ChronosInterface $dt = null, bool $abs = true): int
{
return $this->diffInDaysFiltered(function (ChronosInterface $date) {
return $date->isWeekend();
@@ -188,9 +214,13 @@ public function diffInWeekendDays(ChronosInterface $dt = null, $abs = true)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInHours(ChronosInterface $dt = null, $abs = true)
+ public function diffInHours(?ChronosInterface $dt = null, bool $abs = true): int
{
- return (int)($this->diffInSeconds($dt, $abs) / ChronosInterface::SECONDS_PER_MINUTE / ChronosInterface::MINUTES_PER_HOUR);
+ return (int)(
+ $this->diffInSeconds($dt, $abs)
+ / ChronosInterface::SECONDS_PER_MINUTE
+ / ChronosInterface::MINUTES_PER_HOUR
+ );
}
/**
@@ -200,7 +230,7 @@ public function diffInHours(ChronosInterface $dt = null, $abs = true)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInMinutes(ChronosInterface $dt = null, $abs = true)
+ public function diffInMinutes(?ChronosInterface $dt = null, bool $abs = true): int
{
return (int)($this->diffInSeconds($dt, $abs) / ChronosInterface::SECONDS_PER_MINUTE);
}
@@ -212,9 +242,9 @@ public function diffInMinutes(ChronosInterface $dt = null, $abs = true)
* @param bool $abs Get the absolute of the difference
* @return int
*/
- public function diffInSeconds(ChronosInterface $dt = null, $abs = true)
+ public function diffInSeconds(?ChronosInterface $dt = null, bool $abs = true): int
{
- $dt = ($dt === null) ? static::now($this->tz) : $dt;
+ $dt = $dt ?? static::now($this->tz);
$value = $dt->getTimestamp() - $this->getTimestamp();
return $abs ? abs($value) : $value;
@@ -225,7 +255,7 @@ public function diffInSeconds(ChronosInterface $dt = null, $abs = true)
*
* @return int
*/
- public function secondsSinceMidnight()
+ public function secondsSinceMidnight(): int
{
return $this->diffInSeconds($this->copy()->startOfDay());
}
@@ -235,7 +265,7 @@ public function secondsSinceMidnight()
*
* @return int
*/
- public function secondsUntilEndOfDay()
+ public function secondsUntilEndOfDay(): int
{
return $this->diffInSeconds($this->copy()->endOfDay());
}
@@ -276,7 +306,7 @@ public static function fromNow($datetime)
* @param bool $absolute removes time difference modifiers ago, after, etc
* @return string
*/
- public function diffForHumans(ChronosInterface $other = null, $absolute = false)
+ public function diffForHumans(?ChronosInterface $other = null, bool $absolute = false): string
{
return static::diffFormatter()->diffForHumans($this, $other, $absolute);
}
@@ -284,10 +314,10 @@ public function diffForHumans(ChronosInterface $other = null, $absolute = false)
/**
* Get the difference formatter instance or overwrite the current one.
*
- * @param \Cake\Chronos\DifferenceFormatter|null $formatter The formatter instance when setting.
- * @return \Cake\Chronos\DifferenceFormatter The formatter instance.
+ * @param \Cake\Chronos\DifferenceFormatterInterface|null $formatter The formatter instance when setting.
+ * @return \Cake\Chronos\DifferenceFormatterInterface The formatter instance.
*/
- public static function diffFormatter($formatter = null)
+ public static function diffFormatter(?DifferenceFormatterInterface $formatter = null): DifferenceFormatterInterface
{
if ($formatter === null) {
if (static::$diffFormatter === null) {
diff --git a/app/vendor/cakephp/chronos/src/Traits/FactoryTrait.php b/app/vendor/cakephp/chronos/src/Traits/FactoryTrait.php
index c9b1c33c1..963624345 100644
--- a/app/vendor/cakephp/chronos/src/Traits/FactoryTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/FactoryTrait.php
@@ -1,4 +1,6 @@
fn() rather than
* (new Chronos('Monday next week'))->fn()
*
- * @param \DateTimeInterface|string $time The strtotime compatible string to parse
+ * @param \DateTimeInterface|string|int $time The strtotime compatible string to parse
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name.
* @return static
*/
- public static function parse($time = 'now', $tz = null)
+ public static function parse($time = 'now', $tz = null): ChronosInterface
{
return new static($time, $tz);
}
@@ -64,7 +68,7 @@ public static function parse($time = 'now', $tz = null)
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name.
* @return static
*/
- public static function now($tz = null)
+ public static function now($tz = null): ChronosInterface
{
return new static('now', $tz);
}
@@ -75,7 +79,7 @@ public static function now($tz = null)
* @param \DateTimeZone|string|null $tz The timezone to use.
* @return static
*/
- public static function today($tz = null)
+ public static function today($tz = null): ChronosInterface
{
return new static('midnight', $tz);
}
@@ -86,7 +90,7 @@ public static function today($tz = null)
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
- public static function tomorrow($tz = null)
+ public static function tomorrow($tz = null): ChronosInterface
{
return new static('tomorrow, midnight', $tz);
}
@@ -97,7 +101,7 @@ public static function tomorrow($tz = null)
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
- public static function yesterday($tz = null)
+ public static function yesterday($tz = null): ChronosInterface
{
return new static('yesterday, midnight', $tz);
}
@@ -107,7 +111,7 @@ public static function yesterday($tz = null)
*
* @return \Cake\Chronos\ChronosInterface
*/
- public static function maxValue()
+ public static function maxValue(): ChronosInterface
{
return static::createFromTimestampUTC(PHP_INT_MAX);
}
@@ -117,7 +121,7 @@ public static function maxValue()
*
* @return \Cake\Chronos\ChronosInterface
*/
- public static function minValue()
+ public static function minValue(): ChronosInterface
{
$max = PHP_INT_SIZE === 4 ? PHP_INT_MAX : PHP_INT_MAX / 10;
@@ -131,9 +135,9 @@ public static function minValue()
* will be used.
*
* If $hour is null it will be set to its now() value and the default values
- * for $minute and $second will be their now() values.
- * If $hour is not null then the default values for $minute and $second
- * will be 0.
+ * for $minute, $second and $microsecond will be their now() values.
+ * If $hour is not null then the default values for $minute, $second
+ * and $microsecond will be 0.
*
* @param int|null $year The year to create an instance with.
* @param int|null $month The month to create an instance with.
@@ -141,25 +145,41 @@ public static function minValue()
* @param int|null $hour The hour to create an instance with.
* @param int|null $minute The minute to create an instance with.
* @param int|null $second The second to create an instance with.
+ * @param int|null $microsecond The microsecond to create an instance with.
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
- public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
- {
- $year = ($year === null) ? date('Y') : $year;
- $month = ($month === null) ? date('n') : $month;
- $day = ($day === null) ? date('j') : $day;
+ public static function create(
+ ?int $year = null,
+ ?int $month = null,
+ ?int $day = null,
+ ?int $hour = null,
+ ?int $minute = null,
+ ?int $second = null,
+ ?int $microsecond = null,
+ $tz = null
+ ): ChronosInterface {
+ $now = static::now();
+ $year = $year ?? (int)$now->format('Y');
+ $month = $month ?? $now->format('m');
+ $day = $day ?? $now->format('d');
if ($hour === null) {
- $hour = date('G');
- $minute = ($minute === null) ? date('i') : $minute;
- $second = ($second === null) ? date('s') : $second;
+ $hour = $now->format('H');
+ $minute = $minute ?? $now->format('i');
+ $second = $second ?? $now->format('s');
+ $microsecond = $microsecond ?? $now->format('u');
} else {
- $minute = ($minute === null) ? 0 : $minute;
- $second = ($second === null) ? 0 : $second;
+ $minute = $minute ?? 0;
+ $second = $second ?? 0;
+ $microsecond = $microsecond ?? 0;
}
- $instance = static::createFromFormat('Y-n-j G:i:s', sprintf('%s-%s-%s %s:%02s:%02s', 0, $month, $day, $hour, $minute, $second), $tz);
+ $instance = static::createFromFormat(
+ 'Y-m-d H:i:s.u',
+ sprintf('%s-%s-%s %s:%02s:%02s.%06s', 0, $month, $day, $hour, $minute, $second, $microsecond),
+ $tz
+ );
return $instance->addYears($year);
}
@@ -167,15 +187,19 @@ public static function create($year = null, $month = null, $day = null, $hour =
/**
* Create a ChronosInterface instance from just a date. The time portion is set to now.
*
- * @param int $year The year to create an instance with.
- * @param int $month The month to create an instance with.
- * @param int $day The day to create an instance with.
+ * @param int|null $year The year to create an instance with.
+ * @param int|null $month The month to create an instance with.
+ * @param int|null $day The day to create an instance with.
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
- public static function createFromDate($year = null, $month = null, $day = null, $tz = null)
- {
- return static::create($year, $month, $day, null, null, null, $tz);
+ public static function createFromDate(
+ ?int $year = null,
+ ?int $month = null,
+ ?int $day = null,
+ $tz = null
+ ): ChronosInterface {
+ return static::create($year, $month, $day, null, null, null, null, $tz);
}
/**
@@ -184,12 +208,18 @@ public static function createFromDate($year = null, $month = null, $day = null,
* @param int|null $hour The hour to create an instance with.
* @param int|null $minute The minute to create an instance with.
* @param int|null $second The second to create an instance with.
+ * @param int|null $microsecond The microsecond to create an instance with.
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
- public static function createFromTime($hour = null, $minute = null, $second = null, $tz = null)
- {
- return static::create(null, null, null, $hour, $minute, $second, $tz);
+ public static function createFromTime(
+ ?int $hour = null,
+ ?int $minute = null,
+ ?int $second = null,
+ ?int $microsecond = null,
+ $tz = null
+ ): ChronosInterface {
+ return static::create(null, null, null, $hour, $minute, $second, $microsecond, $tz);
}
/**
@@ -201,7 +231,8 @@ public static function createFromTime($hour = null, $minute = null, $second = nu
* @return static
* @throws \InvalidArgumentException
*/
- public static function createFromFormat($format, $time, $tz = null)
+ #[ReturnTypeWillChange]
+ public static function createFromFormat($format, $time, $tz = null): ChronosInterface
{
if ($tz !== null) {
$dt = parent::createFromFormat($format, $time, static::safeCreateDateTimeZone($tz));
@@ -210,11 +241,11 @@ public static function createFromFormat($format, $time, $tz = null)
}
$errors = parent::getLastErrors();
- if ($dt == false) {
+ if (!$dt) {
throw new InvalidArgumentException(implode(PHP_EOL, $errors['errors']));
}
- $dt = static::instance($dt);
+ $dt = new static($dt->format('Y-m-d H:i:s.u'), $dt->getTimezone());
static::$_lastErrors = $errors;
return $dt;
@@ -242,7 +273,7 @@ public static function createFromFormat($format, $time, $tz = null)
* @param (int|string)[] $values Array of date and time values.
* @return static
*/
- public static function createFromArray($values)
+ public static function createFromArray(array $values): ChronosInterface
{
$values += ['hour' => 0, 'minute' => 0, 'second' => 0, 'microsecond' => 0, 'timezone' => null];
@@ -282,7 +313,7 @@ public static function createFromArray($values)
* @param \DateTimeZone|string|null $tz The DateTimeZone object or timezone name the new instance should use.
* @return static
*/
- public static function createFromTimestamp($timestamp, $tz = null)
+ public static function createFromTimestamp(int $timestamp, $tz = null): ChronosInterface
{
return static::now($tz)->setTimestamp($timestamp);
}
@@ -293,9 +324,9 @@ public static function createFromTimestamp($timestamp, $tz = null)
* @param int $timestamp The UTC timestamp to create an instance from.
* @return static
*/
- public static function createFromTimestampUTC($timestamp)
+ public static function createFromTimestampUTC(int $timestamp): ChronosInterface
{
- return new static('@' . $timestamp);
+ return new static($timestamp);
}
/**
@@ -305,7 +336,7 @@ public static function createFromTimestampUTC($timestamp)
* @return \DateTimeZone
* @throws \InvalidArgumentException
*/
- protected static function safeCreateDateTimeZone($object)
+ protected static function safeCreateDateTimeZone($object): DateTimeZone
{
if ($object === null) {
return new DateTimeZone(date_default_timezone_get());
@@ -324,7 +355,7 @@ protected static function safeCreateDateTimeZone($object)
*
* @return array
*/
- public static function getLastErrors()
+ public static function getLastErrors(): array
{
if (empty(static::$_lastErrors)) {
return parent::getLastErrors();
diff --git a/app/vendor/cakephp/chronos/src/Traits/FormattingTrait.php b/app/vendor/cakephp/chronos/src/Traits/FormattingTrait.php
index 1af15c5ec..61e3ba393 100644
--- a/app/vendor/cakephp/chronos/src/Traits/FormattingTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/FormattingTrait.php
@@ -1,4 +1,6 @@
format(static::$toStringFormat);
}
@@ -58,7 +60,7 @@ public function __toString()
*
* @return string
*/
- public function toDateString()
+ public function toDateString(): string
{
return $this->format('Y-m-d');
}
@@ -68,7 +70,7 @@ public function toDateString()
*
* @return string
*/
- public function toFormattedDateString()
+ public function toFormattedDateString(): string
{
return $this->format('M j, Y');
}
@@ -78,7 +80,7 @@ public function toFormattedDateString()
*
* @return string
*/
- public function toTimeString()
+ public function toTimeString(): string
{
return $this->format('H:i:s');
}
@@ -88,7 +90,7 @@ public function toTimeString()
*
* @return string
*/
- public function toDateTimeString()
+ public function toDateTimeString(): string
{
return $this->format('Y-m-d H:i:s');
}
@@ -98,7 +100,7 @@ public function toDateTimeString()
*
* @return string
*/
- public function toDayDateTimeString()
+ public function toDayDateTimeString(): string
{
return $this->format('D, M j, Y g:i A');
}
@@ -108,7 +110,7 @@ public function toDayDateTimeString()
*
* @return string
*/
- public function toAtomString()
+ public function toAtomString(): string
{
return $this->format(DateTime::ATOM);
}
@@ -118,7 +120,7 @@ public function toAtomString()
*
* @return string
*/
- public function toCookieString()
+ public function toCookieString(): string
{
return $this->format(DateTime::COOKIE);
}
@@ -128,7 +130,7 @@ public function toCookieString()
*
* @return string
*/
- public function toIso8601String()
+ public function toIso8601String(): string
{
return $this->format(DateTime::ATOM);
}
@@ -137,8 +139,9 @@ public function toIso8601String()
* Format the instance as RFC822
*
* @return string
+ * @link https://tools.ietf.org/html/rfc822
*/
- public function toRfc822String()
+ public function toRfc822String(): string
{
return $this->format(DateTime::RFC822);
}
@@ -147,8 +150,9 @@ public function toRfc822String()
* Format the instance as RFC850
*
* @return string
+ * @link https://tools.ietf.org/html/rfc850
*/
- public function toRfc850String()
+ public function toRfc850String(): string
{
return $this->format(DateTime::RFC850);
}
@@ -157,8 +161,9 @@ public function toRfc850String()
* Format the instance as RFC1036
*
* @return string
+ * @link https://tools.ietf.org/html/rfc1036
*/
- public function toRfc1036String()
+ public function toRfc1036String(): string
{
return $this->format(DateTime::RFC1036);
}
@@ -167,8 +172,9 @@ public function toRfc1036String()
* Format the instance as RFC1123
*
* @return string
+ * @link https://tools.ietf.org/html/rfc1123
*/
- public function toRfc1123String()
+ public function toRfc1123String(): string
{
return $this->format(DateTime::RFC1123);
}
@@ -177,8 +183,9 @@ public function toRfc1123String()
* Format the instance as RFC2822
*
* @return string
+ * @link https://tools.ietf.org/html/rfc2822
*/
- public function toRfc2822String()
+ public function toRfc2822String(): string
{
return $this->format(DateTime::RFC2822);
}
@@ -187,8 +194,9 @@ public function toRfc2822String()
* Format the instance as RFC3339
*
* @return string
+ * @link https://tools.ietf.org/html/rfc3339
*/
- public function toRfc3339String()
+ public function toRfc3339String(): string
{
return $this->format(DateTime::RFC3339);
}
@@ -198,7 +206,7 @@ public function toRfc3339String()
*
* @return string
*/
- public function toRssString()
+ public function toRssString(): string
{
return $this->format(DateTime::RSS);
}
@@ -208,7 +216,7 @@ public function toRssString()
*
* @return string
*/
- public function toW3cString()
+ public function toW3cString(): string
{
return $this->format(DateTime::W3C);
}
@@ -218,7 +226,7 @@ public function toW3cString()
*
* @return string UNIX timestamp
*/
- public function toUnixString()
+ public function toUnixString(): string
{
return $this->format('U');
}
@@ -229,9 +237,9 @@ public function toUnixString()
* @param bool $range Range.
* @return int|array 1, 2, 3, or 4 quarter of year or array if $range true
*/
- public function toQuarter($range = false)
+ public function toQuarter(bool $range = false)
{
- $quarter = ceil($this->format('m') / 3);
+ $quarter = (int)ceil($this->format('m') / 3);
if ($range === false) {
return $quarter;
}
@@ -244,15 +252,15 @@ public function toQuarter($range = false)
return [$year . '-04-01', $year . '-06-30'];
case 3:
return [$year . '-07-01', $year . '-09-30'];
- case 4:
+ default:
return [$year . '-10-01', $year . '-12-31'];
}
}
/**
- * @return int
+ * @inheritDoc
*/
- public function toWeek()
+ public function toWeek(): int
{
return (int)$this->format('W');
}
diff --git a/app/vendor/cakephp/chronos/src/Traits/FrozenTimeTrait.php b/app/vendor/cakephp/chronos/src/Traits/FrozenTimeTrait.php
index eaa611b74..fd0a001d5 100644
--- a/app/vendor/cakephp/chronos/src/Traits/FrozenTimeTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/FrozenTimeTrait.php
@@ -1,4 +1,6 @@
format('Y-m-d 00:00:00');
- }
- if (substr($time, 0, 1) === '@') {
- return gmdate('Y-m-d 00:00:00', substr($time, 1));
- }
- if ($time === null || $time === 'now' || $time === '') {
- return date('Y-m-d 00:00:00');
+
+ if (is_string($time) && substr($time, 0, 1) === '@') {
+ return gmdate('Y-m-d 00:00:00', (int)substr($time, 1));
}
- if ($this->hasRelativeKeywords($time)) {
- return date('Y-m-d 00:00:00', strtotime($time));
+
+ if (!($time instanceof DateTimeInterface)) {
+ $time = new DateTimeImmutable($time ?? 'now', $tz);
}
- return preg_replace('/\d{1,2}:\d{1,2}:\d{1,2}(?:\.\d+)?/', '00:00:00', $time);
+ return $time->format('Y-m-d 00:00:00');
}
/**
@@ -58,7 +60,7 @@ protected function stripTime($time)
* @param string $time The input expression
* @return string The output expression with no time modifiers.
*/
- protected function stripRelativeTime($time)
+ protected function stripRelativeTime(string $time): string
{
return preg_replace('/([-+]\s*\d+\s(?:minutes|seconds|hours|microseconds))/', '', $time);
}
@@ -74,13 +76,10 @@ protected function stripRelativeTime($time)
* @param int $microseconds The microseconds to set (ignored)
* @return static A modified Date instance.
*/
- public function setTime($hours, $minutes, $seconds = null, $microseconds = null)
+ #[ReturnTypeWillChange]
+ public function setTime($hours, $minutes, $seconds = null, $microseconds = null): ChronosInterface
{
- if (CHRONOS_SUPPORTS_MICROSECONDS) {
- return parent::setTime(0, 0, 0, 0);
- }
-
- return parent::setTime(0, 0, 0);
+ return parent::setTime(0, 0, 0, 0);
}
/**
@@ -91,7 +90,8 @@ public function setTime($hours, $minutes, $seconds = null, $microseconds = null)
* @param \DateInterval $interval The interval to modify this date by.
* @return static A modified Date instance
*/
- public function add($interval)
+ #[ReturnTypeWillChange]
+ public function add($interval): ChronosInterface
{
return parent::add($interval)->setTime(0, 0, 0);
}
@@ -104,7 +104,8 @@ public function add($interval)
* @param \DateInterval $interval The interval to modify this date by.
* @return static A modified Date instance
*/
- public function sub($interval)
+ #[ReturnTypeWillChange]
+ public function sub($interval): ChronosInterface
{
return parent::sub($interval)->setTime(0, 0, 0);
}
@@ -143,6 +144,7 @@ public function tz($value)
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return $this
*/
+ #[ReturnTypeWillChange]
public function setTimezone($value)
{
return $this;
@@ -157,7 +159,8 @@ public function setTimezone($value)
* @param int $value The timestamp value to set.
* @return static
*/
- public function setTimestamp($value)
+ #[ReturnTypeWillChange]
+ public function setTimestamp($value): ChronosInterface
{
return parent::setTimestamp($value)->setTime(0, 0, 0);
}
@@ -171,7 +174,8 @@ public function setTimestamp($value)
* @param string $relative The relative change to make.
* @return static A new date with the applied date changes.
*/
- public function modify($relative)
+ #[ReturnTypeWillChange]
+ public function modify($relative): ChronosInterface
{
if (preg_match('/hour|minute|second/', $relative)) {
return $this;
diff --git a/app/vendor/cakephp/chronos/src/Traits/MagicPropertyTrait.php b/app/vendor/cakephp/chronos/src/Traits/MagicPropertyTrait.php
index 5556880cf..7c01449a2 100644
--- a/app/vendor/cakephp/chronos/src/Traits/MagicPropertyTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/MagicPropertyTrait.php
@@ -1,4 +1,6 @@
'Y',
@@ -78,6 +81,9 @@ public function __get($name)
case isset($formats[$name]):
return (int)$this->format($formats[$name]);
+ case $name === 'dayOfWeekName':
+ return $this->format('l');
+
case $name === 'weekOfMonth':
return (int)ceil($this->day / ChronosInterface::DAYS_PER_WEEK);
@@ -119,7 +125,7 @@ public function __get($name)
* @param string $name The property name to check.
* @return bool Whether or not the property exists.
*/
- public function __isset($name)
+ public function __isset(string $name): bool
{
try {
$this->__get($name);
diff --git a/app/vendor/cakephp/chronos/src/Traits/ModifierTrait.php b/app/vendor/cakephp/chronos/src/Traits/ModifierTrait.php
index 95bda309b..62e6a049f 100644
--- a/app/vendor/cakephp/chronos/src/Traits/ModifierTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/ModifierTrait.php
@@ -1,4 +1,6 @@
modify('+0 day')->setDateParent($year, $month, $day);
}
@@ -125,7 +125,7 @@ public function setDate($year, $month, $day)
* @param int $day The day to set.
* @return static
*/
- private function setDateParent($year, $month, $day)
+ private function setDateParent(int $year, int $month, int $day): ChronosInterface
{
return parent::setDate($year, $month, $day);
}
@@ -141,8 +141,14 @@ private function setDateParent($year, $month, $day)
* @param int $second The second to set.
* @return static
*/
- public function setDateTime($year, $month, $day, $hour, $minute, $second = 0)
- {
+ public function setDateTime(
+ int $year,
+ int $month,
+ int $day,
+ int $hour,
+ int $minute,
+ int $second = 0
+ ): ChronosInterface {
return $this->setDate($year, $month, $day)->setTime($hour, $minute, $second);
}
@@ -152,14 +158,14 @@ public function setDateTime($year, $month, $day, $hour, $minute, $second = 0)
* @param string $time Time as string.
* @return static
*/
- public function setTimeFromTimeString($time)
+ public function setTimeFromTimeString(string $time): ChronosInterface
{
- $time = explode(":", $time);
- $hour = (int)$time[0];
- $minute = isset($time[1]) ? (int)$time[1] : 0;
- $second = isset($time[2]) ? (int)$time[2] : 0;
+ $time = explode(':', $time);
+ $hour = $time[0];
+ $minute = $time[1] ?? 0;
+ $second = $time[2] ?? 0;
- return $this->setTime($hour, $minute, $second);
+ return $this->setTime((int)$hour, (int)$minute, (int)$second);
}
/**
@@ -168,7 +174,7 @@ public function setTimeFromTimeString($time)
* @param int $value The timestamp value to set.
* @return static
*/
- public function timestamp($value)
+ public function timestamp(int $value): ChronosInterface
{
return $this->setTimestamp($value);
}
@@ -179,7 +185,7 @@ public function timestamp($value)
* @param int $value The year value.
* @return static
*/
- public function year($value)
+ public function year(int $value): ChronosInterface
{
return $this->setDate($value, $this->month, $this->day);
}
@@ -190,7 +196,7 @@ public function year($value)
* @param int $value The month value.
* @return static
*/
- public function month($value)
+ public function month(int $value): ChronosInterface
{
return $this->setDate($this->year, $value, $this->day);
}
@@ -201,7 +207,7 @@ public function month($value)
* @param int $value The day value.
* @return static
*/
- public function day($value)
+ public function day(int $value): ChronosInterface
{
return $this->setDate($this->year, $this->month, $value);
}
@@ -212,7 +218,7 @@ public function day($value)
* @param int $value The hour value.
* @return static
*/
- public function hour($value)
+ public function hour(int $value): ChronosInterface
{
return $this->setTime($value, $this->minute, $this->second);
}
@@ -223,7 +229,7 @@ public function hour($value)
* @param int $value The minute value.
* @return static
*/
- public function minute($value)
+ public function minute(int $value): ChronosInterface
{
return $this->setTime($this->hour, $value, $this->second);
}
@@ -234,7 +240,7 @@ public function minute($value)
* @param int $value The seconds value.
* @return static
*/
- public function second($value)
+ public function second(int $value): ChronosInterface
{
return $this->setTime($this->hour, $this->minute, $value);
}
@@ -243,45 +249,128 @@ public function second($value)
* Add years to the instance. Positive $value travel forward while
* negative $value travel into the past.
*
+ * If the new date does not exist, the last day of the month is used
+ * instead instead of overflowing into the next month.
+ *
+ * ### Example:
+ *
+ * ```
+ * (new Chronos('2015-01-03'))->addYears(1); // Results in 2016-01-03
+ *
+ * (new Chronos('2012-02-29'))->addYears(1); // Results in 2013-02-28
+ * ```
+ *
* @param int $value The number of years to add.
* @return static
*/
- public function addYears($value)
+ public function addYears(int $value): ChronosInterface
{
- return $this->modify((int)$value . ' year');
+ $month = $this->month;
+ $date = $this->modify($value . ' year');
+
+ if ($date->month !== $month) {
+ return $date->modify('last day of previous month');
+ }
+
+ return $date;
}
/**
- * Add a year to the instance
+ * Add a year to the instance.
+ *
+ * Has the same behavior as `addYears()`.
*
* @param int $value The number of years to add.
* @return static
*/
- public function addYear($value = 1)
+ public function addYear(int $value = 1): ChronosInterface
{
return $this->addYears($value);
}
+ /**
+ * Remove years from the instance.
+ *
+ * Has the same behavior as `addYears()`.
+ *
+ * @param int $value The number of years to remove.
+ * @return static
+ */
+ public function subYears(int $value): ChronosInterface
+ {
+ return $this->addYears(-1 * $value);
+ }
+
/**
* Remove a year from the instance
*
+ * Has the same behavior as `addYears()`.
+ *
* @param int $value The number of years to remove.
* @return static
*/
- public function subYear($value = 1)
+ public function subYear(int $value = 1): ChronosInterface
{
return $this->subYears($value);
}
/**
- * Remove years from the instance.
+ * Add years with overflowing to the instance. Positive $value
+ * travels forward while negative $value travels into the past.
+ *
+ * If the new date does not exist, the days overflow into the next month.
+ *
+ * ### Example:
+ *
+ * ```
+ * (new Chronos('2012-02-29'))->addYearsWithOverflow(1); // Results in 2013-03-01
+ * ```
+ *
+ * @param int $value The number of years to add.
+ * @return static
+ */
+ public function addYearsWithOverflow(int $value): ChronosInterface
+ {
+ return $this->modify($value . ' year');
+ }
+
+ /**
+ * Add a year with overflow to the instance.
+ *
+ * Has the same behavior as `addYearsWithOverflow()`.
+ *
+ * @param int $value The number of years to add.
+ * @return static
+ */
+ public function addYearWithOverflow(int $value = 1): ChronosInterface
+ {
+ return $this->addYearsWithOverflow($value);
+ }
+
+ /**
+ * Remove years with overflow from the instance
+ *
+ * Has the same behavior as `addYeasrWithOverflow()`.
*
* @param int $value The number of years to remove.
* @return static
*/
- public function subYears($value)
+ public function subYearsWithOverflow(int $value): ChronosInterface
{
- return $this->addYears(-1 * $value);
+ return $this->addYearsWithOverflow(-1 * $value);
+ }
+
+ /**
+ * Remove a year with overflow from the instance.
+ *
+ * Has the same behavior as `addYearsWithOverflow()`.
+ *
+ * @param int $value The number of years to remove.
+ * @return static
+ */
+ public function subYearWithOverflow(int $value = 1): ChronosInterface
+ {
+ return $this->subYearsWithOverflow($value);
}
/**
@@ -303,10 +392,10 @@ public function subYears($value)
* @param int $value The number of months to add.
* @return static
*/
- public function addMonths($value)
+ public function addMonths(int $value): ChronosInterface
{
$day = $this->day;
- $date = $this->modify((int)$value . ' month');
+ $date = $this->modify($value . ' month');
if ($date->day !== $day) {
return $date->modify('last day of previous month');
@@ -318,22 +407,12 @@ public function addMonths($value)
/**
* Add a month to the instance
*
- * When adding or subtracting months, if the resulting time is a date
- * that does not exist, the result of this operation will always be the
- * last day of the intended month.
- *
- * ### Example:
- *
- * ```
- * (new Chronos('2015-01-03'))->addMonth(); // Results in 2015-02-03
- *
- * (new Chronos('2015-01-31'))->addMonth(); // Results in 2015-02-28
- * ```
+ * Has the same behavior as `addMonths()`.
*
* @param int $value The number of months to add.
* @return static
*/
- public function addMonth($value = 1)
+ public function addMonth(int $value = 1): ChronosInterface
{
return $this->addMonths($value);
}
@@ -341,22 +420,12 @@ public function addMonth($value = 1)
/**
* Remove a month from the instance
*
- * When adding or subtracting months, if the resulting time is a date
- * that does not exist, the result of this operation will always be the
- * last day of the intended month.
- *
- * ### Example:
- *
- * ```
- * (new Chronos('2015-03-01'))->subMonth(); // Results in 2015-02-01
- *
- * (new Chronos('2015-03-31'))->subMonth(); // Results in 2015-02-28
- * ```
+ * Has the same behavior as `addMonths()`.
*
* @param int $value The number of months to remove.
* @return static
*/
- public function subMonth($value = 1)
+ public function subMonth(int $value = 1): ChronosInterface
{
return $this->subMonths($value);
}
@@ -364,22 +433,12 @@ public function subMonth($value = 1)
/**
* Remove months from the instance
*
- * When adding or subtracting months, if the resulting time is a date
- * that does not exist, the result of this operation will always be the
- * last day of the intended month.
- *
- * ### Example:
- *
- * ```
- * (new Chronos('2015-03-01'))->subMonths(1); // Results in 2015-02-01
- *
- * (new Chronos('2015-03-31'))->subMonths(1); // Results in 2015-02-28
- * ```
+ * Has the same behavior as `addMonths()`.
*
* @param int $value The number of months to remove.
* @return static
*/
- public function subMonths($value)
+ public function subMonths(int $value): ChronosInterface
{
return $this->addMonths(-1 * $value);
}
@@ -388,45 +447,59 @@ public function subMonths($value)
* Add months with overflowing to the instance. Positive $value
* travels forward while negative $value travels into the past.
*
+ * If the new date does not exist, the days overflow into the next month.
+ *
+ * ### Example:
+ *
+ * ```
+ * (new Chronos('2012-01-30'))->addMonthsWithOverflow(1); // Results in 2013-03-01
+ * ```
+ *
* @param int $value The number of months to add.
* @return static
*/
- public function addMonthsWithOverflow($value)
+ public function addMonthsWithOverflow(int $value): ChronosInterface
{
- return $this->modify((int)$value . ' month');
+ return $this->modify($value . ' month');
}
/**
- * Add a month with overflow to the instance
+ * Add a month with overflow to the instance.
+ *
+ * Has the same behavior as `addMonthsWithOverflow()`.
*
* @param int $value The number of months to add.
* @return static
*/
- public function addMonthWithOverflow($value = 1)
+ public function addMonthWithOverflow(int $value = 1): ChronosInterface
{
- return $this->modify((int)$value . ' month');
+ return $this->modify($value . ' month');
}
/**
- * Remove a month with overflow from the instance
+ * Remove months with overflow from the instance.
+ *
+ * Has the same behavior as `addMonthsWithOverflow()`.
*
* @param int $value The number of months to remove.
* @return static
*/
- public function subMonthWithOverflow($value = 1)
+ public function subMonthsWithOverflow(int $value): ChronosInterface
{
- return $this->subMonthsWithOverflow($value);
+ return $this->addMonthsWithOverflow(-1 * $value);
}
/**
- * Remove months with overflow from the instance
+ * Remove a month with overflow from the instance.
+ *
+ * Has the same behavior as `addMonthsWithOverflow()`.
*
* @param int $value The number of months to remove.
* @return static
*/
- public function subMonthsWithOverflow($value)
+ public function subMonthWithOverflow(int $value = 1): ChronosInterface
{
- return $this->addMonthsWithOverflow(-1 * $value);
+ return $this->subMonthsWithOverflow($value);
}
/**
@@ -436,10 +509,8 @@ public function subMonthsWithOverflow($value)
* @param int $value The number of days to add.
* @return static
*/
- public function addDays($value)
+ public function addDays(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value day");
}
@@ -449,10 +520,8 @@ public function addDays($value)
* @param int $value The number of days to add.
* @return static
*/
- public function addDay($value = 1)
+ public function addDay(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value day");
}
@@ -462,10 +531,8 @@ public function addDay($value = 1)
* @param int $value The number of days to remove.
* @return static
*/
- public function subDay($value = 1)
+ public function subDay(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value day");
}
@@ -475,10 +542,8 @@ public function subDay($value = 1)
* @param int $value The number of days to remove.
* @return static
*/
- public function subDays($value)
+ public function subDays(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value day");
}
@@ -489,7 +554,7 @@ public function subDays($value)
* @param int $value The number of weekdays to add.
* @return static
*/
- public function addWeekdays($value)
+ public function addWeekdays(int $value): ChronosInterface
{
return $this->modify((int)$value . ' weekdays ' . $this->format('H:i:s'));
}
@@ -500,7 +565,7 @@ public function addWeekdays($value)
* @param int $value The number of weekdays to add.
* @return static
*/
- public function addWeekday($value = 1)
+ public function addWeekday(int $value = 1): ChronosInterface
{
return $this->addWeekdays($value);
}
@@ -511,10 +576,8 @@ public function addWeekday($value = 1)
* @param int $value The number of weekdays to remove.
* @return static
*/
- public function subWeekdays($value)
+ public function subWeekdays(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value weekdays ago, " . $this->format('H:i:s'));
}
@@ -524,7 +587,7 @@ public function subWeekdays($value)
* @param int $value The number of weekdays to remove.
* @return static
*/
- public function subWeekday($value = 1)
+ public function subWeekday(int $value = 1): ChronosInterface
{
return $this->subWeekdays($value);
}
@@ -536,10 +599,8 @@ public function subWeekday($value = 1)
* @param int $value The number of weeks to add.
* @return static
*/
- public function addWeeks($value)
+ public function addWeeks(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value week");
}
@@ -549,10 +610,8 @@ public function addWeeks($value)
* @param int $value The number of weeks to add.
* @return static
*/
- public function addWeek($value = 1)
+ public function addWeek(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value week");
}
@@ -562,10 +621,8 @@ public function addWeek($value = 1)
* @param int $value The number of weeks to remove.
* @return static
*/
- public function subWeek($value = 1)
+ public function subWeek(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value week");
}
@@ -575,10 +632,8 @@ public function subWeek($value = 1)
* @param int $value The number of weeks to remove.
* @return static
*/
- public function subWeeks($value)
+ public function subWeeks(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value week");
}
@@ -589,10 +644,8 @@ public function subWeeks($value)
* @param int $value The number of hours to add.
* @return static
*/
- public function addHours($value)
+ public function addHours(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value hour");
}
@@ -602,10 +655,8 @@ public function addHours($value)
* @param int $value The number of hours to add.
* @return static
*/
- public function addHour($value = 1)
+ public function addHour(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value hour");
}
@@ -615,10 +666,8 @@ public function addHour($value = 1)
* @param int $value The number of hours to remove.
* @return static
*/
- public function subHour($value = 1)
+ public function subHour(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value hour");
}
@@ -628,10 +677,8 @@ public function subHour($value = 1)
* @param int $value The number of hours to remove.
* @return static
*/
- public function subHours($value)
+ public function subHours(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value hour");
}
@@ -642,10 +689,8 @@ public function subHours($value)
* @param int $value The number of minutes to add.
* @return static
*/
- public function addMinutes($value)
+ public function addMinutes(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value minute");
}
@@ -655,10 +700,8 @@ public function addMinutes($value)
* @param int $value The number of minutes to add.
* @return static
*/
- public function addMinute($value = 1)
+ public function addMinute(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value minute");
}
@@ -668,10 +711,8 @@ public function addMinute($value = 1)
* @param int $value The number of minutes to remove.
* @return static
*/
- public function subMinute($value = 1)
+ public function subMinute(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value minute");
}
@@ -681,10 +722,8 @@ public function subMinute($value = 1)
* @param int $value The number of minutes to remove.
* @return static
*/
- public function subMinutes($value)
+ public function subMinutes(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value minute");
}
@@ -695,10 +734,8 @@ public function subMinutes($value)
* @param int $value The number of seconds to add.
* @return static
*/
- public function addSeconds($value)
+ public function addSeconds(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value second");
}
@@ -708,10 +745,8 @@ public function addSeconds($value)
* @param int $value The number of seconds to add.
* @return static
*/
- public function addSecond($value = 1)
+ public function addSecond(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("$value second");
}
@@ -721,10 +756,8 @@ public function addSecond($value = 1)
* @param int $value The number of seconds to remove.
* @return static
*/
- public function subSecond($value = 1)
+ public function subSecond(int $value = 1): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value second");
}
@@ -734,10 +767,8 @@ public function subSecond($value = 1)
* @param int $value The number of seconds to remove.
* @return static
*/
- public function subSeconds($value)
+ public function subSeconds(int $value): ChronosInterface
{
- $value = (int)$value;
-
return $this->modify("-$value second");
}
@@ -746,7 +777,7 @@ public function subSeconds($value)
*
* @return static
*/
- public function startOfDay()
+ public function startOfDay(): ChronosInterface
{
return $this->modify('midnight');
}
@@ -756,7 +787,7 @@ public function startOfDay()
*
* @return static
*/
- public function endOfDay()
+ public function endOfDay(): ChronosInterface
{
return $this->modify('23:59:59');
}
@@ -766,7 +797,7 @@ public function endOfDay()
*
* @return static
*/
- public function startOfMonth()
+ public function startOfMonth(): ChronosInterface
{
return $this->modify('first day of this month midnight');
}
@@ -776,7 +807,7 @@ public function startOfMonth()
*
* @return static
*/
- public function endOfMonth()
+ public function endOfMonth(): ChronosInterface
{
return $this->modify('last day of this month, 23:59:59');
}
@@ -786,7 +817,7 @@ public function endOfMonth()
*
* @return static
*/
- public function startOfYear()
+ public function startOfYear(): ChronosInterface
{
return $this->modify('first day of january midnight');
}
@@ -796,7 +827,7 @@ public function startOfYear()
*
* @return static
*/
- public function endOfYear()
+ public function endOfYear(): ChronosInterface
{
return $this->modify('last day of december, 23:59:59');
}
@@ -806,7 +837,7 @@ public function endOfYear()
*
* @return static
*/
- public function startOfDecade()
+ public function startOfDecade(): ChronosInterface
{
$year = $this->year - $this->year % ChronosInterface::YEARS_PER_DECADE;
@@ -818,7 +849,7 @@ public function startOfDecade()
*
* @return static
*/
- public function endOfDecade()
+ public function endOfDecade(): ChronosInterface
{
$year = $this->year - $this->year % ChronosInterface::YEARS_PER_DECADE + ChronosInterface::YEARS_PER_DECADE - 1;
@@ -830,9 +861,11 @@ public function endOfDecade()
*
* @return static
*/
- public function startOfCentury()
+ public function startOfCentury(): ChronosInterface
{
- $year = $this->startOfYear()->year(($this->year - 1) - ($this->year - 1) % ChronosInterface::YEARS_PER_CENTURY + 1)->year;
+ $year = $this->startOfYear()
+ ->year($this->year - 1 - ($this->year - 1) % ChronosInterface::YEARS_PER_CENTURY + 1)
+ ->year;
return $this->modify("first day of january $year, midnight");
}
@@ -842,9 +875,16 @@ public function startOfCentury()
*
* @return static
*/
- public function endOfCentury()
+ public function endOfCentury(): ChronosInterface
{
- $year = $this->endOfYear()->year(($this->year - 1) - ($this->year - 1) % ChronosInterface::YEARS_PER_CENTURY + ChronosInterface::YEARS_PER_CENTURY)->year;
+ $y = $this->year - 1
+ - ($this->year - 1)
+ % ChronosInterface::YEARS_PER_CENTURY
+ + ChronosInterface::YEARS_PER_CENTURY;
+
+ $year = $this->endOfYear()
+ ->year($y)
+ ->year;
return $this->modify("last day of december $year, 23:59:59");
}
@@ -854,7 +894,7 @@ public function endOfCentury()
*
* @return static
*/
- public function startOfWeek()
+ public function startOfWeek(): ChronosInterface
{
$dt = $this;
if ($dt->dayOfWeek !== static::$weekStartsAt) {
@@ -869,7 +909,7 @@ public function startOfWeek()
*
* @return static
*/
- public function endOfWeek()
+ public function endOfWeek(): ChronosInterface
{
$dt = $this;
if ($dt->dayOfWeek !== static::$weekEndsAt) {
@@ -888,7 +928,7 @@ public function endOfWeek()
* @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function next($dayOfWeek = null)
+ public function next(?int $dayOfWeek = null)
{
if ($dayOfWeek === null) {
$dayOfWeek = $this->dayOfWeek;
@@ -908,7 +948,7 @@ public function next($dayOfWeek = null)
* @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function previous($dayOfWeek = null)
+ public function previous(?int $dayOfWeek = null)
{
if ($dayOfWeek === null) {
$dayOfWeek = $this->dayOfWeek;
@@ -928,7 +968,7 @@ public function previous($dayOfWeek = null)
* @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function firstOfMonth($dayOfWeek = null)
+ public function firstOfMonth(?int $dayOfWeek = null)
{
$day = $dayOfWeek === null ? 'day' : static::$days[$dayOfWeek];
@@ -944,7 +984,7 @@ public function firstOfMonth($dayOfWeek = null)
* @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function lastOfMonth($dayOfWeek = null)
+ public function lastOfMonth(?int $dayOfWeek = null)
{
$day = $dayOfWeek === null ? 'day' : static::$days[$dayOfWeek];
@@ -961,13 +1001,13 @@ public function lastOfMonth($dayOfWeek = null)
* @param int $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function nthOfMonth($nth, $dayOfWeek)
+ public function nthOfMonth(int $nth, int $dayOfWeek)
{
$dt = $this->copy()->firstOfMonth();
$check = $dt->format('Y-m');
$dt = $dt->modify("+$nth " . static::$days[$dayOfWeek]);
- return ($dt->format('Y-m') === $check) ? $dt : false;
+ return $dt->format('Y-m') === $check ? $dt : false;
}
/**
@@ -979,9 +1019,12 @@ public function nthOfMonth($nth, $dayOfWeek)
* @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function firstOfQuarter($dayOfWeek = null)
+ public function firstOfQuarter(?int $dayOfWeek = null)
{
- return $this->day(1)->month($this->quarter * ChronosInterface::MONTHS_PER_QUARTER - 2)->firstOfMonth($dayOfWeek);
+ return $this
+ ->day(1)
+ ->month($this->quarter * ChronosInterface::MONTHS_PER_QUARTER - 2)
+ ->firstOfMonth($dayOfWeek);
}
/**
@@ -993,9 +1036,12 @@ public function firstOfQuarter($dayOfWeek = null)
* @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function lastOfQuarter($dayOfWeek = null)
+ public function lastOfQuarter(?int $dayOfWeek = null)
{
- return $this->day(1)->month($this->quarter * ChronosInterface::MONTHS_PER_QUARTER)->lastOfMonth($dayOfWeek);
+ return $this
+ ->day(1)
+ ->month($this->quarter * ChronosInterface::MONTHS_PER_QUARTER)
+ ->lastOfMonth($dayOfWeek);
}
/**
@@ -1008,14 +1054,14 @@ public function lastOfQuarter($dayOfWeek = null)
* @param int $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function nthOfQuarter($nth, $dayOfWeek)
+ public function nthOfQuarter(int $nth, int $dayOfWeek)
{
$dt = $this->copy()->day(1)->month($this->quarter * ChronosInterface::MONTHS_PER_QUARTER);
$lastMonth = $dt->month;
$year = $dt->year;
$dt = $dt->firstOfQuarter()->modify("+$nth" . static::$days[$dayOfWeek]);
- return ($lastMonth < $dt->month || $year !== $dt->year) ? false : $dt;
+ return $lastMonth < $dt->month || $year !== $dt->year ? false : $dt;
}
/**
@@ -1027,7 +1073,7 @@ public function nthOfQuarter($nth, $dayOfWeek)
* @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function firstOfYear($dayOfWeek = null)
+ public function firstOfYear(?int $dayOfWeek = null)
{
$day = $dayOfWeek === null ? 'day' : static::$days[$dayOfWeek];
@@ -1043,7 +1089,7 @@ public function firstOfYear($dayOfWeek = null)
* @param int|null $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function lastOfYear($dayOfWeek = null)
+ public function lastOfYear(?int $dayOfWeek = null)
{
$day = $dayOfWeek === null ? 'day' : static::$days[$dayOfWeek];
@@ -1060,7 +1106,7 @@ public function lastOfYear($dayOfWeek = null)
* @param int $dayOfWeek The day of the week to move to.
* @return mixed
*/
- public function nthOfYear($nth, $dayOfWeek)
+ public function nthOfYear(int $nth, int $dayOfWeek)
{
$dt = $this->copy()->firstOfYear()->modify("+$nth " . static::$days[$dayOfWeek]);
@@ -1073,9 +1119,9 @@ public function nthOfYear($nth, $dayOfWeek)
* @param \Cake\Chronos\ChronosInterface|null $dt The instance to compare with.
* @return static
*/
- public function average(ChronosInterface $dt = null)
+ public function average(?ChronosInterface $dt = null): ChronosInterface
{
- $dt = ($dt === null) ? static::now($this->tz) : $dt;
+ $dt = $dt ?? static::now($this->tz);
return $this->addSeconds((int)($this->diffInSeconds($dt, false) / 2));
}
diff --git a/app/vendor/cakephp/chronos/src/Traits/RelativeKeywordTrait.php b/app/vendor/cakephp/chronos/src/Traits/RelativeKeywordTrait.php
index 69c6cd66c..c98e92796 100644
--- a/app/vendor/cakephp/chronos/src/Traits/RelativeKeywordTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/RelativeKeywordTrait.php
@@ -1,4 +1,6 @@
0;
}
return false;
}
+
+ /**
+ * Determines if there is no fixed date in the time string.
+ *
+ * @param \DateTimeInterface|string|null $time The time string to check
+ * @return bool true if doesn't contain a fixed date
+ */
+ private static function isRelativeOnly($time): bool
+ {
+ if ($time === null) {
+ return true;
+ }
+
+ if (!is_string($time)) {
+ return false;
+ }
+
+ // must not contain fixed date before relative keywords or time expression
+ return preg_match('/[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}/', $time) !== 1;
+ }
}
diff --git a/app/vendor/cakephp/chronos/src/Traits/TestingAidTrait.php b/app/vendor/cakephp/chronos/src/Traits/TestingAidTrait.php
index 19f8732c6..ab2fef877 100644
--- a/app/vendor/cakephp/chronos/src/Traits/TestingAidTrait.php
+++ b/app/vendor/cakephp/chronos/src/Traits/TestingAidTrait.php
@@ -1,4 +1,6 @@
setTimezone($value);
}
@@ -35,7 +40,7 @@ public function timezone($value)
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return static
*/
- public function tz($value)
+ public function tz($value): ChronosInterface
{
return $this->setTimezone($value);
}
@@ -46,15 +51,9 @@ public function tz($value)
* @param \DateTimeZone|string $value The DateTimeZone object or timezone name to use.
* @return static
*/
- public function setTimezone($value)
+ #[ReturnTypeWillChange]
+ public function setTimezone($value): ChronosInterface
{
- $date = parent::setTimezone(static::safeCreateDateTimeZone($value));
-
- // https://bugs.php.net/bug.php?id=72338
- // this is workaround for this bug
- // Needed for PHP below 7.0 version
- $date->getTimestamp();
-
- return $date;
+ return parent::setTimezone(static::safeCreateDateTimeZone($value));
}
}
diff --git a/app/vendor/cakephp/chronos/src/Translator.php b/app/vendor/cakephp/chronos/src/Translator.php
index e5f97886c..382bfd484 100644
--- a/app/vendor/cakephp/chronos/src/Translator.php
+++ b/app/vendor/cakephp/chronos/src/Translator.php
@@ -1,4 +1,6 @@
singular($key, $vars);
@@ -77,7 +79,7 @@ public function plural($key, $count, array $vars = [])
* @param array $vars Additional context variables.
* @return string The translated message or ''.
*/
- public function singular($key, array $vars = [])
+ public function singular(string $key, array $vars = []): string
{
if (isset(static::$strings[$key])) {
$varKeys = array_keys($vars);
diff --git a/app/vendor/cakephp/chronos/src/carbon_compat.php b/app/vendor/cakephp/chronos/src/carbon_compat.php
index f947cb752..0d8eff724 100644
--- a/app/vendor/cakephp/chronos/src/carbon_compat.php
+++ b/app/vendor/cakephp/chronos/src/carbon_compat.php
@@ -1,4 +1,6 @@
='));
-if (!class_exists('Carbon\Carbon')) {
+// Check if the interface alias exists and don't redeclare it in case we are in
+// a preloaded context.
+if (!\class_exists('Carbon\Carbon') && !\interface_exists('Carbon\CarbonInterface', false)) {
// Create class aliases for Carbon so applications
// can upgrade more easily.
class_alias('Cake\Chronos\Chronos', 'Carbon\MutableDateTime');
diff --git a/app/vendor/cakephp/debug_kit/.github/workflows/ci.yml b/app/vendor/cakephp/debug_kit/.github/workflows/ci.yml
deleted file mode 100644
index 5c039aaf5..000000000
--- a/app/vendor/cakephp/debug_kit/.github/workflows/ci.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-name: CI
-
-
-on:
- push:
- branches:
- - 3.x
- pull_request:
- branches:
- - '*'
-
-jobs:
- testsuite-linux:
- runs-on: ubuntu-18.04
- strategy:
- fail-fast: false
- matrix:
- php-version: ['5.6', '7.4']
- db-type: [mysql, pgsql, sqlite]
- prefer-lowest: ['']
- include:
- - php-version: '5.6'
- db-type: 'sqlite'
- prefer-lowest: 'prefer-lowest'
-
- services:
- postgres:
- image: postgres
- ports:
- - 5432:5432
- env:
- POSTGRES_PASSWORD: postgres
-
- steps:
- - uses: actions/checkout@v2
-
- - name: Setup Service
- if: matrix.db-type == 'mysql'
- run: |
- sudo service mysql start
- mysql -h 127.0.0.1 -u root -proot -e 'CREATE DATABASE cakephp;'
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php-version }}
- extensions: mbstring, intl, pdo_${{ matrix.db-type }}
- coverage: pcov
-
- - name: Get composer cache directory
- id: composer-cache
- run: echo "::set-output name=dir::$(composer config cache-files-dir)"
-
- - name: Get date part for cache key
- id: key-date
- run: echo "::set-output name=date::$(date +'%Y-%m')"
-
- - name: Cache composer dependencies
- uses: actions/cache@v1
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }}
-
- - name: Composer install
- run: |
- if ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then
- composer update --prefer-lowest --prefer-stable
- else
- composer update
- fi
-
- - name: Run PHPUnit
- run: |
- if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then
- export DB_URL='sqlite://./tests.sqlite'
- fi
- if [[ ${{ matrix.db-type }} == 'mysql' ]]; then
- export DB_URL='mysql://root:root@127.0.0.1/cakephp'
- fi
- if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then
- export DB_URL='postgres://postgres:postgres@127.0.0.1/postgres'
- fi
- if [[ ${{ matrix.php-version }} == '7.4' && ${{ matrix.db-type }} == 'mysql' ]]; then
- vendor/bin/phpunit --coverage-clover=coverage.xml
- else
- vendor/bin/phpunit
- fi
-
- - name: Code Coverage Report
- if: matrix.php-version == '7.4' && matrix.db-type == 'mysql'
- uses: codecov/codecov-action@v1
diff --git a/app/vendor/cakephp/debug_kit/README.md b/app/vendor/cakephp/debug_kit/README.md
index 5cb12fc3e..53ab6e165 100644
--- a/app/vendor/cakephp/debug_kit/README.md
+++ b/app/vendor/cakephp/debug_kit/README.md
@@ -37,10 +37,6 @@ php composer.phar require --dev cakephp/debug_kit:"~3.0"
// src/Application.php
$this->addPlugin('DebugKit');
```
-Prior to 3.6.0
-```php
-Plugin::load('DebugKit', ['bootstrap' => true, 'routes' => true]);
-```
* Set `'debug' => true,` in `config/app.php`.
## Reporting Issues
diff --git a/app/vendor/cakephp/debug_kit/composer.json b/app/vendor/cakephp/debug_kit/composer.json
index a075b83bd..34c89f83b 100644
--- a/app/vendor/cakephp/debug_kit/composer.json
+++ b/app/vendor/cakephp/debug_kit/composer.json
@@ -23,17 +23,16 @@
"source": "https://github.com/cakephp/debug_kit"
},
"require": {
- "php": ">=5.6.0",
- "cakephp/cakephp": "^3.7.0",
- "cakephp/chronos": "^1.0.0",
- "composer/composer": "^1.3 | ^2.0",
- "jdorn/sql-formatter": "^1.2.0"
+ "php": ">=7.2",
+ "cakephp/cakephp": "^4.0",
+ "cakephp/chronos": "^2.0",
+ "composer/composer": "^1.3",
+ "jdorn/sql-formatter": "^1.2"
},
"require-dev": {
- "cakephp/authorization": "^1.3.2",
- "cakephp/cakephp-codesniffer": "^3.0",
- "cakephp/plugin-installer": "^1.3",
- "phpunit/phpunit": "^5.7.14|^6.0"
+ "cakephp/cakephp-codesniffer": "^4.0",
+ "cakephp/authorization": "^2.0",
+ "phpunit/phpunit": "^8.0"
},
"autoload": {
"psr-4": {
@@ -53,11 +52,11 @@
"ext-pdo_sqlite": "DebugKit needs to store panel data in a database. SQLite is simple and easy to use."
},
"scripts": {
- "check": [
- "@cs-check",
- "@test"
- ],
- "cs-check": "phpcs --colors -p src/ tests/",
- "cs-fix": "phpcbf --colors -p src/ tests/"
- }
+ "cs-check": "phpcs --colors --parallel=16 -p src/ tests/",
+ "cs-fix": "phpcbf --colors --parallel=16 -p src/ tests/",
+ "test": "phpunit",
+ "psalm": "psalm.phar --show-info=false",
+ "psalm-setup": "cp composer.json composer.backup && composer require --dev psalm/phar:^3.11 && mv composer.backup composer.json"
+ },
+ "prefer-stable": true
}
diff --git a/app/vendor/cakephp/debug_kit/config/bootstrap.php b/app/vendor/cakephp/debug_kit/config/bootstrap.php
index 5b368080d..6e8e0d64e 100644
--- a/app/vendor/cakephp/debug_kit/config/bootstrap.php
+++ b/app/vendor/cakephp/debug_kit/config/bootstrap.php
@@ -1,4 +1,6 @@
isEnabled() || php_sapi_name() === 'cli' || php_sapi_name() === 'phpdbg') {
- return;
-}
-
-if (!empty($service->getConfig('panels')['DebugKit.Deprecations'])) {
- $errorLevel = Configure::read('Error.errorLevel', E_ALL | E_STRICT);
- $previousHandler = set_error_handler(
- function ($code, $message, $file, $line, $context = null) use (&$previousHandler) {
- if ($code == E_USER_DEPRECATED || $code == E_DEPRECATED) {
- DeprecationsPanel::addDeprecatedError(compact('code', 'message', 'file', 'line', 'context'));
-
- return;
- }
- if ($previousHandler) {
- $context['_trace_frame_offset'] = 1;
- return $previousHandler($code, $message, $file, $line, $context);
- }
- },
- $errorLevel | E_USER_DEPRECATED | E_DEPRECATED
- );
-}
$hasDebugKitConfig = ConnectionManager::getConfig('debug_kit');
if (!$hasDebugKitConfig && !in_array('sqlite', PDO::getAvailableDrivers())) {
@@ -67,23 +37,6 @@ function ($code, $message, $file, $line, $context = null) use (&$previousHandler
]);
}
-if (!CorePlugin::getCollection()->get('DebugKit')->isEnabled('routes')) {
- include dirname(__FILE__) . DIRECTORY_SEPARATOR . 'routes.php';
-}
-
-$appClass = Configure::read('App.namespace') . '\Application';
-if (class_exists($appClass)) {
- EventManager::instance()->on('Server.buildMiddleware', function ($event, $queue) use ($service) {
- $middleware = new DebugKitMiddleware($service);
- $queue->insertAt(0, $middleware);
- });
-} else {
- // Setup dispatch filter
- $debugBar = new DebugBarFilter(EventManager::instance(), (array)Configure::read('DebugKit'));
- $debugBar->setup();
- DispatcherFactory::add($debugBar);
-}
-
if (!function_exists('sql')) {
/**
* Prints out the SQL statements generated by a Query object.
@@ -91,11 +44,11 @@ function ($code, $message, $file, $line, $context = null) use (&$previousHandler
* This function returns the same variable that was passed.
* Only runs if debug mode is enabled.
*
- * @param Query $query Query to show SQL statements for.
+ * @param \Cake\Database\Query $query Query to show SQL statements for.
* @param bool $showValues Renders the SQL statement with bound variables.
* @param bool|null $showHtml If set to true, the method prints the debug
* data in a browser-friendly way.
- * @return Query
+ * @return \Cake\Database\Query
*/
function sql(Query $query, $showValues = true, $showHtml = null)
{
@@ -110,7 +63,7 @@ function sql(Query $query, $showValues = true, $showHtml = null)
* Only runs if debug mode is enabled.
* It will otherwise just continue code execution and ignore this function.
*
- * @param Query $query Query to show SQL statements for.
+ * @param \Cake\Database\Query $query Query to show SQL statements for.
* @param bool $showValues Renders the SQL statement with bound variables.
* @param bool|null $showHtml If set to true, the method prints the debug
* data in a browser-friendly way.
diff --git a/app/vendor/cakephp/debug_kit/config/routes.php b/app/vendor/cakephp/debug_kit/config/routes.php
index 4645f19cf..bd5052c90 100644
--- a/app/vendor/cakephp/debug_kit/config/routes.php
+++ b/app/vendor/cakephp/debug_kit/config/routes.php
@@ -36,7 +36,7 @@ function (RouteBuilder $routes) {
$routes->connect('/', ['action' => 'index']);
$routes->connect('/preview', ['action' => 'email']);
$routes->connect('/preview/*', ['action' => 'email']);
- $routes->connect('/sent/:panel/:id', ['action' => 'sent'], ['pass' => ['panel', 'id']]);
+ $routes->connect('/sent/{panel}/{id}', ['action' => 'sent'], ['pass' => ['panel', 'id']]);
}
);
diff --git a/app/vendor/cakephp/debug_kit/docs/config/all.py b/app/vendor/cakephp/debug_kit/docs/config/all.py
index fcc02a3c9..6b3fbc8de 100644
--- a/app/vendor/cakephp/debug_kit/docs/config/all.py
+++ b/app/vendor/cakephp/debug_kit/docs/config/all.py
@@ -10,10 +10,10 @@
#
# The full version, including alpha/beta/rc tags.
-release = '3.x'
+release = '4.x'
# The search index version.
-search_version = 'debugkit-3'
+search_version = 'debugkit-4'
# The marketing display name for the book.
version_name = ''
@@ -23,8 +23,8 @@
# Other versions that display in the version picker menu.
version_list = [
- {'name': '3.x', 'number': '/debugkit/3', 'title': '3.x', 'current': True},
- {'name': '4.x', 'number': '/debugkit/4', 'title': '4.x'},
+ {'name': '3.x', 'number': 'debugkit/3.x', 'title': '3.x'},
+ {'name': '4.x', 'number': 'debugkit/4.x', 'title': '4.x', 'current': True},
]
# Languages available.
@@ -32,10 +32,10 @@
# The GitHub branch name for this version of the docs
# for edit links to point at.
-branch = '3.x'
+branch = '4.x'
# Current version being built
-version = '3.x'
+version = '4.x'
# Language in use for this directory.
language = 'en'
diff --git a/app/vendor/cakephp/debug_kit/docs/en/index.rst b/app/vendor/cakephp/debug_kit/docs/en/index.rst
index d7b8677dd..aab4ab73f 100644
--- a/app/vendor/cakephp/debug_kit/docs/en/index.rst
+++ b/app/vendor/cakephp/debug_kit/docs/en/index.rst
@@ -20,7 +20,7 @@ you've removed it and want to re-install it, you can do so by running the
following from your application's ROOT directory (where composer.json file is
located)::
- php composer.phar require --dev cakephp/debug_kit "~3.0"
+ php composer.phar require --dev cakephp/debug_kit "~4.0"
Then, you need to enable the plugin by executing the following line::
@@ -50,6 +50,12 @@ Configuration
// Before loading DebugKit
Configure::write('DebugKit.forceEnable', true);
+* ``DebugKit.ignorePathsPattern`` - Regex pattern (including delimiter) to ignore paths.
+ DebugKit won't save data for request URLs that match this regex. Defaults to ``null``::
+
+ // Ignore image paths
+ Configure::write('DebugKit.ignorePathsPattern', '/\.(jpg|png|gif)$/');
+
* ``DebugKit.ignoreAuthorization`` - Set to true to ignore Cake Authorization plugin for DebugKit requests. Disabled by default.
Database Configuration
@@ -58,7 +64,7 @@ Database Configuration
By default DebugKit will store panel data into a SQLite database in your
application's ``tmp`` directory. If you cannot install pdo_sqlite, you can
configure DebugKit to use a different database by defining a ``debug_kit``
-connection in your **config/app.php** file. For example::
+connection in the ``Datasources`` variable in your **config/app.php** file. For example::
/**
* The debug_kit connection stores DebugKit meta-data.
diff --git a/app/vendor/cakephp/debug_kit/docs/fr/index.rst b/app/vendor/cakephp/debug_kit/docs/fr/index.rst
index 209477f6d..bbfd7981a 100644
--- a/app/vendor/cakephp/debug_kit/docs/fr/index.rst
+++ b/app/vendor/cakephp/debug_kit/docs/fr/index.rst
@@ -24,7 +24,7 @@ le retirez et voulez le réinstaller, vous pouvez le faire en lançant ce qui
suit à partir du répertoire ROOT de votre application (où le fichier
composer.json est localisé)::
- php composer.phar require --dev cakephp/debug_kit "~3.0"
+ php composer.phar require --dev cakephp/debug_kit "~4.0"
Ensuite, vous devez activer le plugin en exécutant la ligne suivante::
diff --git a/app/vendor/cakephp/debug_kit/docs/ja/index.rst b/app/vendor/cakephp/debug_kit/docs/ja/index.rst
index a6f0277cf..5ff72bc20 100644
--- a/app/vendor/cakephp/debug_kit/docs/ja/index.rst
+++ b/app/vendor/cakephp/debug_kit/docs/ja/index.rst
@@ -18,7 +18,7 @@ DebugKit は、CakePHP アプリケーション用のデバッグツールバー
もし削除してしまって再インストールしたい場合は、以下のコマンドをアプリケーションの
ルートディレクトリー (composer.json ファイルのある場所) で実行してください。 ::
- php composer.phar require --dev cakephp/debug_kit "~3.0"
+ php composer.phar require --dev cakephp/debug_kit "~4.0"
そして以下のコマンドでプラグインを有効化する必要があります。 ::
diff --git a/app/vendor/cakephp/debug_kit/docs/pt/index.rst b/app/vendor/cakephp/debug_kit/docs/pt/index.rst
index d73d860c6..583de577e 100644
--- a/app/vendor/cakephp/debug_kit/docs/pt/index.rst
+++ b/app/vendor/cakephp/debug_kit/docs/pt/index.rst
@@ -12,7 +12,7 @@ você o removeu e gostaria de reinstalá-lo, você pode executar o seguinte coma
a partir do diretório raiz da aplicação
(onde o arquivo composer.json está localizado)::
- php composer.phar require --dev cakephp/debug_kit "~3.0"
+ php composer.phar require --dev cakephp/debug_kit "~4.0"
Então, você precisará habilitar o plugin ao executar o seguinte comando::
diff --git a/app/vendor/cakephp/debug_kit/psalm-baseline.xml b/app/vendor/cakephp/debug_kit/psalm-baseline.xml
new file mode 100644
index 000000000..a2edeb09b
--- /dev/null
+++ b/app/vendor/cakephp/debug_kit/psalm-baseline.xml
@@ -0,0 +1,156 @@
+
+
+
+
+ \Cake\Http\Response
+
+
+ $this->redirect(['action' => 'index'])
+
+
+
+
+ $partType
+
+
+
+
+ $query->query
+
+
+
+
+ string
+
+
+ $this->_pluginPaths
+ $this->_composerPaths
+
+
+ $name
+
+
+
+
+ bindings
+
+
+
+
+ self::$_timers
+
+
+
+
+ $type
+
+
+
+
+ $pos
+
+
+
+
+ $result
+
+
+ array
+
+
+ new $className($config)
+
+
+
+
+ $request
+
+
+
+
+ new $class($connection->configName())
+
+
+
+
+ $pluginName
+ $vendorName
+ $return['plugins']
+ $return['vendor']
+
+
+
+
+ $var['user']
+
+
+
+
+ $pluginName
+ $vendorName
+ $return['plugins']
+ $return['vendor']
+
+
+
+
+ count
+
+
+
+
+ $transport
+
+
+
+
+ $instance
+
+
+ string|null
+
+
+ $instance
+
+
+ $class
+
+
+ \DebugKit\DebugPanel
+
+
+
+
+ genericInstances
+
+
+
+
+ $item
+
+
+ $item
+ $item
+ $item
+
+
+
+
+
+
+
+ $row->id
+
+
+ env('HTTP_HOST')
+
+
+ $url === false
+
+
+
+
+ $value
+
+
+
diff --git a/app/vendor/cakephp/debug_kit/psalm.xml b/app/vendor/cakephp/debug_kit/psalm.xml
new file mode 100644
index 000000000..02997ec3b
--- /dev/null
+++ b/app/vendor/cakephp/debug_kit/psalm.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/vendor/cakephp/debug_kit/src/Cache/Engine/DebugEngine.php b/app/vendor/cakephp/debug_kit/src/Cache/Engine/DebugEngine.php
index 3634e5579..ec9213e23 100644
--- a/app/vendor/cakephp/debug_kit/src/Cache/Engine/DebugEngine.php
+++ b/app/vendor/cakephp/debug_kit/src/Cache/Engine/DebugEngine.php
@@ -1,4 +1,6 @@
0,
+ protected $metrics = [
+ 'set' => 0,
'delete' => 0,
- 'read' => 0,
- 'hit' => 0,
- 'miss' => 0,
+ 'get hit' => 0,
+ 'get miss' => 0,
];
/**
* Constructor
*
* @param mixed $config Config data or the proxied adapter.
+ * @param string $name The name of the proxied cache engine.
+ * @param \Psr\Log\LoggerInterface $logger Logger for collecting cache operation logs.
*/
- public function __construct($config)
+ public function __construct($config, string $name, LoggerInterface $logger)
{
$this->_config = $config;
+ $this->logger = $logger;
+ $this->name = $name;
}
/**
@@ -68,7 +81,7 @@ public function __construct($config)
* @param array $config Array of setting for the engine.
* @return bool True, this engine cannot fail to initialize.
*/
- public function init(array $config = [])
+ public function init(array $config = []): bool
{
if (is_object($this->_config)) {
$this->_engine = $this->_config;
@@ -99,7 +112,7 @@ public function engine()
*/
public function metrics()
{
- return $this->_metrics;
+ return $this->metrics;
}
/**
@@ -108,158 +121,173 @@ public function metrics()
* @param string $metric The metric to increment.
* @return void
*/
- protected function _track($metric)
+ protected function track($metric)
{
- $this->_metrics[$metric]++;
+ $this->metrics[$metric]++;
}
/**
- * {@inheritDoc}
+ * Log a cache operation
+ *
+ * @param string $operation The operation performed.
+ * @param float $duration The duration of the operation.
+ * @param string|null $key The cache key.
+ * @return void
+ */
+ protected function log(string $operation, float $duration, ?string $key = null): void
+ {
+ $key = $key ? " `{$key}`" : '';
+ $duration = number_format($duration, 5);
+ $this->logger->log('info', ":{$this->name}: {$operation}{$key} - {$duration}ms");
+ }
+
+ /**
+ * @inheritDoc
*/
- public function write($key, $value)
+ public function set($key, $value, $ttl = null): bool
{
- $this->_track('write');
- DebugTimer::start('Cache.write ' . $key);
- $result = $this->_engine->write($key, $value);
- DebugTimer::stop('Cache.write ' . $key);
+ $start = microtime(true);
+ $result = $this->_engine->set($key, $value, $ttl);
+ $duration = microtime(true) - $start;
+
+ $this->track('set');
+ $this->log('set', $duration, $key);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function writeMany($data)
+ public function setMultiple($data, $ttl = null): bool
{
- $this->_track('write');
- DebugTimer::start('Cache.writeMany');
- $result = $this->_engine->writeMany($data);
- DebugTimer::stop('Cache.writeMany');
+ $start = microtime(true);
+ $result = $this->_engine->setMultiple($data);
+ $duration = microtime(true) - $start;
+
+ $this->track('set');
+ $this->log('setMultiple', $duration);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function read($key)
+ public function get($key, $default = null)
{
- $this->_track('read');
- DebugTimer::start('Cache.read ' . $key);
- $result = $this->_engine->read($key);
- DebugTimer::stop('Cache.read ' . $key);
+ $start = microtime(true);
+ $result = $this->_engine->get($key, $default);
+ $duration = microtime(true) - $start;
$metric = 'hit';
- if ($result === false) {
+ if ($result === null) {
$metric = 'miss';
}
- $this->_track($metric);
+
+ $this->track("get {$metric}");
+ $this->log('get', $duration, $key);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function readMany($data)
+ public function getMultiple($keys, $default = null): iterable
{
- $this->_track('read');
- DebugTimer::start('Cache.readMany');
- $result = $this->_engine->readMany($data);
- DebugTimer::stop('Cache.readMany');
+ $start = microtime(true);
+ $result = $this->_engine->getMultiple($keys);
+ $duration = microtime(true) - $start;
+
+ $this->track('get hit');
+ $this->log('getMultiple', $duration);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function increment($key, $offset = 1)
+ public function increment(string $key, int $offset = 1)
{
- $this->_track('write');
- DebugTimer::start('Cache.increment ' . $key);
+ $start = microtime(true);
$result = $this->_engine->increment($key, $offset);
- DebugTimer::stop('Cache.increment ' . $key);
+ $duration = microtime(true) - $start;
+
+ $this->track('set');
+ $this->log('increment', $duration, $key);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function decrement($key, $offset = 1)
+ public function decrement(string $key, int $offset = 1)
{
- $this->_track('write');
- DebugTimer::start('Cache.decrement ' . $key);
+ $start = microtime(true);
$result = $this->_engine->decrement($key, $offset);
- DebugTimer::stop('Cache.decrement ' . $key);
+ $duration = microtime(true) - $start;
+
+ $this->track('set');
+ $this->log('decrement', $duration, $key);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function delete($key)
+ public function delete($key): bool
{
- $this->_track('delete');
- DebugTimer::start('Cache.delete ' . $key);
+ $start = microtime(true);
$result = $this->_engine->delete($key);
- DebugTimer::stop('Cache.delete ' . $key);
+ $duration = microtime(true) - $start;
+
+ $this->track('delete');
+ $this->log('delete', $duration, $key);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function deleteMany($data)
+ public function deleteMultiple($data): bool
{
- $this->_track('delete');
- DebugTimer::start('Cache.deleteMany');
- $result = $this->_engine->deleteMany($data);
- DebugTimer::stop('Cache.deleteMany');
+ $start = microtime(true);
+ $result = $this->_engine->deleteMultiple($data);
+ $duration = microtime(true) - $start;
+
+ $this->track('delete');
+ $this->log('deleteMultiple', $duration);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function clear($check)
+ public function clear(): bool
{
- $this->_track('delete');
- DebugTimer::start('Cache.clear');
- $result = $this->_engine->clear($check);
- DebugTimer::stop('Cache.clear');
+ $start = microtime(true);
+ $result = $this->_engine->clear();
+ $duration = microtime(true) - $start;
+
+ $this->track('delete');
+ $this->log('clear', $duration);
return $result;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function groups()
+ public function groups(): array
{
return $this->_engine->groups();
}
- /**
- * Return the proxied configuration data.
- *
- * This method uses func_get_args() as not doing so confuses the
- * proxied class.
- *
- * @deprecated 3.6.0 use setConfig()/getConfig() instead.
- * @param string $key The key to set/read.
- * @param mixed $value The value to set.
- * @param bool $merge Whether or not configuration should be merged.
- * @return mixed
- */
- public function config($key = null, $value = null, $merge = true)
- {
- return call_user_func_array([$this->_engine, 'config'], func_get_args());
- }
-
/**
* Returns the config.
*
@@ -267,7 +295,7 @@ public function config($key = null, $value = null, $merge = true)
* @param mixed $default The return value when the key does not exist.
* @return mixed Config value being read.
*/
- public function getConfig($key = null, $default = null)
+ public function getConfig(?string $key = null, $default = null)
{
return $this->_engine->getConfig($key, $default);
}
@@ -287,14 +315,16 @@ public function setConfig($key, $value = null, $merge = true)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function clearGroup($group)
+ public function clearGroup(string $group): bool
{
- $this->_track('delete');
- DebugTimer::start('Cache.clearGroup ' . $group);
+ $start = microtime(true);
$result = $this->_engine->clearGroup($group);
- DebugTimer::stop('Cache.clearGroup ' . $group);
+ $duration = microtime(true) - $start;
+
+ $this->track('delete');
+ $this->log('clearGroup', $duration, $group);
return $result;
}
@@ -307,7 +337,7 @@ public function clearGroup($group)
public function __toString()
{
if (!empty($this->_engine)) {
- list($ns, $class) = namespaceSplit(get_class($this->_engine));
+ [$ns, $class] = namespaceSplit(get_class($this->_engine));
return str_replace('Engine', '', $class);
}
diff --git a/app/vendor/cakephp/debug_kit/src/Command/BenchmarkCommand.php b/app/vendor/cakephp/debug_kit/src/Command/BenchmarkCommand.php
new file mode 100644
index 000000000..b20413fe7
--- /dev/null
+++ b/app/vendor/cakephp/debug_kit/src/Command/BenchmarkCommand.php
@@ -0,0 +1,190 @@
+io = $io;
+ /** @var string $url */
+ $url = $args->getArgumentAt(0);
+ $defaults = ['t' => 100, 'n' => 10];
+ $options = array_merge($defaults, $args->getOptions());
+ $times = [];
+
+ $io->out(Text::insert(__d('debug_kit', '-> Testing :url'), compact('url')));
+ $io->out('');
+ for ($i = 0; $i < $options['n']; $i++) {
+ if (floor($options['t'] - array_sum($times)) <= 0 || $options['n'] <= 1) {
+ break;
+ }
+
+ $start = microtime(true);
+ file_get_contents($url);
+ $stop = microtime(true);
+
+ $times[] = $stop - $start;
+ }
+ $this->_results($times);
+
+ return static::CODE_SUCCESS;
+ }
+
+ /**
+ * Prints calculated results
+ *
+ * @param array $times Array of time values
+ * @return void
+ */
+ protected function _results($times)
+ {
+ $duration = array_sum($times);
+ $requests = count($times);
+
+ $this->io->out(Text::insert(__d('debug_kit', 'Total Requests made: :requests'), compact('requests')));
+ $this->io->out(Text::insert(__d('debug_kit', 'Total Time elapsed: :duration (seconds)'), compact('duration')));
+
+ $this->io->out('');
+
+ $this->io->out(Text::insert(__d('debug_kit', 'Requests/Second: :rps req/sec'), [
+ 'rps' => round($requests / $duration, 3),
+ ]));
+
+ $this->io->out(Text::insert(__d('debug_kit', 'Average request time: :average-time seconds'), [
+ 'average-time' => round($duration / $requests, 3),
+ ]));
+
+ $this->io->out(Text::insert(__d('debug_kit', 'Standard deviation of average request time: :std-dev'), [
+ 'std-dev' => round($this->_deviation($times, true), 3),
+ ]));
+
+ $this->io->out(Text::insert(__d('debug_kit', 'Longest/shortest request: :longest sec/:shortest sec'), [
+ 'longest' => round(max($times), 3),
+ 'shortest' => round(min($times), 3),
+ ]));
+
+ $this->io->out('');
+ }
+
+ /**
+ * One-pass, numerically stable calculation of population variance.
+ *
+ * Donald E. Knuth (1998).
+ * The Art of Computer Programming, volume 2: Seminumerical Algorithms, 3rd edn.,
+ * p. 232. Boston: Addison-Wesley.
+ *
+ * @param array $times Array of values
+ * @param bool $sample If true, calculates an unbiased estimate of the population
+ * variance from a finite sample.
+ * @return float Variance
+ */
+ protected function _variance($times, $sample = true)
+ {
+ $n = $mean = $M2 = 0;
+
+ foreach ($times as $time) {
+ $n += 1;
+ $delta = $time - $mean;
+ $mean = $mean + $delta / $n;
+ $M2 = $M2 + $delta * ($time - $mean);
+ }
+
+ if ($sample) {
+ $n -= 1;
+ }
+
+ return $M2 / $n;
+ }
+
+ /**
+ * Calculate the standard deviation.
+ *
+ * @param array $times Array of values
+ * @param bool $sample ''
+ * @return float Standard deviation
+ */
+ protected function _deviation($times, $sample = true)
+ {
+ return sqrt($this->_variance($times, $sample));
+ }
+
+ /**
+ * Gets the option parser instance and configures it.
+ *
+ * @param \Cake\Console\ConsoleOptionParser $parser The parser to build
+ * @return \Cake\Console\ConsoleOptionParser
+ */
+ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
+ {
+ $parser->setDescription(__d(
+ 'debug_kit',
+ 'Allows you to obtain some rough benchmarking statistics' .
+ 'about a fully qualified URL.'
+ ))
+ ->addArgument('url', [
+ 'help' => __d('debug_kit', 'The URL to request.'),
+ 'required' => true,
+ ])
+ ->addOption('n', [
+ 'default' => 10,
+ 'help' => __d('debug_kit', 'Number of iterations to perform.'),
+ ])
+ ->addOption('t', [
+ 'default' => 100,
+ 'help' => __d(
+ 'debug_kit',
+ 'Maximum total time for all iterations, in seconds.' .
+ 'If a single iteration takes more than the timeout, only one request will be made'
+ ),
+ ])
+ ->setEpilog(__d(
+ 'debug_kit',
+ 'Example Use: `cake benchmark --n 10 --t 100 http://localhost/testsite`. ' .
+ 'Note: this benchmark does not include browser render times.'
+ ));
+
+ return $parser;
+ }
+}
diff --git a/app/vendor/cakephp/debug_kit/src/Controller/Component/ToolbarComponent.php b/app/vendor/cakephp/debug_kit/src/Controller/Component/ToolbarComponent.php
deleted file mode 100644
index 259066f16..000000000
--- a/app/vendor/cakephp/debug_kit/src/Controller/Component/ToolbarComponent.php
+++ /dev/null
@@ -1,45 +0,0 @@
- true, "routes" => true]);`', 'bootstrap.php');
- throw new \RuntimeException($msg);
- }
-}
diff --git a/app/vendor/cakephp/debug_kit/src/Controller/ComposerController.php b/app/vendor/cakephp/debug_kit/src/Controller/ComposerController.php
index 481747418..f26d379d6 100644
--- a/app/vendor/cakephp/debug_kit/src/Controller/ComposerController.php
+++ b/app/vendor/cakephp/debug_kit/src/Controller/ComposerController.php
@@ -1,4 +1,6 @@
loadComponent('RequestHandler');
@@ -69,15 +71,13 @@ public function checkDependencies()
$packages['bcBreaks'] = trim(implode("\n", $packages['bcBreaks']));
}
- $this->set([
- '_serialize' => ['packages'],
- 'packages' => $packages,
- ]);
+ $this->viewBuilder()->setOption('serialize', ['packages']);
+ $this->set('packages', $packages);
}
/**
- * @param ArrayInput $input An array describing the command input
- * @return BufferedOutput Aa Console command buffered result
+ * @param \Symfony\Component\Console\Input\ArrayInput $input An array describing the command input
+ * @return \Symfony\Component\Console\Output\BufferedOutput Aa Console command buffered result
*/
private function executeComposerCommand(ArrayInput $input)
{
@@ -99,7 +99,7 @@ private function executeComposerCommand(ArrayInput $input)
// Restore environment
chdir($dir);
- set_time_limit($timeLimit);
+ set_time_limit((int)$timeLimit);
ini_set('memory_limit', $memoryLimit);
return $output;
diff --git a/app/vendor/cakephp/debug_kit/src/Controller/DashboardController.php b/app/vendor/cakephp/debug_kit/src/Controller/DashboardController.php
index 079db5b21..e69b905f5 100644
--- a/app/vendor/cakephp/debug_kit/src/Controller/DashboardController.php
+++ b/app/vendor/cakephp/debug_kit/src/Controller/DashboardController.php
@@ -1,4 +1,6 @@
skipAuthorization();
} else {
Log::info(
- "Cake Authorization plugin is enabled. If you would like " .
- "to force DebugKit to ignore it, set `DebugKit.ignoreAuthorization` " .
- " Configure option to true."
+ 'Cake Authorization plugin is enabled. If you would like ' .
+ 'to force DebugKit to ignore it, set `DebugKit.ignoreAuthorization` ' .
+ ' Configure option to true.'
);
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/Controller/MailPreviewController.php b/app/vendor/cakephp/debug_kit/src/Controller/MailPreviewController.php
index 31b22dc4f..5c2a8c9b6 100644
--- a/app/vendor/cakephp/debug_kit/src/Controller/MailPreviewController.php
+++ b/app/vendor/cakephp/debug_kit/src/Controller/MailPreviewController.php
@@ -1,4 +1,6 @@
viewBuilder()->setLayout('DebugKit.mailer');
}
@@ -60,7 +59,7 @@ public function index()
*
* @param string $panelId The Mail panel id where the email data is stored.
* @param string $number The email number as stored in the logs.
- * @return \Psr\Http\Message\ResponseInterface|null.
+ * @return \Psr\Http\Message\ResponseInterface|null
*/
public function sent($panelId, $number)
{
@@ -78,16 +77,21 @@ public function sent($panelId, $number)
$email = $content['emails'][$number];
$email = new SentMailResult(array_filter($email['headers']), $email['message']);
+ /** @var string $partType */
$partType = $this->request->getQuery('part');
if ($partType) {
return $this->respondWithPart($email, $partType);
}
+ /** @var string $part */
+ $part = $this->request->getQuery('part');
$this->set('noHeader', true);
$this->set('email', $email);
$this->set('plugin', '');
- $this->set('part', $this->findPreferredPart($email, $this->request->getQuery('part')));
+ $this->set('part', $this->findPreferredPart($email, $part));
$this->viewBuilder()->setTemplate('email');
+
+ return null;
}
/**
@@ -99,33 +103,46 @@ public function sent($panelId, $number)
*/
public function email($name, $method)
{
+ $restore = Router::getRequest();
// Clear the plugin attribute from the request instance
// Router is holding onto so that we can render mail previews
// in a plugin less request context.
- Router::pushRequest($this->request->withParam('plugin', null));
+ Router::setRequest($this->request->withParam('plugin', null));
+ /** @var string $plugin */
$plugin = $this->request->getQuery('plugin');
$email = $this->findPreview($name, $method, $plugin);
$partType = $this->request->getQuery('part');
- $this->viewBuilder()->setLayout(false);
+ $this->viewBuilder()->disableAutoLayout();
if ($partType) {
- return $this->respondWithPart($email, $partType);
+ $result = $this->respondWithPart($email, $partType);
+ if ($restore) {
+ Router::setRequest($restore);
+ }
+
+ return $result;
}
$humanName = Inflector::humanize(Inflector::underscore($name) . "_$method");
+ /** @var string $part */
+ $part = $this->request->getQuery('part');
$this->set('title', $humanName);
$this->set('email', $email);
$this->set('plugin', $plugin);
- $this->set('part', $this->findPreferredPart($email, $this->request->getQuery('part')));
+ $this->set('part', $this->findPreferredPart($email, $part));
+
+ if ($restore) {
+ Router::setRequest($restore);
+ }
}
/**
* Returns a response object with the requested part type for the
* email or throws an exception, if no such part exists.
*
- * @param \Debugkit\Mailer\AbstractResult $email the email to preview
+ * @param \DebugKit\Mailer\AbstractResult $email the email to preview
* @param string $partType The email part to retrieve
* @return \Psr\Http\Message\ResponseInterface
*/
@@ -138,8 +155,8 @@ protected function respondWithPart($email, $partType)
}
$response = $this->response->withType($partType);
- if ($part === 'text') {
- $part = '' . $part . "
";
+ if ($partType === 'text') {
+ $part = '' . (string)$part . '
';
}
$response = $response->withStringBody($part);
@@ -149,7 +166,7 @@ protected function respondWithPart($email, $partType)
/**
* Retrieves an array of MailPreview objects
*
- * @return \Cake\Core\CollectionInterface
+ * @return \Cake\Collection\CollectionInterface
*/
protected function getMailPreviews()
{
@@ -159,7 +176,7 @@ protected function getMailPreviews()
/**
* Returns an array of MailPreview class names for the app and plugins
*
- * @return \Cake\Core\CollectionInterface
+ * @return \Cake\Collection\CollectionInterface
*/
protected function getMailPreviewClasses()
{
@@ -168,7 +185,7 @@ protected function getMailPreviewClasses()
return $plugin === 'DebugKit';
})
->map(function ($plugin) {
- return [App::path('Mailer/Preview', $plugin), "$plugin."];
+ return [[CorePlugin::classPath($plugin) . 'Mailer/Preview/'], "$plugin."];
});
$appPaths = [App::path('Mailer/Preview'), ''];
@@ -176,14 +193,14 @@ protected function getMailPreviewClasses()
return collection([$appPaths])
->append($pluginPaths)
->unfold(function ($pairs) {
- list($paths, $plugin) = $pairs;
+ [$paths, $plugin] = $pairs;
foreach ($paths as $path) {
yield $plugin => $path;
}
})
->unfold(function ($path, $plugin) {
- foreach (glob($path . "*Preview.php") as $file) {
- $base = str_replace(".php", "", basename($file));
+ foreach (glob($path . '*Preview.php') as $file) {
+ $base = str_replace('.php', '', basename($file));
$class = App::className($plugin . $base, 'Mailer/Preview');
if ($class) {
yield ['plugin' => trim($plugin, '.'), 'class' => new $class()];
@@ -239,17 +256,17 @@ protected function findPreferredPart(AbstractResult $email, $partType)
*
* @param string $previewName The Mailer name
* @param string $emailName The mailer preview method
- * @param string|null $plugin The plugin where the mailer preview should be found
+ * @param string $plugin The plugin where the mailer preview should be found
* @return \DebugKit\Mailer\PreviewResult The result of the email preview
* @throws \Cake\Http\Exception\NotFoundException
*/
- protected function findPreview($previewName, $emailName, $plugin = null)
+ protected function findPreview($previewName, $emailName, $plugin = '')
{
if ($plugin) {
$plugin = "$plugin.";
}
- $realClass = App::className($plugin . $previewName, "Mailer/Preview");
+ $realClass = App::className($plugin . $previewName, 'Mailer/Preview');
if (!$realClass) {
throw new NotFoundException("Mailer preview ${previewName} not found");
}
@@ -257,7 +274,12 @@ protected function findPreview($previewName, $emailName, $plugin = null)
$email = $mailPreview->find($emailName);
if (!$email) {
- throw new NotFoundException(__d('debug_kit', "Mailer preview {0}::{1} not found", $previewName, $emailName));
+ throw new NotFoundException(__d(
+ 'debug_kit',
+ 'Mailer preview {0}::{1} not found',
+ $previewName,
+ $emailName
+ ));
}
return new PreviewResult($mailPreview->$email(), $email);
diff --git a/app/vendor/cakephp/debug_kit/src/Controller/PanelsController.php b/app/vendor/cakephp/debug_kit/src/Controller/PanelsController.php
index 4cbe1b3ca..536bb1091 100644
--- a/app/vendor/cakephp/debug_kit/src/Controller/PanelsController.php
+++ b/app/vendor/cakephp/debug_kit/src/Controller/PanelsController.php
@@ -1,4 +1,6 @@
loadComponent('RequestHandler');
+ }
/**
* Before render handler.
*
- * @param \Cake\Event\Event $event The event.
+ * @param \Cake\Event\EventInterface $event The event.
* @return void
*/
- public function beforeRender(Event $event)
+ public function beforeRender(EventInterface $event)
{
$this->viewBuilder()
->setHelpers([
@@ -64,9 +69,9 @@ public function index($requestId = null)
throw new NotFoundException();
}
$this->set([
- '_serialize' => ['panels'],
'panels' => $panels,
]);
+ $this->viewBuilder()->setOption('serialize', ['panels']);
}
/**
@@ -77,8 +82,7 @@ public function index($requestId = null)
*/
public function view($id = null)
{
- $this->Cookie->configKey('debugKit_sort', 'encryption', false);
- $this->set('sort', $this->Cookie->read('debugKit_sort'));
+ $this->set('sort', $this->request->getCookie('debugKit_sort'));
$panel = $this->Panels->get($id);
$this->set('panel', $panel);
diff --git a/app/vendor/cakephp/debug_kit/src/Controller/RequestsController.php b/app/vendor/cakephp/debug_kit/src/Controller/RequestsController.php
index df2d21fca..b166752bb 100644
--- a/app/vendor/cakephp/debug_kit/src/Controller/RequestsController.php
+++ b/app/vendor/cakephp/debug_kit/src/Controller/RequestsController.php
@@ -1,4 +1,6 @@
viewBuilder()
->setLayout('DebugKit.toolbar')
diff --git a/app/vendor/cakephp/debug_kit/src/Controller/ToolbarController.php b/app/vendor/cakephp/debug_kit/src/Controller/ToolbarController.php
index aad2b1ad1..b047dcf2d 100644
--- a/app/vendor/cakephp/debug_kit/src/Controller/ToolbarController.php
+++ b/app/vendor/cakephp/debug_kit/src/Controller/ToolbarController.php
@@ -1,4 +1,6 @@
loadComponent('RequestHandler');
+ }
/**
* Clear a named cache.
@@ -46,10 +51,8 @@ public function clearCache()
if (!$this->request->getData('name')) {
throw new NotFoundException(__d('debug_kit', 'Invalid cache engine name.'));
}
- $result = Cache::clear(false, $this->request->getData('name'));
- $this->set([
- '_serialize' => ['success'],
- 'success' => $result,
- ]);
+ $result = Cache::clear($this->request->getData('name'));
+ $this->set('success', $result);
+ $this->viewBuilder()->setOption('serialize', ['success']);
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/Database/Log/DebugLog.php b/app/vendor/cakephp/debug_kit/src/Database/Log/DebugLog.php
index 15fc9d8e8..d2055a2d5 100644
--- a/app/vendor/cakephp/debug_kit/src/Database/Log/DebugLog.php
+++ b/app/vendor/cakephp/debug_kit/src/Database/Log/DebugLog.php
@@ -1,4 +1,6 @@
_logger = $logger;
$this->_connectionName = $name;
@@ -90,7 +91,7 @@ public function __construct($logger, $name, $includeSchema = false)
* @param bool $value Set
* @return $this
*/
- public function setIncludeSchema($value)
+ public function setIncludeSchema(bool $value)
{
$this->_includeSchema = $value;
@@ -100,9 +101,9 @@ public function setIncludeSchema($value)
/**
* Get the connection name.
*
- * @return array
+ * @return string
*/
- public function name()
+ public function name(): string
{
return $this->_connectionName;
}
@@ -112,7 +113,7 @@ public function name()
*
* @return array
*/
- public function queries()
+ public function queries(): array
{
return $this->_queries;
}
@@ -122,7 +123,7 @@ public function queries()
*
* @return int
*/
- public function totalTime()
+ public function totalTime(): int
{
return $this->_totalTime;
}
@@ -132,39 +133,31 @@ public function totalTime()
*
* @return int
*/
- public function totalRows()
+ public function totalRows(): int
{
return $this->_totalRows;
}
/**
- * Log queries
- *
- * @param \Cake\Database\Log\LoggedQuery $query The query being logged.
- * @return void
+ * @inheritDoc
*/
- public function log(LoggedQuery $query)
+ public function log($level, $message, array $context = []): void
{
+ $query = $context['query'];
+
if ($this->_logger) {
- if ($this->_logger instanceof PsrAbstractLogger) {
- $this->_logger->log($query, $query->error);
- } else {
- $this->_logger->log($query);
- }
+ $this->_logger->log($level, $message, $context);
}
if ($this->_includeSchema === false && $this->isSchemaQuery($query)) {
return;
}
- if (!empty($query->params)) {
- $query->query = $this->_interpolate($query);
- }
$this->_totalTime += $query->took;
$this->_totalRows += $query->numRows;
$this->_queries[] = [
- 'query' => $query->query,
+ 'query' => (string)$query,
'took' => $query->took,
'rows' => $query->numRows,
];
@@ -176,12 +169,11 @@ public function log(LoggedQuery $query)
* @param \Cake\Database\Log\LoggedQuery $query The query to check.
* @return bool
*/
- protected function isSchemaQuery(LoggedQuery $query)
+ protected function isSchemaQuery(LoggedQuery $query): bool
{
$querystring = $query->query;
- return (
- // Multiple engines
+ return // Multiple engines
strpos($querystring, 'FROM information_schema') !== false ||
// Postgres
strpos($querystring, 'FROM pg_catalog') !== false ||
@@ -194,7 +186,6 @@ protected function isSchemaQuery(LoggedQuery $query)
strpos($querystring, 'PRAGMA') === 0 ||
// Sqlserver
strpos($querystring, 'FROM INFORMATION_SCHEMA') !== false ||
- strpos($querystring, 'FROM sys.') !== false
- );
+ strpos($querystring, 'FROM sys.') !== false;
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/DebugInclude.php b/app/vendor/cakephp/debug_kit/src/DebugInclude.php
index 60964869d..2c1b71061 100644
--- a/app/vendor/cakephp/debug_kit/src/DebugInclude.php
+++ b/app/vendor/cakephp/debug_kit/src/DebugInclude.php
@@ -1,4 +1,6 @@
_composerPaths[$package['name']] = $vendorDir . str_replace('/', DIRECTORY_SEPARATOR, $package['name']) . DIRECTORY_SEPARATOR;
+ $this->_composerPaths[$package['name']] = $vendorDir
+ . str_replace('/', DIRECTORY_SEPARATOR, $package['name'])
+ . DIRECTORY_SEPARATOR;
}
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/DebugMemory.php b/app/vendor/cakephp/debug_kit/src/DebugMemory.php
index 36d4e5edf..221ca650f 100644
--- a/app/vendor/cakephp/debug_kit/src/DebugMemory.php
+++ b/app/vendor/cakephp/debug_kit/src/DebugMemory.php
@@ -1,4 +1,6 @@
plugin) {
return $this->plugin . '.' . Inflector::underscore($name);
}
@@ -101,10 +102,10 @@ public function initialize()
/**
* Shutdown callback
*
- * @param \Cake\Event\Event $event The event.
+ * @param \Cake\Event\EventInterface $event The event.
* @return void
*/
- public function shutdown(Event $event)
+ public function shutdown(EventInterface $event)
{
}
@@ -113,7 +114,7 @@ public function shutdown(Event $event)
*
* @return array
*/
- public function implementedEvents()
+ public function implementedEvents(): array
{
return [
'Controller.shutdown' => 'shutdown',
diff --git a/app/vendor/cakephp/debug_kit/src/DebugSql.php b/app/vendor/cakephp/debug_kit/src/DebugSql.php
index 3bd0b2686..72d3c843f 100644
--- a/app/vendor/cakephp/debug_kit/src/DebugSql.php
+++ b/app/vendor/cakephp/debug_kit/src/DebugSql.php
@@ -1,4 +1,6 @@
getValueBinder()->bindings())
- : static::interpolate($sql, $query->valueBinder()->bindings());
+ $sql = static::interpolate($sql, $query->getValueBinder()->bindings());
}
+ /** @var array $trace */
$trace = Debugger::trace(['start' => 1, 'depth' => $stackDepth + 2, 'format' => 'array']);
$file = isset($trace[$stackDepth]) ? $trace[$stackDepth]['file'] : 'n/a';
$line = isset($trace[$stackDepth]) ? $trace[$stackDepth]['line'] : 0;
@@ -129,7 +130,7 @@ public static function sql(Query $query, $showValues = true, $showHtml = null, $
* Only runs if debug mode is enabled.
* It will otherwise just continue code execution and ignore this function.
*
- * @param Query $query Query to show SQL statements for.
+ * @param \Cake\Database\Query $query Query to show SQL statements for.
* @param bool $showValues Renders the SQL statement with bound variables.
* @param bool|null $showHtml If set to true, the method prints the debug
* data in a browser-friendly way.
diff --git a/app/vendor/cakephp/debug_kit/src/DebugTimer.php b/app/vendor/cakephp/debug_kit/src/DebugTimer.php
index 673a09c08..23e8deef9 100644
--- a/app/vendor/cakephp/debug_kit/src/DebugTimer.php
+++ b/app/vendor/cakephp/debug_kit/src/DebugTimer.php
@@ -1,4 +1,6 @@
hasMethod($email)) {
return false;
}
diff --git a/app/vendor/cakephp/debug_kit/src/Mailer/PreviewResult.php b/app/vendor/cakephp/debug_kit/src/Mailer/PreviewResult.php
index 5866c3504..7f55adcab 100644
--- a/app/vendor/cakephp/debug_kit/src/Mailer/PreviewResult.php
+++ b/app/vendor/cakephp/debug_kit/src/Mailer/PreviewResult.php
@@ -1,4 +1,6 @@
getProperty('_email');
- $prop->setAccessible(true);
- $email = $prop->getValue($mailer);
-
- if (!$email->viewBuilder()->getTemplate()) {
- $email->viewBuilder()->setTemplate($method);
+ if (!$mailer->viewBuilder()->getTemplate()) {
+ $mailer->viewBuilder()->setTemplate($method);
}
- $render = (new ReflectionClass($email))
- ->getMethod('_renderTemplates')
- ->getClosure($email);
-
- $this->parts = $render('');
+ $mailer->render();
+ $message = $mailer->getMessage();
+ $this->parts = [
+ 'html' => $message->getBodyHtml(),
+ 'text' => $message->getBodyText(),
+ ];
$extra = ['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'subject'];
- $this->headers = array_filter($email->getHeaders($extra));
+ $this->headers = array_filter($message->getHeaders($extra));
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/Mailer/SentMailResult.php b/app/vendor/cakephp/debug_kit/src/Mailer/SentMailResult.php
index 60f3fc5f1..d15674a0e 100644
--- a/app/vendor/cakephp/debug_kit/src/Mailer/SentMailResult.php
+++ b/app/vendor/cakephp/debug_kit/src/Mailer/SentMailResult.php
@@ -1,4 +1,6 @@
emailLog = $config['debugKitLog'];
@@ -58,25 +60,22 @@ public function __construct($config = [], AbstractTransport $originalTransport =
}
/**
- * Send mail
- *
- * @param \Cake\Mailer\Email $email Cake Email
- * @return array
+ * @inheritDoc
*/
- public function send(Email $email)
+ public function send(Message $message): array
{
- $headers = $email->getHeaders(['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc']);
+ $headers = $message->getHeaders(['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc']);
$parts = [
- 'text' => $email->message(Email::MESSAGE_TEXT),
- 'html' => $email->message(Email::MESSAGE_HTML),
+ 'text' => $message->getBodyText(),
+ 'html' => $message->getBodyHtml(),
];
- $headers['Subject'] = $email->getOriginalSubject();
+ $headers['Subject'] = $message->getOriginalSubject();
$result = ['headers' => $headers, 'message' => $parts];
$this->emailLog[] = $result;
if ($this->originalTransport !== null) {
- return $this->originalTransport->send($email);
+ return $this->originalTransport->send($message);
}
return $result;
diff --git a/app/vendor/cakephp/debug_kit/src/Middleware/DebugKitMiddleware.php b/app/vendor/cakephp/debug_kit/src/Middleware/DebugKitMiddleware.php
index 99f7f55c5..c53994611 100644
--- a/app/vendor/cakephp/debug_kit/src/Middleware/DebugKitMiddleware.php
+++ b/app/vendor/cakephp/debug_kit/src/Middleware/DebugKitMiddleware.php
@@ -1,4 +1,6 @@
service = $service;
@@ -42,15 +48,21 @@ public function __construct(ToolbarService $service = null)
* DebugKit will augment the response and add the toolbar if possible.
*
* @param \Psr\Http\Message\ServerRequestInterface $request The request.
- * @param \Psr\Http\Message\ResponseInterface $response The response.
- * @param callable $next Callback to invoke the next middleware.
- * @return \Psr\Http\Message\ResponseInterface A response
+ * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
+ * @return \Psr\Http\Message\ResponseInterface A response.
*/
- public function __invoke($request, $response, $next)
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
- $this->service->loadPanels();
- $this->service->initializePanels();
- $response = $next($request, $response);
+ if ($this->service->isEnabled()) {
+ $this->service->loadPanels();
+ $this->service->initializePanels();
+ }
+ $response = $handler->handle($request);
+
+ if (!$this->service->isEnabled()) {
+ return $response;
+ }
+
$row = $this->service->saveData($request, $response);
if (!$row) {
return $response;
diff --git a/app/vendor/cakephp/debug_kit/src/Model/Behavior/TimedBehavior.php b/app/vendor/cakephp/debug_kit/src/Model/Behavior/TimedBehavior.php
index ec4bfac09..4a18f6a03 100644
--- a/app/vendor/cakephp/debug_kit/src/Model/Behavior/TimedBehavior.php
+++ b/app/vendor/cakephp/debug_kit/src/Model/Behavior/TimedBehavior.php
@@ -1,4 +1,6 @@
configName());
if (in_array($fixture->table, $existing)) {
continue;
diff --git a/app/vendor/cakephp/debug_kit/src/Model/Table/PanelsTable.php b/app/vendor/cakephp/debug_kit/src/Model/Table/PanelsTable.php
index 11b36bfac..60d6777e3 100644
--- a/app/vendor/cakephp/debug_kit/src/Model/Table/PanelsTable.php
+++ b/app/vendor/cakephp/debug_kit/src/Model/Table/PanelsTable.php
@@ -1,4 +1,6 @@
belongsTo('DebugKit.Requests');
$this->ensureTables(['DebugKit.Requests', 'DebugKit.Panels']);
@@ -67,7 +68,7 @@ public function findByRequest(Query $query, array $options)
*
* @return string
*/
- public static function defaultConnectionName()
+ public static function defaultConnectionName(): string
{
return 'debug_kit';
}
diff --git a/app/vendor/cakephp/debug_kit/src/Model/Table/RequestsTable.php b/app/vendor/cakephp/debug_kit/src/Model/Table/RequestsTable.php
index ad82c3dc9..150b3c5ff 100644
--- a/app/vendor/cakephp/debug_kit/src/Model/Table/RequestsTable.php
+++ b/app/vendor/cakephp/debug_kit/src/Model/Table/RequestsTable.php
@@ -1,4 +1,6 @@
hasMany('DebugKit.Panels', [
'sort' => ['Panels.title' => 'ASC'],
@@ -57,7 +60,7 @@ public function initialize(array $config)
*
* @return string
*/
- public static function defaultConnectionName()
+ public static function defaultConnectionName(): string
{
return 'debug_kit';
}
@@ -67,7 +70,7 @@ public static function defaultConnectionName()
*
* @param \Cake\ORM\Query $query The query
* @param array $options The options
- * @return Query The query.
+ * @return \Cake\ORM\Query The query.
*/
public function findRecent(Query $query, array $options)
{
@@ -99,30 +102,36 @@ public function gc()
if (!$this->shouldGc()) {
return;
}
- $noPurge = $this->find()
- ->select(['id'])
- ->enableHydration(false)
- ->order(['requested_at' => 'desc'])
- ->limit(Configure::read('DebugKit.requestCount') ?: 20)
- ->extract('id')
- ->toArray();
- $query = $this->Panels->query()
- ->delete()
- ->where(['request_id NOT IN' => $noPurge]);
- $statement = $query->execute();
- $statement->closeCursor();
+ try {
+ $noPurge = $this->find()
+ ->select(['id'])
+ ->enableHydration(false)
+ ->order(['requested_at' => 'desc'])
+ ->limit(Configure::read('DebugKit.requestCount') ?: 20)
+ ->extract('id')
+ ->toArray();
+
+ $query = $this->Panels->query()
+ ->delete()
+ ->where(['request_id NOT IN' => $noPurge]);
+ $statement = $query->execute();
+ $statement->closeCursor();
- $query = $this->query()
- ->delete()
- ->where(['id NOT IN' => $noPurge]);
+ $query = $this->query()
+ ->delete()
+ ->where(['id NOT IN' => $noPurge]);
- $statement = $query->execute();
- $statement->closeCursor();
+ $statement = $query->execute();
+ $statement->closeCursor();
- $conn = $this->getConnection();
- if ($conn->getDriver() instanceof Sqlite) {
- $conn->execute('VACUUM;');
+ $conn = $this->getConnection();
+ if ($conn->getDriver() instanceof Sqlite) {
+ $conn->execute('VACUUM;');
+ }
+ } catch (PDOException $e) {
+ Log::warning('Unable to garbage collect requests table. This is probably due to concurrent requests.');
+ Log::warning((string)$e);
}
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/CachePanel.php b/app/vendor/cakephp/debug_kit/src/Panel/CachePanel.php
index ad4248acc..70f9f9e91 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/CachePanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/CachePanel.php
@@ -1,4 +1,6 @@
logger = new ArrayLog();
+ }
/**
* Initialize - install cache spies.
@@ -43,11 +55,11 @@ public function initialize()
$instance = $config['className'];
} elseif (isset($config['className'])) {
Cache::drop($name);
- $instance = new DebugEngine($config);
+ $instance = new DebugEngine($config, $name, $this->logger);
Cache::setConfig($name, $instance);
}
if (isset($instance)) {
- $this->_instances[$name] = $instance;
+ $this->instances[$name] = $instance;
}
}
}
@@ -60,12 +72,15 @@ public function initialize()
public function data()
{
$metrics = [];
- foreach ($this->_instances as $name => $instance) {
+ foreach ($this->instances as $name => $instance) {
$metrics[$name] = $instance->metrics();
}
+ $logs = $this->logger->read();
+ $this->logger->clear();
return [
'metrics' => $metrics,
+ 'logs' => $logs,
];
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/DeprecationsPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/DeprecationsPanel.php
index 8edf3ee73..3ee9e0932 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/DeprecationsPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/DeprecationsPanel.php
@@ -1,4 +1,6 @@
_prepare();
}
- return array_reduce($data, function ($carry, $item) {
+ return (string)array_reduce($data, function ($carry, $item) {
if (empty($item)) {
return $carry;
}
@@ -160,10 +159,10 @@ public function summary()
/**
* Shutdown callback
*
- * @param \Cake\Event\Event $event Event
+ * @param \Cake\Event\EventInterface $event Event
* @return void
*/
- public function shutdown(Event $event)
+ public function shutdown(EventInterface $event)
{
$this->_data = $this->_prepare();
}
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/EnvironmentPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/EnvironmentPanel.php
index 3765d7609..23433342a 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/EnvironmentPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/EnvironmentPanel.php
@@ -1,4 +1,6 @@
_data = $this->_prepare();
}
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/HistoryPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/HistoryPanel.php
index f2ece233f..14db336e9 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/HistoryPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/HistoryPanel.php
@@ -1,4 +1,6 @@
getTableLocator()->get('DebugKit.Requests');
$recent = $table->find('recent');
return [
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/IncludePanel.php b/app/vendor/cakephp/debug_kit/src/Panel/IncludePanel.php
index 64940504b..9fc6211cc 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/IncludePanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/IncludePanel.php
@@ -1,4 +1,6 @@
_debug->getPluginName($file);
if ($pluginName) {
- $return['plugins'][$pluginName][$this->_debug->getFileType($file)][] = $this->_debug->niceFileName($file, 'plugin', $pluginName);
+ $return['plugins'][$pluginName][$this->_debug->getFileType($file)][] = $this->_debug->niceFileName(
+ $file,
+ 'plugin',
+ $pluginName
+ );
} elseif ($this->_debug->isAppFile($file)) {
$return['app'][$this->_debug->getFileType($file)][] = $this->_debug->niceFileName($file, 'app');
} elseif ($this->_debug->isCakeFile($file)) {
@@ -100,16 +103,16 @@ public function summary()
return !empty($v);
}, ARRAY_FILTER_USE_BOTH);
- return count(Hash::flatten($data));
+ return (string)count(Hash::flatten($data));
}
/**
* Shutdown callback
*
- * @param \Cake\Event\Event $event Event
+ * @param \Cake\Event\EventInterface $event Event
* @return void
*/
- public function shutdown(Event $event)
+ public function shutdown(EventInterface $event)
{
$this->_data = $this->_prepare();
}
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/LogPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/LogPanel.php
index 829744807..3aa23a69e 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/LogPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/LogPanel.php
@@ -1,4 +1,6 @@
emailLog = new ArrayObject();
- foreach ($configs as $name => &$transport) {
+ foreach ($configs as $name => $transport) {
if (is_object($transport)) {
- $configs[$name] = new DebugKitTransport(['debugKitLog' => $log], $transport);
+ if (!$transport instanceof DebugKitTransport) {
+ $configs[$name] = new DebugKitTransport(['debugKitLog' => $log], $transport);
+ }
continue;
}
$className = App::className($transport['className'], 'Mailer/Transport', 'Transport');
-
- if (!$className) {
+ if (!$className || $className === DebugKitTransport::class) {
continue;
}
$transport['originalClassName'] = $transport['className'];
$transport['className'] = 'DebugKit.DebugKit';
$transport['debugKitLog'] = $log;
+
+ $configs[$name] = $transport;
}
$property->setValue($configs);
}
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/PackagesPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/PackagesPanel.php
index 5c2c888d9..f5af7950f 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/PackagesPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/PackagesPanel.php
@@ -1,4 +1,6 @@
getEventManager()->on($instance);
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/RequestPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/RequestPanel.php
index c2489e1d6..577eafaee 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/RequestPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/RequestPanel.php
@@ -1,4 +1,6 @@
getSubject();
$request = $controller->getRequest();
$this->_data = [
- 'params' => $request->getAttribute("params"),
+ 'params' => $request->getAttribute('params'),
'query' => $request->getQueryParams(),
'data' => $request->getData(),
'cookie' => $request->getCookieParams(),
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/RoutesPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/RoutesPanel.php
index 2b87cf913..96db53918 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/RoutesPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/RoutesPanel.php
@@ -1,4 +1,6 @@
defaults['plugin'])) || $route->defaults['plugin'] !== 'DebugKit';
+ return !isset($route->defaults['plugin']) || $route->defaults['plugin'] !== 'DebugKit';
});
return (string)count($routes);
@@ -46,12 +40,12 @@ public function summary()
/**
* Data collection callback.
*
- * @param \Cake\Event\Event $event The shutdown event.
+ * @param \Cake\Event\EventInterface $event The shutdown event.
* @return void
*/
- public function shutdown(Event $event)
+ public function shutdown(EventInterface $event)
{
- /* @var \Cake\Controller\Controller|null $controller */
+ /** @var \Cake\Controller\Controller|null $controller */
$controller = $event->getSubject();
$request = $controller ? $controller->getRequest() : null;
$this->_data = [
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/SessionPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/SessionPanel.php
index 6bd9755f0..217887eab 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/SessionPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/SessionPanel.php
@@ -1,4 +1,6 @@
getSubject()->request;
+ /** @var \Cake\Http\ServerRequest $request */
+ $request = $event->getSubject()->getRequest();
if ($request) {
$this->_data = ['content' => $request->getSession()->read()];
}
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/SqlLogPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/SqlLogPanel.php
index 95c013dfb..1e38c6dbd 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/SqlLogPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/SqlLogPanel.php
@@ -1,4 +1,6 @@
configName() === 'debug_kit') {
+ if (
+ $connection->configName() === 'debug_kit'
+ || !$connection instanceof ConnectionInterface
+ ) {
continue;
}
$logger = null;
@@ -64,12 +70,7 @@ public function initialize()
$logger = new DebugLog($logger, $name, $includeSchemaReflection);
$connection->enableQueryLogging(true);
-
- if (method_exists($connection, 'setLogger')) {
- $connection->setLogger($logger);
- } else {
- $connection->logger($logger);
- }
+ $connection->setLogger($logger);
$this->_loggers[] = $logger;
}
@@ -85,7 +86,7 @@ public function data()
return [
'tables' => array_map(function (Table $table) {
return $table->getAlias();
- }, TableRegistry::getTableLocator()->genericInstances()),
+ }, $this->getTableLocator()->genericInstances()),
'loggers' => $this->_loggers,
];
}
diff --git a/app/vendor/cakephp/debug_kit/src/Panel/TimerPanel.php b/app/vendor/cakephp/debug_kit/src/Panel/TimerPanel.php
index d5fadbf0c..87ff7672b 100644
--- a/app/vendor/cakephp/debug_kit/src/Panel/TimerPanel.php
+++ b/app/vendor/cakephp/debug_kit/src/Panel/TimerPanel.php
@@ -1,4 +1,6 @@
errors();
+ $errors = $entity->getErrors();
- foreach ($entity->visibleProperties() as $property) {
+ foreach ($entity->getVisible() as $property) {
$v = $entity[$property];
if ($v instanceof EntityInterface) {
$errors[$property] = $this->_getErrors($v);
@@ -67,7 +66,6 @@ protected function _getErrors(EntityInterface $entity)
*
* @param callable $walker The walker to apply on the debug info array.
* @param object $item The item whose debug info to retrieve.
- *
* @return array|string
*/
protected function _walkDebugInfo(callable $walker, $item)
@@ -75,7 +73,14 @@ protected function _walkDebugInfo(callable $walker, $item)
try {
$info = $item->__debugInfo();
} catch (\Exception $exception) {
- return __d('debug_kit', 'Could not retrieve debug info - {0}. Error: {1} in {2}, line {3}', get_class($item), $exception->getMessage(), $exception->getFile(), $exception->getLine());
+ return __d(
+ 'debug_kit',
+ 'Could not retrieve debug info - {0}. Error: {1} in {2}, line {3}',
+ get_class($item),
+ $exception->getMessage(),
+ $exception->getFile(),
+ $exception->getLine()
+ );
}
return array_map($walker, $info);
@@ -84,12 +89,12 @@ protected function _walkDebugInfo(callable $walker, $item)
/**
* Shutdown event
*
- * @param \Cake\Event\Event $event The event
+ * @param \Cake\Event\EventInterface $event The event
* @return void
*/
- public function shutdown(Event $event)
+ public function shutdown(EventInterface $event)
{
- /* @var \Cake\Controller\Controller $controller */
+ /** @var \Cake\Controller\Controller $controller */
$controller = $event->getSubject();
$errors = [];
@@ -138,7 +143,7 @@ public function shutdown(Event $event)
return $this->trySerialize($item);
};
// Copy so viewVars is not mutated.
- $vars = $controller->viewVars;
+ $vars = $controller->viewBuilder()->getVars();
array_walk_recursive($vars, $walker);
foreach ($vars as $k => $v) {
@@ -146,9 +151,9 @@ public function shutdown(Event $event)
if ($v instanceof EntityInterface) {
$errors[$k] = $this->_getErrors($v);
} elseif ($v instanceof Form) {
- $formError = $v->getErrors();
- if (!empty($formError)) {
- $errors[$k] = $formError;
+ $formErrors = $v->getErrors();
+ if ($formErrors) {
+ $errors[$k] = $formErrors;
}
}
}
@@ -173,10 +178,23 @@ protected function trySerialize($item)
return $item;
} catch (\Exception $e) {
if (is_object($item)) {
- return __d('debug_kit', 'Unserializable object - {0}. Error: {1} in {2}, line {3}', get_class($item), $e->getMessage(), $e->getFile(), $e->getLine());
+ return __d(
+ 'debug_kit',
+ 'Unserializable object - {0}. Error: {1} in {2}, line {3}',
+ get_class($item),
+ $e->getMessage(),
+ $e->getFile(),
+ $e->getLine()
+ );
}
- return __d('debug_kit', 'Unserializable Error: {1} in {2}, line {3}', $e->getMessage(), $e->getFile(), $e->getLine());
+ return __d(
+ 'debug_kit',
+ 'Unserializable Error: {1} in {2}, line {3}',
+ $e->getMessage(),
+ $e->getFile(),
+ $e->getLine()
+ );
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/Plugin.php b/app/vendor/cakephp/debug_kit/src/Plugin.php
index be6dc5caa..27d4ac077 100644
--- a/app/vendor/cakephp/debug_kit/src/Plugin.php
+++ b/app/vendor/cakephp/debug_kit/src/Plugin.php
@@ -1,4 +1,6 @@
isEnabled() || php_sapi_name() === 'cli' || php_sapi_name() === 'phpdbg') {
+ return;
+ }
+
+ $this->service = $service;
+
+ $this->setDeprecationHandler($service);
+
+ // will load `config/bootstrap.php`.
+ parent::bootstrap($app);
+ }
+
+ /**
+ * Add middleware for the plugin.
+ *
+ * @param \Cake\Http\MiddlewareQueue $middleware The middleware queue to update.
+ * @return \Cake\Http\MiddlewareQueue
+ */
+ public function middleware(MiddlewareQueue $middleware): MiddlewareQueue
+ {
+ if ($this->service) {
+ $middleware->insertAt(0, new DebugKitMiddleware($this->service));
+ }
+
+ return $middleware;
+ }
+
+ /**
+ * Add console commands for the plugin.
+ *
+ * @param \Cake\Console\CommandCollection $commands The command collection to update
+ * @return \Cake\Console\CommandCollection
+ */
+ public function console(CommandCollection $commands): CommandCollection
+ {
+ return $commands->add('benchmark', BenchmarkCommand::class);
+ }
+
+ /**
+ * set deprecation handler
+ *
+ * @param \DebugKit\ToolbarService $service The toolbar service instance
+ * @return void
+ */
+ public function setDeprecationHandler($service)
+ {
+ if (!empty($service->getConfig('panels')['DebugKit.Deprecations'])) {
+ $previousHandler = set_error_handler(
+ function ($code, $message, $file, $line, $context = null) use (&$previousHandler) {
+ if ($code == E_USER_DEPRECATED || $code == E_DEPRECATED) {
+ DeprecationsPanel::addDeprecatedError(compact('code', 'message', 'file', 'line', 'context'));
+
+ return;
+ }
+ if ($previousHandler) {
+ $context['_trace_frame_offset'] = 1;
+
+ return $previousHandler($code, $message, $file, $line, $context);
+ }
+ }
+ );
+ }
+ }
}
diff --git a/app/vendor/cakephp/debug_kit/src/Routing/Filter/DebugBarFilter.php b/app/vendor/cakephp/debug_kit/src/Routing/Filter/DebugBarFilter.php
deleted file mode 100644
index 5d898c6f9..000000000
--- a/app/vendor/cakephp/debug_kit/src/Routing/Filter/DebugBarFilter.php
+++ /dev/null
@@ -1,146 +0,0 @@
-service = new ToolbarService($events, $config);
- }
-
- /**
- * Event bindings
- *
- * @return array
- */
- public function implementedEvents()
- {
- return [
- 'Dispatcher.beforeDispatch' => [
- 'callable' => 'beforeDispatch',
- 'priority' => 0,
- ],
- 'Dispatcher.afterDispatch' => [
- 'callable' => 'afterDispatch',
- 'priority' => 9999,
- ],
- ];
- }
-
- /**
- * Check whether or not debug kit is enabled.
- *
- * @return bool
- */
- public function isEnabled()
- {
- return $this->service->isEnabled();
- }
-
- /**
- * Get the list of loaded panels
- *
- * @return array
- */
- public function loadedPanels()
- {
- return $this->service->registry()->loaded();
- }
-
- /**
- * Get the list of loaded panels
- *
- * @param string $name The name of the panel you want to get.
- * @return \DebugKit\DebugPanel|null The panel or null.
- */
- public function panel($name)
- {
- $registry = $this->service->registry();
-
- return $registry->{$name};
- }
-
- /**
- * Do the required setup work.
- *
- * - Build panels.
- * - Connect events
- *
- * @return void
- */
- public function setup()
- {
- $this->service->loadPanels();
- }
-
- /**
- * Call the initialize method onl all the loaded panels.
- *
- * @param \Cake\Event\Event $event The beforeDispatch event.
- * @return void
- */
- public function beforeDispatch(Event $event)
- {
- $this->service->initializePanels();
- }
-
- /**
- * Save the toolbar data.
- *
- * @param \Cake\Event\Event $event The afterDispatch event.
- * @return \Psr\Http\Message\ResponseInterface|void Modified response or null
- */
- public function afterDispatch(Event $event)
- {
- /* @var Request $request */
- $request = $event->getData('request');
- /* @var Response $response */
- $response = $event->getData('response');
- $row = $this->service->saveData($request, $response);
- if (!$row) {
- return;
- }
-
- return $this->service->injectScripts($row, $response);
- }
-}
diff --git a/app/vendor/cakephp/debug_kit/src/Shell/BenchmarkShell.php b/app/vendor/cakephp/debug_kit/src/Shell/BenchmarkShell.php
deleted file mode 100644
index 0324688f2..000000000
--- a/app/vendor/cakephp/debug_kit/src/Shell/BenchmarkShell.php
+++ /dev/null
@@ -1,173 +0,0 @@
-args[0];
- $defaults = ['t' => 100, 'n' => 10];
- $options = array_merge($defaults, $this->params);
- $times = [];
-
- $this->out(Text::insert(__d('debug_kit', '-> Testing :url'), compact('url')));
- $this->out("");
- for ($i = 0; $i < $options['n']; $i++) {
- if (floor($options['t'] - array_sum($times)) <= 0 || $options['n'] <= 1) {
- break;
- }
-
- $start = microtime(true);
- file_get_contents($url);
- $stop = microtime(true);
-
- $times[] = $stop - $start;
- }
- $this->_results($times);
- }
-
- /**
- * Prints calculated results
- *
- * @param array $times Array of time values
- * @return void
- */
- protected function _results($times)
- {
- $duration = array_sum($times);
- $requests = count($times);
-
- $this->out(Text::insert(__d('debug_kit', 'Total Requests made: :requests'), compact('requests')));
- $this->out(Text::insert(__d('debug_kit', 'Total Time elapsed: :duration (seconds)'), compact('duration')));
-
- $this->out("");
-
- $this->out(Text::insert(__d('debug_kit', 'Requests/Second: :rps req/sec'), [
- 'rps' => round($requests / $duration, 3),
- ]));
-
- $this->out(Text::insert(__d('debug_kit', 'Average request time: :average-time seconds'), [
- 'average-time' => round($duration / $requests, 3),
- ]));
-
- $this->out(Text::insert(__d('debug_kit', 'Standard deviation of average request time: :std-dev'), [
- 'std-dev' => round($this->_deviation($times, true), 3),
- ]));
-
- $this->out(Text::insert(__d('debug_kit', 'Longest/shortest request: :longest sec/:shortest sec'), [
- 'longest' => round(max($times), 3),
- 'shortest' => round(min($times), 3),
- ]));
-
- $this->out("");
- }
-
- /**
- * One-pass, numerically stable calculation of population variance.
- *
- * Donald E. Knuth (1998).
- * The Art of Computer Programming, volume 2: Seminumerical Algorithms, 3rd edn.,
- * p. 232. Boston: Addison-Wesley.
- *
- * @param array $times Array of values
- * @param bool $sample If true, calculates an unbiased estimate of the population
- * variance from a finite sample.
- * @return float Variance
- */
- protected function _variance($times, $sample = true)
- {
- $n = $mean = $M2 = 0;
-
- foreach ($times as $time) {
- $n += 1;
- $delta = $time - $mean;
- $mean = $mean + $delta / $n;
- $M2 = $M2 + $delta * ($time - $mean);
- }
-
- if ($sample) {
- $n -= 1;
- }
-
- return $M2 / $n;
- }
-
- /**
- * Calculate the standard deviation.
- *
- * @param array $times Array of values
- * @param bool $sample ''
- * @return float Standard deviation
- */
- protected function _deviation($times, $sample = true)
- {
- return sqrt($this->_variance($times, $sample));
- }
-
- /**
- * Get option parser.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
- $parser->description(__d(
- 'debug_kit',
- 'Allows you to obtain some rough benchmarking statistics' .
- 'about a fully qualified URL.'
- ))
- ->addArgument('url', [
- 'help' => __d('debug_kit', 'The URL to request.'),
- 'required' => true,
- ])
- ->addOption('n', [
- 'default' => 10,
- 'help' => __d('debug_kit', 'Number of iterations to perform.'),
- ])
- ->addOption('t', [
- 'default' => 100,
- 'help' => __d(
- 'debug_kit',
- 'Maximum total time for all iterations, in seconds.' .
- 'If a single iteration takes more than the timeout, only one request will be made'
- ),
- ])
- ->epilog(__d(
- 'debug_kit',
- 'Example Use: `cake benchmark --n 10 --t 100 http://localhost/testsite`. ' .
- 'Note: this benchmark does not include browser render times.'
- ));
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/debug_kit/src/Shell/WhitespaceShell.php b/app/vendor/cakephp/debug_kit/src/Shell/WhitespaceShell.php
deleted file mode 100644
index 812a768e7..000000000
--- a/app/vendor/cakephp/debug_kit/src/Shell/WhitespaceShell.php
+++ /dev/null
@@ -1,101 +0,0 @@
-params['path']) && strpos($this->params['path'], '/') === 0) {
- $path = $this->params['path'];
- } elseif (!empty($this->params['path'])) {
- $path .= $this->params['path'];
- }
- $folder = new Folder($path);
-
- $r = $folder->findRecursive('.*\.php');
- $this->out("Checking *.php in " . $path);
- foreach ($r as $file) {
- $c = file_get_contents($file);
- if (preg_match('/^[\n\r|\n\r|\n|\r|\s]+\<\?php/', $c)) {
- $this->out('!!!contains leading whitespaces: ' . $this->shortPath($file));
- }
- if (preg_match('/\?\>[\n\r|\n\r|\n|\r|\s]+$/', $c)) {
- $this->out('!!!contains trailing whitespaces: ' . $this->shortPath($file));
- }
- }
- }
-
- /**
- * Much like main() except files are modified. Be sure to have
- * backups or use version control.
- *
- * @return void
- */
- public function trim()
- {
- $path = APP;
- if (!empty($this->params['path']) && strpos($this->params['path'], '/') === 0) {
- $path = $this->params['path'];
- } elseif (!empty($this->params['path'])) {
- $path .= $this->params['path'];
- }
- $folder = new Folder($path);
-
- $r = $folder->findRecursive('.*\.php');
- $this->out("Checking *.php in " . $path);
- foreach ($r as $file) {
- $c = file_get_contents($file);
- if (preg_match('/^[\n\r|\n\r|\n|\r|\s]+\<\?php/', $c) || preg_match('/\?\>[\n\r|\n\r|\n|\r|\s]+$/', $c)) {
- $this->out('trimming' . $this->shortPath($file));
- $c = preg_replace('/^[\n\r|\n\r|\n|\r|\s]+\<\?php/', '[\n\r|\n\r|\n|\r|\s]+$/', '?>', $c);
- file_put_contents($file, $c);
- }
- }
- }
-
- /**
- * get the option parser
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- return $parser->addOption('path', [
- 'short' => 'p',
- 'help' => __d('debug_kit', 'Absolute path or relative to {0}.', 'APP'),
- ]);
- }
-}
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/cache_panel.ctp b/app/vendor/cakephp/debug_kit/src/Template/Element/cache_panel.ctp
deleted file mode 100644
index 63fceef8f..000000000
--- a/app/vendor/cakephp/debug_kit/src/Template/Element/cache_panel.ctp
+++ /dev/null
@@ -1,80 +0,0 @@
-
-
- = __d('debug_kit', 'There were no cache operations this request.') ?>
-
- $counters): ?>
-
- = __d('debug_kit', '{0} Metrics', h($name)) ?>
-
-
-
-
-
- = __d('debug_kit', 'Metric') ?>
- = __d('debug_kit', 'Total') ?>
-
-
-
- $val): ?>
-
- = h($key) ?>
- = $val ?>
-
-
-
-
-
-
-
-
-
diff --git a/app/vendor/cakephp/debug_kit/src/ToolbarService.php b/app/vendor/cakephp/debug_kit/src/ToolbarService.php
index 570b885bf..fe5c24b6c 100644
--- a/app/vendor/cakephp/debug_kit/src/ToolbarService.php
+++ b/app/vendor/cakephp/debug_kit/src/ToolbarService.php
@@ -1,4 +1,6 @@
false,
'safeTld' => [],
+ 'ignorePathsPattern' => null,
];
/**
@@ -117,7 +120,12 @@ public function isEnabled()
*/
protected function isSuspiciouslyProduction()
{
- $host = explode('.', parse_url('http://' . env('HTTP_HOST'), PHP_URL_HOST));
+ $url = parse_url('http://' . env('HTTP_HOST'), PHP_URL_HOST);
+ if ($url === false) {
+ return false;
+ }
+
+ $host = explode('.', $url);
$first = current($host);
$isIP = is_numeric(implode('', $host));
@@ -140,7 +148,7 @@ protected function isSuspiciouslyProduction()
Log::warning(
"DebugKit is disabling itself as your host `{$host}` " .
"is not in the known safe list of top-level-domains ({$safeList}). " .
- "If you would like to force DebugKit on use the `DebugKit.forceEnable` Configure option."
+ 'If you would like to force DebugKit on use the `DebugKit.forceEnable` Configure option.'
);
return true;
@@ -178,7 +186,7 @@ public function panel($name)
public function loadPanels()
{
foreach ($this->getConfig('panels') as $panel => $enabled) {
- list($panel, $enabled) = (is_numeric($panel)) ? [$enabled, true] : [$panel, $enabled];
+ [$panel, $enabled] = is_numeric($panel) ? [$enabled, true] : [$panel, $enabled];
if ($enabled) {
$this->registry->load($panel);
}
@@ -202,19 +210,27 @@ public function initializePanels()
*
* @param \Cake\Http\ServerRequest $request The request
* @param \Psr\Http\Message\ResponseInterface $response The response
- * @return null|\DebugKit\Model\Entity\Request Saved request data.
+ * @return false|\DebugKit\Model\Entity\Request Saved request data.
*/
public function saveData(ServerRequest $request, ResponseInterface $response)
{
- // Skip debugkit requests and requestAction()
+ $ignorePathsPattern = $this->getConfig('ignorePathsPattern');
$path = $request->getUri()->getPath();
+ $statusCode = $response->getStatusCode();
+
if (
strpos($path, 'debug_kit') !== false ||
strpos($path, 'debug-kit') !== false ||
- $request->is('requested')
+ (
+ $ignorePathsPattern &&
+ $statusCode >= 200 &&
+ $statusCode <= 299 &&
+ preg_match($ignorePathsPattern, $path)
+ )
) {
- return null;
+ return false;
}
+
$data = [
'url' => $request->getUri()->getPath(),
'content_type' => $response->getHeaderLine('Content-Type'),
@@ -223,12 +239,12 @@ public function saveData(ServerRequest $request, ResponseInterface $response)
'requested_at' => $request->getEnv('REQUEST_TIME'),
'panels' => [],
];
- /* @var \DebugKit\Model\Table\RequestsTable $requests */
- $requests = TableRegistry::get('DebugKit.Requests');
+ /** @var \DebugKit\Model\Table\RequestsTable $requests */
+ $requests = $this->getTableLocator()->get('DebugKit.Requests');
$requests->gc();
$row = $requests->newEntity($data);
- $row->isNew(true);
+ $row->setNew(true);
foreach ($this->registry->loaded() as $name) {
$panel = $this->registry->{$name};
@@ -248,7 +264,14 @@ public function saveData(ServerRequest $request, ResponseInterface $response)
]);
}
- return $requests->save($row);
+ try {
+ return $requests->save($row);
+ } catch (PDOException $e) {
+ Log::warning('Unable to save request. This is probably due to concurrent requests.');
+ Log::warning((string)$e);
+ }
+
+ return false;
}
/**
diff --git a/app/vendor/cakephp/debug_kit/src/View/AjaxView.php b/app/vendor/cakephp/debug_kit/src/View/AjaxView.php
index cfc310ab9..911a0b6f2 100644
--- a/app/vendor/cakephp/debug_kit/src/View/AjaxView.php
+++ b/app/vendor/cakephp/debug_kit/src/View/AjaxView.php
@@ -1,4 +1,6 @@
response = $this->response->withType('ajax');
diff --git a/app/vendor/cakephp/debug_kit/src/View/Helper/CredentialsHelper.php b/app/vendor/cakephp/debug_kit/src/View/Helper/CredentialsHelper.php
index a2213e6d8..253fabd85 100644
--- a/app/vendor/cakephp/debug_kit/src/View/Helper/CredentialsHelper.php
+++ b/app/vendor/cakephp/debug_kit/src/View/Helper/CredentialsHelper.php
@@ -1,4 +1,6 @@
Html->tag('a', '******', [
'class' => 'filtered-credentials',
'title' => h($credentials),
- 'onclick' => "this.innerHTML = this.title",
+ 'onclick' => 'this.innerHTML = this.title',
]);
return h($protocol) . $link . '@' . h($tail);
diff --git a/app/vendor/cakephp/debug_kit/src/View/Helper/SimpleGraphHelper.php b/app/vendor/cakephp/debug_kit/src/View/Helper/SimpleGraphHelper.php
index 11d1ba182..340ad1cda 100644
--- a/app/vendor/cakephp/debug_kit/src/View/Helper/SimpleGraphHelper.php
+++ b/app/vendor/cakephp/debug_kit/src/View/Helper/SimpleGraphHelper.php
@@ -1,4 +1,6 @@
_defaultSettings, $options);
- /* @var int $max */
- /* @var int $width */
- /* @var string $valueType */
- extract($settings);
+ $max = $settings['max'];
+ $width = $settings['width'];
+ $valueType = $settings['valueType'];
- $graphValue = ($value / $max) * $width;
+ $graphValue = $value / $max * $width;
$graphValue = max(round($graphValue), 1);
if ($valueType === 'percentage') {
$graphOffset = 0;
} else {
- $graphOffset = ($offset / $max) * $width;
+ $graphOffset = $offset / $max * $width;
$graphOffset = round($graphOffset);
}
@@ -73,7 +73,7 @@ public function bar($value, $offset, $options = [])
'',
"width: {$width}px",
"margin-left: {$graphOffset}px; width: {$graphValue}px",
- __d('debug_kit', "Starting {0}ms into the request, taking {1}ms", $offset, $value)
+ __d('debug_kit', 'Starting {0}ms into the request, taking {1}ms', $offset, $value)
);
}
}
diff --git a/app/vendor/cakephp/debug_kit/src/View/Helper/TidyHelper.php b/app/vendor/cakephp/debug_kit/src/View/Helper/TidyHelper.php
deleted file mode 100644
index c8db0f4a6..000000000
--- a/app/vendor/cakephp/debug_kit/src/View/Helper/TidyHelper.php
+++ /dev/null
@@ -1,189 +0,0 @@
-tidyErrors($html, $out);
-
- if (!$errors) {
- return [];
- }
- $result = ['Error' => [], 'Warning' => [], 'Misc' => []];
- $errors = explode("\n", $errors);
- $markup = explode("\n", $out);
- foreach ($errors as $error) {
- preg_match('@line (\d+) column (\d+) - (\w+): (.*)@', $error, $matches);
- if ($matches) {
- list($original, $line, $column, $type, $message) = $matches;
- $line = $line - 1;
-
- $string = '';
- if (isset($markup[$line - 1])) {
- $string .= h($markup[$line - 1]);
- }
- // phpcs:ignore
- $string .= '' . h(@$markup[$line]) . '';
- if (isset($markup[$line + 1])) {
- $string .= h($markup[$line + 1]);
- }
- $string .= '';
-
- $result[$type][$string][] = h($message);
- } elseif ($error) {
- $message = $error;
- $result['Misc'][h($message)][] = h($message);
- }
- }
- $this->results = $result;
-
- return $result;
- }
-
- /**
- * report method
- *
- * Call process if a string is passed, or no prior results exist - and return the results using
- * the toolbar helper to generate a nested navigatable array
- *
- * @param mixed $html null
- * @return string
- */
- public function report($html = null)
- {
- if ($html) {
- $this->process($html);
- } elseif ($this->results === null) {
- $this->process($this->_View->output);
- }
- if (!$this->results) {
- return '' . __d('debug_kit', 'No markup errors found') . '
';
- }
- foreach ($this->results as &$results) {
- foreach ($results as $type => &$messages) {
- foreach ($messages as &$message) {
- $message = html_entity_decode($message, ENT_COMPAT, Configure::read('App.encoding'));
- }
- }
- }
-
- return $this->Toolbar->makeNeatArray(array_filter($this->results), 0, 0, false);
- }
-
- /**
- * Run the html string through tidy, and return the (raw) errors. pass back a reference to the
- * normalized string so that the error messages can be linked to the line that caused them.
- *
- * @param string $in ''
- * @param string $out ''
- * @return string
- */
- public function tidyErrors($in = '', &$out = '')
- {
- $out = preg_replace('@>\s*<@s', ">\n<", $in);
-
- // direct access? windows etc
- if (function_exists('tidy_parse_string')) {
- $tidy = tidy_parse_string($out, [], 'UTF8');
- $tidy->cleanRepair();
- $errors = $tidy->errorBuffer . "\n";
-
- return $errors;
- }
-
- // cli
- $File = new File(rtrim(TMP, DS) . DS . rand() . '.html', true);
- $File->write($out);
- $path = $File->pwd();
- $errors = $path . '.err';
- $this->_exec("tidy -eq -utf8 -f $errors $path");
- $File->delete();
-
- if (!file_exists($errors)) {
- return '';
- }
- $Error = new File($errors);
- $errors = $Error->read();
- $Error->delete();
-
- return $errors;
- }
-
- /**
- * exec method
- *
- * @param mixed $cmd ''
- * @param mixed $out null
- * @return bool True if successful
- */
- protected function _exec($cmd, &$out = null)
- {
- if (DS === '/') {
- $_out = exec($cmd . ' 2>&1', $out, $return);
- } else {
- $_out = exec($cmd, $out, $return);
- }
-
- if (Configure::read('debug')) {
- $source = Debugger::trace(['depth' => 1, 'start' => 2]) . "\n";
- //Log::write('system_calls_' . date('Y-m-d'), "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));
- //Log::write('system_calls', "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));
- }
- if ($return) {
- return false;
- }
-
- return $_out ? $_out : true;
- }
-}
diff --git a/app/vendor/cakephp/debug_kit/src/View/Helper/ToolbarHelper.php b/app/vendor/cakephp/debug_kit/src/View/Helper/ToolbarHelper.php
index cb8cff55b..7c12b3220 100644
--- a/app/vendor/cakephp/debug_kit/src/View/Helper/ToolbarHelper.php
+++ b/app/vendor/cakephp/debug_kit/src/View/Helper/ToolbarHelper.php
@@ -1,4 +1,6 @@
contains($value)) {
- $isObject = false;
+ if (is_object($value) && $ancestors->contains($value)) {
$value = ' - recursion';
}
@@ -133,7 +137,7 @@ public function makeNeatArray($values, $openDepth = 0, $currentDepth = 0, $doubl
$value instanceof ArrayAccess ||
$value instanceof Iterator ||
is_array($value) ||
- $isObject
+ is_object($value)
) && !empty($value)
) {
$out .= $this->makeNeatArray($value, $openDepth, $nextDepth, $doubleEncode, $ancestors);
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Dashboard/index.ctp b/app/vendor/cakephp/debug_kit/templates/Dashboard/index.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Dashboard/index.ctp
rename to app/vendor/cakephp/debug_kit/templates/Dashboard/index.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/MailPreview/email.ctp b/app/vendor/cakephp/debug_kit/templates/MailPreview/email.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/MailPreview/email.ctp
rename to app/vendor/cakephp/debug_kit/templates/MailPreview/email.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/MailPreview/index.ctp b/app/vendor/cakephp/debug_kit/templates/MailPreview/index.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/MailPreview/index.ctp
rename to app/vendor/cakephp/debug_kit/templates/MailPreview/index.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Panels/view.ctp b/app/vendor/cakephp/debug_kit/templates/Panels/view.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Panels/view.ctp
rename to app/vendor/cakephp/debug_kit/templates/Panels/view.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Requests/view.ctp b/app/vendor/cakephp/debug_kit/templates/Requests/view.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Requests/view.ctp
rename to app/vendor/cakephp/debug_kit/templates/Requests/view.php
diff --git a/app/vendor/cakephp/debug_kit/templates/element/cache_panel.php b/app/vendor/cakephp/debug_kit/templates/element/cache_panel.php
new file mode 100644
index 000000000..052450a46
--- /dev/null
+++ b/app/vendor/cakephp/debug_kit/templates/element/cache_panel.php
@@ -0,0 +1,122 @@
+
+
+ = __d('debug_kit', 'There were no cache operations in this request.') ?>
+
+ = __d('debug_kit', 'Cache Utilities') ?>
+
+
+
+ = __d('debug_kit', 'Engine') ?>
+
+
+
+
+ $values) : ?>
+
+ = h($name) ?>
+
+
+
+
+
+
+
+
+ = __d('debug_kit', 'Cache Usage Overview') ?>
+
+
+
+ = __d('debug_kit', 'Engine') ?>
+ = __d('debug_kit', 'get hit') ?>
+ = __d('debug_kit', 'get miss') ?>
+ = __d('debug_kit', 'set') ?>
+ = __d('debug_kit', 'delete') ?>
+
+
+
+ $counters) : ?>
+
+ = h($name) ?>
+ = $counters['get hit'] ?>
+ = $counters['get miss'] ?>
+ = $counters['set'] ?>
+ = $counters['delete'] ?>
+
+
+
+
+
+ = __d('debug_kit', 'Cache Logs') ?>
+
+
+
+ = __d('debug_kit', 'Log') ?>
+
+
+
+
+
+ = h($log) ?>
+
+
+
+
+
+
+
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/deprecations_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/deprecations_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/deprecations_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/deprecations_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/environment_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/environment_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/environment_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/environment_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/history_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/history_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/history_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/history_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/include_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/include_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/include_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/include_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/log_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/log_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/log_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/log_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/mail_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/mail_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/mail_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/mail_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/packages_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/packages_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/packages_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/packages_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/preview_header.ctp b/app/vendor/cakephp/debug_kit/templates/element/preview_header.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/preview_header.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/preview_header.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/request_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/request_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/request_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/request_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/routes_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/routes_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/routes_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/routes_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/session_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/session_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/session_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/session_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/sql_log_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/sql_log_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/sql_log_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/sql_log_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/timer_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/timer_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/timer_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/timer_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Element/variables_panel.ctp b/app/vendor/cakephp/debug_kit/templates/element/variables_panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Element/variables_panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/element/variables_panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Layout/dashboard.ctp b/app/vendor/cakephp/debug_kit/templates/layout/dashboard.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Layout/dashboard.ctp
rename to app/vendor/cakephp/debug_kit/templates/layout/dashboard.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Layout/mailer.ctp b/app/vendor/cakephp/debug_kit/templates/layout/mailer.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Layout/mailer.ctp
rename to app/vendor/cakephp/debug_kit/templates/layout/mailer.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Layout/panel.ctp b/app/vendor/cakephp/debug_kit/templates/layout/panel.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Layout/panel.ctp
rename to app/vendor/cakephp/debug_kit/templates/layout/panel.php
diff --git a/app/vendor/cakephp/debug_kit/src/Template/Layout/toolbar.ctp b/app/vendor/cakephp/debug_kit/templates/layout/toolbar.php
similarity index 100%
rename from app/vendor/cakephp/debug_kit/src/Template/Layout/toolbar.ctp
rename to app/vendor/cakephp/debug_kit/templates/layout/toolbar.php
diff --git a/app/vendor/cakephp/debug_kit/tests/Fixture/PanelsFixture.php b/app/vendor/cakephp/debug_kit/tests/Fixture/PanelsFixture.php
index f22f10a27..4ee5163bb 100644
--- a/app/vendor/cakephp/debug_kit/tests/Fixture/PanelsFixture.php
+++ b/app/vendor/cakephp/debug_kit/tests/Fixture/PanelsFixture.php
@@ -12,7 +12,7 @@
*/
namespace Debugkit\Test\Fixture;
-use Cake\Database\Schema\Table as TableSchema;
+use Cake\Database\Schema\TableSchema;
use Cake\TestSuite\Fixture\TestFixture;
/**
diff --git a/app/vendor/cakephp/debug_kit/webroot/css/toolbar.css b/app/vendor/cakephp/debug_kit/webroot/css/toolbar.css
index f113722ea..29fc2ffae 100644
--- a/app/vendor/cakephp/debug_kit/webroot/css/toolbar.css
+++ b/app/vendor/cakephp/debug_kit/webroot/css/toolbar.css
@@ -79,6 +79,7 @@ strong {
overflow: hidden;
white-space: nowrap;
display: flex;
+ justify-content: flex-end;
}
.hidden {
diff --git a/app/vendor/cakephp/migrations/.github/ISSUE_TEMPLATE.md b/app/vendor/cakephp/migrations/.github/ISSUE_TEMPLATE.md
deleted file mode 100644
index b19aee544..000000000
--- a/app/vendor/cakephp/migrations/.github/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,30 +0,0 @@
-This is a (multiple allowed):
-* [x] bug
-* [ ] enhancement
-* [ ] feature-discussion (RFC)
-
-* CakePHP Version: EXACT RELEASE VERSION OR COMMIT HASH, HERE.
-* Migrations plugin version: EXACT RELEASE VERSION OR COMMIT HASH, HERE.
-* Bake plugin version (if relevant): EXACT RELEASE VERSION OR COMMIT HASH, HERE.
-* Database server (MySQL, SQLite, Postgres): EXACT RELEASE VERSION
-* PHP Version: EXACT RELEASE VERSION
-* Platform / OS: Preferably with version number
-
-### What you did
-EXPLAIN WHAT YOU DID, PREFERABLY WITH CODE EXAMPLES, HERE.
-Give as much details as possible (preferably using [Gist](https://gist.github.com/)) :
-* if your migration file was created with the bake tool or not,
-* the exact shell command you used,
-* the FULL content of the migration files that cause the issue,
-* a way to recreate the schema of your database.
-
-### Expected Behavior
-EXPLAIN WHAT IS TO BE EXPECTED, HERE.
-
-### Actual Behavior
-EXPLAIN WHAT IS ACTUALLY HAPPENING, HERE.
-
-P.S. Remember, an issue is not the place to ask questions. You can use [Stack Overflow](http://stackoverflow.com/questions/tagged/cakephp)
-for that or join the #cakephp channel on irc.freenode.net, where we will be more than happy to help answer your questions.
-
-Before you open an issue, please check if a similar issue already exists or has been closed before.
\ No newline at end of file
diff --git a/app/vendor/cakephp/migrations/.github/PULL_REQUEST_TEMPLATE.md b/app/vendor/cakephp/migrations/.github/PULL_REQUEST_TEMPLATE.md
deleted file mode 100644
index 557d627ec..000000000
--- a/app/vendor/cakephp/migrations/.github/PULL_REQUEST_TEMPLATE.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.
-
-The best way to propose a feature is to open an issue first and discuss your ideas there before implementing them.
-
-Always follow the [contribution guidelines](https://github.com/cakephp/migrations/blob/master/.github/CONTRIBUTING.md) when submitting a pull request. In particular, make sure existing tests still pass, and add tests for all new behavior. When fixing a bug, you may want to add a test to verify the fix.
\ No newline at end of file
diff --git a/app/vendor/cakephp/migrations/.stickler.yml b/app/vendor/cakephp/migrations/.stickler.yml
deleted file mode 100644
index 0ec83f6f0..000000000
--- a/app/vendor/cakephp/migrations/.stickler.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-linters:
- phpcs:
- standard: CakePHP
-files:
- ignore: ['tests/bootstrap.php', 'tests/comparisons/*']
diff --git a/app/vendor/cakephp/migrations/Dockerfile b/app/vendor/cakephp/migrations/Dockerfile
new file mode 100644
index 000000000..478f14c71
--- /dev/null
+++ b/app/vendor/cakephp/migrations/Dockerfile
@@ -0,0 +1,25 @@
+# Basic docker based environment
+# Necessary to trick dokku into building the documentation
+# using dockerfile instead of herokuish
+FROM ubuntu:17.04
+
+# Add basic tools
+RUN apt-get update && \
+ apt-get install -y build-essential \
+ software-properties-common \
+ curl \
+ git \
+ libxml2 \
+ libffi-dev \
+ libssl-dev && \
+ LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php && \
+ apt-get update && \
+ apt-get install -y php7.2-cli php7.2-mbstring php7.2-xml php7.2-zip php7.2-intl php7.2-opcache php7.2-sqlite &&\
+ apt-get clean &&\
+ rm -rf /var/lib/apt/lists/*
+
+WORKDIR /code
+
+VOLUME ["/code"]
+
+CMD [ '/bin/bash' ]
diff --git a/app/vendor/cakephp/migrations/LICENSE.txt b/app/vendor/cakephp/migrations/LICENSE.txt
index 5849d31d4..0a0a98c8e 100644
--- a/app/vendor/cakephp/migrations/LICENSE.txt
+++ b/app/vendor/cakephp/migrations/LICENSE.txt
@@ -1,7 +1,7 @@
The MIT License
CakePHP(tm) : The Rapid Development PHP Framework (http://cakephp.org)
-Copyright (c) 2005-2018, Cake Software Foundation, Inc.
+Copyright (c) 2005-present, Cake Software Foundation, Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/app/vendor/cakephp/migrations/README.md b/app/vendor/cakephp/migrations/README.md
index a7176273f..d929c681d 100644
--- a/app/vendor/cakephp/migrations/README.md
+++ b/app/vendor/cakephp/migrations/README.md
@@ -1,17 +1,19 @@
# Migrations plugin for CakePHP
[](LICENSE.txt)
-[](https://travis-ci.org/cakephp/migrations)
+[](https://travis-ci.com/cakephp/migrations)
[](https://codecov.io/github/cakephp/migrations?branch=master)
[](https://packagist.org/packages/cakephp/migrations)
-This is a Database Migrations system for CakePHP 3.
+This is a Database Migrations system for CakePHP.
-The plugin consists of a CakePHP shell wrapper for the [phinx](http://phinx.org) migrations library.
+The plugin consists of a CakePHP shell wrapper for the [Phinx](https://book.cakephp.org/phinx/0/en/index.html) migrations library.
+
+This branch is for use with CakePHP **4.x**. See [version map](https://github.com/cakephp/migrations/wiki#version-map) for details.
## Installation
-You can install this plugin into your CakePHP application using [composer](http://getcomposer.org).
+You can install this plugin into your CakePHP application using [Composer](http://getcomposer.org).
Run the following command
```sh
@@ -26,14 +28,17 @@ You can load the plugin using the shell command:
bin/cake plugin load Migrations
```
-Or you can manually add the loading statement in the **config/bootstrap.php** file of your application:
-
+Or you can manually add the loading statement in the **src/Application.php** file of your application:
```php
-Plugin::load('Migrations');
+public function bootstrap()
+{
+ parent::bootstrap();
+ $this->addPlugin('Migrations');
+}
```
Additionally, you will need to configure the ``default`` database configuration in your **config/app.php** file.
## Documentation
-Full documentation of the plugin can be found on the [CakePHP Cookbook](http://book.cakephp.org/3.0/en/migrations.html).
+Full documentation of the plugin can be found on the [CakePHP Cookbook](https://book.cakephp.org/migrations/2/).
diff --git a/app/vendor/cakephp/migrations/composer.json b/app/vendor/cakephp/migrations/composer.json
index c4b916c18..b277a25ee 100644
--- a/app/vendor/cakephp/migrations/composer.json
+++ b/app/vendor/cakephp/migrations/composer.json
@@ -1,6 +1,6 @@
{
"name": "cakephp/migrations",
- "description": "Database Migration plugin for CakePHP 3.0 based on Phinx",
+ "description": "Database Migration plugin for CakePHP based on Phinx",
"type": "cakephp-plugin",
"keywords": ["cakephp", "migrations"],
"homepage": "https://github.com/cakephp/migrations",
@@ -13,48 +13,50 @@
],
"support": {
"issues": "https://github.com/cakephp/migrations/issues",
- "forum": "http://stackoverflow.com/tags/cakephp",
+ "forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"source": "https://github.com/cakephp/migrations"
},
"require": {
- "php": ">=5.6.0",
- "robmorgan/phinx": "0.8.1",
- "cakephp/orm": "^3.6.0",
- "cakephp/cache": "^3.6.0"
+ "php": ">=7.2.0",
+ "robmorgan/phinx": "^0.12",
+ "cakephp/orm": "^4.0.5",
+ "cakephp/cache": "^4.0.5"
},
"require-dev": {
- "phpunit/phpunit": "^5.7.14",
- "cakephp/cakephp": "^3.6.0",
- "cakephp/bake": "^1.7.0",
- "cakephp/cakephp-codesniffer": "^3.0"
+ "phpunit/phpunit": "~8.5.0",
+ "cakephp/cakephp": "^4.0.5",
+ "cakephp/bake": "^2.1.0",
+ "cakephp/cakephp-codesniffer": "~4.1.0"
},
"autoload": {
"psr-4": {
- "Migrations\\": "src"
+ "Migrations\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
- "Cake\\Test\\": "./vendor/cakephp/cakephp/tests",
- "Migrations\\PHPStan\\": "tests/PHPStan",
- "Migrations\\Test\\": "tests",
- "TestApp\\": "tests/test_app/App",
- "TestBlog\\": "tests/test_app/Plugin/TestBlog/src"
+ "Cake\\Test\\": "./vendor/cakephp/cakephp/tests/",
+ "Migrations\\Test\\": "tests/",
+ "TestApp\\": "tests/test_app/App/",
+ "TestBlog\\": "tests/test_app/Plugin/TestBlog/src/"
}
},
"suggest": {
- "cakephp/bake": "Required if you want to generate migrations."
+ "cakephp/bake": "If you want to generate migrations.",
+ "dereuromark/cakephp-ide-helper": "If you want to have IDE suggest/autocomplete when creating migrations."
},
- "minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"check": [
"@cs-check",
- "@test"
+ "@test",
+ "@stan"
],
- "cs-check": "phpcs --colors -p ./src ./tests",
- "cs-fix": "phpcbf --colors ./src ./tests",
+ "cs-check": "phpcs --colors -p -s --ignore=/tests/comparisons/,/test_app/config/,/TestBlog/config/ src/ tests/",
+ "cs-fix": "phpcbf --colors -p --ignore=/tests/comparisons/,/test_app/config/,/TestBlog/config/ src/ tests/",
+ "stan": "phpstan analyse src/ && psalm.phar --show-info=false",
+ "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12 psalm/phar:~3.11.2 && mv composer.backup composer.json",
"test": "phpunit",
"test-coverage": "phpunit --coverage-clover=clover.xml"
}
diff --git a/app/vendor/cakephp/migrations/docs.Dockerfile b/app/vendor/cakephp/migrations/docs.Dockerfile
new file mode 100644
index 000000000..57e67529a
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs.Dockerfile
@@ -0,0 +1,20 @@
+# Generate the HTML output.
+FROM markstory/cakephp-docs-builder as builder
+
+COPY docs /data/docs
+
+RUN cd /data/docs-builder && \
+ # In the future repeat website for each version
+ make website LANGS="en fr ja pt ru" SOURCE=/data/docs DEST=/data/website/
+
+# Build a small nginx container with just the static site in it.
+FROM nginx:1.15-alpine
+
+COPY --from=builder /data/website /data/website
+COPY --from=builder /data/docs-builder/nginx.conf /etc/nginx/conf.d/default.conf
+
+# Move each version into place
+RUN cp -R /data/website/html/* /usr/share/nginx/html \
+ && rm -rf /data/website/
+
+RUN ln -s /usr/share/nginx/html /usr/share/nginx/html/2.x
diff --git a/app/vendor/symfony/config/Tests/Fixtures/Again/foo.xml b/app/vendor/cakephp/migrations/docs/config/__init__.py
similarity index 100%
rename from app/vendor/symfony/config/Tests/Fixtures/Again/foo.xml
rename to app/vendor/cakephp/migrations/docs/config/__init__.py
diff --git a/app/vendor/cakephp/migrations/docs/config/all.py b/app/vendor/cakephp/migrations/docs/config/all.py
new file mode 100644
index 000000000..ff278a201
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/config/all.py
@@ -0,0 +1,51 @@
+# Global configuration information used across all the
+# translations of documentation.
+#
+# Import the base theme configuration
+from cakephpsphinx.config.all import *
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+
+# The full version, including alpha/beta/rc tags.
+release = '3.x'
+
+# The search index version.
+search_version = 'migrations-3'
+
+# The marketing display name for the book.
+version_name = ''
+
+# Project name shown in the black header bar
+project = 'CakePHP Migrations'
+
+# Other versions that display in the version picker menu.
+version_list = [
+ {'name': '2.x', 'number': '/migrations/2', 'title': '2.x'},
+ {'name': '3.x', 'number': '/migrations/3', 'title': '3.x', 'current': True},
+]
+
+# Languages available.
+languages = ['en', 'fr', 'ja', 'pt', 'ru']
+
+# The GitHub branch name for this version of the docs
+# for edit links to point at.
+branch = 'master'
+
+# Current version being built
+version = '3.x'
+
+# Language in use for this directory.
+language = 'en'
+
+show_root_link = True
+
+repository = 'cakephp/migrations'
+
+source_path = 'docs/'
+
+hide_page_contents = ('search', '404', 'contents')
+
+is_prerelease = False
diff --git a/app/vendor/cakephp/migrations/docs/en/conf.py b/app/vendor/cakephp/migrations/docs/en/conf.py
new file mode 100644
index 000000000..f638bda22
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/en/conf.py
@@ -0,0 +1,9 @@
+import sys, os
+
+# Append the top level directory of the docs, so we can import from the config dir.
+sys.path.insert(0, os.path.abspath('..'))
+
+# Pull in all the configuration options defined in the global config file..
+from config.all import *
+
+language = 'en'
diff --git a/app/vendor/cakephp/migrations/docs/en/contents.rst b/app/vendor/cakephp/migrations/docs/en/contents.rst
new file mode 100644
index 000000000..1459b1f1b
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/en/contents.rst
@@ -0,0 +1,5 @@
+.. toctree::
+ :maxdepth: 2
+ :caption: CakePHP Migrations
+
+ /index
diff --git a/app/vendor/cakephp/migrations/docs/en/index.rst b/app/vendor/cakephp/migrations/docs/en/index.rst
new file mode 100644
index 000000000..292ab119a
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/en/index.rst
@@ -0,0 +1,1102 @@
+Migrations
+##########
+
+Migrations is a plugin supported by the core team that helps you do schema
+changes in your database by writing PHP files that can be tracked using your
+version control system.
+
+It allows you to evolve your database tables over time. Instead of writing
+schema modifications in SQL, this plugin allows you to use an intuitive set of
+methods to implement your database changes.
+
+This plugin is a wrapper for the database migrations library `Phinx `_.
+
+Installation
+============
+
+By default Migrations is installed with the default application skeleton. If
+you've removed it and want to re-install it, you can do so by running the
+following from your application's ROOT directory (where composer.json file is
+located):
+
+.. code-block:: bash
+
+ php composer.phar require cakephp/migrations "@stable"
+
+ # Or if composer is installed globally
+ composer require cakephp/migrations "@stable"
+
+To use the plugin you'll need to load it in your application's
+**config/bootstrap.php** file. You can use `CakePHP's Plugin shell
+`__ to
+load and unload plugins from your **config/bootstrap.php**:
+
+.. code-block:: bash
+
+ bin/cake plugin load Migrations
+
+Or you can load the plugin by editing your **src/Application.php** file and
+adding the following statement::
+
+ $this->addPlugin('Migrations');
+
+ // Prior to 3.6.0 you need to use Plugin::load()
+
+Additionally, you will need to configure the default database configuration for
+your application in your **config/app.php** file as explained in the `Database
+Configuration section
+`__.
+
+Overview
+========
+
+A migration is basically a single PHP file that describes the changes to operate
+to the database. A migration file can create or drop tables, add or remove
+columns, create indexes and even insert data into your database.
+
+Here's an example of a migration::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+This migration will add a table to your database named ``products`` with the
+following column definitions:
+
+- ``id`` column of type ``integer`` as primary key
+- ``name`` column of type ``string``
+- ``description`` column of type ``text``
+- ``created`` column of type ``datetime``
+- ``modified`` column of type ``datetime``
+
+.. tip::
+
+ The primary key column named ``id`` will be added **implicitly**.
+
+.. note::
+
+ Note that this file describes how the database will look **after**
+ applying the migration. At this point no ``products`` table exists in
+ your database, we have merely created a file that is able to both create
+ the ``products`` table with the specified columns as well as drop it
+ when a ``rollback`` operation of the migration is performed.
+
+Once the file has been created in the **config/Migrations** folder, you will be
+able to execute the following ``migrations`` command to create the table in
+your database:
+
+.. code-block:: bash
+
+ bin/cake migrations migrate
+
+The following ``migrations`` command will perform a ``rollback`` and drop the
+table from your database:
+
+.. code-block:: bash
+
+ bin/cake migrations rollback
+
+Creating Migrations
+===================
+
+Migration files are stored in the **config/Migrations** directory of your
+application. The name of the migration files are prefixed with the date in
+which they were created, in the format **YYYYMMDDHHMMSS_MigrationName.php**.
+Here are examples of migration filenames:
+
+* 20160121163850_CreateProducts.php
+* 20160210133047_AddRatingToProducts.php
+
+The easiest way to create a migrations file is by using ``bin/cake bake
+migration`` CLI command.
+
+Please make sure you read the official
+`Phinx documentation `_
+in order to know the complete list of methods you can use for writing migration
+files.
+
+.. note::
+
+ When using the ``bake`` option, you can still modify the migration before
+ running them if so desired.
+
+Syntax
+------
+
+The ``bake`` command syntax follows the form below:
+
+.. code-block:: bash
+
+ bin/cake bake migration CreateProducts name:string description:text created modified
+
+When using ``bake`` to create tables, add columns and so on, to your
+database, you will usually provide two things:
+
+* the name of the migration you will generate (``CreateProducts`` in our
+ example)
+* the columns of the table that will be added or removed in the migration
+ (``name:string description:text created modified`` in our example)
+
+Due to the conventions, not all schema changes can be performed via these shell
+commands.
+
+Additionally you can create an empty migrations file if you want full control
+over what needs to be executed, by omitting to specify a columns definition:
+
+.. code-block:: bash
+
+ bin/cake migrations create MyCustomMigration
+
+Migrations file name
+~~~~~~~~~~~~~~~~~~~~
+
+Migration names can follow any of the following patterns:
+
+* (``/^(Create)(.*)/``) Creates the specified table.
+* (``/^(Drop)(.*)/``) Drops the specified table.
+ Ignores specified field arguments
+* (``/^(Add).*(?:To)(.*)/``) Adds fields to the specified
+ table
+* (``/^(Remove).*(?:From)(.*)/``) Removes fields from the
+ specified table
+* (``/^(Alter)(.*)/``) Alters the specified table. An alias
+ for CreateTable and AddField.
+* (``/^(Alter).*(?:On)(.*)/``) Alters fields from the specified table.
+
+You can also use the ``underscore_form`` as the name for your migrations i.e.
+``create_products``.
+
+.. versionadded:: cakephp/migrations 1.5.2
+
+ As of v1.5.2 of the `migrations plugin `_,
+ the migration filename will be automatically camelized. This version of the
+ plugin is only available with a release of CakePHP >= to 3.1. Prior to this
+ version of the plugin the migration name would be in the underscore form,
+ i.e. ``20160121164955_create_products.php``.
+
+.. warning::
+
+ Migration names are used as migration class names, and thus may collide with
+ other migrations if the class names are not unique. In this case, it may be
+ necessary to manually override the name at a later date, or simply change
+ the name you are specifying.
+
+Columns definition
+~~~~~~~~~~~~~~~~~~
+
+When using columns in the command line, it may be handy to remember that they
+follow the following pattern::
+
+ fieldName:fieldType?[length]:indexType:indexName
+
+For instance, the following are all valid ways of specifying an email field:
+
+* ``email:string?``
+* ``email:string:unique``
+* ``email:string?[50]``
+* ``email:string:unique:EMAIL_INDEX``
+* ``email:string[120]:unique:EMAIL_INDEX``
+
+While defining decimal, the ``length`` can be defined to have precision and scale, separated by a comma.
+
+* ``amount:decimal[5,2]``
+* ``amount:decimal?[5,2]``
+
+The question mark following the fieldType will make the column nullable.
+
+The ``length`` parameter for the ``fieldType`` is optional and should always be
+written between bracket.
+
+Fields named ``created`` and ``modified``, as well as any field with a ``_at``
+suffix, will automatically be set to the type ``datetime``.
+
+Field types are those generically made available by the ``Phinx`` library. Those
+can be:
+
+* string
+* text
+* integer
+* biginteger
+* float
+* decimal
+* datetime
+* timestamp
+* time
+* date
+* binary
+* boolean
+* uuid
+
+There are some heuristics to choosing fieldtypes when left unspecified or set to
+an invalid value. Default field type is ``string``:
+
+* id: integer
+* created, modified, updated: datetime
+* latitude, longitude (or short forms lat, lng): decimal
+
+Creating a table
+----------------
+
+You can use ``bake`` to create a table:
+
+.. code-block:: bash
+
+ bin/cake bake migration CreateProducts name:string description:text created modified
+
+The command line above will generate a migration file that resembles::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+Adding columns to an existing table
+-----------------------------------
+
+If the migration name in the command line is of the form "AddXXXToYYY" and is
+followed by a list of column names and types then a migration file containing
+the code for creating the columns will be generated:
+
+.. code-block:: bash
+
+ bin/cake bake migration AddPriceToProducts price:decimal[5,2]
+
+Executing the command line above will generate::
+
+ table('products');
+ $table->addColumn('price', 'decimal', [
+ 'default' => null,
+ 'null' => false,
+ 'precision' => 5,
+ 'scale' => 2,
+ ]);
+ $table->update();
+ }
+ }
+
+Adding a column as index to a table
+-----------------------------------
+
+It is also possible to add indexes to columns:
+
+.. code-block:: bash
+
+ bin/cake bake migration AddNameIndexToProducts name:string:index
+
+will generate::
+
+ table('products');
+ $table->addColumn('name', 'string')
+ ->addIndex(['name'])
+ ->update();
+ }
+ }
+
+Specifying field length
+-----------------------
+
+.. versionadded:: cakephp/migrations 1.4
+
+If you need to specify a field length, you can do it within brackets in the
+field type, ie:
+
+.. code-block:: bash
+
+ bin/cake bake migration AddFullDescriptionToProducts full_description:string[60]
+
+Executing the command line above will generate::
+
+ table('products');
+ $table->addColumn('full_description', 'string', [
+ 'default' => null,
+ 'limit' => 60,
+ 'null' => false,
+ ])
+ ->update();
+ }
+ }
+
+If no length is specified, lengths for certain type of columns are defaulted:
+
+* string: 255
+* integer: 11
+* biginteger: 20
+
+Alter a column from a table
+-----------------------------------
+
+In the same way, you can generate a migration to alter a column by using the
+command line, if the migration name is of the form "AlterXXXOnYYY":
+
+.. code-block:: bash
+
+ bin/cake bake migration AlterPriceOnProducts name:float
+
+will generate::
+
+ table('products');
+ $table->changeColumn('name', 'float');
+ $table->update();
+ }
+ }
+
+Removing a column from a table
+------------------------------
+
+In the same way, you can generate a migration to remove a column by using the
+command line, if the migration name is of the form "RemoveXXXFromYYY":
+
+.. code-block:: bash
+
+ bin/cake bake migration RemovePriceFromProducts price
+
+creates the file::
+
+ table('products');
+ $table->removeColumn('price')
+ ->save();
+ }
+ }
+
+.. note::
+
+ The `removeColumn` command is not reversible, so must be called in the
+ `up` method. A corresponding `addColumn` call should be added to the
+ `down` method.
+
+Generating migrations from an existing database
+===============================================
+
+If you are dealing with a pre-existing database and want to start using
+migrations, or to version control the initial schema of your application's
+database, you can run the ``migration_snapshot`` command:
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial
+
+It will generate a migration file called **YYYYMMDDHHMMSS_Initial.php**
+containing all the create statements for all tables in your database.
+
+By default, the snapshot will be created by connecting to the database defined
+in the ``default`` connection configuration.
+If you need to bake a snapshot from a different datasource, you can use the
+``--connection`` option:
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --connection my_other_connection
+
+You can also make sure the snapshot includes only the tables for which you have
+defined the corresponding model classes by using the ``--require-table`` flag:
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --require-table
+
+When using the ``--require-table`` flag, the shell will look through your
+application ``Table`` classes and will only add the model tables in the snapshot
+.
+
+The same logic will be applied implicitly if you wish to bake a snapshot for a
+plugin. To do so, you need to use the ``--plugin`` option:
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --plugin MyPlugin
+
+Only the tables which have a ``Table`` object model class defined will be added
+to the snapshot of your plugin.
+
+.. note::
+
+ When baking a snapshot for a plugin, the migration files will be created
+ in your plugin's **config/Migrations** directory.
+
+Be aware that when you bake a snapshot, it is automatically added to the phinx
+log table as migrated.
+
+Generating a diff between two database states
+=============================================
+
+.. versionadded:: cakephp/migrations 1.6.0
+
+You can generate a migrations file that will group all the differences between
+two database states using the ``migration_diff`` bake template. To do so, you
+can use the following command:
+
+.. code-block:: bash
+
+ bin/cake bake migration_diff NameOfTheMigrations
+
+In order to have a point of comparison from your current database state, the
+migrations shell will generate a "dump" file after each ``migrate`` or
+``rollback`` call. The dump file is a file containing the full schema state of
+your database at a given point in time.
+
+Once a dump file is generated, every modifications you do directly in your
+database management system will be added to the migration file generated when
+you call the ``bake migration_diff`` command.
+
+By default, the diff will be created by connecting to the database defined
+in the ``default`` connection configuration.
+If you need to bake a diff from a different datasource, you can use the
+``--connection`` option:
+
+.. code-block:: bash
+
+ bin/cake bake migration_diff NameOfTheMigrations --connection my_other_connection
+
+If you want to use the diff feature on an application that already has a
+migrations history, you need to manually create the dump file that will be used
+as comparison:
+
+.. code-block:: bash
+
+ bin/cake migrations dump
+
+The database state must be the same as it would be if you just migrated all
+your migrations before you create a dump file.
+Once the dump file is generated, you can start doing changes in your database
+and use the ``bake migration_diff`` command whenever you see fit.
+
+.. note::
+
+ The migrations shell can not detect column renamings.
+
+The commands
+============
+
+``migrate`` : Applying Migrations
+---------------------------------
+
+Once you have generated or written your migration file, you need to execute the
+following command to apply the changes to your database:
+
+.. code-block:: bash
+
+ # Run all the migrations
+ bin/cake migrations migrate
+
+ # Migrate to a specific version using the ``--target`` option
+ # or ``-t`` for short.
+ # The value is the timestamp that is prefixed to the migrations file name::
+ bin/cake migrations migrate -t 20150103081132
+
+ # By default, migration files are looked for in the **config/Migrations**
+ # directory. You can specify the directory using the ``--source`` option
+ # or ``-s`` for short.
+ # The following example will run migrations in the **config/Alternate**
+ # directory
+ bin/cake migrations migrate -s Alternate
+
+ # You can run migrations to a different connection than the ``default`` one
+ # using the ``--connection`` option or ``-c`` for short
+ bin/cake migrations migrate -c my_custom_connection
+
+ # Migrations can also be run for plugins. Simply use the ``--plugin`` option
+ # or ``-p`` for short
+ bin/cake migrations migrate -p MyAwesomePlugin
+
+``rollback`` : Reverting Migrations
+-----------------------------------
+
+The Rollback command is used to undo previous migrations executed by this
+plugin. It is the reverse action of the ``migrate`` command:
+
+.. code-block:: bash
+
+ # You can rollback to the previous migration by using the
+ # ``rollback`` command::
+ bin/cake migrations rollback
+
+ # You can also pass a migration version number to rollback
+ # to a specific version::
+ bin/cake migrations rollback -t 20150103081132
+
+You can also use the ``--source``, ``--connection`` and ``--plugin`` options
+just like for the ``migrate`` command.
+
+``status`` : Migrations Status
+------------------------------
+
+The Status command prints a list of all migrations, along with their current
+status. You can use this command to determine which migrations have been run:
+
+.. code-block:: bash
+
+ bin/cake migrations status
+
+You can also output the results as a JSON formatted string using the
+``--format`` option (or ``-f`` for short):
+
+.. code-block:: bash
+
+ bin/cake migrations status --format json
+
+You can also use the ``--source``, ``--connection`` and ``--plugin`` options
+just like for the ``migrate`` command.
+
+``mark_migrated`` : Marking a migration as migrated
+---------------------------------------------------
+
+.. versionadded:: 1.4.0
+
+It can sometimes be useful to mark a set of migrations as migrated without
+actually running them.
+In order to do this, you can use the ``mark_migrated`` command.
+The command works seamlessly as the other commands.
+
+You can mark all migrations as migrated using this command:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated
+
+You can also mark all migrations up to a specific version as migrated using
+the ``--target`` option:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000
+
+If you do not want the targeted migration to be marked as migrated during the
+process, you can use the ``--exclude`` flag with it:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000 --exclude
+
+Finally, if you wish to mark only the targeted migration as migrated, you can
+use the ``--only`` flag:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000 --only
+
+You can also use the ``--source``, ``--connection`` and ``--plugin`` options
+just like for the ``migrate`` command.
+
+.. note::
+
+ When you bake a snapshot with the ``cake bake migration_snapshot``
+ command, the created migration will automatically be marked as migrated.
+
+.. deprecated:: 1.4.0
+
+ The following way of using the command has been deprecated. Use it only
+ if you are using a version of the plugin < 1.4.0.
+
+This command expects the migration version number as argument:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated 20150420082532
+
+If you wish to mark all migrations as migrated, you can use the ``all`` special
+value. If you use it, it will mark all found migrations as migrated:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated all
+
+``seed`` : Seeding your database
+--------------------------------
+
+As of 1.5.5, you can use the ``migrations`` shell to seed your database. This
+leverages the `Phinx library seed feature `_.
+By default, seed files will be looked for in the ``config/Seeds`` directory of
+your application. Please make sure you follow
+`Phinx instructions to build your seed files `_.
+
+As for migrations, a ``bake`` interface is provided for seed files:
+
+.. code-block:: bash
+
+ # This will create a ArticlesSeed.php file in the directory config/Seeds of your application
+ # By default, the table the seed will try to alter is the "tableized" version of the seed filename
+ bin/cake bake seed Articles
+
+ # You specify the name of the table the seed files will alter by using the ``--table`` option
+ bin/cake bake seed Articles --table my_articles_table
+
+ # You can specify a plugin to bake into
+ bin/cake bake seed Articles --plugin PluginName
+
+ # You can specify an alternative connection when generating a seeder.
+ bin/cake bake seed Articles --connection connection
+
+.. versionadded:: cakephp/migrations 1.6.4
+
+ Options ``--data``, ``--limit`` and ``--fields`` were added to export
+ data from your database.
+
+As of 1.6.4, the ``bake seed`` command allows you to create a seed file with
+data exported from your database by using the ``--data`` flag:
+
+.. code-block:: bash
+
+ bin/cake bake seed --data Articles
+
+By default, it will export all the rows found in your table. You can limit the
+number of rows exported by using the ``--limit`` option:
+
+.. code-block:: bash
+
+ # Will only export the first 10 rows found
+ bin/cake bake seed --data --limit 10 Articles
+
+If you only want to include a selection of fields from the table in your seed
+file, you can use the ``--fields`` option. It takes the list of fields to
+include as a comma separated value string:
+
+.. code-block:: bash
+
+ # Will only export the fields `id`, `title` and `excerpt`
+ bin/cake bake seed --data --fields id,title,excerpt Articles
+
+.. tip::
+
+ Of course you can use both the ``--limit`` and ``--fields`` options in the
+ same command call.
+
+To seed your database, you can use the ``seed`` subcommand:
+
+.. code-block:: bash
+
+ # Without parameters, the seed subcommand will run all available seeders
+ # in the target directory, in alphabetical order.
+ bin/cake migrations seed
+
+ # You can specify only one seeder to be run using the `--seed` option
+ bin/cake migrations seed --seed ArticlesSeed
+
+ # You can run seeders from an alternative directory, relative to config
+ bin/cake migrations seed --source AlternativeSeeds
+
+ # You can run seeders from a plugin
+ bin/cake migrations seed --plugin PluginName
+
+ # You can run seeders from a specific connection
+ bin/cake migrations seed --connection connection
+
+Be aware that, as opposed to migrations, seeders are not tracked, which means
+that the same seeder can be applied multiple times.
+
+Calling a Seeder from another Seeder
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: cakephp/migrations 1.6.2
+
+Usually when seeding, the order in which to insert the data must be respected
+to not encounter constraints violations. Since Seeders are executed in the
+alphabetical order by default, you can use the ``\Migrations\AbstractSeed::call()``
+method to define your own sequence of seeders execution::
+
+ use Migrations\AbstractSeed;
+
+ class DatabaseSeed extends AbstractSeed
+ {
+ public function run()
+ {
+ $this->call('AnotherSeed');
+ $this->call('YetAnotherSeed');
+
+ // You can use the plugin dot syntax to call seeders from a plugin
+ $this->call('PluginName.FromPluginSeed');
+ }
+ }
+
+.. note::
+
+ Make sure to extend the Migrations plugin ``AbstractSeed`` class if you want
+ to be able to use the ``call()`` method. This class was added with release
+ 1.6.2.
+
+``dump`` : Generating a dump file for the diff baking feature
+-------------------------------------------------------------
+
+The Dump command creates a file to be used with the ``migration_diff`` bake
+template:
+
+.. code-block:: bash
+
+ bin/cake migrations dump
+
+Each generated dump file is specific to the Connection it is generated from (and
+is suffixed as such). This allows the ``bake migration_diff`` command to
+properly compute diff in case your application is dealing with multiple database
+possibly from different database vendors.
+
+Dump files are created in the same directory as your migrations files.
+
+You can also use the ``--source``, ``--connection`` and ``--plugin`` options
+just like for the ``migrate`` command.
+
+Using Migrations In Plugins
+===========================
+
+Plugins can also provide migration files. This makes plugins that are intended
+to be distributed much more portable and easy to install. All commands in the
+Migrations plugin support the ``--plugin`` or ``-p`` option that will scope the
+execution to the migrations relative to that plugin:
+
+.. code-block:: bash
+
+ bin/cake migrations status -p PluginName
+
+ bin/cake migrations migrate -p PluginName
+
+Running Migrations in a non-shell environment
+=============================================
+
+.. versionadded:: cakephp/migrations 1.2.0
+
+Since the release of version 1.2 of the migrations plugin, you can run
+migrations from a non-shell environment, directly from an app, by using the new
+``Migrations`` class. This can be handy in case you are developing a plugin
+installer for a CMS for instance.
+The ``Migrations`` class allows you to run the following commands from the
+migrations shell:
+
+* migrate
+* rollback
+* markMigrated
+* status
+* seed
+
+Each of these commands has a method defined in the ``Migrations`` class.
+
+Here is how to use it::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // Will return an array of all migrations and their status
+ $status = $migrations->status();
+
+ // Will return true if success. If an error occurred, an exception will be thrown
+ $migrate = $migrations->migrate();
+
+ // Will return true if success. If an error occurred, an exception will be thrown
+ $rollback = $migrations->rollback();
+
+ // Will return true if success. If an error occurred, an exception will be thrown
+ $markMigrated = $migrations->markMigrated(20150804222900);
+
+ // Will return true if success. If an error occurred, an exception will be thrown
+ $seeded = $migrations->seed();
+
+The methods can accept an array of parameters that should match options from
+the commands::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // Will return an array of all migrations and their status
+ $status = $migrations->status(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+You can pass any options the shell commands would take.
+The only exception is the ``markMigrated`` command which is expecting the
+version number of the migrations to mark as migrated as first argument. Pass
+the array of parameters as the second argument for this method.
+
+Optionally, you can pass these parameters in the constructor of the class.
+They will be used as default and this will prevent you from having to pass
+them on each method call::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // All the following calls will be done with the parameters passed to the Migrations class constructor
+ $status = $migrations->status();
+ $migrate = $migrations->migrate();
+
+If you need to override one or more default parameters for one call, you can
+pass them to the method::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // This call will be made with the "custom" connection
+ $status = $migrations->status();
+ // This one with the "default" connection
+ $migrate = $migrations->migrate(['connection' => 'default']);
+
+Tips and tricks
+===============
+
+Creating Custom Primary Keys
+----------------------------
+
+If you need to avoid the automatic creation of the ``id`` primary key when
+adding new tables to the database, you can use the second argument of the
+``table()`` method::
+
+ table('products', ['id' => false, 'primary_key' => ['id']]);
+ $table
+ ->addColumn('id', 'uuid')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+The above will create a ``CHAR(36)`` ``id`` column that is also the primary key.
+
+.. note::
+
+ When specifying a custom primary key on the command line, you must note
+ it as the primary key in the id field, otherwise you may get an error
+ regarding duplicate id fields, i.e.:
+
+ .. code-block:: bash
+
+ bin/cake bake migration CreateProducts id:uuid:primary name:string description:text created modified
+
+Additionally, since Migrations 1.3, a new way to deal with primary key was
+introduced. To do so, your migration class should extend the new
+``Migrations\AbstractMigration`` class.
+You can specify a ``autoId`` property in the Migration class and set it to
+``false``, which will turn off the automatic ``id`` column creation. You will
+need to manually create the column that will be used as a primary key and add
+it to the table declaration::
+
+ table('products');
+ $table
+ ->addColumn('id', 'integer', [
+ 'autoIncrement' => true,
+ 'limit' => 11
+ ])
+ ->addPrimaryKey('id')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+Compared to the previous way of dealing with primary key, this method gives you
+the ability to have more control over the primary key column definition:
+unsigned or not, limit, comment, etc.
+
+All baked migrations and snapshot will use this new way when necessary.
+
+.. warning::
+
+ Dealing with primary key can only be done on table creation operations.
+ This is due to limitations for some database servers the plugin supports.
+
+Collations
+----------
+
+If you need to create a table with a different collation than the database
+default one, you can define it with the ``table()`` method, as an option::
+
+ table('categories', [
+ 'collation' => 'latin1_german1_ci'
+ ])
+ ->addColumn('title', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ])
+ ->create();
+ }
+ }
+
+Note however this can only be done on table creation : there is currently
+no way of adding a column to an existing table with a different collation than
+the table or the database.
+Only ``MySQL`` and ``SqlServer`` supports this configuration key for the time
+being.
+
+Updating columns name and using Table objects
+---------------------------------------------
+
+If you use a CakePHP ORM Table object to manipulate values from your database
+along with renaming or removing a column, make sure you create a new instance of
+your Table object after the ``update()`` call. The Table object registry is
+cleared after an ``update()`` call in order to refresh the schema that is
+reflected and stored in the Table object upon instantiation.
+
+Migrations and Deployment
+-------------------------
+
+If you use the plugin when deploying your application, be sure to clear the ORM
+cache so it renews the column metadata of your tables. Otherwise, you might end
+up having errors about columns not existing when performing operations on those
+new columns. The CakePHP Core includes a `Schema Cache Shell
+`__ that
+you can use to perform this operation:
+
+.. code-block:: bash
+
+ // Prior to 3.6 use orm_cache
+ bin/cake schema_cache clear
+
+Renaming a table
+----------------
+
+The plugin gives you the ability to rename a table, using the ``rename()``
+method. In your migration file, you can do the following::
+
+ public function up()
+ {
+ $this->table('old_table_name')
+ ->rename('new_table_name')
+ ->save();
+ }
+
+Skipping the ``schema.lock`` file generation
+--------------------------------------------
+
+.. versionadded:: cakephp/migrations 1.6.5
+
+In order for the diff feature to work, a **.lock** file is generated everytime
+you migrate, rollback or bake a snapshot, to keep track of the state of your
+database schema at any given point in time. You can skip this file generation,
+for instance when deploying on your production environment, by using the
+``--no-lock`` option for the aforementioned command:
+
+.. code-block:: bash
+
+ bin/cake migrations migrate --no-lock
+
+ bin/cake migrations rollback --no-lock
+
+ bin/cake bake migration_snapshot MyMigration --no-lock
+
+IDE autocomplete support
+------------------------
+
+The `IdeHelper plugin
+`__ can help
+you to get more IDE support for the tables, their column names and possible column types.
+Specifically PHPStorm understands the meta information and can help you autocomplete those.
diff --git a/app/vendor/cakephp/migrations/docs/fr/conf.py b/app/vendor/cakephp/migrations/docs/fr/conf.py
new file mode 100644
index 000000000..b02032efa
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/fr/conf.py
@@ -0,0 +1,9 @@
+import sys, os
+
+# Append the top level directory of the docs, so we can import from the config dir.
+sys.path.insert(0, os.path.abspath('..'))
+
+# Pull in all the configuration options defined in the global config file..
+from config.all import *
+
+language = 'fr'
diff --git a/app/vendor/cakephp/migrations/docs/fr/contents.rst b/app/vendor/cakephp/migrations/docs/fr/contents.rst
new file mode 100644
index 000000000..1459b1f1b
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/fr/contents.rst
@@ -0,0 +1,5 @@
+.. toctree::
+ :maxdepth: 2
+ :caption: CakePHP Migrations
+
+ /index
diff --git a/app/vendor/cakephp/migrations/docs/fr/index.rst b/app/vendor/cakephp/migrations/docs/fr/index.rst
new file mode 100644
index 000000000..b8e78cd0a
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/fr/index.rst
@@ -0,0 +1,1131 @@
+Migrations
+##########
+
+Migrations est un plugin supporté par la core team pour vous aider à gérer les
+changements dans la base de données en écrivant des fichiers PHP qui peuvent
+être versionnés par votre système de gestion de version.
+
+Il vous permet de faire évoluer vos tables au fil du temps.
+Au lieu d'écrire vos modifications de schéma en SQL, ce plugin vous permet
+d'utiliser un ensemble intuitif de méthodes qui facilite la mise en œuvre des
+modifications au sein de la base de données.
+
+Ce plugin est un wrapper pour la librairie de gestion des migrations de bases de
+données `Phinx `_.
+
+Installation
+============
+
+Par défaut Migrations est installé avec le squelette d’application. Si vous le
+retirez et voulez le réinstaller, vous pouvez le faire en lançant ce qui suit à
+partir du répertoire ROOT de votre application (où le fichier composer.json est
+localisé):
+
+.. code-block:: bash
+
+ php composer.phar require cakephp/migrations "@stable"
+
+ # Ou si composer est installé globalement
+
+ composer require cakephp/migrations "@stable"
+
+Pour utiliser le plugin, vous devrez le charger dans le fichier
+**config/bootstrap.php** de votre application.
+Vous pouvez utiliser :ref:`le shell de Plugin de CakePHP ` pour
+charger et décharger les plugins de votre **config/bootstrap.php**:
+
+.. code-block:: bash
+
+ bin/cake plugin load Migrations
+
+Ou vous pouvez charger le plugin en modifiant votre fichier
+**config/bootstrap.php**, en ajoutant ce qui suit::
+
+ Plugin::load('Migrations');
+
+De plus, vous devrez configurer la base de données par défaut pour votre
+application dans le fichier **config/app.php** comme expliqué dans la section
+sur la :ref:`configuration des bases de données `.
+
+Vue d'ensemble
+==============
+
+Une migration est simplement un fichier PHP qui décrit les changements à
+effectuer sur la base de données. Un fichier de migration peut créer ou
+supprimer des tables, ajouter ou supprimer des colonnes, créer des index et même
+insérer des données dans votre base de données.
+
+Ci-dessous un exemple de migration::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+Cette migration va ajouter une table à votre base de données nommée ``products``
+avec les définitions de colonne suivantes:
+
+- ``id`` colonne de type ``integer`` comme clé primaire
+- ``name`` colonne de type ``string``
+- ``description`` colonne de type ``text``
+- ``created`` colonne de type ``datetime``
+
+.. tip::
+
+ La colonne avec clé primaire nommée ``id`` sera ajoutée **implicitement**.
+
+.. note::
+
+ Notez que ce fichier décrit ce à quoi la base de données devrait ressembler
+ **après** l'application de la migration. À ce stade la table ``products``
+ n'existe pas dans votre base de données, nous avons simplement créé un
+ fichier qui est à la fois capable de créer la table ``products`` avec les
+ bonnes colonnes mais aussi de supprimer la table quand une opération de
+ ``rollback`` (retour en arrière) de la migration est effectuée.
+
+Une fois que le fichier a été créé dans le dossier **config/Migrations**, vous
+pourrez exécuter la commande ``migrations`` suivante pour créer la table dans
+votre base de données:
+
+.. code-block:: bash
+
+ bin/cake migrations migrate
+
+La commande ``migrations`` suivante va effectuer un ``rollback`` (retour en
+arrière) et supprimer la table de votre base de données:
+
+.. code-block:: bash
+
+ bin/cake migrations rollback
+
+Création de Migrations
+======================
+
+Les fichiers de migrations sont stockés dans le répertoire **config/Migrations**
+de votre application. Le nom des fichiers de migration est précédé de la
+date/heure du jour de création, dans le format
+**YYYYMMDDHHMMSS_MigrationName.php**.
+Voici quelques exemples de noms de fichiers de migration:
+
+* 20160121163850_CreateProducts.php
+* 20160210133047_AddRatingToProducts.php
+
+La meilleure façon de créer un fichier de migration est d'utiliser la ligne de
+commande :doc:`/bake/usage`.
+
+Assurez-vous de bien lire la `documentation officielle de Phinx `_ afin de connaître la liste
+complète des méthodes que vous pouvez utiliser dans l'écriture des fichiers de
+migration.
+
+.. note::
+
+ Quand vous utilisez l'option ``bake``, vous pouvez toujours modifier la
+ migration avant de l'exécuter si besoin.
+
+Syntaxe
+-------
+
+La syntaxe de la commande ``bake`` est de la forme suivante:
+
+.. code-block:: bash
+
+ bin/cake bake migration CreateProducts name:string description:text created modified
+
+Quand vous utilisez ``bake`` pour créer des tables, ajouter des colonnes ou
+effectuer diverses opérations sur votre base de données, vous devez en général
+fournir deux choses:
+
+* le nom de la migration que vous allez générer (``CreateProducts`` dans notre
+ exemple)
+* les colonnes de la table qui seront ajoutées ou retirées dans la migration
+ (``name:string description:text created modified`` dans notre exemple)
+
+Étant données les conventions, tous les changements de schéma ne peuvent pas
+être effectuées avec les commandes shell.
+
+De plus, vous pouvez créer un fichier de migration vide si vous voulez un
+contrôle total sur ce qui doit être executé, en ne spécifiant pas de définition
+de colonnes:
+
+.. code-block:: bash
+
+ bin/cake migrations create MyCustomMigration
+
+Nom de Fichier des Migrations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Les noms des migrations peuvent suivre l'une des structures suivantes:
+
+* (``/^(Create)(.*)/``) Crée la table spécifiée.
+* (``/^(Drop)(.*)/``) Supprime la table spécifiée. Ignore les arguments de champ spécifié.
+* (``/^(Add).*(?:To)(.*)/``) Ajoute les champs à la table spécifiée.
+* (``/^(Remove).*(?:From)(.*)/``) Supprime les champs de la table spécifiée.
+* (``/^(Alter)(.*)/``) Modifie la table spécifiée. Un alias pour CreateTable et AddField.
+* (``/^(Alter).*(?:On)(.*)/``) Modifie les champs de la table spécifiée.
+
+Vous pouvez aussi utiliser ``la_forme_avec_underscores`` comme nom pour vos
+migrations par exemple ``create_products``.
+
+.. versionadded:: cakephp/migrations 1.5.2
+
+ Depuis la version 1.5.2 du `plugin migrations `_,
+ le nom de fichier de migration sera automatiquement avec des majuscules.
+ Cette version du plugin est seulement disponible pour une version de
+ CakePHP >= to 3.1. Avant cette version du plugin, le nom des migrations
+ serait sous la forme avec des underscores, par exemple
+ ``20160121164955_create_products.php``.
+
+.. warning::
+
+ Les noms des migrations sont utilisés comme noms de classe de migration, et
+ peuvent donc être en conflit avec d'autres migrations si les noms de classe
+ ne sont pas uniques. Dans ce cas, il peut être nécessaire de remplacer
+ manuellement le nom plus tard, ou simplement changer le nom
+ que vous avez spécifié.
+
+Définition de Colonnes
+~~~~~~~~~~~~~~~~~~~~~~
+
+Quand vous définissez des colonnes avec la ligne de commande, il peut être
+pratique de se souvenir qu'elles suivent le modèle suivant::
+
+ fieldName:fieldType?[length]:indexType:indexName
+
+Par exemple, les façons suivantes sont toutes des façons valides pour spécifier
+un champ d'email:
+
+* ``email:string?``
+* ``email:string:unique``
+* ``email:string?[50]``
+* ``email:string:unique:EMAIL_INDEX``
+* ``email:string[120]:unique:EMAIL_INDEX``
+
+Le point d'interrogation qui suit le type du champ entrainera que la colonne
+peut être null.
+
+Le paramètre ``length`` pour ``fieldType`` est optionnel et doit toujours être
+écrit entre crochets.
+
+Les champs nommés ``created`` et ``modified``, tout comme les champs ayant pour
+suffixe ``_at``, vont automatiquement être définis avec le type ``datetime``.
+
+Les types de champ sont ceux qui sont disponibles avec la librairie ``Phinx``.
+Ce sont les suivants:
+
+* string
+* text
+* integer
+* biginteger
+* float
+* decimal
+* datetime
+* timestamp
+* time
+* date
+* binary
+* boolean
+* uuid
+
+Il existe quelques heuristiques pour choisir les types de champ quand ils ne
+sont pas spécifiés ou définis avec une valeur invalide. Par défaut, le type est
+``string``:
+
+* id: integer
+* created, modified, updated: datetime
+
+Créer une Table
+---------------
+
+Vous pouvez utiliser ``bake`` pour créer une table:
+
+.. code-block:: bash
+
+ bin/cake bake migration CreateProducts name:string description:text created modified
+
+La ligne de commande ci-dessus va générer un fichier de migration qui ressemble
+à::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+Ajouter des Colonnes à une Table Existante
+------------------------------------------
+
+Si le nom de la migration dans la ligne de commande est de la forme
+"AddXXXToYYY" et est suivie d'une liste de noms de colonnes et de types alors
+un fichier de migration contenant le code pour la création des colonnes sera
+généré:
+
+.. code-block:: bash
+
+ bin/cake bake migration AddPriceToProducts price:decimal
+
+L'exécution de la ligne de commande ci-dessus va générer::
+
+ table('products');
+ $table->addColumn('price', 'decimal')
+ ->update();
+ }
+ }
+
+Ajouter un Index de Colonne à une Table
+---------------------------------------
+
+Il est également possible d'ajouter des indexes de colonnes:
+
+.. code-block:: bash
+
+ bin/cake bake migration AddNameIndexToProducts name:string:index
+
+va générer::
+
+ table('products');
+ $table->addColumn('name', 'string')
+ ->addIndex(['name'])
+ ->update();
+ }
+ }
+
+Spécifier la Longueur d'un Champ
+--------------------------------
+
+.. versionadded:: cakephp/migrations 1.4
+
+Si vous voulez spécifier une longueur de champ, vous pouvez le faire entre
+crochets dans le type du champ, par exemple:
+
+.. code-block:: bash
+
+ bin/cake bake migration AddFullDescriptionToProducts full_description:string[60]
+
+L'exécution de la ligne de commande ci-dessus va générer::
+
+ table('products');
+ $table->addColumn('full_description', 'string', [
+ 'default' => null,
+ 'limit' => 60,
+ 'null' => false,
+ ])
+ ->update();
+ }
+ }
+
+Si aucune longueur n'est spécifiée, les longueurs pour certain types de
+colonnes sont par défaut:
+
+* string: 255
+* integer: 11
+* biginteger: 20
+
+Modifier une colonne d'une table
+-----------------------------------
+
+De la même manière, vous pouvez générer une migration pour modifier une colonne à l'aide de la commande
+ligne de commande, si le nom de la migration est de la forme "AlterXXXOnYYY":
+
+.. code-block:: bash
+
+ bin/cake bake migration AlterPriceOnProducts name:float
+
+créé le fichier::
+
+ table('products');
+ $table->changeColumn('name', 'float');
+ $table->update();
+ }
+ }
+
+Retirer une Colonne d'une Table
+-------------------------------
+
+De la même façon, vous pouvez générer une migration pour retirer une colonne
+en utilisant la ligne de commande, si le nom de la migration est de la forme
+"RemoveXXXFromYYY":
+
+.. code-block:: bash
+
+ bin/cake bake migration RemovePriceFromProducts price
+
+créé le fichier::
+
+ table('products');
+ $table->removeColumn('price')
+ ->save();
+ }
+ }
+
+.. note::
+
+ La commande `removeColumn` n'est pas réversible, donc elle doit être appelée
+ dans la méthode `up`. Un appel correspondant au `addColumn` doit être
+ ajouté à la méthode `down`.
+
+Générer une Migration à partir d'une Base de Données Existante
+==============================================================
+
+Si vous avez affaire à une base de données pré-existante et que vous voulez
+commencer à utiliser migrations, ou que vous souhaitez versionner le schéma
+initial de votre base de données, vous pouvez exécuter la commande
+``migration_snapshot``:
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial
+
+Elle va générer un fichier de migration appelé **Initial** contenant toutes les
+déclarations pour toutes les tables de votre base de données.
+
+Par défaut, le snapshot va être créé en se connectant à la base de données
+définie dans la configuration de la connection ``default``.
+Si vous devez créer un snapshot à partir d'une autre source de données, vous
+pouvez utiliser l'option ``--connection``:
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --connection my_other_connection
+
+Vous pouvez aussi vous assurer que le snapshot inclut seulement les tables pour
+lesquelles vous avez défini les classes de model correspondantes en utilisant
+le flag ``--require-table``:
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --require-table
+
+Quand vous utilisez le flag ``--require-table``, le shell va chercher les
+classes ``Table`` de votre application et va seulement ajouter les tables de
+model dans le snapshot.
+
+La même logique sera appliquée implicitement si vous souhaitez créer un
+snapshot pour un plugin. Pour ce faire, vous devez utiliser l'option
+``--plugin``:
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --plugin MyPlugin
+
+Seules les tables ayant une classe d'un objet model ``Table`` définie seront
+ajoutées au snapshot de votre plugin.
+
+.. note::
+
+ Quand vous créez un snapshot pour un plugin, les fichiers de migration sont
+ créés dans le répertoire **config/Migrations** de votre plugin.
+
+Notez que quand vous créez un snapshot, il est automatiquement marqué dans la
+table de log de phinx comme migré.
+
+Générer un diff entre deux états de base de données
+===================================================
+
+.. versionadded:: cakephp/migrations 1.6.0
+
+Vous pouvez générer un fichier de migrations qui regroupera toutes les
+différences entre deux états de base de données en utilisant le template bake
+``migration_diff``. Pour cela, vous pouvez utiliser la commande suivante:
+
+.. code-block:: bash
+
+ bin/cake bake migration_diff NameOfTheMigrations
+
+Pour avoir un point de comparaison avec l'état actuel de votre base de données,
+le shell migrations va générer, après chaque appel de ``migrate`` ou
+``rollback`` un fichier "dump". Ce fichier dump est un fichier qui contient
+l'ensemble de l'état de votre base de données à un point précis dans le temps.
+
+Quand un fichier dump a été généré, toutes les modifications que vous ferez
+directement dans votre SGBD seront ajoutées au fichier de migration qui sera
+généré quand vous appelerez la commande ``bake migration_diff``.
+
+Par défaut, le diff sera fait en se connectant à la base de données définie
+dans votre configuration de Connection ``default``.
+Si vous avez besoin de faire un diff depuis une source différente, vous pouvez
+utiliser l'option ``--connection``:
+
+.. code-block:: bash
+
+ bin/cake bake migration_diff NameOfTheMigrations --connection my_other_connection
+
+Si vous souhaitez utiliser la fonctionnalité de diff sur une application qui
+possède déjà un historique de migrations, vous allez avoir besoin de créer le
+fichier dump manuellement pour qu'il puisse être utilisé comme point de
+comparaison:
+
+.. code-block:: bash
+
+ bin/cake migrations dump
+
+L'état de votre base de données devra être le même que si vous aviez migré tous
+vos fichiers de migrations avant de créer le fichier dump.
+Une fois que le fichier dump est créé, vous pouvez opérer des changements dans
+votre base de données et utiliser la commande ``bake migration_diff`` quand
+vous voulez
+
+.. note::
+
+ Veuillez noter que le système n'est pas capable de détecter les colonnes
+ renommées.
+
+Les Commandes
+=============
+
+``migrate`` : Appliquer les Migrations
+--------------------------------------
+
+Une fois que vous avez généré ou écrit votre fichier de migration, vous devez
+exécuter la commande suivante pour appliquer les modifications à votre base de
+données:
+
+.. code-block:: bash
+
+ # Exécuter toutes les migrations
+ bin/cake migrations migrate
+
+ # Pour migrer vers une version spécifique, utilisez
+ # le paramètre ``--target`` ou -t (version courte)
+ # Cela correspond à l'horodatage qui est ajouté au début
+ # du nom de fichier des migrations.
+ bin/cake migrations migrate -t 20150103081132
+
+ # Par défaut, les fichiers de migration se trouvent dans
+ # le répertoire **config/Migrations**. Vous pouvez spécifier le répertoire
+ # en utilisant l'option ``--source`` ou ``-s`` (version courte).
+ # L'exemple suivant va exécuter les migrations
+ # du répertoire **config/Alternate**
+ bin/cake migrations migrate -s Alternate
+
+ # Vous pouvez exécuter les migrations avec une connection différente
+ # de celle par défaut ``default`` en utilisant l'option ``--connection``
+ # ou ``-c`` (version courte)
+ bin/cake migrations migrate -c my_custom_connection
+
+ # Les migrations peuvent aussi être exécutées pour les plugins. Utilisez
+ # simplement l'option ``--plugin`` ou ``-p`` (version courte)
+ bin/cake migrations migrate -p MyAwesomePlugin
+
+``rollback`` : Annuler les Migrations
+-------------------------------------
+
+La commande de restauration est utilisée pour annuler les précédentes migrations
+réalisées par ce plugin. C'est l'inverse de la commande ``migrate``.:
+
+.. code-block:: bash
+
+ # Vous pouvez annuler la migration précédente en utilisant
+ # la commande ``rollback``::
+ bin/cake migrations rollback
+
+ # Vous pouvez également passer un numéro de version de migration
+ # pour revenir à une version spécifique::
+ bin/cake migrations rollback -t 20150103081132
+
+Vous pouvez aussi utilisez les options ``--source``, ``--connection`` et
+``--plugin`` comme pour la commande ``migrate``.
+
+``status`` : Statuts de Migrations
+----------------------------------
+
+La commande ``status`` affiche une liste de toutes les migrations, ainsi que
+leur état actuel. Vous pouvez utiliser cette commande pour déterminer les
+migrations qui ont été exécutées:
+
+.. code-block:: bash
+
+ bin/cake migrations status
+
+Vous pouvez aussi afficher les résultats avec le format JSON en utilisant
+l'option ``--format`` (ou ``-f`` en raccourci):
+
+.. code-block:: bash
+
+ bin/cake migrations status --format json
+
+Vous pouvez aussi utiliser les options ``--source``, ``--connection`` et
+``--plugin`` comme pour la commande ``migrate``.
+
+``mark_migrated`` : Marquer une Migration en Migrée
+---------------------------------------------------
+
+.. versionadded:: 1.4.0
+
+Il peut parfois être utile de marquer une série de migrations comme "migrées"
+sans avoir à les exécuter.
+Pour ce faire, vous pouvez utiliser la commande ``mark_migrated``.
+Cette commande fonctionne de la même manière que les autres commandes.
+
+Vous pouvez marquer toutes les migrations comme migrées en utilisant cette
+commande:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated
+
+Vous pouvez également marquer toutes les migrations jusqu'à une version
+spécifique en utilisant l'option ``--target``:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000
+
+Si vous ne souhaitez pas que la migration "cible" soit marquée, vous pouvez
+utiliser le _flag_ ``--exclude``:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000 --exclude
+
+Enfin, si vous souhaitez marquer seulement une migration, vous pouvez utiliser
+le _flag_ ``--only``:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000 --only
+
+Vous pouvez aussi utilisez les options ``--source``, ``--connection`` et
+``--plugin`` comme pour la commande ``migrate``.
+
+.. note::
+
+ Lorsque vous créez un snapshot avec la commande
+ ``cake bake migration_snapshot``, la migration créée sera automatiquement
+ marquée comme "migrée".
+
+.. deprecated:: 1.4.0
+
+ Les instructions suivantes ont été dépréciées. Utilisez les seulement si
+ vous utilisez une version du plugin inférieure à 1.4.0.
+
+La commande attend le numéro de version de la migration comme argument:
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated 20150420082532
+
+Si vous souhaitez marquer toutes les migrations comme "migrées", vous pouvez
+utiliser la valeur spéciale ``all``. Si vous l'utilisez, toutes les migrations
+trouvées seront marquées comme "migrées":
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated all
+
+``seed`` : Remplir votre Base de Données (Seed)
+-----------------------------------------------
+
+Depuis la version 1.5.5, vous pouvez utiliser le shell ``migrations`` pour
+remplir votre base de données. Cela vient de la `fonctionnalité de seed
+de la librairie Phinx `_.
+Par défaut, les fichiers de seed vont être recherchés dans le répertoire
+``config/Seeds`` de votre application. Assurez-vous de suivre les
+`instructions de Phinx pour construire les fichiers de seed `_.
+
+En ce qui concerne migrations, une interface ``bake`` est fournie pour les
+fichiers de seed:
+
+.. code-block:: bash
+ # Ceci va créer un fichier ArticlesSeed.php dans le répertoire config/Seeds
+ # de votre application
+ # Par défaut, la table que le seed va essayer de modifier est la version
+ # "tableized" du nom de fichier du seed
+ bin/cake bake seed Articles
+
+ # Vous spécifiez le nom de la table que les fichiers de seed vont modifier
+ # en utilisant l'option ``--table``
+ bin/cake bake seed Articles --table my_articles_table
+
+ # Vous pouvez spécifier un plugin dans lequel faire la création
+ bin/cake bake seed Articles --plugin PluginName
+
+ # Vous pouvez spécifier une connection alternative quand vous générez un
+ # seeder.
+ bin/cake bake seed Articles --connection connection
+
+.. versionadded:: cakephp/migrations 1.6.4
+
+ Les options ``--data``, ``--limit`` and ``--fields`` ont été ajoutées pour
+ permettre d'exporter des données extraites depuis votre base de données.
+
+A partir de 1.6.4, la commande ``bake seed`` vous permet de créer des fichiers
+de seed avec des lignes exportées de votre base de données en utilisant
+l'option ``--data``:
+
+.. code-block:: bash
+
+ bin/cake bake seed --data Articles
+
+Par défaut, cela exportera toutes les lignes trouvées dans la table. Vous
+pouvez limiter le nombre de lignes exportées avec l'option ``--limit``:
+
+.. code-block:: bash
+
+ # N'exportera que les 10 premières lignes trouvées
+ bin/cake bake seed --data --limit 10 Articles
+
+Si vous ne souhaitez inclure qu'une sélection des champs de la table dans votre
+fichier de seed, vous pouvez utiliser l'option ``--fields``. Elle prend la
+liste des champs séparés par une virgule comme argument:
+
+.. code-block:: bash
+
+ # N'exportera que les champs `id`, `title` et `excerpt`
+ bin/cake bake seed --data --fields id,title,excerpt Articles
+
+.. tip::
+
+ Vous pouvez bien sûr utiliser les options ``--limit`` et ``--fields``
+ ensemble dans le même appel.
+
+Pour faire un seed de votre base de données, vous pouvez utiliser la
+sous-commande ``seed``:
+
+.. code-block:: bash
+
+ # Sans paramètres, la sous-commande seed va exécuter tous les seeders
+ # disponibles du répertoire cible, dans l'ordre alphabétique.
+ bin/cake migrations seed
+
+ # Vous pouvez spécifier seulement un seeder à exécuter en utilisant
+ # l'option `--seed`
+ bin/cake migrations seed --seed ArticlesSeed
+
+ # Vous pouvez exécuter les seeders d'un autre répertoire
+ bin/cake migrations seed --source AlternativeSeeds
+
+ # Vous pouvez exécuter les seeders d'un plugin
+ bin/cake migrations seed --plugin PluginName
+
+ # Vous pouvez exécuter les seeders d'une connection spécifique
+ bin/cake migrations seed --connection connection
+
+Notez que, à l'opposé des migrations, les seeders ne sont pas suivies, ce qui
+signifie que le même seeder peut être appliqué plusieurs fois.
+
+Appeler un Seeder depuis un autre Seeder
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: cakephp/migrations 1.6.2
+
+Généralement, quand vous remplissez votre base de données avec des *seeders*,
+l'ordre dans lequel vous faites les insertions est important pour éviter de
+rencontrer des erreurs dûes à des *constraints violations*.
+Puisque les *seeders* sont exécutés dans l'ordre alphabétique par défaut, vous
+pouvez utiliser la méthode ``\Migrations\AbstractSeed::call()`` pour définir
+votre propre séquence d'exécution de *seeders*::
+
+ use Migrations\AbstractSeed;
+
+ class DatabaseSeed extends AbstractSeed
+ {
+ public function run()
+ {
+ $this->call('AnotherSeed');
+ $this->call('YetAnotherSeed');
+
+ // Vous pouvez utiliser la syntaxe "plugin" pour appeler un seeder
+ // d'un autre plugin
+ $this->call('PluginName.FromPluginSeed');
+ }
+ }
+
+.. note::
+
+ Assurez vous d'*extend* la classe du plugin Migrations ``AbstractSeed`` si
+ vous voulez pouvoir utiliser la méthode ``call()``. Cette classe a été
+ ajoutée dans la version 1.6.2.
+
+``dump`` : Générer un fichier dump pour la fonctionnalité de diff
+-----------------------------------------------------------------
+
+La commande Dump crée un fichier qui sera utilisé avec le template bake
+``migration_diff``:
+
+.. code-block:: bash
+
+ bin/cake migrations dump
+
+Chaque fichier dump généré est spécifique à la _Connection_ par laquelle il a
+été générée (le nom du fichier est suffixé par ce nom). Cela permet à la
+commande ``bake migration_diff`` de calculer le diff correctement dans le cas
+où votre application gérerait plusieurs bases de données (qui pourraient être
+basées sur plusieurs SGDB.
+
+Les fichiers de dump sont créés dans le même dossier que vos fichiers de
+migrations.
+
+Vous pouvez aussi utiliser les options ``--source``, ``--connection`` et
+``--plugin`` comme pour la commande ``migrate``.
+
+Utiliser Migrations dans les Plugins
+====================================
+
+Les plugins peuvent également contenir des fichiers de migration. Cela rend les
+plugins destinés à la communauté beaucoup plus portable et plus facile à
+installer. Toutes les commandes du plugin Migrations supportent l'option
+``--plugin`` ou ``-p`` afin d'exécuter les commandes par rapport à ce plugin:
+
+.. code-block:: bash
+
+ bin/cake migrations status -p PluginName
+
+ bin/cake migrations migrate -p PluginName
+
+Effectuer des Migrations en dehors d'un environnement Console
+=============================================================
+
+.. versionadded:: cakephp/migrations 1.2.0
+
+Depuis la sortie de la version 1.2 du plugin migrations, vous pouvez effectuer
+des migrations en dehors d'un environnement Console, directement depuis une
+application, en utilisant la nouvelle classe ``Migrations``.
+Cela peut être pratique si vous développez un installeur de plugins pour un CMS
+par exemple.
+La classe ``Migrations`` vous permet de lancer les commandes de la console de
+migrations suivantes:
+
+* migrate
+* rollback
+* markMigrated
+* status
+* seed
+
+Chacune de ces commandes possède une méthode définie dans la classe
+``Migrations``.
+
+Voici comment l'utiliser::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // Va retourner un tableau des migrations et leur statut
+ $status = $migrations->status();
+
+ // Va retourner true en cas de succès. Si une erreur se produit, une exception est lancée
+ $migrate = $migrations->migrate();
+
+ // Va retourner true en cas de succès. Si une erreur se produit, une exception est lancée
+ $rollback = $migrations->rollback();
+
+ // Va retourner true en cas de succès. Si une erreur se produit, une exception est lancée
+ $markMigrated = $migrations->markMigrated(20150804222900);
+
+ // Va retourner true en cas de succès. Su une erreur se produit, une exception est lancée
+ $seeded = $migrations->seed();
+
+Ces méthodes acceptent un tableau de paramètres qui doivent correspondre aux
+options de chacune des commandes::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // Va retourner un tableau des migrations et leur statut
+ $status = $migrations->status(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+Vous pouvez passer n'importe quelle option que la commande de la console
+accepterait.
+La seule exception étant la commande ``markMigrated`` qui attend le numéro de
+version de la migration à marquer comme "migrée" comme premier argument.
+Passez le tableau de paramètres en second argument pour cette méthode.
+
+En option, vous pouvez passer ces paramètres au constructeur de la classe.
+Ils seront utilisés comme paramètres par défaut et vous éviteront ainsi d'avoir
+à les passer à chaque appel de méthode::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // Tous les appels suivant seront faits avec les paramètres passés au constructeur de la classe Migrations
+ $status = $migrations->status();
+ $migrate = $migrations->migrate();
+
+Si vous avez besoin d'écraser un ou plusieurs paramètres pour un appel, vous
+pouvez les passer à la méthode::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // Cet appel sera fait avec la connexion "custom"
+ $status = $migrations->status();
+ // Cet appel avec la connexion "default"
+ $migrate = $migrations->migrate(['connection' => 'default']);
+
+Trucs et Astuces
+================
+
+Créer des Clés Primaires Personnalisées
+---------------------------------------
+
+Pour personnaliser la création automatique de la clé primaire ``id`` lors
+de l'ajout de nouvelles tables, vous pouvez utiliser le deuxième argument de la
+méthode ``table()``::
+
+ table('products', ['id' => false, 'primary_key' => ['id']]);
+ $table
+ ->addColumn('id', 'uuid')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+Le code ci-dessus va créer une colonne ``CHAR(36)`` ``id`` également utilisée
+comme clé primaire.
+
+.. note::
+
+ Quand vous spécifiez une clé primaire personnalisée avec les lignes de
+ commande, vous devez la noter comme clé primaire dans le champ id,
+ sinon vous obtiendrez une erreur de champs id dupliqués, par exemple:
+
+ .. code-block:: bash
+
+ bin/cake bake migration CreateProducts id:uuid:primary name:string description:text created modified
+
+Depuis Migrations 1.3, une nouvelle manière de gérer les clés primaires a été
+introduite. Pour l'utiliser, votre classe de migration devra étendre la
+nouvelle classe ``Migrations\AbstractMigration``.
+Vous pouvez définir la propriété ``autoId`` à ``false`` dans la classe de
+Migration, ce qui désactivera la création automatique de la colonne ``id``.
+Vous aurez cependant besoin de manuellement créer la colonne qui servira de clé
+primaire et devrez l'ajouter à la déclaration de la table::
+
+ table('products');
+ $table
+ ->addColumn('id', 'integer', [
+ 'autoIncrement' => true,
+ 'limit' => 11
+ ])
+ ->addPrimaryKey('id')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+Comparée à la méthode précédente de gestion des clés primaires, cette méthode
+vous donne un plus grand contrôle sur la définition de la colonne de la clé
+primaire : signée ou non, limite, commentaire, etc.
+
+Toutes les migrations et les snapshots créés avec ``bake`` utiliseront cette
+nouvelle méthode si nécessaire.
+
+.. warning::
+
+ Gérer les clés primaires ne peut être fait que lors des opérations de
+ créations de tables. Ceci est dû à des limitations pour certains serveurs
+ de base de données supportés par le plugin.
+
+Collations
+----------
+
+Si vous avez besoin de créer une table avec une ``collation`` différente
+de celle par défaut de la base de données, vous pouvez la définir comme option
+de la méthode ``table()``::
+
+ table('categories', [
+ 'collation' => 'latin1_german1_ci'
+ ])
+ ->addColumn('title', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ])
+ ->create();
+ }
+ }
+
+Notez cependant que ceci ne peut être fait qu'en cas de création de table :
+il n'y a actuellement aucun moyen d'ajouter une colonne avec une ``collation``
+différente de celle de la table ou de la base de données.
+Seuls ``MySQL`` et ``SqlServer`` supportent cette option de configuration pour
+le moment.
+
+Mettre à jour les Noms de Colonne et Utiliser les Objets Table
+--------------------------------------------------------------
+
+Si vous utilisez un objet Table de l'ORM de CakePHP pour manipuler des valeurs
+de votre base de données, comme renommer ou retirer une colonne, assurez-vous
+de créer une nouvelle instance de votre objet Table après l'appel à
+``update()``. Le registre de l'objet Table est nettoyé après un appel à
+``update()`` afin de rafraîchir le schéma qui est reflèté et stocké dans l'objet
+Table lors de l'instanciation.
+
+Migrations et déploiement
+-------------------------
+Si vous utilisez le plugin dans vos processus de déploiement, assurez-vous de
+vider le cache de l'ORM pour qu'il renouvelle les _metadata_ des colonnes de vos
+tables.
+Autrement, vous pourrez rencontrer des erreurs de colonnes inexistantes quand
+vous effectuerez des opérations sur vos nouvelles colonnes.
+Le Core de CakePHP inclut un
+:doc:`Shell de Cache du Schéma ` que vous pouvez
+utilisez pour vider le cache:
+
+.. code-block:: bash
+
+ // Avant 3.6, utilisez orm_cache
+ bin/cake schema_cache clear
+
+Veuillez vous référer à la section du cookbook à propos du
+:doc:`Shell du Cache du Schéma ` si vous voulez
+plus de détails à propos de ce shell.
+
+Renommer une table
+------------------
+
+Le plugin vous donne la possibilité de renommer une table en utilisant la
+méthode ``rename()``.
+Dans votre fichier de migration, vous pouvez utiliser la syntaxe suivante::
+
+ public function up()
+ {
+ $this->table('old_table_name')
+ ->rename('new_table_name');
+ }
+
+Ne pas générer le fichier ``schema.lock``
+-----------------------------------------
+
+.. versionadded:: cakephp/migrations 1.6.5
+
+Pour que la fonctionnalité de "diff" fonctionne, un fichier **.lock** est
+généré à chaque que vous faites un migrate, un rollback ou que vous générez un
+snapshot via bake pour permettre de suivre l'état de votre base de données à
+n'importe quel moment. Vous pouvez empêcher que ce fichier ne soit généré,
+comme par exemple lors d'un déploiement sur votre environnement de production,
+en utilisant l'option ``--no-lock`` sur les commandes mentionnées ci-dessus:
+
+.. code-block:: bash
+
+ bin/cake migrations migrate --no-lock
+
+ bin/cake migrations rollback --no-lock
+
+ bin/cake bake migration_snapshot MyMigration --no-lock
diff --git a/app/vendor/cakephp/migrations/docs/ja/conf.py b/app/vendor/cakephp/migrations/docs/ja/conf.py
new file mode 100644
index 000000000..5871da648
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/ja/conf.py
@@ -0,0 +1,9 @@
+import sys, os
+
+# Append the top level directory of the docs, so we can import from the config dir.
+sys.path.insert(0, os.path.abspath('..'))
+
+# Pull in all the configuration options defined in the global config file..
+from config.all import *
+
+language = 'ja'
diff --git a/app/vendor/cakephp/migrations/docs/ja/contents.rst b/app/vendor/cakephp/migrations/docs/ja/contents.rst
new file mode 100644
index 000000000..1459b1f1b
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/ja/contents.rst
@@ -0,0 +1,5 @@
+.. toctree::
+ :maxdepth: 2
+ :caption: CakePHP Migrations
+
+ /index
diff --git a/app/vendor/cakephp/migrations/docs/ja/index.rst b/app/vendor/cakephp/migrations/docs/ja/index.rst
new file mode 100644
index 000000000..a819f6a49
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/ja/index.rst
@@ -0,0 +1,1050 @@
+Migrations
+##########
+
+マイグレーションは、バージョン管理システムを使用して追跡することができる PHP ファイルを
+記述することによって、あなたのデータベースのスキーマ変更を行うための、コアチームによって
+サポートされているプラグインです。
+
+それはあなたが時間をかけてあなたのデータベーステーブルを進化させることができます。
+スキーマ変更の SQL を書く代わりに、このプラグインでは、直観的にデータベースの変更を
+実現するための手段を使用することができます。
+
+このプラグインは、データベースマイグレーションライブラリーの
+`Phinx `_ のラッパーです。
+
+インストール
+============
+
+初期状態で Migrations は、デフォルトのアプリケーションの雛形と一緒にインストールされます。
+もしあなたがそれを削除して再インストールしたい場合は、(composer.json ファイルが
+配置されている)アプリケーションルートディレクトリーから次のコマンドを実行します。
+
+.. code-block:: bash
+
+ php composer.phar require cakephp/migrations "@stable"
+
+ # また、composer がグローバルにインストールされていた場合は、
+
+ composer require cakephp/migrations "@stable"
+
+このプラグインを使用するためには、あなたは、アプリケーションの **config/bootstrap.php**
+ファイルでロードする必要があります。あなたの **config/bootstrap.php** からプラグインを
+ロード・アンロードするために :ref:`CakePHP の Plugin シェル `
+が利用できます。 :
+
+.. code-block:: bash
+
+ bin/cake plugin load Migrations
+
+もしくは、あなたの **src/Application.php** ファイルを編集し、次の行を追加することで
+ロードすることができます。 ::
+
+ $this->addPlugin('Migrations');
+
+ // 3.6.0 より前は Plugin::load() を使用する必要があります
+
+また、 :ref:`データベース設定 ` の項で説明したように、
+あなたの **config/app.php** ファイル内のデフォルトのデータベース構成を設定する必要が
+あります。
+
+概要
+====
+
+マイグレーションは、基本的にはデータベースの変更の操作を PHP ファイルで表します。
+マイグレーションファイルはテーブルを作成し、カラムの追加や削除、インデックスの作成や
+データの作成さえ可能です。
+
+ここにマイグレーションの例があります。 ::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+マイグレーションは、データベースに ``products`` という名前のテーブルを追加します。
+以下のカラムが定義します。
+
+- ``id`` カラムの型は、主キーの ``integer``
+- ``name`` カラムの型は ``string``
+- ``description`` カラムの型は ``text``
+- ``created`` カラムの型は ``datetime``
+- ``modified`` カラムの型は ``datetime``
+
+.. tip::
+
+ 主キーのカラム名 ``id`` は、 **暗黙のうちに** 追加されます。
+
+.. note::
+
+ このファイルは変更を **適用後** にデータベースがどのようになるかを記述していることに
+ 注意してください。この時点でデータベースに ``products`` テーブルは存在せず、
+ ``products`` テーブルを作って項目を追加することができるのと同様に、マイグレーションを
+ ``rollback`` すればテーブルが消えてしまいます。
+
+マイグレーションファイルを **config/Migrations** フォルダーに作成したら、下記の
+``migrations`` コマンドを実行することでデータベースにテーブルを作成することがでます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations migrate
+
+以下の ``migrations`` コマンドは、 ``rollback`` を実行するとあなたのデータベースから
+テーブルが削除されます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations rollback
+
+マイグレーションファイルの作成
+==============================
+
+マイグレーションファイルは、あなたのアプリケーションの **config/Migration**
+ディレクトリーに配置します。マイグレーションファイルの名前には、先頭に
+**YYYYMMDDHHMMSS_MigrationName.php** というように作成した日付を付けます。
+以下がマイグレーションファイルの例です。
+
+* 20160121163850_CreateProducts.php
+* 20160210133047_AddRatingToProducts.php
+
+マイグレーションファイルを作成する最も簡単な方法は ``bake`` CLI
+コマンドを使用することです。
+
+マイグレーションファイルに記述可能なメソッドの一覧については、オフィシャルの
+`Phinx ドキュメント `_
+をご覧ください。
+
+.. note::
+
+ ``bake`` オプションを使用する場合、もし望むなら実行する前にマイグレーションを修正できます。
+
+シンタックス
+------------
+
+以下の ``bake`` コマンドは、 ``products`` テーブルを追加するためのマイグレーションファイルを
+作成します。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration CreateProducts name:string description:text created modified
+
+あなたのデータベースにテーブルの作成、カラムの追加などをするために ``bake`` を使用する場合、
+一般に以下の2点を指定します。
+
+* あなたが生成するマイグレーションの名前 (例えば、 ``CreateProducts``)
+* マイグレーションで追加や削除を行うテーブルのカラム
+ (例えば、 ``name:string description:text created modified``)
+
+規約のために、すべてのスキーマの変更がこれらのシェルコマンドで動作するわけではありません。
+
+さらに、実行内容を完全に制御したいのであれば、空のマイグレーションファイルを
+作る事ができます。 ::
+
+.. code-block:: bash
+
+ bin/cake migrations create MyCustomMigration
+
+マイグレーションファイル名
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+マイグレーション名は下記のパターンに従うことができます。
+
+* (``/^(Create)(.*)/``) 指定したテーブルを作成します。
+* (``/^(Drop)(.*)/``) 指定したテーブルを削除します。フィールドの指定は無視されます。
+* (``/^(Add).*(?:To)(.*)/``) 指定したテーブルにカラム追加します。
+* (``/^(Remove).*(?:From)(.*)/``) 指定のテーブルのカラムを削除します。
+* (``/^(Alter)(.*)/``) 指定したテーブルを変更します。 CreateTable と AddField の別名。
+* (``/^(Alter).*(?:On)(.*)/``) 指定されたテーブルのフィールドを変更します。
+
+マイグレーションの名前に ``アンダースコアー_形式`` を使用できます。例: create_products
+
+.. versionadded:: cakephp/migrations 1.5.2
+
+ マイグレーションファイル名のキャメルケースへの変換は `migrations プラグイン
+ `_ の v1.5.2 に含まれます。
+ このプラグインのバージョンは、 CakePHP 3.1 以上のリリースで利用できます。
+ このプラグインのバージョン以前では、マイグレーション名はアンダースコアー形式です。
+ 例: 20160121164955_create_products.php
+
+.. warning::
+
+ マイグレーション名は、マイグレーションのクラス名として使われます。そして、
+ クラス名はユニークでない場合、他のマイグレーションと衝突するかもしれません。この場合、後日、
+ 名前を手動で上書きするか、単純にあなたが指定した名前に変更する必要があるかもしれません。
+
+カラムの定義
+~~~~~~~~~~~~
+
+コマンドラインでカラムを使用する場合には、次のようなパターンに従っている事を
+覚えておくと便利です。 ::
+
+ fieldName:fieldType?[length]:indexType:indexName
+
+例えば、以下はメールアドレスのカラムを指定する方法です。
+
+* ``email:string?``
+* ``email:string:unique``
+* ``email:string?[50]``
+* ``email:string:unique:EMAIL_INDEX``
+* ``email:string[120]:unique:EMAIL_INDEX``
+
+fieldType の後のクエスチョンマークは、ヌルを許可するカラムを作成します。
+
+``fieldType`` のための ``length`` パラメーターは任意です。カッコの中に記述します。
+
+フィールド名が ``created`` と ``modified`` 、それに ``_at`` サフィックス付きの
+任意のフィールドなら、自動的に ``datetime`` 型が設定されます。
+
+``Phinx`` で一般的に利用可能なフィールドの型は次の通り:
+
+* string
+* text
+* integer
+* biginteger
+* float
+* decimal
+* datetime
+* timestamp
+* time
+* date
+* binary
+* boolean
+* uuid
+
+未確定で無効な値のままのフィールド型を選ぶためのいくつかの発見的手法があります。
+デフォルトのフィールド型は ``string`` です。
+
+* id: integer
+* created, modified, updated: datetime
+
+テーブルの作成
+--------------
+
+テーブルを作成するために ``bake`` が使えます。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration CreateProducts name:string description:text created modified
+
+上記のコマンドラインは、よく似たマイグレーションファイルを生成します。 ::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+既存のテーブルにカラムを追加
+----------------------------
+
+もしコマンドラインのマイグレーション名が "AddXXXToYYY" といった
+書式で、その後にカラム名と型が続けば、カラムの追加を行うコードを含んだ
+マイグレーションファイルが生成されます。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration AddPriceToProducts price:decimal
+
+コマンドラインを実行すると下記のようなファイルが生成されます。 ::
+
+ table('products');
+ $table->addColumn('price', 'decimal')
+ ->update();
+ }
+ }
+
+テーブルにインデックスとしてカラムを追加
+----------------------------------------
+
+カラムにインデックスを追加することも可能です。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration AddNameIndexToProducts name:string:index
+
+このようなファイルが生成されます。 ::
+
+ table('products');
+ $table->addColumn('name', 'string')
+ ->addIndex(['name'])
+ ->update();
+ }
+ }
+
+フィールド長を指定
+------------------
+
+.. versionadded:: cakephp/migrations 1.4
+
+もし、フィールド長を指定する必要がある場合、フィールドタイプにカギ括弧の中で指定できます。例:
+
+.. code-block:: bash
+
+ bin/cake bake migration AddFullDescriptionToProducts full_description:string[60]
+
+上記のコマンドラインを実行すると生成されます。 ::
+
+ table('products');
+ $table->addColumn('full_description', 'string', [
+ 'default' => null,
+ 'limit' => 60,
+ 'null' => false,
+ ])
+ ->update();
+ }
+ }
+
+長さが未指定の場合、いくつかのカラム型の長さは初期値が設定されます。
+
+* string: 255
+* integer: 11
+* biginteger: 20
+
+テーブルから列を変更する
+-----------------------------------
+
+同様に、移行名が「AlterXXXOnYYY」の形式の場合、コマンドラインを使用して、列を変更する移行を生成できます。
+
+.. code-block:: bash
+
+ bin/cake bake migration AlterPriceOnProducts name:float
+
+生成されます::
+
+ table('products');
+ $table->changeColumn('name', 'float');
+ $table->update();
+ }
+ }
+
+テーブルからカラムを削除
+------------------------
+
+もしマイグレーション名が "RemoveXXXFromYYY" であるなら、同様にコマンドラインを使用して、
+カラム削除のマイグレーションファイルを生成することができます。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration RemovePriceFromProducts price
+
+このようなファイルが生成されます。 ::
+
+ table('products');
+ $table->removeColumn('price')
+ ->save();
+ }
+ }
+
+.. note::
+
+ `removeColumn` は不可逆ですので、 `up` メソッドの中で呼び出してください。
+ それに対する `addColumn` の呼び出しは、 `down` メソッドに追加してください。
+
+既存のデータベースからマイグレーションファイルを作成する
+--------------------------------------------------------
+
+もしあなたが既存のデータベースで、マイグレーションの使用を始めたい場合や、
+あなたのアプリケーションのデータベースで初期状態のスキーマのバージョン管理を
+行いたい場合、 ``migration_snapshot`` コマンドを実行します。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial
+
+これはデータベース内のすべてのテーブルの create 文を含んだ **YYYYMMDDHHMMSS_Initial.php**
+と呼ばれるマイグレーションファイルを生成します。
+
+デフォルトで、スナップショットは、 ``default`` 接続設定で定義されたデータベースに
+接続することによって作成されます。
+もし、異なるデータベースからスナップショットを bake する必要があるなら、
+``--connection`` オプションが使用できます。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --connection my_other_connection
+
+``--require-table`` フラグを使用することによって対応するモデルクラスを定義したテーブルだけを
+含まれることを確認することができます。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --require-table
+
+``--require-table`` フラグを使用した時、シェルは、あなたのアプリケーションを通して
+``Table`` クラスを見つけて、スナップショットのモデルテーブルのみ追加します。
+
+プラグインのためのスナップショットを bake したい場合、同じロジックが暗黙的に適用されます。
+そうするために、 ``--plugin`` オプションを使用する必要があります。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration_snapshot Initial --plugin MyPlugin
+
+定義された ``Table`` オブジェクトモデルを持つテーブルだけプラグインのスナップショットに
+追加されます。
+
+.. note::
+
+ プラグインのためのスナップショットを bake した時、マイグレーションファイルは、
+ あなたのプラグインの **config/Migrations** ディレクトリーに作成されます。
+
+スナップショットを bake した時、phinx のログテーブルに自動的に追加されることに注意してください。
+
+2つのデータベース間の状態の差分を生成する
+=============================================
+
+.. versionadded:: cakephp/migrations 1.6.0
+
+``migration_diff`` の bake テンプレートを使用して2つのデータベースの状態の
+すべての差分をまとめたマイグレーションファイルを生成することができます。
+そのためには、以下のコマンドを使用します。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration_diff NameOfTheMigrations
+
+現在のデータベースの状態からの比較のポイントを保持するために、migrations シェルは、
+``migrate`` もしくは ``rollback`` が呼ばれた後に "dump" ファイルを生成します。
+ダンプファイルは、取得した時点でのあなたのデータベースの全スキーマの状態を含むファイルです。
+
+一度ダンプファイルが生成されると、あなたのデータベース管理システムに直接行ったすべての変更は、
+``bake migration_diff`` コマンドが呼ばれた時に生成されたマイグレーションファイルに追加されます。
+
+デフォルトでは、 ``default`` 接続設定に定義されたデータベースに接続することによって
+差分が作成されます。もし、あなたが異なるデータソースから差分を bake する必要がある場合、
+``--connection`` オプションを使用できます。 :
+
+.. code-block:: bash
+
+ bin/cake bake migration_diff NameOfTheMigrations --connection my_other_connection
+
+もし、すでにマイグレーションの履歴を持つアプリケーション上で diff 機能を使用したい場合、
+マニュアルで比較に使用するダンプファイルを作成する必要があります。 :
+
+.. code-block:: bash
+
+ bin/cake migrations dump
+
+データベースの状態は、あなたがダンプファイルを作成する前にマイグレーションを全て実行した状態と
+同じでなければなりません。一度ダンプファイルが生成されると、あなたのデータベースの変更を始めて、
+都合の良い時に ``bake migration_diff`` コマンドを使用することができます。
+
+.. note::
+
+ migrations シェルは、カラム名の変更は検知できません。
+
+コマンド
+========
+
+``migrate`` : マイグレーションを適用する
+----------------------------------------
+
+マイグレーションファイルを生成したり記述したら、以下のコマンドを実行して
+変更をデータベースに適用しましょう。 :
+
+.. code-block:: bash
+
+ # マイグレーションをすべて実行
+ bin/cake migrations migrate
+
+ # 特定のバージョンに移行するためには、 ``--target`` オプション
+ # (省略形は ``-t`` )を使用します。
+ # これはマイグレーションファイル名の前に付加されるタイムスタンプに対応しています。
+ bin/cake migrations migrate -t 20150103081132
+
+ # デフォルトで、マイグレーションファイルは、 **config/Migrations** ディレクトリーに
+ # あります。 ``--source`` オプション (省略形は ``-s``) を使用することで、
+ # ディレクトリーを指定できます。
+ # 次の例は、 **config/Alternate** ディレクトリー内でマイグレーションを実行します。
+ bin/cake migrations migrate -s Alternate
+
+ # ``--connection`` オプション (省略形は ``-c``) を使用することで
+ # ``default`` とは異なる接続でマイグレーションを実行できます。
+ bin/cake migrations migrate -c my_custom_connection
+
+ # マイグレーションは、プラグインのためにも実行できます。 ``--plugin`` オプション
+ # (省略形は ``-p``) を使用します。
+ bin/cake migrations migrate -p MyAwesomePlugin
+
+``rollback`` : マイグレーションを戻す
+-------------------------------------
+
+ロールバックコマンドは、このプラグインを実行する前の状態に戻すために使われます。
+これは ``migrate`` コマンドの逆向きの動作をします。 :
+
+.. code-block:: bash
+
+ # あなたは ``rollback`` コマンドを使って以前のマイグレーション状態に戻すことができます。
+ bin/cake migrations rollback
+
+ # また、特定のバージョンに戻すために、マイグレーションバージョン番号を引き渡すこともできます。
+ bin/cake migrations rollback -t 20150103081132
+
+``migrate`` コマンドのように ``--source`` 、 ``--connection`` そして ``--plugin``
+オプションが使用できます。
+
+``status`` : マイグレーションのステータス
+-----------------------------------------
+
+Status コマンドは、現在の状況とすべてのマイグレーションのリストを出力します。
+あなたはマイグレーションが実行されたかを判断するために、このコマンドを使用することができます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations status
+
+``--format`` (省略形は ``-f``) オプションを使用することで
+JSON 形式の文字列として結果を出力できます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations status --format json
+
+``migrate`` コマンドのように ``--source`` 、 ``--connection`` そして ``--plugin``
+オプションが使用できます。
+
+``mark_migrated`` : マイグレーション済みとしてマーキングする
+------------------------------------------------------------
+
+.. versionadded:: 1.4.0
+
+時には、実際にはマイグレーションを実行せずにマークだけすることが便利な事もあります。
+これを実行するためには、 ``mark_migrated`` コマンドを使用します。
+コマンドは、他のコマンドとしてシームレスに動作します。
+
+このコマンドを使用して、すべてのマイグレーションをマイグレーション済みとして
+マークすることができます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated
+
+また、 ``--target`` オプションを使用して、指定したバージョンに対して、
+すべてマイグレーション済みとしてマークすることができます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000
+
+もし、指定したマイグレーションを処理中にマーク済みにしたくない場合、
+``--exclude`` フラグをつけて使用することができます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000 --exclude
+
+最後に、指定したマイグレーションだけをマイグレーション済みとしてマークしたい場合、
+``--only`` フラグを使用できます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated --target=20151016204000 --only
+
+``migrate`` コマンドのように ``--source`` 、 ``--connection`` そして ``--plugin``
+オプションが使用できます。
+
+.. note::
+
+ あなたが ``cake bake migration_snapshot`` コマンドでスナップショットを作成したとき、
+ 自動的にマイグレーション済みとしてマーキングされてマイグレーションが作成されます。
+
+.. deprecated:: 1.4.0
+
+ 以下のコマンドの使用方法は非推奨になりました。もし、あなたが 1.4.0 より前のバージョンの
+ プラグインの場合のみに使用してください。
+
+このコマンドは、引数としてマイグレーションバージョン番号を想定しています。 :
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated 20150420082532
+
+もし、すべてのマイグレーションをマイグレーション済みとしてマークしたい場合、
+特別な値 ``all`` を使用できます。もし使用した場合、すべての見つかったマイグレーションを
+マイグレーション済みとしてマークします。 :
+
+.. code-block:: bash
+
+ bin/cake migrations mark_migrated all
+
+``seed`` : データベースの初期データ投入
+----------------------------------------
+
+1.5.5 より、データベースの初期データ投入のために ``migrations`` シェルが使用できます。
+これは、 `Phinx ライブラリーの seed 機能 `_
+を利用しています。デフォルトで、seed ファイルは、あなたのアプリケーションの ``config/Seeds``
+ディレクトリーの中に置かれます。 `seed ファイル作成のための Phinx の命令
+`_
+を確認してください。
+
+マイグレーションに関して、 seed ファイルのための ``bake`` インターフェースが提供されます。 :
+
+.. code-block:: bash
+
+ # これは、あなたのアプリケーションの config/Seeds ディレクトリー内に ArticlesSeed.php を作成します。
+ # デフォルトでは、変換対象の seed は、 "tableized" バージョンの seed ファイル名です。
+ bin/cake bake seed Articles
+
+ # ``--table`` オプションを使用することで seed ファイルに変換するテーブル名を指定します。
+ bin/cake bake seed Articles --table my_articles_table
+
+ # bake するプラグインを指定できます。
+ bin/cake bake seed Articles --plugin PluginName
+
+ # シーダーの生成時に別の接続を指定できます。
+ bin/cake bake seed Articles --connection connection
+
+.. versionadded:: cakephp/migrations 1.6.4
+
+ オプションの ``--data``, ``--limit`` そして ``--fields`` は、
+ データベースからデータをエクスポートするために追加されました。
+
+1.6.4 から、 ``bake seed`` コマンドは、 ``--data`` フラグを使用することによって、
+データベースからエクスポートされたデータを元に seed ファイルを作成することができます。 :
+
+.. code-block:: bash
+
+ bin/cake bake seed --data Articles
+
+デフォルトでは、テーブル内にある行を全てエクスポートします。 ``--limit`` オプションを
+使用することによって、エクスポートされる行の数を制限できます。 :
+
+.. code-block:: bash
+
+ # 10 行のみエクスポート
+ bin/cake bake seed --data --limit 10 Articles
+
+もし、seed ファイルの中にテーブルから選択したフィールドのみを含めたい場合、
+``--fields`` オプションが使用できます。そのオプションは、
+フィールドのリストをカンマ区切りの値の文字列として含めます。 :
+
+.. code-block:: bash
+
+ # `id`, `title` そして `excerpt` フィールドのみをエクスポート
+ bin/cake bake seed --data --fields id,title,excerpt Articles
+
+.. tip::
+
+ もちろん、同じコマンド呼び出し中に ``--limit`` と ``--fields``
+ オプションの両方が利用できます。
+
+データベースの初期データ投入のために、 ``seed`` サブコマンドが使用できます。 :
+
+.. code-block:: bash
+
+ # パラメーターなしの seed サブコマンドは、対象のディレクトリーのアルファベット順で、
+ # すべての利用可能なシーダーを実行します。
+ bin/cake migrations seed
+
+ # `--seed` オプションを使用して実行するための一つだけシーダーを指定できます。
+ bin/cake migrations seed --seed ArticlesSeed
+
+ # 別のディレクトリーでシーダーを実行できます。
+ bin/cake migrations seed --source AlternativeSeeds
+
+ # プラグインのシーダーを実行できます
+ bin/cake migrations seed --plugin PluginName
+
+ # 指定したコネクションでシーダーを実行できます
+ bin/cake migrations seed --connection connection
+
+マイグレーションとは対照的にシーダーは追跡されないことに注意してください。
+それは、同じシーダーは、複数回適用することができることを意味します。
+
+シーダーから別のシーダーの呼び出し
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: cakephp/migrations 1.6.2
+
+たいてい初期データ投入時は、データの挿入する順番は、規約違反しないように遵守しなければなりません。
+デフォルトでは、アルファベット順でシーダーが実行されますが、独自にシーダーの実行順を定義するために
+``\Migrations\AbstractSeed::call()`` メソッドが利用できます。 ::
+
+ use Migrations\AbstractSeed;
+
+ class DatabaseSeed extends AbstractSeed
+ {
+ public function run()
+ {
+ $this->call('AnotherSeed');
+ $this->call('YetAnotherSeed');
+
+ // プラグインからシーダーを呼ぶためにプラグインドット記法が使えます
+ $this->call('PluginName.FromPluginSeed');
+ }
+ }
+
+.. note::
+
+ もし、 ``call()`` メソッドを使いたい場合、Migrations プラグインの ``AbstractSeed``
+ クラスを継承していることを確認してください。このクラスは、リリース 1.6.2 で追加されました。
+
+``dump`` : 差分を bake する機能のためのダンプファイルの生成
+-------------------------------------------------------------
+
+dump コマンドは、 ``migration_diff`` の bake テンプレートで使用するファイルを作成します。 :
+
+.. code-block:: bash
+
+ bin/cake migrations dump
+
+各生成されたダンプファイルは、生成元の接続固有のものです(そして、そのようにサフィックスされます)。
+これは、アプリケーションが、異なるデータベースベンダーの複数のデータベースを扱う場合、
+``bake migration_diff`` コマンドで正しく差分を算出することができます。
+
+ダンプファイルは、マイグレーションファイルと同じディレクトリーに作成されます。
+
+``migrate`` コマンドのように ``--source`` 、 ``--connection`` そして ``--plugin``
+オプションが使用できます。
+
+プラグイン内のマイグレーションファイルを使う
+============================================
+
+プラグインはマイグレーションファイルも提供することができます。
+これはプラグインの移植性とインストールの容易さを高め、配布しやすくなるように意図されています。
+Migrations プラグインの全てのコマンドは、プラグイン関連のマイグレーションを行うための
+``--plugin`` か ``-p`` オプションをサポートしています。 :
+
+.. code-block:: bash
+
+ bin/cake migrations status -p PluginName
+
+ bin/cake migrations migrate -p PluginName
+
+非シェルの環境でマイグレーションを実行する
+==========================================
+
+.. versionadded:: cakephp/migrations 1.2.0
+
+migrations プラグインのバージョン 1.2 から、非シェル環境でも app から直接
+``Migrations`` クラスを使ってマイグレーションを実行できるようになりました。
+これは CMS のプラグインインストーラーを作る時などに便利です。
+``Migrations`` クラスを使用すると、マイグレーションシェルから下記のコマンドを
+実行することができます。:
+
+* migrate
+* rollback
+* markMigrated
+* status
+* seed
+
+それぞれのコマンドは ``Migrations`` クラスのメソッドとして実装されています。
+
+使い方は以下の通りです。 ::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // 全てのマイグレーションバージョンとそのステータスの配列を返します。
+ $status = $migrations->status();
+
+ // 成功した場合、 true を返し、エラーが発生した場合、例外が投げられます。
+ $migrate = $migrations->migrate();
+
+ // 成功した場合、 true を返し、エラーが発生した場合、例外が投げられます。
+ $rollback = $migrations->rollback();
+
+ // 成功した場合、 true を返し、エラーが発生した場合、例外が投げられます。
+ $markMigrated = $migrations->markMigrated(20150804222900);
+
+ // 成功した場合、 true を返し、エラーが発生した場合、例外が投げられます。
+ $seeded = $migrations->seed();
+
+メソッドはコマンドラインのオプションと同じパラメーター配列を受け取ります。 ::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // 全てのマイグレーションバージョンとそのステータスの配列を返す
+ $status = $migrations->status(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+あなたはシェルコマンドのように任意のオプションを引き渡すことができます。
+唯一の例外は ``markMigrated`` コマンドで、第1引数にはマイグレーション済みとして
+マーキングしたいマイグレーションバージョン番号を渡し、第2引数にパラメーターの配列を
+渡します。
+
+必要に応じて、クラスのコンストラクターでこれらのパラメーターを引き渡すことができます。
+それはデフォルトとして使用され、それぞれのメソッド呼び出しの時に引き渡されることを
+防止します。 ::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // 以下のすべての呼び出しは、マイグレーションクラスのコンストラクターに渡されたパラメーターを使用して行われます
+ $status = $migrations->status();
+ $migrate = $migrations->migrate();
+
+個別の呼び出しでデフォルトのパラメーターを上書きしたい場合は、メソッド呼び出し時に引き渡します。 ::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // この呼び出しでは "custom" コネクションを使用します。
+ $status = $migrations->status();
+ // こちらでは "default" コネクションを使用します。
+ $migrate = $migrations->migrate(['connection' => 'default']);
+
+小技と裏技
+===============
+
+主キーをカスタマイズする
+------------------------
+
+あなたがデータベースに新しいテーブルを作成する時、 ``id`` を主キーとして
+自動生成したくない場合、 ``table()`` メソッドの第2引数を使うことができます。 ::
+
+ table('products', ['id' => false, 'primary_key' => ['id']]);
+ $table
+ ->addColumn('id', 'uuid')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+上記の例では、 ``CHAR(36)`` の ``id`` というカラムを主キーとして作成します。
+
+.. note::
+
+ 独自の主キーをコマンドラインで指定した時、id フィールドの中の主キーとして注意してください。
+ そうしなければ、id フィールドが重複してエラーになります。例:
+
+ .. code-block:: bash
+
+ bin/cake bake migration CreateProducts id:uuid:primary name:string description:text created modified
+
+さらに、Migrations 1.3 以降では 主キーに対処するための新しい方法が導入されました。
+これを行うには、あなたのマイグレーションクラスは新しい ``Migrations\AbstractMigration``
+クラスを継承する必要があります。
+あなたは Migration クラスの ``autoId`` プロパティーに ``false`` を設定することで、
+自動的な ``id`` カラムの生成をオフにすることができます。
+あなたは手動で主キーカラムを作成し、テーブル宣言に追加する必要があります。 ::
+
+ table('products');
+ $table
+ ->addColumn('id', 'integer', [
+ 'autoIncrement' => true,
+ 'limit' => 11
+ ])
+ ->addPrimaryKey('id')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+主キーを扱うこれまでの方法と比較すると、この方法は、unsigned や not や limit や comment など
+さらに多くの主キーの定義を操作することができるようになっています。
+
+Bake で生成されたマイグレーションファイルとスナップショットは、この新しい方法を
+必要に応じて使用します。
+
+.. warning::
+
+ 主キーの操作ができるのは、テーブル作成時のみです。これはプラグインがサポートしている
+ いくつかのデータベースサーバーの制限によるものです。
+
+照合順序
+--------
+
+もしデータベースのデフォルトとは別の照合順序を持つテーブルを作成する必要がある場合は、
+``table()`` メソッドのオプションとして定義することができます。::
+
+ table('categories', [
+ 'collation' => 'latin1_german1_ci'
+ ])
+ ->addColumn('title', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ])
+ ->create();
+ }
+ }
+
+ですが、これはテーブル作成時にしかできず、既存のテーブルに対してカラムを追加する時に
+テーブルやデータベースと異なる照合順序を指定する方法がないことに注意してください。
+ただ ``MySQL`` と ``SqlServer`` だけはこの設定キーをサポートしています。
+
+カラム名の更新と Table オブジェクトの使用
+-----------------------------------------
+
+カラムのリネームや移動とともに、あなたのデータベースから値を操作するために
+CakePHP ORM Table オブジェクトを使用している場合、 ``update()`` を呼んだ後に Table
+オブジェクトの新しいインスタンスを作成できることを確かめてください。
+インスタンス上の Table オブジェクトに反映し保存されたスキーマをリフレッシュするために
+Table オブジェクトのレジストリーは、 ``update()`` が呼ばれた後にクリアされます。
+
+マイグレーションとデプロイメント
+--------------------------------
+
+もし、アプリケーションをデプロイする時にプラグインを使用する場合、
+テーブルのカラムメタデータを更新するように、必ず ORM キャッシュをクリアしてください。
+そうしなければ、それらの新しいカラムの操作を実行する時に、カラムが存在しないエラーになります。
+CakePHP コアは、この操作を行うために使用できる :doc:`スキーマキャッシュシェル
+` を含みます。 :
+
+.. code-block:: bash
+
+ // 3.6.0 より前の場合、orm_cache を使用
+ bin/cake schema_cache clear
+
+このシェルについてもっと知りたい場合、クックブックの
+:doc:`スキーマキャッシュシェル `
+セクションをご覧ください。
+
+テーブルのリネーム
+------------------
+
+プラグインは、 ``rename()`` メソッドを使用することでテーブルのリネームができます。
+あなたのマイグレーションファイルの中で、以下のように記述できます。 ::
+
+ public function up()
+ {
+ $this->table('old_table_name')
+ ->rename('new_table_name')
+ ->save();
+ }
+
+``schema.lock`` ファイル生成のスキップ
+--------------------------------------------
+
+.. versionadded:: cakephp/migrations 1.6.5
+
+diff 機能を動作させるために、 **.lock** ファイルは、migrate、rollback または
+スナップショットの bake の度に生成され、指定された時点でのデータベーススキーマの状態を追跡します。
+例えば本番環境上にデプロイするときなど、前述のコマンドに ``--no-lock``
+オプションを使用することによって、このファイルの生成をスキップすることができます。 :
+
+.. code-block:: bash
+
+ bin/cake migrations migrate --no-lock
+
+ bin/cake migrations rollback --no-lock
+
+ bin/cake bake migration_snapshot MyMigration --no-lock
+
diff --git a/app/vendor/cakephp/migrations/docs/pt/conf.py b/app/vendor/cakephp/migrations/docs/pt/conf.py
new file mode 100644
index 000000000..9e22cb017
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/pt/conf.py
@@ -0,0 +1,9 @@
+import sys, os
+
+# Append the top level directory of the docs, so we can import from the config dir.
+sys.path.insert(0, os.path.abspath('..'))
+
+# Pull in all the configuration options defined in the global config file..
+from config.all import *
+
+language = 'pt'
diff --git a/app/vendor/cakephp/migrations/docs/pt/contents.rst b/app/vendor/cakephp/migrations/docs/pt/contents.rst
new file mode 100644
index 000000000..1459b1f1b
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/pt/contents.rst
@@ -0,0 +1,5 @@
+.. toctree::
+ :maxdepth: 2
+ :caption: CakePHP Migrations
+
+ /index
diff --git a/app/vendor/cakephp/migrations/docs/pt/index.rst b/app/vendor/cakephp/migrations/docs/pt/index.rst
new file mode 100644
index 000000000..d993770d4
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/pt/index.rst
@@ -0,0 +1,940 @@
+Migrations
+##########
+
+Migrations é um plugin suportado pela equipe oficial do CakePHP que ajuda você a
+fazer mudanças no **schema** do banco de dados utilizando arquivos PHP,
+que podem ser versionados utilizando um sistema de controle de versão.
+
+Ele permite que você atualize suas tabelas ao longo do tempo. Ao invés de
+escrever modificações de **schema** via SQL, este plugin permite que você
+utilize um conjunto intuitivo de métodos para fazer mudanças no seu banco de
+dados.
+
+Esse plugin é um **wrapper** para a biblioteca `Phinx `_.
+
+Instalação
+==========
+
+Por padrão o plugin é instalado junto com o esqueleto da aplicação.
+Se você o removeu e quer reinstalá-lo, execute o comando a seguir a partir do
+diretório **ROOT** da sua aplicação
+(onde o arquivo composer.json está localizado):
+
+.. code-block:: bash
+
+ $ php composer.phar require cakephp/migrations "@stable"
+
+ # Or if composer is installed globally
+
+ $ composer require cakephp/migrations "@stable"
+
+Para usar o plugin você precisa carregá-lo no arquivo **config/bootstrap.php**
+da sua aplicação. Você pode usar o
+:ref:`shell de plugins do CakePHP ` para carregar e descarregar
+plugins do seu arquivo **config/bootstrap.php**::
+
+ $ bin/cake plugin load Migrations
+
+Ou você pode carregar o plugin editando seu arquivo **config/bootstrap.php** e
+adicionando a linha::
+
+ Plugin::load('Migrations');
+
+Adicionalmente, você precisará configurar o banco de dados padrão da sua
+aplicação, no arquivo **config/app.php** como explicado na seção
+:ref:`Configuração de banco de dados `.
+
+Visão Geral
+===========
+
+Uma migração é basicamente um arquivo PHP que descreve as mudanças a
+serem feitas no banco de dados. Um arquivo de migração pode criar ou excluir
+tabelas, adicionar ou remover colunas, criar índices e até mesmo inserir
+dados em seu banco de dados.
+
+Aqui segue um exemplo de migração::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+Essa migração irá adicionar uma tabela chamada ``products`` ao banco de dados
+com as seguintes colunas:
+
+- ``id`` coluna do tipo ``integer`` como chave primária
+- ``name`` coluna do tipo ``string``
+- ``description`` coluna do tipo ``text``
+- ``created`` coluna do tipo ``datetime``
+- ``modified`` coluna do tipo ``datetime``
+
+.. tip::
+
+ A coluna de chave primária ``id`` será adicionada **implicitamente**.
+
+.. note::
+
+ Note que este arquivo descreve como o banco de dados deve ser **após** a
+ aplicação da migração. Neste ponto, a tabela ``products``ainda não existe
+ no banco de dados, nós apenas criamos um arquivo que é capaz de criar a
+ tabela ``products`` com seus devidos campos ou excluir a tabela caso uma
+ operação rollback seja executada.
+
+Com o arquivo criado na pasta **config/MIgrations**, você será capaz de executar
+o comando abaixo para executar as migrações no seu banco de dados::
+
+ bin/cake migrations migrate
+
+O comando seguinte irá executar um **rollback** na migração e irá excluir a
+tabela recém criada::
+
+ bin/cake migrations rollback
+
+Criando migrations
+==================
+
+Arquivos de migração são armazeados no diretório **config/Migrations** da
+sua aplicação. O nome dos arquivos de migração têm como prefixo a data
+em que foram criados, no formato **YYYYMMDDHHMMSS_MigrationName.php**. Aqui
+estão exemplos de arquivos de migração:
+
+* 20160121163850_CreateProducts.php
+* 20160210133047_AddRatingToProducts.php
+
+A maneira mais fácil de criar um arquivo de migrações é usando o
+:doc:`/bake/usage` a linha de comando.
+
+Por favor, leia a `documentação do Phinx `
+a fim de conhecer a lista completa dos métodos que você pode usar para escrever
+os arquivos de migração.
+
+.. note::
+
+ Ao gerar as migrações através do ``bake`` você ainda pode alterá-las antes
+ da sua execução, caso seja necessário.
+
+Sintaxe
+-------
+
+A sintaxe do ``bake`` para a geração de migrações segue o formato abaixo::
+
+ $ bin/cake bake migration CreateProducts name:string description:text created modified
+
+Quando utilizar o ``bake`` para criar as migrações, você normalmente precisará
+informar os seguintes dados::
+
+ * o nome da migração que você irá gerar (``CreateProducts`` por exemplo)
+ * as colunas da tabela que serão adicionadas ou removidas na migração
+ (``name:string description:text created modified`` no nosso caso)
+
+Devido às convenções, nem todas as alterações de schema podem ser realizadas
+através destes comandos.
+
+Além disso, você pode criar um arquivo de migração vazio caso deseje ter um
+controle total do que precisa ser executado. Para isto, apenas omita a definição
+das colunas::
+
+ $ bin/cake migrations create MyCustomMigration
+
+Nomenclatura de migrations
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A nomenclatura das migrações pode seguir qualquer um dos padrões apresentados a
+seguir:
+
+* (``/^(Create)(.*)/``) Cria a tabela especificada.
+* (``/^(Drop)(.*)/``) Exclui a tabela especificada.
+ Ignora campos especificados nos argumentos
+* (``/^(Add).*(?:To)(.*)/``) Adiciona campos a
+ tabela especificada
+* (``/^(Remove).*(?:From)(.*)/``) Remove campos de uma
+ tabela específica
+* (``/^(Alter)(.*)/``) Altera a tabela especificada. Um apelido para
+ um CreateTable seguido de um AlterTable
+* (``/^(Alter).*(?:On)(.*)/``) Alterar os campos da tabela especificada
+
+Você também pode usar ``underscore_form`` como nome das suas **migrations**.
+Ex.: ``create_products``.
+
+.. versionadded:: cakephp/migrations 1.5.2
+
+ A partir da versão 1.5.2 do `plugin migrations `_,
+ o nome dos arquivos de migrações são colocados automaticamente no padrão
+ **camel case**.
+ Esta versão do plugin está disponível apenas a partir da versão 3.1 do
+ CakePHP.
+ Antes disto, o padrão de nomes do plugin migrations utilizava a nomenclatura
+ baseada em **underlines**, ex.: ``20160121164955_create_products.php``.
+
+.. warning::
+
+ O nome das migrações são usados como nomes de classe, e podem colidir com
+ outras migrações se o nome das classes não forem únicos. Neste caso, pode
+ ser necessário sobreescrever manualmente os nomes mais tarde ou simplesmente
+ mudar os nomes que você está especificando.
+
+Definição de colunas
+~~~~~~~~~~~~~~~~~~~~
+
+Quando utilizar colunas na linha de comando, pode ser útil lembrar que eles seguem o
+seguinte padrão::
+
+ fieldName:fieldType[length]:indexType:indexName
+
+Por exemplo, veja formas válidas de especificar um campo de e-mail:
+
+* ``email:string:unique``
+* ``email:string:unique:EMAIL_INDEX``
+* ``email:string[120]:unique:EMAIL_INDEX``
+
+O parâmetro ``length`` para o ``fieldType`` é opcional e deve sempre ser
+escrito entre colchetes
+
+Os campos ``created`` e ``modified`` serão automaticamente definidos
+como ``datetime``.
+
+Os tipos de campos são genericamente disponibilizados pela biblioteca ``Phinx``.
+Eles podem ser:
+
+* string
+* text
+* integer
+* biginteger
+* float
+* decimal
+* datetime
+* timestamp
+* time
+* date
+* binary
+* boolean
+* uuid
+
+Há algumas heurísticas para a escolha de tipos de campos que não são especificados
+ou são definidos com valor inválido. O tipo de campo padrão é ``string``;
+
+* id: integer
+* created, modified, updated: datetime
+
+Criando uma tabela
+------------------
+
+Você pode utilizar o ``bake`` para criar uma tabela::
+
+ $ bin/cake bake migration CreateProducts name:string description:text created modified
+
+A linha de comando acima irá gerar um arquivo de migração parecido com este::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+Adicionando colunas a uma tabela existente
+------------------------------------------
+
+Se o nome da migração na linha de comando estiver na forma "AddXXXToYYY" e
+for seguido por uma lista de nomes de colunas e tipos, então o arquivo de
+migração com o código para criar as colunas será gerado::
+
+ $ bin/cake bake migration AddPriceToProducts price:decimal
+
+A linha de comando acima irá gerar um arquivo com o seguinte conteúdo::
+
+ table('products');
+ $table->addColumn('price', 'decimal')
+ ->update();
+ }
+ }
+
+Adicionando uma coluna como indice a uma tabela
+-----------------------------------------------
+
+Também é possível adicionar índices a colunas::
+
+ $ bin/cake bake migration AddNameIndexToProducts name:string:index
+
+irá gerar::
+
+ table('products');
+ $table->addColumn('name', 'string')
+ ->addIndex(['name'])
+ ->update();
+ }
+ }
+
+Especificando o tamanho do campo
+--------------------------------
+
+.. versionadded:: cakephp/migrations 1.4
+
+Se você precisar especificar o tamanho do campo, você pode fazer isto entre
+colchetes logo após o tipo do campo, ex.::
+
+ $ bin/cake bake migration AddFullDescriptionToProducts full_description:string[60]
+
+Executar o comando acima irá gerar::
+
+ table('products');
+ $table->addColumn('full_description', 'string', [
+ 'default' => null,
+ 'limit' => 60,
+ 'null' => false,
+ ])
+ ->update();
+ }
+ }
+
+Se o tamanho não for especificado, os seguintes padrões serão utilizados:
+
+* string: 255
+* integer: 11
+* biginteger: 20
+
+Alterar uma coluna de uma tabela
+-----------------------------------
+
+Da mesma maneira, você pode gerar uma migração para alterar uma coluna usando a
+linha de comando, se o nome da migração estiver no formato "X""AlterXXXOnYYY":
+
+.. code-block:: bash
+
+ bin/cake bake migration AlterPriceOnProducts name:float
+
+Cria o arquivo::
+
+ table('products');
+ $table->changeColumn('name', 'float');
+ $table->update();
+ }
+ }
+
+Removendo uma coluna de uma tabela
+----------------------------------
+
+Da mesma forma, você pode gerar uma migração para remover uma coluna
+utilizando a linha de comando, se o nome da migração estiver na forma
+"RemoveXXXFromYYY"::
+
+ $ bin/cake bake migration RemovePriceFromProducts price
+
+Cria o arquivo::
+
+ table('products');
+ $table->removeColumn('price');
+ }
+ }
+
+Gerando migrações a partir de uma base de dados existente
+=========================================================
+
+Se você está trabalhando com um banco de dados pré-existente e quer começar
+a usar migrações, ou para versionar o schema inicial da base de dados da sua
+aplicação, você pode executar o comando ``migration_snapshot``::
+
+ $ bin/cake bake migration_snapshot Initial
+
+Isto irá gerar um arquivo de migração chamado **YYYYMMDDHHMMSS_Initial.php**
+contendo todas as instruções CREATE para todas as tabelas no seu banco de dados.
+
+Por padrão, o snapshot será criado a partir da conexão ``default`` definida na
+configuração.
+Se você precisar fazer o bake de um snapshot de uma fonte de dados diferente,
+você pode utilizar a opção ``--connection``::
+
+ $ bin/cake bake migration_snapshot Initial --connection my_other_connection
+
+Você também pode definir que o snapshot inclua apenas as tabelas para as quais
+você tenha definido models correspendentes, utilizando a flag
+``require-table``::
+
+ $ bin/cake bake migration_snapshot Initial --require-table
+
+Quando utilizar a flag ``--require-table``, o shell irá olhar através das
+classes do diretório ``Table`` da sua aplicação e apenas irá adicionar no
+snapshot as tabelas lá definidas.
+
+A mesma lógica será aplicada implicitamente se você quiser fazer o bake de um
+snapshot para um plugin. Para fazer isso, você precisa usar a opção
+``--plugin``, veja a seguir::
+
+ $ bin/cake bake migration_snapshot Initial --plugin MyPlugin
+
+Apenas as tabelas que tiverem um objeto ``Table`` definido serão adicionadas
+ao snapshot do seu plugin.
+
+.. note::
+
+ Quando fizer o bake de um snapshot para um plugin, os arquivos de migrações
+ serão criados no diretório **config/Migrations** do seu plugin.
+
+Fique atento que quando você faz o bake de um snapshot, ele é automaticamente
+ adicionado ao log do phinx como migrado.
+
+Gerando um *diff* entre dois estados da base de dados
+=====================================================
+
+.. versionadded:: cakephp/migrations 1.6.0
+
+Você pode gerar um arquivo de migração que agrupará todas as diferenças entre
+dois estados de uma base de dados usando ``migration_diff``. Para fazê-lo,
+você pode usar o seguinte comando::
+
+ $ bin/cake bake migration_diff NomeDasMigrações
+
+De forma a ter um ponto de comparação do estado atual da sua base de dados, a
+*shell* de ``migrations`` gerará um arquivo de *dump* após cada chamada de
+``migrate`` ou ``rollback``. O arquivo de *dump* é um arquivo contendo o
+estado completo do esquema da sua base de dados em um determinado instante no
+tempo.
+
+Uma vez gerado o arquivo de *dump*, cada modificação que você fizer
+diretamente no seu sistema de gerenciamento da base de dados será adicionada
+quando você chamar o comando ``bake migration_diff``.
+
+Por padrão, o *diff* será criado através de uma conexão com a base de dados
+definida na configuração de conexão ``default``.
+Se você precisar criar um *diff* de uma fonte de dados diferente, você pode
+usar a opção ``--connection``::
+
+ $ bin/cake bake migration_diff NomeDasMigrações --connection minha_outra_conexão
+
+Se você quiser usar a funcionalidade de *diff* em uma aplicação que já possui
+um histórico de migrações, você precisará criar manualmente o arquivo de
+*dump* a ser usado como base da comparação::
+
+ $ bin/cake migrations dump
+
+O estado da base de dados deve ser o mesmo que você teria caso você tivesse
+migrado todas as suas migrações antes de criar o arquivo de *dump*.
+Uma vez que o arquivo de *dump* for gerado, você pode começar a fazer
+modificações na sua base de dados e usar o comando ``bake migration_diff``
+sempre que desejar.
+
+.. note::
+
+ A *shell* de migrações não é capaz de detectar colunas renomeadas.
+
+Os Comandos
+===========
+
+``migrate`` : Aplicando migrações
+---------------------------------
+
+Depois de ter gerado ou escrito seu arquivo de migração, você precisa executar
+o seguinte comando para aplicar as mudanças a sua base de dados::
+
+ # Executa todas as migrações
+ $ bin/cake migrations migrate
+
+ # Execute uma migração específica utilizando a opção ``--target`` ou ``-t``
+ # O valor é um timestamp que serve como prefixo para cada migração::
+ $ bin/cake migrations migrate -t 20150103081132
+
+ # Por padrão, as migrações ficam no diretório **config/Migrations**. Você
+ # pode especificar um diretório utilizando a opção ``--source`` ou ``-s``.
+ # O comando abaixo executa as migrações no diretório **config/Alternate**
+ $ bin/cake migrations migrate -s Alternate
+
+ # Você pode executar as migrações de uma conexão diferente da ``default``
+ # utilizando a opção ``--connection`` ou ``-c``.
+ $ bin/cake migrations migrate -c my_custom_connection
+
+ # Migrações também podem ser executadas para plugins. Simplesmente utilize
+ # a opção ``--plugin`` ou ``-p``
+ $ bin/cake migrations migrate -p MyAwesomePlugin
+
+``rollback`` : Revertendo migrações
+-----------------------------------
+
+O comando rollback é utilizado para desfazer migrações realizadas anteriormente
+pelo plugin Migrations. É o inverso do comando ``migrate``::
+
+ # Você pode desfazer uma migração anterior utilizando o
+ # comando ``rollback``::
+ $ bin/cake migrations rollback
+
+ # Você também pode passar a versão da migração para voltar
+ # para uma versão específica::
+ $ bin/cake migrations rollback -t 20150103081132
+
+Você também pode utilizar as opções ``--source``, ``--connection`` e
+``--plugin`` exatamente como no comando ``migrate``.
+
+``status`` : Status da migração
+-------------------------------
+
+O comando status exibe uma lista de todas as migrações juntamente com seu
+status. Você pode utilizar este comando para ver quais migrações foram
+executadas::
+
+ $ bin/cake migrations status
+
+Você também pode ver os resultados como JSON utilizando a opção
+``--format`` (ou ``-f``)::
+
+ $ bin/cake migrations status --format json
+
+Você também pode utilizar as opções ``--source``, ``--connection`` e
+``--plugin`` exatamente como no comando ``migrate``.
+
+``mark_migrated`` : Marcando uma migração como migrada
+------------------------------------------------------
+
+.. versionadded:: 1.4.0
+
+Algumas vezes pode ser útil marcar uma lista de migrações como migrada sem
+efetivamente executá-las.
+Para fazer isto, você pode usar o comando ``mark_migrated``. O comando é
+bastante semelhante aos outros comandos.
+
+Você pode marcar todas as migrações como migradas utilizando este comando::
+
+ $ bin/cake migrations mark_migrated
+
+Você também pode marcar todas as migrações de uma versão específica
+utilizando a opção ``--target``::
+
+ $ bin/cake migrations mark_migrated --target=20151016204000
+
+Se você não quer marcar a migração alvo como migrada durante o processo, você
+pode utilizar a opção ``--exclude``::
+
+ $ bin/cake migrations mark_migrated --target=20151016204000 --exclude
+
+Finalmente, se você deseja marcar somente a migração alvo como migrada,
+você pode utilizar a opção ``--only``::
+
+ $ bin/cake migrations mark_migrated --target=20151016204000 --only
+
+Você também pode utilizar as opções ``--source``, ``--connection`` e
+``--plugin`` exatamente como no comando ``migrate``.
+
+.. note::
+
+ Quando você criar um snapshot utilizando o bake com o comando
+ ``cake bake migration_snapshot``, a migração criada será automaticamente
+ marcada como migrada.
+
+.. deprecated:: 1.4.0
+
+ A seguinte maneira de utilizar o comando foi depreciada. Use somente se
+ você estiver utilizando uma versão do plugin inferior a 1.4.0.
+
+Este comando espera um número de versão de migração como argumento::
+
+ $ bin/cake migrations mark_migrated
+
+Se você deseja marcar todas as migrações como migradas, você pode utilizar
+o valor especial ``all``. Se você o utilizar, ele irá marcar todas as migrações
+como migradas::
+
+ $ bin/cake migrations mark_migrated all
+
+``seed`` : Populando seu banco de dados
+---------------------------------------
+
+A partir da versão 1.5.5, você pode usar a **shell** de ``migrations`` para
+popular seu banco de dados. Essa função é oferecida graças ao
+`recurso de seed da biblioteca Phinx `_.
+Por padrão, arquivos **seed** ficarão no diretório ``config/Seeds`` de sua
+aplicação. Por favor, tenha certeza de seguir as
+`instruções do Phinx para construir seus arquivos de seed `_.
+
+Assim como nos **migrations**, uma interface do ```bake`` é oferecida para gerar
+arquivos de **seed**::
+
+ # This will create a ArticlesSeed.php file in the directory config/Seeds of your application
+ # By default, the table the seed will try to alter is the "tableized" version of the seed filename
+ $ bin/cake bake seed Articles
+
+ # You specify the name of the table the seed files will alter by using the ``--table`` option
+ $ bin/cake bake seed Articles --table my_articles_table
+
+ # You can specify a plugin to bake into
+ $ bin/cake bake seed Articles --plugin PluginName
+
+ # You can specify an alternative connection when generating a seeder.
+ $ bin/cake bake seed Articles --connection connection
+
+.. versionadded:: cakephp/migrations 1.6.4
+
+ As opções ``--data``, ``--limit`` e ``--fields`` foram adicionadas para
+ exportar dados da sua base de dados.
+
+A partir da versão 16.4, o comando ``bake seed`` permite que você crie um
+arquivo de *seed* com dados exportados da sua base de dados com o uso da
+*flag* ``--data``::
+
+ $ bin/cake bake seed --data Articles
+
+Por padrão, esse comando exportará todas as linhas encontradas na sua
+tabela. Você pode limitar o número de linhas a exportar usando a opção
+``--limit``::
+
+ # Exportará apenas as 10 primeiras linhas encontradas
+ $ bin/cake bake seed --data --limit 10 Articles
+
+Se você deseja incluir apenas uma seleção dos campos da tabela no seu
+arquivo de *seed*, você pode usar a opção ``--fields``. Ela recebe a
+lista de campos a incluir na forma de uma *string* separada por
+vírgulas::
+
+ # Exportará apenas os campos `id`, `title` e `excerpt`
+ $ bin/cake bake seed --data --fields id,title,excerpt Articles
+
+.. tip::
+
+ Você pode utilizar ambas as opções ``--limit`` e ``--fields``
+ simultaneamente em uma mesma chamada.
+
+Para popular seu banco de dados, você pode usar o subcomando ``seed``::
+
+ # Without parameters, the seed subcommand will run all available seeders
+ # in the target directory, in alphabetical order.
+ $ bin/cake migrations seed
+
+ # You can specify only one seeder to be run using the `--seed` option
+ $ bin/cake migrations seed --seed ArticlesSeed
+
+ # You can run seeders from an alternative directory
+ $ bin/cake migrations seed --source AlternativeSeeds
+
+ # You can run seeders from a plugin
+ $ bin/cake migrations seed --plugin PluginName
+
+ # You can run seeders from a specific connection
+ $ bin/cake migrations seed --connection connection
+
+Esteja ciente que, ao oposto das **migrations**, **seeders** não são
+versionados, o que significa que o mesmo **seeder** pode ser aplicado diversas
+vezes.
+
+Usando migrations em plugins
+============================
+
+**Plugins** também podem oferecer **migrations**. Isso faz com que **plugins**
+que são planejados para serem distribuídos tornem-se muito mais práticos e
+fáceis de instalar. Todos os comandos do plugin **Migrations** suportam a opção
+``--plugin`` ou ``-p``, que por sua vez vai delegar a execução da tarefa ao
+escopo relativo a um determinado **plugin**::
+
+ $ bin/cake migrations status -p PluginName
+
+ $ bin/cake migrations migrate -p PluginName
+
+Executando migrations em ambientes fora da linha de comando
+===========================================================
+
+.. versionadded:: cakephp/migrations 1.2.0
+
+Desde o lançamento da versão 1.2 do plugin, você pode executar **migrations**
+fora da linha de comando, diretamente de uma aplicação, ao usar a nova classe
+``Migrations``. Isso pode ser muito útil caso você esteja desenvolvendo um
+instalador de **plugins** para um CMS, para exemplificar.
+
+A classe ``Migrations`` permite que você execute os seguintes comandos
+disponíveis na **shell**:
+
+* migrate
+* rollback
+* markMigrated
+* status
+* seed
+
+Cada um desses comandos tem um método definido na classe ``Migrations``.
+
+Veja como usá-la::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // Retornará um array de todos migrations e seus status
+ $status = $migrations->status();
+
+ // Retornará true se bem sucedido. Se um erro ocorrer, uma exceção será lançada
+ $migrate = $migrations->migrate();
+
+ // Retornará true se bem sucedido. Se um erro ocorrer, uma exceção será lançada
+ $rollback = $migrations->rollback();
+
+ // Retornará true se bem sucedido. Se um erro ocorrer, uma exceção será lançada
+ $markMigrated = $migrations->markMigrated(20150804222900);
+
+ // Retornará true se bem sucedido. Se um erro ocorrer, uma exceção será lançada
+ $seeded = $migrations->seed();
+
+Os métodos aceitam um **array** de parâmetros que devem combinar com as opções
+dos comandos::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // Retornará um array de todos migrations e seus status
+ $status = $migrations->status(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+Você pode passar qualquer opção que esteja disponível pelos comandos **shell**.
+A única exceção é o comando ``markMigrated`` que espera um número de versão a
+ser marcado como migrado, como primeiro argumento. Passe o **array** de
+parâmetros como segundo argumento nesse caso.
+
+Opcionalmente, você pode passar esses parâmetros pelo construtor da classe.
+Eles serão usados como padrão evitando que você tenha que passá-los em cada
+chamada do método::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // Todas as chamadas de métodos serão executadas usando os parâmetros passados pelo construtor da classe
+ $status = $migrations->status();
+ $migrate = $migrations->migrate();
+
+Se você precisar sobrescrever um ou mais parâmetros definidos previamente, você
+pode passá-los para um método::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // Essa chamada será feita com a conexão "custom"
+ $status = $migrations->status();
+ // Essa chamada será feita com a conexão "default"
+ $migrate = $migrations->migrate(['connection' => 'default']);
+
+Dicas e truques
+===============
+
+Criando chaves primárias customizadas
+-------------------------------------
+
+Se você precisa evitar a criação automática da chave primária ``id`` ao
+adicioanr novas tabelas ao banco de dados, é possível usar o segundo argumento
+do método ``table()``::
+
+ table('products', ['id' => false, 'primary_key' => ['id']]);
+ $table
+ ->addColumn('id', 'uuid')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+O código acima vai criar uma coluna ``CHAR(36)`` ``id`` que também é a chave
+primária.
+
+.. note::
+
+ Ao especificar chaves primárias customizadas pela linha de comando, você
+ deve apontá-las como chave primária no campo id, caso contrário você pode
+ receber um erro apontando campos diplicados, i.e.::
+
+ $ bin/cake bake migration CreateProducts id:uuid:primary name:string description:text created modified
+
+Adicionalmente, desde a versão 1.3, uma novo meio de lidar com chaves primárias
+foi introduzido. Para tal, sua classe de migração deve estender a nova classe
+``Migrations\AbstractMigration``.
+
+Você pode especificar uma propriedade ``autoId`` na sua classe e defini-la como
+``false``, o quê desabilitará a geração automática da coluna ``id``. Você
+vai precisar criar manualmente a coluna que será usada como chave primária e
+adicioná-la à declaração da tabela::
+
+ table('products');
+ $table
+ ->addColumn('id', 'integer', [
+ 'autoIncrement' => true,
+ 'limit' => 11
+ ])
+ ->addPrimaryKey('id')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+Comparado ao método apresentado anteriormente de lidar com chaves primárias,
+nesse método, temos a possibilidade de ter maior controle sobre as definições
+da coluna da chave primária:
+unsigned, limit, comentários, etc.
+
+Todas as migrations e snapshots criadas pelo bake vão usar essa nova forma
+quando necessário.
+
+.. warning::
+
+ Lidar com chaves primárias só é possível no momento de criação de tabelas.
+ Isso é devido a algumas limitações de alguns servidores de banco de dados
+ que o plugin suporta.
+
+Colações
+--------
+
+Se você precisar criar uma tabela com colação diferente do padrão do banco de
+dados, você pode defini-la pelo método ``table()``, como uma opção::
+
+ table('categories', [
+ 'collation' => 'latin1_german1_ci'
+ ])
+ ->addColumn('title', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ])
+ ->create();
+ }
+ }
+
+Note que isso só pode ser feito na criação da tabela : não há atualmente uma
+forma de adicionar uma coluna a uma tabela existente com uma colação diferente
+do padrão da tabela, ou mesmo do banco de dados.
+Apenas ``MySQL`` e ``SqlServer`` suportam essa chave de configuração.
+
+Atualizando nome de colunas e usando objetos de tabela
+------------------------------------------------------
+
+Se você usa um objeto ORM Table do CakePHP para manipular valores do seu banco
+de dados, renomeando ou removendo uma coluna, certifique-se de criar uma nova
+instância do seu objeto depois da chamada do ``update()``. O registro do objeto
+é limpo depois da chamada do ``update()`` para atualizar o **schema** que é
+refletido e armazenado no objeto ``Table`` paralelo à instanciação.
+
+Migrations e Deployment
+-----------------------
+
+Se você usa o plugin ao fazer o **deploy** de sua aplicação, garanta que o cache
+ORM seja limpo para renovar os metadados das colunas de suas tabelas.
+Caso contrário, você pode acabar recebendo erros relativos a colunas
+inexistentes ao criar operações nessas mesmas colunas.
+O **core** do CakePHP possui uma :doc:`Schema Cache Shell `
+que você pode usar para realizar essas operação::
+
+ $ bin/cake schema_cache clear
+
+Leia a seção :doc:`Schema Cache Shell ` do cookbook
+se você quiser conhecer mais sobre essa **shell**.
diff --git a/app/vendor/cakephp/migrations/docs/ru/conf.py b/app/vendor/cakephp/migrations/docs/ru/conf.py
new file mode 100644
index 000000000..f8a170ee5
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/ru/conf.py
@@ -0,0 +1,9 @@
+import sys, os
+
+# Append the top level directory of the docs, so we can import from the config dir.
+sys.path.insert(0, os.path.abspath('..'))
+
+# Pull in all the configuration options defined in the global config file..
+from config.all import *
+
+language = 'ru'
diff --git a/app/vendor/cakephp/migrations/docs/ru/contents.rst b/app/vendor/cakephp/migrations/docs/ru/contents.rst
new file mode 100644
index 000000000..1459b1f1b
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/ru/contents.rst
@@ -0,0 +1,5 @@
+.. toctree::
+ :maxdepth: 2
+ :caption: CakePHP Migrations
+
+ /index
diff --git a/app/vendor/cakephp/migrations/docs/ru/index.rst b/app/vendor/cakephp/migrations/docs/ru/index.rst
new file mode 100644
index 000000000..f0574835d
--- /dev/null
+++ b/app/vendor/cakephp/migrations/docs/ru/index.rst
@@ -0,0 +1,1016 @@
+Миграции
+########
+
+Миграции (Migrations) - это плагин, поддерживаемый основной командой, который помогает вам выполнять
+изменение схемы вашей базе данных путём написания файлов PHP, которые можно отслеживать с помощью
+системы управления версиями.
+
+Это позволяет вам постепенно менять таблицы базы данных. Вместо написания
+модификации схемы в виде SQL, этот плагин позволяет вам использовать интуитивно
+понятный набор методов для изменения вашей базы данных.
+
+Этот плагин является обёрткой для библиотеки миграции баз данных `Phinx `_.
+
+Установка
+=========
+
+По умолчанию Migrations устанавливается вместе с дефолтным скелетом приложения.
+Если вы удалили его и хотите его переустановить, вы можете сделать это, запустив
+следующее из каталога ROOT вашего приложения (где находится файл composer.json):
+
+.. code-block:: bash
+
+ $ php composer.phar require cakephp/migrations "@stable"
+
+ # Или, если композитор установлен глобально
+
+ $ composer require cakephp/migrations "@stable"
+
+Чтобы использовать плагин, вам нужно загрузить его в файле **config/bootstrap.php**
+вашего приложения. Вы можете использовать
+:ref:`CakePHP's Plugin shell ` для загрузки и выгрузки плагинов из
+вашего **config/bootstrap.php**::
+
+ $ bin/cake plugin load Migrations
+
+Или вы можете загрузить плагин, отредактировав файл **config/bootstrap.php**
+и добавив следующий оператор::
+
+ Plugin::load('Migrations');
+
+Кроме того, вам нужно будет настроить конфигурацию базы данных по умолчанию для вашего
+приложения в файле **config/app.php**, как описано в
+:ref:`Раздел о конфигурации БД `.
+
+Обзор
+=====
+
+Миграция в основном представляет собой один файл PHP, который описывает изменения
+для работы с базой данных. Файл миграции может создавать или удалять таблицы,
+добавлять или удалять столбцы, создавать индексы и даже вставлять данные в вашу базу данных.
+
+Вот пример миграции::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+Эта миграция добавит таблицу в вашу базу данных под названием ``products``
+со следующими определениями столбцов:
+
+- ``id`` столбец типа ``integer`` как primary key (первичный ключ)
+- ``name`` столбец типа ``string``
+- ``description`` столбец типа ``text``
+- ``created`` столбец типа ``datetime``
+- ``modified`` столбец типа ``datetime``
+
+.. tip::
+
+ Столбец первичного ключа с именем ``id`` будет добавлен **неявно**.
+
+.. note::
+
+ Обратите внимание, что этот файл описывает, как будет выглядеть база
+ данных **после** применения миграции. На данный момент в вашей базе
+ данных нет таблицы ``products``, мы просто создали файл, который способен
+ создавать таблицу ``products`` с указанными столбцами, а также удалить её,
+ когда выполняется ``rollback`` операция миграции.
+
+После того, как файл был создан в папке **config/Migrations**, вы сможете
+выполнить следующую команду ``migrations``, чтобы создать таблицу в своей
+базе данных::
+
+ bin/cake migrations migrate
+
+Следующая команда ``migrations`` выполнит ``rollback`` и удалит эту таблицу
+из вашей базы данных::
+
+ bin/cake migrations rollback
+
+Создание миграций
+=================
+
+Файлы миграции хранятся в каталоге **config/Migrations** вашего приложения.
+Имя файлов миграции имеет префикс даты, в которой они были созданы, в
+формате **YYYYMMDDHHMMSS_MigrationName.php**. Ниже приведены примеры имён
+файлов миграции:
+
+* 20160121163850_CreateProducts.php
+* 20160210133047_AddRatingToProducts.php
+
+Самый простой способ создать файл миграции - это использовать команду CLI
+:doc:`/bake/usage`.
+
+Пожалуйста, убедитесь, что вы читали официальную
+`Phinx documentation `_
+чтобы узнать полный список методов, которые вы можете использовать для
+записи файлов миграции.
+
+.. note::
+
+ При использовании опции ``bake`` вы всё равно можете изменить миграции,
+ прежде чем запускать их, если это необходимо.
+
+Синтаксис
+---------
+
+Синтаксис команды ``bake`` следует форме ниже::
+
+ $ bin/cake bake migration CreateProducts name:string description:text created modified
+
+При использовании ``bake`` для создания таблиц, добавления столбцов и т. п. в
+вашей базе данных, вы обычно предоставляете две вещи:
+
+* имя миграции, которую вы создадите (``CreateProducts`` в нашем примере)
+* столбцы таблицы, которые будут добавлены или удалены в процессе миграции
+ (``name: string description: text created modified`` в нашем примере)
+
+В связи с соглашениями CakePHP, не все изменения схемы могут выполняться с помощью этих
+команд оболочки.
+
+Кроме того, вы можете создать пустой файл миграции, если хотите получить полный контроль
+над тем, что нужно выполнить, указав определение столбцов::
+
+ $ bin/cake migrations create MyCustomMigration
+
+Имя файла миграции
+~~~~~~~~~~~~~~~~~~
+
+Имена миграции могут следовать любому из следующих шаблонов:
+
+* (``/^(Create)(.*)/``) Создаёт указанную таблицу.
+* (``/^(Drop)(.*)/``) Уничтожает указанную таблицу.
+ Игнорирует аргументы заданного поля.
+* (``/^(Add).*(?:To)(.*)/``) Добавляет поля в указанную таблицу.
+* (``/^(Remove).*(?:From)(.*)/``) Удаляет поля из указанной таблицы.
+* (``/^(Alter)(.*)/``) Изменяет указанную таблицу. Псевдоним для
+ CreateTable и AddField.
+* (``/^(Alter).*(?:On)(.*)/``) Изменяет поля указанной таблицы.
+
+Вы также можете использовать ``underscore_form`` как имя для своих миграций, например
+``create_products``.
+
+.. versionadded:: cakephp/migrations 1.5.2
+
+ Начиная с версии 1.5.2 `migrations plugin `_,
+ имя файла миграции будет автоматически изменено. Эта версия плагина доступна только
+ с выпуском CakePHP> = to 3.1. До этой версии плагина имя миграции было бы в форме
+ подчеркивания, то есть ``20160121164955_create_products.php``.
+
+.. warning::
+
+ Имена миграции используются как имена классов миграции и, таким образом,
+ могут сталкиваться с другими миграциями, если имена классов не уникальны.
+ В этом случае может потребоваться вручную переопределить имя на более
+ позднюю дату или просто изменить имя, которое вы указываете.
+
+Определение столбцов
+~~~~~~~~~~~~~~~~~~~~
+
+При использовании столбцов в командной строке может быть удобно запомнить, что они
+используют следующий шаблон::
+
+ fieldName:fieldType?[length]:indexType:indexName
+
+Например, все допустимые способы указания поля электронной почты:
+
+* ``email:string?``
+* ``email:string:unique``
+* ``email:string?[50]``
+* ``email:string:unique:EMAIL_INDEX``
+* ``email:string[120]:unique:EMAIL_INDEX``
+
+Знак вопроса, следующий за типом fieldType, сделает столбец нулевым.
+
+Параметр ``length`` для ``fieldType`` является необязательным и всегда должен быть
+записан в скобках.
+
+Поля с именем ``created`` и ``modified``, а также любое поле с суффиксом ``_at``
+автоматически будут установлены в тип ``datetime``.
+
+Типы полей поддерживаемые библиотекой ``Sphinx``:
+
+* string
+* text
+* integer
+* biginteger
+* float
+* decimal
+* datetime
+* timestamp
+* time
+* date
+* binary
+* boolean
+* uuid
+
+Существуют некоторые эвристики для выбора типов полей, если они не указаны или
+установлено недопустимое значение. Тип поля по умолчанию - ``string``:
+
+* id: integer
+* created, modified, updated: datetime
+
+Создание таблицы
+----------------
+
+Вы можете использовать ``bake`` для создания таблицы::
+
+ $ bin/cake bake migration CreateProducts name:string description:text created modified
+
+В приведённой выше командной строке будет создан файл миграции, напоминающий::
+
+ table('products');
+ $table->addColumn('name', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ]);
+ $table->addColumn('description', 'text', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('created', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->addColumn('modified', 'datetime', [
+ 'default' => null,
+ 'null' => false,
+ ]);
+ $table->create();
+ }
+ }
+
+Добавление столбцов в существующую таблицу
+------------------------------------------
+
+Если имя миграции в командной строке имеет форму "AddXXXToYYY" и за ней следует
+список имён столбцов и типов, тогда будет создан файл миграции, содержащий код
+для создания столбцов::
+
+ $ bin/cake bake migration AddPriceToProducts price:decimal
+
+Выполнение приведенной выше командной строки сгенерирует::
+
+ table('products');
+ $table->addColumn('price', 'decimal')
+ ->update();
+ }
+ }
+
+Добавление столбца в качестве индекса в таблицу
+-----------------------------------------------
+
+Также можно добавлять индексы в столбцы::
+
+ $ bin/cake bake migration AddNameIndexToProducts name:string:index
+
+будет сгенерировано::
+
+ table('products');
+ $table->addColumn('name', 'string')
+ ->addIndex(['name'])
+ ->update();
+ }
+ }
+
+Указание длины поля
+-------------------
+
+.. versionadded:: cakephp/migrations 1.4
+
+Если вам нужно указать длину поля, вы можете сделать это в квадратных скобках
+в поле типа::
+
+ $ bin/cake bake migration AddFullDescriptionToProducts full_description:string[60]
+
+Выполнение приведенной выше командной строки будет генерировать::
+
+ table('products');
+ $table->addColumn('full_description', 'string', [
+ 'default' => null,
+ 'limit' => 60,
+ 'null' => false,
+ ])
+ ->update();
+ }
+ }
+
+Если длина не указана, значения длины для определённого типа столбцов установятся
+по умолчания как:
+
+* string: 255
+* integer: 11
+* biginteger: 20
+
+Изменить столбец из таблицы
+-----------------------------------
+
+Таким же образом вы можете сгенерировать миграцию для изменения столбца с помощью
+командной строки, если имя миграции имеет вид "AlterXXXOnYYY":
+
+.. code-block:: bash
+
+ bin/cake bake migration AlterPriceOnProducts name:float
+
+создаст файл::
+
+ table('products');
+ $table->changeColumn('name', 'float');
+ $table->update();
+ }
+ }
+
+Удаление столбца из таблицы
+---------------------------
+
+Аналогичным образом вы можете сгенерировать миграцию для удаления столбца с помощью
+командной строки, если имя миграции имеет форму "RemoveXXXFromYYY"::
+
+ $ bin/cake bake migration RemovePriceFromProducts price
+
+создаст файл::
+
+ table('products');
+ $table->removeColumn('price')
+ ->save();
+ }
+ }
+
+.. note::
+
+ Команда `removeColumn` не является обратимой, поэтому её нужно вызывать
+ в методе `up`. Соответствующий вызов `addColumn` должен быть добавлен к
+ методу `down`.
+
+Создание миграции для существующей базы данных
+==============================================
+
+Если вы имеете дело с уже существующей базой данных и хотите начать
+использовать миграцию или управлять версией исходной схемы базы данных
+вашего приложения, вы можете запустить команду ``migration_snapshot``::
+
+ $ bin/cake bake migration_snapshot Initial
+
+Это заставит сгенерировать файл миграции с именем **YYYYMMDDHHMMSS_Initial.php**,
+содержащий все инструкции create для всех таблиц в вашей базе данных.
+
+По умолчанию, моментальный снимок будет создан путём подключения к базе данных,
+определённой в ``default`` конфигурации подключения.
+
+Если же вам нужно создать снимок из другого источника данных (из другой настройки),
+вы можете использовать опцию ``--connection``::
+
+ $ bin/cake bake migration_snapshot Initial --connection my_other_connection
+
+Вы также можете убедиться, что моментальный снимок содержит только те таблицы,
+для которых вы определили соответствующие классы моделей, используя флаг
+``--require-table``::
+
+ $ bin/cake bake migration_snapshot Initial --require-table
+
+При использовании флага ``--require-table`` оболочка будет просматривать классы
+вашего приложения ``Table`` и будет добавлять таблицы модели в моментальный снимок.
+
+Эта же логика будет применяться неявно, если вы хотите создать снимок для плагина.
+Для этого вам нужно использовать опцию ``--plugin``::
+
+ $ bin/cake bake migration_snapshot Initial --plugin MyPlugin
+
+В моментальный снимок вашего плагина будут добавлены только те таблицы, у которых
+есть класс объектной модели ``Table``.
+
+.. note::
+
+ При создании моментального снимка для плагина, файлы миграции будут созданы
+ в каталоге **config/Migrations** вашего плагина.
+
+Имейте в виду, что когда вы создаёте моментальный снимок, он автоматически
+добавляется в таблицу журналов sphinx как перенесённый.
+
+Создание разницы между двумя состояниями базы данных
+====================================================
+
+.. versionadded:: cakephp/migrations 1.6.0
+
+Вы можете создать файл миграции, в котором будут группироваться все различия
+между двумя состояниями базы данных с использованием шаблона ``migration_diff``.
+Для этого вы можете использовать следующую команду::
+
+ $ bin/cake bake migration_diff NameOfTheMigrations
+
+Чтобы иметь точку сравнения с текущим состоянием базы данных, оболочка миграции
+будет генерировать файл "дампа" после каждого вызова ``migrate`` или
+``rollback``. Файл дампа - это файл, содержащий полное состояние схемы вашей
+базы данных в данный момент времени.
+
+После создания дамп-файла все изменения, которые вы делаете непосредственно
+в вашей системе управления базой данных, будут добавлены в файл миграции,
+сгенерированный при вызове команды ``bake migration_diff``.
+
+По умолчанию diff будет создан путём подключения к базе данных, определенной
+в конфигурации ``default``. Если вам нужно испечь diff от другого источника
+данных, вы можете использовать опцию ``--connection``::
+
+ $ bin/cake bake migration_diff NameOfTheMigrations --connection my_other_connection
+
+Если вы хотите использовать функцию diff в приложении, которое уже имеет историю
+миграции, вам необходимо вручную создать файл дампа, который будет использоваться
+в качестве сравнения::
+
+ $ bin/cake migrations dump
+
+Состояние базы данных должно быть таким же, как если бы вы просто перенесли все
+свои миграции перед созданием файла дампа. После создания файла дампа вы можете
+начать делать изменения в своей базе данных и использовать команду
+``bake migration_diff`` всякий раз, когда вы считаете нужным.
+
+.. note::
+
+ Оболочка миграций не может обнаруживать переименования столбцов.
+
+Команды
+=======
+
+``migrate`` : Применение миграции
+---------------------------------
+
+После создания или записи файла миграции вам необходимо выполнить одну из
+следующих команд, чтобы применить изменения в своей базе данных::
+
+ # Запуск всех миграций
+ $ bin/cake migrations migrate
+
+ # Миграция к определённой версии, используя опцию ``--target``
+ # или ``-t`` для краткости.
+ # Значение - это метка времени, которая имеет префикс имени файла миграции::
+ $ bin/cake migrations migrate -t 20150103081132
+
+ # По умолчанию файлы миграции ищются в каталоге **config/Migrations**.
+ # Вы можете указать альтернативный каталог, используя опцию ``--source``
+ # или ``-s`` для краткости.
+ # В следующем примере будут выполняться миграции в каталоге
+ # **config/Alternate**
+ $ bin/cake migrations migrate -s Alternate
+
+ # Вы можете запускать миграции используя другое соединение, чем ``default``,
+ # для этого используйте опцию ``--connection`` или ``-c`` для краткости.
+ $ bin/cake migrations migrate -c my_custom_connection
+
+ # Миграции также могут выполняться для плагинов. Просто используйте опцию
+ # ``--plugin`` или ``-p`` для краткости.
+ $ bin/cake migrations migrate -p MyAwesomePlugin
+
+``rollback`` : Откат миграций
+-----------------------------
+
+Команда Rollback используется для отмены предыдущих миграций, выполняемых
+этим плагином. Это обратное действие по отношения к команде ``migrate``::
+
+ # Вы можете вернуться к предыдущей миграции, используя команду
+ # ``rollback``::
+ $ bin/cake migrations rollback
+
+ # Вы также можете передать номер версии миграции для отката
+ # к определённой версии::
+ $ bin/cake migrations rollback -t 20150103081132
+
+Вы также можете использовать параметры ``--source``, ``--connection``
+и ``--plugin``, как и для ``migrate``.
+
+``status`` : Статус миграции
+----------------------------
+
+Команда Status выводит список всех миграций вместе с их текущим статусом.
+Вы можете использовать эту команду, чтобы определить, какие миграции были
+выполнены::
+
+ $ bin/cake migrations status
+
+Вы также можете выводить результаты как форматированную JSON строку,
+используя опцию ``--format`` или ``-f`` для краткости.::
+
+ $ bin/cake migrations status --format json
+
+Вы также можете использовать параметры ``--source``, ``--connection``
+и ``--plugin``, как и для ``migrate``.
+
+``mark_migrated`` : Пометка миграций как перенесённые
+-----------------------------------------------------
+
+.. versionadded:: 1.4.0
+
+Иногда бывает полезно отметить набор миграций, перенесённых без их
+фактического запуска. Для этого вы можете использовать команду
+``mark_migrated``. Команда работает плавно, как и другие команды.
+
+Вы можете пометить все миграции как перенесенные с помощью этой команды::
+
+ $ bin/cake migrations mark_migrated
+
+Вы также можете пометить все миграции до определённой версии как перенесенные
+с помощью параметра ``--target``::
+
+ $ bin/cake migrations mark_migrated --target=20151016204000
+
+Если вы не хотите, чтобы целевая миграция была помечена как перенесённая во
+время процесса миграции, вы можете использовать флаг ``--exclude``::
+
+ $ bin/cake migrations mark_migrated --target=20151016204000 --exclude
+
+Наконец, если вы хотите пометить только перенесённую миграцию, вы можете
+использовать флаг ``--only``::
+
+ $ bin/cake migrations mark_migrated --target=20151016204000 --only
+
+Вы также можете использовать параметры ``--source``, ``--connection``
+и ``--plugin``, как и для ``migrate``.
+
+.. note::
+
+ Когда вы выпекаете моментальный снимок с помощью команды
+ ``cake bake migration_snapshot``, созданная миграция будет автоматически
+ помечена как перенесенная.
+
+.. deprecated:: 1.4.0
+
+ Следующий способ использования команды устарел. Используйте его
+ только в том случае, если вы используете версию плагина < 1.4.0.
+
+Эта команда ожидает номер версии миграции в качестве аргумента::
+
+ $ bin/cake migrations mark_migrated 20150420082532
+
+Если вы хотите пометить все миграции как перенесенные, вы можете использовать
+специальное значение ``all``. Если вы используете его, оно будет отмечать все
+найденные миграции как перенесенные::
+
+ $ bin/cake migrations mark_migrated all
+
+``seed`` : Засеивание базы данных
+---------------------------------
+
+Начиная с 1.5.5, вы можете использовать оболочку ``migrations`` для засеивания
+вашей базы данных. Это использует
+`Phinx library seed feature `_.
+По умолчанию файлы семян будут искать в каталоге ``config/Seeds`` вашего приложения.
+Пожалуйста, убедитесь, что вы следуете
+`Phinx instructions to build your seed files `_.
+
+Что касается миграций, для файлов семян предоставляется интерфейс ``bake``::
+
+ # Это создаст файл ArticlesSeed.php в каталоге config/Seeds вашего приложения.
+ # По умолчанию таблица, которую семя будет пытаться изменить, является "табличной"
+ # версией имени файла семени.
+ $ bin/cake bake seed Articles
+
+ # Вы указываете имя таблицы, которую будут изменять семенные файлы,
+ # используя опцию ``--table``
+ $ bin/cake bake seed Articles --table my_articles_table
+
+ # Вы можете указать плагин для выпечки
+ $ bin/cake bake seed Articles --plugin PluginName
+
+ # Вы можете указать альтернативное соединение при создании сеялки.
+ $ bin/cake bake seed Articles --connection connection
+
+.. versionadded:: cakephp/migrations 1.6.4
+
+ Для экспорта данных из базы данных были добавлены опции ``--data``,
+ ``--limit`` и ``--fields``.
+
+Начиная с версии 1.6.4 команда ``bake seed`` позволяет создать файл семян с данными,
+экспортированными из вашей базы данных, с помощью флага ``--data``::
+
+ $ bin/cake bake seed --data Articles
+
+По умолчанию он будет экспортировать все строки, найденные в вашей таблице.
+Вы можете ограничить количество строк, экспортированных с помощью опции
+``-limit``::
+
+ # Будет экспортировано только первые 10 найденных строк
+ $ bin/cake bake seed --data --limit 10 Articles
+
+Если вы хотите включить только поле из таблицы в файл семени, вы можете
+использовать опцию ``--fields``. Она принимает список полей для включения
+в виде строки значений, разделенных запятой::
+
+ # Будет экспортировать только поля `id`, `title` и `excerpt`
+ $ bin/cake bake seed --data --fields id,title,excerpt Articles
+
+.. tip::
+
+ Конечно, вы можете использовать оба параметра ``--limit`` и ``--fields``
+ в том же командном вызове.
+
+Чтобы засеять вашу базу данных, вы можете использовать подкоманду ``seed``::
+
+ # Без параметров подкоманда seed будет запускать все доступные сеялки
+ # в целевом каталоге, в алфавитном порядке.
+ $ bin/cake migrations seed
+
+ # Вы можете указать только одну сеялку для запуска с использованием
+ # опции `--seed`
+ $ bin/cake migrations seed --seed ArticlesSeed
+
+ # Вы можете запускать сеялки из альтернативного каталога
+ $ bin/cake migrations seed --source AlternativeSeeds
+
+ # Вы можете запускать сеялки из плагина
+ $ bin/cake migrations seed --plugin PluginName
+
+ # Вы можете запускать сеялки из определённого соединения
+ $ bin/cake migrations seed --connection connection
+
+Имейте в виду, что в отличие от миграций сеялки не отслеживаются, а это
+означает, что одну и ту же сеялку можно применять несколько раз.
+
+Вызов сеялки из другой сеялки
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: cakephp/migrations 1.6.2
+
+Обычно при посеве необходимо соблюдать порядок, в котором нужно вставлять данные,
+чтобы не встречаться с нарушениями ограничений. Поскольку по умолчанию Seeders
+выполняются в алфавитном порядке, вы можете использовать метод
+``\Migrations\AbstractSeed::call()`` для определения вашей собственной
+последовательности выполнения сеялок::
+
+ use Migrations\AbstractSeed;
+
+ class DatabaseSeed extends AbstractSeed
+ {
+ public function run()
+ {
+ $this->call('AnotherSeed');
+ $this->call('YetAnotherSeed');
+
+ // Вы можете использовать plugin dot syntax, чтобы
+ // вызывать сеялки из плагина
+ $this->call('PluginName.FromPluginSeed');
+ }
+ }
+
+.. note::
+
+ Не забудьте расширить модуль плагина Migrations ``AbstractSeed``, если вы
+ хотите использовать метод ``call()``. Этот класс был добавлен с выпуском 1.6.2.
+
+``dump`` : Создание файла дампа для разницы выпечек
+---------------------------------------------------
+
+Команда Dump создаёт файл, который будет использоваться с bake шаблоном
+``migration_diff``::
+
+ $ bin/cake migrations dump
+
+Каждый сгенерированный файл дампа относится к соединению, из которого он создан
+(и суффикс как таковой). Это позволяет команде ``bake migration_diff`` правильно
+вычислять разницу, если ваше приложение имеет дело с несколькими базами данных,
+возможно, от разных поставщиков баз данных.
+
+Файлы дампов создаются в том же каталоге, что и файлы миграции.
+
+Вы также можете использовать параметры ``--source``, ``--connection``
+и ``--plugin``, как и для ``migrate``.
+
+Использование миграции в плагинах
+=================================
+
+Плагины также могут предоставлять файлы миграции. Это делает плагины, которые
+предназначены для распространения, гораздо более портативны и простыми в
+установке. Все команды в плагине Migrations поддерживают опцию ``--plugin``
+или ``-p``, которая охватит выполнение миграции относительно этого
+плагина::
+
+ $ bin/cake migrations status -p PluginName
+
+ $ bin/cake migrations migrate -p PluginName
+
+Выполнение миграции в среде без оболочки
+========================================
+
+.. versionadded:: cakephp/migrations 1.2.0
+
+Начиная с версии 1.2 плагина миграции вы можете запускать миграции из среды
+без оболочки, непосредственно из приложения, используя новый класс ``Migrations``.
+Это может быть удобно, если вы разрабатываете например инсталлятор плагинов для CMS.
+Класс ``Migrations`` позволяет запускать следующие команды из оболочки миграции:
+
+* migrate
+* rollback
+* markMigrated
+* status
+* seed
+
+Каждая из этих команд имеет метод, определённый в классе ``Migrations``.
+
+Вот как его использовать::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // Вернёт массив всех миграций и их статус
+ $status = $migrations->status();
+
+ // Вернёт true, если успешно. Если произошла ошибка, будет возвращено исключение
+ $migrate = $migrations->migrate();
+
+ // Вернёт true, если успешно. Если произошла ошибка, будет возвращено исключение
+ $rollback = $migrations->rollback();
+
+ // Вернёт true, если успешно. Если произошла ошибка, будет возвращено исключение
+ $markMigrated = $migrations->markMigrated(20150804222900);
+
+ // Вернёт true, если успешно. Если произошла ошибка, будет возвращено исключение
+ $seeded = $migrations->seed();
+
+Методы могут принимать массив параметров, которые должны соответствовать параметрам
+из команд::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations();
+
+ // Вернёт массив всех миграций и их статус
+ $status = $migrations->status(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+Вы можете передать любые параметры, которые потребуются командам оболочки.
+Единственным исключением является команда ``markMigrated``, которая ожидает,
+что номер версии миграции будет отмечен как перенесённый как первый аргумент.
+Передайте массив параметров в качестве второго аргумента для этого метода.
+
+При желании вы можете передать эти параметры в конструкторе класса.
+Они будут использоваться по умолчанию, и это не позволит вам передать их
+при каждом вызове метода::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // Все последующие вызовы будут выполнены с параметрами, переданными конструктору класса Migrations
+ $status = $migrations->status();
+ $migrate = $migrations->migrate();
+
+Если вам необходимо переопределить один или несколько параметров по умолчанию для одного вызова,
+вы можете передать их методу::
+
+ use Migrations\Migrations;
+
+ $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+ // Этот вызов будет выполнен с использованием "пользовательского" соединения
+ $status = $migrations->status();
+ // Этот с подключением "по умолчанию"
+ $migrate = $migrations->migrate(['connection' => 'default']);
+
+Советы и приёмы
+===============
+
+Создание пользовательских первичных ключей
+------------------------------------------
+
+Если вам нужно избегать автоматического создания первичного ключа ``id``
+при добавлении новых таблиц в базу данных, вы можете использовать второй
+аргумент метода ``table()``::
+
+ table('products', ['id' => false, 'primary_key' => ['id']]);
+ $table
+ ->addColumn('id', 'uuid')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+Вышеупомянутый элемент создаст столбец ``id`` с типом ``CHAR(36)``, который также является первичным ключом.
+
+.. note::
+
+ При указании настраиваемого первичного ключа в командной строке вы
+ должны отметить его как первичный ключ в поле id, иначе вы можете
+ получить ошибку в отношении повторяющихся полей id, т.е.::
+
+ $ bin/cake bake migration CreateProducts id:uuid:primary name:string description:text created modified
+
+Кроме того, начиная с Migrations 1.3 был введён новый способ обработки
+первичного ключа. Для этого ваш класс миграции должен расширить новый
+класс ``Migrations\AbstractMigration``.
+
+Вы можете указать свойство ``autoId`` в классе Migration и установить его в
+``false``, что отключит автоматическое создание столбца ``id``. Вам нужно
+будет вручную создать столбец, который будет использоваться в качестве
+первичного ключа, и добавить его в объявление таблицы::
+
+ table('products');
+ $table
+ ->addColumn('id', 'integer', [
+ 'autoIncrement' => true,
+ 'limit' => 11
+ ])
+ ->addPrimaryKey('id')
+ ->addColumn('name', 'string')
+ ->addColumn('description', 'text')
+ ->create();
+ }
+ }
+
+По сравнению с предыдущим способом работы с первичным ключом, этот метод даёт
+вам возможность больше контролировать определение столбца первичного ключа:
+unsigned или not, limit, comment и т.д.
+
+Все запечённые миграции и моментальные снимки будут использовать этот новый
+способ, когда это необходимо.
+
+.. warning::
+
+ Работа с первичным ключом может выполняться только при выполнении операций
+ создания таблиц. Это связано с ограничениями для некоторых серверов баз данных,
+ поддерживаемых плагинами.
+
+Параметры сортировки
+--------------------
+
+Если вам нужно создать таблицу с другой сортировкой, чем стандартная по
+умолчанию, вы можете определить её с помощью метода ``table()`` в качестве
+опции::
+
+ table('categories', [
+ 'collation' => 'latin1_german1_ci'
+ ])
+ ->addColumn('title', 'string', [
+ 'default' => null,
+ 'limit' => 255,
+ 'null' => false,
+ ])
+ ->create();
+ }
+ }
+
+
+Обратите внимание, что это можно сделать только при создании таблицы:
+в настоящее время нет способа добавить столбец в существующую таблицу с
+другой сортировкой, чем таблица или база данных.
+В настоящее время только ``MySQL`` и ``SqlServer`` поддерживают этот
+ключ конфигурации.
+
+Обновление имени столбцов и использование объектов Table
+--------------------------------------------------------
+
+Если вы используете объект CakePHP ORM Table для управления значениями из
+своей базы данных вместе с переименованием или удалением столбца, убедитесь,
+что вы создали новый экземпляр объекта Table после вызова ``update()``.
+Реестр объектов таблицы очищается после вызова ``update()``, чтобы обновить
+схему, которая отражается и хранится в объекте Table при создании экземпляра.
+
+Миграции и развёртывание
+------------------------
+
+Если вы используете плагин при развёртывании приложения, обязательно очистите
+кэш ORM, чтобы он обновил метаданные столбца ваших таблиц. В противном случае
+вы можете столкнуться с ошибками в отношении столбцов, которые не существуют
+при выполнении операций над этими новыми столбцами.
+Ядро CakePHP включает :doc:`Schema Cache Shell `
+который вы можете использовать для выполнения этой операции::
+
+ $ bin/cake schema_cache clear
+
+Обязательно прочитайте раздел :doc:`Schema Cache Shell `,
+если вы хотите узнать больше об этой оболочке.
+
+Переименование таблицы
+----------------------
+
+Плагин даёт вам возможность переименовать таблицу, используя метод ``rename()``.
+В файле миграции вы можете сделать следующее::
+
+ public function up()
+ {
+ $this->table('old_table_name')
+ ->rename('new_table_name');
+ }
+
+Пропуск генерации файла ``schema.lock``
+---------------------------------------
+
+.. versionadded:: cakephp/migrations 1.6.5
+
+Для того, чтобы функция diff работала, каждый раз, когда вы переносите,
+откатываете или выпекаете снимок, создается файл **.Lock**, чтобы отслеживать
+состояние вашей схемы базы данных в любой момент времени. Вы можете пропустить
+создание этого файла, например, при развёртывании в рабочей среде, используя
+опцию ``--no-lock`` для вышеупомянутой команды::
+
+ $ bin/cake migrations migrate --no-lock
+
+ $ bin/cake migrations rollback --no-lock
+
+ $ bin/cake bake migration_snapshot MyMigration --no-lock
+
diff --git a/app/vendor/cakephp/migrations/phpcs.xml.dist b/app/vendor/cakephp/migrations/phpcs.xml.dist
deleted file mode 100644
index 561d55f65..000000000
--- a/app/vendor/cakephp/migrations/phpcs.xml.dist
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
- 0
-
- /tests/comparisons/*
-
diff --git a/app/vendor/cakephp/migrations/phpstan.neon b/app/vendor/cakephp/migrations/phpstan.neon
deleted file mode 100644
index 311dea8ea..000000000
--- a/app/vendor/cakephp/migrations/phpstan.neon
+++ /dev/null
@@ -1,7 +0,0 @@
-services:
- -
- class: Migrations\PHPStan\ShellPropertiesClassReflectionExtension
- tags:
- - phpstan.broker.propertiesClassReflectionExtension
-parameters:
- bootstrap: tests/PHPStan/bootstrap.phpstan.php
\ No newline at end of file
diff --git a/app/vendor/cakephp/migrations/psalm-baseline.xml b/app/vendor/cakephp/migrations/psalm-baseline.xml
new file mode 100644
index 000000000..8eb333857
--- /dev/null
+++ b/app/vendor/cakephp/migrations/psalm-baseline.xml
@@ -0,0 +1,36 @@
+
+
+
+
+ array|string
+
+
+
+
+ setInput
+
+
+
+
+ $name
+
+
+
+
+ new Filesystem()
+
+
+ find
+
+
+
+
+ $fieldType
+
+
+
+
+ string|null
+
+
+
diff --git a/app/vendor/cakephp/migrations/psalm.xml b/app/vendor/cakephp/migrations/psalm.xml
new file mode 100644
index 000000000..bbcc1b2b4
--- /dev/null
+++ b/app/vendor/cakephp/migrations/psalm.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/vendor/cakephp/migrations/src/AbstractMigration.php b/app/vendor/cakephp/migrations/src/AbstractMigration.php
index 623e8a293..a14f83445 100644
--- a/app/vendor/cakephp/migrations/src/AbstractMigration.php
+++ b/app/vendor/cakephp/migrations/src/AbstractMigration.php
@@ -1,4 +1,6 @@
input->getOption('plugin');
@@ -103,7 +103,8 @@ protected function runCall($seeder)
$config = $seedCommand->getConfig();
$seedPaths = $config->getSeedPaths();
- require_once(array_pop($seedPaths) . DS . $seeder . '.php');
+ require_once array_pop($seedPaths) . DS . $seeder . '.php';
+ /** @var \Phinx\Seed\SeedInterface $seeder */
$seeder = new $seeder();
$seeder->setOutput($this->getOutput());
$seeder->setAdapter($this->getAdapter());
@@ -114,11 +115,13 @@ protected function runCall($seeder)
/**
* Sets the InputInterface this Seed class is being used with.
*
- * @param InputInterface $input Input object.
- * @return void
+ * @param \Symfony\Component\Console\Input\InputInterface $input Input object.
+ * @return $this
*/
public function setInput(InputInterface $input)
{
$this->input = $input;
+
+ return $this;
}
}
diff --git a/app/vendor/cakephp/migrations/src/CakeAdapter.php b/app/vendor/cakephp/migrations/src/CakeAdapter.php
index 2b67a268a..565b85cda 100644
--- a/app/vendor/cakephp/migrations/src/CakeAdapter.php
+++ b/app/vendor/cakephp/migrations/src/CakeAdapter.php
@@ -1,4 +1,6 @@
adapter = $adapter;
+ if ($connection === null) {
+ throw new \InvalidArgumentException("The cake connection cannot be null");
+ }
+
+ parent::__construct($adapter);
+
$this->connection = $connection;
$pdo = $adapter->getConnection();
@@ -69,27 +62,6 @@ public function __construct(AdapterInterface $adapter, Connection $connection)
$connection->getDriver()->setConnection($pdo);
}
- /**
- * Gets the database PDO connection object.
- *
- * @return \PDO
- */
- public function getConnection()
- {
- return $this->adapter->getConnection();
- }
-
- /**
- * Gets the database PDO connection object.
- *
- * @param \PDO $connection Connection
- * @return AdapterInterface
- */
- public function setConnection($connection)
- {
- return $this->adapter->setConnection($connection);
- }
-
/**
* Gets the CakePHP Connection object.
*
@@ -101,680 +73,22 @@ public function getCakeConnection()
}
/**
- * Get all migrated version numbers.
- *
- * @return array
- */
- public function getVersions()
- {
- return $this->adapter->getVersions();
- }
-
- /**
- * Get all migration log entries, indexed by version number.
- *
- * @return array
- */
- public function getVersionLog()
- {
- return $this->adapter->getVersionLog();
- }
-
- /**
- * Set adapter configuration options.
- *
- * @param array $options Options array.
- * @return $this
- */
- public function setOptions(array $options)
- {
- return $this->adapter->setOptions($options);
- }
-
- /**
- * Get all adapter options.
- *
- * @return array
- */
- public function getOptions()
- {
- return $this->adapter->getOptions();
- }
-
- /**
- * Check if an option has been set.
- *
- * @param string $name Option name.
- * @return bool
- */
- public function hasOption($name)
- {
- return $this->adapter->hasOption($name);
- }
-
- /**
- * Get a single adapter option, or null if the option does not exist.
- *
- * @param string $name Option name.
- * @return mixed
- */
- public function getOption($name)
- {
- return $this->adapter->getOption($name);
- }
-
- /**
- * Sets the console output.
- *
- * @param OutputInterface $output Output
- * @return $this
- */
- public function setOutput(OutputInterface $output)
- {
- return $this->adapter->setOutput($output);
- }
-
- /**
- * Gets the console output.
- *
- * @return OutputInterface
- */
- public function getOutput()
- {
- return $this->adapter->getOutput();
- }
-
- /**
- * Sets the command start time
- *
- * @param int $time Start time.
- * @return $this
- */
- public function setCommandStartTime($time)
- {
- return $this->adapter->setCommandStartTime($time);
- }
-
- /**
- * Gets the command start time
- *
- * @return int
- */
- public function getCommandStartTime()
- {
- return $this->adapter->getCommandStartTime();
- }
-
- /**
- * Start timing a command.
- *
- * @return void
- */
- public function startCommandTimer()
- {
- $this->adapter->startCommandTimer();
- }
-
- /**
- * Stop timing the current command and write the elapsed time to the
- * output.
- *
- * @return void
- */
- public function endCommandTimer()
- {
- $this->adapter->endCommandTimer();
- }
-
- /**
- * Write a Phinx command to the output.
- *
- * @param string $command Command Name
- * @param array $args Command Args
- * @return void
- */
- public function writeCommand($command, $args = [])
- {
- $this->adapter->writeCommand($command, $args);
- }
-
- /**
- * Records a migration being run.
- *
- * @param MigrationInterface $migration Migration
- * @param string $direction Direction
- * @param int $startTime Start Time
- * @param int $endTime End Time
- * @return $this
- */
- public function migrated(MigrationInterface $migration, $direction, $startTime, $endTime)
- {
- return $this->adapter->migrated($migration, $direction, $startTime, $endTime);
- }
-
- /**
- * Does the schema table exist?
- *
- * @deprecated use hasTable instead.
- * @return bool
- */
- public function hasSchemaTable()
- {
- return $this->adapter->hasSchemaTable();
- }
-
- /**
- * Creates the schema table.
+ * Returns a new Query object
*
- * @return void
+ * @return \Cake\Database\Query
*/
- public function createSchemaTable()
+ public function getQueryBuilder()
{
- $this->adapter->createSchemaTable();
+ return $this->getCakeConnection()->newQuery();
}
/**
- * Returns the adapter type.
+ * Returns the adapter type name, for example mysql
*
* @return string
*/
public function getAdapterType()
{
- return $this->adapter->getAdapterType();
- }
-
- /**
- * Initializes the database connection.
- *
- * @throws \RuntimeException When the requested database driver is not installed.
- * @return void
- */
- public function connect()
- {
- $this->adapter->connect();
- }
-
- /**
- * Closes the database connection.
- *
- * @return void
- */
- public function disconnect()
- {
- $this->adapter->disconnect();
- }
-
- /**
- * Does the adapter support transactions?
- *
- * @return bool
- */
- public function hasTransactions()
- {
- return $this->adapter->hasTransactions();
- }
-
- /**
- * Begin a transaction.
- *
- * @return void
- */
- public function beginTransaction()
- {
- $this->connection->begin();
- }
-
- /**
- * Commit a transaction.
- *
- * @return void
- */
- public function commitTransaction()
- {
- $this->connection->commit();
- }
-
- /**
- * Rollback a transaction.
- *
- * @return void
- */
- public function rollbackTransaction()
- {
- $this->connection->rollback();
- }
-
- /**
- * Executes a SQL statement and returns the number of affected rows.
- *
- * @param string $sql SQL
- * @return int
- */
- public function execute($sql)
- {
- return $this->adapter->execute($sql);
- }
-
- /**
- * Executes a SQL statement and returns the result as an array.
- *
- * @param string $sql SQL
- * @return array
- */
- public function query($sql)
- {
- return $this->adapter->query($sql);
- }
-
- /**
- * Executes a query and returns only one row as an array.
- *
- * @param string $sql SQL
- * @return array
- */
- public function fetchRow($sql)
- {
- return $this->adapter->fetchRow($sql);
- }
-
- /**
- * Executes a query and returns an array of rows.
- *
- * @param string $sql SQL
- * @return array
- */
- public function fetchAll($sql)
- {
- return $this->adapter->fetchAll($sql);
- }
-
- /**
- * Inserts data into a table.
- *
- * @param \Phinx\Db\Table $table where to insert data
- * @param array $row Row array.
- * @return void
- */
- public function insert(PhinxTable $table, $row)
- {
- $this->adapter->insert($table, $row);
- }
-
- /**
- * Quotes a table name for use in a query.
- *
- * @param string $tableName Table Name
- * @return string
- */
- public function quoteTableName($tableName)
- {
- return $this->adapter->quoteTableName($tableName);
- }
-
- /**
- * Quotes a column name for use in a query.
- *
- * @param string $columnName Table Name
- * @return string
- */
- public function quoteColumnName($columnName)
- {
- return $this->adapter->quoteColumnName($columnName);
- }
-
- /**
- * Checks to see if a table exists.
- *
- * @param string $tableName Table Name
- * @return bool
- */
- public function hasTable($tableName)
- {
- return $this->adapter->hasTable($tableName);
- }
-
- /**
- * Creates the specified database table.
- *
- * @param \Phinx\Db\Table $table Table
- * @return void
- */
- public function createTable(PhinxTable $table)
- {
- $this->adapter->createTable($table);
- }
-
- /**
- * Renames the specified database table.
- *
- * @param string $tableName Table Name
- * @param string $newName New Name
- * @return void
- */
- public function renameTable($tableName, $newName)
- {
- $this->adapter->renameTable($tableName, $newName);
- }
-
- /**
- * Drops the specified database table.
- *
- * @param string $tableName Table Name
- * @return void
- */
- public function dropTable($tableName)
- {
- $this->adapter->dropTable($tableName);
- }
-
- /**
- * Truncates the specified table
- *
- * @param string $tableName Table name.
- * @return void
- */
- public function truncateTable($tableName)
- {
- $this->adapter->truncateTable($tableName);
- }
-
- /**
- * Returns table columns
- *
- * @param string $tableName Table Name
- * @return Column[]
- */
- public function getColumns($tableName)
- {
- return $this->adapter->getColumns($tableName);
- }
-
- /**
- * Checks to see if a column exists.
- *
- * @param string $tableName Table Name
- * @param string $columnName Column Name
- * @return bool
- */
- public function hasColumn($tableName, $columnName)
- {
- return $this->adapter->hasColumn($tableName, $columnName);
- }
-
- /**
- * Adds the specified column to a database table.
- *
- * @param \Phinx\Db\Table $table Table
- * @param \Phinx\Db\Table\Column $column Column
- * @return void
- */
- public function addColumn(PhinxTable $table, Column $column)
- {
- $this->adapter->addColumn($table, $column);
- }
-
- /**
- * Renames the specified column.
- *
- * @param string $tableName Table Name
- * @param string $columnName Column Name
- * @param string $newColumnName New Column Name
- * @return void
- */
- public function renameColumn($tableName, $columnName, $newColumnName)
- {
- $this->adapter->renameColumn($tableName, $columnName, $newColumnName);
- }
-
- /**
- * Change a table column type.
- *
- * @param string $tableName Table Name
- * @param string $columnName Column Name
- * @param \Phinx\Db\Table\Column $newColumn New Column
- * @return \Phinx\Db\Table
- */
- public function changeColumn($tableName, $columnName, Column $newColumn)
- {
- return $this->adapter->changeColumn($tableName, $columnName, $newColumn);
- }
-
- /**
- * Drops the specified column.
- *
- * @param string $tableName Table Name
- * @param string $columnName Column Name
- * @return void
- */
- public function dropColumn($tableName, $columnName)
- {
- $this->adapter->dropColumn($tableName, $columnName);
- }
-
- /**
- * Checks to see if an index exists.
- *
- * @param string $tableName Table Name
- * @param mixed $columns Column(s)
- * @return bool
- */
- public function hasIndex($tableName, $columns)
- {
- return $this->adapter->hasIndex($tableName, $columns);
- }
-
- /**
- * Checks to see if an index specified by name exists.
- *
- * @param string $tableName Table name.
- * @param string $indexName Index name.
- * @return bool
- */
- public function hasIndexByName($tableName, $indexName)
- {
- return $this->adapter->hasIndexByName($tableName, $indexName);
- }
-
- /**
- * Adds the specified index to a database table.
- *
- * @param \Phinx\Db\Table $table Table
- * @param Index $index Index
- * @return void
- */
- public function addIndex(PhinxTable $table, Index $index)
- {
- $this->adapter->addIndex($table, $index);
- }
-
- /**
- * Drops the specified index from a database table.
- *
- * @param string $tableName Table name.
- * @param mixed $columns Column(s)
- * @return void
- */
- public function dropIndex($tableName, $columns)
- {
- $this->adapter->dropIndex($tableName, $columns);
- }
-
- /**
- * Drops the index specified by name from a database table.
- *
- * @param string $tableName Table name.
- * @param string $indexName Index name.
- * @return void
- */
- public function dropIndexByName($tableName, $indexName)
- {
- $this->adapter->dropIndexByName($tableName, $indexName);
- }
-
- /**
- * Checks to see if a foreign key exists.
- *
- * @param string $tableName Table name.
- * @param string[] $columns Column(s)
- * @param string|null $constraint Constraint name
- * @return bool
- */
- public function hasForeignKey($tableName, $columns, $constraint = null)
- {
- return $this->adapter->hasForeignKey($tableName, $columns, $constraint);
- }
-
- /**
- * Adds the specified foreign key to a database table.
- *
- * @param \Phinx\Db\Table $table Table object.
- * @param \Phinx\Db\Table\ForeignKey $foreignKey Foreign key object.
- * @return void
- */
- public function addForeignKey(PhinxTable $table, ForeignKey $foreignKey)
- {
- $this->adapter->addForeignKey($table, $foreignKey);
- }
-
- /**
- * Drops the specified foreign key from a database table.
- * If the adapter property is an instance of the \Phinx\Db\Adapter\SQLiteAdapter,
- * a specific method will be called. The original one from Phinx contains a bug
- * that can drop a table in certain conditions.
- *
- * @param string $tableName Table name.
- * @param string[] $columns Column(s)
- * @param string|null $constraint Constraint name
- * @return void
- */
- public function dropForeignKey($tableName, $columns, $constraint = null)
- {
- $this->adapter->dropForeignKey($tableName, $columns, $constraint);
- }
-
- /**
- * Returns an array of the supported Phinx column types.
- *
- * @return array
- */
- public function getColumnTypes()
- {
- return $this->adapter->getColumnTypes();
- }
-
- /**
- * Checks that the given column is of a supported type.
- *
- * @param \Phinx\Db\Table\Column $column Column object.
- * @return bool
- */
- public function isValidColumnType(Column $column)
- {
- return $this->adapter->isValidColumnType($column);
- }
-
- /**
- * Converts the Phinx logical type to the adapter's SQL type.
- *
- * @param string $type Type name.
- * @param int|null $limit Limit.
- * @return string
- */
- public function getSqlType($type, $limit = null)
- {
- return $this->adapter->getSqlType($type, $limit);
- }
-
- /**
- * Creates a new database.
- *
- * @param string $name Database Name
- * @param array $options Options
- * @return void
- */
- public function createDatabase($name, $options = [])
- {
- $this->adapter->createDatabase($name, $options);
- }
-
- /**
- * Checks to see if a database exists.
- *
- * @param string $name Database Name
- * @return bool
- */
- public function hasDatabase($name)
- {
- return $this->adapter->hasDatabase($name);
- }
-
- /**
- * Drops the specified database.
- *
- * @param string $name Database Name
- * @return void
- */
- public function dropDatabase($name)
- {
- $this->adapter->dropDatabase($name);
- }
-
- /**
- * Cast a value to a boolean appropriate for the adapter.
- *
- * @param mixed $value The value to be cast
- *
- * @return mixed
- */
- public function castToBool($value)
- {
- return $this->adapter->castToBool($value);
- }
-
- /**
- * Sets the console input.
- *
- * @param InputInterface $input Input
- * @return $this
- */
- public function setInput(InputInterface $input)
- {
- $this->adapter->setInput($input);
-
- return $this;
- }
-
- /**
- * Gets the console input.
- *
- * @return InputInterface
- */
- public function getInput()
- {
- return $this->adapter->getInput();
- }
-
- /**
- * Toggle a migration breakpoint.
- *
- * @param MigrationInterface $migration Migration instance.
- *
- * @return $this
- */
- public function toggleBreakpoint(MigrationInterface $migration)
- {
- $this->adapter->toggleBreakpoint($migration);
-
- return $this;
- }
-
- /**
- * Reset all migration breakpoints.
- *
- * @return int The number of breakpoints reset
- */
- public function resetAllBreakpoints()
- {
- return $this->adapter->resetAllBreakpoints();
+ return $this->getAdapter()->getAdapterType();
}
}
diff --git a/app/vendor/cakephp/migrations/src/CakeManager.php b/app/vendor/cakephp/migrations/src/CakeManager.php
index 367ccfc8b..1341cfbea 100644
--- a/app/vendor/cakephp/migrations/src/CakeManager.php
+++ b/app/vendor/cakephp/migrations/src/CakeManager.php
@@ -1,4 +1,6 @@
getMigrations())) {
+ if (count($this->getMigrations('default'))) {
$env = $this->getEnvironment($environment);
$versions = $env->getVersionLog();
$this->maxNameLength = $versions ? max(array_map(function ($version) {
- return strlen($version['migration_name']);
+ return strlen((string)$version['migration_name']);
}, $versions)) : 0;
- foreach ($this->getMigrations() as $migration) {
+ foreach ($this->getMigrations('default') as $migration) {
if (array_key_exists($migration->getVersion(), $versions)) {
$status = 'up';
unset($versions[$migration->getVersion()]);
@@ -80,7 +84,7 @@ public function printStatus($environment, $format = null)
$migrationParams = [
'status' => $status,
'id' => $migration->getVersion(),
- 'name' => $migration->getName()
+ 'name' => $migration->getName(),
];
$migrations[$version] = $migrationParams;
@@ -91,13 +95,13 @@ public function printStatus($environment, $format = null)
$migrationParams = [
'status' => 'up',
'id' => $version,
- 'name' => $missing['migration_name']
+ 'name' => $missing['migration_name'],
];
if (!$isJson) {
- $migrationParams = array_merge($migrationParams, [
- 'missing' => true
- ]);
+ $migrationParams = [
+ 'missing' => true,
+ ] + $migrationParams;
}
$migrations[$version] = $migrationParams;
@@ -115,11 +119,11 @@ public function printStatus($environment, $format = null)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
- public function migrateToDateTime($environment, \DateTime $dateTime)
+ public function migrateToDateTime($environment, \DateTime $dateTime, $fake = false)
{
- $versions = array_keys($this->getMigrations());
+ $versions = array_keys($this->getMigrations('default'));
$dateString = $dateTime->format('Ymdhis');
$versionToMigrate = null;
foreach ($versions as $version) {
@@ -139,13 +143,13 @@ public function migrateToDateTime($environment, \DateTime $dateTime)
$this->getOutput()->writeln(
'Migrating to version ' . $versionToMigrate
);
- $this->migrate($environment, $versionToMigrate);
+ $this->migrate($environment, $versionToMigrate, $fake);
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
- public function rollbackToDateTime($environment, \DateTime $dateTime, $force = false)
+ public function rollbackToDateTime(string $environment, \DateTime $dateTime, bool $force = false): void
{
$env = $this->getEnvironment($environment);
$versions = $env->getVersions();
@@ -215,7 +219,7 @@ public function markMigrated($version, $path)
$migrationFile = $migrationFile[0];
$className = $this->getMigrationClassName($migrationFile);
require_once $migrationFile;
- $Migration = new $className($version);
+ $Migration = new $className('default', $version);
$time = date('Y-m-d H:i:s', time());
@@ -235,16 +239,17 @@ public function markMigrated($version, $path)
*/
public function getVersionsToMark($input)
{
- $migrations = $this->getMigrations();
+ $migrations = $this->getMigrations('default');
$versions = array_keys($migrations);
$versionArg = $input->getArgument('version');
$targetArg = $input->getOption('target');
- $hasAllVersion = in_array($versionArg, ['all', '*']);
+ $hasAllVersion = in_array($versionArg, ['all', '*'], true);
if ((empty($versionArg) && empty($targetArg)) || $hasAllVersion) {
return $versions;
}
+ /** @var string $version */
$version = $targetArg ?: $versionArg;
if ($input->getOption('only') || !empty($versionArg)) {
@@ -276,7 +281,7 @@ public function getVersionsToMark($input)
* the command output
* @return void
*/
- public function markVersionsAsMigrated($path, $versions, $output)
+ public function markVersionsAsMigrated($path, array $versions, $output)
{
$adapter = $this->getEnvironment('default')->getAdapter();
@@ -328,6 +333,7 @@ protected function getMigrationClassName($path)
$class = ucwords($class);
$class = str_replace(' ', '', $class);
if (strpos($class, '.') !== false) {
+ /** @psalm-suppress PossiblyFalseArgument */
$class = substr($class, 0, strpos($class, '.'));
}
@@ -338,25 +344,30 @@ protected function getMigrationClassName($path)
* Sets the InputInterface the Manager is dealing with for the current shell call
*
* @param \Symfony\Component\Console\Input\InputInterface $input Instance of InputInterface
- * @return void
+ * @return $this
*/
public function setInput(InputInterface $input)
{
$this->input = $input;
+
+ return $this;
}
/**
+ * Gets an array of database seeders.
+ *
* Overload the basic behavior to add an instance of the InputInterface the shell call is
* using in order to gives the ability to the AbstractSeed::call() method to propagate options
* to the other MigrationsDispatcher it is generating.
*
- * {@inheritdoc}
+ * @throws \InvalidArgumentException
+ * @return \Phinx\Seed\AbstractSeed[]
*/
public function getSeeds()
{
parent::getSeeds();
if (empty($this->seeds)) {
- return $this->seeds;
+ return [];
}
foreach ($this->seeds as $class => $instance) {
diff --git a/app/vendor/cakephp/migrations/src/Command/BakeMigrationCommand.php b/app/vendor/cakephp/migrations/src/Command/BakeMigrationCommand.php
new file mode 100644
index 000000000..a8ca32ac4
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/BakeMigrationCommand.php
@@ -0,0 +1,148 @@
+on('Bake.initialize', function (Event $event) {
+ $event->getSubject()->loadHelper('Migrations.Migration');
+ });
+ $this->_name = $name;
+
+ parent::bake($name, $args, $io);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function template(): string
+ {
+ return 'Migrations.config/skeleton';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function templateData(Arguments $arguments): array
+ {
+ $className = $this->_name;
+ $namespace = Configure::read('App.namespace');
+ $pluginPath = '';
+ if ($this->plugin) {
+ $namespace = $this->_pluginNamespace($this->plugin);
+ $pluginPath = $this->plugin . '.';
+ }
+
+ $action = $this->detectAction($className);
+
+ if (empty($action)) {
+ return [
+ 'plugin' => $this->plugin,
+ 'pluginPath' => $pluginPath,
+ 'namespace' => $namespace,
+ 'tables' => [],
+ 'action' => null,
+ 'name' => $className,
+ ];
+ }
+
+ $arguments = $arguments->getArguments();
+ unset($arguments[0]);
+ $columnParser = new ColumnParser();
+ $fields = $columnParser->parseFields($arguments);
+ $indexes = $columnParser->parseIndexes($arguments);
+ $primaryKey = $columnParser->parsePrimaryKey($arguments);
+
+ if (in_array($action[0], ['alter_table', 'add_field'], true) && !empty($primaryKey)) {
+ $this->io->abort('Adding a primary key to an already existing table is not supported.');
+ }
+
+ [$action, $table] = $action;
+
+ return [
+ 'plugin' => $this->plugin,
+ 'pluginPath' => $pluginPath,
+ 'namespace' => $namespace,
+ 'tables' => [$table],
+ 'action' => $action,
+ 'columns' => [
+ 'fields' => $fields,
+ 'indexes' => $indexes,
+ 'primaryKey' => $primaryKey,
+ ],
+ 'name' => $className,
+ ];
+ }
+
+ /**
+ * Detects the action and table from the name of a migration
+ *
+ * @param string $name Name of migration
+ * @return array
+ **/
+ public function detectAction($name)
+ {
+ if (preg_match('/^(Create|Drop)(.*)/', $name, $matches)) {
+ $action = strtolower($matches[1]) . '_table';
+ $table = Inflector::underscore($matches[2]);
+ } elseif (preg_match('/^(Add).+?(?:To)(.*)/', $name, $matches)) {
+ $action = 'add_field';
+ $table = Inflector::underscore($matches[2]);
+ } elseif (preg_match('/^(Remove).+?(?:From)(.*)/', $name, $matches)) {
+ $action = 'drop_field';
+ $table = Inflector::underscore($matches[2]);
+ } elseif (preg_match('/^(Alter).+?(?:On)(.*)/', $name, $matches)) {
+ $action = 'alter_field';
+ $table = Inflector::underscore($matches[2]);
+ } elseif (preg_match('/^(Alter)(.*)/', $name, $matches)) {
+ $action = 'alter_table';
+ $table = Inflector::underscore($matches[2]);
+ } else {
+ return [];
+ }
+
+ return [$action, $table];
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/BakeMigrationDiffCommand.php b/app/vendor/cakephp/migrations/src/Command/BakeMigrationDiffCommand.php
new file mode 100644
index 000000000..c6cce9d5b
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/BakeMigrationDiffCommand.php
@@ -0,0 +1,584 @@
+setup($args);
+
+ if (!$this->checkSync()) {
+ $io->abort('Your migrations history is not in sync with your migrations files. ' .
+ 'Make sure all your migrations have been migrated before baking a diff.');
+ }
+
+ if (empty($this->migrationsFiles) && empty($this->migratedItems)) {
+ $this->bakeSnapshot($name, $args, $io);
+ }
+
+ $collection = $this->getCollection($this->connection);
+ EventManager::instance()->on('Bake.initialize', function (Event $event) use ($collection) {
+ $event->getSubject()->loadHelper('Migrations.Migration', [
+ 'collection' => $collection,
+ ]);
+ });
+
+ parent::bake($name, $args, $io);
+ }
+
+ /**
+ * Sets up everything the baking process needs
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @return void
+ */
+ protected function setup(Arguments $args)
+ {
+ $this->migrationsPath = $this->getPath($args);
+ $this->migrationsFiles = glob($this->migrationsPath . '*.php');
+ $this->phinxTable = $this->getPhinxTable($this->plugin);
+
+ $connection = ConnectionManager::get($this->connection);
+ $this->tables = $connection->getSchemaCollection()->listTables();
+ $tableExists = in_array($this->phinxTable, $this->tables, true);
+
+ $migratedItems = [];
+ if ($tableExists) {
+ $query = $connection->newQuery();
+ /** @var array $migratedItems */
+ $migratedItems = $query
+ ->select(['version'])
+ ->from($this->phinxTable)
+ ->order(['version DESC'])
+ ->execute()->fetchAll('assoc');
+ }
+
+ $this->migratedItems = $migratedItems;
+ }
+
+ /**
+ * Get a collection from a database.
+ *
+ * @param string $connection Database connection name.
+ * @return \Cake\Database\Schema\Collection
+ */
+ public function getCollection($connection)
+ {
+ $connection = ConnectionManager::get($connection);
+
+ return $connection->getSchemaCollection();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function templateData(Arguments $arguments): array
+ {
+ $this->dumpSchema = $this->getDumpSchema($arguments);
+ $this->currentSchema = $this->getCurrentSchema();
+ $this->commonTables = array_intersect_key($this->currentSchema, $this->dumpSchema);
+
+ $this->calculateDiff();
+
+ return [
+ 'data' => $this->templateData,
+ 'dumpSchema' => $this->dumpSchema,
+ 'currentSchema' => $this->currentSchema,
+ ];
+ }
+
+ /**
+ * This methods runs the various methods needed to calculate a diff between the current
+ * state of the database and the schema dump file.
+ *
+ * @return void
+ */
+ protected function calculateDiff()
+ {
+ $this->getConstraints();
+ $this->getIndexes();
+ $this->getColumns();
+ $this->getTables();
+ }
+
+ /**
+ * Calculate the diff between the current state of the database and the schema dump
+ * by returning an array containing the full \Cake\Database\Schema\TableSchema definitions
+ * of tables to be created and removed in the diff file.
+ *
+ * The method directly sets the diff in a property of the class.
+ *
+ * @return void
+ */
+ protected function getTables()
+ {
+ $this->templateData['fullTables'] = [
+ 'add' => array_diff_key($this->currentSchema, $this->dumpSchema),
+ 'remove' => array_diff_key($this->dumpSchema, $this->currentSchema),
+ ];
+ }
+
+ /**
+ * Calculate the diff between columns in existing tables.
+ * This will look for columns addition, columns removal and changes in columns metadata
+ * such as change of types or property such as length.
+ *
+ * Note that the method is not able to detect columns name change.
+ * The method directly sets the diff in a property of the class.
+ *
+ * @return void
+ */
+ protected function getColumns()
+ {
+ foreach ($this->commonTables as $table => $currentSchema) {
+ $currentColumns = $currentSchema->columns();
+ $oldColumns = $this->dumpSchema[$table]->columns();
+
+ // brand new columns
+ $addedColumns = array_diff($currentColumns, $oldColumns);
+ foreach ($addedColumns as $columnName) {
+ $column = $currentSchema->getColumn($columnName);
+ /** @var int $key */
+ $key = array_search($columnName, $currentColumns);
+ if ($key > 0) {
+ $column['after'] = $currentColumns[$key - 1];
+ }
+ if (isset($column['unsigned'])) {
+ $column['signed'] = !$column['unsigned'];
+ unset($column['unsigned']);
+ }
+ $this->templateData[$table]['columns']['add'][$columnName] = $column;
+ }
+
+ // changes in columns meta-data
+ foreach ($currentColumns as $columnName) {
+ $column = $currentSchema->getColumn($columnName);
+ $oldColumn = $this->dumpSchema[$table]->getColumn($columnName);
+ unset($column['collate']);
+ unset($column['fixed']);
+ unset($oldColumn['collate']);
+ unset($oldColumn['fixed']);
+
+ if (
+ in_array($columnName, $oldColumns, true) &&
+ $column !== $oldColumn
+ ) {
+ $changedAttributes = array_diff_assoc($column, $oldColumn);
+
+ foreach (['type', 'length', 'null', 'default'] as $attribute) {
+ $phinxAttributeName = $attribute;
+ if ($attribute === 'length') {
+ $phinxAttributeName = 'limit';
+ }
+ if (!isset($changedAttributes[$phinxAttributeName])) {
+ $changedAttributes[$phinxAttributeName] = $column[$attribute];
+ }
+ }
+
+ if (isset($changedAttributes['unsigned'])) {
+ $changedAttributes['signed'] = !$changedAttributes['unsigned'];
+ unset($changedAttributes['unsigned']);
+ } else {
+ // badish hack
+ if (isset($column['unsigned']) && $column['unsigned'] === true) {
+ $changedAttributes['signed'] = false;
+ }
+ }
+
+ if (isset($changedAttributes['length'])) {
+ if (!isset($changedAttributes['limit'])) {
+ $changedAttributes['limit'] = $changedAttributes['length'];
+ }
+
+ unset($changedAttributes['length']);
+ }
+
+ $this->templateData[$table]['columns']['changed'][$columnName] = $changedAttributes;
+ }
+ }
+
+ // columns deletion
+ if (!isset($this->templateData[$table]['columns']['remove'])) {
+ $this->templateData[$table]['columns']['remove'] = [];
+ }
+ $removedColumns = array_diff($oldColumns, $currentColumns);
+ if (!empty($removedColumns)) {
+ foreach ($removedColumns as $columnName) {
+ $column = $this->dumpSchema[$table]->getColumn($columnName);
+ /** @var int $key */
+ $key = array_search($columnName, $oldColumns);
+ if ($key > 0) {
+ $column['after'] = $oldColumns[$key - 1];
+ }
+ $this->templateData[$table]['columns']['remove'][$columnName] = $column;
+ }
+ }
+ }
+ }
+
+ /**
+ * Calculate the diff between contraints in existing tables.
+ * This will look for contraints addition, contraints removal and changes in contraints metadata
+ * such as change of referenced columns if the old constraints and the new one have the same name.
+ *
+ * The method directly sets the diff in a property of the class.
+ *
+ * @return void
+ */
+ protected function getConstraints()
+ {
+ foreach ($this->commonTables as $table => $currentSchema) {
+ $currentConstraints = $currentSchema->constraints();
+ $oldConstraints = $this->dumpSchema[$table]->constraints();
+
+ // brand new constraints
+ $addedConstraints = array_diff($currentConstraints, $oldConstraints);
+ foreach ($addedConstraints as $constraintName) {
+ $this->templateData[$table]['constraints']['add'][$constraintName] =
+ $currentSchema->getConstraint($constraintName);
+ $constraint = $currentSchema->getConstraint($constraintName);
+ if ($constraint['type'] === TableSchema::CONSTRAINT_FOREIGN) {
+ $this->templateData[$table]['constraints']['add'][$constraintName] = $constraint;
+ } else {
+ $this->templateData[$table]['indexes']['add'][$constraintName] = $constraint;
+ }
+ }
+
+ // constraints having the same name between new and old schema
+ // if present in both, check if they are the same : if not, remove the old one and add the new one
+ foreach ($currentConstraints as $constraintName) {
+ $constraint = $currentSchema->getConstraint($constraintName);
+
+ if (
+ in_array($constraintName, $oldConstraints, true) &&
+ $constraint !== $this->dumpSchema[$table]->getConstraint($constraintName)
+ ) {
+ $this->templateData[$table]['constraints']['remove'][$constraintName] =
+ $this->dumpSchema[$table]->getConstraint($constraintName);
+ $this->templateData[$table]['constraints']['add'][$constraintName] =
+ $constraint;
+ }
+ }
+
+ // removed constraints
+ $removedConstraints = array_diff($oldConstraints, $currentConstraints);
+ foreach ($removedConstraints as $constraintName) {
+ $constraint = $this->dumpSchema[$table]->getConstraint($constraintName);
+ if ($constraint['type'] === TableSchema::CONSTRAINT_FOREIGN) {
+ $this->templateData[$table]['constraints']['remove'][$constraintName] = $constraint;
+ } else {
+ $this->templateData[$table]['indexes']['remove'][$constraintName] = $constraint;
+ }
+ }
+ }
+ }
+
+ /**
+ * Calculate the diff between indexes in existing tables.
+ * This will look for indexes addition, indexes removal and changes in indexes metadata
+ * such as change of referenced columns if the old indexes and the new one have the same name.
+ *
+ * The method directly sets the diff in a property of the class.
+ *
+ * @return void
+ */
+ protected function getIndexes()
+ {
+ foreach ($this->commonTables as $table => $currentSchema) {
+ $currentIndexes = $currentSchema->indexes();
+ $oldIndexes = $this->dumpSchema[$table]->indexes();
+ sort($currentIndexes);
+ sort($oldIndexes);
+
+ // brand new indexes
+ $addedIndexes = array_diff($currentIndexes, $oldIndexes);
+ foreach ($addedIndexes as $indexName) {
+ $this->templateData[$table]['indexes']['add'][$indexName] = $currentSchema->getIndex($indexName);
+ }
+
+ // indexes having the same name between new and old schema
+ // if present in both, check if they are the same : if not, remove the old one and add the new one
+ foreach ($currentIndexes as $indexName) {
+ $index = $currentSchema->getIndex($indexName);
+
+ if (
+ in_array($indexName, $oldIndexes, true) &&
+ $index !== $this->dumpSchema[$table]->getIndex($indexName)
+ ) {
+ $this->templateData[$table]['indexes']['remove'][$indexName] =
+ $this->dumpSchema[$table]->getIndex($indexName);
+ $this->templateData[$table]['indexes']['add'][$indexName] = $index;
+ }
+ }
+
+ // indexes deletion
+ if (!isset($this->templateData[$table]['indexes']['remove'])) {
+ $this->templateData[$table]['indexes']['remove'] = [];
+ }
+
+ $removedIndexes = array_diff($oldIndexes, $currentIndexes);
+ $parts = [];
+ if (!empty($removedIndexes)) {
+ foreach ($removedIndexes as $index) {
+ $parts[$index] = $this->dumpSchema[$table]->getIndex($index);
+ }
+ }
+ $this->templateData[$table]['indexes']['remove'] = array_merge(
+ $this->templateData[$table]['indexes']['remove'],
+ $parts
+ );
+ }
+ }
+
+ /**
+ * Checks that the migrations history is in sync with the migrations files
+ *
+ * @return bool Whether migrations history is sync or not
+ */
+ protected function checkSync()
+ {
+ if (empty($this->migrationsFiles) && empty($this->migratedItems)) {
+ return true;
+ }
+
+ if (!empty($this->migratedItems)) {
+ $lastVersion = $this->migratedItems[0]['version'];
+ $lastFile = end($this->migrationsFiles);
+
+ return (bool)strpos($lastFile, (string)$lastVersion);
+ }
+
+ return false;
+ }
+
+ /**
+ * Fallback method called to bake a snapshot when the phinx log history is empty and
+ * there are no migration files.
+ *
+ * @param string $name Name.
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return int|null Value of the snapshot baking dispatch process
+ */
+ protected function bakeSnapshot($name, Arguments $args, ConsoleIo $io)
+ {
+ $io->out('Your migrations history is empty and you do not have any migrations files.');
+ $io->out('Falling back to baking a snapshot...');
+ $newArgs = [];
+ $newArgs[] = $name;
+
+ if ($args->getOption('connection')) {
+ $newArgs[] = '-c';
+ $newArgs[] = $args->getOption('connection');
+ }
+
+ if ($args->getOption('plugin')) {
+ $newArgs[] = '-p';
+ $newArgs[] = $args->getOption('plugin');
+ }
+
+ $exitCode = $this->executeCommand(BakeMigrationSnapshotCommand::class, $newArgs, $io);
+
+ if ($exitCode === 1) {
+ $io->abort('Something went wrong during the snapshot baking. Please try again.');
+ }
+
+ return $exitCode;
+ }
+
+ /**
+ * Fetch the correct schema dump based on the arguments and options passed to the shell call
+ * and returns it as an array
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @return array Full database schema : the key is the name of the table and the value is
+ * an instance of \Cake\Database\Schema\Table.
+ */
+ protected function getDumpSchema(Arguments $args)
+ {
+ $inputArgs = [];
+
+ $connectionName = 'default';
+ if (!empty($args->getOption('connection'))) {
+ $connectionName = $inputArgs['--connection'] = $args->getOption('connection');
+ }
+ if (!empty($args->getOption('plugin'))) {
+ $inputArgs['--plugin'] = $args->getOption('plugin');
+ }
+
+ $className = Dump::class;
+ $definition = (new $className())->getDefinition();
+
+ $input = new ArrayInput($inputArgs, $definition);
+ $path = $this->getOperationsPath($input) . DS . 'schema-dump-' . $connectionName . '.lock';
+
+ if (!file_exists($path)) {
+ $msg = 'Unable to retrieve the schema dump file. You can create a dump file using ' .
+ 'the `cake migrations dump` command';
+ $this->io->abort($msg);
+ }
+
+ return unserialize(file_get_contents($path));
+ }
+
+ /**
+ * Reflects the current database schema.
+ *
+ * @return array Full database schema : the key is the name of the table and the value is
+ * an instance of \Cake\Database\Schema\Table.
+ */
+ protected function getCurrentSchema()
+ {
+ $schema = [];
+
+ if (empty($this->tables)) {
+ return $schema;
+ }
+
+ $connection = ConnectionManager::get($this->connection);
+ if (method_exists($connection, 'cacheMetadata')) {
+ $connection->cacheMetadata(false);
+ }
+ $collection = $connection->getSchemaCollection();
+ foreach ($this->tables as $table) {
+ if (preg_match("/^.*phinxlog$/", $table) === 1) {
+ continue;
+ }
+
+ $schema[$table] = $collection->describe($table);
+ }
+
+ return $schema;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function template(): string
+ {
+ return 'Migrations.config/diff';
+ }
+
+ /**
+ * Gets the option parser instance and configures it.
+ *
+ * @return \Cake\Console\ConsoleOptionParser
+ */
+ public function getOptionParser(): ConsoleOptionParser
+ {
+ $parser = parent::getOptionParser();
+
+ $parser->addArgument('name', [
+ 'help' => 'Name of the migration to bake. Can use Plugin.name to bake migration files into plugins.',
+ 'required' => true,
+ ]);
+
+ return $parser;
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/BakeMigrationSnapshotCommand.php b/app/vendor/cakephp/migrations/src/Command/BakeMigrationSnapshotCommand.php
new file mode 100644
index 000000000..0defa204c
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/BakeMigrationSnapshotCommand.php
@@ -0,0 +1,171 @@
+getCollection($this->connection);
+ EventManager::instance()->on('Bake.initialize', function (Event $event) use ($collection) {
+ $event->getSubject()->loadHelper('Migrations.Migration', [
+ 'collection' => $collection,
+ ]);
+ });
+ $this->_name = $name;
+
+ parent::bake($name, $args, $io);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function template(): string
+ {
+ return 'Migrations.config/snapshot';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function templateData(Arguments $arguments): array
+ {
+ $namespace = Configure::read('App.namespace');
+ $pluginPath = '';
+ if ($this->plugin) {
+ $namespace = $this->_pluginNamespace($this->plugin);
+ $pluginPath = $this->plugin . '.';
+ }
+
+ $collection = $this->getCollection($this->connection);
+ $options = [
+ 'require-table' => $arguments->getOption('require-table'),
+ 'plugin' => $this->plugin,
+ ];
+ $tables = $this->getTablesToBake($collection, $options);
+
+ sort($tables, SORT_NATURAL);
+
+ $tables = array_combine($tables, $tables);
+
+ $autoId = true;
+ if ($arguments->hasOption('disable-autoid')) {
+ $autoId = !$arguments->getOption('disable-autoid');
+ }
+
+ return [
+ 'plugin' => $this->plugin,
+ 'pluginPath' => $pluginPath,
+ 'namespace' => $namespace,
+ 'collection' => $collection,
+ 'tables' => $tables,
+ 'action' => 'create_table',
+ 'name' => $this->_name,
+ 'autoId' => $autoId,
+ ];
+ }
+
+ /**
+ * Get a collection from a database
+ *
+ * @param string $connection Database connection name.
+ * @return \Cake\Database\Schema\Collection
+ */
+ public function getCollection($connection)
+ {
+ $connection = ConnectionManager::get($connection);
+
+ return $connection->getSchemaCollection();
+ }
+
+ /**
+ * To check if a Table Model is to be added in the migration file
+ *
+ * @param string $tableName Table name in underscore case.
+ * @param string|null $pluginName Plugin name if exists.
+ * @deprecated Will be removed in the next version
+ * @return bool True if the model is to be added.
+ */
+ public function tableToAdd($tableName, $pluginName = null)
+ {
+ return true;
+ }
+
+ /**
+ * Gets the option parser instance and configures it.
+ *
+ * @return \Cake\Console\ConsoleOptionParser
+ */
+ public function getOptionParser(): ConsoleOptionParser
+ {
+ $parser = parent::getOptionParser();
+
+ $parser->setDescription(
+ 'Bake migration snapshot class.'
+ )->addArgument('name', [
+ 'help' => 'Name of the migration to bake. Can use Plugin.name to bake migration files into plugins.',
+ 'required' => true,
+ ])
+ ->addOption('require-table', [
+ 'boolean' => true,
+ 'default' => false,
+ 'help' => 'If require-table is set to true, check also that the table class exists.',
+ ])->addOption('disable-autoid', [
+ 'boolean' => true,
+ 'default' => false,
+ 'help' => 'Disable phinx behavior of automatically adding an id field.',
+ ])
+ ->addOption('no-lock', [
+ 'help' => 'If present, no lock file will be generated after baking',
+ 'boolean' => true,
+ ]);
+
+ return $parser;
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/BakeSeedCommand.php b/app/vendor/cakephp/migrations/src/Command/BakeSeedCommand.php
new file mode 100644
index 000000000..498092e21
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/BakeSeedCommand.php
@@ -0,0 +1,258 @@
+pathFragment;
+ if (isset($this->plugin)) {
+ $path = $this->_pluginPath($this->plugin) . $this->pathFragment;
+ }
+
+ return str_replace('/', DS, $path);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function template(): string
+ {
+ return 'Migrations.Seed/seed';
+ }
+
+ /**
+ * Get template data.
+ *
+ * @param \Cake\Console\Arguments $arguments The arguments for the command
+ * @return array
+ * @phpstan-return array
+ */
+ public function templateData(Arguments $arguments): array
+ {
+ $namespace = Configure::read('App.namespace');
+ if ($this->plugin) {
+ $namespace = $this->_pluginNamespace($this->plugin);
+ }
+
+ /** @psalm-suppress PossiblyNullArgument */
+ $table = Inflector::tableize($arguments->getArgumentAt(0));
+ if ($arguments->hasOption('table')) {
+ /** @var string $table */
+ $table = $arguments->getOption('table');
+ }
+
+ $records = false;
+ if ($arguments->getOption('data')) {
+ $limit = (int)$arguments->getOption('limit');
+
+ /** @var string $fields */
+ $fields = $arguments->getOption('fields') ?: '*';
+ if ($fields !== '*') {
+ $fields = explode(',', $fields);
+ }
+
+ $connection = ConnectionManager::get($this->connection);
+
+ $query = $connection->newQuery()
+ ->from($table)
+ ->select($fields);
+
+ if ($limit) {
+ $query->limit($limit);
+ }
+
+ /** @var array $records */
+ $records = $connection->execute($query->sql())->fetchAll('assoc');
+ $records = $this->prettifyArray($records);
+ }
+
+ return [
+ 'className' => $this->_name,
+ 'namespace' => $namespace,
+ 'records' => $records,
+ 'table' => $table,
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function bake(string $name, Arguments $args, ConsoleIo $io): void
+ {
+ $newArgs = new Arguments(
+ $args->getArguments(),
+ ['no-test' => true] + $args->getOptions(),
+ ['name']
+ );
+ $this->_name = $name;
+ parent::bake($name, $newArgs, $io);
+ }
+
+ /**
+ * Gets the option parser instance and configures it.
+ *
+ * @param \Cake\Console\ConsoleOptionParser $parser Option parser to update.
+ * @return \Cake\Console\ConsoleOptionParser
+ */
+ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
+ {
+ $parser = parent::buildOptionParser($parser);
+
+ $parser->setDescription(
+ 'Bake seed class.'
+ )->addOption('table', [
+ 'help' => 'The database table to use.',
+ ])->addOption('data', [
+ 'boolean' => true,
+ 'help' => 'Include data from the table to the seed',
+ ])->addOption('fields', [
+ 'default' => '*',
+ 'help' => 'If including data, comma separated list of fields to select (all fields by default)',
+ ])->addOption('limit', [
+ 'short' => 'l',
+ 'help' => 'If including data, max number of rows to select',
+ ]);
+
+ return $parser;
+ }
+
+ /**
+ * Prettify var_export of an array output
+ *
+ * @param array $array Array to prettify
+ * @param int $tabCount Initial tab count
+ * @param string $indentCharacter Desired indent for the code.
+ * @return string
+ */
+ protected function prettifyArray(array $array, $tabCount = 3, $indentCharacter = " ")
+ {
+ $content = var_export($array, true);
+
+ $lines = explode("\n", $content);
+
+ $inString = false;
+
+ foreach ($lines as $k => &$line) {
+ if ($k === 0) {
+ // First row
+ $line = '[';
+ continue;
+ }
+
+ if ($k === count($lines) - 1) {
+ // Last row
+ $line = str_repeat($indentCharacter, --$tabCount) . ']';
+ continue;
+ }
+
+ $line = ltrim($line);
+
+ if (!$inString) {
+ if ($line === '),') {
+ //Check for closing bracket
+ $line = '],';
+ $tabCount--;
+ } elseif (preg_match("/^\d+\s\=\>\s$/", $line)) {
+ // Mark '0 =>' kind of lines to remove
+ $line = false;
+ continue;
+ }
+
+ //Insert tab count
+ $line = str_repeat($indentCharacter, $tabCount) . $line;
+ }
+
+ $length = strlen($line);
+ for ($j = 0; $j < $length; $j++) {
+ if ($line[$j] === '\\') {
+ //skip character right after an escape \
+ $j++;
+ } elseif ($line[$j] === '\'') {
+ //check string open/end
+ $inString = !$inString;
+ }
+ }
+
+ //check for opening bracket
+ if (!$inString && trim($line) === 'array (') {
+ $line = str_replace('array (', '[', $line);
+ $tabCount++;
+ }
+ }
+ unset($line);
+
+ // Remove marked lines
+ $lines = array_filter($lines, function ($line) {
+ return $line !== false;
+ });
+
+ return implode("\n", $lines);
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/BakeSimpleMigrationCommand.php b/app/vendor/cakephp/migrations/src/Command/BakeSimpleMigrationCommand.php
new file mode 100644
index 000000000..f7c4c14c4
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/BakeSimpleMigrationCommand.php
@@ -0,0 +1,197 @@
+getMigrationName($name);
+
+ return Util::getCurrentTimestamp() . '_' . Inflector::camelize($name) . '.php';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getPath(Arguments $args): string
+ {
+ $path = ROOT . DS . $this->pathFragment;
+ if (isset($this->plugin)) {
+ $path = $this->_pluginPath($this->plugin) . $this->pathFragment;
+ }
+
+ return str_replace('/', DS, $path);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function execute(Arguments $args, ConsoleIo $io): ?int
+ {
+ $this->extractCommonProperties($args);
+ $name = $args->getArgumentAt(0);
+ if (empty($name)) {
+ $io->err('You must provide a name to bake a ' . $this->name());
+ $this->abort();
+
+ return null;
+ }
+ $name = $this->_getName($name);
+ $name = Inflector::camelize($name);
+ $this->bake($name, $args, $io);
+
+ return static::CODE_SUCCESS;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function bake(string $name, Arguments $args, ConsoleIo $io): void
+ {
+ $this->io = $io;
+ $migrationWithSameName = glob($this->getPath($args) . '*_' . $name . '.php');
+ if (!empty($migrationWithSameName)) {
+ $force = $args->getOption('force');
+ if (!$force) {
+ $io->abort(
+ sprintf(
+ 'A migration with the name `%s` already exists. Please use a different name.',
+ $name
+ )
+ );
+ }
+
+ $io->info(sprintf('A migration with the name `%s` already exists, it will be deleted.', $name));
+ foreach ($migrationWithSameName as $migration) {
+ $io->info(sprintf('Deleting migration file `%s`...', $migration));
+ if (unlink($migration)) {
+ $io->success(sprintf('Deleted `%s`', $migration));
+ } else {
+ $io->err(sprintf('An error occurred while deleting `%s`', $migration));
+ }
+ }
+ }
+
+ $renderer = new TemplateRenderer($this->theme);
+ $renderer->set('name', $name);
+ $renderer->set($this->templateData($args));
+ $contents = $renderer->generate($this->template());
+
+ $filename = $this->getPath($args) . $this->fileName($name);
+ $this->createFile($filename, $contents, $args, $io);
+
+ $emptyFile = $this->getPath($args) . '.gitkeep';
+ $this->deleteEmptyFile($emptyFile, $io);
+ }
+
+ /**
+ * @param string $path Where to put the file.
+ * @param string $contents Content to put in the file.
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return bool Success
+ */
+ protected function createFile(string $path, string $contents, Arguments $args, ConsoleIo $io): bool
+ {
+ return $io->createFile($path, $contents);
+ }
+
+ /**
+ * Returns a class name for the migration class
+ *
+ * If the name is invalid, the task will exit
+ *
+ * @param string|null $name Name for the generated migration
+ * @return string Name of the migration file
+ */
+ protected function getMigrationName($name = null)
+ {
+ if (empty($name)) {
+ $this->io->abort('Choose a migration name to bake in CamelCase format');
+ }
+
+ /** @psalm-suppress PossiblyNullArgument */
+ $name = $this->_getName($name);
+ $name = Inflector::camelize($name);
+
+ if (!preg_match('/^[A-Z]{1}[a-zA-Z0-9]+$/', $name)) {
+ $this->io->abort('The className is not correct. The className can only contain "A-Z" and "0-9".');
+ }
+
+ return $name;
+ }
+
+ /**
+ * Gets the option parser instance and configures it.
+ *
+ * @param \Cake\Console\ConsoleOptionParser $parser Option parser to update.
+ * @return \Cake\Console\ConsoleOptionParser
+ */
+ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
+ {
+ $parser = $this->_setCommonOptions($parser);
+
+ $parser->setDescription(
+ 'Bake migration class.'
+ )->addOption('no-test', [
+ 'boolean' => true,
+ 'help' => 'Do not generate a test skeleton.',
+ ])->addOption('force', [
+ 'short' => 'f',
+ 'boolean' => true,
+ 'help' => 'Force overwriting existing file if a migration already exists with the same name.',
+ ]);
+
+ return $parser;
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/CacheBuild.php b/app/vendor/cakephp/migrations/src/Command/CacheBuild.php
deleted file mode 100644
index 70fd1ab9a..000000000
--- a/app/vendor/cakephp/migrations/src/Command/CacheBuild.php
+++ /dev/null
@@ -1,59 +0,0 @@
-setName('orm-cache-build')
- ->setDescription('Build all metadata caches for the connection. If a table name is provided, only that table will be cached.')
- ->addOption(
- 'connection',
- null,
- InputOption::VALUE_OPTIONAL,
- 'The connection to build/clear metadata cache data for.',
- 'default'
- )
- ->addArgument(
- 'name',
- InputArgument::OPTIONAL,
- 'A specific table you want to clear/refresh cached data for.'
- );
- }
-
- /**
- * {@inheritDoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $name = $input->getArgument('name');
- $schema = $this->_getSchema($input, $output);
- if (!$schema) {
- return false;
- }
- $tables = [$name];
- if (empty($name)) {
- $tables = $schema->listTables();
- }
- foreach ($tables as $table) {
- $output->writeln('Building metadata cache for ' . $table);
- $schema->describe($table, ['forceRefresh' => true]);
- }
- $output->writeln('Cache build complete ');
-
- return true;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Command/CacheClear.php b/app/vendor/cakephp/migrations/src/Command/CacheClear.php
deleted file mode 100644
index 954cc44ba..000000000
--- a/app/vendor/cakephp/migrations/src/Command/CacheClear.php
+++ /dev/null
@@ -1,67 +0,0 @@
-setName('orm-cache-clear')
- ->setDescription('Clear all metadata caches for the connection. If a table name is provided, only that table will be removed.')
- ->addOption(
- 'connection',
- null,
- InputOption::VALUE_OPTIONAL,
- 'The connection to build/clear metadata cache data for.',
- 'default'
- )
- ->addArgument(
- 'name',
- InputArgument::OPTIONAL,
- 'A specific table you want to clear/refresh cached data for.'
- );
- }
-
- /**
- * {@inheritDoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $schema = $this->_getSchema($input, $output);
- $name = $input->getArgument('name');
- if (!$schema) {
- return false;
- }
- $tables = [$name];
- if (empty($name)) {
- $tables = $schema->listTables();
- }
- $configName = $schema->getCacheMetadata();
-
- foreach ($tables as $table) {
- $output->writeln(sprintf(
- 'Clearing metadata cache from "%s" for %s',
- $configName,
- $table
- ));
- $key = $schema->cacheKey($table);
- Cache::delete($key, $configName);
- }
- $output->writeln('Cache clear complete');
-
- return true;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Command/Migrate.php b/app/vendor/cakephp/migrations/src/Command/Migrate.php
deleted file mode 100644
index 1389915be..000000000
--- a/app/vendor/cakephp/migrations/src/Command/Migrate.php
+++ /dev/null
@@ -1,68 +0,0 @@
-setName('migrate')
- ->setDescription('Migrate the database')
- ->setHelp('runs all available migrations, optionally up to a specific version')
- ->addOption('--target', '-t', InputOption::VALUE_REQUIRED, 'The version number to migrate to')
- ->addOption('--date', '-d', InputOption::VALUE_REQUIRED, 'The date to migrate to')
- ->addOption('--plugin', '-p', InputOption::VALUE_REQUIRED, 'The plugin containing the migrations')
- ->addOption('--connection', '-c', InputOption::VALUE_REQUIRED, 'The datasource connection to use')
- ->addOption('--source', '-s', InputOption::VALUE_REQUIRED, 'The folder where migrations are in')
- ->addOption(
- '--no-lock',
- null,
- InputOption::VALUE_NONE,
- 'If present, no lock file will be generated after migrating'
- );
- }
-
- /**
- * Overrides the action execute method in order to vanish the idea of environments
- * from phinx. CakePHP does not believe in the idea of having in-app environments
- *
- * @param \Symfony\Component\Console\Input\InputInterface $input the input object
- * @param \Symfony\Component\Console\Output\OutputInterface $output the output object
- * @return mixed
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $event = $this->dispatchEvent('Migration.beforeMigrate');
- if ($event->isStopped()) {
- return $event->result;
- }
- $this->parentExecute($input, $output);
- $this->dispatchEvent('Migration.afterMigrate');
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Command/MigrationsCacheBuildCommand.php b/app/vendor/cakephp/migrations/src/Command/MigrationsCacheBuildCommand.php
new file mode 100644
index 000000000..3150fcc44
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/MigrationsCacheBuildCommand.php
@@ -0,0 +1,29 @@
+getName();
+
+ return 'migrations ' . $name;
+ }
+
+ /**
+ * Array of arguments to run the shell with.
+ *
+ * @var array
+ */
+ public $argv = [];
+
+ /**
+ * Defines what options can be passed to the shell.
+ * This is required because CakePHP validates the passed options
+ * and would complain if something not configured here is present
+ *
+ * @return \Cake\Console\ConsoleOptionParser
+ */
+ public function getOptionParser(): ConsoleOptionParser
+ {
+ if (parent::defaultName() === 'migrations') {
+ return parent::getOptionParser();
+ }
+ $parser = parent::getOptionParser();
+ $command = new MigrationsDispatcher::$phinxCommands[static::$commandName]();
+ $parser->setDescription($command->getDescription());
+ $definition = $command->getDefinition();
+ foreach ($definition->getOptions() as $key => $option) {
+ if (!empty($option->getShortcut())) {
+ $parser->addOption($option->getName(), [
+ 'short' => $option->getShortcut(),
+ 'help' => $option->getDescription(),
+ ]);
+ continue;
+ }
+ $parser->addOption($option->getName());
+ }
+
+ return $parser;
+ }
+
+ /**
+ * Defines constants that are required by phinx to get running
+ *
+ * @return void
+ */
+ public function initialize(): void
+ {
+ if (!defined('PHINX_VERSION')) {
+ define('PHINX_VERSION', 'UNKNOWN');
+ }
+ parent::initialize();
+ }
+
+ /**
+ * This acts as a front-controller for phinx. It just instantiates the classes
+ * responsible for parsing the command line from phinx and gives full control of
+ * the rest of the flow to it.
+ *
+ * The input parameter of the ``MigrationDispatcher::run()`` method is manually built
+ * in case a MigrationsShell is dispatched using ``Shell::dispatch()``.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return null|int The exit code or null for success
+ */
+ public function execute(Arguments $args, ConsoleIo $io): ?int
+ {
+ $app = $this->getApp();
+ $input = new ArgvInput($this->argv);
+ $app->setAutoExit(false);
+ $exitCode = $app->run($input, $this->getOutput());
+
+ if (in_array('-h', $this->argv, true) || in_array('--help', $this->argv, true)) {
+ return $exitCode;
+ }
+
+ if (
+ isset($this->argv[1]) && in_array($this->argv[1], ['migrate', 'rollback'], true) &&
+ !in_array('--no-lock', $this->argv, true) &&
+ $exitCode === 0
+ ) {
+ $newArgs = [];
+ if (!empty($args->getOption('connection'))) {
+ $newArgs[] = '-c';
+ $newArgs[] = $args->getOption('connection');
+ }
+
+ if (!empty($args->getOption('plugin'))) {
+ $newArgs[] = '-p';
+ $newArgs[] = $args->getOption('plugin');
+ }
+
+ $io->out('');
+ $io->out('Dumps the current schema of the database to be used while baking a diff');
+ $io->out('');
+
+ $dumpExitCode = $this->executeCommand(MigrationsDumpCommand::class, $newArgs, $io);
+ }
+
+ if (isset($dumpExitCode) && $exitCode === 0 && $dumpExitCode !== 0) {
+ $exitCode = 1;
+ }
+
+ return $exitCode;
+ }
+
+ /**
+ * Returns the MigrationsDispatcher the Shell will have to use
+ *
+ * @return \Migrations\MigrationsDispatcher
+ */
+ protected function getApp()
+ {
+ return new MigrationsDispatcher(PHINX_VERSION);
+ }
+
+ /**
+ * Returns the instance of OutputInterface the MigrationsDispatcher will have to use.
+ *
+ * @return \Symfony\Component\Console\Output\ConsoleOutput
+ */
+ protected function getOutput()
+ {
+ return new ConsoleOutput();
+ }
+
+ /**
+ * Override the default behavior to save the command called
+ * in order to pass it to the command dispatcher
+ *
+ * @param array $argv Arguments from the CLI environment.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return int|null Exit code or null for success.
+ */
+ public function run(array $argv, ConsoleIo $io): ?int
+ {
+ $name = static::defaultName();
+ $name = explode(' ', $name);
+
+ array_unshift($argv, ...$name);
+ $this->argv = $argv;
+
+ return parent::run($argv, $io);
+ }
+
+ /**
+ * Output help content
+ *
+ * @param \Cake\Console\ConsoleOptionParser $parser The option parser.
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return void
+ */
+ protected function displayHelp(ConsoleOptionParser $parser, Arguments $args, ConsoleIo $io): void
+ {
+ $this->execute($args, $io);
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/MigrationsCreateCommand.php b/app/vendor/cakephp/migrations/src/Command/MigrationsCreateCommand.php
new file mode 100644
index 000000000..c882f7afa
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/MigrationsCreateCommand.php
@@ -0,0 +1,29 @@
+setName('orm-cache-build')
+ ->setDescription(
+ 'Build all metadata caches for the connection. ' .
+ 'If a table name is provided, only that table will be cached.'
+ )
+ ->addOption(
+ 'connection',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'The connection to build/clear metadata cache data for.',
+ 'default'
+ )
+ ->addArgument(
+ 'name',
+ InputArgument::OPTIONAL,
+ 'A specific table you want to clear/refresh cached data for.'
+ );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ /** @var string $name */
+ $name = $input->getArgument('name');
+ $schema = $this->_getSchema($input, $output);
+ if (!$schema) {
+ return static::CODE_ERROR;
+ }
+ $tables = [$name];
+ if (empty($name)) {
+ $tables = $schema->listTables();
+ }
+ foreach ($tables as $table) {
+ $output->writeln('Building metadata cache for ' . $table);
+ $schema->describe($table, ['forceRefresh' => true]);
+ }
+ $output->writeln('Cache build complete ');
+
+ return static::CODE_SUCCESS;
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/Phinx/CacheClear.php b/app/vendor/cakephp/migrations/src/Command/Phinx/CacheClear.php
new file mode 100644
index 000000000..0e1025f08
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/CacheClear.php
@@ -0,0 +1,70 @@
+setName('orm-cache-clear')
+ ->setDescription(
+ 'Clear all metadata caches for the connection. ' .
+ 'If a table name is provided, only that table will be removed.'
+ )
+ ->addOption(
+ 'connection',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'The connection to build/clear metadata cache data for.',
+ 'default'
+ )
+ ->addArgument(
+ 'name',
+ InputArgument::OPTIONAL,
+ 'A specific table you want to clear/refresh cached data for.'
+ );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $schema = $this->_getSchema($input, $output);
+ /** @var string $name */
+ $name = $input->getArgument('name');
+ if (!$schema) {
+ return static::CODE_ERROR;
+ }
+ $tables = [$name];
+ if (empty($name)) {
+ $tables = $schema->listTables();
+ }
+ $cacher = $schema->getCacher();
+ foreach ($tables as $table) {
+ $output->writeln(sprintf(
+ 'Clearing metadata cache for %s',
+ $table
+ ));
+ $cacher->delete($table);
+ }
+ $output->writeln('Cache clear complete');
+
+ return static::CODE_SUCCESS;
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/CommandTrait.php b/app/vendor/cakephp/migrations/src/Command/Phinx/CommandTrait.php
similarity index 91%
rename from app/vendor/cakephp/migrations/src/Command/CommandTrait.php
rename to app/vendor/cakephp/migrations/src/Command/Phinx/CommandTrait.php
index aaa3030ea..794c127c0 100644
--- a/app/vendor/cakephp/migrations/src/Command/CommandTrait.php
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/CommandTrait.php
@@ -1,4 +1,6 @@
beforeExecute($input, $output);
- parent::execute($input, $output);
+
+ return parent::execute($input, $output);
}
/**
@@ -65,6 +67,7 @@ public function bootstrap(InputInterface $input, OutputInterface $output)
$name = $this->getConnectionName($input);
$this->connection = $name;
ConnectionManager::alias($name, 'default');
+ /** @var \Cake\Database\Connection $connection */
$connection = ConnectionManager::get($name);
$manager = $this->getManager();
@@ -72,6 +75,8 @@ public function bootstrap(InputInterface $input, OutputInterface $output)
if (!$manager instanceof CakeManager) {
$this->setManager(new CakeManager($this->getConfig(), $input, $output));
}
+ /** @var \Phinx\Migration\Manager\Environment $env */
+ /** @psalm-suppress PossiblyNullReference */
$env = $this->getManager()->getEnvironment('default');
$adapter = $env->getAdapter();
if (!$adapter instanceof CakeAdapter) {
diff --git a/app/vendor/cakephp/migrations/src/Command/Create.php b/app/vendor/cakephp/migrations/src/Command/Phinx/Create.php
similarity index 89%
rename from app/vendor/cakephp/migrations/src/Command/Create.php
rename to app/vendor/cakephp/migrations/src/Command/Phinx/Create.php
index 3b868d3d8..6b3f2842c 100644
--- a/app/vendor/cakephp/migrations/src/Command/Create.php
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/Create.php
@@ -1,4 +1,6 @@
parentExecute($input, $output);
+ $result = $this->parentExecute($input, $output);
$output->writeln('renaming file in CamelCase to follow CakePHP convention... ');
$migrationPaths = $this->getConfig()->getMigrationPaths();
$migrationPath = array_pop($migrationPaths) . DS;
+ /** @var string $name */
$name = $input->getArgument('name');
- list($phinxTimestamp, $phinxName) = explode('_', Util::mapClassNameToFileName($name), 2);
+ [$phinxTimestamp, $phinxName] = explode('_', Util::mapClassNameToFileName($name), 2);
$migrationFilename = glob($migrationPath . '*' . $phinxName);
if (empty($migrationFilename)) {
@@ -94,5 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$output->writeln(sprintf('An error occurred while renaming file to %s ', $newPath));
}
}
+
+ return $result ?? BaseCommand::CODE_SUCCESS;
}
}
diff --git a/app/vendor/cakephp/migrations/src/Command/Dump.php b/app/vendor/cakephp/migrations/src/Command/Phinx/Dump.php
similarity index 90%
rename from app/vendor/cakephp/migrations/src/Command/Dump.php
rename to app/vendor/cakephp/migrations/src/Command/Phinx/Dump.php
index 45c965456..936851b2c 100644
--- a/app/vendor/cakephp/migrations/src/Command/Dump.php
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/Dump.php
@@ -1,4 +1,6 @@
output = $output;
@@ -73,7 +76,7 @@ public function output(OutputInterface $output = null)
*
* @param \Symfony\Component\Console\Input\InputInterface $input the input object
* @param \Symfony\Component\Console\Output\OutputInterface $output the output object
- * @return bool Success of the call.
+ * @return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
@@ -82,13 +85,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->output($output);
$path = $this->getOperationsPath($input);
+ /** @var string $connectionName */
$connectionName = $input->getOption('connection') ?: 'default';
$connection = ConnectionManager::get($connectionName);
$collection = $connection->getSchemaCollection();
$options = [
'require-table' => false,
- 'plugin' => $this->getPlugin($input)
+ 'plugin' => $this->getPlugin($input),
];
$tables = $this->getTablesToBake($collection, $options);
@@ -105,7 +109,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (file_put_contents($filePath, serialize($dump))) {
$output->writeln(sprintf('Dump file `%s` was successfully written ', $filePath));
- return true;
+ return BaseCommand::CODE_SUCCESS;
}
$output->writeln(sprintf(
@@ -113,6 +117,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
$filePath
));
- return false;
+ return BaseCommand::CODE_ERROR;
}
}
diff --git a/app/vendor/cakephp/migrations/src/Command/MarkMigrated.php b/app/vendor/cakephp/migrations/src/Command/Phinx/MarkMigrated.php
similarity index 91%
rename from app/vendor/cakephp/migrations/src/Command/MarkMigrated.php
rename to app/vendor/cakephp/migrations/src/Command/Phinx/MarkMigrated.php
index 4af6492d3..f9553d63c 100644
--- a/app/vendor/cakephp/migrations/src/Command/MarkMigrated.php
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/MarkMigrated.php
@@ -1,4 +1,6 @@
output = $output;
@@ -46,7 +50,9 @@ public function output(OutputInterface $output = null)
}
/**
- * {@inheritdoc}
+ * Configures the current command.
+ *
+ * @return void
*/
protected function configure()
{
@@ -98,7 +104,7 @@ protected function configure()
*
* @param \Symfony\Component\Console\Input\InputInterface $input the input object
* @param \Symfony\Component\Console\Output\OutputInterface $output the output object
- * @return void
+ * @return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
@@ -114,7 +120,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
"You should use `--exclude` OR `--only` (not both) along with a `--target` ! "
);
- return;
+ return BaseCommand::CODE_ERROR;
}
if ($this->isUsingDeprecatedAll()) {
@@ -130,10 +136,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
} catch (InvalidArgumentException $e) {
$output->writeln(sprintf("%s ", $e->getMessage()));
- return;
+ return BaseCommand::CODE_ERROR;
}
$this->getManager()->markVersionsAsMigrated($path, $versions, $output);
+
+ return BaseCommand::CODE_SUCCESS;
}
/**
@@ -143,7 +151,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
*/
protected function isUsingDeprecatedAll()
{
- $version = $this->input->getArgument('version');
+ $version = $this->input()->getArgument('version');
return $version === 'all' || $version === '*';
}
@@ -155,7 +163,7 @@ protected function isUsingDeprecatedAll()
*/
protected function hasExclude()
{
- return $this->input->getOption('exclude');
+ return (bool)$this->input()->getOption('exclude');
}
/**
@@ -165,7 +173,7 @@ protected function hasExclude()
*/
protected function hasOnly()
{
- return $this->input->getOption('only');
+ return (bool)$this->input()->getOption('only');
}
/**
@@ -175,7 +183,7 @@ protected function hasOnly()
*/
protected function isUsingDeprecatedVersion()
{
- $version = $this->input->getArgument('version');
+ $version = $this->input()->getArgument('version');
return $version && $version !== 'all' && $version !== '*';
}
@@ -189,7 +197,7 @@ protected function invalidOnlyOrExclude()
{
return ($this->hasExclude() && $this->hasOnly()) ||
($this->hasExclude() || $this->hasOnly()) &&
- $this->input->getOption('target') === null;
+ $this->input()->getOption('target') === null;
}
/**
diff --git a/app/vendor/cakephp/migrations/src/Command/Phinx/Migrate.php b/app/vendor/cakephp/migrations/src/Command/Phinx/Migrate.php
new file mode 100644
index 000000000..0b0fadc9c
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/Migrate.php
@@ -0,0 +1,90 @@
+setName('migrate')
+ ->setDescription('Migrate the database')
+ ->setHelp('runs all available migrations, optionally up to a specific version')
+ ->addOption('--target', '-t', InputOption::VALUE_REQUIRED, 'The version number to migrate to')
+ ->addOption('--date', '-d', InputOption::VALUE_REQUIRED, 'The date to migrate to')
+ ->addOption(
+ '--dry-run',
+ '-x',
+ InputOption::VALUE_NONE,
+ 'Dump queries to standard output instead of executing it'
+ )
+ ->addOption(
+ '--plugin',
+ '-p',
+ InputOption::VALUE_REQUIRED,
+ 'The plugin containing the migrations'
+ )
+ ->addOption('--connection', '-c', InputOption::VALUE_REQUIRED, 'The datasource connection to use')
+ ->addOption('--source', '-s', InputOption::VALUE_REQUIRED, 'The folder where migrations are in')
+ ->addOption(
+ '--fake',
+ null,
+ InputOption::VALUE_NONE,
+ "Mark any migrations selected as run, but don't actually execute them"
+ )
+ ->addOption(
+ '--no-lock',
+ null,
+ InputOption::VALUE_NONE,
+ 'If present, no lock file will be generated after migrating'
+ );
+ }
+
+ /**
+ * Overrides the action execute method in order to vanish the idea of environments
+ * from phinx. CakePHP does not believe in the idea of having in-app environments
+ *
+ * @param \Symfony\Component\Console\Input\InputInterface $input the input object
+ * @param \Symfony\Component\Console\Output\OutputInterface $output the output object
+ * @return int
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $event = $this->dispatchEvent('Migration.beforeMigrate');
+ if ($event->isStopped()) {
+ return $event->getResult() ? BaseCommand::CODE_SUCCESS : BaseCommand::CODE_ERROR;
+ }
+ $result = $this->parentExecute($input, $output);
+ $this->dispatchEvent('Migration.afterMigrate');
+
+ return $result ?? BaseCommand::CODE_SUCCESS;
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Command/Rollback.php b/app/vendor/cakephp/migrations/src/Command/Phinx/Rollback.php
similarity index 75%
rename from app/vendor/cakephp/migrations/src/Command/Rollback.php
rename to app/vendor/cakephp/migrations/src/Command/Phinx/Rollback.php
index d149cb85f..e3efa9533 100644
--- a/app/vendor/cakephp/migrations/src/Command/Rollback.php
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/Rollback.php
@@ -1,4 +1,6 @@
addOption('--connection', '-c', InputOption::VALUE_REQUIRED, 'The datasource connection to use')
->addOption('--source', '-s', InputOption::VALUE_REQUIRED, 'The folder where migrations are in')
->addOption('--force', '-f', InputOption::VALUE_NONE, 'Force rollback to ignore breakpoints')
+ ->addOption(
+ '--dry-run',
+ '-x',
+ InputOption::VALUE_NONE,
+ 'Dump queries to standard output instead of executing it'
+ )
+ ->addOption(
+ '--fake',
+ null,
+ InputOption::VALUE_NONE,
+ "Mark any rollbacks selected as run, but don't actually execute them"
+ )
->addOption(
'--no-lock',
null,
@@ -55,15 +70,17 @@ protected function configure()
*
* @param \Symfony\Component\Console\Input\InputInterface $input the input object
* @param \Symfony\Component\Console\Output\OutputInterface $output the output object
- * @return mixed
+ * @return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$event = $this->dispatchEvent('Migration.beforeRollback');
if ($event->isStopped()) {
- return $event->result;
+ return $event->getResult() ? BaseCommand::CODE_SUCCESS : BaseCommand::CODE_ERROR;
}
- $this->parentExecute($input, $output);
+ $result = $this->parentExecute($input, $output);
$this->dispatchEvent('Migration.afterRollback');
+
+ return $result ?? BaseCommand::CODE_SUCCESS;
}
}
diff --git a/app/vendor/cakephp/migrations/src/Command/Seed.php b/app/vendor/cakephp/migrations/src/Command/Phinx/Seed.php
similarity index 86%
rename from app/vendor/cakephp/migrations/src/Command/Seed.php
rename to app/vendor/cakephp/migrations/src/Command/Phinx/Seed.php
index 31f063ec0..3cd2bef23 100644
--- a/app/vendor/cakephp/migrations/src/Command/Seed.php
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/Seed.php
@@ -1,4 +1,6 @@
dispatchEvent('Migration.beforeSeed');
if ($event->isStopped()) {
- return $event->result;
+ return $event->getResult() ? BaseCommand::CODE_SUCCESS : BaseCommand::CODE_ERROR;
}
$seed = $input->getOption('seed');
if (!empty($seed) && !is_array($seed)) {
+ /** @psalm-suppress InvalidScalarArgument */
$input->setOption('seed', [$seed]);
}
$this->setInput($input);
$this->bootstrap($input, $output);
$this->getManager()->setInput($input);
- $this->parentExecute($input, $output);
+ $result = $this->parentExecute($input, $output);
$this->dispatchEvent('Migration.afterSeed');
+
+ return $result ?? BaseCommand::CODE_SUCCESS;
}
}
diff --git a/app/vendor/cakephp/migrations/src/Command/Status.php b/app/vendor/cakephp/migrations/src/Command/Phinx/Status.php
similarity index 90%
rename from app/vendor/cakephp/migrations/src/Command/Status.php
rename to app/vendor/cakephp/migrations/src/Command/Phinx/Status.php
index 523f64ca6..adfb1a33b 100644
--- a/app/vendor/cakephp/migrations/src/Command/Status.php
+++ b/app/vendor/cakephp/migrations/src/Command/Phinx/Status.php
@@ -1,4 +1,6 @@
beforeExecute($input, $output);
$this->bootstrap($input, $output);
+ /** @var string|null $environment */
$environment = $input->getOption('environment');
+ /** @var string|null $format */
$format = $input->getOption('format');
- if (null === $environment) {
+ if ($environment === null) {
$environment = $this->getManager()->getConfig()->getDefaultEnvironment();
$output->writeln('warning no environment specified, defaulting to: ' . $environment);
} else {
$output->writeln('using environment ' . $environment);
}
- if (null !== $format) {
+ if ($format !== null) {
$output->writeln('using format ' . $format);
}
// print the status
+ /** @var array $migrations */
$migrations = $this->getManager()->printStatus($environment, $format);
switch ($format) {
@@ -78,6 +87,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->display($migrations);
break;
}
+
+ return BaseCommand::CODE_SUCCESS;
}
/**
@@ -98,7 +109,7 @@ protected function display(array $migrations)
foreach ($migrations as $migration) {
$status = $migration['status'] === 'up' ? ' up ' : ' down ';
$maxNameLength = $this->getManager()->maxNameLength;
- $name = $migration['name'] !== false ?
+ $name = $migration['name'] ?
' ' . str_pad($migration['name'], $maxNameLength, ' ') . ' ' :
' ** MISSING ** ';
diff --git a/app/vendor/cakephp/migrations/src/Command/SnapshotTrait.php b/app/vendor/cakephp/migrations/src/Command/SnapshotTrait.php
new file mode 100644
index 000000000..a8317c49b
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Command/SnapshotTrait.php
@@ -0,0 +1,101 @@
+markSnapshotApplied($path, $args, $io);
+
+ if (!$args->getOption('no-lock')) {
+ $this->refreshDump($args, $io);
+ }
+ }
+
+ return $createFile;
+ }
+
+ /**
+ * Will mark a snapshot created, the snapshot being identified by its
+ * full file path.
+ *
+ * @param string $path Path to the newly created snapshot
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return void
+ */
+ protected function markSnapshotApplied($path, Arguments $args, ConsoleIo $io)
+ {
+ $fileName = pathinfo($path, PATHINFO_FILENAME);
+ [$version, ] = explode('_', $fileName, 2);
+
+ $newArgs = [];
+ $newArgs[] = '-t';
+ $newArgs[] = $version;
+ $newArgs[] = '-o';
+
+ if ($args->getOption('connection')) {
+ $newArgs[] = '-c';
+ $newArgs[] = $args->getOption('connection');
+ }
+
+ if ($args->getOption('plugin')) {
+ $newArgs[] = '-p';
+ $newArgs[] = $args->getOption('plugin');
+ }
+
+ $io->out('Marking the migration ' . $fileName . ' as migrated...');
+ $this->executeCommand(MigrationsMarkMigratedCommand::class, $newArgs, $io);
+ }
+
+ /**
+ * After a file has been successfully created, we refresh the dump of the database
+ * to be able to generate a new diff afterward.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return void
+ */
+ protected function refreshDump(Arguments $args, ConsoleIo $io)
+ {
+ $newArgs = [];
+
+ if ($args->getOption('connection')) {
+ $newArgs[] = '-c';
+ $newArgs[] = $args->getOption('connection');
+ }
+
+ if ($args->getOption('plugin')) {
+ $newArgs[] = '-p';
+ $newArgs[] = $args->getOption('plugin');
+ }
+
+ $io->out('Creating a dump of the new database state...');
+ $this->executeCommand(MigrationsDumpCommand::class, $newArgs, $io);
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/ConfigurationTrait.php b/app/vendor/cakephp/migrations/src/ConfigurationTrait.php
index 66da0abf7..c213b6af4 100644
--- a/app/vendor/cakephp/migrations/src/ConfigurationTrait.php
+++ b/app/vendor/cakephp/migrations/src/ConfigurationTrait.php
@@ -1,4 +1,6 @@
input === null) {
+ throw new \RuntimeException('Input not set');
+ }
+
+ return $this->input;
+ }
+
/**
* Overrides the original method from phinx in order to return a tailored
* Config object containing the connection details for the database.
@@ -62,9 +74,9 @@ public function getConfig($forceRefresh = false)
return $this->configuration;
}
- $migrationsPath = $this->getOperationsPath($this->input);
- $seedsPath = $this->getOperationsPath($this->input, 'Seeds');
- $plugin = $this->getPlugin($this->input);
+ $migrationsPath = $this->getOperationsPath($this->input());
+ $seedsPath = $this->getOperationsPath($this->input(), 'Seeds');
+ $plugin = $this->getPlugin($this->input());
if (!is_dir($migrationsPath)) {
mkdir($migrationsPath, 0777, true);
@@ -76,39 +88,46 @@ public function getConfig($forceRefresh = false)
$phinxTable = $this->getPhinxTable($plugin);
- $connection = $this->getConnectionName($this->input);
+ $connection = $this->getConnectionName($this->input());
$connectionConfig = ConnectionManager::getConfig($connection);
+ /**
+ * @psalm-suppress PossiblyNullArgument
+ * @psalm-suppress PossiblyNullArrayAccess
+ */
$adapterName = $this->getAdapterName($connectionConfig['driver']);
- $templatePath = Plugin::path('Migrations') . 'src' . DS . 'Template' . DS;
+ $templatePath = dirname(__DIR__) . DS . 'templates' . DS;
+ /** @psalm-suppress PossiblyNullArrayAccess */
$config = [
'paths' => [
'migrations' => $migrationsPath,
'seeds' => $seedsPath,
],
'templates' => [
- 'file' => $templatePath . 'Phinx' . DS . 'create.php.template'
+ 'file' => $templatePath . 'Phinx' . DS . 'create.php.template',
],
'migration_base_class' => 'Migrations\AbstractMigration',
'environments' => [
'default_migration_table' => $phinxTable,
- 'default_database' => 'default',
+ 'default_environment' => 'default',
'default' => [
'adapter' => $adapterName,
- 'host' => isset($connectionConfig['host']) ? $connectionConfig['host'] : null,
- 'user' => isset($connectionConfig['username']) ? $connectionConfig['username'] : null,
- 'pass' => isset($connectionConfig['password']) ? $connectionConfig['password'] : null,
- 'port' => isset($connectionConfig['port']) ? $connectionConfig['port'] : null,
+ 'host' => $connectionConfig['host'] ?? null,
+ 'user' => $connectionConfig['username'] ?? null,
+ 'pass' => $connectionConfig['password'] ?? null,
+ 'port' => $connectionConfig['port'] ?? null,
'name' => $connectionConfig['database'],
- 'charset' => isset($connectionConfig['encoding']) ? $connectionConfig['encoding'] : null,
- 'unix_socket' => isset($connectionConfig['unix_socket']) ? $connectionConfig['unix_socket'] : null,
- ]
- ]
+ 'charset' => $connectionConfig['encoding'] ?? null,
+ 'unix_socket' => $connectionConfig['unix_socket'] ?? null,
+ 'suffix' => '',
+ ],
+ ],
];
if ($adapterName === 'pgsql') {
if (!empty($connectionConfig['schema'])) {
+ /** @psalm-suppress PossiblyNullArrayAccess */
$config['environments']['default']['schema'] = $connectionConfig['schema'];
}
}
@@ -119,9 +138,36 @@ public function getConfig($forceRefresh = false)
$config['environments']['default']['mysql_attr_ssl_cert'] = $connectionConfig['ssl_cert'];
}
+ /** @psalm-suppress PossiblyNullReference */
if (!empty($connectionConfig['ssl_ca'])) {
+ /**
+ * @psalm-suppress PossiblyNullReference
+ * @psalm-suppress PossiblyNullArrayAccess
+ */
$config['environments']['default']['mysql_attr_ssl_ca'] = $connectionConfig['ssl_ca'];
}
+
+ /** @psalm-suppress PossiblyNullReference */
+ if (!empty($connectionConfig['flags'])) {
+ /**
+ * @psalm-suppress PossiblyNullArrayAccess
+ * @psalm-suppress PossiblyNullArgument
+ */
+ $config['environments']['default'] +=
+ $this->translateConnectionFlags($connectionConfig['flags'], $adapterName);
+ }
+ }
+
+ if ($adapterName === 'sqlsrv') {
+ /** @psalm-suppress PossiblyNullReference */
+ if (!empty($connectionConfig['flags'])) {
+ /**
+ * @psalm-suppress PossiblyNullArrayAccess
+ * @psalm-suppress PossiblyNullArgument
+ */
+ $config['environments']['default'] +=
+ $this->translateConnectionFlags($connectionConfig['flags'], $adapterName);
+ }
}
return $this->configuration = new Config($config);
@@ -161,14 +207,64 @@ public function getAdapterName($driver)
*
* @param \Symfony\Component\Console\Input\InputInterface $input the input object
* @return string
+ * @psalm-suppress InvalidReturnType
*/
protected function getConnectionName(InputInterface $input)
{
- $connection = 'default';
- if ($input->getOption('connection')) {
- $connection = $input->getOption('connection');
+ return $input->getOption('connection') ?: 'default';
+ }
+
+ /**
+ * Translates driver specific connection flags (PDO attributes) to
+ * Phinx compatible adapter options.
+ *
+ * Currently Phinx supports the `PDO::MYSQL_ATTR_*` and
+ * `PDO::SQLSRV_ATTR_*` attributes.
+ *
+ * ### Example:
+ *
+ * ```
+ * [
+ * \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
+ * \PDO::SQLSRV_ATTR_DIRECT_QUERY => true,
+ * // ...
+ * ]
+ * ```
+ *
+ * will be translated to:
+ *
+ * ```
+ * [
+ * 'mysql_attr_ssl_verify_server_cert' => false,
+ * 'sqlsrv_attr_direct_query' => true,
+ * // ...
+ * ]
+ * ```
+ *
+ * @param array $flags An array of connection flags.
+ * @param string $adapterName The adapter name, eg `mysql` or `sqlsrv`.
+ * @return array An array of Phinx compatible connection attribute options.
+ */
+ protected function translateConnectionFlags(array $flags, $adapterName)
+ {
+ $pdo = new \ReflectionClass(\PDO::class);
+ $constants = $pdo->getConstants();
+
+ $attributes = [];
+ foreach ($constants as $name => $value) {
+ $name = strtolower($name);
+ if (strpos($name, "{$adapterName}_attr_") === 0) {
+ $attributes[$value] = $name;
+ }
+ }
+
+ $options = [];
+ foreach ($flags as $flag => $value) {
+ if (isset($attributes[$flag])) {
+ $options[$attributes[$flag]] = $value;
+ }
}
- return $connection;
+ return $options;
}
}
diff --git a/app/vendor/cakephp/migrations/src/Migrations.php b/app/vendor/cakephp/migrations/src/Migrations.php
index 1bbf541c3..fd71cfaea 100644
--- a/app/vendor/cakephp/migrations/src/Migrations.php
+++ b/app/vendor/cakephp/migrations/src/Migrations.php
@@ -1,4 +1,6 @@
command = $command;
@@ -130,10 +133,9 @@ public function getCommand()
* - `connection` The datasource connection to use
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
- *
* @return array The migrations list and their statuses
*/
- public function status($options = [])
+ public function status(array $options = [])
{
$this->setCommand('status');
$input = $this->getInput('Status', [], $options);
@@ -154,10 +156,9 @@ public function status($options = [])
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
* - `date` The date to migrate to
- *
* @return bool Success
*/
- public function migrate($options = [])
+ public function migrate(array $options = [])
{
$this->setCommand('migrate');
$input = $this->getInput('Migrate', [], $options);
@@ -166,6 +167,7 @@ public function migrate($options = [])
if ($input->getOption('date')) {
$method = 'migrateToDateTime';
+ /** @psalm-suppress PossiblyInvalidArgument */
$params[1] = new \DateTime($input->getOption('date'));
}
@@ -186,10 +188,9 @@ public function migrate($options = [])
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
* - `date` The date to rollback to
- *
* @return bool Success
*/
- public function rollback($options = [])
+ public function rollback(array $options = [])
{
$this->setCommand('rollback');
$input = $this->getInput('Rollback', [], $options);
@@ -198,6 +199,7 @@ public function rollback($options = [])
if ($input->getOption('date')) {
$method = 'rollbackToDateTime';
+ /** @psalm-suppress PossiblyInvalidArgument */
$params[1] = new \DateTime($input->getOption('date'));
}
@@ -216,14 +218,14 @@ public function rollback($options = [])
* - `connection` The datasource connection to use
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
- *
* @return bool Success
*/
- public function markMigrated($version = null, $options = [])
+ public function markMigrated($version = null, array $options = [])
{
$this->setCommand('mark_migrated');
- if (isset($options['target']) &&
+ if (
+ isset($options['target']) &&
isset($options['exclude']) &&
isset($options['only'])
) {
@@ -238,7 +240,7 @@ public function markMigrated($version = null, $options = [])
$params = [
array_pop($migrationPaths),
$this->getManager()->getVersionsToMark($input),
- $this->output
+ $this->output,
];
$this->run('markVersionsAsMigrated', $params, $input);
@@ -256,10 +258,9 @@ public function markMigrated($version = null, $options = [])
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
* - `seed` The seed file to use
- *
* @return bool Success
*/
- public function seed($options = [])
+ public function seed(array $options = [])
{
$this->setCommand('seed');
$input = $this->getInput('Seed', [], $options);
@@ -282,10 +283,9 @@ public function seed($options = [])
* @param array $params Manager params to pass
* @param \Symfony\Component\Console\Input\InputInterface $input InputInterface needed for the
* Manager to properly run
- *
* @return mixed The result of the CakeManager::$method() call
*/
- protected function run($method, $params, $input)
+ protected function run($method, array $params, $input)
{
if ($this->configuration instanceof Config) {
$migrationPaths = $this->getConfig()->getMigrationPaths();
@@ -294,6 +294,7 @@ protected function run($method, $params, $input)
$seedPath = array_pop($seedPaths);
}
+ $pdo = null;
if ($this->manager instanceof Manager) {
$pdo = $this->manager->getEnvironment('default')
->getAdapter()
@@ -305,10 +306,14 @@ protected function run($method, $params, $input)
$manager = $this->getManager($newConfig);
$manager->setInput($input);
- if (isset($pdo)) {
- $this->manager->getEnvironment('default')
- ->getAdapter()
- ->setConnection($pdo);
+ if ($pdo !== null) {
+ /** @var \Phinx\Db\Adapter\PdoAdapter|\Migrations\CakeAdapter $adapter */
+ $adapter = $this->manager->getEnvironment('default')->getAdapter();
+ while ($adapter instanceof WrapperInterface) {
+ /** @var \Phinx\Db\Adapter\PdoAdapter|\Migrations\CakeAdapter $adapter */
+ $adapter = $adapter->getAdapter();
+ }
+ $adapter->setConnection($pdo);
}
$newMigrationPaths = $newConfig->getMigrationPaths();
@@ -346,7 +351,7 @@ public function getManager($config = null)
$environment = $this->manager->getEnvironment('default');
$oldConfig = $environment->getOptions();
unset($oldConfig['connection']);
- if ($oldConfig == $defaultEnvironment) {
+ if ($oldConfig === $defaultEnvironment) {
$defaultEnvironment['connection'] = $environment
->getAdapter()
->getConnection();
@@ -371,18 +376,19 @@ public function getManager($config = null)
*/
public function setAdapter()
{
- if ($this->input !== null) {
- $connectionName = 'default';
- if ($this->input->getOption('connection')) {
- $connectionName = $this->input->getOption('connection');
- }
- $connection = ConnectionManager::get($connectionName);
+ if ($this->input === null) {
+ return;
+ }
- $env = $this->manager->getEnvironment('default');
- $adapter = $env->getAdapter();
- if (!$adapter instanceof CakeAdapter) {
- $env->setAdapter(new CakeAdapter($adapter, $connection));
- }
+ /** @var string $connectionName */
+ $connectionName = $this->input()->getOption('connection') ?: 'default';
+ /** @var \Cake\Database\Connection $connection */
+ $connection = ConnectionManager::get($connectionName);
+
+ $env = $this->manager->getEnvironment('default');
+ $adapter = $env->getAdapter();
+ if (!$adapter instanceof CakeAdapter) {
+ $env->setAdapter(new CakeAdapter($adapter, $connection));
}
}
@@ -397,11 +403,13 @@ public function setAdapter()
* @return \Symfony\Component\Console\Input\InputInterface InputInterface needed for the
* Manager to properly run
*/
- public function getInput($command, $arguments, $options)
+ public function getInput($command, array $arguments, array $options)
{
- $className = '\Migrations\Command\\' . $command;
+ $className = 'Migrations\Command\Phinx\\' . $command;
$options = $arguments + $this->prepareOptions($options);
- $definition = (new $className())->getDefinition();
+ /** @var \Symfony\Component\Console\Command\Command $command */
+ $command = new $className();
+ $definition = $command->getDefinition();
return new ArrayInput($options, $definition);
}
@@ -412,9 +420,9 @@ public function getInput($command, $arguments, $options)
* @param array $options Simple key-values array to pass to the InputInterface
* @return array Prepared $options
*/
- protected function prepareOptions($options = [])
+ protected function prepareOptions(array $options = [])
{
- $options = array_merge($this->default, $options);
+ $options += $this->default;
if (!$options) {
return $options;
}
diff --git a/app/vendor/cakephp/migrations/src/MigrationsDispatcher.php b/app/vendor/cakephp/migrations/src/MigrationsDispatcher.php
index e75aa3d5e..e12f33a13 100644
--- a/app/vendor/cakephp/migrations/src/MigrationsDispatcher.php
+++ b/app/vendor/cakephp/migrations/src/MigrationsDispatcher.php
@@ -1,4 +1,6 @@
Phinx\Create::class,
+ 'Dump' => Phinx\Dump::class,
+ 'MarkMigrated' => Phinx\MarkMigrated::class,
+ 'Migrate' => Phinx\Migrate::class,
+ 'Rollback' => Phinx\Rollback::class,
+ 'Seed' => Phinx\Seed::class,
+ 'Status' => Phinx\Status::class,
+ 'CacheBuild' => Phinx\CacheBuild::class,
+ 'CacheClear' => Phinx\CacheClear::class,
+ ];
/**
* Class Constructor.
*
@@ -30,15 +46,9 @@ class MigrationsDispatcher extends Application
public function __construct($version)
{
parent::__construct('Migrations plugin, based on Phinx by Rob Morgan.', $version);
- $this->add(new Command\Create());
- $this->add(new Command\Dump());
- $this->add(new Command\MarkMigrated());
- $this->add(new Command\Migrate());
- $this->add(new Command\Rollback());
- $this->add(new Command\Seed());
- $this->add(new Command\Status());
- $this->add(new Command\CacheBuild());
- $this->add(new Command\CacheClear());
+ foreach (static::$phinxCommands as $key => $value) {
+ $this->add(new $value());
+ }
$this->setCatchExceptions(false);
}
}
diff --git a/app/vendor/cakephp/migrations/src/Plugin.php b/app/vendor/cakephp/migrations/src/Plugin.php
new file mode 100644
index 000000000..282a42456
--- /dev/null
+++ b/app/vendor/cakephp/migrations/src/Plugin.php
@@ -0,0 +1,82 @@
+discoverPlugin($this->getName());
+
+ return $collection->addMany($commands);
+ }
+ $commands = [];
+ foreach ($this->migrationCommandsList as $class) {
+ $name = $class::defaultName();
+ // If the short name has been used, use the full name.
+ // This allows app commands to have name preference.
+ // and app commands to overwrite migration commands.
+ if (!$collection->has($name)) {
+ $commands[$name] = $class;
+ }
+ // full name
+ $commands['migrations.' . $name] = $class;
+ }
+
+ return $collection->addMany($commands);
+ }
+}
diff --git a/app/vendor/cakephp/migrations/src/Shell/MigrationsShell.php b/app/vendor/cakephp/migrations/src/Shell/MigrationsShell.php
deleted file mode 100644
index 56661bc83..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/MigrationsShell.php
+++ /dev/null
@@ -1,187 +0,0 @@
-addOption('plugin', ['short' => 'p'])
- ->addOption('target', ['short' => 't'])
- ->addOption('connection', ['short' => 'c'])
- ->addOption('source', ['short' => 's'])
- ->addOption('seed')
- ->addOption('ansi')
- ->addOption('no-ansi')
- ->addOption('no-lock', ['boolean' => true])
- ->addOption('force', ['boolean' => true])
- ->addOption('version', ['short' => 'V'])
- ->addOption('no-interaction', ['short' => 'n'])
- ->addOption('template', ['short' => 't'])
- ->addOption('format', ['short' => 'f'])
- ->addOption('only', ['short' => 'o'])
- ->addOption('exclude', ['short' => 'x']);
- }
-
- /**
- * Defines constants that are required by phinx to get running
- *
- * @return void
- */
- public function initialize()
- {
- if (!defined('PHINX_VERSION')) {
- define('PHINX_VERSION', (0 === strpos('@PHINX_VERSION@', '@PHINX_VERSION')) ? '0.4.3' : '@PHINX_VERSION@');
- }
- parent::initialize();
- }
-
- /**
- * This acts as a front-controller for phinx. It just instantiates the classes
- * responsible for parsing the command line from phinx and gives full control of
- * the rest of the flow to it.
- *
- * The input parameter of the ``MigrationDispatcher::run()`` method is manually built
- * in case a MigrationsShell is dispatched using ``Shell::dispatch()``.
- *
- * @return bool Success of the call.
- */
- public function main()
- {
- $app = $this->getApp();
- $input = new ArgvInput($this->argv);
- $app->setAutoExit(false);
- $exitCode = $app->run($input, $this->getOutput());
-
- if (isset($this->argv[1]) && in_array($this->argv[1], ['migrate', 'rollback']) &&
- !$this->params['no-lock'] &&
- $exitCode === 0
- ) {
- $dispatchCommand = 'migrations dump';
- if (!empty($this->params['connection'])) {
- $dispatchCommand .= ' -c ' . $this->params['connection'];
- }
-
- if (!empty($this->params['plugin'])) {
- $dispatchCommand .= ' -p ' . $this->params['plugin'];
- }
-
- $dumpExitCode = $this->dispatchShell($dispatchCommand);
- }
-
- if (isset($dumpExitCode) && $exitCode === 0 && $dumpExitCode !== 0) {
- $exitCode = 1;
- }
-
- return $exitCode === 0;
- }
-
- /**
- * Returns the MigrationsDispatcher the Shell will have to use
- *
- * @return \Migrations\MigrationsDispatcher
- */
- protected function getApp()
- {
- return new MigrationsDispatcher(PHINX_VERSION);
- }
-
- /**
- * Returns the instance of OutputInterface the MigrationsDispatcher will have to use.
- *
- * @return \Symfony\Component\Console\Output\ConsoleOutput
- */
- protected function getOutput()
- {
- return new ConsoleOutput();
- }
-
- /**
- * Override the default behavior to save the command called
- * in order to pass it to the command dispatcher
- *
- * {@inheritDoc}
- */
- public function runCommand($argv, $autoMethod = false, $extra = [])
- {
- array_unshift($argv, 'migrations');
- $this->argv = $argv;
-
- return parent::runCommand($argv, $autoMethod, $extra);
- }
-
- /**
- * Display the help in the correct format
- *
- * @param string $command The command to get help for.
- * @return int|bool|null Exit code or number of bytes written to stdout
- */
- protected function displayHelp($command)
- {
- return $this->main();
- }
-
- /**
- * {@inheritDoc}
- */
- // @codingStandardsIgnoreStart
- protected function _displayHelp($command)
- {
- // @codingStandardsIgnoreEnd
- return $this->displayHelp($command);
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/CommandTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/CommandTask.php
deleted file mode 100644
index 08f5d9983..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/CommandTask.php
+++ /dev/null
@@ -1,54 +0,0 @@
-addOption('plugin', [
- 'short' => 'p',
- 'help' => 'The plugin the command should be applied to',
- 'required' => false
- ])
- ->addOption('connection', [
- 'short' => 'c',
- 'help' => 'The datasource connection to use',
- 'required' => false
- ])
- ->addOption('source', [
- 'short' => 's',
- 'help' => 'The name of the folder where migrations are stored',
- 'required' => false
- ])
- ->addOption('ansi')
- ->addOption('no-ansi')
- ->addOption('no-interaction', ['short' => 'n']);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/CreateTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/CreateTask.php
deleted file mode 100644
index b4fb8675c..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/CreateTask.php
+++ /dev/null
@@ -1,49 +0,0 @@
-addArgument('name', [
- 'help' => 'What is the name of the migration?'
- ])
- ->addOption('template', [
- 'short' => 't',
- 'help' => 'Use an alternative template',
- 'required' => false
- ])
- ->addOption('class', [
- 'short' => 'l',
- 'help' => 'Use a class implementing "' . Create::CREATION_INTERFACE . '" to generate the template',
- 'required' => false
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/DumpTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/DumpTask.php
deleted file mode 100644
index 28e74c6d7..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/DumpTask.php
+++ /dev/null
@@ -1,35 +0,0 @@
-setDescription('Dumps the current schema of the database to be used while baking a diff');
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/MarkMigratedTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/MarkMigratedTask.php
deleted file mode 100644
index 4d0beee63..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/MarkMigratedTask.php
+++ /dev/null
@@ -1,47 +0,0 @@
-addArgument('version', [
- 'help' => 'What is the version of the migration?'
- ])
- ->addOption('exclude', [
- 'short' => 'x',
- 'help' => 'If present it will mark migrations from beginning until the given version, excluding it',
- 'required' => false
- ])
- ->addOption('only', [
- 'short' => 'o',
- 'help' => 'If present it will only mark the given migration version',
- 'required' => false
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/MigrateTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/MigrateTask.php
deleted file mode 100644
index 384b6a1fe..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/MigrateTask.php
+++ /dev/null
@@ -1,48 +0,0 @@
-addOption('target', [
- 'short' => 't',
- 'help' => 'The version number to migrate to',
- 'required' => false
- ])
- ->addOption('date', [
- 'short' => 'd',
- 'help' => 'The date to migrate to',
- 'required' => false
- ])
- ->addOption('no-lock', [
- 'help' => 'If present, no lock file will be generated after migrating',
- 'boolean' => true
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/MigrationDiffTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/MigrationDiffTask.php
deleted file mode 100644
index 71a54f2d2..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/MigrationDiffTask.php
+++ /dev/null
@@ -1,538 +0,0 @@
-setup();
-
- if (!$this->checkSync()) {
- $this->error('Your migrations history is not in sync with your migrations files. ' .
- 'Make sure all your migrations have been migrated before baking a diff.');
-
- return 1;
- }
-
- if (empty($this->migrationsFiles) && empty($this->migratedItems)) {
- return $this->bakeSnapshot($name);
- }
-
- $collection = $this->getCollection($this->connection);
- EventManager::instance()->on('Bake.initialize', function (Event $event) use ($collection) {
- $event->getSubject()->loadHelper('Migrations.Migration', [
- 'collection' => $collection
- ]);
- });
-
- return parent::bake($name);
- }
-
- /**
- * Sets up everything the baking process needs
- *
- * @return void
- */
- public function setup()
- {
- $this->migrationsPath = $this->getPath();
- $this->migrationsFiles = glob($this->migrationsPath . '*.php');
- $this->phinxTable = $this->getPhinxTable($this->plugin);
-
- $connection = ConnectionManager::get($this->connection);
- $this->tables = $connection->getSchemaCollection()->listTables();
- $tableExists = in_array($this->phinxTable, $this->tables);
-
- $migratedItems = [];
- if ($tableExists) {
- $query = $connection->newQuery();
- $migratedItems = $query
- ->select(['version'])
- ->from($this->phinxTable)
- ->order(['version DESC'])
- ->execute()->fetchAll('assoc');
- }
-
- $this->migratedItems = $migratedItems;
- }
-
- /**
- * Get a collection from a database.
- *
- * @param string $connection Database connection name.
- * @return \Cake\Database\Schema\Collection
- */
- public function getCollection($connection)
- {
- $connection = ConnectionManager::get($connection);
-
- return $connection->getSchemaCollection();
- }
-
- /**
- * Process and prepare the data needed for the bake template to be generated.
- *
- * @return array
- */
- public function templateData()
- {
- $this->dumpSchema = $this->getDumpSchema();
- $this->currentSchema = $this->getCurrentSchema();
- $this->commonTables = array_intersect_key($this->currentSchema, $this->dumpSchema);
-
- $this->calculateDiff();
-
- return [
- 'data' => $this->templateData,
- 'dumpSchema' => $this->dumpSchema,
- 'currentSchema' => $this->currentSchema,
- ];
- }
-
- /**
- * This methods runs the various methods needed to calculate a diff between the current
- * state of the database and the schema dump file.
- *
- * @return void
- */
- protected function calculateDiff()
- {
- $this->getConstraints();
- $this->getIndexes();
- $this->getColumns();
- $this->getTables();
- }
-
- /**
- * Calculate the diff between the current state of the database and the schema dump
- * by returning an array containing the full \Cake\Database\Schema\Table definitions
- * of tables to be created and removed in the diff file.
- *
- * The method directly sets the diff in a property of the class.
- *
- * @return void
- */
- protected function getTables()
- {
- $this->templateData['fullTables'] = [
- 'add' => array_diff_key($this->currentSchema, $this->dumpSchema),
- 'remove' => array_diff_key($this->dumpSchema, $this->currentSchema)
- ];
- }
-
- /**
- * Calculate the diff between columns in existing tables.
- * This will look for columns addition, columns removal and changes in columns metadata
- * such as change of types or property such as length.
- *
- * Note that the method is not able to detect columns name change.
- * The method directly sets the diff in a property of the class.
- *
- * @return void
- */
- protected function getColumns()
- {
- foreach ($this->commonTables as $table => $currentSchema) {
- $currentColumns = $currentSchema->columns();
- $oldColumns = $this->dumpSchema[$table]->columns();
-
- // brand new columns
- $addedColumns = array_diff($currentColumns, $oldColumns);
- foreach ($addedColumns as $columnName) {
- $column = $currentSchema->getColumn($columnName);
- $key = array_search($columnName, $currentColumns);
- if ($key > 0) {
- $column['after'] = $currentColumns[$key - 1];
- }
- $this->templateData[$table]['columns']['add'][$columnName] = $column;
- }
-
- // changes in columns meta-data
- foreach ($currentColumns as $columnName) {
- $column = $currentSchema->getColumn($columnName);
- $oldColumn = $this->dumpSchema[$table]->getColumn($columnName);
- unset($column['collate']);
- unset($oldColumn['collate']);
-
- if (in_array($columnName, $oldColumns) &&
- $column !== $oldColumn
- ) {
- $changedAttributes = array_diff($column, $oldColumn);
-
- foreach (['type', 'length', 'null', 'default'] as $attribute) {
- $phinxAttributeName = $attribute;
- if ($attribute == 'length') {
- $phinxAttributeName = 'limit';
- }
- if (!isset($changedAttributes[$phinxAttributeName])) {
- $changedAttributes[$phinxAttributeName] = $column[$attribute];
- }
- }
-
- if (isset($changedAttributes['length'])) {
- if (!isset($changedAttributes['limit'])) {
- $changedAttributes['limit'] = $changedAttributes['length'];
- }
-
- unset($changedAttributes['length']);
- }
-
- $this->templateData[$table]['columns']['changed'][$columnName] = $changedAttributes;
- }
- }
-
- // columns deletion
- if (!isset($this->templateData[$table]['columns']['remove'])) {
- $this->templateData[$table]['columns']['remove'] = [];
- }
- $removedColumns = array_diff($oldColumns, $currentColumns);
- if (!empty($removedColumns)) {
- foreach ($removedColumns as $columnName) {
- $column = $this->dumpSchema[$table]->getColumn($columnName);
- $key = array_search($columnName, $oldColumns);
- if ($key > 0) {
- $column['after'] = $oldColumns[$key - 1];
- }
- $this->templateData[$table]['columns']['remove'][$columnName] = $column;
- }
- }
- }
- }
-
- /**
- * Calculate the diff between contraints in existing tables.
- * This will look for contraints addition, contraints removal and changes in contraints metadata
- * such as change of referenced columns if the old constraints and the new one have the same name.
- *
- * The method directly sets the diff in a property of the class.
- *
- * @return void
- */
- protected function getConstraints()
- {
- foreach ($this->commonTables as $table => $currentSchema) {
- $currentConstraints = $currentSchema->constraints();
- $oldConstraints = $this->dumpSchema[$table]->constraints();
-
- // brand new constraints
- $addedConstraints = array_diff($currentConstraints, $oldConstraints);
- foreach ($addedConstraints as $constraintName) {
- $this->templateData[$table]['constraints']['add'][$constraintName] =
- $currentSchema->getConstraint($constraintName);
- }
-
- // constraints having the same name between new and old schema
- // if present in both, check if they are the same : if not, remove the old one and add the new one
- foreach ($currentConstraints as $constraintName) {
- $constraint = $currentSchema->getConstraint($constraintName);
-
- if (in_array($constraintName, $oldConstraints) &&
- $constraint !== $this->dumpSchema[$table]->getConstraint($constraintName)
- ) {
- $this->templateData[$table]['constraints']['remove'][$constraintName] =
- $this->dumpSchema[$table]->getConstraint($constraintName);
- $this->templateData[$table]['constraints']['add'][$constraintName] =
- $constraint;
- }
- }
-
- // removed constraints
- $removedConstraints = array_diff($oldConstraints, $currentConstraints);
- foreach ($removedConstraints as $constraintName) {
- $constraint = $this->dumpSchema[$table]->getConstraint($constraintName);
- if ($constraint['type'] === Table::CONSTRAINT_FOREIGN) {
- $this->templateData[$table]['constraints']['remove'][$constraintName] = $constraint;
- } else {
- $this->templateData[$table]['indexes']['remove'][$constraintName] = $constraint;
- }
- }
- }
- }
-
- /**
- * Calculate the diff between indexes in existing tables.
- * This will look for indexes addition, indexes removal and changes in indexes metadata
- * such as change of referenced columns if the old indexes and the new one have the same name.
- *
- * The method directly sets the diff in a property of the class.
- *
- * @return void
- */
- protected function getIndexes()
- {
- foreach ($this->commonTables as $table => $currentSchema) {
- $currentIndexes = $currentSchema->indexes();
- $oldIndexes = $this->dumpSchema[$table]->indexes();
- sort($currentIndexes);
- sort($oldIndexes);
-
- // brand new indexes
- $addedIndexes = array_diff($currentIndexes, $oldIndexes);
- foreach ($addedIndexes as $indexName) {
- $this->templateData[$table]['indexes']['add'][$indexName] = $currentSchema->getIndex($indexName);
- }
-
- // indexes having the same name between new and old schema
- // if present in both, check if they are the same : if not, remove the old one and add the new one
- foreach ($currentIndexes as $indexName) {
- $index = $currentSchema->getIndex($indexName);
-
- if (in_array($indexName, $oldIndexes) &&
- $index !== $this->dumpSchema[$table]->getIndex($indexName)
- ) {
- $this->templateData[$table]['indexes']['remove'][$indexName] =
- $this->dumpSchema[$table]->getIndex($indexName);
- $this->templateData[$table]['indexes']['add'][$indexName] = $index;
- }
- }
-
- // indexes deletion
- if (!isset($this->templateData[$table]['indexes']['remove'])) {
- $this->templateData[$table]['indexes']['remove'] = [];
- }
-
- $removedIndexes = array_diff($oldIndexes, $currentIndexes);
- $parts = [];
- if (!empty($removedIndexes)) {
- foreach ($removedIndexes as $index) {
- $parts[$index] = $this->dumpSchema[$table]->getIndex($index);
- }
- }
- $this->templateData[$table]['indexes']['remove'] = array_merge(
- $this->templateData[$table]['indexes']['remove'],
- $parts
- );
- }
- }
-
- /**
- * Checks that the migrations history is in sync with the migrations files
- *
- * @return bool Whether migrations history is sync or not
- */
- protected function checkSync()
- {
- if (empty($this->migrationsFiles) && empty($this->migratedItems)) {
- return true;
- }
-
- if (!empty($this->migratedItems)) {
- $lastVersion = $this->migratedItems[0]['version'];
- $lastFile = end($this->migrationsFiles);
-
- return (bool)strpos($lastFile, (string)$lastVersion);
- }
-
- return false;
- }
-
- /**
- * Fallback method called to bake a snapshot when the phinx log history is empty and
- * there are no migration files.
- *
- * @param string $name Name.
- * @return int Value of the snapshot baking dispatch process
- */
- protected function bakeSnapshot($name)
- {
- $this->out('Your migrations history is empty and you do not have any migrations files.');
- $this->out('Falling back to baking a snapshot...');
- $dispatchCommand = 'bake migration_snapshot ' . $name;
-
- if (!empty($this->params['connection'])) {
- $dispatchCommand .= ' -c ' . $this->params['connection'];
- }
- if (!empty($this->params['plugin'])) {
- $dispatchCommand .= ' -p ' . $this->params['plugin'];
- }
-
- $dispatch = $this->dispatchShell([
- 'command' => $dispatchCommand
- ]);
-
- if ($dispatch === 1) {
- $this->error('Something went wrong during the snapshot baking. Please try again.');
- }
-
- return $dispatch;
- }
-
- /**
- * Fetch the correct schema dump based on the arguments and options passed to the shell call
- * and returns it as an array
- *
- * @return array Full database schema : the key is the name of the table and the value is
- * an instance of \Cake\Database\Schema\Table.
- */
- protected function getDumpSchema()
- {
- $inputArgs = [];
-
- $connectionName = 'default';
- if (!empty($this->params['connection'])) {
- $connectionName = $inputArgs['--connection'] = $this->params['connection'];
- }
- if (!empty($this->params['plugin'])) {
- $inputArgs['--plugin'] = $this->params['plugin'];
- }
-
- $className = '\Migrations\Command\Dump';
- $definition = (new $className())->getDefinition();
-
- $input = new ArrayInput($inputArgs, $definition);
- $path = $this->getOperationsPath($input) . DS . 'schema-dump-' . $connectionName . '.lock';
-
- if (!file_exists($path)) {
- $msg = 'Unable to retrieve the schema dump file. You can create a dump file using ' .
- 'the `cake migrations dump` command';
- $this->error($msg);
- }
-
- return unserialize(file_get_contents($path));
- }
-
- /**
- * Reflects the current database schema.
- *
- * @return array Full database schema : the key is the name of the table and the value is
- * an instance of \Cake\Database\Schema\Table.
- */
- protected function getCurrentSchema()
- {
- $schema = [];
-
- if (empty($this->tables)) {
- return $schema;
- }
-
- $collection = ConnectionManager::get($this->connection)->getSchemaCollection();
- foreach ($this->tables as $table) {
- if (preg_match("/^.*phinxlog$/", $table) === 1) {
- continue;
- }
-
- $schema[$table] = $collection->describe($table);
- }
-
- return $schema;
- }
-
- /**
- * {@inheritDoc}
- */
- public function template()
- {
- return 'Migrations.config/diff';
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->addArgument('name', [
- 'help' => 'Name of the migration to bake. Can use Plugin.name to bake migration files into plugins.',
- 'required' => true
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/MigrationSnapshotTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/MigrationSnapshotTask.php
deleted file mode 100644
index af777f593..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/MigrationSnapshotTask.php
+++ /dev/null
@@ -1,156 +0,0 @@
-getCollection($this->connection);
- EventManager::instance()->on('Bake.initialize', function (Event $event) use ($collection) {
- $event->getSubject()->loadHelper('Migrations.Migration', [
- 'collection' => $collection
- ]);
- });
-
- return parent::bake($name);
- }
-
- /**
- * {@inheritDoc}
- */
- public function template()
- {
- return 'Migrations.config/snapshot';
- }
-
- /**
- * {@inheritDoc}
- */
- public function templateData()
- {
- $namespace = Configure::read('App.namespace');
- $pluginPath = '';
- if ($this->plugin) {
- $namespace = $this->_pluginNamespace($this->plugin);
- $pluginPath = $this->plugin . '.';
- }
-
- $collection = $this->getCollection($this->connection);
- $options = [
- 'require-table' => $this->params['require-table'],
- 'plugin' => $this->plugin
- ];
- $tables = $this->getTablesToBake($collection, $options);
-
- sort($tables, SORT_NATURAL);
-
- $tables = array_combine($tables, $tables);
-
- $autoId = true;
- if (isset($this->params['disable-autoid'])) {
- $autoId = !$this->params['disable-autoid'];
- }
-
- return [
- 'plugin' => $this->plugin,
- 'pluginPath' => $pluginPath,
- 'namespace' => $namespace,
- 'collection' => $collection,
- 'tables' => $tables,
- 'action' => 'create_table',
- 'name' => $this->BakeTemplate->viewVars['name'],
- 'autoId' => $autoId
- ];
- }
-
- /**
- * Get a collection from a database
- *
- * @param string $connection Database connection name.
- * @return \Cake\Database\Schema\Collection
- */
- public function getCollection($connection)
- {
- $connection = ConnectionManager::get($connection);
-
- return $connection->getSchemaCollection();
- }
-
- /**
- * To check if a Table Model is to be added in the migration file
- *
- * @param string $tableName Table name in underscore case.
- * @param string|null $pluginName Plugin name if exists.
- * @deprecated Will be removed in the next version
- * @return bool True if the model is to be added.
- */
- public function tableToAdd($tableName, $pluginName = null)
- {
- return true;
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $parser = parent::getOptionParser();
-
- $parser->setDescription(
- 'Bake migration snapshot class.'
- )->addArgument('name', [
- 'help' => 'Name of the migration to bake. Can use Plugin.name to bake migration files into plugins.',
- 'required' => true
- ])
- ->addOption('require-table', [
- 'boolean' => true,
- 'default' => false,
- 'help' => 'If require-table is set to true, check also that the table class exists.'
- ])->addOption('disable-autoid', [
- 'boolean' => true,
- 'default' => false,
- 'help' => 'Disable phinx behavior of automatically adding an id field.'
- ])
- ->addOption('no-lock', [
- 'help' => 'If present, no lock file will be generated after baking',
- 'boolean' => true
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/MigrationTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/MigrationTask.php
deleted file mode 100644
index 94698d194..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/MigrationTask.php
+++ /dev/null
@@ -1,131 +0,0 @@
-on('Bake.initialize', function (Event $event) {
- $event->getSubject()->loadHelper('Migrations.Migration');
- });
-
- return parent::bake($name);
- }
-
- /**
- * {@inheritDoc}
- */
- public function template()
- {
- return 'Migrations.config/skeleton';
- }
-
- /**
- * {@inheritdoc}
- */
- public function templateData()
- {
- $className = $this->BakeTemplate->viewVars['name'];
- $namespace = Configure::read('App.namespace');
- $pluginPath = '';
- if ($this->plugin) {
- $namespace = $this->_pluginNamespace($this->plugin);
- $pluginPath = $this->plugin . '.';
- }
-
- $action = $this->detectAction($className);
-
- if (empty($action)) {
- return [
- 'plugin' => $this->plugin,
- 'pluginPath' => $pluginPath,
- 'namespace' => $namespace,
- 'tables' => [],
- 'action' => null,
- 'name' => $className
- ];
- }
-
- $arguments = $this->args;
- unset($arguments[0]);
- $columnParser = new ColumnParser;
- $fields = $columnParser->parseFields($arguments);
- $indexes = $columnParser->parseIndexes($arguments);
- $primaryKey = $columnParser->parsePrimaryKey($arguments);
-
- if (in_array($action[0], ['alter_table', 'add_field']) && !empty($primaryKey)) {
- $this->error('Adding a primary key to an already existing table is not supported.');
- }
-
- list($action, $table) = $action;
-
- return [
- 'plugin' => $this->plugin,
- 'pluginPath' => $pluginPath,
- 'namespace' => $namespace,
- 'tables' => [$table],
- 'action' => $action,
- 'columns' => [
- 'fields' => $fields,
- 'indexes' => $indexes,
- 'primaryKey' => $primaryKey
- ],
- 'name' => $className
- ];
- }
-
- /**
- * Detects the action and table from the name of a migration
- *
- * @param string $name Name of migration
- * @return array
- **/
- public function detectAction($name)
- {
- if (preg_match('/^(Create|Drop)(.*)/', $name, $matches)) {
- $action = strtolower($matches[1]) . '_table';
- $table = Inflector::underscore($matches[2]);
- } elseif (preg_match('/^(Add).+?(?:To)(.*)/', $name, $matches)) {
- $action = 'add_field';
- $table = Inflector::underscore($matches[2]);
- } elseif (preg_match('/^(Remove).+?(?:From)(.*)/', $name, $matches)) {
- $action = 'drop_field';
- $table = Inflector::underscore($matches[2]);
- } elseif (preg_match('/^(Alter)(.*)/', $name, $matches)) {
- $action = 'alter_table';
- $table = Inflector::underscore($matches[2]);
- } else {
- return [];
- }
-
- return [$action, $table];
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/RollbackTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/RollbackTask.php
deleted file mode 100644
index 46c2f88b8..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/RollbackTask.php
+++ /dev/null
@@ -1,48 +0,0 @@
-addOption('target', [
- 'short' => 't',
- 'help' => 'The version number to migrate to',
- 'required' => false
- ])
- ->addOption('date', [
- 'short' => 'd',
- 'help' => 'The date to migrate to',
- 'required' => false
- ])
- ->addOption('no-lock', [
- 'help' => 'If present, no lock file will be generated after rolling back',
- 'boolean' => true
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/SeedTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/SeedTask.php
deleted file mode 100644
index 7e944d027..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/SeedTask.php
+++ /dev/null
@@ -1,258 +0,0 @@
-pathFragment;
- if (isset($this->plugin)) {
- $path = $this->_pluginPath($this->plugin) . $this->pathFragment;
- }
-
- return str_replace('/', DS, $path);
- }
-
- /**
- * {@inheritDoc}
- */
- public function template()
- {
- return 'Migrations.Seed/seed';
- }
-
- /**
- * Get template data.
- *
- * @return array
- */
- public function templateData()
- {
- $namespace = Configure::read('App.namespace');
- if ($this->plugin) {
- $namespace = $this->_pluginNamespace($this->plugin);
- }
-
- $table = Inflector::tableize($this->args[0]);
- if (!empty($this->params['table'])) {
- $table = $this->params['table'];
- }
-
- $records = false;
- if ($this->param('data')) {
- $limit = (int)$this->param('limit');
-
- $fields = $this->param('fields') ?: '*';
- if ($fields !== '*') {
- $fields = explode(',', $fields);
- }
-
- $connection = ConnectionManager::get($this->connection);
-
- $query = $connection->newQuery()
- ->from($table)
- ->select($fields);
-
- if ($limit) {
- $query->limit($limit);
- }
-
- $records = $connection->execute($query)->fetchAll('assoc');
- $records = $this->prettifyArray($records);
- }
-
- return [
- 'className' => $this->BakeTemplate->viewVars['name'],
- 'namespace' => $namespace,
- 'records' => $records,
- 'table' => $table,
- ];
- }
-
- /**
- * {@inheritDoc}
- */
- public function bake($name)
- {
- $this->params['no-test'] = true;
-
- return parent::bake($name);
- }
-
- /**
- * Gets the option parser instance and configures it.
- *
- * @return \Cake\Console\ConsoleOptionParser
- */
- public function getOptionParser()
- {
- $name = ($this->plugin ? $this->plugin . '.' : '') . $this->name;
- $parser = new ConsoleOptionParser($name);
-
- $bakeThemes = [];
- foreach (Plugin::loaded() as $plugin) {
- $path = Plugin::classPath($plugin);
- if (is_dir($path . 'Template' . DS . 'Bake')) {
- $bakeThemes[] = $plugin;
- }
- }
-
- $parser->setDescription(
- 'Bake seed class.'
- )->addOption('plugin', [
- 'short' => 'p',
- 'help' => 'Plugin to bake into.'
- ])->addOption('force', [
- 'short' => 'f',
- 'boolean' => true,
- 'help' => 'Force overwriting existing files without prompting.'
- ])->addOption('connection', [
- 'short' => 'c',
- 'default' => 'default',
- 'help' => 'The datasource connection to get data from.'
- ])->addOption('table', [
- 'help' => 'The database table to use.'
- ])->addOption('theme', [
- 'short' => 't',
- 'help' => 'The theme to use when baking code.',
- 'choices' => $bakeThemes
- ])->addArgument('name', [
- 'help' => 'Name of the seed to bake. Can use Plugin.name to bake plugin models.'
- ])->addOption('data', [
- 'boolean' => true,
- 'help' => 'Include data from the table to the seed'
- ])->addOption('fields', [
- 'default' => '*',
- 'help' => 'If including data, comma separated list of fields to select (all fields by default)',
- ])->addOption('limit', [
- 'short' => 'l',
- 'help' => 'If including data, max number of rows to select'
- ]);
-
- return $parser;
- }
-
- /**
- * Prettify var_export of an array output
- *
- * @param array $array Array to prettify
- * @param int $tabCount Initial tab count
- * @param string $indentCharacter Desired indent for the code.
- * @return string
- */
- protected function prettifyArray($array, $tabCount = 3, $indentCharacter = " ")
- {
- $content = var_export($array, true);
-
- $lines = explode("\n", $content);
-
- $inString = false;
-
- foreach ($lines as $k => &$line) {
- if ($k === 0) {
- // First row
- $line = '[';
- continue;
- }
-
- if ($k === count($lines) - 1) {
- // Last row
- $line = str_repeat($indentCharacter, --$tabCount) . ']';
- continue;
- }
-
- $line = ltrim($line);
-
- if (!$inString) {
- if ($line === '),') {
- //Check for closing bracket
- $line = '],';
- $tabCount--;
- } elseif (preg_match("/^\d+\s\=\>\s$/", $line)) {
- // Mark '0 =>' kind of lines to remove
- $line = false;
- continue;
- }
-
- //Insert tab count
- $line = str_repeat($indentCharacter, $tabCount) . $line;
- }
-
- $length = strlen($line);
- for ($j = 0; $j < $length; $j++) {
- if ($line[$j] === '\\') {
- //skip character right after an escape \
- $j++;
- } elseif ($line[$j] === '\'') {
- //check string open/end
- $inString = !$inString;
- }
- }
-
- //check for opening bracket
- if (!$inString && trim($line) === 'array (') {
- $line = str_replace('array (', '[', $line);
- $tabCount++;
- }
- }
- unset($line);
-
- // Remove marked lines
- $lines = array_filter($lines, function ($line) {
- return $line !== false;
- });
-
- return implode("\n", $lines);
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/SimpleMigrationTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/SimpleMigrationTask.php
index 89428d492..4287bfab2 100644
--- a/app/vendor/cakephp/migrations/src/Shell/Task/SimpleMigrationTask.php
+++ b/app/vendor/cakephp/migrations/src/Shell/Task/SimpleMigrationTask.php
@@ -1,4 +1,6 @@
getMigrationName($name);
@@ -50,9 +52,9 @@ public function fileName($name)
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function getPath()
+ public function getPath(): string
{
$path = ROOT . DS . $this->pathFragment;
if (isset($this->plugin)) {
@@ -63,9 +65,9 @@ public function getPath()
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
- public function bake($name)
+ public function bake(string $name): string
{
$migrationWithSameName = glob($this->getPath() . '*_' . $name . '.php');
if (!empty($migrationWithSameName)) {
@@ -124,14 +126,14 @@ protected function getMigrationName($name = null)
*
* @return \Cake\Console\ConsoleOptionParser
*/
- public function getOptionParser()
+ public function getOptionParser(): ConsoleOptionParser
{
$name = ($this->plugin ? $this->plugin . '.' : '') . $this->name;
$parser = new ConsoleOptionParser($name);
$bakeThemes = [];
- foreach (Plugin::loaded() as $plugin) {
- $path = Plugin::classPath($plugin);
+ foreach (CorePlugin::loaded() as $plugin) {
+ $path = CorePlugin::classPath($plugin);
if (is_dir($path . 'Template' . DS . 'Bake')) {
$bakeThemes[] = $plugin;
}
@@ -142,22 +144,22 @@ public function getOptionParser()
)
->addOption('plugin', [
'short' => 'p',
- 'help' => 'Plugin to bake into.'
+ 'help' => 'Plugin to bake into.',
])
->addOption('force', [
'short' => 'f',
'boolean' => true,
- 'help' => 'Force overwriting existing file if a migration already exists with the same name.'
+ 'help' => 'Force overwriting existing file if a migration already exists with the same name.',
])
->addOption('connection', [
'short' => 'c',
'default' => 'default',
- 'help' => 'The datasource connection to get data from.'
+ 'help' => 'The datasource connection to get data from.',
])
->addOption('theme', [
'short' => 't',
'help' => 'The theme to use when baking code.',
- 'choices' => $bakeThemes
+ 'choices' => $bakeThemes,
]);
return $parser;
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/SnapshotTrait.php b/app/vendor/cakephp/migrations/src/Shell/Task/SnapshotTrait.php
deleted file mode 100644
index 96218dcb5..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/SnapshotTrait.php
+++ /dev/null
@@ -1,97 +0,0 @@
-markSnapshotApplied($path);
-
- if (!isset($this->params['no-lock']) || !$this->params['no-lock']) {
- $this->refreshDump();
- }
- }
-
- return $createFile;
- }
-
- /**
- * Will mark a snapshot created, the snapshot being identified by its
- * full file path.
- *
- * @param string $path Path to the newly created snapshot
- * @return void
- */
- protected function markSnapshotApplied($path)
- {
- $fileName = pathinfo($path, PATHINFO_FILENAME);
- list($version, ) = explode('_', $fileName, 2);
-
- $dispatchCommand = 'migrations mark_migrated -t ' . $version . ' -o';
- if (!empty($this->params['connection'])) {
- $dispatchCommand .= ' -c ' . $this->params['connection'];
- }
-
- if (!empty($this->params['plugin'])) {
- $dispatchCommand .= ' -p ' . $this->params['plugin'];
- }
-
- $this->_io->out('Marking the migration ' . $fileName . ' as migrated...');
- $this->dispatchShell($dispatchCommand);
- }
-
- /**
- * After a file has been successfully created, we refresh the dump of the database
- * to be able to generate a new diff afterward.
- *
- * @return void
- */
- protected function refreshDump()
- {
- $dispatchCommand = 'migrations dump';
- if (!empty($this->params['connection'])) {
- $dispatchCommand .= ' -c ' . $this->params['connection'];
- }
-
- if (!empty($this->params['plugin'])) {
- $dispatchCommand .= ' -p ' . $this->params['plugin'];
- }
-
- $this->_io->out('Creating a dump of the new database state...');
- $this->dispatchShell($dispatchCommand);
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Shell/Task/StatusTask.php b/app/vendor/cakephp/migrations/src/Shell/Task/StatusTask.php
deleted file mode 100644
index cbda1974b..000000000
--- a/app/vendor/cakephp/migrations/src/Shell/Task/StatusTask.php
+++ /dev/null
@@ -1,38 +0,0 @@
-addOption('format', [
- 'short' => 'f',
- 'help' => 'The output format: text or json. Defaults to text.',
- 'required' => false
- ]);
-
- return $parser;
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Table.php b/app/vendor/cakephp/migrations/src/Table.php
index 42fd6a0b4..55414fa4d 100644
--- a/app/vendor/cakephp/migrations/src/Table.php
+++ b/app/vendor/cakephp/migrations/src/Table.php
@@ -1,4 +1,6 @@
convertedAutoIncrement($options);
+
+ return parent::addColumn($columnName, $type, $options);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * You can pass `autoIncrement` as an option and it will be converted
+ * to the correct option for phinx to create the column with an
+ * auto increment attribute
+ *
+ * @param string $columnName Column Name
+ * @param string|\Phinx\Db\Table\Column|\Phinx\Util\Literal $newColumnType New Column Type
+ * @param array $options Options
+ * @return $this
+ */
+ public function changeColumn($columnName, $newColumnType, array $options = [])
+ {
+ $options = $this->convertedAutoIncrement($options);
+
+ return parent::changeColumn($columnName, $newColumnType, $options);
+ }
+
+ /**
+ * Convert the `autoIncrement` option to the correct options for phinx.
+ *
+ * @param array $options Options
+ * @return array Converted options
+ */
+ protected function convertedAutoIncrement(array $options)
{
if (isset($options['autoIncrement']) && $options['autoIncrement'] === true) {
$options['identity'] = true;
unset($options['autoIncrement']);
}
- return parent::addColumn($columnName, $type, $options);
+ return $options;
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*
* If using MySQL and no collation information has been given to the table options, a request to the information
* schema will be made to get the default database collation and apply it to the database. This is to prevent
* phinx default mechanism to put the collation to a default of "utf8_general_ci".
+ *
+ * @return void
*/
public function create()
{
- if ((!isset($this->options['id']) || $this->options['id'] === false) && !empty($this->primaryKey)) {
- $this->options['primary_key'] = $this->primaryKey;
+ $options = $this->getTable()->getOptions();
+ if ((!isset($options['id']) || $options['id'] === false) && !empty($this->primaryKey)) {
+ $options['primary_key'] = $this->primaryKey;
$this->filterPrimaryKey();
}
- $options = $this->getOptions();
if ($this->getAdapter()->getAdapterType() === 'mysql' && empty($options['collation'])) {
$encodingRequest = 'SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = "%s"';
@@ -80,31 +127,32 @@ public function create()
$connectionConfig = $cakeConnection->config();
$encodingRequest = sprintf($encodingRequest, $connectionConfig['database']);
- $defaultEncoding = $cakeConnection->execute($encodingRequest)->fetch('assoc');
+ /** @var \Cake\Database\StatementInterface $statement */
+ $statement = $cakeConnection->execute($encodingRequest);
+ $defaultEncoding = $statement->fetch('assoc');
if (!empty($defaultEncoding['DEFAULT_COLLATION_NAME'])) {
$options['collation'] = $defaultEncoding['DEFAULT_COLLATION_NAME'];
- $this->setOptions($options);
}
}
+ $this->getTable()->setOptions($options);
+
parent::create();
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*
* After a table update, the TableRegistry should be cleared in order to prevent issues with
* table schema stored in Table objects having columns that might have been renamed or removed during
* the update process.
+ *
+ * @return void
*/
public function update()
{
- if ($this->getAdapter()->getAdapterType() == 'sqlite') {
- $this->foreignKeys = [];
- }
-
parent::update();
- TableRegistry::clear();
+ $this->getTableLocator()->clear();
}
/**
@@ -113,10 +161,14 @@ public function update()
* We disable foreign key deletion for the SQLite adapter as SQLite does not support the feature natively and the
* process implemented by Phinx has serious side-effects (for instance it rename FK references in existing tables
* which breaks the database schema cohesion).
+ *
+ * @param string|array $columns Column(s)
+ * @param string|null $constraint Constraint names
+ * @return $this
*/
public function dropForeignKey($columns, $constraint = null)
{
- if ($this->getAdapter()->getAdapterType() == 'sqlite') {
+ if ($this->getAdapter()->getAdapterType() === 'sqlite') {
return $this;
}
@@ -134,18 +186,26 @@ public function dropForeignKey($columns, $constraint = null)
*/
protected function filterPrimaryKey()
{
- if ($this->getAdapter()->getAdapterType() !== 'sqlite' || empty($this->options['primary_key'])) {
+ $options = $this->getTable()->getOptions();
+ if ($this->getAdapter()->getAdapterType() !== 'sqlite' || empty($options['primary_key'])) {
return;
}
- $primaryKey = $this->options['primary_key'];
+ $primaryKey = $options['primary_key'];
if (!is_array($primaryKey)) {
$primaryKey = [$primaryKey];
}
$primaryKey = array_flip($primaryKey);
- $columnsCollection = new Collection($this->columns);
- $primaryKeyColumns = $columnsCollection->filter(function ($columnDef, $key) use ($primaryKey) {
+ $columnsCollection = (new Collection($this->actions->getActions()))
+ ->filter(function ($action) {
+ return $action instanceof \Phinx\Db\Action\AddColumn;
+ })
+ ->map(function ($action) {
+ /** @var \Phinx\Db\Action\ChangeColumn|\Phinx\Db\Action\RenameColumn|\Phinx\Db\Action\RemoveColumn|\Phinx\Db\Action\AddColumn $action */
+ return $action->getColumn();
+ });
+ $primaryKeyColumns = $columnsCollection->filter(function (Column $columnDef, $key) use ($primaryKey) {
return isset($primaryKey[$columnDef->getName()]);
})->toArray();
@@ -162,9 +222,11 @@ protected function filterPrimaryKey()
$primaryKey = array_flip($primaryKey);
if (!empty($primaryKey)) {
- $this->options['primary_key'] = $primaryKey;
+ $options['primary_key'] = $primaryKey;
} else {
- unset($this->options['primary_key']);
+ unset($options['primary_key']);
}
+
+ $this->getTable()->setOptions($options);
}
}
diff --git a/app/vendor/cakephp/migrations/src/TableFinderTrait.php b/app/vendor/cakephp/migrations/src/TableFinderTrait.php
index 0b2efc6b4..738cd883b 100644
--- a/app/vendor/cakephp/migrations/src/TableFinderTrait.php
+++ b/app/vendor/cakephp/migrations/src/TableFinderTrait.php
@@ -1,4 +1,6 @@
false, 'plugin' => null], $options);
+ $options += [
+ 'require-table' => false,
+ 'plugin' => null,
+ ];
$tables = $collection->listTables();
if (empty($tables)) {
@@ -67,19 +72,20 @@ protected function getTablesToBake(Collection $collection, $options = [])
$config = ConnectionManager::getConfig($this->connection);
$key = isset($config['schema']) ? 'schema' : 'database';
+ /** @psalm-suppress PossiblyNullArrayAccess */
if ($config[$key] === $splitted[1]) {
$table = $splitted[0];
}
}
- if (!in_array($table, $tables)) {
+ if (!in_array($table, $tables, true)) {
unset($tableNamesInModel[$num]);
}
}
$tables = $tableNamesInModel;
} else {
foreach ($tables as $num => $table) {
- if ((in_array($table, $this->skipTables)) || (strpos($table, $this->skipTablesRegex) !== false)) {
+ if (in_array($table, $this->skipTables, true) || (strpos($table, $this->skipTablesRegex) !== false)) {
unset($tables[$num]);
continue;
}
@@ -93,11 +99,11 @@ protected function getTablesToBake(Collection $collection, $options = [])
* Gets list Tables Names
*
* @param string|null $pluginName Plugin name if exists.
- * @return array
+ * @return string[]
*/
protected function getTableNames($pluginName = null)
{
- if ($pluginName !== null && !Plugin::loaded($pluginName)) {
+ if ($pluginName !== null && !CorePlugin::getCollection()->has($pluginName)) {
return [];
}
$list = [];
@@ -124,8 +130,9 @@ protected function findTables($pluginName = null)
{
$path = 'Model' . DS . 'Table' . DS;
if ($pluginName) {
- $path = Plugin::path($pluginName) . 'src' . DS . $path;
+ $path = CorePlugin::path($pluginName) . 'src' . DS . $path;
} else {
+ /** @psalm-suppress UndefinedConstant */
$path = APP . $path;
}
@@ -133,10 +140,10 @@ protected function findTables($pluginName = null)
return [];
}
- $tableDir = new Folder($path);
- $tableDir = $tableDir->find('.*\.php');
+ $files = (new Filesystem())->find($path, '/\.php$/i', FilesystemIterator::KEY_AS_FILENAME
+ | FilesystemIterator::UNIX_PATHS);
- return $tableDir;
+ return array_keys(iterator_to_array($files));
}
/**
@@ -144,7 +151,7 @@ protected function findTables($pluginName = null)
*
* @param string $className Name of Table Class.
* @param string|null $pluginName Plugin name if exists.
- * @return array
+ * @return string[]
*/
protected function fetchTableName($className, $pluginName = null)
{
@@ -156,7 +163,7 @@ protected function fetchTableName($className, $pluginName = null)
$namespacedClassName = App::className($className, 'Model/Table', 'Table');
- if (!class_exists($namespacedClassName)) {
+ if ($namespacedClassName === null || !class_exists($namespacedClassName)) {
return $tables;
}
@@ -165,19 +172,24 @@ protected function fetchTableName($className, $pluginName = null)
return $tables;
}
- $table = TableRegistry::get($className);
+ $table = TableRegistry::getTableLocator()->get($className);
foreach ($table->associations()->keys() as $key) {
+ /** @psalm-suppress PossiblyNullReference */
if ($table->associations()->get($key)->type() === 'belongsToMany') {
- $tables[] = $table->associations()->get($key)->junction()->getTable();
+ /** @var \Cake\ORM\Association\BelongsToMany $belongsToMany */
+ $belongsToMany = $table->associations()->get($key);
+ $tables[] = $belongsToMany->junction()->getTable();
}
}
$tableName = $table->getTable();
$splitted = array_reverse(explode('.', $tableName, 2));
if (isset($splitted[1])) {
$config = ConnectionManager::getConfig($this->connection);
- $key = isset($config['schema']) ? 'schema' : 'database';
- if ($config[$key] === $splitted[1]) {
- $tableName = $splitted[0];
+ if ($config) {
+ $key = isset($config['schema']) ? 'schema' : 'database';
+ if ($config[$key] === $splitted[1]) {
+ $tableName = $splitted[0];
+ }
}
}
$tables[] = $tableName;
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-columns.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-columns.ctp
deleted file mode 100644
index 0238b2055..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-columns.ctp
+++ /dev/null
@@ -1,12 +0,0 @@
-<% foreach ($columns as $columnName => $columnAttributes):
-$type = $columnAttributes['type'];
-unset($columnAttributes['type']);
-
-$columnAttributes = $this->Migration->getColumnOption($columnAttributes);
-$columnAttributes = $this->Migration->stringifyList($columnAttributes, ['indent' => 4]);
-if (!empty($columnAttributes)): %>
- ->addColumn('<%= $columnName %>', '<%= $type %>', [<%= $columnAttributes %>])
-<% else: %>
- ->addColumn('<%= $columnName %>', '<%= $type %>')
-<% endif; %>
-<% endforeach; %>
\ No newline at end of file
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-foreign-keys-from-create.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-foreign-keys-from-create.ctp
deleted file mode 100644
index 001ce8162..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-foreign-keys-from-create.ctp
+++ /dev/null
@@ -1,3 +0,0 @@
-<% foreach ($constraints as $table => $tableConstraints):
- echo $this->element('Migrations.add-foreign-keys', ['constraints' => $tableConstraints, 'table' => $table]);
-endforeach; %>
\ No newline at end of file
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-foreign-keys.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-foreign-keys.ctp
deleted file mode 100644
index 1829e3108..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-foreign-keys.ctp
+++ /dev/null
@@ -1,44 +0,0 @@
-<%
-$statement = $this->Migration->tableStatement($table, true);
-$hasProcessedConstraint = false;
-%>
-<% foreach ($constraints as $constraint):
- $constraintColumns = $constraint['columns'];
- sort($constraintColumns);
- if ($constraint['type'] !== 'unique'):
- $hasProcessedConstraint = true;
- $columnsList = '\'' . $constraint['columns'][0] . '\'';
- if (count($constraint['columns']) > 1):
- $columnsList = '[' . $this->Migration->stringifyList($constraint['columns'], ['indent' => 5]) . ']';
- endif;
- $this->Migration->returnedData['dropForeignKeys'][$table][] = $columnsList;
-
- if (is_array($constraint['references'][1])):
- $columnsReference = '[' . $this->Migration->stringifyList($constraint['references'][1], ['indent' => 5]) . ']';
- else:
- $columnsReference = '\'' . $constraint['references'][1] . '\'';
- endif;
-
- if (!isset($statement)):
- $statement = $this->Migration->tableStatement($table);
- endif;
-
- if (!empty($statement)): %>
-
- <%= $statement %>
-<% unset($statement);
- endif; %>
- ->addForeignKey(
- <%= $columnsList %>,
- '<%= $constraint['references'][0] %>',
- <%= $columnsReference %>,
- [
- 'update' => '<%= $this->Migration->formatConstraintAction($constraint['update']) %>',
- 'delete' => '<%= $this->Migration->formatConstraintAction($constraint['delete']) %>'
- ]
- )
-<% endif; %>
-<% endforeach; %>
-<% if (isset($this->Migration->tableStatements[$table]) && $hasProcessedConstraint): %>
- ->update();
-<% endif; %>
\ No newline at end of file
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-indexes.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-indexes.ctp
deleted file mode 100644
index d3676d810..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/Element/add-indexes.ctp
+++ /dev/null
@@ -1,12 +0,0 @@
-<% foreach ($indexes as $indexName => $index): %>
- ->addIndex(
- [<% echo $this->Migration->stringifyList($index['columns'], ['indent' => 5]); %>],
- [<%
- $params = ['name' => $indexName];
- if ($index['type'] === 'unique'):
- $params['unique'] = true;
- endif;
- echo $this->Migration->stringifyList($params, ['indent' => 5]);
- %>]
- )
-<% endforeach; %>
\ No newline at end of file
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/Element/create-tables.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/Element/create-tables.ctp
deleted file mode 100644
index a1fa448e2..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/Element/create-tables.ctp
+++ /dev/null
@@ -1,80 +0,0 @@
-<% foreach ($tables as $table => $schema):
- $tableArgForMethods = $useSchema === true ? $schema : $table;
- $tableArgForArray = $useSchema === true ? $table : $schema;
-
-$foreignKeys = [];
-$primaryKeysColumns = $this->Migration->primaryKeysColumnsList($tableArgForMethods);
-$primaryKeys = $this->Migration->primaryKeys($tableArgForMethods);
-$specialPk = (count($primaryKeys) > 1 || $primaryKeys[0]['name'] !== 'id' || $primaryKeys[0]['info']['columnType'] !== 'integer') && $autoId;
-%>
-<% if ($specialPk): %>
-
- $this->table('<%= $tableArgForArray %>', ['id' => false, 'primary_key' => ['<%= implode("', '", \Cake\Utility\Hash::extract($primaryKeys, '{n}.name')) %>']])
-<% else: %>
-
- $this->table('<%= $tableArgForArray %>')
-<% endif; %>
-<% if ($specialPk || !$autoId):
- foreach ($primaryKeys as $primaryKey) :
-%>
- ->addColumn('<%= $primaryKey['name'] %>', '<%= $primaryKey['info']['columnType'] %>', [<%
- $columnOptions = $this->Migration->getColumnOption($primaryKey['info']['options']);
- echo $this->Migration->stringifyList($columnOptions, ['indent' => 4]);
- %>])
-<% endforeach; %>
-<% if (!$autoId): %>
- ->addPrimaryKey(['<%= implode("', '", \Cake\Utility\Hash::extract($primaryKeys, '{n}.name')) %>'])
-<% endif; %>
-<% endif;
-foreach ($this->Migration->columns($tableArgForMethods) as $column => $config):
-%>
- ->addColumn('<%= $column %>', '<%= $config['columnType'] %>', [<%
- $columnOptions = $this->Migration->getColumnOption($config['options']);
- if ($config['columnType'] === 'boolean' && isset($columnOptions['default']) && $this->Migration->value($columnOptions['default']) !== 'null'):
- $columnOptions['default'] = (bool)$columnOptions['default'];
- endif;
- echo $this->Migration->stringifyList($columnOptions, ['indent' => 4]);
- %>])
-<% endforeach;
-$tableConstraints = $this->Migration->constraints($tableArgForMethods);
-if (!empty($tableConstraints)):
- sort($tableConstraints);
- $constraints[$tableArgForArray] = $tableConstraints;
-
- foreach ($constraints[$tableArgForArray] as $name => $constraint):
- if ($constraint['type'] === 'foreign'):
- $foreignKeys[] = $constraint['columns'];
- endif;
- if ($constraint['columns'] !== $primaryKeysColumns): %>
- ->addIndex(
- [<% echo $this->Migration->stringifyList($constraint['columns'], ['indent' => 5]); %>]<% echo ($constraint['type'] === 'unique') ? ',' : ''; %>
-
-<% if ($constraint['type'] === 'unique'): %>
- ['unique' => true]
-<% endif; %>
- )
-<% endif;
- endforeach;
-endif;
-foreach($this->Migration->indexes($tableArgForMethods) as $index):
- sort($foreignKeys);
- $indexColumns = $index['columns'];
- sort($indexColumns);
- if (!in_array($indexColumns, $foreignKeys)):
- %>
- ->addIndex(
- [<%
- echo $this->Migration->stringifyList($index['columns'], ['indent' => 5]);
- %>]<% echo ($index['type'] === 'fulltext') ? ',' : ''; %>
-
- <%- if ($index['type'] === 'fulltext'): %>
- ['type' => 'fulltext']
- <%- endif; %>
- )
-<% endif;
-endforeach; %>
- ->create();
-<% endforeach; %>
-<% if (!empty($constraints)): %>
-<% echo $this->element('Migrations.add-foreign-keys-from-create', ['constraints' => $constraints]); %>
-<% endif; %>
\ No newline at end of file
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/Seed/seed.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/Seed/seed.ctp
deleted file mode 100644
index 9cec327f9..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/Seed/seed.ctp
+++ /dev/null
@@ -1,45 +0,0 @@
-<%
-/**
- * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- * @link http://cakephp.org CakePHP(tm) Project
- * @since 0.1.0
- * @license http://www.opensource.org/licenses/mit-license.php MIT License
- */
-%>
- seed.
- */
-class <%= $name %>Seed extends AbstractSeed
-{
- /**
- * Run Method.
- *
- * Write your database seeder using this method.
- *
- * More information on writing seeds is available here:
- * http://docs.phinx.org/en/latest/seeding.html
- *
- * @return void
- */
- public function run()
- {
-<% if ($records): %>
- $data = <%= $records %>;
-<% else: %>
- $data = [];
-<% endif; %>
-
- $table = $this->table('<%= $table %>');
- $table->insert($data)->save();
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/config/diff.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/config/diff.ctp
deleted file mode 100644
index 507457806..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/config/diff.ctp
+++ /dev/null
@@ -1,205 +0,0 @@
-<%
-/**
-* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
-* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
-*
-* Licensed under The MIT License
-* For full copyright and license information, please see the LICENSE.txt
-* Redistributions of files must retain the above copyright notice.
-*
-* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
-* @link http://cakephp.org CakePHP(tm) Project
-* @since 3.0.0
-* @license http://www.opensource.org/licenses/mit-license.php MIT License
-*/
-
-$tables = $data['fullTables'];
-unset($data['fullTables']);
-$constraints = [];
-
-$hasUnsignedPk = $this->Migration->hasUnsignedPrimaryKey($tables['add']);
-
-$autoId = true;
-if ($hasUnsignedPk) {
- $autoId = false;
-}
-%>
- extends AbstractMigration
-{
- <%- if (!$autoId): %>
-
- public $autoId = false;
- <%- endif; %>
-
- public function up()
- {
- <%- foreach ($data as $tableName => $tableDiff):
- $hasRemoveFK = !empty($tableDiff['constraints']['remove']) || !empty($tableDiff['indexes']['remove']);
- %>
- <%- if ($hasRemoveFK): %>
- $this->table('<%= $tableName %>')
- <%- endif; %>
- <%- if (!empty($tableDiff['constraints']['remove'])): %>
- <%- foreach ($tableDiff['constraints']['remove'] as $constraintName => $constraintDefinition): %>
- ->dropForeignKey([], '<%= $constraintName %>')
- <%- endforeach; %>
- <%- endif; %>
- <%- if (!empty($tableDiff['indexes']['remove'])): %>
- <%- foreach ($tableDiff['indexes']['remove'] as $indexName => $indexDefinition): %>
- ->removeIndexByName('<%= $indexName %>')
- <%- endforeach; %>
- <%- endif; %>
- <%- if ($hasRemoveFK): %>
- ->update();
- <%- endif; %>
- <%- if (!empty($tableDiff['columns']['remove']) || !empty($tableDiff['columns']['changed'])): %>
-
- <%= $this->Migration->tableStatement($tableName, true) %>
- <%- if (!empty($tableDiff['columns']['remove'])): %>
- <%- foreach ($tableDiff['columns']['remove'] as $columnName => $columnDefinition): %>
- ->removeColumn('<%= $columnName %>')
- <%- endforeach; %>
- <%- endif; %>
- <%- if (!empty($tableDiff['columns']['changed'])): %>
- <%- foreach ($tableDiff['columns']['changed'] as $columnName => $columnAttributes):
- $type = $columnAttributes['type'];
- unset($columnAttributes['type']);
- $columnAttributes = $this->Migration->getColumnOption($columnAttributes);
- $columnAttributes = $this->Migration->stringifyList($columnAttributes, ['indent' => 4]);
- if (!empty($columnAttributes)): %>
- ->changeColumn('<%= $columnName %>', '<%= $type %>', [<%= $columnAttributes %>])
- <%- else: %>
- ->changeColumn('<%= $columnName %>', '<%= $type %>')
- <%- endif; %>
- <%- endforeach; %>
- <%- endif; %>
- <%- if (isset($this->Migration->tableStatements[$tableName])): %>
- ->update();
- <%- endif; %>
- <%- endif; %>
- <%- endforeach; %>
- <%- if (!empty($tables['add'])): %>
- <%- echo $this->element('Migrations.create-tables', ['tables' => $tables['add'], 'autoId' => $autoId, 'useSchema' => true]) %>
- <%- endif; %>
- <%- foreach ($data as $tableName => $tableDiff): %>
- <%- if (!empty($tableDiff['columns']['add']) || !empty($tableDiff['indexes']['add'])): %>
-
- <%= $this->Migration->tableStatement($tableName, true) %>
- <%- if (!empty($tableDiff['columns']['add'])): %>
- <%- echo $this->element('Migrations.add-columns', ['columns' => $tableDiff['columns']['add']]) %>
- <%- endif; %>
- <%- if (!empty($tableDiff['indexes']['add'])): %>
- <%- echo $this->element('Migrations.add-indexes', ['indexes' => $tableDiff['indexes']['add']]) %>
- <%- endif;
- if (isset($this->Migration->tableStatements[$tableName])): %>
- ->update();
- <%- endif; %>
- <%- endif; %>
- <%- endforeach; %>
- <%- foreach ($data as $tableName => $tableDiff): %>
- <%- if (!empty($tableDiff['constraints']['add'])): %>
- <%- echo $this->element(
- 'Migrations.add-foreign-keys',
- ['constraints' => $tableDiff['constraints']['add'], 'table' => $tableName]
- ); %>
- <%- endif; %>
- <%- endforeach; %>
- <%- if (!empty($tables['remove'])): %>
- <%- foreach ($tables['remove'] as $tableName => $table): %>
-
- $this->dropTable('<%= $tableName %>');
- <%- endforeach; %>
- <%- endif; %>
- }
-
- public function down()
- {
- <%- $constraints = [];
- $emptyLine = false;
- if (!empty($this->Migration->returnedData['dropForeignKeys'])):
- foreach ($this->Migration->returnedData['dropForeignKeys'] as $table => $columnsList):
- $maxKey = count($columnsList) - 1;
- if ($emptyLine === true): %>
-
- <%- else:
- $emptyLine = true;
- endif; %>
- $this->table('<%= $table %>')
- <%- foreach ($columnsList as $key => $columns): %>
- ->dropForeignKey(
- <%= $columns %>
- )<%= ($key === $maxKey) ? ';' : '' %>
- <%- endforeach; %>
- <%- endforeach; %>
- <%- endif; %>
- <%- if (!empty($tables['remove'])): %>
- <%- echo $this->element('Migrations.create-tables', ['tables' => $tables['remove'], 'autoId' => $autoId, 'useSchema' => true]) %>
- <%- endif; %>
- <%- foreach ($data as $tableName => $tableDiff):
- unset($this->Migration->tableStatements[$tableName]);
- if (!empty($tableDiff['indexes']['add'])): %>
-
- $this->table('<%= $tableName %>')
- <%- foreach ($tableDiff['indexes']['add'] as $indexName => $index): %>
- ->removeIndexByName('<%= $indexName %>')
- <%- endforeach %>
- ->update();
- <%- endif; %>
- <%- if (!empty($tableDiff['columns']['remove']) ||
- !empty($tableDiff['columns']['changed']) ||
- !empty($tableDiff['columns']['add']) ||
- !empty($tableDiff['indexes']['remove'])
- ): %>
-
- <%= $this->Migration->tableStatement($tableName, true) %>
- <%- endif; %>
- <%- if (!empty($tableDiff['columns']['remove'])): %>
- <%- echo $this->element('Migrations.add-columns', ['columns' => $tableDiff['columns']['remove']]) %>
- <%- endif; %>
- <%- if (!empty($tableDiff['columns']['changed'])):
- $oldTableDef = $dumpSchema[$tableName];
- foreach ($tableDiff['columns']['changed'] as $columnName => $columnAttributes):
- $columnAttributes = $oldTableDef->getColumn($columnName);
- $type = $columnAttributes['type'];
- unset($columnAttributes['type']);
- $columnAttributes = $this->Migration->getColumnOption($columnAttributes);
- $columnAttributes = $this->Migration->stringifyList($columnAttributes, ['indent' => 4]);
- if (!empty($columnAttributes)): %>
- ->changeColumn('<%= $columnName %>', '<%= $type %>', [<%= $columnAttributes %>])
- <%- else: %>
- ->changeColumn('<%= $columnName %>', '<%= $type %>')
- <%- endif; %>
- <%- endforeach; %>
- <%- endif; %>
- <%- if (!empty($tableDiff['columns']['add'])): %>
- <%- foreach ($tableDiff['columns']['add'] as $columnName => $columnAttributes): %>
- ->removeColumn('<%= $columnName %>')
- <%- endforeach; %>
- <%- endif; %>
- <%- if (!empty($tableDiff['indexes']['remove'])): %>
- <%- echo $this->element('Migrations.add-indexes', ['indexes' => $tableDiff['indexes']['remove']]) %>
- <%- endif;
- if (isset($this->Migration->tableStatements[$tableName])): %>
- ->update();
- <%- endif; %>
- <%- endforeach; %>
- <%- foreach ($data as $tableName => $tableDiff): %>
- <%- if (!empty($tableDiff['constraints']['remove'])): %>
- <%- echo $this->element(
- 'Migrations.add-foreign-keys',
- ['constraints' => $tableDiff['constraints']['remove'], 'table' => $tableName]
- ); %>
- <%- endif; %>
- <%- endforeach; %>
- <%- if (!empty($tables['add'])): %>
- <%- foreach ($tables['add'] as $tableName => $table): %>
-
- $this->dropTable('<%= $tableName %>');
- <%- endforeach; %>
- <%- endif; %>
- }
-}
-
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/config/skeleton.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/config/skeleton.ctp
deleted file mode 100644
index f00d047cc..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/config/skeleton.ctp
+++ /dev/null
@@ -1,79 +0,0 @@
-<%
-/**
- * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- * @link http://cakephp.org CakePHP(tm) Project
- * @since 3.0.0
- * @license http://www.opensource.org/licenses/mit-license.php MIT License
- */
-
-$wantedOptions = array_flip(['length', 'limit', 'default', 'unsigned', 'null', 'comment', 'autoIncrement']);
-$tableMethod = $this->Migration->tableMethod($action);
-$columnMethod = $this->Migration->columnMethod($action);
-$indexMethod = $this->Migration->indexMethod($action);
-%>
- extends AbstractMigration
-{
- <%- if ($tableMethod === 'create' && !empty($columns['primaryKey'])): %>
-
- public $autoId = false;
-
- <%- endif; %>
- /**
- * Change Method.
- *
- * More information on this method is available here:
- * http://docs.phinx.org/en/latest/migrations.html#the-change-method
- * @return void
- */
- public function change()
- {
-<% foreach ($tables as $table): %>
- $table = $this->table('<%= $table%>');
-<% if ($tableMethod !== 'drop') : %>
-<% if ($columnMethod === 'removeColumn'): %>
-<% foreach ($columns['fields'] as $column => $config): %>
- <%= "\$table->$columnMethod('" . $column . "');"; %>
-<% endforeach; %>
-<% foreach ($columns['indexes'] as $column => $config): %>
- <%= "\$table->$indexMethod([" . $this->Migration->stringifyList($config['columns']) . ");"; %>
-<% endforeach; %>
-<% else : %>
-<% foreach ($columns['fields'] as $column => $config): %>
- $table-><%= $columnMethod %>('<%= $column %>', '<%= $config['columnType'] %>', [<%
- $columnOptions = $config['options'];
- $columnOptions = array_intersect_key($columnOptions, $wantedOptions);
- if (empty($columnOptions['comment'])) {
- unset($columnOptions['comment']);
- }
- echo $this->Migration->stringifyList($columnOptions, ['indent' => 3]);
- %>]);
-<% endforeach; %>
-<% foreach ($columns['indexes'] as $column => $config): %>
- $table-><%= $indexMethod %>([<%=
- $this->Migration->stringifyList($config['columns'], ['indent' => 3])
- %>], [<%
- $options = [];
- echo $this->Migration->stringifyList($config['options'], ['indent' => 3]);
- %>]);
-<% endforeach; %>
-<% if ($tableMethod === 'create' && !empty($columns['primaryKey'])): %>
- $table->addPrimaryKey([<%=
- $this->Migration->stringifyList($columns['primaryKey'], ['indent' => 3])
- %>]);
-<% endif; %>
-<% endif; %>
-<% endif; %>
- $table-><%= $tableMethod %>();
-<% endforeach; %>
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Template/Bake/config/snapshot.ctp b/app/vendor/cakephp/migrations/src/Template/Bake/config/snapshot.ctp
deleted file mode 100644
index 71b5164c9..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Bake/config/snapshot.ctp
+++ /dev/null
@@ -1,60 +0,0 @@
-<%
-/**
- * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- * @link http://cakephp.org CakePHP(tm) Project
- * @since 3.0.0
- * @license http://www.opensource.org/licenses/mit-license.php MIT License
- */
-
-use Cake\Database\Schema\Table;
-
-$constraints = $foreignKeys = $dropForeignKeys = [];
-$hasUnsignedPk = $this->Migration->hasUnsignedPrimaryKey($tables);
-
-if ($autoId && $hasUnsignedPk) {
- $autoId = false;
-}
-%>
- extends AbstractMigration
-{
- <%- if (!$autoId): %>
-
- public $autoId = false;
-
- <%- endif; %>
- public function up()
- {
- <%- echo $this->element('Migrations.create-tables', ['tables' => $tables, 'autoId' => $autoId, 'useSchema' => false]) %>
- }
-
- public function down()
- {
- <%- if (!empty($this->Migration->returnedData['dropForeignKeys'])):
- foreach ($this->Migration->returnedData['dropForeignKeys'] as $table => $columnsList):
- $maxKey = count($columnsList) - 1;
- %>
- $this->table('<%= $table %>')
- <%- foreach ($columnsList as $key => $columns): %>
- ->dropForeignKey(
- <%= $columns %>
- )<%= ($key === $maxKey) ? ';' : '' %>
- <%- endforeach; %>
-
- <%- endforeach;
- endif;
- %>
- <%- foreach ($tables as $table): %>
- $this->dropTable('<%= $table%>');
- <%- endforeach; %>
- }
-}
diff --git a/app/vendor/cakephp/migrations/src/Template/Phinx/create.php.template b/app/vendor/cakephp/migrations/src/Template/Phinx/create.php.template
deleted file mode 100644
index 76cd4e059..000000000
--- a/app/vendor/cakephp/migrations/src/Template/Phinx/create.php.template
+++ /dev/null
@@ -1,16 +0,0 @@
-validArguments($arguments);
foreach ($arguments as $field) {
preg_match($this->regexpParseColumn, $field, $matches);
$field = $matches[1];
- $type = Hash::get($matches, 2);
+ $type = Hash::get($matches, 2, '');
$indexType = Hash::get($matches, 3);
- $typeIsPk = in_array($type, ['primary', 'primary_key']);
+ $typeIsPk = in_array($type, ['primary', 'primary_key'], true);
$isPrimaryKey = false;
- if ($typeIsPk || in_array($indexType, ['primary', 'primary_key'])) {
+ if ($typeIsPk || in_array($indexType, ['primary', 'primary_key'], true)) {
$isPrimaryKey = true;
if ($typeIsPk) {
$type = 'primary';
}
}
-
- $nullable = (bool)preg_match('/\w+\?(\[\d+\])?/', $type);
+ $nullable = (bool)strpos($type, '?');
$type = $nullable ? str_replace('?', '', $type) : $type;
- list($type, $length) = $this->getTypeAndLength($field, $type);
+ [$type, $length] = $this->getTypeAndLength($field, $type);
$fields[$field] = [
'columnType' => $type,
'options' => [
'null' => $nullable,
'default' => null,
- ]
+ ],
];
if ($length !== null) {
- $fields[$field]['options']['limit'] = $length;
+ if (is_array($length)) {
+ [$fields[$field]['options']['precision'], $fields[$field]['options']['scale']] = $length;
+ } else {
+ $fields[$field]['options']['limit'] = $length;
+ }
}
if ($isPrimaryKey === true && $type === 'integer') {
@@ -81,7 +98,7 @@ public function parseFields($arguments)
* @param array $arguments A list of arguments being parsed
* @return array
*/
- public function parseIndexes($arguments)
+ public function parseIndexes(array $arguments)
{
$indexes = [];
$arguments = $this->validArguments($arguments);
@@ -92,9 +109,11 @@ public function parseIndexes($arguments)
$indexType = Hash::get($matches, 3);
$indexName = Hash::get($matches, 4);
- if (in_array($type, ['primary', 'primary_key']) ||
- in_array($indexType, ['primary', 'primary_key']) ||
- $indexType === null) {
+ if (
+ in_array($type, ['primary', 'primary_key'], true) ||
+ in_array($indexType, ['primary', 'primary_key'], true) ||
+ $indexType === null
+ ) {
continue;
}
@@ -128,7 +147,7 @@ public function parseIndexes($arguments)
* @param array $arguments A list of arguments being parsed
* @return array
*/
- public function parsePrimaryKey($arguments)
+ public function parsePrimaryKey(array $arguments)
{
$primaryKey = [];
$arguments = $this->validArguments($arguments);
@@ -138,7 +157,10 @@ public function parsePrimaryKey($arguments)
$type = Hash::get($matches, 2);
$indexType = Hash::get($matches, 3);
- if (in_array($type, ['primary', 'primary_key']) || in_array($indexType, ['primary', 'primary_key'])) {
+ if (
+ in_array($type, ['primary', 'primary_key'], true)
+ || in_array($indexType, ['primary', 'primary_key'], true)
+ ) {
$primaryKey[] = $field;
}
}
@@ -152,12 +174,12 @@ public function parsePrimaryKey($arguments)
* @param array $arguments A list of arguments
* @return array
*/
- public function validArguments($arguments)
+ public function validArguments(array $arguments)
{
$collection = new Collection($arguments);
return $collection->filter(function ($value, $field) {
- return preg_match($this->regexpParseColumn, $field);
+ return preg_match($this->regexpParseColumn, (string)$field);
})->toArray();
}
@@ -165,13 +187,17 @@ public function validArguments($arguments)
* Get the type and length of a field based on the field and the type passed
*
* @param string $field Name of field
- * @param string $type User-specified type
+ * @param string|null $type User-specified type
* @return array First value is the field type, second value is the field length. If no length
* can be extracted, null is returned for the second value
*/
public function getTypeAndLength($field, $type)
{
- if (preg_match($this->regexpParseField, $type, $matches)) {
+ if ($type && preg_match($this->regexpParseField, $type, $matches)) {
+ if (strpos($matches[2], ',') !== false) {
+ $matches[2] = explode(',', $matches[2]);
+ }
+
return [$matches[1], $matches[2]];
}
@@ -185,26 +211,27 @@ public function getTypeAndLength($field, $type)
* Retrieves a type that should be used for a specific field
*
* @param string $field Name of field
- * @param string $type User-specified type
- * @return string
+ * @param string|null $type User-specified type
+ * @return string|null
*/
- public function getType($field, $type)
+ public function getType($field, $type): ?string
{
- $reflector = new ReflectionClass('Phinx\Db\Adapter\AdapterInterface');
+ $reflector = new ReflectionClass(AdapterInterface::class);
$collection = new Collection($reflector->getConstants());
$validTypes = $collection->filter(function ($value, $constant) {
return substr($constant, 0, strlen('PHINX_TYPE_')) === 'PHINX_TYPE_';
})->toArray();
-
$fieldType = $type;
- if ($type === null || !in_array($type, $validTypes)) {
+ if ($type === null || !in_array($type, $validTypes, true)) {
if ($type === 'primary') {
$fieldType = 'integer';
} elseif ($field === 'id') {
$fieldType = 'integer';
- } elseif (in_array($field, ['created', 'modified', 'updated']) || substr($field, -3) === '_at') {
+ } elseif (in_array($field, ['created', 'modified', 'updated'], true) || substr($field, -3) === '_at') {
$fieldType = 'datetime';
+ } elseif (in_array($field, ['latitude', 'longitude', 'lat', 'lng'], true)) {
+ $fieldType = 'decimal';
} else {
$fieldType = 'string';
}
@@ -217,19 +244,27 @@ public function getType($field, $type)
* Returns the default length to be used for a given fie
*
* @param string $type User-specified type
- * @return int
+ * @return int|int[]
+ * @psalm-suppress InvalidNullableReturnType
*/
public function getLength($type)
{
$length = null;
if ($type === 'string') {
$length = 255;
+ } elseif ($type === 'tinyinteger') {
+ $length = 4;
+ } elseif ($type === 'smallinteger') {
+ $length = 6;
} elseif ($type === 'integer') {
$length = 11;
} elseif ($type === 'biginteger') {
$length = 20;
+ } elseif ($type === 'decimal') {
+ $length = [10, 6];
}
+ /** @psalm-suppress NullableReturnStatement */
return $length;
}
@@ -237,8 +272,8 @@ public function getLength($type)
* Returns the default length to be used for a given fie
*
* @param string $field Name of field
- * @param string $indexType Type of index
- * @param string $indexName Name of index
+ * @param string|null $indexType Type of index
+ * @param string|null $indexName Name of index
* @param bool $indexUnique Whether this is a unique index or not
* @return string
*/
diff --git a/app/vendor/cakephp/migrations/src/Util/SchemaTrait.php b/app/vendor/cakephp/migrations/src/Util/SchemaTrait.php
index 01d01c3ec..9e799c634 100644
--- a/app/vendor/cakephp/migrations/src/Util/SchemaTrait.php
+++ b/app/vendor/cakephp/migrations/src/Util/SchemaTrait.php
@@ -1,4 +1,6 @@
getOption('connection');
+ /** @var \Cake\Database\Connection $connection */
$connection = ConnectionManager::get($connectionName);
if (!method_exists($connection, 'getSchemaCollection')) {
@@ -54,6 +58,9 @@ protected function _getSchema(InputInterface $input, OutputInterface $output)
$connection->cacheMetadata(true);
+ /**
+ * @var \Cake\Database\Schema\CachedCollection
+ */
return $connection->getSchemaCollection();
}
}
diff --git a/app/vendor/cakephp/migrations/src/Util/UtilTrait.php b/app/vendor/cakephp/migrations/src/Util/UtilTrait.php
index ac57c3455..019259d9c 100644
--- a/app/vendor/cakephp/migrations/src/Util/UtilTrait.php
+++ b/app/vendor/cakephp/migrations/src/Util/UtilTrait.php
@@ -1,4 +1,6 @@
getOption('plugin') ?: null;
return $plugin;
}
+
/**
* Get the phinx table name used to store migrations data
*
@@ -65,10 +67,15 @@ protected function getOperationsPath(InputInterface $input, $default = 'Migratio
$folder = $input->getOption('source') ?: $default;
$dir = ROOT . DS . 'config' . DS . $folder;
+
+ if (defined('CONFIG')) {
+ $dir = CONFIG . $folder;
+ }
+
$plugin = $this->getPlugin($input);
if ($plugin !== null) {
- $dir = Plugin::path($plugin) . 'config' . DS . $folder;
+ $dir = CorePlugin::path($plugin) . 'config' . DS . $folder;
}
return $dir;
diff --git a/app/vendor/cakephp/migrations/src/View/Helper/MigrationHelper.php b/app/vendor/cakephp/migrations/src/View/Helper/MigrationHelper.php
index 0769bef01..b15c67b60 100644
--- a/app/vendor/cakephp/migrations/src/View/Helper/MigrationHelper.php
+++ b/app/vendor/cakephp/migrations/src/View/Helper/MigrationHelper.php
@@ -1,4 +1,6 @@
returnedData['dropForeignKeys'][$table][] = $columnsList;
+ }
+
+ /**
+ * Get all stored data.
+ *
+ * @return array An array of stored data.
+ */
+ public function getReturnedData(): array
+ {
+ return $this->returnedData;
+ }
+
/**
* Constructor
*
@@ -103,14 +129,19 @@ public function columnMethod($action)
return 'removeColumn';
}
+ if ($action === 'alter_field') {
+ return 'changeColumn';
+ }
+
return 'addColumn';
}
/**
- * Returns the Cake\Database\Schema\Table for $table
+ * Returns the Cake\Database\Schema\TableSchema for $table
*
- * @param string $table Name of the table to get the Schema for
- * @return \Cake\Database\Schema\Table
+ * @param string|\Cake\Database\Schema\TableSchema $table Name of the table to retrieve constraints for
+ * or a table schema object.
+ * @return \Cake\Database\Schema\TableSchema
*/
protected function schema($table)
{
@@ -118,7 +149,7 @@ protected function schema($table)
return $this->schemas[$table];
}
- if ($table instanceof Table) {
+ if ($table instanceof TableSchema) {
return $this->schemas[$table->name()] = $table;
}
@@ -132,19 +163,20 @@ protected function schema($table)
/**
* Returns an array of column data for a given table
*
- * @param string $table Name of the table to retrieve columns for
+ * @param string|\Cake\Database\Schema\TableSchema $table Name of the table to retrieve constraints for
+ * or a table schema object.
* @return array
*/
public function columns($table)
{
$tableSchema = $table;
- if (!($table instanceof Table)) {
- $tableSchema = $this->schema($table);
+ if (!($tableSchema instanceof TableSchema)) {
+ $tableSchema = $this->schema($tableSchema);
}
$columns = [];
- $tablePrimaryKeys = $tableSchema->primaryKey();
+ $tablePrimaryKeys = $tableSchema->getPrimaryKey();
foreach ($tableSchema->columns() as $column) {
- if (in_array($column, $tablePrimaryKeys)) {
+ if (in_array($column, $tablePrimaryKeys, true)) {
continue;
}
$columns[$column] = $this->column($tableSchema, $column);
@@ -156,14 +188,15 @@ public function columns($table)
/**
* Returns an array of indexes for a given table
*
- * @param string $table Name of the table to retrieve indexes for
+ * @param string|\Cake\Database\Schema\TableSchema $table Name of the table to retrieve constraints for
+ * or a table schema object.
* @return array
*/
public function indexes($table)
{
$tableSchema = $table;
- if (!($table instanceof Table)) {
- $tableSchema = $this->schema($table);
+ if (!($tableSchema instanceof TableSchema)) {
+ $tableSchema = $this->schema($tableSchema);
}
$tableIndexes = $tableSchema->indexes();
@@ -180,14 +213,15 @@ public function indexes($table)
/**
* Returns an array of constraints for a given table
*
- * @param string $table Name of the table to retrieve constraints for
+ * @param string|\Cake\Database\Schema\TableSchema $table Name of the table to retrieve constraints for
+ * or a table schema object.
* @return array
*/
public function constraints($table)
{
$tableSchema = $table;
- if (!($table instanceof Table)) {
- $tableSchema = $this->schema($table);
+ if (!($tableSchema instanceof TableSchema)) {
+ $tableSchema = $this->schema($tableSchema);
}
$constraints = [];
@@ -202,8 +236,10 @@ public function constraints($table)
if (!empty($tableConstraints)) {
foreach ($tableConstraints as $name) {
$constraint = $tableSchema->getConstraint($name);
- if (isset($constraint['update'])) {
+ if ($constraint && isset($constraint['update'])) {
$constraint['update'] = $this->formatConstraintAction($constraint['update']);
+ }
+ if ($constraint && isset($constraint['delete'])) {
$constraint['delete'] = $this->formatConstraintAction($constraint['delete']);
}
$constraints[$name] = $constraint;
@@ -231,19 +267,19 @@ public function formatConstraintAction($constraint)
/**
* Returns the primary key data for a given table
*
- * @param string $table Name of the table ot retrieve primary key for
+ * @param string|\Cake\Database\Schema\TableSchema $table Name of the table ot retrieve primary key for
* @return array
*/
public function primaryKeys($table)
{
$tableSchema = $table;
- if (!($table instanceof Table)) {
- $tableSchema = $this->schema($table);
+ if (!($tableSchema instanceof TableSchema)) {
+ $tableSchema = $this->schema($tableSchema);
}
$primaryKeys = [];
- $tablePrimaryKeys = $tableSchema->primaryKey();
+ $tablePrimaryKeys = $tableSchema->getPrimaryKey();
foreach ($tableSchema->columns() as $column) {
- if (in_array($column, $tablePrimaryKeys)) {
+ if (in_array($column, $tablePrimaryKeys, true)) {
$primaryKeys[] = ['name' => $column, 'info' => $this->column($tableSchema, $column)];
}
}
@@ -258,14 +294,14 @@ public function primaryKeys($table)
* @param array $tables List of tables to check
* @return bool
*/
- public function hasUnsignedPrimaryKey($tables)
+ public function hasUnsignedPrimaryKey(array $tables)
{
foreach ($tables as $table) {
$tableSchema = $table;
- if (!($table instanceof Table)) {
+ if (!($table instanceof TableSchema)) {
$tableSchema = $this->schema($table);
}
- $tablePrimaryKeys = $tableSchema->primaryKey();
+ $tablePrimaryKeys = $tableSchema->getPrimaryKey();
foreach ($tablePrimaryKeys as $primaryKey) {
$column = $tableSchema->getColumn($primaryKey);
@@ -287,6 +323,7 @@ public function hasUnsignedPrimaryKey($tables)
public function primaryKeysColumnsList($table)
{
$primaryKeys = $this->primaryKeys($table);
+ /** @var array $primaryKeysColumns */
$primaryKeysColumns = Hash::extract($primaryKeys, '{n}.name');
sort($primaryKeysColumns);
@@ -296,7 +333,7 @@ public function primaryKeysColumnsList($table)
/**
* Returns an array of column data for a single column
*
- * @param \Cake\Database\Schema\Table $tableSchema Name of the table to retrieve columns for
+ * @param \Cake\Database\Schema\TableSchema $tableSchema Name of the table to retrieve columns for
* @param string $column A column to retrieve data for
* @return array
*/
@@ -316,7 +353,7 @@ public function column($tableSchema, $column)
* @param array $options Array of options to compute the final list from.
* @return array
*/
- public function getColumnOption($options)
+ public function getColumnOption(array $options)
{
$wantedOptions = array_flip([
'length',
@@ -327,7 +364,7 @@ public function getColumnOption($options)
'comment',
'autoIncrement',
'precision',
- 'after'
+ 'after',
]);
$columnOptions = array_intersect_key($options, $wantedOptions);
if (empty($columnOptions['comment'])) {
@@ -361,7 +398,7 @@ public function getColumnOption($options)
/**
* Returns a string-like representation of a value
*
- * @param string $value A value to represent as a string
+ * @param string|bool|null $value A value to represent as a string
* @param bool $numbersAsString Set tu true to return as string.
* @return mixed
*/
@@ -383,20 +420,20 @@ public function value($value, $numbersAsString = false)
return (float)$value;
}
- return sprintf("'%s'", addslashes($value));
+ return sprintf("'%s'", addslashes((string)$value));
}
/**
* Returns an array of attributes for a given table column
*
- * @param string $table Name of the table to retrieve columns for
+ * @param \Cake\Database\Schema\TableSchema|string $table Name of the table to retrieve columns for
* @param string $column A column to retrieve attributes for
* @return array
*/
public function attributes($table, $column)
{
$tableSchema = $table;
- if (!($table instanceof Table)) {
+ if (!($tableSchema instanceof TableSchema)) {
$tableSchema = $this->schema($table);
}
$validOptions = [
@@ -406,11 +443,15 @@ public function attributes($table, $column)
'after', 'update',
'comment', 'unsigned',
'signed', 'properties',
- 'autoIncrement'
+ 'autoIncrement', 'unique',
];
$attributes = [];
$options = $tableSchema->getColumn($column);
+ if ($options === null) {
+ return [];
+ }
+
foreach ($options as $_option => $value) {
$option = $_option;
switch ($_option) {
@@ -426,7 +467,7 @@ public function attributes($table, $column)
break;
}
- if (!in_array($option, $validOptions)) {
+ if (!in_array($option, $validOptions, true)) {
continue;
}
@@ -443,14 +484,29 @@ public function attributes($table, $column)
*
* @param array $list array of items to be stringified
* @param array $options options to use
+ * @param array $wantedOptions The options you want to include in the output. If undefined all keys are included.
* @return string
*/
- public function stringifyList(array $list, array $options = [])
+ public function stringifyList(array $list, array $options = [], array $wantedOptions = [])
{
+ if (!empty($wantedOptions)) {
+ $list = array_intersect_key($list, $wantedOptions);
+ if (empty($list['comment'])) {
+ unset($list['comment']);
+ }
+ }
+
$options += [
- 'indent' => 2
+ 'indent' => 2,
];
+ if (!empty($options['remove'])) {
+ foreach ($options['remove'] as $option) {
+ unset($list[$option]);
+ }
+ unset($options['remove']);
+ }
+
if (!$list) {
return '';
}
@@ -459,7 +515,7 @@ public function stringifyList(array $list, array $options = [])
foreach ($list as $k => &$v) {
if (is_array($v)) {
$v = $this->stringifyList($v, [
- 'indent' => $options['indent'] + 1
+ 'indent' => $options['indent'] + 1,
]);
$v = sprintf('[%s]', $v);
} else {
@@ -503,4 +559,112 @@ public function tableStatement($table, $reset = false)
return '';
}
+
+ /**
+ * Get the stored table statement.
+ *
+ * @param string $table The table name.
+ * @return bool|string|null
+ */
+ public function getTableStatement(string $table)
+ {
+ if (array_key_exists($table, $this->tableStatements)) {
+ return $this->tableStatements[$table];
+ }
+
+ return null;
+ }
+
+ /**
+ * Remove a stored table statement
+ *
+ * @param string $table The table to remove
+ * @return void
+ */
+ public function removeTableStatement(string $table): void
+ {
+ unset($this->tableStatements[$table]);
+ }
+
+ /**
+ * Render an element.
+ *
+ * @param string $name The name of the element to render.
+ * @param array $data Additional data for the element.
+ * @return ?string
+ */
+ public function element(string $name, array $data): ?string
+ {
+ return $this->getView()->element($name, $data);
+ }
+
+ /**
+ * Wrapper around Hash::extract()
+ *
+ * @param array|\ArrayAccess $list The data to extract from.
+ * @param string $path The path to extract.
+ * @return mixed
+ */
+ public function extract($list, string $path = '{n}.name')
+ {
+ return Hash::extract($list, $path);
+ }
+
+ /**
+ * Get data to use in create tables element
+ *
+ * @param string|\Cake\Database\Schema\TableSchema $table Name of the table to retrieve constraints for
+ * or a table schema object.
+ * @return array
+ */
+ public function getCreateTableData($table): array
+ {
+ $constraints = $this->constraints($table);
+ $indexes = $this->indexes($table);
+ $foreignKeys = [];
+ foreach ($constraints as $constraint) {
+ if ($constraint['type'] === 'foreign') {
+ $foreignKeys[] = $constraint['columns'];
+ }
+ }
+ $indexes = array_filter($indexes, function ($index) use ($foreignKeys) {
+ return !in_array($index['columns'], $foreignKeys, true);
+ });
+ $result = compact('constraints', 'constraints', 'indexes', 'foreignKeys');
+
+ return $result;
+ }
+
+ /**
+ * Get data to use inside the create-tables element
+ *
+ * @param array $tables The tables to create element data for.
+ * @return array
+ */
+ public function getCreateTablesElementData(array $tables)
+ {
+ $result = [
+ 'constraints' => [],
+ 'tables' => [],
+ ];
+ foreach ($tables as $table) {
+ $tableName = $table;
+ if ($table instanceof TableSchema) {
+ $tableName = $table->name();
+ }
+ $data = $this->getCreateTableData($table);
+ $tableConstraintsNoUnique = array_filter(
+ $data['constraints'],
+ function ($constraint) {
+ return $constraint['type'] !== 'unique';
+ }
+ );
+ if ($tableConstraintsNoUnique) {
+ $result['constraints'][$tableName] = $data['constraints'];
+ }
+ $result['tables'][$tableName] = $data;
+ }
+
+ return $result;
+ }
}
diff --git a/app/vendor/cakephp/migrations/templates/Phinx/create.php.template b/app/vendor/cakephp/migrations/templates/Phinx/create.php.template
new file mode 100644
index 000000000..ab4ce8a53
--- /dev/null
+++ b/app/vendor/cakephp/migrations/templates/Phinx/create.php.template
@@ -0,0 +1,18 @@
+table('{{ table }}');
+ $table->insert($data)->save();
+ }
+}
diff --git a/app/vendor/cakephp/migrations/templates/bake/config/diff.twig b/app/vendor/cakephp/migrations/templates/bake/config/diff.twig
new file mode 100644
index 000000000..8aca4ebff
--- /dev/null
+++ b/app/vendor/cakephp/migrations/templates/bake/config/diff.twig
@@ -0,0 +1,221 @@
+{#
+/**
+* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+*
+* Licensed under The MIT License
+* For full copyright and license information, please see the LICENSE.txt
+* Redistributions of files must retain the above copyright notice.
+*
+* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+* @link http://cakephp.org CakePHP(tm) Project
+* @since 3.0.0
+* @license http://www.opensource.org/licenses/mit-license.php MIT License
+*/
+#}
+{% set tables = data['fullTables'] %}
+{# unset($data['fullTables']) #}
+{% set constraints = [] %}
+{% set hasUnsignedPk = Migration.hasUnsignedPrimaryKey(tables['add']) %}
+{% set autoId = true %}
+{% if hasUnsignedPk %}
+{% set autoId = false %}
+{% endif %}
+table('{{ tableName }}')
+{% endif %}
+{% if tableDiff['constraints']['remove'] is not empty %}
+{% for constraintName, constraintDefinition in tableDiff['constraints']['remove'] %}
+ ->dropForeignKey([], '{{ constraintName }}')
+{% endfor %}
+{% endif %}
+{% if tableDiff['indexes']['remove'] is not empty %}
+{% for indexName, indexDefinition in tableDiff['indexes']['remove'] %}
+ ->removeIndexByName('{{ indexName }}')
+{% endfor %}
+{% endif %}
+{% if hasRemoveFK %}
+ ->update();
+{% endif %}
+{% if tableDiff['columns']['remove'] is not empty or tableDiff['columns']['changed'] is not empty %}
+
+ {{ Migration.tableStatement(tableName, true) | raw }}
+{% if tableDiff['columns']['remove'] is not empty %}
+{% for columnName, columnDefinition in tableDiff['columns']['remove'] %}
+ ->removeColumn('{{ columnName }}')
+{% endfor %}
+{% endif %}
+{% if tableDiff['columns']['changed'] is not empty %}
+{% for columnName, columnAttributes in tableDiff['columns']['changed'] %}
+{% set type = columnAttributes['type'] %}
+{% set columnAttributes = Migration.getColumnOption(columnAttributes) %}
+{% set columnAttributes = Migration.stringifyList(columnAttributes, {'indent': 4, 'remove':
+ ['type']}) %}
+{% if columnAttributes is not empty %}
+ ->changeColumn('{{ columnName }}', '{{ type }}', [{{ columnAttributes | raw }}])
+{% else %}
+ ->changeColumn('{{ columnName }}', '{{ type }}')
+{% endif %}
+{% endfor %}
+{% endif -%}
+{% if Migration.getTableStatement(tableName) != null %}
+ ->update();
+{% endif %}
+{% endif %}
+{% endfor %}
+{% if tables['add'] is not empty %}
+{{ Migration.element('Migrations.create-tables', {'tables': tables['add'], 'autoId': autoId, 'useSchema':
+ true}) | raw -}}
+{% endif %}
+{% for tableName, tableDiff in data %}
+{% if tableDiff['columns']['add'] is not empty or tableDiff['indexes']['add'] is not empty %}
+
+ {{ Migration.tableStatement(tableName, true) | raw }}
+{% if tableDiff['columns']['add'] is not empty %}
+{{ Migration.element('Migrations.add-columns', {'columns': tableDiff['columns']['add']}) | raw -}}
+{% endif -%}
+{% if tableDiff['indexes']['add'] is not empty %}
+{{ Migration.element('Migrations.add-indexes', {'indexes': tableDiff['indexes']['add']}) | raw -}}
+{% endif -%}
+{% if Migration.getTableStatement(tableName) != null %}
+ ->update();
+{% endif -%}
+{% endif -%}
+{% endfor -%}
+{% for tableName, tableDiff in data -%}
+{% if tableDiff['constraints']['add'] is not empty -%}
+
+{{ Migration.element(
+ 'Migrations.add-foreign-keys',
+ {'constraints': tableDiff['constraints']['add'], 'table': tableName}
+ ) | raw -}}
+{% endif -%}
+{% endfor -%}
+{% if tables['remove'] is not empty %}
+{% for tableName, table in tables['remove'] %}
+
+ $this->table('{{ tableName }}')->drop()->save();
+{% endfor %}
+{% endif %}
+ }
+
+ /**
+ * Down Method.
+ *
+ * More information on this method is available here:
+ * https://book.cakephp.org/phinx/0/en/migrations.html#the-down-method
+ * @return void
+ */
+ public function down()
+ {
+{% set returnedData = Migration.getReturnedData() %}
+{% set constraints = [] %}
+{% set emptyLine = false %}
+{% if returnedData['dropForeignKeys'] is not empty %}
+{% for table, columnsList in returnedData['dropForeignKeys'] %}
+{% set maxKey = columnsList | length - 1 %}
+{% if emptyLine %}
+
+{% else %}
+{% set emptyLine = true %}
+{% endif %}
+ $this->table('{{ table }}')
+{% for key, columns in columnsList %}
+ ->dropForeignKey(
+ {{ columns | raw }}
+ ){{ (key == maxKey) ? '->save();' : '' }}
+{% endfor -%}
+{% endfor -%}
+{% endif -%}
+{% if tables['remove'] is not empty -%}
+{{ Migration.element('Migrations.create-tables', {
+ 'tables': tables['remove'],
+ 'autoId': autoId,
+ 'useSchema': true
+ }) | raw -}}
+{% endif -%}
+{% for tableName, tableDiff in data -%}
+{% set _unused = Migration.removeTableStatement(tableName) %}
+{% if tableDiff['indexes']['add'] is not empty %}
+
+ $this->table('{{ tableName }}')
+{% for indexName, index in tableDiff['indexes']['add'] %}
+ ->removeIndexByName('{{ indexName }}')
+{% endfor %}
+ ->update();
+{% endif %}
+{% if (tableDiff['columns']['remove'] is not empty or
+ tableDiff['columns']['changed'] is not empty or
+ tableDiff['columns']['add'] is not empty or
+ tableDiff['indexes']['remove'] is not empty) %}
+
+ {{ Migration.tableStatement(tableName, true) | raw}}
+{% endif %}
+{% if tableDiff['columns']['remove'] is not empty -%}
+{{ Migration.element('Migrations.add-columns', {'columns': tableDiff['columns']['remove']}) | raw -}}
+{% endif -%}
+{% if tableDiff['columns']['changed'] is not empty -%}
+{% set oldTableDef = dumpSchema[tableName] -%}
+{% for columnName, columnAttributes in tableDiff['columns']['changed'] -%}
+{% set columnAttributes = oldTableDef.getColumn(columnName) -%}
+{% set type = columnAttributes['type'] -%}
+{% set columnAttributes = Migration.getColumnOption(columnAttributes) -%}
+{% set columnAttributes = Migration.stringifyList(columnAttributes, {'indent': 4, 'remove': ['type']}) -%}
+{% if columnAttributes is not empty %}
+ ->changeColumn('{{ columnName }}', '{{ type }}', [{{ columnAttributes | raw }}])
+{% else %}
+ ->changeColumn('{{ columnName }}', '{{ type }}'])
+{% endif -%}
+{% endfor -%}
+{% endif -%}
+{% if tableDiff['columns']['add'] is not empty %}
+{% for columnName, columnAttributes in tableDiff['columns']['add'] %}
+ ->removeColumn('{{ columnName }}')
+{% endfor -%}
+{% endif -%}
+{% if tableDiff['indexes']['remove'] is not empty -%}
+{{ Migration.element('Migrations.add-indexes', {'indexes': tableDiff['indexes']['remove']}) | raw -}}
+{% endif -%}
+{% if Migration.getTableStatement(tableName) != null %}
+ ->update();
+{% endif %}
+{% endfor %}
+{% for tableName, tableDiff in data %}
+{% if tableDiff['constraints']['remove'] is not empty %}
+{{ Migration.element(
+ 'Migrations.add-foreign-keys',
+ {'constraints': tableDiff['constraints']['remove'], 'table': tableName}
+ ) | raw -}}
+{% endif %}
+{% endfor %}
+{% if tables['add'] is not empty %}
+
+{% for tableName, table in tables['add'] %}
+ $this->table('{{ tableName }}')->drop()->save();
+{% endfor %}
+{% endif %}
+ }
+}
diff --git a/app/vendor/cakephp/migrations/templates/bake/config/skeleton.twig b/app/vendor/cakephp/migrations/templates/bake/config/skeleton.twig
new file mode 100644
index 000000000..63225cd09
--- /dev/null
+++ b/app/vendor/cakephp/migrations/templates/bake/config/skeleton.twig
@@ -0,0 +1,75 @@
+{#
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link http://cakephp.org CakePHP(tm) Project
+ * @since 3.0.0
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+#}
+{% set wantedOptions = {'length': '', 'limit': '', 'default': '', 'unsigned': '', 'null': '', 'comment': '', 'autoIncrement': '', 'precision': '', 'scale': ''} %}
+{% set tableMethod = Migration.tableMethod(action) %}
+{% set columnMethod = Migration.columnMethod(action) %}
+{% set indexMethod = Migration.indexMethod(action) %}
+table('{{ table }}');
+{% if tableMethod != 'drop' %}
+{% if columnMethod == 'removeColumn' %}
+{% for column, config in columns['fields'] %}
+ $table->{{ columnMethod }}('{{ column }}');
+{% endfor %}
+{% for column, config in columns['indexes'] %}
+ $table->{{ indexMethod }}([{{
+ Migration.stringifyList(config['columns']) | raw
+ }}]);
+{% endfor %}
+{% else %}
+{% for column, config in columns['fields'] %}
+ $table->{{ columnMethod }}('{{ column }}', '{{ config['columnType'] }}', [{{
+ Migration.stringifyList(config['options'], {'indent': 3}, wantedOptions) | raw
+ }}]);
+{% endfor %}
+{% for column, config in columns['indexes'] %}
+ $table->{{ indexMethod }}([{{
+ Migration.stringifyList(config['columns'], {'indent': 3}) | raw }}
+ ], [{{
+ Migration.stringifyList(config['options'], {'indent': 3}) | raw
+ }}]);
+{% endfor %}
+{% if tableMethod == 'create' and columns['primaryKey'] is not empty %}
+ $table->addPrimaryKey([{{
+ Migration.stringifyList(columns['primaryKey'], {'indent': 3}) | raw
+ }}]);
+{% endif %}
+{% endif %}
+{% endif %}
+ $table->{{ tableMethod }}();
+{% endfor %}
+ }
+}
diff --git a/app/vendor/cakephp/migrations/templates/bake/config/snapshot.twig b/app/vendor/cakephp/migrations/templates/bake/config/snapshot.twig
new file mode 100644
index 000000000..ad67fb47f
--- /dev/null
+++ b/app/vendor/cakephp/migrations/templates/bake/config/snapshot.twig
@@ -0,0 +1,76 @@
+{#
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link http://cakephp.org CakePHP(tm) Project
+ * @since 3.0.0
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+#}
+{% set constraints = [] %}
+{% set foreignKeys = [] %}
+{% set dropForeignKeys = [] %}
+{% set hasUnsignedPk = Migration.hasUnsignedPrimaryKey(tables) %}
+{% if autoId and hasUnsignedPk %}
+{% set autoId = false %}
+{% endif %}
+table('{{ table }}')
+{% for key, columns in columnsList %}
+ ->dropForeignKey(
+ {{ columns|raw }}
+ ){{ (key == maxKey) ? '->save();' : '' }}
+{% endfor %}
+
+{% endfor %}
+{% endif %}
+{% for table in tables %}
+ $this->table('{{ table }}')->drop()->save();
+{% endfor %}
+ }
+}
diff --git a/app/vendor/cakephp/migrations/templates/bake/element/add-columns.twig b/app/vendor/cakephp/migrations/templates/bake/element/add-columns.twig
new file mode 100644
index 000000000..7bfe7a994
--- /dev/null
+++ b/app/vendor/cakephp/migrations/templates/bake/element/add-columns.twig
@@ -0,0 +1,10 @@
+{% for columnName, columnAttributes in columns %}
+{% set type = columnAttributes['type'] %}
+{% set columnAttributes = Migration.getColumnOption(columnAttributes) %}
+{% set columnAttributes = Migration.stringifyList(columnAttributes, {'indent': 4, 'remove': ['type']}) %}
+{% if columnAttributes is not empty %}
+ ->addColumn('{{ columnName }}', '{{ type }}', [{{ columnAttributes | raw }}])
+{% else %}
+ ->addColumn('{{ columnName }}', '{{ type }}')
+{% endif -%}
+{% endfor -%}
diff --git a/app/vendor/cakephp/migrations/templates/bake/element/add-foreign-keys.twig b/app/vendor/cakephp/migrations/templates/bake/element/add-foreign-keys.twig
new file mode 100644
index 000000000..ef75c63aa
--- /dev/null
+++ b/app/vendor/cakephp/migrations/templates/bake/element/add-foreign-keys.twig
@@ -0,0 +1,38 @@
+{% set statement = Migration.tableStatement(table, true) %}
+{% set hasProcessedConstraint = false %}
+{% for constraint in constraints %}
+{% set constraintColumns = constraint['columns']|sort %}
+{% if constraint['type'] != 'unique' %}
+{% set hasProcessedConstraint = true %}
+{% set columnsList = '\'' ~ constraint['columns'][0] ~ '\'' %}
+{% if constraint['columns']|length > 1 %}
+{% set columnsList = '[' ~ Migration.stringifyList(constraint['columns'], {'indent': 5}) ~ ']' %}
+{% endif %}
+{% set record = Migration.storeReturnedData(table, columnsList) %}
+{% if constraint['references'][1] is iterable %}
+{% set columnsReference = '[' ~ Migration.stringifyList(constraint['references'][1], {'indent': 5}) ~ ']' %}
+{% else %}
+{% set columnsReference = '\'' ~ constraint['references'][1] ~ '\'' %}
+{% endif %}
+{% if statement is not defined %}
+{% set statement = Migration.tableStatement(table) %}
+{% endif %}
+{% if statement is not empty %}
+
+ {{ statement | raw }}
+{% set statement = null %}
+{% endif %}
+ ->addForeignKey(
+ {{ columnsList | raw }},
+ '{{ constraint['references'][0] }}',
+ {{ columnsReference | raw }},
+ [
+ 'update' => '{{ Migration.formatConstraintAction(constraint['update']) | raw }}',
+ 'delete' => '{{ Migration.formatConstraintAction(constraint['delete']) | raw }}',
+ ]
+ )
+{% endif %}
+{% endfor %}
+{% if Migration.getTableStatement(table) != null and hasProcessedConstraint %}
+ ->update();
+{% endif -%}
diff --git a/app/vendor/cakephp/migrations/templates/bake/element/add-indexes.twig b/app/vendor/cakephp/migrations/templates/bake/element/add-indexes.twig
new file mode 100644
index 000000000..18d7c3a93
--- /dev/null
+++ b/app/vendor/cakephp/migrations/templates/bake/element/add-indexes.twig
@@ -0,0 +1,10 @@
+{% for indexName, index in indexes %}
+ ->addIndex(
+ [{{ Migration.stringifyList(index['columns'], {'indent': 5}) | raw }}],
+{% set params = {'name': indexName} %}
+{% if index['type'] == 'unique' %}
+{% set params = params|merge({'unique': true}) %}
+{% endif %}
+ [{{ Migration.stringifyList(params, {'indent': 5}) | raw }}]
+ )
+{% endfor %}
diff --git a/app/vendor/cakephp/migrations/templates/bake/element/create-tables.twig b/app/vendor/cakephp/migrations/templates/bake/element/create-tables.twig
new file mode 100644
index 000000000..8f4a2e330
--- /dev/null
+++ b/app/vendor/cakephp/migrations/templates/bake/element/create-tables.twig
@@ -0,0 +1,70 @@
+{% set createData = Migration.getCreateTablesElementData(tables) %}
+{% for table, schema in tables %}
+{% set tableArgForMethods = useSchema ? schema : table %}
+{% set tableArgForArray = useSchema ? table : schema %}
+{% set foreignKeys = [] %}
+{% set primaryKeysColumns = Migration.primaryKeysColumnsList(tableArgForMethods) %}
+{% set primaryKeys = Migration.primaryKeys(tableArgForMethods) %}
+{% set specialPk = primaryKeys and (primaryKeys|length > 1 or primaryKeys[0]['name'] != 'id' or primaryKeys[0]['info']['columnType'] != 'integer') and autoId %}
+{% if loop.index > 1 %}
+
+{% endif -%}
+{% if specialPk %}
+ $this->table('{{ tableArgForArray }}', ['id' => false, 'primary_key' => ['{{ Migration.extract(primaryKeys)|join("', '")|raw }}']])
+{% elseif not primaryKeys and autoId %}
+ $this->table('{{ tableArgForArray }}', ['id' => false])
+{% else %}
+ $this->table('{{ tableArgForArray }}')
+{% endif %}
+{% if specialPk or not autoId %}
+{% for primaryKey in primaryKeys %}
+{% set columnOptions = Migration.getColumnOption(primaryKey['info']['options']) %}
+ ->addColumn('{{ primaryKey['name'] }}', '{{ primaryKey['info']['columnType'] }}', [{{ Migration.stringifyList(columnOptions, {'indent': 4}) | raw }}])
+{% endfor %}
+{% if not autoId and primaryKeys %}
+ ->addPrimaryKey(['{{ Migration.extract(primaryKeys)
+ | join("', '") | raw }}'])
+{% endif %}
+{% endif %}
+{% for column, config in Migration.columns(tableArgForMethods) %}
+{% set columnOptions = Migration.getColumnOption(config['options']) %}
+{% if config['columnType'] == 'boolean' and columnOptions['default'] is defined and (Migration.value(columnOptions['default'])) is not same as('null') %}
+{% set default = columnOptions['default'] ? true : false %}
+{% set columnOptions = columnOptions|merge({'default': default}) %}
+{% endif %}
+ ->addColumn('{{ column }}', '{{ config['columnType'] }}', [{{
+ Migration.stringifyList(columnOptions, {'indent': 4}) | raw
+ }}])
+{% endfor %}
+{% if createData.tables[table].constraints is not empty %}
+{% for name, constraint in createData.tables[table].constraints %}
+{% if constraint['columns'] != primaryKeysColumns %}
+ ->addIndex(
+ [{{ Migration.stringifyList(constraint['columns'], {'indent': 5}) | raw }}]{{ (constraint['type'] == 'unique') ? ',' : '' }}
+{% if constraint['type'] == 'unique' %}
+ ['unique' => true]
+{% endif %}
+ )
+{% endif %}
+{% endfor %}
+{% endif %}
+{% for index in createData.tables[table].indexes %}
+{% set indexColumns = index['columns'] | sort %}
+ ->addIndex(
+ [{{ Migration.stringifyList(index['columns'], {'indent': 5}) | raw }}]{{ (index['type'] == 'fulltext') ? ',' : '' }}
+{% if index['type'] == 'fulltext' %}
+ ['type' => 'fulltext']
+{% endif %}
+ )
+{% endfor %}
+ ->create();
+{% endfor -%}
+{% if createData.constraints %}
+{% for table, tableConstraints in createData.constraints %}
+{{- element('Migrations.add-foreign-keys', {
+ constraints: tableConstraints,
+ table: table
+ })
+-}}
+{% endfor -%}
+{% endif -%}
diff --git a/app/vendor/cakephp/twig-view/LICENSE b/app/vendor/cakephp/twig-view/LICENSE
new file mode 100644
index 000000000..2b79cc319
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+Copyright (c) 2014 Cees-Jan Kiewiet
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/app/vendor/cakephp/twig-view/README.md b/app/vendor/cakephp/twig-view/README.md
new file mode 100644
index 000000000..74ce3c511
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/README.md
@@ -0,0 +1,264 @@
+# TwigView plugin for CakePHP
+
+[](https://travis-ci.com/cakephp/twig-view)
+[](https://packagist.org/packages/cakephp/twig-view)
+[](https://packagist.org/packages/cakephp/twig-view/stats)
+[](https://coveralls.io/r/cakephp/twig-view?branch=master)
+[](LICENSE)
+
+
+This plugin allows you to use the [Twig Templating Language](http://twig.sensiolabs.org/documentation) for your views.
+
+It provides wrappers for common View opertions and many helpful extensions that expose CakePHP functions and `jasny/twig-extensions` helpers.
+
+## Installation
+
+To install with [Composer](http://getcomposer.org/), use the command below.
+
+```bash
+composer require cakephp/twig-view
+```
+
+Then, [load the `Cake/TwigView` plugin](https://book.cakephp.org/4/en/plugins.html#loading-a-plugin)
+in your `Application` bootstrap just like other Cake plugins.
+
+## Configuration
+
+`TwigView` allows you to configure the Twig Environment through `View` options. You can set these through `ViewBuilder`
+in the `Controller` or set them directly in `TwigView`.
+
+```php
+// In controller
+public function initialize(): void
+{
+ $this->viewBuilder()->setOption('environment', ['cache' => false]);
+}
+
+// In your AppView
+public function initialize(): void
+{
+ $this->setConfig('environment', ['cache' => false]);
+
+ // Call parent TwigView initialize
+ parent::initialize();
+}
+```
+
+### Available Options
+
+- `environment`
+
+ [Twig Environment options](https://twig.symfony.com/doc/3.x/api.html#environment-options).
+
+ Defaults to empty.
+
+- `markdown`
+
+ Which markdown engine is used for `markdown_to_html` filter. Set to `default` to use `DefaultMarkdown` or set
+ custom [Twig Markdown extension](https://packagist.org/packages/twig/markdown-extra) `MarkdownInterface` instance.
+
+ If using `default`, require one of:
+ - `erusev/parsedown`
+ - `league/commonmark`
+ - `michelf/php-markdown`
+
+ Defaults to disabled.
+
+## AppView Setup
+
+To start using Twig templates in your application, simply extend `TwigView` in your `AppView`.
+In general, it is safe to add your application's setup in `AppView::initialize()`.
+
+```php
+namespace App\View;
+
+use Cake\TwigView\View\TwigView;
+
+class AppView extends TwigView
+{
+ public function initialize(): void
+ {
+ parent::initialize();
+
+ // Add application-specific extensions
+ }
+}
+```
+
+### Customization
+
+You can override several parts of `TwigView` initialization to create a custom Twig setup.
+
+- File Extensions
+
+ You can specify the file extensions used to search for templates by overriding the
+ `$extensions` property.
+
+ ```php
+ class AppView extends TwigView
+ {
+ protected $extensions = [
+ '.custom',
+ ];
+ }
+ ```
+
+- Twig Loader
+
+ You can override the template loader used by Twig.
+
+ ```php
+ protected function createLoader(): \Twig\Loader\LoaderInterface
+ {
+ // Return a custom Twig template loader
+ }
+ ```
+
+- Twig Extensions
+
+ You can override the Twig Extensions loading. If you want to use the built-in
+ `View` wrappers, make sure you load `Cake\TwigView\Twig\Extensions\ViewExtension`.
+
+ ```php
+ protected function initializeExtensions(): void
+ {
+ // Load only specific extensions
+ }
+
+- Twig Profiler
+
+ You can override the Twig profiler used when `DebugKit` is loaded.
+
+ ```php
+ protected function initializeProfiler(): void
+ {
+ parent::initializeProfiler();
+ // Add custom profiler logging using $this->getProfile()
+ }
+ ```
+
+## Templates
+
+You can create views using Twig templates much like you can with standard CakePHP templates.
+
+Templates are loaded the same way wherever they are used and follow the `View` path conventions.
+
+```twig
+{% extends 'Common/base' %}
+{{ include('Common/helper') }}
+```
+
+- Template names are always relative to `App.path.templates` not the current file.
+- File extensions are automatically generated. Defaults to '.twig'.
+- Templates can be loaded from plugins the same as `View` templates.
+
+Layout templates are supported and loaded the same way as `View` layouts.
+
+`templates/layout/default.twig`:
+
+```twig
+
+
+
+
+ {{ fetch('title') }}
+
+
+ {{ fetch('meta') }}
+ {{ fetch('css') }}
+ {{ fetch('script') }}
+
+
+ {{ fetch('content') }}
+
+
+```
+
+### Accessing View
+
+You can access the `View` instance using the `_view` global.
+
+`TwigView` provides wrappers for `fetch()`, `cell()` and `element()` rendering.
+Cell and element templates are always loaded from **cell/** and **element/** sub-directories
+the same as `View` templates.
+
+```twig
+{{ fetch('content')}}
+
+{{ cell('myCell')}}
+{{ element('myElement') }}
+```
+
+`TwigView` also provides wrappers for any loaded helper using a special naming convention - `helper_Name_function()`.
+
+```twig
+{{ helper_Text_autoParagraph('some text for a paragarph') }}
+```
+
+All wrapper functions are pre-escaped and do not require using `|raw` filter. However, keep in mind that Twig keeps the whitespace when using `{{ }}` to print. Please read the [Twig documentation]((https://twig.symfony.com/doc/3.x/templates.html#whitespace-control)) on how to remove the extra white space when needed.
+
+### Extension Filters
+
+* `low` maps to [`strtolower`](http://php.net/strtolower)
+* `up` maps to [`strtoupper`](http://php.net/strtoupper)
+* `env` maps to [`env`](https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#global-functions)
+* `pluralize` maps to [`Cake\Utility\Inflector::pluralize`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::pluralize)
+* `singularize` maps to [`Cake\Utility\Inflector::singularize`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::singularize)
+* `camelize` maps to [`Cake\Utility\Inflector::camelize`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::camelize)
+* `underscore` maps to [`Cake\Utility\Inflector::underscore`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::underscore)
+* `humanize` maps to [`Cake\Utility\Inflector::humanize`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::humanize)
+* `tableize` maps to [`Cake\Utility\Inflector::tableize`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::tableize)
+* `classify` maps to [`Cake\Utility\Inflector::classify`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::classify)
+* `variable` maps to [`Cake\Utility\Inflector::variable`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::variable)
+* `slug` maps to [`Cake\Utility\Inflector::slug`](https://book.cakephp.org/4/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::slug)
+* `toReadableSize` maps to [`Cake\I18n\Number::toReadableSize`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::toReadableSize)
+* `toPercentage` maps to [`Cake\I18n\Number::toPercentage`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::toPercentage)
+* `cake_number_format` maps to [`Cake\I18n\Number::format`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::format)
+* `formatDelta` maps to [`Cake\I18n\Number::formatDelta`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::formatDelta)
+* `currency` maps to [`Cake\I18n\Number::currency`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::currency)
+* `substr` maps to [`substr`](http://php.net/substr)
+* `tokenize` maps to [`Cake\Utility\Text::tokenize`](https://book.cakephp.org/4/en/core-libraries/text.html#simple-string-parsing)
+* `insert` maps to [`Cake\Utility\Text::insert`](https://book.cakephp.org/4/en/core-libraries/text.html#formatting-strings)
+* `cleanInsert` maps to [`Cake\Utility\Text::cleanInsert`](https://book.cakephp.org/4/en/core-libraries/text.html#formatting-strings)
+* `wrap` maps to [`Cake\Utility\Text::wrap`](https://book.cakephp.org/4/en/core-libraries/text.html#wrapping-text)
+* `wrapBlock` maps to [`Cake\Utility\Text::wrapBlock`](https://book.cakephp.org/4/en/core-libraries/text.html#wrapping-text)
+* `wordWrap` maps to [`Cake\Utility\Text::wordWrap`](https://book.cakephp.org/4/en/core-libraries/text.html#wrapping-text)
+* `highlight` maps to [`Cake\Utility\Text::highlight`](https://book.cakephp.org/4/en/core-libraries/text.html#highlighting-substrings)
+* `tail` maps to [`Cake\Utility\Text::tail`](https://book.cakephp.org/4/en/core-libraries/text.html#truncating-the-tail-of-a-string)
+* `truncate` maps to [`Cake\Utility\Text::truncate`](https://book.cakephp.org/4/en/core-libraries/text.html#truncating-text)
+* `excerpt` maps to [`Cake\Utility\Text::excerpt`](https://book.cakephp.org/4/en/core-libraries/text.html#extracting-an-excerpt)
+* `toList` maps to [`Cake\Utility\Text::toList`](https://book.cakephp.org/4/en/core-libraries/text.html#converting-an-array-to-sentence-)
+* `stripLinks` maps to [`Cake\Utility\Text::stripLinks`](https://book.cakephp.org/4/en/core-libraries/text.html#removing-links)
+* `isMultibyte` maps to `Cake\Utility\Text::isMultibyte`
+* `utf8` maps to `Cake\Utility\Text::utf8`
+* `ascii` maps to `Cake\Utility\Text::ascii`
+* `parseFileSize` maps to [`Cake\Utility\Text::parseFileSize`](https://book.cakephp.org/4/en/core-libraries/text.html#simple-string-parsing)
+* `serialize` maps to [`serialize`](http://php.net/serialize)
+* `unserialize` maps to [`unserialize`](http://php.net/unserialize)
+* `md5` maps to [`md5`](http://php.net/md5)
+* `base64_encode` maps to [`base64_encode`](http://php.net/base64_encode)
+* `base64_decode` maps to [`base64_decode`](http://php.net/base64_decode)
+* `string` cast to [`string`](http://php.net/manual/en/language.types.type-juggling.php)
+
+See `jasny/twig-extensions` for the filters they provide.
+
+### Extension Functions
+
+* `in_array` maps to [`in_array`](http://php.net/in_array)
+* `explode` maps to [`explode`](http://php.net/explode)
+* `array` cast to [`array`](http://php.net/manual/en/language.types.type-juggling.php)
+* `array_push` maps to [`push`](http://php.net/array_push)
+* `array_prev` maps to [`prev`](http://php.net/prev)
+* `array_next` maps to [`next`](http://php.net/next)
+* `array_current` maps to [`current`](http://php.net/current)
+* `__` maps to [`__`](https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html)
+* `__d` maps to [`__d`](https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html)
+* `__n` maps to [`__n`](https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html)
+* `__x` maps to [`__x`](https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html)
+* `__dn` maps to [`__dn`](https://book.cakephp.org/4/en/core-libraries/internationalization-and-localization.html)
+* `defaultCurrency` maps to [`Cake\I18n\Number::getDefaultCurrency`](https://book.cakephp.org/4/en/core-libraries/number.html#Cake\\I18n\\Number::getDefaultCurrency)
+* `uuid` maps to [`Cake\Utility\Text::uuid`](https://book.cakephp.org/4/en/core-libraries/text.html#generating-uuids)
+* `time` passed the first and optional second argument into [`new \Cake\I18n\Time()`](https://book.cakephp.org/4/en/core-libraries/time.html#creating-time-instances)
+* `timezones` maps to `Cake\I18n\Time::listTimezones`
+
+See `jasny/twig-extensions` for the functions they provide.
diff --git a/app/vendor/cakephp/twig-view/composer.json b/app/vendor/cakephp/twig-view/composer.json
new file mode 100644
index 000000000..fff940a58
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/composer.json
@@ -0,0 +1,75 @@
+{
+ "name": "cakephp/twig-view",
+ "description": "Twig powered View for CakePHP",
+ "type":"cakephp-plugin",
+ "license": "MIT",
+ "keywords": [
+ "twig",
+ "view",
+ "template",
+ "cakephp"
+ ],
+ "authors": [
+ {
+ "name": "CakePHP Community",
+ "homepage": "https://github.com/cakephp/cakephp/graphs/contributors"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/cakephp/twig-view/issues",
+ "forum": "https://stackoverflow.com/tags/cakephp",
+ "irc": "irc://irc.freenode.org/cakephp",
+ "source": "https://github.com/cakephp/twig-view"
+ },
+ "require": {
+ "php": ">=7.2",
+ "cakephp/cakephp": "^4.0",
+ "jasny/twig-extensions": "^1.3",
+ "twig/markdown-extra": "^3.0",
+ "twig/twig": "^3.0"
+ },
+ "require-dev": {
+ "cakephp/cakephp-codesniffer": "^4.0",
+ "cakephp/debug_kit": "^4.0",
+ "cakephp/plugin-installer": "^1.3",
+ "michelf/php-markdown": "^1.9",
+ "mikey179/vfsstream": "^1.6",
+ "phpunit/phpunit": "^8.5 || ^9.3"
+ },
+ "conflict": {
+ "wyrihaximus/twig-view": "*"
+ },
+ "autoload": {
+ "psr-4": {
+ "Cake\\TwigView\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Cake\\TwigView\\Test\\": "tests/",
+ "TestApp\\": "tests/test_app/src/",
+ "TestTwigView\\": "tests/test_app/plugins/TestTwigView/src/"
+ }
+ },
+ "scripts": {
+ "cs-check": [
+ "phpcs --colors --parallel=16 -p src/ tests/"
+ ],
+ "cs-fix": [
+ "phpcbf --colors --parallel=16 -p src/ tests/"
+ ],
+ "phpstan": "phpstan.phar analyse",
+ "psalm": "psalm.phar --show-info=false",
+ "stan": [
+ "@phpstan",
+ "@psalm"
+ ],
+ "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12.54 psalm/phar:~4.3.0 && mv composer.backup composer.json",
+ "test": [
+ "phpunit"
+ ]
+ },
+ "config": {
+ "sort-packages": true
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Command/CompileCommand.php b/app/vendor/cakephp/twig-view/src/Command/CompileCommand.php
new file mode 100644
index 000000000..0c8bba8b5
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Command/CompileCommand.php
@@ -0,0 +1,151 @@
+addArgument('type', [
+ 'required' => true,
+ 'choices' => ['all', 'file', 'plugin'],
+ 'help' => 'The type you want to compile.',
+ ]);
+
+ $parser->addArgument('target', [
+ 'required' => false,
+ 'help' => 'The file or plugin you want to compile.',
+ ]);
+
+ $parser->addOption('view-class', [
+ 'help' => 'The class name of the View used to load and compile.',
+ 'default' => TwigView::class,
+ ]);
+
+ return $parser;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function execute(Arguments $args, ConsoleIo $io)
+ {
+ $type = $args->getArgumentAt(0);
+
+ /** @psalm-var class-string<\Cake\TwigView\View\TwigView> $viewClass */
+ $viewClass = $args->getOption('view-class');
+
+ // Setup cached TwigView to avoid creating for every file
+ $this->twigView = new $viewClass();
+
+ // $type is validated by the 'choices' option in buildOptionsParser
+ return $this->{"execute{$type}"}($args, $io);
+ }
+
+ /**
+ * Compile all templates.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments
+ * @param \Cake\Console\ConsoleIo $io The console logger
+ * @return int
+ */
+ protected function executeAll(Arguments $args, ConsoleIo $io): int
+ {
+ $io->info('Compiling all templates');
+
+ foreach (Scanner::all($this->twigView->getExtensions()) as $section => $templates) {
+ $io->info("Compiling section {$section}");
+ foreach ($templates as $template) {
+ if ($this->compileFile($io, $template) === static::CODE_ERROR) {
+ return static::CODE_ERROR;
+ }
+ }
+ }
+
+ return static::CODE_SUCCESS;
+ }
+
+ /**
+ * Compile all templates for a plugin.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments
+ * @param \Cake\Console\ConsoleIo $io The console logger
+ * @return int
+ */
+ protected function executePlugin(Arguments $args, ConsoleIo $io): int
+ {
+ $plugin = $args->getArgumentAt(1);
+ if ($plugin === null) {
+ $io->error('Plugin name not specified.');
+
+ return static::CODE_ERROR;
+ }
+
+ $io->info("Compiling plugin {$plugin}");
+ foreach (Scanner::plugin($plugin, $this->twigView->getExtensions()) as $template) {
+ if ($this->compileFile($io, $template) === static::CODE_ERROR) {
+ return static::CODE_ERROR;
+ }
+ }
+
+ return static::CODE_SUCCESS;
+ }
+
+ /**
+ * Compile a single template file.
+ *
+ * @param \Cake\Console\Arguments $args The command arguments
+ * @param \Cake\Console\ConsoleIo $io The console logger
+ * @return int
+ */
+ protected function executeFile(Arguments $args, ConsoleIo $io): int
+ {
+ $filename = $args->getArgumentAt(1);
+ if ($filename === null) {
+ $io->error('File name not specified.');
+
+ return static::CODE_ERROR;
+ }
+
+ return $this->compileFile($io, $filename);
+ }
+
+ /**
+ * Compile a single template file.
+ *
+ * @param \Cake\Console\ConsoleIo $io The console logger
+ * @param string $filename The template filename
+ * @return int
+ */
+ protected function compileFile(ConsoleIo $io, string $filename): int
+ {
+ try {
+ $this->twigView->getTwig()->load($filename);
+ $io->success("Compiled {$filename}.");
+ } catch (Exception $exception) {
+ $io->error("Unable to compile {$filename}.");
+ $io->error($exception->getMessage());
+
+ return static::CODE_ERROR;
+ }
+
+ return static::CODE_SUCCESS;
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Filesystem/RelativeScanner.php b/app/vendor/cakephp/twig-view/src/Filesystem/RelativeScanner.php
new file mode 100644
index 000000000..d91db800c
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Filesystem/RelativeScanner.php
@@ -0,0 +1,96 @@
+ Scanner::plugin($plugin, $extensions),
+ ])[$plugin];
+ }
+
+ /**
+ * Strip the absolute path of template's paths for all given sections.
+ *
+ * @param array $sections Sections to iterate over.
+ * @return array
+ */
+ protected static function strip(array $sections): array
+ {
+ foreach ($sections as $section => $paths) {
+ $sections[$section] = static::stripAbsolutePath($paths, $section === 'APP' ? null : $section);
+ }
+
+ return $sections;
+ }
+
+ /**
+ * Strip the absolute path of template's paths.
+ *
+ * @param array $paths Paths to strip.
+ * @param string|null $plugin Hold plugin name or null for App.
+ * @return array
+ */
+ protected static function stripAbsolutePath(array $paths, ?string $plugin = null): array
+ {
+ if ($plugin === null) {
+ $allPaths = App::path('templates');
+ } else {
+ $allPaths = [Plugin::templatePath($plugin)];
+ }
+
+ foreach ($allPaths as $templatesPath) {
+ array_walk($paths, function (&$path) use ($templatesPath) {
+ if (substr($path, 0, strlen($templatesPath)) === $templatesPath) {
+ $path = substr($path, strlen($templatesPath));
+ }
+ });
+ }
+
+ return $paths;
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Filesystem/Scanner.php b/app/vendor/cakephp/twig-view/src/Filesystem/Scanner.php
new file mode 100644
index 000000000..ef87e0974
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Filesystem/Scanner.php
@@ -0,0 +1,178 @@
+ RelativeScanner::plugin($plugin, $extensions),
+ ])[$plugin];
+ }
+
+ /**
+ * Strip the absolute path of template's paths for all given sections.
+ *
+ * @param array $sections Sections to iterate over.
+ * @return array
+ */
+ protected static function deepen(array $sections): array
+ {
+ foreach ($sections as $section => $paths) {
+ $sections[$section] = static::convertToTree($paths);
+ }
+
+ return $sections;
+ }
+
+ /**
+ * Turn a set of paths into a tree.
+ *
+ * @param array $paths Paths to turn into a tree.
+ * @return array
+ */
+ protected static function convertToTree(array $paths): array
+ {
+ foreach ($paths as $index => $path) {
+ static::convertPathToTree($paths, $index, $path);
+ }
+
+ return $paths;
+ }
+
+ /**
+ * Convert a path into a tree when it contains a directory separator.
+ *
+ * @param array $paths The paths to work on.
+ * @param mixed $index Index of $path.
+ * @param string $path Path to breakup and turn into a tree.
+ * @return void
+ */
+ protected static function convertPathToTree(array &$paths, $index, string $path)
+ {
+ if (strpos($path, DIRECTORY_SEPARATOR) !== false) {
+ $chunks = explode(DIRECTORY_SEPARATOR, $path);
+ $paths = static::branch($paths, $chunks);
+ unset($paths[$index]);
+ }
+ }
+
+ /**
+ * Create a branch for the current level and push a twig on it.
+ *
+ * @param array $paths Paths to append.
+ * @param string[] $branches Branches to use until only one left.
+ * @return array
+ */
+ protected static function branch(array $paths, array $branches): array
+ {
+ $twig = array_shift($branches);
+ if (count($branches) === 0) {
+ $paths[] = $twig;
+
+ return $paths;
+ }
+
+ if (!isset($paths[$twig])) {
+ $paths[$twig] = [];
+ }
+
+ $paths[$twig] = static::branch($paths[$twig], $branches);
+
+ return $paths;
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Panel/TwigPanel.php b/app/vendor/cakephp/twig-view/src/Panel/TwigPanel.php
new file mode 100644
index 000000000..591f95f4e
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Panel/TwigPanel.php
@@ -0,0 +1,60 @@
+ TreeScanner::all(static::$extensions),
+ ];
+ }
+
+ /**
+ * Sets the template file extensions to search.
+ *
+ * @param string[] $extensions Template extensions to search
+ * @return void
+ */
+ public static function setExtensions(array $extensions): void
+ {
+ static::$extensions = $extensions;
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Plugin.php b/app/vendor/cakephp/twig-view/src/Plugin.php
new file mode 100644
index 000000000..c7dbfb3ff
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Plugin.php
@@ -0,0 +1,53 @@
+add('twig-view compile', CompileCommand::class);
+
+ return $commands;
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/Extension/ArraysExtension.php b/app/vendor/cakephp/twig-view/src/Twig/Extension/ArraysExtension.php
new file mode 100644
index 000000000..61bb19a81
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/Extension/ArraysExtension.php
@@ -0,0 +1,48 @@
+isTemplate()) {
+ $name = 'Twig: ' . $profile->getTemplate();
+ DebugTimer::start($name, $name);
+ }
+ }
+
+ /**
+ * @param \Twig\Profiler\Profile $profile Profile.
+ * @return void
+ */
+ public function leave(Profile $profile)
+ {
+ if ($profile->isTemplate()) {
+ $name = 'Twig: ' . $profile->getTemplate();
+ DebugTimer::stop($name);
+ }
+
+ parent::leave($profile);
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/Extension/StringsExtension.php b/app/vendor/cakephp/twig-view/src/Twig/Extension/StringsExtension.php
new file mode 100644
index 000000000..ffcf72328
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/Extension/StringsExtension.php
@@ -0,0 +1,72 @@
+cell($name, $data, $options);
+ },
+ ['needs_context' => true, 'is_safe' => ['all']]
+ ),
+ new TwigFunction(
+ 'element',
+ function ($context, string $name, array $data = [], array $options = []) {
+ return $context['_view']->element($name, $data, $options);
+ },
+ ['needs_context' => true, 'is_safe' => ['all']]
+ ),
+ new TwigFunction(
+ 'fetch',
+ function ($context, string $name, string $default = '') {
+ return $context['_view']->fetch($name, $default);
+ },
+ ['needs_context' => true, 'is_safe' => ['all']]
+ ),
+ new TwigFunction(
+ 'helper_*_*',
+ function ($context, $helper, $method, array $args = []) {
+ return $context['_view']->{$helper}->{$method}(...$args);
+ },
+ ['needs_context' => true, 'is_variadic' => true, 'is_safe' => ['all']]
+ ),
+ ];
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/FileLoader.php b/app/vendor/cakephp/twig-view/src/Twig/FileLoader.php
new file mode 100644
index 000000000..58747661c
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/FileLoader.php
@@ -0,0 +1,146 @@
+extensions = $extensions;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSourceContext(string $name): Source
+ {
+ $path = $this->findTemplate($name);
+
+ return new Source(file_get_contents($path), $name, $path);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getCacheKey(string $name): string
+ {
+ return $this->findTemplate($name);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function isFresh(string $name, int $time): bool
+ {
+ $path = $this->findTemplate($name);
+
+ return filemtime($path) < $time;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function exists(string $name)
+ {
+ try {
+ $this->findTemplate($name);
+ } catch (LoaderError $e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @param string $name Template name
+ * @return string
+ */
+ public function findTemplate(string $name): string
+ {
+ if (file_exists($name)) {
+ return $name;
+ }
+
+ [$plugin, $name] = pluginSplit($name);
+ $name = str_replace('/', DIRECTORY_SEPARATOR, $name);
+
+ if ($plugin !== null) {
+ $templatePath = Plugin::templatePath($plugin);
+ $path = $this->checkExtensions($templatePath . $name);
+ if ($path !== null) {
+ return $path;
+ }
+
+ $error = "Could not find template `{$name}` in plugin `{$plugin}` in these paths:\n\n"
+ . "- `{$templatePath}`\n";
+ throw new LoaderError($error);
+ }
+
+ foreach (App::path('templates') as $templatePath) {
+ $path = $this->checkExtensions($templatePath . $name);
+ if ($path !== null) {
+ return $path;
+ }
+ }
+
+ $error = "Could not find template `{$name}` in these paths:\n\n";
+ foreach (App::path('templates') as $templatePath) {
+ $error .= "- `{$templatePath}`\n";
+ }
+ throw new LoaderError($error);
+ }
+
+ /**
+ * Check partial path with all template file extensions to see
+ * which file exists.
+ *
+ * @param string $partial Template path excluding extension
+ * @return string|null
+ */
+ public function checkExtensions(string $partial): ?string
+ {
+ foreach ($this->extensions as $extension) {
+ $path = $partial . $extension;
+ if (file_exists($path)) {
+ return $path;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/Node/Cell.php b/app/vendor/cakephp/twig-view/src/Twig/Node/Cell.php
new file mode 100644
index 000000000..4a789758f
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/Node/Cell.php
@@ -0,0 +1,113 @@
+ $name,
+ 'data' => $data,
+ 'options' => $options,
+ ],
+ [
+ 'variable' => $variable,
+ ],
+ $lineno,
+ $tag
+ );
+
+ $this->assign = $assign;
+ }
+
+ /**
+ * Compile tag.
+ *
+ * @param \Twig\Compiler $compiler Compiler.
+ * @return void
+ */
+ public function compile(Compiler $compiler)
+ {
+ $compiler->addDebugInfo($this);
+
+ if ($this->assign) {
+ $compiler->raw('$context[\'' . $this->getAttribute('variable') . '\'] = ');
+ } else {
+ $compiler->raw('echo ');
+ }
+ $compiler->raw('$context[\'_view\']->cell(');
+ $compiler->subcompile($this->getNode('name'));
+
+ $data = $this->getNode('data');
+ $compiler->raw(',');
+ $compiler->subcompile($data);
+
+ $options = $this->getNode('options');
+ $compiler->raw(',');
+ $compiler->subcompile($options);
+
+ $compiler->raw(");\n");
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/Node/Element.php b/app/vendor/cakephp/twig-view/src/Twig/Node/Element.php
new file mode 100644
index 000000000..677d5f5d3
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/Node/Element.php
@@ -0,0 +1,92 @@
+ $name,
+ 'data' => $data,
+ 'options' => $options,
+ ],
+ [],
+ $lineno,
+ $tag
+ );
+ }
+
+ /**
+ * Compile node.
+ *
+ * @param \Twig\Compiler $compiler Compiler.
+ * @return void
+ */
+ public function compile(Compiler $compiler)
+ {
+ $compiler->addDebugInfo($this);
+
+ $compiler->raw('echo $context[\'_view\']->element(');
+ $compiler->subcompile($this->getNode('name'));
+
+ $data = $this->getNode('data');
+ $compiler->raw(',');
+ $compiler->subcompile($data);
+
+ $options = $this->getNode('options');
+ $compiler->raw(',');
+ $compiler->subcompile($options);
+
+ $compiler->raw(");\n");
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/Node/LayoutNode.php b/app/vendor/cakephp/twig-view/src/Twig/Node/LayoutNode.php
new file mode 100644
index 000000000..4df5368af
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/Node/LayoutNode.php
@@ -0,0 +1,56 @@
+ $layout], [], $line, $tag);
+ }
+
+ /**
+ * Compile tag.
+ *
+ * @param \Twig\Compiler $compiler Compiler.
+ * @return void
+ */
+ public function compile(Compiler $compiler)
+ {
+ $compiler
+ ->addDebugInfo($this)
+ ->write('$context[\'_view\']->setLayout(')
+ ->subcompile($this->getNode('layout'))
+ ->raw(");\n");
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/TokenParser/CellParser.php b/app/vendor/cakephp/twig-view/src/Twig/TokenParser/CellParser.php
new file mode 100644
index 000000000..8e057272d
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/TokenParser/CellParser.php
@@ -0,0 +1,83 @@
+parser->getStream();
+
+ $variable = null;
+ if ($stream->test(Token::NAME_TYPE)) {
+ $variable = $stream->expect(Token::NAME_TYPE)->getValue();
+ }
+ $assign = false;
+ if ($stream->test(Token::OPERATOR_TYPE)) {
+ $stream->expect(Token::OPERATOR_TYPE, '=');
+ $assign = true;
+ }
+
+ $name = $this->parser->getExpressionParser()->parseExpression();
+ $data = null;
+ if (!$stream->test(Token::BLOCK_END_TYPE)) {
+ $data = $this->parser->getExpressionParser()->parseExpression();
+ }
+ $options = null;
+ if (!$stream->test(Token::BLOCK_END_TYPE)) {
+ $options = $this->parser->getExpressionParser()->parseExpression();
+ }
+
+ $stream->expect(Token::BLOCK_END_TYPE);
+
+ return new CellNode($assign, $variable, $name, $data, $options, $token->getLine(), $this->getTag());
+ }
+
+ /**
+ * Tag name.
+ *
+ * @return string
+ */
+ public function getTag(): string
+ {
+ return 'cell';
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/TokenParser/ElementParser.php b/app/vendor/cakephp/twig-view/src/Twig/TokenParser/ElementParser.php
new file mode 100644
index 000000000..40e8127a9
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/TokenParser/ElementParser.php
@@ -0,0 +1,74 @@
+parser->getStream();
+ $name = $this->parser->getExpressionParser()->parseExpression();
+
+ $data = null;
+ if (!$stream->test(Token::BLOCK_END_TYPE)) {
+ $data = $this->parser->getExpressionParser()->parseExpression();
+ }
+
+ $options = null;
+ if (!$stream->test(Token::BLOCK_END_TYPE)) {
+ $options = $this->parser->getExpressionParser()->parseExpression();
+ }
+
+ $stream->expect(Token::BLOCK_END_TYPE);
+
+ return new ElementNode($name, $data, $options, $token->getLine(), $this->getTag());
+ }
+
+ /**
+ * Get tag name.
+ *
+ * @return string
+ */
+ public function getTag(): string
+ {
+ return 'element';
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/Twig/TokenParser/LayoutParser.php b/app/vendor/cakephp/twig-view/src/Twig/TokenParser/LayoutParser.php
new file mode 100644
index 000000000..e2b2bde0e
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/Twig/TokenParser/LayoutParser.php
@@ -0,0 +1,56 @@
+parser;
+ $stream = $parser->getStream();
+
+ $layout = $parser->getExpressionParser()->parseExpression();
+ $stream->expect(\Twig\Token::BLOCK_END_TYPE);
+
+ return new LayoutNode($layout, $token->getLine(), $this->getTag());
+ }
+
+ /**
+ * Tag name.
+ *
+ * @return string
+ */
+ public function getTag(): string
+ {
+ return 'layout';
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/src/View/TwigView.php b/app/vendor/cakephp/twig-view/src/View/TwigView.php
new file mode 100644
index 000000000..2be780314
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/src/View/TwigView.php
@@ -0,0 +1,353 @@
+ [
+ ],
+ 'markdown' => null,
+ ];
+
+ /**
+ * @inheritDoc
+ */
+ protected $_ext = '.twig';
+
+ /**
+ * List of extensions searched when loading templates.
+ *
+ * @var string[]
+ */
+ protected $extensions = [
+ '.twig',
+ ];
+
+ /**
+ * Initialize view.
+ *
+ * @return void
+ */
+ public function initialize(): void
+ {
+ parent::initialize();
+
+ if (static::$twig === null) {
+ // Cache instance to avoid re-creating when rendering Cells
+ static::$twig = $this->createEnvironment();
+
+ $this->initializeTokenParser();
+ $this->initializeExtensions();
+
+ if (Configure::read('debug') && Plugin::isLoaded('DebugKit')) {
+ $this->initializeProfiler();
+ }
+ }
+
+ if (Configure::read('debug') && Plugin::isLoaded('DebugKit')) {
+ TwigPanel::setExtensions($this->extensions);
+ }
+ }
+
+ /**
+ * Get Twig Environment instance.
+ *
+ * @return \Twig\Environment
+ */
+ public function getTwig(): Environment
+ {
+ if (static::$twig === null) {
+ throw new RuntimeException('Twig Environment instance not created.');
+ }
+
+ return static::$twig;
+ }
+
+ /**
+ * Gets Twig Profile if profiler enabled.
+ *
+ * @return \Twig\Profiler\Profile|null
+ */
+ public function getProfile(): ?Profile
+ {
+ return static::$profile;
+ }
+
+ /** Gets the template file extensions.
+ *
+ * @return string[]
+ */
+ public function getExtensions(): array
+ {
+ return $this->extensions;
+ }
+
+ /**
+ * Creates the Twig LoaderInterface instance.
+ *
+ * @return \Twig\Loader\LoaderInterface
+ */
+ protected function createLoader(): LoaderInterface
+ {
+ return new FileLoader($this->extensions);
+ }
+
+ /**
+ * Creates the Twig Environment.
+ *
+ * @return \Twig\Environment
+ */
+ protected function createEnvironment(): Environment
+ {
+ $debug = Configure::read('debug', false);
+ $cachePath = CACHE . 'twig_view' . DS;
+
+ $config = $this->getConfig('environment') + [
+ 'charset' => Configure::read('App.encoding', 'UTF-8'),
+ 'debug' => $debug,
+ 'cache' => $debug ? false : $cachePath,
+ 'strict_variables' => $debug,
+ ];
+
+ if ($config['cache'] === true) {
+ $config['cache'] = $cachePath;
+ }
+
+ $env = new Environment($this->createLoader(), $config);
+ // Must add before any templates are rendered so can be updated in _render().
+ $env->addGlobal('_view', $this);
+
+ return $env;
+ }
+
+ /**
+ * Adds custom Twig token parsers.
+ *
+ * @return void
+ */
+ protected function initializeTokenParser(): void
+ {
+ $this->getTwig()->addTokenParser(new TokenParser\LayoutParser());
+ $this->getTwig()->addTokenParser(new TokenParser\CellParser());
+ $this->getTwig()->addTokenParser(new TokenParser\ElementParser());
+ }
+
+ // phpcs:disable CakePHP.Commenting.FunctionComment.InvalidReturnVoid
+
+ /**
+ * Adds Twig extensions.
+ *
+ * @return void
+ */
+ protected function initializeExtensions(): void
+ {
+ $twig = $this->getTwig();
+
+ // Twig core extensions
+ $twig->addExtension(new StringLoaderExtension());
+
+ if (Configure::read('debug', false)) {
+ $twig->addExtension(new DebugExtension());
+ }
+
+ // CakePHP bridging extensions
+ $twig->addExtension(new Extension\ArraysExtension());
+ $twig->addExtension(new Extension\BasicExtension());
+ $twig->addExtension(new Extension\ConfigureExtension());
+ $twig->addExtension(new Extension\I18nExtension());
+ $twig->addExtension(new Extension\InflectorExtension());
+ $twig->addExtension(new Extension\NumberExtension());
+ $twig->addExtension(new Extension\StringsExtension());
+ $twig->addExtension(new Extension\TimeExtension());
+ $twig->addExtension(new Extension\UtilsExtension());
+ $twig->addExtension(new Extension\ViewExtension());
+
+ // Markdown extension
+ $markdown = $this->getConfig('markdown');
+ if ($markdown !== null) {
+ $twig->addExtension(new MarkdownExtension());
+
+ $engine = $markdown === 'default' ? new DefaultMarkdown() : $markdown;
+ $twig->addRuntimeLoader(new class ($engine) implements RuntimeLoaderInterface {
+ /**
+ * @var \Twig\Extra\Markdown\MarkdownInterface
+ */
+ private $engine;
+
+ /**
+ * @param \Twig\Extra\Markdown\MarkdownInterface $engine MarkdownInterface instance
+ */
+ public function __construct(MarkdownInterface $engine)
+ {
+ $this->engine = $engine;
+ }
+
+ /**
+ * @param string $class FQCN
+ * @return object|null
+ */
+ public function load($class)
+ {
+ if ($class === MarkdownRuntime::class) {
+ return new MarkdownRuntime($this->engine);
+ }
+
+ return null;
+ }
+ });
+ }
+
+ // jasny/twig-extensions
+ $twig->addExtension(new DateExtension());
+ $twig->addExtension(new ArrayExtension());
+ $twig->addExtension(new PcreExtension());
+ $twig->addExtension(new TextExtension());
+ }
+
+ // phpcs:enable
+
+ /**
+ * Initializes Twig profiler extension.
+ *
+ * @return void
+ */
+ protected function initializeProfiler(): void
+ {
+ static::$profile = new Profile();
+ $this->getTwig()->addExtension(new Extension\ProfilerExtension(static::$profile));
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function _evaluate(string $templateFile, array $dataForView): string
+ {
+ // Set _view for each render because Twig Environment is shared between views.
+ $this->getTwig()->addGlobal('_view', $this);
+
+ $dataForView = array_merge(
+ $dataForView,
+ iterator_to_array($this->helpers()->getIterator())
+ );
+
+ return $this->getTwig()->load($templateFile)->render($dataForView);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function _getTemplateFileName(?string $name = null): string
+ {
+ foreach ($this->extensions as $extension) {
+ $this->_ext = $extension;
+ try {
+ return parent::_getTemplateFileName($name);
+ } catch (MissingTemplateException $exception) {
+ $missingException = $exception;
+ }
+ }
+
+ throw $missingException ?? new MissingTemplateException($name ?? $this->getTemplate());
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function _getLayoutFileName(?string $name = null): string
+ {
+ foreach ($this->extensions as $extension) {
+ $this->_ext = $extension;
+ try {
+ return parent::_getLayoutFileName($name);
+ } catch (MissingLayoutException $exception) {
+ $missingException = $exception;
+ }
+ }
+
+ throw $missingException ?? new MissingLayoutException($name ?? $this->getLayout());
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function _getElementFileName(string $name, bool $pluginCheck = true)
+ {
+ foreach ($this->extensions as $extension) {
+ $this->_ext = $extension;
+ $result = parent::_getElementFileName($name, $pluginCheck);
+ if ($result !== false) {
+ return $result;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/app/vendor/cakephp/twig-view/templates/element/twig_panel.php b/app/vendor/cakephp/twig-view/templates/element/twig_panel.php
new file mode 100644
index 000000000..70e4b06fa
--- /dev/null
+++ b/app/vendor/cakephp/twig-view/templates/element/twig_panel.php
@@ -0,0 +1,2 @@
+Templates
+= $this->Toolbar->makeNeatArray($templates) ?>
diff --git a/app/vendor/composer/autoload_classmap.php b/app/vendor/composer/autoload_classmap.php
index 7399327be..5a89603f5 100644
--- a/app/vendor/composer/autoload_classmap.php
+++ b/app/vendor/composer/autoload_classmap.php
@@ -8,9 +8,596 @@
return array(
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
+ 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
'Mobile_Detect' => $vendorDir . '/mobiledetect/mobiledetectlib/Mobile_Detect.php',
+ 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
+ 'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
+ 'PHPUnit\\Framework\\Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php',
+ 'PHPUnit\\Framework\\AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php',
+ 'PHPUnit\\Framework\\CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php',
+ 'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArrayHasKey.php',
+ 'PHPUnit\\Framework\\Constraint\\ArraySubset' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArraySubset.php',
+ 'PHPUnit\\Framework\\Constraint\\Attribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Attribute.php',
+ 'PHPUnit\\Framework\\Constraint\\Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php',
+ 'PHPUnit\\Framework\\Constraint\\ClassHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasAttribute.php',
+ 'PHPUnit\\Framework\\Constraint\\ClassHasStaticAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasStaticAttribute.php',
+ 'PHPUnit\\Framework\\Constraint\\Composite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Composite.php',
+ 'PHPUnit\\Framework\\Constraint\\Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php',
+ 'PHPUnit\\Framework\\Constraint\\Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Count.php',
+ 'PHPUnit\\Framework\\Constraint\\DirectoryExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/DirectoryExists.php',
+ 'PHPUnit\\Framework\\Constraint\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception.php',
+ 'PHPUnit\\Framework\\Constraint\\ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionCode.php',
+ 'PHPUnit\\Framework\\Constraint\\ExceptionMessage' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessage.php',
+ 'PHPUnit\\Framework\\Constraint\\ExceptionMessageRegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessageRegularExpression.php',
+ 'PHPUnit\\Framework\\Constraint\\FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/FileExists.php',
+ 'PHPUnit\\Framework\\Constraint\\GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/GreaterThan.php',
+ 'PHPUnit\\Framework\\Constraint\\IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php',
+ 'PHPUnit\\Framework\\Constraint\\IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEmpty.php',
+ 'PHPUnit\\Framework\\Constraint\\IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEqual.php',
+ 'PHPUnit\\Framework\\Constraint\\IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsFalse.php',
+ 'PHPUnit\\Framework\\Constraint\\IsFinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsFinite.php',
+ 'PHPUnit\\Framework\\Constraint\\IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php',
+ 'PHPUnit\\Framework\\Constraint\\IsInfinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsInfinite.php',
+ 'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsInstanceOf.php',
+ 'PHPUnit\\Framework\\Constraint\\IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsJson.php',
+ 'PHPUnit\\Framework\\Constraint\\IsNan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsNan.php',
+ 'PHPUnit\\Framework\\Constraint\\IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsNull.php',
+ 'PHPUnit\\Framework\\Constraint\\IsReadable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsReadable.php',
+ 'PHPUnit\\Framework\\Constraint\\IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsTrue.php',
+ 'PHPUnit\\Framework\\Constraint\\IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsType.php',
+ 'PHPUnit\\Framework\\Constraint\\IsWritable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsWritable.php',
+ 'PHPUnit\\Framework\\Constraint\\JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php',
+ 'PHPUnit\\Framework\\Constraint\\JsonMatchesErrorMessageProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php',
+ 'PHPUnit\\Framework\\Constraint\\LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LessThan.php',
+ 'PHPUnit\\Framework\\Constraint\\LogicalAnd' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LogicalAnd.php',
+ 'PHPUnit\\Framework\\Constraint\\LogicalNot' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LogicalNot.php',
+ 'PHPUnit\\Framework\\Constraint\\LogicalOr' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LogicalOr.php',
+ 'PHPUnit\\Framework\\Constraint\\LogicalXor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LogicalXor.php',
+ 'PHPUnit\\Framework\\Constraint\\ObjectHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ObjectHasAttribute.php',
+ 'PHPUnit\\Framework\\Constraint\\RegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/RegularExpression.php',
+ 'PHPUnit\\Framework\\Constraint\\SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/SameSize.php',
+ 'PHPUnit\\Framework\\Constraint\\StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringContains.php',
+ 'PHPUnit\\Framework\\Constraint\\StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringEndsWith.php',
+ 'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringMatchesFormatDescription.php',
+ 'PHPUnit\\Framework\\Constraint\\StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringStartsWith.php',
+ 'PHPUnit\\Framework\\Constraint\\TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContains.php',
+ 'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsEqual.php',
+ 'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsIdentical.php',
+ 'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsOnly.php',
+ 'PHPUnit\\Framework\\CoveredCodeNotExecutedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php',
+ 'PHPUnit\\Framework\\DataProviderTestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php',
+ 'PHPUnit\\Framework\\Error\\Deprecated' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Deprecated.php',
+ 'PHPUnit\\Framework\\Error\\Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Error.php',
+ 'PHPUnit\\Framework\\Error\\Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Notice.php',
+ 'PHPUnit\\Framework\\Error\\Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Warning.php',
+ 'PHPUnit\\Framework\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Exception.php',
+ 'PHPUnit\\Framework\\ExceptionWrapper' => $vendorDir . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php',
+ 'PHPUnit\\Framework\\ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php',
+ 'PHPUnit\\Framework\\IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTest.php',
+ 'PHPUnit\\Framework\\IncompleteTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php',
+ 'PHPUnit\\Framework\\IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php',
+ 'PHPUnit\\Framework\\InvalidArgumentException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php',
+ 'PHPUnit\\Framework\\InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php',
+ 'PHPUnit\\Framework\\InvalidDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php',
+ 'PHPUnit\\Framework\\InvalidParameterGroupException' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php',
+ 'PHPUnit\\Framework\\MissingCoversAnnotationException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php',
+ 'PHPUnit\\Framework\\MockObject\\Api' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/Api.php',
+ 'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\Match_' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/Match_.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php',
+ 'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php',
+ 'PHPUnit\\Framework\\MockObject\\ConfigurableMethodsAlreadyInitializedException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php',
+ 'PHPUnit\\Framework\\MockObject\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php',
+ 'PHPUnit\\Framework\\MockObject\\Generator' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator.php',
+ 'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php',
+ 'PHPUnit\\Framework\\MockObject\\Invocation' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Invocation.php',
+ 'PHPUnit\\Framework\\MockObject\\InvocationHandler' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php',
+ 'PHPUnit\\Framework\\MockObject\\Matcher' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Matcher.php',
+ 'PHPUnit\\Framework\\MockObject\\Method' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/Method.php',
+ 'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php',
+ 'PHPUnit\\Framework\\MockObject\\MockBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php',
+ 'PHPUnit\\Framework\\MockObject\\MockClass' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockClass.php',
+ 'PHPUnit\\Framework\\MockObject\\MockMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockMethod.php',
+ 'PHPUnit\\Framework\\MockObject\\MockMethodSet' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php',
+ 'PHPUnit\\Framework\\MockObject\\MockObject' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockObject.php',
+ 'PHPUnit\\Framework\\MockObject\\MockTrait' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockTrait.php',
+ 'PHPUnit\\Framework\\MockObject\\MockType' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockType.php',
+ 'PHPUnit\\Framework\\MockObject\\MockedCloneMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/MockedCloneMethod.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\ConsecutiveParameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtIndex' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php',
+ 'PHPUnit\\Framework\\MockObject\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php',
+ 'PHPUnit\\Framework\\MockObject\\UnmockedCloneMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/UnmockedCloneMethod.php',
+ 'PHPUnit\\Framework\\MockObject\\Verifiable' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Verifiable.php',
+ 'PHPUnit\\Framework\\NoChildTestSuiteException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php',
+ 'PHPUnit\\Framework\\OutputError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/OutputError.php',
+ 'PHPUnit\\Framework\\PHPTAssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php',
+ 'PHPUnit\\Framework\\RiskyTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php',
+ 'PHPUnit\\Framework\\SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
+ 'PHPUnit\\Framework\\SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTest.php',
+ 'PHPUnit\\Framework\\SkippedTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestCase.php',
+ 'PHPUnit\\Framework\\SkippedTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php',
+ 'PHPUnit\\Framework\\SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php',
+ 'PHPUnit\\Framework\\SyntheticError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SyntheticError.php',
+ 'PHPUnit\\Framework\\SyntheticSkippedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php',
+ 'PHPUnit\\Framework\\Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php',
+ 'PHPUnit\\Framework\\TestBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/TestBuilder.php',
+ 'PHPUnit\\Framework\\TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php',
+ 'PHPUnit\\Framework\\TestFailure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestFailure.php',
+ 'PHPUnit\\Framework\\TestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListener.php',
+ 'PHPUnit\\Framework\\TestListenerDefaultImplementation' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php',
+ 'PHPUnit\\Framework\\TestResult' => $vendorDir . '/phpunit/phpunit/src/Framework/TestResult.php',
+ 'PHPUnit\\Framework\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php',
+ 'PHPUnit\\Framework\\TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php',
+ 'PHPUnit\\Framework\\UnintentionallyCoveredCodeError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php',
+ 'PHPUnit\\Framework\\Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Warning.php',
+ 'PHPUnit\\Framework\\WarningTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/WarningTestCase.php',
+ 'PHPUnit\\Runner\\AfterIncompleteTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php',
+ 'PHPUnit\\Runner\\AfterLastTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php',
+ 'PHPUnit\\Runner\\AfterRiskyTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php',
+ 'PHPUnit\\Runner\\AfterSkippedTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php',
+ 'PHPUnit\\Runner\\AfterSuccessfulTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php',
+ 'PHPUnit\\Runner\\AfterTestErrorHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php',
+ 'PHPUnit\\Runner\\AfterTestFailureHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php',
+ 'PHPUnit\\Runner\\AfterTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php',
+ 'PHPUnit\\Runner\\AfterTestWarningHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php',
+ 'PHPUnit\\Runner\\BaseTestRunner' => $vendorDir . '/phpunit/phpunit/src/Runner/BaseTestRunner.php',
+ 'PHPUnit\\Runner\\BeforeFirstTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php',
+ 'PHPUnit\\Runner\\BeforeTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php',
+ 'PHPUnit\\Runner\\DefaultTestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/DefaultTestResultCache.php',
+ 'PHPUnit\\Runner\\Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception.php',
+ 'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php',
+ 'PHPUnit\\Runner\\Filter\\Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php',
+ 'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php',
+ 'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php',
+ 'PHPUnit\\Runner\\Filter\\NameFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php',
+ 'PHPUnit\\Runner\\Hook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/Hook.php',
+ 'PHPUnit\\Runner\\NullTestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/NullTestResultCache.php',
+ 'PHPUnit\\Runner\\PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Runner/PhptTestCase.php',
+ 'PHPUnit\\Runner\\ResultCacheExtension' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCacheExtension.php',
+ 'PHPUnit\\Runner\\StandardTestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php',
+ 'PHPUnit\\Runner\\TestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/TestHook.php',
+ 'PHPUnit\\Runner\\TestListenerAdapter' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php',
+ 'PHPUnit\\Runner\\TestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResultCache.php',
+ 'PHPUnit\\Runner\\TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php',
+ 'PHPUnit\\Runner\\TestSuiteSorter' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php',
+ 'PHPUnit\\Runner\\Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php',
+ 'PHPUnit\\TextUI\\Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command.php',
+ 'PHPUnit\\TextUI\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception.php',
+ 'PHPUnit\\TextUI\\Help' => $vendorDir . '/phpunit/phpunit/src/TextUI/Help.php',
+ 'PHPUnit\\TextUI\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/ResultPrinter.php',
+ 'PHPUnit\\TextUI\\TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php',
+ 'PHPUnit\\Util\\Annotation\\DocBlock' => $vendorDir . '/phpunit/phpunit/src/Util/Annotation/DocBlock.php',
+ 'PHPUnit\\Util\\Annotation\\Registry' => $vendorDir . '/phpunit/phpunit/src/Util/Annotation/Registry.php',
+ 'PHPUnit\\Util\\Blacklist' => $vendorDir . '/phpunit/phpunit/src/Util/Blacklist.php',
+ 'PHPUnit\\Util\\Color' => $vendorDir . '/phpunit/phpunit/src/Util/Color.php',
+ 'PHPUnit\\Util\\Configuration' => $vendorDir . '/phpunit/phpunit/src/Util/Configuration.php',
+ 'PHPUnit\\Util\\ConfigurationGenerator' => $vendorDir . '/phpunit/phpunit/src/Util/ConfigurationGenerator.php',
+ 'PHPUnit\\Util\\ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Util/ErrorHandler.php',
+ 'PHPUnit\\Util\\Exception' => $vendorDir . '/phpunit/phpunit/src/Util/Exception.php',
+ 'PHPUnit\\Util\\FileLoader' => $vendorDir . '/phpunit/phpunit/src/Util/FileLoader.php',
+ 'PHPUnit\\Util\\Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php',
+ 'PHPUnit\\Util\\Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php',
+ 'PHPUnit\\Util\\Getopt' => $vendorDir . '/phpunit/phpunit/src/Util/Getopt.php',
+ 'PHPUnit\\Util\\GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php',
+ 'PHPUnit\\Util\\InvalidDataSetException' => $vendorDir . '/phpunit/phpunit/src/Util/InvalidDataSetException.php',
+ 'PHPUnit\\Util\\Json' => $vendorDir . '/phpunit/phpunit/src/Util/Json.php',
+ 'PHPUnit\\Util\\Log\\JUnit' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JUnit.php',
+ 'PHPUnit\\Util\\Log\\TeamCity' => $vendorDir . '/phpunit/phpunit/src/Util/Log/TeamCity.php',
+ 'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php',
+ 'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php',
+ 'PHPUnit\\Util\\PHP\\WindowsPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php',
+ 'PHPUnit\\Util\\Printer' => $vendorDir . '/phpunit/phpunit/src/Util/Printer.php',
+ 'PHPUnit\\Util\\RegularExpression' => $vendorDir . '/phpunit/phpunit/src/Util/RegularExpression.php',
+ 'PHPUnit\\Util\\Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php',
+ 'PHPUnit\\Util\\TestDox\\CliTestDoxPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\HtmlResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php',
+ 'PHPUnit\\Util\\TestDox\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\TestDoxPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\TextResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\XmlResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php',
+ 'PHPUnit\\Util\\TextTestListRenderer' => $vendorDir . '/phpunit/phpunit/src/Util/TextTestListRenderer.php',
+ 'PHPUnit\\Util\\Type' => $vendorDir . '/phpunit/phpunit/src/Util/Type.php',
+ 'PHPUnit\\Util\\VersionComparisonOperator' => $vendorDir . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php',
+ 'PHPUnit\\Util\\XdebugFilterScriptGenerator' => $vendorDir . '/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php',
+ 'PHPUnit\\Util\\Xml' => $vendorDir . '/phpunit/phpunit/src/Util/Xml.php',
+ 'PHPUnit\\Util\\XmlTestListRenderer' => $vendorDir . '/phpunit/phpunit/src/Util/XmlTestListRenderer.php',
+ 'PHP_Token' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
+ 'PHP_TokenWithScope' => $vendorDir . '/phpunit/php-token-stream/src/TokenWithScope.php',
+ 'PHP_TokenWithScopeAndVisibility' => $vendorDir . '/phpunit/php-token-stream/src/TokenWithScopeAndVisibility.php',
+ 'PHP_Token_ABSTRACT' => $vendorDir . '/phpunit/php-token-stream/src/Abstract.php',
+ 'PHP_Token_AMPERSAND' => $vendorDir . '/phpunit/php-token-stream/src/Ampersand.php',
+ 'PHP_Token_AND_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/AndEqual.php',
+ 'PHP_Token_ARRAY' => $vendorDir . '/phpunit/php-token-stream/src/Array.php',
+ 'PHP_Token_ARRAY_CAST' => $vendorDir . '/phpunit/php-token-stream/src/ArrayCast.php',
+ 'PHP_Token_AS' => $vendorDir . '/phpunit/php-token-stream/src/As.php',
+ 'PHP_Token_AT' => $vendorDir . '/phpunit/php-token-stream/src/At.php',
+ 'PHP_Token_BACKTICK' => $vendorDir . '/phpunit/php-token-stream/src/Backtick.php',
+ 'PHP_Token_BAD_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/BadCharacter.php',
+ 'PHP_Token_BOOLEAN_AND' => $vendorDir . '/phpunit/php-token-stream/src/BooleanAnd.php',
+ 'PHP_Token_BOOLEAN_OR' => $vendorDir . '/phpunit/php-token-stream/src/BooleanOr.php',
+ 'PHP_Token_BOOL_CAST' => $vendorDir . '/phpunit/php-token-stream/src/BoolCast.php',
+ 'PHP_Token_BREAK' => $vendorDir . '/phpunit/php-token-stream/src/break.php',
+ 'PHP_Token_CALLABLE' => $vendorDir . '/phpunit/php-token-stream/src/Callable.php',
+ 'PHP_Token_CARET' => $vendorDir . '/phpunit/php-token-stream/src/Caret.php',
+ 'PHP_Token_CASE' => $vendorDir . '/phpunit/php-token-stream/src/Case.php',
+ 'PHP_Token_CATCH' => $vendorDir . '/phpunit/php-token-stream/src/Catch.php',
+ 'PHP_Token_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Character.php',
+ 'PHP_Token_CLASS' => $vendorDir . '/phpunit/php-token-stream/src/Class.php',
+ 'PHP_Token_CLASS_C' => $vendorDir . '/phpunit/php-token-stream/src/ClassC.php',
+ 'PHP_Token_CLASS_NAME_CONSTANT' => $vendorDir . '/phpunit/php-token-stream/src/ClassNameConstant.php',
+ 'PHP_Token_CLONE' => $vendorDir . '/phpunit/php-token-stream/src/Clone.php',
+ 'PHP_Token_CLOSE_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/CloseBracket.php',
+ 'PHP_Token_CLOSE_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/CloseCurly.php',
+ 'PHP_Token_CLOSE_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/CloseSquare.php',
+ 'PHP_Token_CLOSE_TAG' => $vendorDir . '/phpunit/php-token-stream/src/CloseTag.php',
+ 'PHP_Token_COALESCE' => $vendorDir . '/phpunit/php-token-stream/src/Coalesce.php',
+ 'PHP_Token_COALESCE_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/CoalesceEqual.php',
+ 'PHP_Token_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Colon.php',
+ 'PHP_Token_COMMA' => $vendorDir . '/phpunit/php-token-stream/src/Comma.php',
+ 'PHP_Token_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Comment.php',
+ 'PHP_Token_CONCAT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/ConcatEqual.php',
+ 'PHP_Token_CONST' => $vendorDir . '/phpunit/php-token-stream/src/Const.php',
+ 'PHP_Token_CONSTANT_ENCAPSED_STRING' => $vendorDir . '/phpunit/php-token-stream/src/ConstantEncapsedString.php',
+ 'PHP_Token_CONTINUE' => $vendorDir . '/phpunit/php-token-stream/src/Continue.php',
+ 'PHP_Token_CURLY_OPEN' => $vendorDir . '/phpunit/php-token-stream/src/CurlyOpen.php',
+ 'PHP_Token_DEC' => $vendorDir . '/phpunit/php-token-stream/src/Dec.php',
+ 'PHP_Token_DECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Declare.php',
+ 'PHP_Token_DEFAULT' => $vendorDir . '/phpunit/php-token-stream/src/Default.php',
+ 'PHP_Token_DIR' => $vendorDir . '/phpunit/php-token-stream/src/Dir.php',
+ 'PHP_Token_DIV' => $vendorDir . '/phpunit/php-token-stream/src/Div.php',
+ 'PHP_Token_DIV_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/DivEqual.php',
+ 'PHP_Token_DNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/DNumber.php',
+ 'PHP_Token_DO' => $vendorDir . '/phpunit/php-token-stream/src/Do.php',
+ 'PHP_Token_DOC_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/DocComment.php',
+ 'PHP_Token_DOLLAR' => $vendorDir . '/phpunit/php-token-stream/src/Dollar.php',
+ 'PHP_Token_DOLLAR_OPEN_CURLY_BRACES' => $vendorDir . '/phpunit/php-token-stream/src/DollarOpenCurlyBraces.php',
+ 'PHP_Token_DOT' => $vendorDir . '/phpunit/php-token-stream/src/Dot.php',
+ 'PHP_Token_DOUBLE_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/DoubleArrow.php',
+ 'PHP_Token_DOUBLE_CAST' => $vendorDir . '/phpunit/php-token-stream/src/DoubleCast.php',
+ 'PHP_Token_DOUBLE_COLON' => $vendorDir . '/phpunit/php-token-stream/src/DoubleColon.php',
+ 'PHP_Token_DOUBLE_QUOTES' => $vendorDir . '/phpunit/php-token-stream/src/DoubleQuotes.php',
+ 'PHP_Token_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Echo.php',
+ 'PHP_Token_ELLIPSIS' => $vendorDir . '/phpunit/php-token-stream/src/Ellipsis.php',
+ 'PHP_Token_ELSE' => $vendorDir . '/phpunit/php-token-stream/src/Else.php',
+ 'PHP_Token_ELSEIF' => $vendorDir . '/phpunit/php-token-stream/src/Elseif.php',
+ 'PHP_Token_EMPTY' => $vendorDir . '/phpunit/php-token-stream/src/Empty.php',
+ 'PHP_Token_ENCAPSED_AND_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/EncapsedAndWhitespace.php',
+ 'PHP_Token_ENDDECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Enddeclare.php',
+ 'PHP_Token_ENDFOR' => $vendorDir . '/phpunit/php-token-stream/src/Endfor.php',
+ 'PHP_Token_ENDFOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Endforeach.php',
+ 'PHP_Token_ENDIF' => $vendorDir . '/phpunit/php-token-stream/src/Endif.php',
+ 'PHP_Token_ENDSWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Endswitch.php',
+ 'PHP_Token_ENDWHILE' => $vendorDir . '/phpunit/php-token-stream/src/Endwhile.php',
+ 'PHP_Token_END_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/EndHeredoc.php',
+ 'PHP_Token_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Equal.php',
+ 'PHP_Token_EVAL' => $vendorDir . '/phpunit/php-token-stream/src/Eval.php',
+ 'PHP_Token_EXCLAMATION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/ExclamationMark.php',
+ 'PHP_Token_EXIT' => $vendorDir . '/phpunit/php-token-stream/src/Exit.php',
+ 'PHP_Token_EXTENDS' => $vendorDir . '/phpunit/php-token-stream/src/Extends.php',
+ 'PHP_Token_FILE' => $vendorDir . '/phpunit/php-token-stream/src/File.php',
+ 'PHP_Token_FINAL' => $vendorDir . '/phpunit/php-token-stream/src/Final.php',
+ 'PHP_Token_FINALLY' => $vendorDir . '/phpunit/php-token-stream/src/Finally.php',
+ 'PHP_Token_FN' => $vendorDir . '/phpunit/php-token-stream/src/Fn.php',
+ 'PHP_Token_FOR' => $vendorDir . '/phpunit/php-token-stream/src/For.php',
+ 'PHP_Token_FOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Foreach.php',
+ 'PHP_Token_FUNCTION' => $vendorDir . '/phpunit/php-token-stream/src/Function.php',
+ 'PHP_Token_FUNC_C' => $vendorDir . '/phpunit/php-token-stream/src/FuncC.php',
+ 'PHP_Token_GLOBAL' => $vendorDir . '/phpunit/php-token-stream/src/Global.php',
+ 'PHP_Token_GOTO' => $vendorDir . '/phpunit/php-token-stream/src/Goto.php',
+ 'PHP_Token_GT' => $vendorDir . '/phpunit/php-token-stream/src/Gt.php',
+ 'PHP_Token_HALT_COMPILER' => $vendorDir . '/phpunit/php-token-stream/src/HaltCompiler.php',
+ 'PHP_Token_IF' => $vendorDir . '/phpunit/php-token-stream/src/If.php',
+ 'PHP_Token_IMPLEMENTS' => $vendorDir . '/phpunit/php-token-stream/src/Implements.php',
+ 'PHP_Token_INC' => $vendorDir . '/phpunit/php-token-stream/src/Inc.php',
+ 'PHP_Token_INCLUDE' => $vendorDir . '/phpunit/php-token-stream/src/Include.php',
+ 'PHP_Token_INCLUDE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/IncludeOnce.php',
+ 'PHP_Token_INLINE_HTML' => $vendorDir . '/phpunit/php-token-stream/src/InlineHtml.php',
+ 'PHP_Token_INSTANCEOF' => $vendorDir . '/phpunit/php-token-stream/src/Instanceof.php',
+ 'PHP_Token_INSTEADOF' => $vendorDir . '/phpunit/php-token-stream/src/Insteadof.php',
+ 'PHP_Token_INTERFACE' => $vendorDir . '/phpunit/php-token-stream/src/Interface.php',
+ 'PHP_Token_INT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/IntCast.php',
+ 'PHP_Token_ISSET' => $vendorDir . '/phpunit/php-token-stream/src/Isset.php',
+ 'PHP_Token_IS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/IsEqual.php',
+ 'PHP_Token_IS_GREATER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/IsGreaterOrEqual.php',
+ 'PHP_Token_IS_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/IsIdentical.php',
+ 'PHP_Token_IS_NOT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/IsNotEqual.php',
+ 'PHP_Token_IS_NOT_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/IsNotIdentical.php',
+ 'PHP_Token_IS_SMALLER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/IsSmallerOrEqual.php',
+ 'PHP_Token_Includes' => $vendorDir . '/phpunit/php-token-stream/src/Includes.php',
+ 'PHP_Token_LINE' => $vendorDir . '/phpunit/php-token-stream/src/Line.php',
+ 'PHP_Token_LIST' => $vendorDir . '/phpunit/php-token-stream/src/List.php',
+ 'PHP_Token_LNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Lnumber.php',
+ 'PHP_Token_LOGICAL_AND' => $vendorDir . '/phpunit/php-token-stream/src/LogicalAnd.php',
+ 'PHP_Token_LOGICAL_OR' => $vendorDir . '/phpunit/php-token-stream/src/LogicalOr.php',
+ 'PHP_Token_LOGICAL_XOR' => $vendorDir . '/phpunit/php-token-stream/src/LogicalXor.php',
+ 'PHP_Token_LT' => $vendorDir . '/phpunit/php-token-stream/src/Lt.php',
+ 'PHP_Token_METHOD_C' => $vendorDir . '/phpunit/php-token-stream/src/MethodC.php',
+ 'PHP_Token_MINUS' => $vendorDir . '/phpunit/php-token-stream/src/Minus.php',
+ 'PHP_Token_MINUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/MinusEqual.php',
+ 'PHP_Token_MOD_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/ModEqual.php',
+ 'PHP_Token_MULT' => $vendorDir . '/phpunit/php-token-stream/src/Mult.php',
+ 'PHP_Token_MUL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/MulEqual.php',
+ 'PHP_Token_NAMESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Namespace.php',
+ 'PHP_Token_NAME_FULLY_QUALIFIED' => $vendorDir . '/phpunit/php-token-stream/src/NameFullyQualified.php',
+ 'PHP_Token_NAME_QUALIFIED' => $vendorDir . '/phpunit/php-token-stream/src/NameQualified.php',
+ 'PHP_Token_NAME_RELATIVE' => $vendorDir . '/phpunit/php-token-stream/src/NameRelative.php',
+ 'PHP_Token_NEW' => $vendorDir . '/phpunit/php-token-stream/src/New.php',
+ 'PHP_Token_NS_C' => $vendorDir . '/phpunit/php-token-stream/src/NsC.php',
+ 'PHP_Token_NS_SEPARATOR' => $vendorDir . '/phpunit/php-token-stream/src/NsSeparator.php',
+ 'PHP_Token_NUM_STRING' => $vendorDir . '/phpunit/php-token-stream/src/NumString.php',
+ 'PHP_Token_OBJECT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/ObjectCast.php',
+ 'PHP_Token_OBJECT_OPERATOR' => $vendorDir . '/phpunit/php-token-stream/src/ObjectOperator.php',
+ 'PHP_Token_OPEN_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/OpenBracket.php',
+ 'PHP_Token_OPEN_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/OpenCurly.php',
+ 'PHP_Token_OPEN_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/OpenSquare.php',
+ 'PHP_Token_OPEN_TAG' => $vendorDir . '/phpunit/php-token-stream/src/OpenTag.php',
+ 'PHP_Token_OPEN_TAG_WITH_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/OpenTagWithEcho.php',
+ 'PHP_Token_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/OrEqual.php',
+ 'PHP_Token_PAAMAYIM_NEKUDOTAYIM' => $vendorDir . '/phpunit/php-token-stream/src/PaamayimNekudotayim.php',
+ 'PHP_Token_PERCENT' => $vendorDir . '/phpunit/php-token-stream/src/Percent.php',
+ 'PHP_Token_PIPE' => $vendorDir . '/phpunit/php-token-stream/src/Pipe.php',
+ 'PHP_Token_PLUS' => $vendorDir . '/phpunit/php-token-stream/src/Plus.php',
+ 'PHP_Token_PLUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/PlusEqual.php',
+ 'PHP_Token_POW' => $vendorDir . '/phpunit/php-token-stream/src/Pow.php',
+ 'PHP_Token_POW_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/PowEqual.php',
+ 'PHP_Token_PRINT' => $vendorDir . '/phpunit/php-token-stream/src/Print.php',
+ 'PHP_Token_PRIVATE' => $vendorDir . '/phpunit/php-token-stream/src/Private.php',
+ 'PHP_Token_PROTECTED' => $vendorDir . '/phpunit/php-token-stream/src/Protected.php',
+ 'PHP_Token_PUBLIC' => $vendorDir . '/phpunit/php-token-stream/src/Public.php',
+ 'PHP_Token_QUESTION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/QuestionMark.php',
+ 'PHP_Token_REQUIRE' => $vendorDir . '/phpunit/php-token-stream/src/Require.php',
+ 'PHP_Token_REQUIRE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/RequireOnce.php',
+ 'PHP_Token_RETURN' => $vendorDir . '/phpunit/php-token-stream/src/Return.php',
+ 'PHP_Token_SEMICOLON' => $vendorDir . '/phpunit/php-token-stream/src/Semicolon.php',
+ 'PHP_Token_SL' => $vendorDir . '/phpunit/php-token-stream/src/Sl.php',
+ 'PHP_Token_SL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/SlEqual.php',
+ 'PHP_Token_SPACESHIP' => $vendorDir . '/phpunit/php-token-stream/src/Spaceship.php',
+ 'PHP_Token_SR' => $vendorDir . '/phpunit/php-token-stream/src/Sr.php',
+ 'PHP_Token_SR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/SrEqual.php',
+ 'PHP_Token_START_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/StartHeredoc.php',
+ 'PHP_Token_STATIC' => $vendorDir . '/phpunit/php-token-stream/src/Static.php',
+ 'PHP_Token_STRING' => $vendorDir . '/phpunit/php-token-stream/src/String.php',
+ 'PHP_Token_STRING_CAST' => $vendorDir . '/phpunit/php-token-stream/src/StringCast.php',
+ 'PHP_Token_STRING_VARNAME' => $vendorDir . '/phpunit/php-token-stream/src/StringVarname.php',
+ 'PHP_Token_SWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Switch.php',
+ 'PHP_Token_Stream' => $vendorDir . '/phpunit/php-token-stream/src/Stream.php',
+ 'PHP_Token_Stream_CachingFactory' => $vendorDir . '/phpunit/php-token-stream/src/CachingFactory.php',
+ 'PHP_Token_THROW' => $vendorDir . '/phpunit/php-token-stream/src/Throw.php',
+ 'PHP_Token_TILDE' => $vendorDir . '/phpunit/php-token-stream/src/Tilde.php',
+ 'PHP_Token_TRAIT' => $vendorDir . '/phpunit/php-token-stream/src/Trait.php',
+ 'PHP_Token_TRAIT_C' => $vendorDir . '/phpunit/php-token-stream/src/TraitC.php',
+ 'PHP_Token_TRY' => $vendorDir . '/phpunit/php-token-stream/src/Try.php',
+ 'PHP_Token_UNSET' => $vendorDir . '/phpunit/php-token-stream/src/Unset.php',
+ 'PHP_Token_UNSET_CAST' => $vendorDir . '/phpunit/php-token-stream/src/UnsetCast.php',
+ 'PHP_Token_USE' => $vendorDir . '/phpunit/php-token-stream/src/Use.php',
+ 'PHP_Token_USE_FUNCTION' => $vendorDir . '/phpunit/php-token-stream/src/UseFunction.php',
+ 'PHP_Token_Util' => $vendorDir . '/phpunit/php-token-stream/src/Util.php',
+ 'PHP_Token_VAR' => $vendorDir . '/phpunit/php-token-stream/src/Var.php',
+ 'PHP_Token_VARIABLE' => $vendorDir . '/phpunit/php-token-stream/src/Variable.php',
+ 'PHP_Token_WHILE' => $vendorDir . '/phpunit/php-token-stream/src/While.php',
+ 'PHP_Token_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Whitespace.php',
+ 'PHP_Token_XOR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/XorEqual.php',
+ 'PHP_Token_YIELD' => $vendorDir . '/phpunit/php-token-stream/src/Yield.php',
+ 'PHP_Token_YIELD_FROM' => $vendorDir . '/phpunit/php-token-stream/src/YieldFrom.php',
+ 'PharIo\\Manifest\\Application' => $vendorDir . '/phar-io/manifest/src/values/Application.php',
+ 'PharIo\\Manifest\\ApplicationName' => $vendorDir . '/phar-io/manifest/src/values/ApplicationName.php',
+ 'PharIo\\Manifest\\Author' => $vendorDir . '/phar-io/manifest/src/values/Author.php',
+ 'PharIo\\Manifest\\AuthorCollection' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollection.php',
+ 'PharIo\\Manifest\\AuthorCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollectionIterator.php',
+ 'PharIo\\Manifest\\AuthorElement' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElement.php',
+ 'PharIo\\Manifest\\AuthorElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElementCollection.php',
+ 'PharIo\\Manifest\\BundledComponent' => $vendorDir . '/phar-io/manifest/src/values/BundledComponent.php',
+ 'PharIo\\Manifest\\BundledComponentCollection' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollection.php',
+ 'PharIo\\Manifest\\BundledComponentCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php',
+ 'PharIo\\Manifest\\BundlesElement' => $vendorDir . '/phar-io/manifest/src/xml/BundlesElement.php',
+ 'PharIo\\Manifest\\ComponentElement' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElement.php',
+ 'PharIo\\Manifest\\ComponentElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElementCollection.php',
+ 'PharIo\\Manifest\\ContainsElement' => $vendorDir . '/phar-io/manifest/src/xml/ContainsElement.php',
+ 'PharIo\\Manifest\\CopyrightElement' => $vendorDir . '/phar-io/manifest/src/xml/CopyrightElement.php',
+ 'PharIo\\Manifest\\CopyrightInformation' => $vendorDir . '/phar-io/manifest/src/values/CopyrightInformation.php',
+ 'PharIo\\Manifest\\ElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ElementCollection.php',
+ 'PharIo\\Manifest\\ElementCollectionException' => $vendorDir . '/phar-io/manifest/src/exceptions/ElementCollectionException.php',
+ 'PharIo\\Manifest\\Email' => $vendorDir . '/phar-io/manifest/src/values/Email.php',
+ 'PharIo\\Manifest\\Exception' => $vendorDir . '/phar-io/manifest/src/exceptions/Exception.php',
+ 'PharIo\\Manifest\\ExtElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtElement.php',
+ 'PharIo\\Manifest\\ExtElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ExtElementCollection.php',
+ 'PharIo\\Manifest\\Extension' => $vendorDir . '/phar-io/manifest/src/values/Extension.php',
+ 'PharIo\\Manifest\\ExtensionElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtensionElement.php',
+ 'PharIo\\Manifest\\InvalidApplicationNameException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php',
+ 'PharIo\\Manifest\\InvalidEmailException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidEmailException.php',
+ 'PharIo\\Manifest\\InvalidUrlException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidUrlException.php',
+ 'PharIo\\Manifest\\Library' => $vendorDir . '/phar-io/manifest/src/values/Library.php',
+ 'PharIo\\Manifest\\License' => $vendorDir . '/phar-io/manifest/src/values/License.php',
+ 'PharIo\\Manifest\\LicenseElement' => $vendorDir . '/phar-io/manifest/src/xml/LicenseElement.php',
+ 'PharIo\\Manifest\\Manifest' => $vendorDir . '/phar-io/manifest/src/values/Manifest.php',
+ 'PharIo\\Manifest\\ManifestDocument' => $vendorDir . '/phar-io/manifest/src/xml/ManifestDocument.php',
+ 'PharIo\\Manifest\\ManifestDocumentException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php',
+ 'PharIo\\Manifest\\ManifestDocumentLoadingException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php',
+ 'PharIo\\Manifest\\ManifestDocumentMapper' => $vendorDir . '/phar-io/manifest/src/ManifestDocumentMapper.php',
+ 'PharIo\\Manifest\\ManifestDocumentMapperException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php',
+ 'PharIo\\Manifest\\ManifestElement' => $vendorDir . '/phar-io/manifest/src/xml/ManifestElement.php',
+ 'PharIo\\Manifest\\ManifestElementException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestElementException.php',
+ 'PharIo\\Manifest\\ManifestLoader' => $vendorDir . '/phar-io/manifest/src/ManifestLoader.php',
+ 'PharIo\\Manifest\\ManifestLoaderException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php',
+ 'PharIo\\Manifest\\ManifestSerializer' => $vendorDir . '/phar-io/manifest/src/ManifestSerializer.php',
+ 'PharIo\\Manifest\\PhpElement' => $vendorDir . '/phar-io/manifest/src/xml/PhpElement.php',
+ 'PharIo\\Manifest\\PhpExtensionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpExtensionRequirement.php',
+ 'PharIo\\Manifest\\PhpVersionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpVersionRequirement.php',
+ 'PharIo\\Manifest\\Requirement' => $vendorDir . '/phar-io/manifest/src/values/Requirement.php',
+ 'PharIo\\Manifest\\RequirementCollection' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollection.php',
+ 'PharIo\\Manifest\\RequirementCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollectionIterator.php',
+ 'PharIo\\Manifest\\RequiresElement' => $vendorDir . '/phar-io/manifest/src/xml/RequiresElement.php',
+ 'PharIo\\Manifest\\Type' => $vendorDir . '/phar-io/manifest/src/values/Type.php',
+ 'PharIo\\Manifest\\Url' => $vendorDir . '/phar-io/manifest/src/values/Url.php',
+ 'PharIo\\Version\\AbstractVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AbstractVersionConstraint.php',
+ 'PharIo\\Version\\AndVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php',
+ 'PharIo\\Version\\AnyVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AnyVersionConstraint.php',
+ 'PharIo\\Version\\ExactVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/ExactVersionConstraint.php',
+ 'PharIo\\Version\\Exception' => $vendorDir . '/phar-io/version/src/exceptions/Exception.php',
+ 'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php',
+ 'PharIo\\Version\\InvalidPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php',
+ 'PharIo\\Version\\InvalidVersionException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidVersionException.php',
+ 'PharIo\\Version\\NoPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php',
+ 'PharIo\\Version\\OrVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php',
+ 'PharIo\\Version\\PreReleaseSuffix' => $vendorDir . '/phar-io/version/src/PreReleaseSuffix.php',
+ 'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php',
+ 'PharIo\\Version\\SpecificMajorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php',
+ 'PharIo\\Version\\UnsupportedVersionConstraintException' => $vendorDir . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php',
+ 'PharIo\\Version\\Version' => $vendorDir . '/phar-io/version/src/Version.php',
+ 'PharIo\\Version\\VersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/VersionConstraint.php',
+ 'PharIo\\Version\\VersionConstraintParser' => $vendorDir . '/phar-io/version/src/VersionConstraintParser.php',
+ 'PharIo\\Version\\VersionConstraintValue' => $vendorDir . '/phar-io/version/src/VersionConstraintValue.php',
+ 'PharIo\\Version\\VersionNumber' => $vendorDir . '/phar-io/version/src/VersionNumber.php',
+ 'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php',
+ 'SebastianBergmann\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php',
+ 'SebastianBergmann\\CodeCoverage\\CoveredCodeNotExecutedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/CoveredCodeNotExecutedException.php',
+ 'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Driver.php',
+ 'SebastianBergmann\\CodeCoverage\\Driver\\PCOV' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PCOV.php',
+ 'SebastianBergmann\\CodeCoverage\\Driver\\PHPDBG' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PHPDBG.php',
+ 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Xdebug.php',
+ 'SebastianBergmann\\CodeCoverage\\Exception' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Exception.php',
+ 'SebastianBergmann\\CodeCoverage\\Filter' => $vendorDir . '/phpunit/php-code-coverage/src/Filter.php',
+ 'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php',
+ 'SebastianBergmann\\CodeCoverage\\MissingCoversAnnotationException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/MissingCoversAnnotationException.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => $vendorDir . '/phpunit/php-code-coverage/src/Node/AbstractNode.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\Builder' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Builder.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Directory.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Node/File.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Iterator.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Clover.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Crap4j.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Facade.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\PHP' => $vendorDir . '/phpunit/php-code-coverage/src/Report/PHP.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Text.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/File.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Method.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Node.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Project.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Report.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Source.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php',
+ 'SebastianBergmann\\CodeCoverage\\RuntimeException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/RuntimeException.php',
+ 'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php',
+ 'SebastianBergmann\\CodeCoverage\\Util' => $vendorDir . '/phpunit/php-code-coverage/src/Util.php',
+ 'SebastianBergmann\\CodeCoverage\\Version' => $vendorDir . '/phpunit/php-code-coverage/src/Version.php',
+ 'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => $vendorDir . '/sebastian/code-unit-reverse-lookup/src/Wizard.php',
+ 'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php',
+ 'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php',
+ 'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php',
+ 'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php',
+ 'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php',
+ 'SebastianBergmann\\Comparator\\DoubleComparator' => $vendorDir . '/sebastian/comparator/src/DoubleComparator.php',
+ 'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php',
+ 'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php',
+ 'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php',
+ 'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php',
+ 'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php',
+ 'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php',
+ 'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php',
+ 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php',
+ 'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php',
+ 'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php',
+ 'SebastianBergmann\\Diff\\ConfigurationException' => $vendorDir . '/sebastian/diff/src/Exception/ConfigurationException.php',
+ 'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php',
+ 'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php',
+ 'SebastianBergmann\\Diff\\Exception' => $vendorDir . '/sebastian/diff/src/Exception/Exception.php',
+ 'SebastianBergmann\\Diff\\InvalidArgumentException' => $vendorDir . '/sebastian/diff/src/Exception/InvalidArgumentException.php',
+ 'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php',
+ 'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php',
+ 'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php',
+ 'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php',
+ 'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php',
+ 'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php',
+ 'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php',
+ 'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php',
+ 'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php',
+ 'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php',
+ 'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php',
+ 'SebastianBergmann\\Environment\\OperatingSystem' => $vendorDir . '/sebastian/environment/src/OperatingSystem.php',
+ 'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php',
+ 'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php',
+ 'SebastianBergmann\\FileIterator\\Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php',
+ 'SebastianBergmann\\FileIterator\\Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php',
+ 'SebastianBergmann\\FileIterator\\Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php',
+ 'SebastianBergmann\\GlobalState\\Blacklist' => $vendorDir . '/sebastian/global-state/src/Blacklist.php',
+ 'SebastianBergmann\\GlobalState\\CodeExporter' => $vendorDir . '/sebastian/global-state/src/CodeExporter.php',
+ 'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/exceptions/Exception.php',
+ 'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php',
+ 'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/exceptions/RuntimeException.php',
+ 'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php',
+ 'SebastianBergmann\\ObjectEnumerator\\Enumerator' => $vendorDir . '/sebastian/object-enumerator/src/Enumerator.php',
+ 'SebastianBergmann\\ObjectEnumerator\\Exception' => $vendorDir . '/sebastian/object-enumerator/src/Exception.php',
+ 'SebastianBergmann\\ObjectEnumerator\\InvalidArgumentException' => $vendorDir . '/sebastian/object-enumerator/src/InvalidArgumentException.php',
+ 'SebastianBergmann\\ObjectReflector\\Exception' => $vendorDir . '/sebastian/object-reflector/src/Exception.php',
+ 'SebastianBergmann\\ObjectReflector\\InvalidArgumentException' => $vendorDir . '/sebastian/object-reflector/src/InvalidArgumentException.php',
+ 'SebastianBergmann\\ObjectReflector\\ObjectReflector' => $vendorDir . '/sebastian/object-reflector/src/ObjectReflector.php',
+ 'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php',
+ 'SebastianBergmann\\RecursionContext\\Exception' => $vendorDir . '/sebastian/recursion-context/src/Exception.php',
+ 'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => $vendorDir . '/sebastian/recursion-context/src/InvalidArgumentException.php',
+ 'SebastianBergmann\\ResourceOperations\\ResourceOperations' => $vendorDir . '/sebastian/resource-operations/src/ResourceOperations.php',
+ 'SebastianBergmann\\Timer\\Exception' => $vendorDir . '/phpunit/php-timer/src/Exception.php',
+ 'SebastianBergmann\\Timer\\RuntimeException' => $vendorDir . '/phpunit/php-timer/src/RuntimeException.php',
+ 'SebastianBergmann\\Timer\\Timer' => $vendorDir . '/phpunit/php-timer/src/Timer.php',
+ 'SebastianBergmann\\Type\\CallableType' => $vendorDir . '/sebastian/type/src/CallableType.php',
+ 'SebastianBergmann\\Type\\Exception' => $vendorDir . '/sebastian/type/src/exception/Exception.php',
+ 'SebastianBergmann\\Type\\GenericObjectType' => $vendorDir . '/sebastian/type/src/GenericObjectType.php',
+ 'SebastianBergmann\\Type\\IterableType' => $vendorDir . '/sebastian/type/src/IterableType.php',
+ 'SebastianBergmann\\Type\\NullType' => $vendorDir . '/sebastian/type/src/NullType.php',
+ 'SebastianBergmann\\Type\\ObjectType' => $vendorDir . '/sebastian/type/src/ObjectType.php',
+ 'SebastianBergmann\\Type\\RuntimeException' => $vendorDir . '/sebastian/type/src/exception/RuntimeException.php',
+ 'SebastianBergmann\\Type\\SimpleType' => $vendorDir . '/sebastian/type/src/SimpleType.php',
+ 'SebastianBergmann\\Type\\Type' => $vendorDir . '/sebastian/type/src/Type.php',
+ 'SebastianBergmann\\Type\\TypeName' => $vendorDir . '/sebastian/type/src/TypeName.php',
+ 'SebastianBergmann\\Type\\UnknownType' => $vendorDir . '/sebastian/type/src/UnknownType.php',
+ 'SebastianBergmann\\Type\\VoidType' => $vendorDir . '/sebastian/type/src/VoidType.php',
+ 'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php',
'SqlFormatter' => $vendorDir . '/jdorn/sql-formatter/lib/SqlFormatter.php',
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
+ 'Text_Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php',
+ 'TheSeer\\Tokenizer\\Exception' => $vendorDir . '/theseer/tokenizer/src/Exception.php',
+ 'TheSeer\\Tokenizer\\NamespaceUri' => $vendorDir . '/theseer/tokenizer/src/NamespaceUri.php',
+ 'TheSeer\\Tokenizer\\NamespaceUriException' => $vendorDir . '/theseer/tokenizer/src/NamespaceUriException.php',
+ 'TheSeer\\Tokenizer\\Token' => $vendorDir . '/theseer/tokenizer/src/Token.php',
+ 'TheSeer\\Tokenizer\\TokenCollection' => $vendorDir . '/theseer/tokenizer/src/TokenCollection.php',
+ 'TheSeer\\Tokenizer\\TokenCollectionException' => $vendorDir . '/theseer/tokenizer/src/TokenCollectionException.php',
+ 'TheSeer\\Tokenizer\\Tokenizer' => $vendorDir . '/theseer/tokenizer/src/Tokenizer.php',
+ 'TheSeer\\Tokenizer\\XMLSerializer' => $vendorDir . '/theseer/tokenizer/src/XMLSerializer.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
);
diff --git a/app/vendor/composer/autoload_files.php b/app/vendor/composer/autoload_files.php
index 806a8b15d..00304d13e 100644
--- a/app/vendor/composer/autoload_files.php
+++ b/app/vendor/composer/autoload_files.php
@@ -6,12 +6,11 @@
$baseDir = dirname($vendorDir);
return array(
+ '9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
- '34122c0574b76bf21c9a8db62b5b9cf3' => $vendorDir . '/cakephp/chronos/src/carbon_compat.php',
- 'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
- '7e9bd612cc444b3eed788ebbe46263a0' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/autoload.php',
+ '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'07d7f1a47144818725fd8d91a907ac57' => $vendorDir . '/laminas/laminas-diactoros/src/functions/create_uploaded_file.php',
'da94ac5d3ca7d2dbab84ce561ce72bfd' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.php',
'3d97c8dcdfba8cb85d3b34f116bb248b' => $vendorDir . '/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.php',
@@ -28,12 +27,19 @@
'cc8e14526dc240491e17a838cb78508c' => $vendorDir . '/laminas/laminas-diactoros/src/functions/normalize_server.legacy.php',
'786bf90caabc9e09b6ad4cc5ca8f0e30' => $vendorDir . '/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.legacy.php',
'751a5a3f463e4be759be31748b61737c' => $vendorDir . '/laminas/laminas-diactoros/src/functions/parse_cookie_header.legacy.php',
+ '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
+ '34122c0574b76bf21c9a8db62b5b9cf3' => $vendorDir . '/cakephp/chronos/src/carbon_compat.php',
+ '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
+ 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
+ '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
+ '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
+ 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
+ '7e9bd612cc444b3eed788ebbe46263a0' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/autoload.php',
'c720f792236cd163ece8049879166850' => $vendorDir . '/cakephp/cakephp/src/Core/functions.php',
'ede59e3a405fb689cd1cebb7bb1db3fb' => $vendorDir . '/cakephp/cakephp/src/Collection/functions.php',
'90236b492da7ca2983a2ad6e33e4152e' => $vendorDir . '/cakephp/cakephp/src/I18n/functions.php',
'b1fc73705e1bec51cd2b20a32cf1c60a' => $vendorDir . '/cakephp/cakephp/src/Utility/bootstrap.php',
- '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
- '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
+ '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'bf9f5270ae66ac6fa0290b4bf47867b7' => $vendorDir . '/adodb/adodb-php/adodb.inc.php',
'801c31d8ed748cfa537fa45402288c95' => $vendorDir . '/psy/psysh/src/functions.php',
);
diff --git a/app/vendor/composer/autoload_namespaces.php b/app/vendor/composer/autoload_namespaces.php
index 0aa0e8ef9..7be99901a 100644
--- a/app/vendor/composer/autoload_namespaces.php
+++ b/app/vendor/composer/autoload_namespaces.php
@@ -7,8 +7,5 @@
return array(
'josegonzalez\\Dotenv' => array($vendorDir . '/josegonzalez/dotenv/src', $vendorDir . '/josegonzalez/dotenv/tests'),
- 'Umpirsky\\' => array($vendorDir . '/umpirsky/twig-php-function/src'),
- 'Twig_' => array($vendorDir . '/twig/twig/lib'),
'Detection' => array($vendorDir . '/mobiledetect/mobiledetectlib/namespaced'),
- 'Aptoma' => array($vendorDir . '/aptoma/twig-markdown/src'),
);
diff --git a/app/vendor/composer/autoload_psr4.php b/app/vendor/composer/autoload_psr4.php
index f70ae87fb..872052d2e 100644
--- a/app/vendor/composer/autoload_psr4.php
+++ b/app/vendor/composer/autoload_psr4.php
@@ -6,47 +6,58 @@
$baseDir = dirname($vendorDir);
return array(
- 'WyriHaximus\\TwigView\\' => array($vendorDir . '/wyrihaximus/twig-view/src'),
+ 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
+ 'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
+ 'Twig\\Extra\\Markdown\\' => array($vendorDir . '/twig/markdown-extra'),
'Twig\\' => array($vendorDir . '/twig/twig/src'),
+ 'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
- 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
+ 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
+ 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
+ 'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
- 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
+ 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
+ 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
- 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
'Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'),
'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
- 'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
'Psy\\' => array($vendorDir . '/psy/psysh/src'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
- 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
+ 'Psr\\Http\\Server\\' => array($vendorDir . '/psr/http-server-handler/src', $vendorDir . '/psr/http-server-middleware/src'),
+ 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
+ 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
+ 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
+ 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'Phinx\\' => array($vendorDir . '/robmorgan/phinx/src/Phinx'),
'Migrations\\' => array($vendorDir . '/cakephp/migrations/src'),
'M1\\Env\\' => array($vendorDir . '/m1/env/src'),
'Laminas\\ZendFrameworkBridge\\' => array($vendorDir . '/laminas/laminas-zendframework-bridge/src'),
+ 'Laminas\\HttpHandlerRunner\\' => array($vendorDir . '/laminas/laminas-httphandlerrunner/src'),
'Laminas\\Diactoros\\' => array($vendorDir . '/laminas/laminas-diactoros/src'),
'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
'Jasny\\Twig\\' => array($vendorDir . '/jasny/twig-extensions/src'),
+ 'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/lib/Doctrine/Deprecations'),
'Doctrine\\DBAL\\' => array($vendorDir . '/doctrine/dbal/lib/Doctrine/DBAL'),
'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'),
'Doctrine\\Common\\' => array($vendorDir . '/doctrine/event-manager/lib/Doctrine/Common'),
+ 'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
'DebugKit\\Test\\Fixture\\' => array($vendorDir . '/cakephp/debug_kit/tests/Fixture'),
'DebugKit\\' => array($vendorDir . '/cakephp/debug_kit/src'),
'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
- 'Composer\\MetadataMinifier\\' => array($vendorDir . '/composer/metadata-minifier/src'),
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
'Composer\\' => array($vendorDir . '/composer/composer/src/Composer'),
+ 'Cake\\TwigView\\' => array($vendorDir . '/cakephp/twig-view/src'),
'Cake\\Test\\' => array($vendorDir . '/cakephp/cakephp/tests'),
'Cake\\Composer\\' => array($vendorDir . '/cakephp/plugin-installer/src'),
'Cake\\Chronos\\' => array($vendorDir . '/cakephp/chronos/src'),
@@ -56,6 +67,4 @@
'Aura\\Intl\\' => array($vendorDir . '/aura/intl/src'),
'App\\Test\\' => array($baseDir . '/tests'),
'App\\' => array($baseDir . '/src'),
- 'Ajgl\\Twig\\Extension\\' => array($vendorDir . '/ajgl/breakpoint-twig-extension/src'),
- '' => array($vendorDir . '/asm89/twig-cache-extension/lib'),
);
diff --git a/app/vendor/composer/autoload_real.php b/app/vendor/composer/autoload_real.php
index 54c6e7c9e..100bd8001 100644
--- a/app/vendor/composer/autoload_real.php
+++ b/app/vendor/composer/autoload_real.php
@@ -22,6 +22,8 @@ public static function getLoader()
return self::$loader;
}
+ require __DIR__ . '/platform_check.php';
+
spl_autoload_register(array('ComposerAutoloaderInit8d81387c26c532d7a48feda4036c56c7', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit8d81387c26c532d7a48feda4036c56c7', 'loadClassLoader'));
diff --git a/app/vendor/composer/autoload_static.php b/app/vendor/composer/autoload_static.php
index a30258452..91761359d 100644
--- a/app/vendor/composer/autoload_static.php
+++ b/app/vendor/composer/autoload_static.php
@@ -7,12 +7,11 @@
class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
{
public static $files = array (
+ '9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
- '34122c0574b76bf21c9a8db62b5b9cf3' => __DIR__ . '/..' . '/cakephp/chronos/src/carbon_compat.php',
- 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
- '7e9bd612cc444b3eed788ebbe46263a0' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/autoload.php',
+ '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'07d7f1a47144818725fd8d91a907ac57' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/functions/create_uploaded_file.php',
'da94ac5d3ca7d2dbab84ce561ce72bfd' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.php',
'3d97c8dcdfba8cb85d3b34f116bb248b' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.php',
@@ -29,52 +28,67 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
'cc8e14526dc240491e17a838cb78508c' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/functions/normalize_server.legacy.php',
'786bf90caabc9e09b6ad4cc5ca8f0e30' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.legacy.php',
'751a5a3f463e4be759be31748b61737c' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/functions/parse_cookie_header.legacy.php',
+ '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
+ '34122c0574b76bf21c9a8db62b5b9cf3' => __DIR__ . '/..' . '/cakephp/chronos/src/carbon_compat.php',
+ '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
+ 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
+ '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
+ '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
+ 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
+ '7e9bd612cc444b3eed788ebbe46263a0' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/autoload.php',
'c720f792236cd163ece8049879166850' => __DIR__ . '/..' . '/cakephp/cakephp/src/Core/functions.php',
'ede59e3a405fb689cd1cebb7bb1db3fb' => __DIR__ . '/..' . '/cakephp/cakephp/src/Collection/functions.php',
'90236b492da7ca2983a2ad6e33e4152e' => __DIR__ . '/..' . '/cakephp/cakephp/src/I18n/functions.php',
'b1fc73705e1bec51cd2b20a32cf1c60a' => __DIR__ . '/..' . '/cakephp/cakephp/src/Utility/bootstrap.php',
- '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
- '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
+ '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'bf9f5270ae66ac6fa0290b4bf47867b7' => __DIR__ . '/..' . '/adodb/adodb-php/adodb.inc.php',
'801c31d8ed748cfa537fa45402288c95' => __DIR__ . '/..' . '/psy/psysh/src/functions.php',
);
public static $prefixLengthsPsr4 = array (
+ 'p' =>
+ array (
+ 'phpDocumentor\\Reflection\\' => 25,
+ ),
'W' =>
array (
- 'WyriHaximus\\TwigView\\' => 21,
+ 'Webmozart\\Assert\\' => 17,
),
'T' =>
array (
+ 'Twig\\Extra\\Markdown\\' => 20,
'Twig\\' => 5,
),
'S' =>
array (
+ 'Symfony\\Polyfill\\Php81\\' => 23,
'Symfony\\Polyfill\\Php80\\' => 23,
- 'Symfony\\Polyfill\\Php72\\' => 23,
+ 'Symfony\\Polyfill\\Php73\\' => 23,
'Symfony\\Polyfill\\Mbstring\\' => 26,
+ 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
+ 'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31,
'Symfony\\Polyfill\\Ctype\\' => 23,
- 'Symfony\\Component\\Yaml\\' => 23,
+ 'Symfony\\Contracts\\Service\\' => 26,
'Symfony\\Component\\VarDumper\\' => 28,
+ 'Symfony\\Component\\String\\' => 25,
'Symfony\\Component\\Process\\' => 26,
'Symfony\\Component\\Finder\\' => 25,
'Symfony\\Component\\Filesystem\\' => 29,
- 'Symfony\\Component\\Debug\\' => 24,
'Symfony\\Component\\Console\\' => 26,
'Symfony\\Component\\Config\\' => 25,
'Seld\\PharUtils\\' => 15,
'Seld\\JsonLint\\' => 14,
),
- 'R' =>
- array (
- 'React\\Promise\\' => 14,
- ),
'P' =>
array (
'Psy\\' => 4,
'Psr\\SimpleCache\\' => 16,
'Psr\\Log\\' => 8,
+ 'Psr\\Http\\Server\\' => 16,
'Psr\\Http\\Message\\' => 17,
+ 'Psr\\Http\\Client\\' => 16,
+ 'Psr\\Container\\' => 14,
+ 'Prophecy\\' => 9,
'PhpParser\\' => 10,
'Phinx\\' => 6,
),
@@ -86,6 +100,7 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
'L' =>
array (
'Laminas\\ZendFrameworkBridge\\' => 28,
+ 'Laminas\\HttpHandlerRunner\\' => 26,
'Laminas\\Diactoros\\' => 18,
),
'J' =>
@@ -95,10 +110,12 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
),
'D' =>
array (
+ 'Doctrine\\Instantiator\\' => 22,
'Doctrine\\Deprecations\\' => 22,
'Doctrine\\DBAL\\' => 14,
'Doctrine\\Common\\Cache\\' => 22,
'Doctrine\\Common\\' => 16,
+ 'DeepCopy\\' => 9,
'DebugKit\\Test\\Fixture\\' => 22,
'DebugKit\\' => 9,
),
@@ -107,9 +124,9 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
'Composer\\XdebugHandler\\' => 23,
'Composer\\Spdx\\' => 14,
'Composer\\Semver\\' => 16,
- 'Composer\\MetadataMinifier\\' => 26,
'Composer\\CaBundle\\' => 18,
'Composer\\' => 9,
+ 'Cake\\TwigView\\' => 14,
'Cake\\Test\\' => 10,
'Cake\\Composer\\' => 14,
'Cake\\Chronos\\' => 13,
@@ -125,43 +142,68 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
'Aura\\Intl\\' => 10,
'App\\Test\\' => 9,
'App\\' => 4,
- 'Ajgl\\Twig\\Extension\\' => 20,
),
);
public static $prefixDirsPsr4 = array (
- 'WyriHaximus\\TwigView\\' =>
+ 'phpDocumentor\\Reflection\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src',
+ 1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src',
+ 2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src',
+ ),
+ 'Webmozart\\Assert\\' =>
array (
- 0 => __DIR__ . '/..' . '/wyrihaximus/twig-view/src',
+ 0 => __DIR__ . '/..' . '/webmozart/assert/src',
+ ),
+ 'Twig\\Extra\\Markdown\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/twig/markdown-extra',
),
'Twig\\' =>
array (
0 => __DIR__ . '/..' . '/twig/twig/src',
),
+ 'Symfony\\Polyfill\\Php81\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-php81',
+ ),
'Symfony\\Polyfill\\Php80\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
),
- 'Symfony\\Polyfill\\Php72\\' =>
+ 'Symfony\\Polyfill\\Php73\\' =>
array (
- 0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-php73',
),
'Symfony\\Polyfill\\Mbstring\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
),
+ 'Symfony\\Polyfill\\Intl\\Normalizer\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer',
+ ),
+ 'Symfony\\Polyfill\\Intl\\Grapheme\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme',
+ ),
'Symfony\\Polyfill\\Ctype\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
),
- 'Symfony\\Component\\Yaml\\' =>
+ 'Symfony\\Contracts\\Service\\' =>
array (
- 0 => __DIR__ . '/..' . '/symfony/yaml',
+ 0 => __DIR__ . '/..' . '/symfony/service-contracts',
),
'Symfony\\Component\\VarDumper\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/var-dumper',
),
+ 'Symfony\\Component\\String\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/string',
+ ),
'Symfony\\Component\\Process\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/process',
@@ -174,10 +216,6 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/..' . '/symfony/filesystem',
),
- 'Symfony\\Component\\Debug\\' =>
- array (
- 0 => __DIR__ . '/..' . '/symfony/debug',
- ),
'Symfony\\Component\\Console\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/console',
@@ -194,10 +232,6 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
),
- 'React\\Promise\\' =>
- array (
- 0 => __DIR__ . '/..' . '/react/promise/src',
- ),
'Psy\\' =>
array (
0 => __DIR__ . '/..' . '/psy/psysh/src',
@@ -210,9 +244,27 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
),
+ 'Psr\\Http\\Server\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/http-server-handler/src',
+ 1 => __DIR__ . '/..' . '/psr/http-server-middleware/src',
+ ),
'Psr\\Http\\Message\\' =>
array (
- 0 => __DIR__ . '/..' . '/psr/http-message/src',
+ 0 => __DIR__ . '/..' . '/psr/http-factory/src',
+ 1 => __DIR__ . '/..' . '/psr/http-message/src',
+ ),
+ 'Psr\\Http\\Client\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/http-client/src',
+ ),
+ 'Psr\\Container\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/container/src',
+ ),
+ 'Prophecy\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/phpspec/prophecy/src/Prophecy',
),
'PhpParser\\' =>
array (
@@ -234,6 +286,10 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src',
),
+ 'Laminas\\HttpHandlerRunner\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/laminas/laminas-httphandlerrunner/src',
+ ),
'Laminas\\Diactoros\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-diactoros/src',
@@ -246,6 +302,10 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/..' . '/jasny/twig-extensions/src',
),
+ 'Doctrine\\Instantiator\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator',
+ ),
'Doctrine\\Deprecations\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/deprecations/lib/Doctrine/Deprecations',
@@ -262,6 +322,10 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/..' . '/doctrine/event-manager/lib/Doctrine/Common',
),
+ 'DeepCopy\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy',
+ ),
'DebugKit\\Test\\Fixture\\' =>
array (
0 => __DIR__ . '/..' . '/cakephp/debug_kit/tests/Fixture',
@@ -282,10 +346,6 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/..' . '/composer/semver/src',
),
- 'Composer\\MetadataMinifier\\' =>
- array (
- 0 => __DIR__ . '/..' . '/composer/metadata-minifier/src',
- ),
'Composer\\CaBundle\\' =>
array (
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
@@ -294,6 +354,10 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/..' . '/composer/composer/src/Composer',
),
+ 'Cake\\TwigView\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/cakephp/twig-view/src',
+ ),
'Cake\\Test\\' =>
array (
0 => __DIR__ . '/..' . '/cakephp/cakephp/tests',
@@ -330,14 +394,6 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
array (
0 => __DIR__ . '/../..' . '/src',
),
- 'Ajgl\\Twig\\Extension\\' =>
- array (
- 0 => __DIR__ . '/..' . '/ajgl/breakpoint-twig-extension/src',
- ),
- );
-
- public static $fallbackDirsPsr4 = array (
- 0 => __DIR__ . '/..' . '/asm89/twig-cache-extension/lib',
);
public static $prefixesPsr0 = array (
@@ -349,20 +405,6 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
1 => __DIR__ . '/..' . '/josegonzalez/dotenv/tests',
),
),
- 'U' =>
- array (
- 'Umpirsky\\' =>
- array (
- 0 => __DIR__ . '/..' . '/umpirsky/twig-php-function/src',
- ),
- ),
- 'T' =>
- array (
- 'Twig_' =>
- array (
- 0 => __DIR__ . '/..' . '/twig/twig/lib',
- ),
- ),
'D' =>
array (
'Detection' =>
@@ -370,21 +412,601 @@ class ComposerStaticInit8d81387c26c532d7a48feda4036c56c7
0 => __DIR__ . '/..' . '/mobiledetect/mobiledetectlib/namespaced',
),
),
- 'A' =>
- array (
- 'Aptoma' =>
- array (
- 0 => __DIR__ . '/..' . '/aptoma/twig-markdown/src',
- ),
- ),
);
public static $classMap = array (
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+ 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
'Mobile_Detect' => __DIR__ . '/..' . '/mobiledetect/mobiledetectlib/Mobile_Detect.php',
+ 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
+ 'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php',
+ 'PHPUnit\\Framework\\Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert.php',
+ 'PHPUnit\\Framework\\AssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php',
+ 'PHPUnit\\Framework\\CodeCoverageException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php',
+ 'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ArrayHasKey.php',
+ 'PHPUnit\\Framework\\Constraint\\ArraySubset' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ArraySubset.php',
+ 'PHPUnit\\Framework\\Constraint\\Attribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Attribute.php',
+ 'PHPUnit\\Framework\\Constraint\\Callback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Callback.php',
+ 'PHPUnit\\Framework\\Constraint\\ClassHasAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ClassHasAttribute.php',
+ 'PHPUnit\\Framework\\Constraint\\ClassHasStaticAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ClassHasStaticAttribute.php',
+ 'PHPUnit\\Framework\\Constraint\\Composite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Composite.php',
+ 'PHPUnit\\Framework\\Constraint\\Constraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php',
+ 'PHPUnit\\Framework\\Constraint\\Count' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Count.php',
+ 'PHPUnit\\Framework\\Constraint\\DirectoryExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/DirectoryExists.php',
+ 'PHPUnit\\Framework\\Constraint\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception.php',
+ 'PHPUnit\\Framework\\Constraint\\ExceptionCode' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ExceptionCode.php',
+ 'PHPUnit\\Framework\\Constraint\\ExceptionMessage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessage.php',
+ 'PHPUnit\\Framework\\Constraint\\ExceptionMessageRegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessageRegularExpression.php',
+ 'PHPUnit\\Framework\\Constraint\\FileExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/FileExists.php',
+ 'PHPUnit\\Framework\\Constraint\\GreaterThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/GreaterThan.php',
+ 'PHPUnit\\Framework\\Constraint\\IsAnything' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php',
+ 'PHPUnit\\Framework\\Constraint\\IsEmpty' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsEmpty.php',
+ 'PHPUnit\\Framework\\Constraint\\IsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsEqual.php',
+ 'PHPUnit\\Framework\\Constraint\\IsFalse' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsFalse.php',
+ 'PHPUnit\\Framework\\Constraint\\IsFinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsFinite.php',
+ 'PHPUnit\\Framework\\Constraint\\IsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php',
+ 'PHPUnit\\Framework\\Constraint\\IsInfinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsInfinite.php',
+ 'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsInstanceOf.php',
+ 'PHPUnit\\Framework\\Constraint\\IsJson' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsJson.php',
+ 'PHPUnit\\Framework\\Constraint\\IsNan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsNan.php',
+ 'PHPUnit\\Framework\\Constraint\\IsNull' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsNull.php',
+ 'PHPUnit\\Framework\\Constraint\\IsReadable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsReadable.php',
+ 'PHPUnit\\Framework\\Constraint\\IsTrue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsTrue.php',
+ 'PHPUnit\\Framework\\Constraint\\IsType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsType.php',
+ 'PHPUnit\\Framework\\Constraint\\IsWritable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsWritable.php',
+ 'PHPUnit\\Framework\\Constraint\\JsonMatches' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php',
+ 'PHPUnit\\Framework\\Constraint\\JsonMatchesErrorMessageProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php',
+ 'PHPUnit\\Framework\\Constraint\\LessThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/LessThan.php',
+ 'PHPUnit\\Framework\\Constraint\\LogicalAnd' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/LogicalAnd.php',
+ 'PHPUnit\\Framework\\Constraint\\LogicalNot' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/LogicalNot.php',
+ 'PHPUnit\\Framework\\Constraint\\LogicalOr' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/LogicalOr.php',
+ 'PHPUnit\\Framework\\Constraint\\LogicalXor' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/LogicalXor.php',
+ 'PHPUnit\\Framework\\Constraint\\ObjectHasAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ObjectHasAttribute.php',
+ 'PHPUnit\\Framework\\Constraint\\RegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/RegularExpression.php',
+ 'PHPUnit\\Framework\\Constraint\\SameSize' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/SameSize.php',
+ 'PHPUnit\\Framework\\Constraint\\StringContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/StringContains.php',
+ 'PHPUnit\\Framework\\Constraint\\StringEndsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/StringEndsWith.php',
+ 'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/StringMatchesFormatDescription.php',
+ 'PHPUnit\\Framework\\Constraint\\StringStartsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/StringStartsWith.php',
+ 'PHPUnit\\Framework\\Constraint\\TraversableContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/TraversableContains.php',
+ 'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsEqual.php',
+ 'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsIdentical.php',
+ 'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsOnly.php',
+ 'PHPUnit\\Framework\\CoveredCodeNotExecutedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php',
+ 'PHPUnit\\Framework\\DataProviderTestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php',
+ 'PHPUnit\\Framework\\Error\\Deprecated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Deprecated.php',
+ 'PHPUnit\\Framework\\Error\\Error' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Error.php',
+ 'PHPUnit\\Framework\\Error\\Notice' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Notice.php',
+ 'PHPUnit\\Framework\\Error\\Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Warning.php',
+ 'PHPUnit\\Framework\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Exception.php',
+ 'PHPUnit\\Framework\\ExceptionWrapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php',
+ 'PHPUnit\\Framework\\ExpectationFailedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php',
+ 'PHPUnit\\Framework\\IncompleteTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTest.php',
+ 'PHPUnit\\Framework\\IncompleteTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php',
+ 'PHPUnit\\Framework\\IncompleteTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php',
+ 'PHPUnit\\Framework\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php',
+ 'PHPUnit\\Framework\\InvalidCoversTargetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php',
+ 'PHPUnit\\Framework\\InvalidDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php',
+ 'PHPUnit\\Framework\\InvalidParameterGroupException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php',
+ 'PHPUnit\\Framework\\MissingCoversAnnotationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php',
+ 'PHPUnit\\Framework\\MockObject\\Api' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/Api.php',
+ 'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\Match_' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/Match_.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php',
+ 'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php',
+ 'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php',
+ 'PHPUnit\\Framework\\MockObject\\ConfigurableMethodsAlreadyInitializedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php',
+ 'PHPUnit\\Framework\\MockObject\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php',
+ 'PHPUnit\\Framework\\MockObject\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator.php',
+ 'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php',
+ 'PHPUnit\\Framework\\MockObject\\Invocation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Invocation.php',
+ 'PHPUnit\\Framework\\MockObject\\InvocationHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php',
+ 'PHPUnit\\Framework\\MockObject\\Matcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Matcher.php',
+ 'PHPUnit\\Framework\\MockObject\\Method' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/Method.php',
+ 'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php',
+ 'PHPUnit\\Framework\\MockObject\\MockBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php',
+ 'PHPUnit\\Framework\\MockObject\\MockClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockClass.php',
+ 'PHPUnit\\Framework\\MockObject\\MockMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockMethod.php',
+ 'PHPUnit\\Framework\\MockObject\\MockMethodSet' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php',
+ 'PHPUnit\\Framework\\MockObject\\MockObject' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockObject.php',
+ 'PHPUnit\\Framework\\MockObject\\MockTrait' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockTrait.php',
+ 'PHPUnit\\Framework\\MockObject\\MockType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockType.php',
+ 'PHPUnit\\Framework\\MockObject\\MockedCloneMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/MockedCloneMethod.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\ConsecutiveParameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtIndex' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php',
+ 'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php',
+ 'PHPUnit\\Framework\\MockObject\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php',
+ 'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php',
+ 'PHPUnit\\Framework\\MockObject\\UnmockedCloneMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/UnmockedCloneMethod.php',
+ 'PHPUnit\\Framework\\MockObject\\Verifiable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Verifiable.php',
+ 'PHPUnit\\Framework\\NoChildTestSuiteException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php',
+ 'PHPUnit\\Framework\\OutputError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/OutputError.php',
+ 'PHPUnit\\Framework\\PHPTAssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php',
+ 'PHPUnit\\Framework\\RiskyTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php',
+ 'PHPUnit\\Framework\\SelfDescribing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
+ 'PHPUnit\\Framework\\SkippedTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTest.php',
+ 'PHPUnit\\Framework\\SkippedTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTestCase.php',
+ 'PHPUnit\\Framework\\SkippedTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php',
+ 'PHPUnit\\Framework\\SkippedTestSuiteError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php',
+ 'PHPUnit\\Framework\\SyntheticError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SyntheticError.php',
+ 'PHPUnit\\Framework\\SyntheticSkippedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php',
+ 'PHPUnit\\Framework\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Test.php',
+ 'PHPUnit\\Framework\\TestBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestBuilder.php',
+ 'PHPUnit\\Framework\\TestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestCase.php',
+ 'PHPUnit\\Framework\\TestFailure' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestFailure.php',
+ 'PHPUnit\\Framework\\TestListener' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestListener.php',
+ 'PHPUnit\\Framework\\TestListenerDefaultImplementation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php',
+ 'PHPUnit\\Framework\\TestResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestResult.php',
+ 'PHPUnit\\Framework\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuite.php',
+ 'PHPUnit\\Framework\\TestSuiteIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php',
+ 'PHPUnit\\Framework\\UnintentionallyCoveredCodeError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php',
+ 'PHPUnit\\Framework\\Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Warning.php',
+ 'PHPUnit\\Framework\\WarningTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/WarningTestCase.php',
+ 'PHPUnit\\Runner\\AfterIncompleteTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php',
+ 'PHPUnit\\Runner\\AfterLastTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php',
+ 'PHPUnit\\Runner\\AfterRiskyTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php',
+ 'PHPUnit\\Runner\\AfterSkippedTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php',
+ 'PHPUnit\\Runner\\AfterSuccessfulTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php',
+ 'PHPUnit\\Runner\\AfterTestErrorHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php',
+ 'PHPUnit\\Runner\\AfterTestFailureHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php',
+ 'PHPUnit\\Runner\\AfterTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php',
+ 'PHPUnit\\Runner\\AfterTestWarningHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php',
+ 'PHPUnit\\Runner\\BaseTestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/BaseTestRunner.php',
+ 'PHPUnit\\Runner\\BeforeFirstTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php',
+ 'PHPUnit\\Runner\\BeforeTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php',
+ 'PHPUnit\\Runner\\DefaultTestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/DefaultTestResultCache.php',
+ 'PHPUnit\\Runner\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception.php',
+ 'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php',
+ 'PHPUnit\\Runner\\Filter\\Factory' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Factory.php',
+ 'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php',
+ 'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php',
+ 'PHPUnit\\Runner\\Filter\\NameFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php',
+ 'PHPUnit\\Runner\\Hook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/Hook.php',
+ 'PHPUnit\\Runner\\NullTestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/NullTestResultCache.php',
+ 'PHPUnit\\Runner\\PhptTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/PhptTestCase.php',
+ 'PHPUnit\\Runner\\ResultCacheExtension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCacheExtension.php',
+ 'PHPUnit\\Runner\\StandardTestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php',
+ 'PHPUnit\\Runner\\TestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/TestHook.php',
+ 'PHPUnit\\Runner\\TestListenerAdapter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php',
+ 'PHPUnit\\Runner\\TestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResultCache.php',
+ 'PHPUnit\\Runner\\TestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php',
+ 'PHPUnit\\Runner\\TestSuiteSorter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php',
+ 'PHPUnit\\Runner\\Version' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Version.php',
+ 'PHPUnit\\TextUI\\Command' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command.php',
+ 'PHPUnit\\TextUI\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception.php',
+ 'PHPUnit\\TextUI\\Help' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Help.php',
+ 'PHPUnit\\TextUI\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/ResultPrinter.php',
+ 'PHPUnit\\TextUI\\TestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestRunner.php',
+ 'PHPUnit\\Util\\Annotation\\DocBlock' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Annotation/DocBlock.php',
+ 'PHPUnit\\Util\\Annotation\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Annotation/Registry.php',
+ 'PHPUnit\\Util\\Blacklist' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Blacklist.php',
+ 'PHPUnit\\Util\\Color' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Color.php',
+ 'PHPUnit\\Util\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Configuration.php',
+ 'PHPUnit\\Util\\ConfigurationGenerator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ConfigurationGenerator.php',
+ 'PHPUnit\\Util\\ErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ErrorHandler.php',
+ 'PHPUnit\\Util\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception.php',
+ 'PHPUnit\\Util\\FileLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/FileLoader.php',
+ 'PHPUnit\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filesystem.php',
+ 'PHPUnit\\Util\\Filter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filter.php',
+ 'PHPUnit\\Util\\Getopt' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Getopt.php',
+ 'PHPUnit\\Util\\GlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/GlobalState.php',
+ 'PHPUnit\\Util\\InvalidDataSetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/InvalidDataSetException.php',
+ 'PHPUnit\\Util\\Json' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Json.php',
+ 'PHPUnit\\Util\\Log\\JUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/JUnit.php',
+ 'PHPUnit\\Util\\Log\\TeamCity' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/TeamCity.php',
+ 'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php',
+ 'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php',
+ 'PHPUnit\\Util\\PHP\\WindowsPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php',
+ 'PHPUnit\\Util\\Printer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Printer.php',
+ 'PHPUnit\\Util\\RegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/RegularExpression.php',
+ 'PHPUnit\\Util\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Test.php',
+ 'PHPUnit\\Util\\TestDox\\CliTestDoxPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\HtmlResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\NamePrettifier' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php',
+ 'PHPUnit\\Util\\TestDox\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\TestDoxPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\TextResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php',
+ 'PHPUnit\\Util\\TestDox\\XmlResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php',
+ 'PHPUnit\\Util\\TextTestListRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TextTestListRenderer.php',
+ 'PHPUnit\\Util\\Type' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Type.php',
+ 'PHPUnit\\Util\\VersionComparisonOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php',
+ 'PHPUnit\\Util\\XdebugFilterScriptGenerator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php',
+ 'PHPUnit\\Util\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml.php',
+ 'PHPUnit\\Util\\XmlTestListRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/XmlTestListRenderer.php',
+ 'PHP_Token' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
+ 'PHP_TokenWithScope' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/TokenWithScope.php',
+ 'PHP_TokenWithScopeAndVisibility' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/TokenWithScopeAndVisibility.php',
+ 'PHP_Token_ABSTRACT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Abstract.php',
+ 'PHP_Token_AMPERSAND' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Ampersand.php',
+ 'PHP_Token_AND_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/AndEqual.php',
+ 'PHP_Token_ARRAY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Array.php',
+ 'PHP_Token_ARRAY_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ArrayCast.php',
+ 'PHP_Token_AS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/As.php',
+ 'PHP_Token_AT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/At.php',
+ 'PHP_Token_BACKTICK' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Backtick.php',
+ 'PHP_Token_BAD_CHARACTER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/BadCharacter.php',
+ 'PHP_Token_BOOLEAN_AND' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/BooleanAnd.php',
+ 'PHP_Token_BOOLEAN_OR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/BooleanOr.php',
+ 'PHP_Token_BOOL_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/BoolCast.php',
+ 'PHP_Token_BREAK' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/break.php',
+ 'PHP_Token_CALLABLE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Callable.php',
+ 'PHP_Token_CARET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Caret.php',
+ 'PHP_Token_CASE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Case.php',
+ 'PHP_Token_CATCH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Catch.php',
+ 'PHP_Token_CHARACTER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Character.php',
+ 'PHP_Token_CLASS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Class.php',
+ 'PHP_Token_CLASS_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ClassC.php',
+ 'PHP_Token_CLASS_NAME_CONSTANT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ClassNameConstant.php',
+ 'PHP_Token_CLONE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Clone.php',
+ 'PHP_Token_CLOSE_BRACKET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/CloseBracket.php',
+ 'PHP_Token_CLOSE_CURLY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/CloseCurly.php',
+ 'PHP_Token_CLOSE_SQUARE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/CloseSquare.php',
+ 'PHP_Token_CLOSE_TAG' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/CloseTag.php',
+ 'PHP_Token_COALESCE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Coalesce.php',
+ 'PHP_Token_COALESCE_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/CoalesceEqual.php',
+ 'PHP_Token_COLON' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Colon.php',
+ 'PHP_Token_COMMA' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Comma.php',
+ 'PHP_Token_COMMENT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Comment.php',
+ 'PHP_Token_CONCAT_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ConcatEqual.php',
+ 'PHP_Token_CONST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Const.php',
+ 'PHP_Token_CONSTANT_ENCAPSED_STRING' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ConstantEncapsedString.php',
+ 'PHP_Token_CONTINUE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Continue.php',
+ 'PHP_Token_CURLY_OPEN' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/CurlyOpen.php',
+ 'PHP_Token_DEC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Dec.php',
+ 'PHP_Token_DECLARE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Declare.php',
+ 'PHP_Token_DEFAULT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Default.php',
+ 'PHP_Token_DIR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Dir.php',
+ 'PHP_Token_DIV' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Div.php',
+ 'PHP_Token_DIV_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/DivEqual.php',
+ 'PHP_Token_DNUMBER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/DNumber.php',
+ 'PHP_Token_DO' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Do.php',
+ 'PHP_Token_DOC_COMMENT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/DocComment.php',
+ 'PHP_Token_DOLLAR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Dollar.php',
+ 'PHP_Token_DOLLAR_OPEN_CURLY_BRACES' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/DollarOpenCurlyBraces.php',
+ 'PHP_Token_DOT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Dot.php',
+ 'PHP_Token_DOUBLE_ARROW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/DoubleArrow.php',
+ 'PHP_Token_DOUBLE_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/DoubleCast.php',
+ 'PHP_Token_DOUBLE_COLON' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/DoubleColon.php',
+ 'PHP_Token_DOUBLE_QUOTES' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/DoubleQuotes.php',
+ 'PHP_Token_ECHO' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Echo.php',
+ 'PHP_Token_ELLIPSIS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Ellipsis.php',
+ 'PHP_Token_ELSE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Else.php',
+ 'PHP_Token_ELSEIF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Elseif.php',
+ 'PHP_Token_EMPTY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Empty.php',
+ 'PHP_Token_ENCAPSED_AND_WHITESPACE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/EncapsedAndWhitespace.php',
+ 'PHP_Token_ENDDECLARE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Enddeclare.php',
+ 'PHP_Token_ENDFOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Endfor.php',
+ 'PHP_Token_ENDFOREACH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Endforeach.php',
+ 'PHP_Token_ENDIF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Endif.php',
+ 'PHP_Token_ENDSWITCH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Endswitch.php',
+ 'PHP_Token_ENDWHILE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Endwhile.php',
+ 'PHP_Token_END_HEREDOC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/EndHeredoc.php',
+ 'PHP_Token_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Equal.php',
+ 'PHP_Token_EVAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Eval.php',
+ 'PHP_Token_EXCLAMATION_MARK' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ExclamationMark.php',
+ 'PHP_Token_EXIT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Exit.php',
+ 'PHP_Token_EXTENDS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Extends.php',
+ 'PHP_Token_FILE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/File.php',
+ 'PHP_Token_FINAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Final.php',
+ 'PHP_Token_FINALLY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Finally.php',
+ 'PHP_Token_FN' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Fn.php',
+ 'PHP_Token_FOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/For.php',
+ 'PHP_Token_FOREACH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Foreach.php',
+ 'PHP_Token_FUNCTION' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Function.php',
+ 'PHP_Token_FUNC_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/FuncC.php',
+ 'PHP_Token_GLOBAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Global.php',
+ 'PHP_Token_GOTO' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Goto.php',
+ 'PHP_Token_GT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Gt.php',
+ 'PHP_Token_HALT_COMPILER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/HaltCompiler.php',
+ 'PHP_Token_IF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/If.php',
+ 'PHP_Token_IMPLEMENTS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Implements.php',
+ 'PHP_Token_INC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Inc.php',
+ 'PHP_Token_INCLUDE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Include.php',
+ 'PHP_Token_INCLUDE_ONCE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/IncludeOnce.php',
+ 'PHP_Token_INLINE_HTML' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/InlineHtml.php',
+ 'PHP_Token_INSTANCEOF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Instanceof.php',
+ 'PHP_Token_INSTEADOF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Insteadof.php',
+ 'PHP_Token_INTERFACE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Interface.php',
+ 'PHP_Token_INT_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/IntCast.php',
+ 'PHP_Token_ISSET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Isset.php',
+ 'PHP_Token_IS_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/IsEqual.php',
+ 'PHP_Token_IS_GREATER_OR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/IsGreaterOrEqual.php',
+ 'PHP_Token_IS_IDENTICAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/IsIdentical.php',
+ 'PHP_Token_IS_NOT_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/IsNotEqual.php',
+ 'PHP_Token_IS_NOT_IDENTICAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/IsNotIdentical.php',
+ 'PHP_Token_IS_SMALLER_OR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/IsSmallerOrEqual.php',
+ 'PHP_Token_Includes' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Includes.php',
+ 'PHP_Token_LINE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Line.php',
+ 'PHP_Token_LIST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/List.php',
+ 'PHP_Token_LNUMBER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Lnumber.php',
+ 'PHP_Token_LOGICAL_AND' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/LogicalAnd.php',
+ 'PHP_Token_LOGICAL_OR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/LogicalOr.php',
+ 'PHP_Token_LOGICAL_XOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/LogicalXor.php',
+ 'PHP_Token_LT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Lt.php',
+ 'PHP_Token_METHOD_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/MethodC.php',
+ 'PHP_Token_MINUS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Minus.php',
+ 'PHP_Token_MINUS_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/MinusEqual.php',
+ 'PHP_Token_MOD_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ModEqual.php',
+ 'PHP_Token_MULT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Mult.php',
+ 'PHP_Token_MUL_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/MulEqual.php',
+ 'PHP_Token_NAMESPACE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Namespace.php',
+ 'PHP_Token_NAME_FULLY_QUALIFIED' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/NameFullyQualified.php',
+ 'PHP_Token_NAME_QUALIFIED' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/NameQualified.php',
+ 'PHP_Token_NAME_RELATIVE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/NameRelative.php',
+ 'PHP_Token_NEW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/New.php',
+ 'PHP_Token_NS_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/NsC.php',
+ 'PHP_Token_NS_SEPARATOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/NsSeparator.php',
+ 'PHP_Token_NUM_STRING' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/NumString.php',
+ 'PHP_Token_OBJECT_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ObjectCast.php',
+ 'PHP_Token_OBJECT_OPERATOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/ObjectOperator.php',
+ 'PHP_Token_OPEN_BRACKET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/OpenBracket.php',
+ 'PHP_Token_OPEN_CURLY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/OpenCurly.php',
+ 'PHP_Token_OPEN_SQUARE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/OpenSquare.php',
+ 'PHP_Token_OPEN_TAG' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/OpenTag.php',
+ 'PHP_Token_OPEN_TAG_WITH_ECHO' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/OpenTagWithEcho.php',
+ 'PHP_Token_OR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/OrEqual.php',
+ 'PHP_Token_PAAMAYIM_NEKUDOTAYIM' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/PaamayimNekudotayim.php',
+ 'PHP_Token_PERCENT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Percent.php',
+ 'PHP_Token_PIPE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Pipe.php',
+ 'PHP_Token_PLUS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Plus.php',
+ 'PHP_Token_PLUS_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/PlusEqual.php',
+ 'PHP_Token_POW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Pow.php',
+ 'PHP_Token_POW_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/PowEqual.php',
+ 'PHP_Token_PRINT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Print.php',
+ 'PHP_Token_PRIVATE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Private.php',
+ 'PHP_Token_PROTECTED' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Protected.php',
+ 'PHP_Token_PUBLIC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Public.php',
+ 'PHP_Token_QUESTION_MARK' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/QuestionMark.php',
+ 'PHP_Token_REQUIRE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Require.php',
+ 'PHP_Token_REQUIRE_ONCE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/RequireOnce.php',
+ 'PHP_Token_RETURN' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Return.php',
+ 'PHP_Token_SEMICOLON' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Semicolon.php',
+ 'PHP_Token_SL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Sl.php',
+ 'PHP_Token_SL_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/SlEqual.php',
+ 'PHP_Token_SPACESHIP' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Spaceship.php',
+ 'PHP_Token_SR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Sr.php',
+ 'PHP_Token_SR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/SrEqual.php',
+ 'PHP_Token_START_HEREDOC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/StartHeredoc.php',
+ 'PHP_Token_STATIC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Static.php',
+ 'PHP_Token_STRING' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/String.php',
+ 'PHP_Token_STRING_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/StringCast.php',
+ 'PHP_Token_STRING_VARNAME' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/StringVarname.php',
+ 'PHP_Token_SWITCH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Switch.php',
+ 'PHP_Token_Stream' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Stream.php',
+ 'PHP_Token_Stream_CachingFactory' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/CachingFactory.php',
+ 'PHP_Token_THROW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Throw.php',
+ 'PHP_Token_TILDE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Tilde.php',
+ 'PHP_Token_TRAIT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Trait.php',
+ 'PHP_Token_TRAIT_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/TraitC.php',
+ 'PHP_Token_TRY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Try.php',
+ 'PHP_Token_UNSET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Unset.php',
+ 'PHP_Token_UNSET_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/UnsetCast.php',
+ 'PHP_Token_USE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Use.php',
+ 'PHP_Token_USE_FUNCTION' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/UseFunction.php',
+ 'PHP_Token_Util' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Util.php',
+ 'PHP_Token_VAR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Var.php',
+ 'PHP_Token_VARIABLE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Variable.php',
+ 'PHP_Token_WHILE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/While.php',
+ 'PHP_Token_WHITESPACE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Whitespace.php',
+ 'PHP_Token_XOR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/XorEqual.php',
+ 'PHP_Token_YIELD' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Yield.php',
+ 'PHP_Token_YIELD_FROM' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/YieldFrom.php',
+ 'PharIo\\Manifest\\Application' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Application.php',
+ 'PharIo\\Manifest\\ApplicationName' => __DIR__ . '/..' . '/phar-io/manifest/src/values/ApplicationName.php',
+ 'PharIo\\Manifest\\Author' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Author.php',
+ 'PharIo\\Manifest\\AuthorCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollection.php',
+ 'PharIo\\Manifest\\AuthorCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollectionIterator.php',
+ 'PharIo\\Manifest\\AuthorElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElement.php',
+ 'PharIo\\Manifest\\AuthorElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElementCollection.php',
+ 'PharIo\\Manifest\\BundledComponent' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponent.php',
+ 'PharIo\\Manifest\\BundledComponentCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollection.php',
+ 'PharIo\\Manifest\\BundledComponentCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php',
+ 'PharIo\\Manifest\\BundlesElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/BundlesElement.php',
+ 'PharIo\\Manifest\\ComponentElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElement.php',
+ 'PharIo\\Manifest\\ComponentElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElementCollection.php',
+ 'PharIo\\Manifest\\ContainsElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ContainsElement.php',
+ 'PharIo\\Manifest\\CopyrightElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/CopyrightElement.php',
+ 'PharIo\\Manifest\\CopyrightInformation' => __DIR__ . '/..' . '/phar-io/manifest/src/values/CopyrightInformation.php',
+ 'PharIo\\Manifest\\ElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ElementCollection.php',
+ 'PharIo\\Manifest\\ElementCollectionException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ElementCollectionException.php',
+ 'PharIo\\Manifest\\Email' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Email.php',
+ 'PharIo\\Manifest\\Exception' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/Exception.php',
+ 'PharIo\\Manifest\\ExtElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElement.php',
+ 'PharIo\\Manifest\\ExtElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElementCollection.php',
+ 'PharIo\\Manifest\\Extension' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Extension.php',
+ 'PharIo\\Manifest\\ExtensionElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtensionElement.php',
+ 'PharIo\\Manifest\\InvalidApplicationNameException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php',
+ 'PharIo\\Manifest\\InvalidEmailException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidEmailException.php',
+ 'PharIo\\Manifest\\InvalidUrlException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidUrlException.php',
+ 'PharIo\\Manifest\\Library' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Library.php',
+ 'PharIo\\Manifest\\License' => __DIR__ . '/..' . '/phar-io/manifest/src/values/License.php',
+ 'PharIo\\Manifest\\LicenseElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/LicenseElement.php',
+ 'PharIo\\Manifest\\Manifest' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Manifest.php',
+ 'PharIo\\Manifest\\ManifestDocument' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestDocument.php',
+ 'PharIo\\Manifest\\ManifestDocumentException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php',
+ 'PharIo\\Manifest\\ManifestDocumentLoadingException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php',
+ 'PharIo\\Manifest\\ManifestDocumentMapper' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestDocumentMapper.php',
+ 'PharIo\\Manifest\\ManifestDocumentMapperException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php',
+ 'PharIo\\Manifest\\ManifestElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestElement.php',
+ 'PharIo\\Manifest\\ManifestElementException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestElementException.php',
+ 'PharIo\\Manifest\\ManifestLoader' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestLoader.php',
+ 'PharIo\\Manifest\\ManifestLoaderException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php',
+ 'PharIo\\Manifest\\ManifestSerializer' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestSerializer.php',
+ 'PharIo\\Manifest\\PhpElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/PhpElement.php',
+ 'PharIo\\Manifest\\PhpExtensionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpExtensionRequirement.php',
+ 'PharIo\\Manifest\\PhpVersionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpVersionRequirement.php',
+ 'PharIo\\Manifest\\Requirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Requirement.php',
+ 'PharIo\\Manifest\\RequirementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollection.php',
+ 'PharIo\\Manifest\\RequirementCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollectionIterator.php',
+ 'PharIo\\Manifest\\RequiresElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/RequiresElement.php',
+ 'PharIo\\Manifest\\Type' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Type.php',
+ 'PharIo\\Manifest\\Url' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Url.php',
+ 'PharIo\\Version\\AbstractVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AbstractVersionConstraint.php',
+ 'PharIo\\Version\\AndVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php',
+ 'PharIo\\Version\\AnyVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AnyVersionConstraint.php',
+ 'PharIo\\Version\\ExactVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/ExactVersionConstraint.php',
+ 'PharIo\\Version\\Exception' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/Exception.php',
+ 'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php',
+ 'PharIo\\Version\\InvalidPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php',
+ 'PharIo\\Version\\InvalidVersionException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidVersionException.php',
+ 'PharIo\\Version\\NoPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php',
+ 'PharIo\\Version\\OrVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php',
+ 'PharIo\\Version\\PreReleaseSuffix' => __DIR__ . '/..' . '/phar-io/version/src/PreReleaseSuffix.php',
+ 'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php',
+ 'PharIo\\Version\\SpecificMajorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php',
+ 'PharIo\\Version\\UnsupportedVersionConstraintException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php',
+ 'PharIo\\Version\\Version' => __DIR__ . '/..' . '/phar-io/version/src/Version.php',
+ 'PharIo\\Version\\VersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/VersionConstraint.php',
+ 'PharIo\\Version\\VersionConstraintParser' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintParser.php',
+ 'PharIo\\Version\\VersionConstraintValue' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintValue.php',
+ 'PharIo\\Version\\VersionNumber' => __DIR__ . '/..' . '/phar-io/version/src/VersionNumber.php',
+ 'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php',
+ 'SebastianBergmann\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage.php',
+ 'SebastianBergmann\\CodeCoverage\\CoveredCodeNotExecutedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/CoveredCodeNotExecutedException.php',
+ 'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Driver.php',
+ 'SebastianBergmann\\CodeCoverage\\Driver\\PCOV' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PCOV.php',
+ 'SebastianBergmann\\CodeCoverage\\Driver\\PHPDBG' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PHPDBG.php',
+ 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Xdebug.php',
+ 'SebastianBergmann\\CodeCoverage\\Exception' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Exception.php',
+ 'SebastianBergmann\\CodeCoverage\\Filter' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Filter.php',
+ 'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php',
+ 'SebastianBergmann\\CodeCoverage\\MissingCoversAnnotationException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/MissingCoversAnnotationException.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/AbstractNode.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\Builder' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Builder.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Directory.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/File.php',
+ 'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Iterator.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Clover.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Crap4j.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Facade.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\PHP' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/PHP.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Text.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/File.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Method.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Node.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Project.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Report.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Source.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php',
+ 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php',
+ 'SebastianBergmann\\CodeCoverage\\RuntimeException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/RuntimeException.php',
+ 'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php',
+ 'SebastianBergmann\\CodeCoverage\\Util' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util.php',
+ 'SebastianBergmann\\CodeCoverage\\Version' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Version.php',
+ 'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => __DIR__ . '/..' . '/sebastian/code-unit-reverse-lookup/src/Wizard.php',
+ 'SebastianBergmann\\Comparator\\ArrayComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ArrayComparator.php',
+ 'SebastianBergmann\\Comparator\\Comparator' => __DIR__ . '/..' . '/sebastian/comparator/src/Comparator.php',
+ 'SebastianBergmann\\Comparator\\ComparisonFailure' => __DIR__ . '/..' . '/sebastian/comparator/src/ComparisonFailure.php',
+ 'SebastianBergmann\\Comparator\\DOMNodeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DOMNodeComparator.php',
+ 'SebastianBergmann\\Comparator\\DateTimeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DateTimeComparator.php',
+ 'SebastianBergmann\\Comparator\\DoubleComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DoubleComparator.php',
+ 'SebastianBergmann\\Comparator\\ExceptionComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ExceptionComparator.php',
+ 'SebastianBergmann\\Comparator\\Factory' => __DIR__ . '/..' . '/sebastian/comparator/src/Factory.php',
+ 'SebastianBergmann\\Comparator\\MockObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/MockObjectComparator.php',
+ 'SebastianBergmann\\Comparator\\NumericComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/NumericComparator.php',
+ 'SebastianBergmann\\Comparator\\ObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ObjectComparator.php',
+ 'SebastianBergmann\\Comparator\\ResourceComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ResourceComparator.php',
+ 'SebastianBergmann\\Comparator\\ScalarComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ScalarComparator.php',
+ 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/SplObjectStorageComparator.php',
+ 'SebastianBergmann\\Comparator\\TypeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/TypeComparator.php',
+ 'SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php',
+ 'SebastianBergmann\\Diff\\ConfigurationException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/ConfigurationException.php',
+ 'SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php',
+ 'SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php',
+ 'SebastianBergmann\\Diff\\Exception' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/Exception.php',
+ 'SebastianBergmann\\Diff\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/InvalidArgumentException.php',
+ 'SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php',
+ 'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php',
+ 'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php',
+ 'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php',
+ 'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php',
+ 'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php',
+ 'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php',
+ 'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php',
+ 'SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php',
+ 'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php',
+ 'SebastianBergmann\\Environment\\Console' => __DIR__ . '/..' . '/sebastian/environment/src/Console.php',
+ 'SebastianBergmann\\Environment\\OperatingSystem' => __DIR__ . '/..' . '/sebastian/environment/src/OperatingSystem.php',
+ 'SebastianBergmann\\Environment\\Runtime' => __DIR__ . '/..' . '/sebastian/environment/src/Runtime.php',
+ 'SebastianBergmann\\Exporter\\Exporter' => __DIR__ . '/..' . '/sebastian/exporter/src/Exporter.php',
+ 'SebastianBergmann\\FileIterator\\Facade' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Facade.php',
+ 'SebastianBergmann\\FileIterator\\Factory' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Factory.php',
+ 'SebastianBergmann\\FileIterator\\Iterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Iterator.php',
+ 'SebastianBergmann\\GlobalState\\Blacklist' => __DIR__ . '/..' . '/sebastian/global-state/src/Blacklist.php',
+ 'SebastianBergmann\\GlobalState\\CodeExporter' => __DIR__ . '/..' . '/sebastian/global-state/src/CodeExporter.php',
+ 'SebastianBergmann\\GlobalState\\Exception' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/Exception.php',
+ 'SebastianBergmann\\GlobalState\\Restorer' => __DIR__ . '/..' . '/sebastian/global-state/src/Restorer.php',
+ 'SebastianBergmann\\GlobalState\\RuntimeException' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/RuntimeException.php',
+ 'SebastianBergmann\\GlobalState\\Snapshot' => __DIR__ . '/..' . '/sebastian/global-state/src/Snapshot.php',
+ 'SebastianBergmann\\ObjectEnumerator\\Enumerator' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/Enumerator.php',
+ 'SebastianBergmann\\ObjectEnumerator\\Exception' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/Exception.php',
+ 'SebastianBergmann\\ObjectEnumerator\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/InvalidArgumentException.php',
+ 'SebastianBergmann\\ObjectReflector\\Exception' => __DIR__ . '/..' . '/sebastian/object-reflector/src/Exception.php',
+ 'SebastianBergmann\\ObjectReflector\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/object-reflector/src/InvalidArgumentException.php',
+ 'SebastianBergmann\\ObjectReflector\\ObjectReflector' => __DIR__ . '/..' . '/sebastian/object-reflector/src/ObjectReflector.php',
+ 'SebastianBergmann\\RecursionContext\\Context' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Context.php',
+ 'SebastianBergmann\\RecursionContext\\Exception' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Exception.php',
+ 'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/recursion-context/src/InvalidArgumentException.php',
+ 'SebastianBergmann\\ResourceOperations\\ResourceOperations' => __DIR__ . '/..' . '/sebastian/resource-operations/src/ResourceOperations.php',
+ 'SebastianBergmann\\Timer\\Exception' => __DIR__ . '/..' . '/phpunit/php-timer/src/Exception.php',
+ 'SebastianBergmann\\Timer\\RuntimeException' => __DIR__ . '/..' . '/phpunit/php-timer/src/RuntimeException.php',
+ 'SebastianBergmann\\Timer\\Timer' => __DIR__ . '/..' . '/phpunit/php-timer/src/Timer.php',
+ 'SebastianBergmann\\Type\\CallableType' => __DIR__ . '/..' . '/sebastian/type/src/CallableType.php',
+ 'SebastianBergmann\\Type\\Exception' => __DIR__ . '/..' . '/sebastian/type/src/exception/Exception.php',
+ 'SebastianBergmann\\Type\\GenericObjectType' => __DIR__ . '/..' . '/sebastian/type/src/GenericObjectType.php',
+ 'SebastianBergmann\\Type\\IterableType' => __DIR__ . '/..' . '/sebastian/type/src/IterableType.php',
+ 'SebastianBergmann\\Type\\NullType' => __DIR__ . '/..' . '/sebastian/type/src/NullType.php',
+ 'SebastianBergmann\\Type\\ObjectType' => __DIR__ . '/..' . '/sebastian/type/src/ObjectType.php',
+ 'SebastianBergmann\\Type\\RuntimeException' => __DIR__ . '/..' . '/sebastian/type/src/exception/RuntimeException.php',
+ 'SebastianBergmann\\Type\\SimpleType' => __DIR__ . '/..' . '/sebastian/type/src/SimpleType.php',
+ 'SebastianBergmann\\Type\\Type' => __DIR__ . '/..' . '/sebastian/type/src/Type.php',
+ 'SebastianBergmann\\Type\\TypeName' => __DIR__ . '/..' . '/sebastian/type/src/TypeName.php',
+ 'SebastianBergmann\\Type\\UnknownType' => __DIR__ . '/..' . '/sebastian/type/src/UnknownType.php',
+ 'SebastianBergmann\\Type\\VoidType' => __DIR__ . '/..' . '/sebastian/type/src/VoidType.php',
+ 'SebastianBergmann\\Version' => __DIR__ . '/..' . '/sebastian/version/src/Version.php',
'SqlFormatter' => __DIR__ . '/..' . '/jdorn/sql-formatter/lib/SqlFormatter.php',
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
+ 'Text_Template' => __DIR__ . '/..' . '/phpunit/php-text-template/src/Template.php',
+ 'TheSeer\\Tokenizer\\Exception' => __DIR__ . '/..' . '/theseer/tokenizer/src/Exception.php',
+ 'TheSeer\\Tokenizer\\NamespaceUri' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUri.php',
+ 'TheSeer\\Tokenizer\\NamespaceUriException' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUriException.php',
+ 'TheSeer\\Tokenizer\\Token' => __DIR__ . '/..' . '/theseer/tokenizer/src/Token.php',
+ 'TheSeer\\Tokenizer\\TokenCollection' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollection.php',
+ 'TheSeer\\Tokenizer\\TokenCollectionException' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollectionException.php',
+ 'TheSeer\\Tokenizer\\Tokenizer' => __DIR__ . '/..' . '/theseer/tokenizer/src/Tokenizer.php',
+ 'TheSeer\\Tokenizer\\XMLSerializer' => __DIR__ . '/..' . '/theseer/tokenizer/src/XMLSerializer.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
);
@@ -394,7 +1016,6 @@ public static function getInitializer(ClassLoader $loader)
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit8d81387c26c532d7a48feda4036c56c7::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit8d81387c26c532d7a48feda4036c56c7::$prefixDirsPsr4;
- $loader->fallbackDirsPsr4 = ComposerStaticInit8d81387c26c532d7a48feda4036c56c7::$fallbackDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInit8d81387c26c532d7a48feda4036c56c7::$prefixesPsr0;
$loader->classMap = ComposerStaticInit8d81387c26c532d7a48feda4036c56c7::$classMap;
diff --git a/app/vendor/composer/composer/.gitattributes b/app/vendor/composer/composer/.gitattributes
index 2ee43db45..51b431136 100644
--- a/app/vendor/composer/composer/.gitattributes
+++ b/app/vendor/composer/composer/.gitattributes
@@ -2,7 +2,7 @@
* text=auto eol=lf
# These files are always considered text and should use LF.
-# See core.whitespace @ https://git-scm.com/docs/git-config for whitespace flags.
+# See core.whitespace @ http://git-scm.com/docs/git-config for whitespace flags.
*.php text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=4 diff=php
*.json text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=4
*.test text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=4
@@ -15,4 +15,3 @@
.travis.yml export-ignore
appveyor.yml export-ignore
phpunit.xml.dist export-ignore
-/phpstan/ export-ignore
diff --git a/app/vendor/composer/composer/.gitignore b/app/vendor/composer/composer/.gitignore
index 0b1fb77c0..f9d78df20 100644
--- a/app/vendor/composer/composer/.gitignore
+++ b/app/vendor/composer/composer/.gitignore
@@ -4,9 +4,8 @@
/composer.phar
/vendor
/nbproject
-.phpunit.result.cache
phpunit.xml
.vagrant
Vagrantfile
.idea
-.php_cs.cache
+.php_cs.cache
\ No newline at end of file
diff --git a/app/vendor/composer/composer/CHANGELOG.md b/app/vendor/composer/composer/CHANGELOG.md
index 1b5a194a0..bc6a92fc8 100644
--- a/app/vendor/composer/composer/CHANGELOG.md
+++ b/app/vendor/composer/composer/CHANGELOG.md
@@ -1,325 +1,3 @@
-### [2.1.8] 2021-09-15
-
- * Fixed regression in 2.1.7 when parsing classmaps in files containing invalid Unicode (#10102)
-
-### [2.1.7] 2021-09-14
-
- * Added many type annotations internally, which may have an effect on CI/static analysis for people using Composer as a dependency. This work will continue in following releases
- * Fixed regression in 2.1.6 when parsing classmaps with empty heredocs (#10067)
- * Fixed regression in 2.1.6 where list command was not showing plugin commands (#10075)
- * Fixed issue handling package updates where the package type changed (#10076)
- * Fixed docker being detected as WSL when run inside WSL (#10094)
-
-### [2.1.6] 2021-08-19
-
- * Updated internal PHAR signatures to be SHA512 instead of SHA1
- * Fixed uncaught exception handler regression (#10022)
- * Fixed more PHP 8.1 deprecation warnings (#10036, #10038, #10061)
- * Fixed corrupted zips in the cache from blocking installs until a cache clear, the bad archives are now deleted automatically on first failure (#10028)
- * Fixed URL sanitizer handling of new github tokens (#10048)
- * Fixed issue finding classes with very long heredocs in classmap autoload (#10050)
- * Fixed proc_open being required for simple installs from zip, as well as diagnose (#9253)
- * Fixed path repository bug causing symlinks to be left behind after a package is uninstalled (#10023)
- * Fixed issue in 7-zip support on windows with certain archives (#10058)
- * Fixed bootstrapping process to avoid loading the composer.json and plugins until necessary, speeding things up slightly (#10064)
- * Fixed lib-openssl detection on FreeBSD (#10046)
- * Fixed support for `ircs://` protocol for support.irc composer.json entries
-
-### [2.1.5] 2021-07-23
-
- * Fixed `create-project` creating a `php:` directory in the directory it was executed in (#10020, #10021)
- * Fixed curl downloader to respect default_socket_timeout if it is bigger than our default 300s (#10018)
-
-### [2.1.4] 2021-07-22
-
- * Fixed PHP 8.1 deprecation warnings (#10008)
- * Fixed support for working within UNC/WSL paths on Windows (#9993)
- * Fixed 7-zip support to also be looked up on Linux/macOS as 7z or 7zz (#9951)
- * Fixed repositories' `only`/`exclude` properties to avoid matching names as sub-strings of full package names (#10001)
- * Fixed open_basedir regression from #9855
- * Fixed schema errors being reported incorrectly in some conditions (#9986)
- * Fixed `archive` command not working with async archive extraction
- * Fixed `init` command being able to generate an invalid composer.json (#9986)
-
-### [2.1.3] 2021-06-09
-
- * Add "symlink" option for "bin-compat" config to force symlinking even on WSL/Windows (#9959)
- * Fixed source binaries not being made executable when symlinks cannot be used (#9961)
- * Fixed more deletion edge cases (#9955, #9956)
- * Fixed `dump-autoload` command not dispatching scripts anymore, regressed in 2.1.2 (#9954)
-
-### [2.1.2] 2021-06-07
-
- * Added `--dev` to `dump-autoload` command to allow force-dumping dev autoload rules even if dev requirements are not present (#9946)
- * Fixed `--no-scripts` disabling events for plugins too instead of only disabling script handlers, using `--no-plugins` is the way to disable plugins (#9942)
- * Fixed handling of deletions during package installs on some filesystems (#9945, #9947)
- * Fixed undefined array access when using "@php " in a script handler (#9943)
- * Fixed usage of InstalledVersions when loaded from composer/composer installed as a dependency and runtime Composer is v1 (#9937)
-
-### [2.1.1] 2021-06-04
-
- * Fixed regression in autoload generation when --no-scripts is used (#9935)
- * Fixed `outdated` color legend to have the right color in the right place (#9939)
- * Fixed PCRE bug causing a previously valid pattern to fail to match (#9941)
- * Fixed JsonFile::validateSchema regression when used as a library to validate custom schema files (#9938)
-
-### [2.1.0] 2021-06-03
-
- * Fixed PHP 8.1 deprecation warning (#9932)
- * Fixed env var handling when variables_order includes E and symfony/console 3.3.15+ is in use (#9930)
-
-### [2.1.0-RC1] 2021-06-02
-
- * Bumped `composer-runtime-api` and `composer-plugin-api` to `2.1.0`
- * UX Change: The default install method for packages is now always dist/zip, even for dev packages, added `--prefer-install=auto` if you want the old behavior (#9603)
- * UX Change: Packages from `path` repositories which are symlinked in the vendor dir will always be updated in partial updates to avoid mistakes when the original composer.json changes but the symlinked package is not explicitly updated (#9765)
- * Added `reinstall` command that takes one or more package names, including wildcard (`*`) support, and removes then reinstalls them in the exact same version they had (#9915)
- * Added support for parallel package installs on Windows via [7-Zip](https://www.7-zip.org/) if it is installed (#9875)
- * Added detection of invalid composer.lock files that do not fullfil the composer.json requirements to `validate` command (#9899)
- * Added `InstalledVersions::getInstalledPackagesByType(string $type)` to retrieve installed plugins for example, [read more](https://getcomposer.org/doc/07-runtime.md#knowing-which-packages-of-a-given-type-are-installed) (#9699)
- * Added `InstalledVersions::getInstalledPath(string $packageName)` to retrieve the install path of a given package, [read more](https://getcomposer.org/doc/07-runtime.md#knowing-the-path-in-which-a-package-is-installed) (#9699)
- * Added flag to `InstalledVersions::isInstalled()` to allow excluding dev requirements from that check (#9682)
- * Added support for PHP 8.1 enums in autoloader / classmap generation (#9670)
- * Added support for using `@php binary-name foo` in scripts to refer to a binary without using its full path, but forcing to use the same PHP version as Composer used (#9726)
- * Added `--format=json` support to the `fund` command (#9678)
- * Added `--format=json` support to the `search` command (#9747)
- * Added `COMPOSER_DEV_MODE` env var definition within the run-script command for compatibility (#9793)
- * Added async uninstall of packages (#9618)
- * Added color legend to `outdated` and `show --latest` commands (#9716)
- * Added `secure-svn-domains` config option to mark secure svn:// hostnames and suppress warnings without disabling secure-http (#9872)
- * Added `gitlab-protocol` config option to allow forcing `git` or `http` URLs for all gitlab repos loaded inline, instead of the default of git for private and http for public (#9401)
- * Added generation of autoload rules in `init` command (#9829)
- * Added source/dist validation in `validate` command
- * Added automatic detection of WSL when generating binaries and use `bin-compat:full` implicitly (#9855)
- * Added automatic detection of the --no-dev state for `dump-autoload` based on the last install run (#9714)
- * Added warning/prompt to `require` command if requiring a package that already exists in require-dev or vice versa (#9542)
- * Added information about package conflicts in the `why`/`why-not` commands (#9693)
- * Removed version argument from `why` command as it was not needed (#9729)
- * Fixed `why-not` command to always require a specific version as it is useless without (#9729)
- * Fixed cache dir on macOS to follow OS guidelines, it is now in ~/Library/Caches/composer (#9898)
- * Fixed composer.json JSON schema to avoid having name/description required by default (#9912)
- * Fixed support for running inside WSL paths from a Windows PHP/Composer (#9861)
- * Fixed InstalledVersions to include the original doc blocks when installed from a Composer phar file
- * Fixed `require` command to use `*` as constraint for extensions bundled with PHP instead of duplicating the PHP constraint (#9483)
- * Fixed `search` output to be aligned and avoid wrapped long lines to be more readable (#9455)
- * Error output improvements for many cases (#9876, #9837, #9928, and some smaller improvements)
-
-### [2.0.14] 2021-05-21
-
- * Updated composer/xdebug-handler to 2.0 which adds supports for Xdebug 3
- * Fixed handling of inline-update-constraints with references or stability flags (#9847)
- * Fixed async processes erroring in an unclear way when they failed to start (#9808)
- * Fixed support for the upcoming Symfony 6.0 release when Composer is installed as a library (#9896)
- * Fixed progress output missing newlines on PowerShell, and disable progress output by default when CI env var is present (#9621)
- * Fixed support for Vagrant/VirtualBox filesystem slowness when installing binaries from packages (#9627)
- * Fixed type annotations for the InstalledVersions class
- * Deprecated InstalledVersions::getRawData in favor of InstalledVersions::getAllRawData (#9816)
-
-### [2.0.13] 2021-04-27
-
- * Security: Fixed command injection vulnerability in HgDriver/HgDownloader and hardened other VCS drivers and downloaders (GHSA-h5h8-pc6h-jvvx / CVE-2021-29472)
- * Fixed install step at the end of the init command to take new dependencies into account correctly
- * Fixed `update --lock` listing updates which were not really happening (#9812)
- * Fixed support for --no-dev combined with --locked in outdated and show commands (#9788)
-
-### [2.0.12] 2021-04-01
-
- * Fixed support for new GitHub OAuth token format (#9757)
- * Fixed support for Vagrant/VirtualBox filesystem slowness by adding short sleeps in some places (#9627)
- * Fixed unclear error reporting when a package is in the lock file but not in the remote repositories (#9750)
- * Fixed processes silently ignoring the CWD when it does not exist
- * Fixed new Windows bin handling to avoid proxying phar files (#9742)
- * Fixed issue extracting archives into paths that already exist, fixing problems with some custom installers (composer/installers#479)
- * Fixed support for branch names starting with master/trunk/default (#9739)
- * Fixed self-update to preserve phar file permissions on Windows (#9733)
- * Fixed detection of hg version when localized (#9753)
- * Fixed git execution failures to also include the stdout output (#9720)
-
-### [2.0.11] 2021-02-24
-
- * Reverted "Fixed runtime autoloader registration (for plugins and script handlers) to prefer the project dependencies over the bundled Composer ones" as it caused more problems than expected
-
-### [2.0.10] 2021-02-23
-
- * Added COMPOSER_MAX_PARALLEL_HTTP to let people set a lower amount of parallel requests if needed
- * Fixed autoloader registration when plugins are loaded, which may impact plugins relying on this bug (if you use `symfony/flex` make sure you upgrade it to 1.12.2+ to fix `dump-env` issues)
- * Fixed `exec` command suppressing output in some circumstances
- * Fixed Windows/cmd.exe support for script handlers defined as `path/to/foo`, which are now rewritten internally to `path\to\foo` when needed
- * Fixed bin handling on Windows for PHP scripts, to more closely match symlinks and allow `@php vendor/bin/foo` to work cross-platform
- * Fixed Git for Windows/Git Bash not being detected correctly as an interactive shell (regression since 2.0.7)
- * Fixed regression handling some private Bitbucket repository clones
- * Fixed Ctrl-C/SIGINT handling during downloads to correctly abort as soon as possible
- * Fixed runtime autoloader registration (for plugins and script handlers) to prefer the project dependencies over the bundled Composer ones
- * Fixed numeric default branches being aliased as 9999999-dev internally. This alias now only applies to default branches being non-numeric (e.g. `dev-main`)
- * Fixed support for older lib-sodium versions
- * Fixed various minor issues
-
-### [2.0.9] 2021-01-27
-
- * Added warning if the curl extension is not enabled as it significantly degrades performance
- * Fixed InstalledVersions to report all packages when several vendor dirs are present in the same runtime
- * Fixed download speed when downloading large files
- * Fixed `archive` and path repo copies mishandling some .gitignore paths
- * Fixed root package classes not being available to the plugins/scripts during the initial install
- * Fixed cache writes to be atomic and better support multiple Composer processes running in parallel
- * Fixed preg jit issues when `config` or `require` modifies large composer.json files
- * Fixed compatibility with envs having open_basedir restrictions
- * Fixed exclude-from-classmap causing regex issues when having too many paths
- * Fixed compatibility issue with Symfony 4/5
- * Several small performance and debug output improvements
-
-### [2.0.8] 2020-12-03
-
- * Fixed packages with aliases not matching conflicts which match the alias
- * Fixed invalid reports of uncommitted changes when using non-default remotes in vendor dir
- * Fixed curl error handling edge cases
- * Fixed cached git repositories becoming stale by having a `git gc` applied to them periodically
- * Fixed issue initializing plugins when using dev packages
- * Fixed update --lock / mirrors failing to update in some edge cases
- * Fixed partial update with --with-dependencies failing in some edge cases with some nonsensical error
-
-### [2.0.7] 2020-11-13
-
- * Fixed detection of TTY mode, made input non-interactive automatically if STDIN is not a TTY
- * Fixed root aliases not being present in lock file if not required by anything else
- * Fixed `remove` command requiring a lock file to be present
- * Fixed `Composer\InstalledVersions` to always contain up to date data during installation
- * Fixed `status` command breaking on slow networks
- * Fixed order of POST_PACKAGE_* events to occur together once all installations of a package batch are done
-
-### [2.0.6] 2020-11-07
-
- * Fixed regression in 2.0.5 dealing with custom installers which do not pass absolute paths
-
-### [2.0.5] 2020-11-06
-
- * Disabled platform-check verification of extensions by default (now defaulting `php-only`), set platform-check to `true` if you want a complete check
- * Improved platform-check handling of issue reporting
- * Fixed platform-check to only check non-dev requires even if require-dev dependencies are installed
- * Fixed issues dealing with custom installers which return trailing slashes in getInstallPath (ideally avoid doing this as there might be other issues left)
- * Fixed issues when curl functions are disabled
- * Fixed gitlab-domains/github-domains to make sure if they are overridden the default value remains present
- * Fixed issues removing/upgrading packages from path repositories on Windows
- * Fixed regression in 2.0.4 when handling of git@bitbucket.org URLs in vcs repositories
- * Fixed issue running create-project in current directory on Windows
-
-### [2.0.4] 2020-10-30
-
- * Fixed `check-platform-req` command not being clear on what packages are checked, and added a --lock flag to explicitly check the locked packages
- * Fixed `config` & `create-project` adding of repositories to make sure they are prepended as order is much more important in Composer 2, also added a --append flag to `config` to restore the old behavior in the unlikely case this is needed
- * Fixed curl downloader failing on old PHP releases or when using self-signed SSL certificates
- * Fixed Bitbucket API authentication issue
-
-### [2.0.3] 2020-10-28
-
- * Fixed bug in `outdated` command where dev packages with branch-aliases where always shown as being outdated
- * Fixed issue in lock file interoperability with composer 1.x when using `dev-master as xxx` aliases
- * Fixed new `--locked` option being missing from `outdated` command, for checking outdated packages directly from the lock file
- * Fixed a few debug/error reporting strings
-
-### [2.0.2] 2020-10-25
-
- * Fixed regression handling `composer show -s` in projects where no version can be guessed from VCS
- * Fixed regression handling partial updates/`require` when a lock file was missing
- * Fixed interop issue with plugins that need to update dist URLs of packages, [see docs](https://getcomposer.org/doc/articles/plugins.md#plugin-modifies-downloads) if you need this
-
-### [2.0.1] 2020-10-24
-
- * Fixed crash on PHP8
-
-### [2.0.0] 2020-10-24
-
- * Fixed proxy handling issues when combined with our new curl-based downloader
- * Fixed solver bug resulting in endless loops in some cases
- * Fixed solver output being extremely long due to learnt rules
- * Fixed solver bug with multi literals
- * Fixed a couple minor regressions
-
-### [2.0.0-RC2] 2020-10-14
-
- * Breaking: Removed `OperationInterface::getReason` as the data was not accurate
- * Added automatic removal of packages which are not required anymore whenever an update is done, this will purge packages previously left over by partial updates and `require`/`remove`
- * Added shorthand aliases `-w` for `--with-dependencies` and `-W` for `--with-all-dependencies` on `update`/`require`/`remove` commands
- * Added `COMPOSER_DEBUG_EVENTS=1` env var support for plugin authors to figure out which events are triggered when
- * Added `setCustomCacheKey` to `PreFileDownloadEvent` and fixed a cache bug for integrations changing the processed url of package archives
- * Added `Composer\Util\SyncHelper` for plugin authors to deal with async Promises more easily
- * Added `$composer->getLoop()->getHttpDownloader()` to get access to the main HttpDownloader instance in plugins
- * Added a non-zero exit code (2) and warning to `remove` command when a package to be removed could not be removed
- * Added `--apcu-autoloader-prefix` (or `--apcu-prefix` for `dump-autoload` command) flag to let people use apcu autoloading in a deterministic output way if that is needed
- * Fixed version guesser to look at remote branches as well as local ones
- * Lots of minor bug fixes and improvements
-
-### [2.0.0-RC1] 2020-09-10
-
- * Added more advanced filtering to avoid loading all versions of all referenced packages when resolving dependencies, which should reduce memory usage further in some cases
- * Added support for many new `lib-*` packages in the platform repository and improved version detection for some `ext-*` and `lib-*` packages
- * Added an `--ask` flag to `create-project` command to make Composer prompt for the install dir name, [useful for project install instructions](https://github.com/composer/composer/pull/9181)
- * Added support for tar in artifact repositories
- * Added a `cache-read-only` config option to make the cache usable in read only mode for containers and such
- * Added better error reporting for a few more specific cases
- * Added a new optional `available-package-patterns` attribute for v2-format Composer repositories, see [UPGRADE](UPGRADE-2.0.md) for details
- * Fixed more PHP 8 compatibility issues
- * Lots of minor bug fixes for regressions
-
-### [2.0.0-alpha3] 2020-08-03
-
- * Breaking: Zip archives loaded by artifact repositories must now have a composer.json on top level, or a max of one folder on top level of the archive
- * Added --no-dev support to `show` and `outdated` commands to skip dev requirements
- * Added support for multiple --repository flags being passed into the `create-project` command, only useful in combination with `--add-repository` to persist them to composer.json
- * Added a new optional `list` API endpoint for v2-format Composer repositories, see [UPGRADE](UPGRADE-2.0.md) for details
- * Fixed `show -a` command not listing anything
- * Fixed solver bug where it ended in a "Reached invalid decision id 0"
- * Fixed updates of git-installed packages on windows
- * Lots of minor bug fixes
-
-### [2.0.0-alpha2] 2020-06-24
-
- * Added parallel installation of packages (requires OSX/Linux/WSL, and that `unzip` is present in PATH)
- * Added optimization of constraints by compiling them to PHP code, which should reduce CPU time of updates
- * Added handling of Ctrl-C on Windows for PHP 7.4+
- * Added better support for default branch names other than `master`
- * Added --format=summary flag to `license` command
- * Fixed issue in platform check when requiring ext-zend-opcache
- * Fixed inline aliases issues
- * Fixed git integration issue when signatures are set to be shown by default
-
-### [2.0.0-alpha1] 2020-06-03
-
- * Breaking: This is a major release and while we tried to keep things compatible for most users, you might want to have a look at the [UPGRADE](UPGRADE-2.0.md) guides
- * Many CPU and memory performance improvements
- * The update command is now much more deterministic as it does not take the already installed packages into account
- * Package installation now performs all network operations first before doing any changes on disk, to reduce the chances of ending up with a partially updated vendor dir
- * Partial updates and require/remove are now much faster as they only load the metadata required for the updated packages
- * Added a [platform-check step](doc/07-runtime.md#platform-check) when vendor/autoload.php gets initialized which checks the current PHP version/extensions match what is expected and fails hard otherwise. Can be disabled with the platform-check config option
- * Added a [`Composer\InstalledVersions`](doc/07-runtime.md#installed-versions) class which is autoloaded in every project and lets you check which packages/versions are present at runtime
- * Added a `composer-runtime-api` virtual package which you can require (as e.g. `^2.0`) to ensure things like the InstalledVersions class above are present. It will effectively force people to use Composer 2.x to install your project
- * Added support for parallel downloads of package metadata and zip files, this requires that the curl extension is present and we thus strongly recommend enabling curl
- * Added much clearer dependency resolution error reporting for common error cases
- * Added support for updating to a specific version with partial updates, as well as a [--with flag](doc/03-cli.md#update--u) to pass in temporary constraint overrides
- * Added support for TTY mode on Linux/OSX/WSL so that script handlers now run in interactive mode
- * Added `only`, `exclude` and `canonical` options to all repositories, see [repository priorities](https://getcomposer.org/repoprio) for details
- * Added support for lib-zip platform package
- * Added `pre-operations-exec` event to be fired before the packages get installed/upgraded/removed
- * Added `pre-pool-create` event to be fired before the package pool for the dependency solver is created, which lets you modify the list of packages going in
- * Added `post-file-download` event to be fired after package dist files are downloaded, which lets you do additional checks on the files
- * Added --locked flag to `show` command to see the packages from the composer.lock file
- * Added --unused flag to `remove` command to make sure any packages which are not needed anymore get removed
- * Added --dry-run flag to `require` and `remove` commands
- * Added --no-install flag to `update`, `require` and `remove` commands to disable the install step and only do the update step (composer.lock file update)
- * Added --with-dependencies and --with-all-dependencies flag aliases to `require` and `remove` commands for consistency with `update`
- * Added more info to `vendor/composer/installed.json`, a dev key stores whether dev requirements were installed, and every package now has an install-path key with its install location
- * Added COMPOSER_DISABLE_NETWORK which if set makes Composer do its best to run offline. This can be useful when you have poor connectivity or to do benchmarking without network jitter
- * Added --json and --merge flags to `config` command to allow editing complex `extra.*` values by using json as input
- * Added confirmation prompt when running Composer as superuser in interactive mode
- * Added --no-check-version to `validate` command to remove the warning in case the version is defined
- * Added --ignore-platform-req (without s) to all commands supporting --ignore-platform-reqs, which accepts a package name so you can ignore only specific platform requirements
- * Added support for wildcards (`*`) in classmap autoloader paths
- * Added support for configuring GitLab deploy tokens in addition to private tokens, see [gitlab-token](doc/06-config.md#gitlab-token)
- * Added support for package version guessing for require and init command to take all platform packages into account, not just php version
- * Fixed package ordering when autoloading and especially when loading plugins, to make sure dependencies are loaded before their dependents
- * Fixed suggest output being very spammy, it now is only one line long and shows more rarely
- * Fixed conflict rules like e.g. >=5 from matching dev-master, as it is not normalized to 9999999-dev internally anymore
-
### [1.10.22] 2021-04-27
* Security: Fixed command injection vulnerability in HgDriver/HgDownloader and hardened other VCS drivers and downloaders (GHSA-h5h8-pc6h-jvvx / CVE-2021-29472)
@@ -468,7 +146,7 @@
* Fixed archive command to persist file permissions inside the zip files
* Fixed init/require command to avoid suggesting packages which are already selected in the search results
* Fixed create-project UX issues
- * Fixed filemtime for `vendor/composer/*` files is now only changing when the files actually change
+ * Fixed filemtime for vendor/composer/* files is now only changing when the files actually change
* Fixed issues detecting docker environment with an active open_basedir
### [1.9.3] 2020-02-04
@@ -478,7 +156,7 @@
### [1.9.2] 2020-01-14
* Fixed minor git driver bugs
- * Fixed schema validation for version field to allow `dev-*` versions too
+ * Fixed schema validation for version field to allow dev-* versions too
* Fixed external processes' output being formatted even though it should not
* Fixed issue with path repositories when trying to install feature branches
@@ -779,7 +457,7 @@
* Fixed dist downloads from Bitbucket
* Fixed some regressions related to xdebug disabling
* Fixed `--minor-only` flag in `outdated` command
- * Fixed handling of config.platform.php which did not replace other `php-*` package's versions
+ * Fixed handling of config.platform.php which did not replace other php-* package's versions
### [1.3.0] - 2016-12-24
@@ -1151,7 +829,7 @@
### [1.0.0-alpha6] - 2012-10-23
* Schema: Added ability to pass additional options to repositories (i.e. ssh keys/client certificates to secure private repos)
- * Schema: Added a new `~` operator that should be preferred over `>=`, see https://getcomposer.org/doc/01-basic-usage.md#package-versions
+ * Schema: Added a new `~` operator that should be preferred over `>=`, see http://getcomposer.org/doc/01-basic-usage.md#package-versions
* Schema: Version constraints ` | [naderman.de](https://naderman.de)
-- Jordi Boggiano | [GitHub](https://github.com/Seldaek) | [Twitter](https://twitter.com/seldaek) | | [seld.be](https://seld.be)
+- Nils Adermann | [GitHub](https://github.com/naderman) | [Twitter](https://twitter.com/naderman) | | [naderman.de](http://naderman.de)
+- Jordi Boggiano | [GitHub](https://github.com/Seldaek) | [Twitter](https://twitter.com/seldaek) | | [seld.be](http://seld.be)
See also the list of [contributors](https://github.com/composer/composer/contributors) who participated in this project.
@@ -52,7 +54,7 @@ Please send any sensitive issue to [security@packagist.org](mailto:security@pack
License
-------
-Composer is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+Composer is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
Acknowledgments
---------------
diff --git a/app/vendor/composer/composer/UPGRADE-2.0.md b/app/vendor/composer/composer/UPGRADE-2.0.md
deleted file mode 100644
index 3e5878ea3..000000000
--- a/app/vendor/composer/composer/UPGRADE-2.0.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# Upgrade guides for Composer 1.x to 2.0
-
-## For composer CLI users
-
-- The new platform-check feature means that Composer checks the runtime PHP version and available extensions to ensure they match the project dependencies. If a mismatch is found, it exits with error details to make sure problems are not overlooked. To avoid issues when deploying to production it is recommended to run `composer check-platform-reqs` with the production PHP process as part of your build or deployment process.
-- If a package exists in a higher priority repository, it will now be entirely ignored in lower priority repositories. See [repository priorities](https://getcomposer.org/repoprio) for details.
-- Invalid PSR-0 / PSR-4 class configurations will not autoload anymore in optimized-autoloader mode, as per the warnings introduced in 1.10
-- On linux systems supporting the XDG Base Directory Specification, Composer will now prefer using XDG_CONFIG_DIR/composer over `~/.composer` if both are available (1.x used `~/.composer` first)
-- Package names now must comply to our [naming guidelines](doc/04-schema.md#name) or Composer will abort, as per the warnings introduced in 1.8.1
-- Deprecated --no-suggest flag as it is not needed anymore
-- PEAR support (repository, downloader, etc.) has been removed
-- `update` now lists changes to the lock file first (update step), and then the changes applied when installing the lock file to the vendor dir (install step)
-- `HTTPS_PROXY_REQUEST_FULLURI` if not specified will now default to false as this seems to work better in most environments
-- `dev-trunk`, `dev-master` and `dev-default` are no longer aliases for each other. The exact branch names are now preserved.
-
-## For integrators and plugin authors
-
-- composer-plugin-api has been bumped to 2.0.0 - you can detect which version of Composer you run via `PluginInterface::PLUGIN_API_VERSION`
-- `PluginInterface` added a deactivate (so plugin can stop whatever it is doing) and an uninstall (so the plugin can remove any files it created or do general cleanup) method.
-- Plugins implementing `EventSubscriberInterface` will be deregistered from the EventDispatcher automatically when being deactivated, nothing to do there.
-- `Pool` objects are now created via the `RepositorySet` class, you should use that in case you were using the `Pool` class directly.
-- Custom installers extending from LibraryInstaller should be aware that in Composer 2 it MAY return PromiseInterface instances when calling parent::install/update/uninstall/installCode/removeCode. See [composer/installers](https://github.com/composer/installers/commit/5006d0c28730ade233a8f42ec31ac68fb1c5c9bb) for an example of how to handle this best.
-- The `Composer\Installer` class changed quite a bit internally, but the inputs are almost the same:
- - `setAdditionalInstalledRepository` is now `setAdditionalFixedRepository`
- - `setUpdateWhitelist` is now `setUpdateAllowList`
- - `setWhitelistDependencies`, `setWhitelistTransitiveDependencies` and `setWhitelistAllDependencies` are now all rolled into `setUpdateAllowTransitiveDependencies` which takes one of the `Request::UPDATE_*` constants
- - `setSkipSuggest` is gone
-- `vendor/composer/installed.json` format changed:
- - packages are now wrapped into a `"packages"` top level key instead of the whole file being the package array
- - packages now contain an `"installed-path"` key which lists where they were installed
- - there is a top level `"dev"` key which stores whether dev requirements were installed or not
-- Removed `OperationInterface::getReason` as the data was not accurate. There is no replacement available.
-- `PreFileDownloadEvent` now receives an `HttpDownloader` instance instead of `RemoteFilesystem`, and that instance cannot be overridden by listeners anymore, you can however call setProcessedUrl or setCustomCacheKey.
-- `VersionSelector::findBestCandidate`'s third argument (phpVersion) was removed in favor of passing in a complete PlatformRepository instance into the constructor
-- `InitCommand::determineRequirements`'s fourth argument (phpVersion) should now receive a complete PlatformRepository instance or null if platform requirements are to be ignored
-- `IOInterface` now extends PSR-3's `LoggerInterface`, and has new `writeRaw` + `writeErrorRaw` methods
-- `RepositoryInterface` changes:
- - A new `loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags)` function was added for use during pool building
- - `search` now has a third `$type` argument
- - A new `getRepoName()` function was added to describe the repository
- - A new `getProviders()` function was added to list packages providing a given package's name
-- Removed `BaseRepository` abstract class
-- `DownloaderInterface` changes:
- - `download` now receives a third `$prevPackage` argument for updates
- - `download` should now only do network operations to prepare the package for installation but not actually install anything
- - `prepare` (do user prompts or any checks which need to happen to make sure that install/update/remove will most likely succeed), `install` (should do the non-network part that `download` used to do) and `cleanup` (cleaning up anything that may be left over) were added as new steps in the package install flow
- - All packages get first downloaded, then all together prepared, then all together installed/updated/uninstalled, then finally cleanup is called for all. Therefore for error recovery it is important to avoid failing during install/update/uninstall as much as possible, and risky things or user prompts should happen in the prepare step rather. In case of failure, cleanup() will be called so that changes can be undone as much as possible.
-- If you used `RemoteFilesystem` you probably should use `HttpDownloader` instead now
-- `PRE_DEPENDENCIES_SOLVING` and `POST_DEPENDENCIES_SOLVING` events have been removed, use the new `PRE_OPERATIONS_EXEC`, `PRE_POOL_CREATE` or other existing events instead or talk to us if you think you really need this. See below for more details.
-- The bundled composer/semver is now the 3.x range, see release notes for [2.0](https://github.com/composer/semver/releases/tag/2.0.0) and [3.0](https://github.com/composer/semver/releases/tag/3.0.0) for the minor breaking changes there
-- Run Composer with COMPOSER_DEBUG_EVENTS=1 set in the environment to show which events happen which might help you.
-
-### Detailed differences in event flow during dependency resolution, composer updates and installs
-
-#### Composer v1
-
-- Composer resolves dependencies (dispatching PRE/POST_DEPENDENCIES_SOLVING)
-- It then iterates over all packages one by one (dispatching PRE_PACKAGE_INSTALL/UPDATE/UNINSTALL, then PRE_FILE_DOWNLOAD if needed, then POST_PACKAGE_\*)
-- And finally writes the lock file at the end
-
-#### Composer v2
-
-The update and install process have been split up.
-
-Update does:
-
-- Composer resolves dependencies (dispatching PRE_POOL_CREATE)
-- It then writes the lock file and that's the end of the update
-
-Install then does:
-
-- Dispatches PRE_OPERATIONS_EXEC with the full list of operations to be executed
-- Downloads all the packages not in cache yet in parallel (dispatching PRE_FILE_DOWNLOAD for those not in cache yet)
-- It then iterates over all packages and executes updates/installs/uninstalls in parallel (dispatching PRE_PACKAGE_INSTALL/UPDATE/UNINSTALL then POST_PACKAGE_\* but one package started last may finish installing before another is done for example).
-
-## For Composer repository implementors
-
-Composer 2.0 adds support for a new Composer repository format.
-
-It is possible to build a repository which is compatible with both Composer v1 and v2, you keep everything you had and simply add the new fields in `packages.json`.
-
-Here are examples of the new values from packagist.org:
-
-### metadata-url
-
-`"metadata-url": "/p2/%package%.json",`
-
-This new metadata-url should serve all packages which are in the repository.
-
-- Whenever Composer looks for a package, it will replace `%package%` by the package name, and fetch that URL.
-- If dev stability is allowed for the package, it will also load the URL again with `$packageName~dev` (e.g. `/p2/foo/bar~dev.json` to look for `foo/bar`'s dev versions).
-- Caching is done via the use of If-Modified-Since header, so make sure you return Last-Modified headers and that they are accurate.
-- Any requested package which does not exist MUST return a 404 status code, which will indicate to Composer that this package does not exist in your repository. Make sure the 404 response is fast to avoid blocking Composer. Avoid redirects to alternative 404 pages.
-- The `foo/bar.json` and `foo/bar~dev.json` files containing package versions MUST contain only versions for the foo/bar package, as `{"packages":{"foo/bar":[ ... versions here ... ]}}`.
-- The array of versions can also optionally be minified using `Composer\Util\MetadataMinifier::minify()`. If you do that, you should add a `"minified": "composer/2.0"` key at the top level to indicate to Composer it must expand the version list back into the original data. See https://repo.packagist.org/p2/monolog/monolog.json for an example.
-
-If your repository only has a small number of packages, and you want to avoid the 404-requests, you can also specify an `"available-packages"` key in `packages.json` which should be an array with all the package names that your repository contain. Alternatively you can specify an `"available-package-patterns"` key which is an array of package name patterns (with `*` matching any string, e.g. `vendor/*` would make composer look up every matching package name in this repository).
-
-### providers-api
-
-`"providers-api": "https://packagist.org/providers/%package%.json",`
-
-The providers-api is optional, but if you implement it it should return packages which provide a given package name, but not the package which has that name. For example https://packagist.org/providers/monolog/monolog.json lists some package which have a "provide" rule for monolog/monolog, but it does not list monolog/monolog itself.
-
-### list
-
-This is also optional, it should accept an optional `?filter=xx` query param, which can contain `*` as wildcards matching any substring.
-
-It must return an array of package names as `{"packageNames": ["a/b", "c/d"]}`. See for example.
-
-It should return the names of package which names match the filter (or all names if no filter is present). Replace/provide rules should not be considered here.
diff --git a/app/vendor/composer/composer/bin/compile b/app/vendor/composer/composer/bin/compile
index f9156245f..a2720a95d 100755
--- a/app/vendor/composer/composer/bin/compile
+++ b/app/vendor/composer/composer/bin/compile
@@ -20,7 +20,7 @@ require __DIR__.'/../src/bootstrap.php';
use Composer\Compiler;
error_reporting(-1);
-ini_set('display_errors', '1');
+ini_set('display_errors', 1);
try {
$compiler = new Compiler();
diff --git a/app/vendor/composer/composer/bin/composer b/app/vendor/composer/composer/bin/composer
index 62c18974d..b7ab5318b 100755
--- a/app/vendor/composer/composer/bin/composer
+++ b/app/vendor/composer/composer/bin/composer
@@ -10,13 +10,11 @@ require __DIR__.'/../src/bootstrap.php';
use Composer\Console\Application;
use Composer\XdebugHandler\XdebugHandler;
-use Composer\Util\Platform;
-use Composer\Util\ErrorHandler;
error_reporting(-1);
// Restart without Xdebug
-$xdebug = new XdebugHandler('Composer');
+$xdebug = new XdebugHandler('Composer', '--ansi');
$xdebug->check();
unset($xdebug);
@@ -26,42 +24,38 @@ if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '4.0', '>=')) {
}
if (function_exists('ini_set')) {
- @ini_set('display_errors', '1');
+ @ini_set('display_errors', 1);
+
+ $memoryInBytes = function ($value) {
+ $unit = strtolower(substr($value, -1, 1));
+ $value = (int) $value;
+ switch($unit) {
+ case 'g':
+ $value *= 1024;
+ // no break (cumulative multiplier)
+ case 'm':
+ $value *= 1024;
+ // no break (cumulative multiplier)
+ case 'k':
+ $value *= 1024;
+ }
+
+ return $value;
+ };
+ $memoryLimit = trim(ini_get('memory_limit'));
+ // Increase memory_limit if it is lower than 1.5GB
+ if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
+ @ini_set('memory_limit', '1536M');
+ }
// Set user defined memory limit
if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
@ini_set('memory_limit', $memoryLimit);
- } else {
- $memoryInBytes = function ($value) {
- $unit = strtolower(substr($value, -1, 1));
- $value = (int) $value;
- switch($unit) {
- case 'g':
- $value *= 1024;
- // no break (cumulative multiplier)
- case 'm':
- $value *= 1024;
- // no break (cumulative multiplier)
- case 'k':
- $value *= 1024;
- }
-
- return $value;
- };
-
- $memoryLimit = trim(ini_get('memory_limit'));
- // Increase memory_limit if it is lower than 1.5GB
- if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
- @ini_set('memory_limit', '1536M');
- }
- unset($memoryInBytes);
}
- unset($memoryLimit);
+ unset($memoryInBytes, $memoryLimit);
}
-Platform::putEnv('COMPOSER_BINARY', realpath($_SERVER['argv'][0]));
-
-ErrorHandler::register();
+putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
// run the command application
$application = new Application();
diff --git a/app/vendor/composer/composer/composer.json b/app/vendor/composer/composer/composer.json
index 9225f2e5f..e0a3d64af 100644
--- a/app/vendor/composer/composer/composer.json
+++ b/app/vendor/composer/composer/composer.json
@@ -13,33 +13,34 @@
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
- "homepage": "https://www.naderman.de"
+ "homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
- "homepage": "https://seld.be"
+ "homepage": "http://seld.be"
}
],
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0",
"composer/ca-bundle": "^1.0",
- "composer/metadata-minifier": "^1.0",
- "composer/semver": "^3.0",
+ "composer/semver": "^1.0",
"composer/spdx-licenses": "^1.2",
- "composer/xdebug-handler": "^2.0",
- "justinrainbow/json-schema": "^5.2.11",
+ "composer/xdebug-handler": "^1.1",
+ "justinrainbow/json-schema": "^5.2.10",
"psr/log": "^1.0",
"seld/jsonlint": "^1.4",
"seld/phar-utils": "^1.0",
- "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
- "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
- "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
- "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
- "react/promise": "^1.2 || ^2.7"
+ "symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0",
+ "symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0",
+ "symfony/finder": "^2.7 || ^3.0 || ^4.0 || ^5.0",
+ "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0"
+ },
+ "conflict": {
+ "symfony/console": "2.8.38"
},
"require-dev": {
- "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0",
+ "symfony/phpunit-bridge": "^4.2",
"phpspec/prophecy": "^1.10"
},
"suggest": {
@@ -50,12 +51,11 @@
"config": {
"platform": {
"php": "5.3.9"
- },
- "platform-check": false
+ }
},
"extra": {
"branch-alias": {
- "dev-master": "2.1-dev"
+ "dev-master": "1.10-dev"
}
},
"autoload": {
@@ -65,36 +65,22 @@
},
"autoload-dev": {
"psr-4": {
- "Composer\\Test\\": "tests/Composer/Test",
- "Composer\\PHPStanRules\\": "phpstan/Rules/src",
- "Composer\\PHPStanRulesTests\\": "phpstan/Rules/tests"
- },
- "classmap": [
- "phpstan/Rules/tests/data"
- ]
+ "Composer\\Test\\": "tests/Composer/Test"
+ }
},
"bin": [
"bin/composer"
],
"scripts": {
"compile": "@php -dphar.readonly=0 bin/compile",
- "test": "simple-phpunit",
- "phpstan-setup": [
- "@composer config platform --unset",
- "@php composer.phar update",
- "@composer require --dev phpstan/phpstan:^0.12.93 phpstan/phpstan-phpunit:^0.12.17 phpunit/phpunit:^7.5.20 --with-all-dependencies",
- "git checkout composer.json composer.lock"
- ],
- "phpstan": "@php vendor/bin/phpstan analyse --configuration=phpstan/config.neon"
+ "test": "simple-phpunit"
},
"scripts-descriptions": {
"compile": "Compile composer.phar",
- "test": "Run all tests",
- "phpstan-setup": "Prepare environment to run PHPStan locally (must be run with PHP7.4)",
- "phpstan": "Runs PHPStan (after phpstan-setup was executed, must be run with PHP7.4)"
+ "test": "Run all tests"
},
"support": {
"issues": "https://github.com/composer/composer/issues",
- "irc": "ircs://irc.libera.chat:6697/composer"
+ "irc": "irc://irc.freenode.org/composer"
}
}
diff --git a/app/vendor/composer/composer/composer.lock b/app/vendor/composer/composer/composer.lock
index b953e70c9..816a15fce 100644
--- a/app/vendor/composer/composer/composer.lock
+++ b/app/vendor/composer/composer/composer.lock
@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "dfe550a024c0c2bb0784765e457968af",
+ "content-hash": "f572867898a016e14b08d0b15faedffb",
"packages": [
{
"name": "composer/ca-bundle",
- "version": "1.2.10",
+ "version": "1.2.9",
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
- "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8"
+ "reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8",
- "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/78a0e288fdcebf92aa2318a8d3656168da6ac1a5",
+ "reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5",
"shasum": ""
},
"require": {
@@ -64,7 +64,7 @@
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/ca-bundle/issues",
- "source": "https://github.com/composer/ca-bundle/tree/1.2.10"
+ "source": "https://github.com/composer/ca-bundle/tree/1.2.9"
},
"funding": [
{
@@ -80,102 +80,32 @@
"type": "tidelift"
}
],
- "time": "2021-06-07T13:58:28+00:00"
- },
- {
- "name": "composer/metadata-minifier",
- "version": "1.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/composer/metadata-minifier.git",
- "reference": "c549d23829536f0d0e984aaabbf02af91f443207"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207",
- "reference": "c549d23829536f0d0e984aaabbf02af91f443207",
- "shasum": ""
- },
- "require": {
- "php": "^5.3.2 || ^7.0 || ^8.0"
- },
- "require-dev": {
- "composer/composer": "^2",
- "phpstan/phpstan": "^0.12.55",
- "symfony/phpunit-bridge": "^4.2 || ^5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Composer\\MetadataMinifier\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
- }
- ],
- "description": "Small utility library that handles metadata minification and expansion.",
- "keywords": [
- "composer",
- "compression"
- ],
- "support": {
- "issues": "https://github.com/composer/metadata-minifier/issues",
- "source": "https://github.com/composer/metadata-minifier/tree/1.0.0"
- },
- "funding": [
- {
- "url": "https://packagist.com",
- "type": "custom"
- },
- {
- "url": "https://github.com/composer",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/composer/composer",
- "type": "tidelift"
- }
- ],
- "time": "2021-04-07T13:37:33+00:00"
+ "time": "2021-01-12T12:10:35+00:00"
},
{
"name": "composer/semver",
- "version": "3.2.5",
+ "version": "1.7.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
- "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9"
+ "reference": "647490bbcaf7fc4891c58f47b825eb99d19c377a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9",
- "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9",
+ "url": "https://api.github.com/repos/composer/semver/zipball/647490bbcaf7fc4891c58f47b825eb99d19c377a",
+ "reference": "647490bbcaf7fc4891c58f47b825eb99d19c377a",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
- "phpstan/phpstan": "^0.12.54",
- "symfony/phpunit-bridge": "^4.2 || ^5"
+ "phpunit/phpunit": "^4.5 || ^5.0.5"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.x-dev"
+ "dev-master": "1.x-dev"
}
},
"autoload": {
@@ -211,11 +141,6 @@
"validation",
"versioning"
],
- "support": {
- "irc": "irc://irc.freenode.org/composer",
- "issues": "https://github.com/composer/semver/issues",
- "source": "https://github.com/composer/semver/tree/3.2.5"
- },
"funding": [
{
"url": "https://packagist.com",
@@ -230,7 +155,7 @@
"type": "tidelift"
}
],
- "time": "2021-05-24T12:41:47+00:00"
+ "time": "2020-12-03T15:47:16+00:00"
},
{
"name": "composer/spdx-licenses",
@@ -313,21 +238,21 @@
},
{
"name": "composer/xdebug-handler",
- "version": "2.0.2",
+ "version": "1.4.6",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
- "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339"
+ "reference": "f27e06cd9675801df441b3656569b328e04aa37c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339",
- "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f27e06cd9675801df441b3656569b328e04aa37c",
+ "reference": "f27e06cd9675801df441b3656569b328e04aa37c",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0",
- "psr/log": "^1 || ^2 || ^3"
+ "psr/log": "^1.0"
},
"require-dev": {
"phpstan/phpstan": "^0.12.55",
@@ -354,11 +279,6 @@
"Xdebug",
"performance"
],
- "support": {
- "irc": "irc://irc.freenode.org/composer",
- "issues": "https://github.com/composer/xdebug-handler/issues",
- "source": "https://github.com/composer/xdebug-handler/tree/2.0.2"
- },
"funding": [
{
"url": "https://packagist.com",
@@ -373,20 +293,20 @@
"type": "tidelift"
}
],
- "time": "2021-07-31T17:03:58+00:00"
+ "time": "2021-03-25T17:01:18+00:00"
},
{
"name": "justinrainbow/json-schema",
- "version": "5.2.11",
+ "version": "5.2.10",
"source": {
"type": "git",
"url": "https://github.com/justinrainbow/json-schema.git",
- "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa"
+ "reference": "2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ab6744b7296ded80f8cc4f9509abbff393399aa",
- "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa",
+ "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b",
+ "reference": "2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b",
"shasum": ""
},
"require": {
@@ -441,22 +361,22 @@
],
"support": {
"issues": "https://github.com/justinrainbow/json-schema/issues",
- "source": "https://github.com/justinrainbow/json-schema/tree/5.2.11"
+ "source": "https://github.com/justinrainbow/json-schema/tree/5.2.10"
},
- "time": "2021-07-22T09:24:00+00:00"
+ "time": "2020-05-27T16:41:55+00:00"
},
{
"name": "psr/log",
- "version": "1.1.4",
+ "version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
+ "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
- "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
+ "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
"shasum": ""
},
"require": {
@@ -480,7 +400,7 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "https://www.php-fig.org/"
+ "homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
@@ -491,57 +411,9 @@
"psr-3"
],
"support": {
- "source": "https://github.com/php-fig/log/tree/1.1.4"
- },
- "time": "2021-05-03T11:20:27+00:00"
- },
- {
- "name": "react/promise",
- "version": "v1.2.1",
- "source": {
- "type": "git",
- "url": "https://github.com/reactphp/promise.git",
- "reference": "eefff597e67ff66b719f8171480add3c91474a1e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/reactphp/promise/zipball/eefff597e67ff66b719f8171480add3c91474a1e",
- "reference": "eefff597e67ff66b719f8171480add3c91474a1e",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.1-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "React\\Promise": "src/"
- },
- "files": [
- "src/React/Promise/functions_include.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jan Sorgalla",
- "email": "jsorgalla@gmail.com"
- }
- ],
- "description": "A lightweight implementation of CommonJS Promises/A for PHP",
- "support": {
- "issues": "https://github.com/reactphp/promise/issues",
- "source": "https://github.com/reactphp/promise/tree/1.0"
+ "source": "https://github.com/php-fig/log/tree/1.1.3"
},
- "time": "2016-03-07T13:46:50+00:00"
+ "time": "2020-03-23T09:12:05+00:00"
},
{
"name": "seld/jsonlint",
@@ -608,16 +480,16 @@
},
{
"name": "seld/phar-utils",
- "version": "1.1.2",
+ "version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/phar-utils.git",
- "reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0"
+ "reference": "8674b1d84ffb47cc59a101f5d5a3b61e87d23796"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/749042a2315705d2dfbbc59234dd9ceb22bf3ff0",
- "reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0",
+ "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/8674b1d84ffb47cc59a101f5d5a3b61e87d23796",
+ "reference": "8674b1d84ffb47cc59a101f5d5a3b61e87d23796",
"shasum": ""
},
"require": {
@@ -650,9 +522,9 @@
],
"support": {
"issues": "https://github.com/Seldaek/phar-utils/issues",
- "source": "https://github.com/Seldaek/phar-utils/tree/1.1.2"
+ "source": "https://github.com/Seldaek/phar-utils/tree/master"
},
- "time": "2021-08-19T21:01:38+00:00"
+ "time": "2020-07-07T18:42:57+00:00"
},
{
"name": "symfony/console",
@@ -1607,5 +1479,5 @@
"platform-overrides": {
"php": "5.3.9"
},
- "plugin-api-version": "2.1.0"
+ "plugin-api-version": "1.1.0"
}
diff --git a/app/vendor/composer/composer/doc/00-intro.md b/app/vendor/composer/composer/doc/00-intro.md
index 8afd60090..a6cf10d71 100644
--- a/app/vendor/composer/composer/doc/00-intro.md
+++ b/app/vendor/composer/composer/doc/00-intro.md
@@ -9,7 +9,7 @@ for you.
Composer is **not** a package manager in the same sense as Yum or Apt are. Yes,
it deals with "packages" or libraries, but it manages them on a per-project
basis, installing them in a directory (e.g. `vendor`) inside your project. By
-default, it does not install anything globally. Thus, it is a dependency
+default it does not install anything globally. Thus, it is a dependency
manager. It does however support a "global" project for convenience via the
[global](03-cli.md#global) command.
@@ -155,7 +155,7 @@ Close your current terminal. Test usage with a new terminal:
```sh
C:\Users\username>composer -V
-Composer version 2.0.12 2021-04-01 10:14:59
+Composer version 1.0.0 2016-01-10 20:34:53
```
## Using Composer
diff --git a/app/vendor/composer/composer/doc/01-basic-usage.md b/app/vendor/composer/composer/doc/01-basic-usage.md
index 4ccc50965..cbdd3ebb7 100644
--- a/app/vendor/composer/composer/doc/01-basic-usage.md
+++ b/app/vendor/composer/composer/doc/01-basic-usage.md
@@ -13,21 +13,18 @@ a logging library. If you have not yet installed Composer, refer to the
To start using Composer in your project, all you need is a `composer.json`
file. This file describes the dependencies of your project and may contain
-other metadata as well. It typically should go in the top-most directory of
-your project/VCS repository. You can technically run Composer anywhere but
-if you want to publish a package to Packagist.org, it will have to be able
-to find the file at the top of your VCS repository.
+other metadata as well.
### The `require` key
-The first thing you specify in `composer.json` is the
+The first (and often only) thing you specify in `composer.json` is the
[`require`](04-schema.md#require) key. You are telling Composer which
packages your project depends on.
```json
{
"require": {
- "monolog/monolog": "2.0.*"
+ "monolog/monolog": "1.0.*"
}
}
```
@@ -38,11 +35,11 @@ As you can see, [`require`](04-schema.md#require) takes an object that maps
Composer uses this information to search for the right set of files in package
"repositories" that you register using the [`repositories`](04-schema.md#repositories)
-key, or in [Packagist.org](https://packagist.org), the default package repository.
-In the above example, since no other repository has been registered in the
-`composer.json` file, it is assumed that the `monolog/monolog` package is registered
-on Packagist.org. (See more about Packagist [below](#packagist), or read more
-about repositories [here](05-repositories.md)).
+key, or in Packagist, the default package repository. In the above example,
+since no other repository has been registered in the `composer.json` file, it is
+assumed that the `monolog/monolog` package is registered on Packagist. (See more
+about Packagist [below](#packagist), or read more about repositories
+[here](05-repositories.md)).
### Package names
@@ -59,9 +56,9 @@ you to require certain versions of server software. See
### Package version constraints
In our example, we are requesting the Monolog package with the version constraint
-[`2.0.*`](https://semver.mwl.be/#?package=monolog%2Fmonolog&version=2.0.*).
-This means any version in the `2.0` development branch, or any version that is
-greater than or equal to 2.0 and less than 2.1 (`>=2.0 <2.1`).
+[`1.0.*`](https://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*).
+This means any version in the `1.0` development branch, or any version that is
+greater than or equal to 1.0 and less than 1.1 (`>=1.0 <1.1`).
Please read [versions](articles/versions.md) for more in-depth information on
versions, how versions relate to each other, and on version constraints.
@@ -71,16 +68,16 @@ versions, how versions relate to each other, and on version constraints.
> and searches for it in any repositories that you have registered using the
> [`repositories`](04-schema.md#repositories) key. If you have not registered
> any extra repositories, or it does not find a package with that name in the
-> repositories you have specified, it falls back to Packagist.org (more [below](#packagist)).
+> repositories you have specified, it falls back to Packagist (more [below](#packagist)).
>
-> When Composer finds the right package, either in Packagist.org or in a repo you have specified,
+> When Composer finds the right package, either in Packagist or in a repo you have specified,
> it then uses the versioning features of the package's VCS (i.e., branches and tags)
> to attempt to find the best match for the version constraint you have specified. Be sure to read
> about versions and package resolution in the [versions article](articles/versions.md).
> **Note:** If you are trying to require a package but Composer throws an error
> regarding package stability, the version you have specified may not meet your
-> default minimum stability requirements. By default, only stable releases are taken
+> default minimum stability requirements. By default only stable releases are taken
> into consideration when searching for valid package versions in your VCS.
>
> You might run into this if you are trying to require dev, alpha, beta, or RC
@@ -89,51 +86,40 @@ versions, how versions relate to each other, and on version constraints.
## Installing dependencies
-To initially install the defined dependencies for your project, you should run the
-[`update`](03-cli.md#update-u) command.
+To install the defined dependencies for your project, run the
+[`install`](03-cli.md#install) command.
```sh
-php composer.phar update
+php composer.phar install
```
-This will make Composer do two things:
+When you run this command, one of two things may happen:
-- It resolves all dependencies listed in your `composer.json` file and writes all of the
- packages and their exact versions to the `composer.lock` file, locking the project to
- those specific versions. You should commit the `composer.lock` file to your project repo
- so that all people working on the project are locked to the same versions of dependencies
- (more below). This is the main role of the `update` command.
-- It then implicitly runs the [`install`](03-cli.md#install-i) command. This will download
- the dependencies' files into the `vendor` directory in your project. (The `vendor`
- directory is the conventional location for all third-party code in a project). In our
- example from above, you would end up with the Monolog source files in
- `vendor/monolog/monolog/`. As Monolog has a dependency on `psr/log`, that package's files
- can also be found inside `vendor/`.
+### Installing without `composer.lock`
+
+If you have never run the command before and there is also no `composer.lock` file present,
+Composer resolves all dependencies listed in your `composer.json` file and downloads
+the latest version of their files into the `vendor` directory in your project. (The `vendor`
+directory is the conventional location for all third-party code in a project). In our
+example from above, you would end up with the Monolog source files in
+`vendor/monolog/monolog/`. If Monolog listed any dependencies, those would also be in
+folders under `vendor/`.
> **Tip:** If you are using git for your project, you probably want to add
> `vendor` in your `.gitignore`. You really don't want to add all of that
> third-party code to your versioned repository.
-### Commit your `composer.lock` file to version control
-
-Committing this file to version control is important because it will cause anyone
-who sets up the project to use the exact same
-versions of the dependencies that you are using. Your CI server, production
-machines, other developers in your team, everything and everyone runs on the
-same dependencies, which mitigates the potential for bugs affecting only some
-parts of the deployments. Even if you develop alone, in six months when
-reinstalling the project you can feel confident the dependencies installed are
-still working even if your dependencies released many new versions since then.
-(See note below about using the `update` command.)
-
-> **Note:** For libraries it is not necessary to commit the lock
-> file, see also: [Libraries - Lock file](02-libraries.md#lock-file).
+When Composer has finished installing, it writes all of the packages and the exact versions
+of them that it downloaded to the `composer.lock` file, locking the project to those specific
+versions. You should commit the `composer.lock` file to your project repo so that all people
+working on the project are locked to the same versions of dependencies (more below).
-### Installing from `composer.lock`
+### Installing with `composer.lock`
-If there is already a `composer.lock` file in the project folder, it means either
-you ran the `update` command before, or someone else on the project ran the `update`
-command and committed the `composer.lock` file to the project (which is good).
+This brings us to the second scenario. If there is already a `composer.lock` file as well as a
+`composer.json` file when you run `composer install`, it means either you ran the
+`install` command before, or someone else on the project ran the `install` command and
+committed the `composer.lock` file to the project (which is good).
Either way, running `install` when a `composer.lock` file is present resolves and installs
all dependencies that you listed in `composer.json`, but Composer uses the exact versions listed
@@ -144,21 +130,26 @@ working on your project. As a result you will have all dependencies requested by
the file was created). This is by design, it ensures that your project does not break because of
unexpected changes in dependencies.
-So after fetching new changes from your VCS repository it is recommended to run
-a Composer `install` to make sure the vendor directory is up in sync with your
-`composer.lock` file.
+### Commit your `composer.lock` file to version control
-```sh
-php composer.phar install
-```
+Committing this file to VC is important because it will cause anyone who sets
+up the project to use the exact same
+versions of the dependencies that you are using. Your CI server, production
+machines, other developers in your team, everything and everyone runs on the
+same dependencies, which mitigates the potential for bugs affecting only some
+parts of the deployments. Even if you develop alone, in six months when
+reinstalling the project you can feel confident the dependencies installed are
+still working even if your dependencies released many new versions since then.
+(See note below about using the `update` command.)
## Updating dependencies to their latest versions
As mentioned above, the `composer.lock` file prevents you from automatically getting
the latest versions of your dependencies. To update to the latest versions, use the
-[`update`](03-cli.md#update-u) command. This will fetch the latest matching
+[`update`](03-cli.md#update) command. This will fetch the latest matching
versions (according to your `composer.json` file) and update the lock file
-with the new versions.
+with the new versions. (This is equivalent to deleting the `composer.lock` file
+and running `install` again.)
```sh
php composer.phar update
@@ -168,21 +159,24 @@ php composer.phar update
> if the `composer.lock` has not been updated since changes were made to the
> `composer.json` that might affect dependency resolution.
-If you only want to install, upgrade or remove one dependency, you can explicitly list it as an argument:
+If you only want to install or update one dependency, you can allow them:
```sh
php composer.phar update monolog/monolog [...]
```
+> **Note:** For libraries it is not necessary to commit the lock
+> file, see also: [Libraries - Lock file](02-libraries.md#lock-file).
+
## Packagist
-[Packagist.org](https://packagist.org/) is the main Composer repository. A Composer
+[Packagist](https://packagist.org/) is the main Composer repository. A Composer
repository is basically a package source: a place where you can get packages
from. Packagist aims to be the central repository that everybody uses. This
means that you can automatically `require` any package that is available there,
without further specifying where Composer should look for the package.
-If you go to the [Packagist.org website](https://packagist.org/),
+If you go to the [Packagist website](https://packagist.org/) (packagist.org),
you can browse and search for packages.
Any open source project using Composer is recommended to publish their packages
@@ -225,7 +219,7 @@ require __DIR__ . '/vendor/autoload.php';
$log = new Monolog\Logger('name');
$log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING));
-$log->warning('Foo');
+$log->addWarning('Foo');
```
You can even add your own code to the autoloader by adding an
@@ -239,7 +233,7 @@ You can even add your own code to the autoloader by adding an
}
```
-Composer will register a [PSR-4](https://www.php-fig.org/psr/psr-4/) autoloader
+Composer will register a [PSR-4](http://www.php-fig.org/psr/psr-4/) autoloader
for the `Acme` namespace.
You define a mapping from namespaces to directories. The `src` directory would
diff --git a/app/vendor/composer/composer/doc/02-libraries.md b/app/vendor/composer/composer/doc/02-libraries.md
index c731f105d..6eb3f2fde 100644
--- a/app/vendor/composer/composer/doc/02-libraries.md
+++ b/app/vendor/composer/composer/doc/02-libraries.md
@@ -26,14 +26,14 @@ In this case the project name is `acme/hello-world`, where `acme` is the vendor
name. Supplying a vendor name is mandatory.
> **Note:** If you don't know what to use as a vendor name, your GitHub
-> username is usually a good bet. Package names must be lowercase, and the
-> convention is to use dashes for word separation.
+> username is usually a good bet. While package names are case insensitive, the
+> convention is all lowercase and dashes for word separation.
## Library Versioning
In the vast majority of cases, you will be maintaining your library using some
sort of version control system like git, svn, hg or fossil. In these cases,
-Composer infers versions from your VCS, and you **should not** specify a version
+Composer infers versions from your VCS and you **should not** specify a version
in your `composer.json` file. (See the [Versions article](articles/versions.md)
to learn about how Composer uses VCS branches and tags to resolve version
constraints.)
@@ -69,7 +69,7 @@ can help your team to always test against the same dependency versions.
However, this lock file will not have any effect on other projects that depend
on it. It only has an effect on the main project.
-If you do not want to commit the lock file, and you are using git, add it to
+If you do not want to commit the lock file and you are using git, add it to
the `.gitignore`.
## Publishing to a VCS
diff --git a/app/vendor/composer/composer/doc/03-cli.md b/app/vendor/composer/composer/doc/03-cli.md
index c35eabb61..88d21c01d 100644
--- a/app/vendor/composer/composer/doc/03-cli.md
+++ b/app/vendor/composer/composer/doc/03-cli.md
@@ -65,7 +65,6 @@ php composer.phar init
the list of requires. Every repository can be either an HTTP URL pointing
to a `composer` repository or a JSON string which similar to what the
[repositories](04-schema.md#repositories) key accepts.
-* **--autoload (-a):** Add a PSR-4 autoload mapping to the composer.json. Automatically maps your package's namespace to the provided directory. (Expects a relative path, e.g. src/) See also [PSR-4 autoload](04-schema.md#psr-4).
## install / i
@@ -85,14 +84,17 @@ resolution.
### Options
-* **--prefer-install:** There are two ways of downloading a package: `source`
- and `dist`. Composer uses `dist` by default. If you pass
- `--prefer-install=source` (or `--prefer-source`) Composer will install from
- `source` if there is one. This is useful if you want to make a bugfix to a
- project and get a local git clone of the dependency directly.
- To get the legacy behavior where Composer use `source` automatically for dev
- versions of packages, use `--prefer-install=auto`. See also [config.preferred-install](06-config.md#preferred-install).
- Passing this flag will override the config value.
+* **--prefer-source:** There are two ways of downloading a package: `source`
+ and `dist`. For stable versions Composer will use the `dist` by default.
+ The `source` is a version control repository. If `--prefer-source` is
+ enabled, Composer will install from `source` if there is one. This is
+ useful if you want to make a bugfix to a project and get a local git
+ clone of the dependency directly.
+* **--prefer-dist:** Reverse of `--prefer-source`, Composer will install
+ from `dist` if possible. This can speed up installs substantially on build
+ servers and other use cases where you typically do not run updates of the
+ vendors. It is also a way to circumvent problems with git if you do not
+ have a proper setup.
* **--dry-run:** If you want to run through an installation without actually
installing a package, you can use `--dry-run`. This will simulate the
installation and show you what would happen.
@@ -103,21 +105,16 @@ resolution.
* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
* **--no-progress:** Removes the progress display that can mess with some
terminals or scripts which don't handle backspace characters.
+* **--no-suggest:** Skips suggested packages in the output.
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
autoloader. This is recommended especially for production, but can take
a bit of time to run so it is currently not done by default.
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize-autoloader`.
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
-* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
- Implicitly enables `--apcu-autoloader`.
-* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
- `lib-*` and `ext-*`) and force the installation even if the local machine does
- not fulfill these.
- See also the [`platform`](06-config.md#platform) config option.
-* **--ignore-platform-req:** ignore a specific platform requirement(`php`,
- `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
- does not fulfill it.
+* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
+ requirements and force the installation even if the local machine does not
+ fulfill these. See also the [`platform`](06-config.md#platform) config option.
## update / u
@@ -145,64 +142,31 @@ You can also use wildcards to update a bunch of packages at once:
php composer.phar update "vendor/*"
```
-
-If you want to downgrade a package to a specific version without changing your
-composer.json you can use `--with` and provide a custom version constraint:
-
-```sh
-php composer.phar update --with vendor/package:2.0.1
-```
-
-The custom constraint has to be a subset of the existing constraint you have,
-and this feature is only available for your root package dependencies.
-
-If you only want to update the package(s) for which you provide custom constraints
-using `--with`, you can skip `--with` and just use constraints with the partial
-update syntax:
-
-```sh
-php composer.phar update vendor/package:2.0.1 vendor/package2:3.0.*
-```
-
-
### Options
-* **--prefer-install:** There are two ways of downloading a package: `source`
- and `dist`. Composer uses `dist` by default. If you pass
- `--prefer-install=source` (or `--prefer-source`) Composer will install from
- `source` if there is one. This is useful if you want to make a bugfix to a
- project and get a local git clone of the dependency directly.
- To get the legacy behavior where Composer use `source` automatically for dev
- versions of packages, use `--prefer-install=auto`. See also [config.preferred-install](06-config.md#preferred-install).
- Passing this flag will override the config value.
+* **--prefer-source:** Install packages from `source` when available.
+* **--prefer-dist:** Install packages from `dist` when available.
* **--dry-run:** Simulate the command without actually doing anything.
* **--dev:** Install packages listed in `require-dev` (this is the default behavior).
* **--no-dev:** Skip installing packages listed in `require-dev`. The autoloader generation skips the `autoload-dev` rules.
-* **--no-install:** Does not run the install step after updating the composer.lock file.
* **--lock:** Only updates the lock file hash to suppress warning about the
lock file being out of date.
-* **--with:** Temporary version constraint to add, e.g. foo/bar:1.0.0 or foo/bar=1.0.0
* **--no-autoloader:** Skips autoloader generation.
* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
* **--no-progress:** Removes the progress display that can mess with some
terminals or scripts which don't handle backspace characters.
-* **--with-dependencies (-w):** Update also dependencies of packages in the argument list, except those which are root requirements.
-* **--with-all-dependencies (-W):** Update also dependencies of packages in the argument list, including those which are root requirements.
+* **--no-suggest:** Skips suggested packages in the output.
+* **--with-dependencies:** Add also dependencies of allowed packages to the allow list, except those that are root requirements.
+* **--with-all-dependencies:** Add also all dependencies of allowed packages to the allow list, including those that are root requirements.
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
autoloader. This is recommended especially for production, but can take
- a bit of time to run, so it is currently not done by default.
+ a bit of time to run so it is currently not done by default.
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize-autoloader`.
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
-* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
- Implicitly enables `--apcu-autoloader`.
-* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
- `lib-*` and `ext-*`) and force the installation even if the local machine does
- not fulfill these.
- See also the [`platform`](06-config.md#platform) config option.
-* **--ignore-platform-req:** ignore a specific platform requirement(`php`,
- `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
- does not fulfill it.
+* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
+ requirements and force the installation even if the local machine does not
+ fulfill these. See also the [`platform`](06-config.md#platform) config option.
* **--prefer-stable:** Prefer stable versions of dependencies.
* **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal
versions of requirements, generally used with `--prefer-stable`.
@@ -235,42 +199,29 @@ If you do not specify a package, composer will prompt you to search for a packag
### Options
* **--dev:** Add packages to `require-dev`.
-* **--dry-run:** Simulate the command without actually doing anything.
-* **--prefer-install:** There are two ways of downloading a package: `source`
- and `dist`. Composer uses `dist` by default. If you pass
- `--prefer-install=source` (or `--prefer-source`) Composer will install from
- `source` if there is one. This is useful if you want to make a bugfix to a
- project and get a local git clone of the dependency directly.
- To get the legacy behavior where Composer use `source` automatically for dev
- versions of packages, use `--prefer-install=auto`. See also [config.preferred-install](06-config.md#preferred-install).
- Passing this flag will override the config value.
+* **--prefer-source:** Install packages from `source` when available.
+* **--prefer-dist:** Install packages from `dist` when available.
* **--no-progress:** Removes the progress display that can mess with some
terminals or scripts which don't handle backspace characters.
-* **--no-update:** Disables the automatic update of the dependencies (implies --no-install).
-* **--no-install:** Does not run the install step after updating the composer.lock file.
+* **--no-suggest:** Skips suggested packages in the output.
+* **--no-update:** Disables the automatic update of the dependencies.
* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
* **--update-no-dev:** Run the dependency update with the `--no-dev` option.
-* **--update-with-dependencies (-w):** Also update dependencies of the newly required packages, except those that are root requirements.
-* **--update-with-all-dependencies (-W):** Also update dependencies of the newly required packages, including those that are root requirements.
-* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
- `lib-*` and `ext-*`) and force the installation even if the local machine does
- not fulfill these.
- See also the [`platform`](06-config.md#platform) config option.
-* **--ignore-platform-req:** ignore a specific platform requirement(`php`,
- `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
- does not fulfill it.
+* **--update-with-dependencies:** Also update dependencies of the newly required packages, except those that are root requirements.
+* **--update-with-all-dependencies:** Also update dependencies of the newly required packages, including those that are root requirements.
+* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
+ requirements and force the installation even if the local machine does not
+ fulfill these. See also the [`platform`](06-config.md#platform) config option.
* **--prefer-stable:** Prefer stable versions of dependencies.
* **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal
versions of requirements, generally used with `--prefer-stable`.
* **--sort-packages:** Keep packages sorted in `composer.json`.
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to
get a faster autoloader. This is recommended especially for production, but
- can take a bit of time to run, so it is currently not done by default.
+ can take a bit of time to run so it is currently not done by default.
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize-autoloader`.
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
-* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
- Implicitly enables `--apcu-autoloader`.
## remove
@@ -286,79 +237,21 @@ uninstalled.
### Options
* **--dev:** Remove packages from `require-dev`.
-* **--dry-run:** Simulate the command without actually doing anything.
* **--no-progress:** Removes the progress display that can mess with some
terminals or scripts which don't handle backspace characters.
-* **--no-update:** Disables the automatic update of the dependencies (implies --no-install).
-* **--no-install:** Does not run the install step after updating the composer.lock file.
+* **--no-update:** Disables the automatic update of the dependencies.
* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
* **--update-no-dev:** Run the dependency update with the --no-dev option.
-* **--update-with-dependencies (-w):** Also update dependencies of the removed packages.
- (Deprecated, is now default behavior)
-* **--update-with-all-dependencies (-W):** Allows all inherited dependencies to be updated,
- including those that are root requirements.
-* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
- `lib-*` and `ext-*`) and force the installation even if the local machine does
- not fulfill these.
- See also the [`platform`](06-config.md#platform) config option.
-* **--ignore-platform-req:** ignore a specific platform requirement(`php`,
- `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
- does not fulfill it.
+* **--update-with-dependencies:** Also update dependencies of the removed packages.
+* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
+ requirements and force the installation even if the local machine does not
+ fulfill these. See also the [`platform`](06-config.md#platform) config option.
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to
get a faster autoloader. This is recommended especially for production, but
can take a bit of time to run so it is currently not done by default.
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize-autoloader`.
* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
-* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
- Implicitly enables `--apcu-autoloader`.
-
-## reinstall
-
-The `reinstall` command looks up installed packages by name,
-uninstalls them and reinstalls them. This lets you do a clean install
-of a package if you messed with its files, or if you wish to change
-the installation type using --prefer-install.
-
-```sh
-php composer.phar reinstall acme/foo acme/bar
-```
-
-You can specify more than one package name to reinstall, or use a
-wildcard to select several packages at once:
-
-```sh
-php composer.phar reinstall "acme/*"
-```
-
-### Options
-
-* **--prefer-install:** There are two ways of downloading a package: `source`
- and `dist`. Composer uses `dist` by default. If you pass
- `--prefer-install=source` (or `--prefer-source`) Composer will install from
- `source` if there is one. This is useful if you want to make a bugfix to a
- project and get a local git clone of the dependency directly.
- To get the legacy behavior where Composer use `source` automatically for dev
- versions of packages, use `--prefer-install=auto`. See also [config.preferred-install](06-config.md#preferred-install).
- Passing this flag will override the config value.
-* **--no-autoloader:** Skips autoloader generation.
-* **--no-scripts:** Skips execution of scripts defined in `composer.json`.
-* **--no-progress:** Removes the progress display that can mess with some
- terminals or scripts which don't handle backspace characters.
-* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
- autoloader. This is recommended especially for production, but can take
- a bit of time to run so it is currently not done by default.
-* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
- Implicitly enables `--optimize-autoloader`.
-* **--apcu-autoloader:** Use APCu to cache found/not-found classes.
-* **--apcu-autoloader-prefix:** Use a custom prefix for the APCu autoloader cache.
- Implicitly enables `--apcu-autoloader`.
-* **--ignore-platform-reqs:** ignore all platform requirements. This only
- has an effect in the context of the autoloader generation for the
- reinstall command.
-* **--ignore-platform-req:** ignore a specific platform requirement. This only
- has an effect in the context of the autoloader generation for the
- reinstall command.
## check-platform-reqs
@@ -416,11 +309,6 @@ You can also search for more than one term by passing multiple arguments.
* **--only-name (-N):** Search only in name.
* **--type (-t):** Search for a specific package type.
-* **--format (-f):** Lets you pick between text (default) or json output format.
- Note that in the json, only the name and description keys are guaranteed to be
- present. The rest (`url`, `repository`, `downloads` and `favers`) are available
- for Packagist.org search results and other repositories may return more or less
- data.
## show
@@ -471,7 +359,6 @@ php composer.phar show monolog/monolog 1.0.2
* **--all :** List all packages available in all your repositories.
* **--installed (-i):** List the packages that are installed (this is enabled by default, and deprecated).
-* **--locked:** List the locked packages from composer.lock.
* **--platform (-p):** List only platform packages (php & extensions).
* **--available (-a):** List available packages only.
* **--self (-s):** List the root package info.
@@ -480,7 +367,6 @@ php composer.phar show monolog/monolog 1.0.2
* **--tree (-t):** List your dependencies as a tree. If you pass a package name it will show the dependency tree for that package.
* **--latest (-l):** List all installed packages including their latest version.
* **--outdated (-o):** Implies --latest, but this lists *only* packages that have a newer version available.
-* **--no-dev:** Filters dev dependencies from the package list.
* **--minor-only (-m):** Use with --latest. Only shows packages that have minor SemVer-compatible updates.
* **--direct (-D):** Restricts the list of packages to your direct dependencies.
* **--strict:** Return a non-zero exit code when there are outdated packages.
@@ -495,7 +381,7 @@ including their current and latest versions. This is basically an alias for
The color coding is as such:
- **green (=)**: Dependency is in the latest version and is up to date.
-- **yellow (`~`)**: Dependency has a new version available that includes backwards compatibility breaks according to semver, so upgrade when
+- **yellow (~)**: Dependency has a new version available that includes backwards compatibility breaks according to semver, so upgrade when
you can but it may involve work.
- **red (!)**: Dependency has a new version that is semver-compatible and you should upgrade it.
@@ -506,8 +392,6 @@ The color coding is as such:
* **--strict:** Returns non-zero exit code if any package is outdated.
* **--minor-only (-m):** Only shows packages that have minor SemVer-compatible updates.
* **--format (-f):** Lets you pick between text (default) or json output format.
-* **--no-dev:** Do not show outdated dev dependencies.
-* **--locked:** Shows updates for packages from the lock file, regardless of what is currently in vendor dir.
## browse / home
@@ -525,29 +409,22 @@ Lists all packages suggested by currently installed set of packages. You can
optionally pass one or multiple package names in the format of `vendor/package`
to limit output to suggestions made by those packages only.
-Use the `--by-package` (default) or `--by-suggestion` flags to group the output by
+Use the `--by-package` or `--by-suggestion` flags to group the output by
the package offering the suggestions or the suggested packages respectively.
-If you only want a list of suggested package names, use `--list`.
+Use the `--verbose (-v)` flag to display the suggesting package and the suggestion reason.
+This implies `--by-package --by-suggestion`, showing both lists.
### Options
-* **--by-package:** Groups output by suggesting package (default).
+* **--by-package:** Groups output by suggesting package.
* **--by-suggestion:** Groups output by suggested package.
-* **--all:** Show suggestions from all dependencies, including transitive ones (by
- default only direct dependencies' suggestions are shown).
-* **--list:** Show only list of suggested package names.
* **--no-dev:** Excludes suggestions from `require-dev` packages.
## fund
Discover how to help fund the maintenance of your dependencies. This lists
-all funding links from the installed dependencies. Use `--format=json` to
-get machine-readable output.
-
-### Options
-
-* **--format (-f):** Lets you pick between text (default) or json output format.
+all funding links from the installed dependencies.
## depends (why)
@@ -675,9 +552,6 @@ you may have to run the command with `root` privileges
sudo -H composer self-update
```
-If Composer was not installed as a PHAR, this command is not available.
-(This is sometimes the case when Composer was installed by an operating system package manager.)
-
### Options
* **--rollback (-r):** Rollback to the last version you had installed.
@@ -688,9 +562,6 @@ If Composer was not installed as a PHAR, this command is not available.
* **--stable:** Force an update to the stable channel.
* **--preview:** Force an update to the preview channel.
* **--snapshot:** Force an update to the snapshot channel.
-* **--1:** Force an update to the stable channel, but only use 1.x versions
-* **--2:** Force an update to the stable channel, but only use 2.x versions
-* **--set-channel-only:** Only store the channel as the default one and then exit
## config
@@ -732,10 +603,8 @@ See the [Config](06-config.md) chapter for valid configuration options.
option this lists the global configuration only.
* **--file="..." (-f):** Operate on a specific file instead of composer.json. Note
that this cannot be used in conjunction with the `--global` option.
-* **--absolute:** Returns absolute paths when fetching `*-dir` config values
+* **--absolute:** Returns absolute paths when fetching *-dir config values
instead of relative.
-* **--json:** JSON decode the setting value, to be used with `extra.*` keys.
-* **--merge:** Merge the setting value with the current value, to be used with `extra.*` keys in combination with `--json`.
### Modifying Repositories
@@ -764,13 +633,6 @@ php composer.phar config extra.foo.bar value
The dots indicate array nesting, a max depth of 3 levels is allowed though. The above
would set `"extra": { "foo": { "bar": "value" } }`.
-If you have a complex value to add/modify, you can use the `--json` and `--merge` flags
-to edit extra fields as json:
-
-```sh
-php composer.phar config --json extra.foo.bar '{"baz": true, "qux": []}'
-```
-
## create-project
You can use Composer to create new projects from an existing package. This is
@@ -802,21 +664,14 @@ By default the command checks for the packages on packagist.org.
### Options
* **--stability (-s):** Minimum stability of package. Defaults to `stable`.
-* **--prefer-install:** There are two ways of downloading a package: `source`
- and `dist`. Composer uses `dist` by default. If you pass
- `--prefer-install=source` (or `--prefer-source`) Composer will install from
- `source` if there is one. This is useful if you want to make a bugfix to a
- project and get a local git clone of the dependency directly.
- To get the legacy behavior where Composer use `source` automatically for dev
- versions of packages, use `--prefer-install=auto`. See also [config.preferred-install](06-config.md#preferred-install).
- Passing this flag will override the config value.
+* **--prefer-source:** Install packages from `source` when available.
+* **--prefer-dist:** Install packages from `dist` when available.
* **--repository:** Provide a custom repository to search for the package,
which will be used instead of packagist. Can be either an HTTP URL pointing
to a `composer` repository, a path to a local `packages.json` file, or a
JSON string which similar to what the [repositories](04-schema.md#repositories)
- key accepts. You can use this multiple times to configure multiple repositories.
-* **--add-repository:** Add the custom repository in the composer.json. If a lock
- file is present it will be deleted and an update will be run instead of install.
+ key accepts.
+* **--add-repository:** Add the repository option to the composer.json.
* **--dev:** Install packages listed in `require-dev`.
* **--no-dev:** Disables installation of require-dev packages.
* **--no-scripts:** Disables the execution of the scripts defined in the root
@@ -831,14 +686,9 @@ By default the command checks for the packages on packagist.org.
mode.
* **--remove-vcs:** Force-remove the VCS metadata without prompting.
* **--no-install:** Disables installation of the vendors.
-* **--ignore-platform-reqs:** ignore all platform requirements (`php`, `hhvm`,
- `lib-*` and `ext-*`) and force the installation even if the local machine does
- not fulfill these.
- See also the [`platform`](06-config.md#platform) config option.
-* **--ignore-platform-req:** ignore a specific platform requirement(`php`,
- `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
- does not fulfill it.
-* **--ask:** Ask user to provide target directory for new project.
+* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
+ requirements and force the installation even if the local machine does not
+ fulfill these.
## dump-autoload (dumpautoload)
@@ -857,21 +707,11 @@ performance.
* **--no-scripts:** Skips the execution of all scripts defined in `composer.json` file.
* **--optimize (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
autoloader. This is recommended especially for production, but can take
- a bit of time to run, so it is currently not done by default.
+ a bit of time to run so it is currently not done by default.
* **--classmap-authoritative (-a):** Autoload classes from the classmap only.
Implicitly enables `--optimize`.
* **--apcu:** Use APCu to cache found/not-found classes.
-* **--apcu-prefix:** Use a custom prefix for the APCu autoloader cache.
- Implicitly enables `--apcu`.
-* **--no-dev:** Disables autoload-dev rules. Composer will by default infer this
- automatically according to the last `install` or `update` `--no-dev` state.
-* **--dev:** Enables autoload-dev rules. Composer will by default infer this
- automatically according to the last `install` or `update` `--no-dev` state.
-* **--ignore-platform-reqs:** ignore all `php`, `hhvm`, `lib-*` and `ext-*`
- requirements and skip the [platform check](07-runtime.md#platform-check) for these.
- See also the [`platform`](06-config.md#platform) config option.
-* **--ignore-platform-req:** ignore a specific platform requirement (`php`, `hhvm`,
- `lib-*` and `ext-*`) and skip the [platform check](07-runtime.md#platform-check) for it.
+* **--no-dev:** Disables autoload-dev rules.
## clear-cache / clearcache / cc
@@ -880,11 +720,11 @@ Deletes all content from Composer's cache directories.
## licenses
Lists the name, version and license of every package installed. Use
-`--format=json` to get machine-readable output.
+`--format=json` to get machine readable output.
### Options
-* **--format:** Format of the output: text, json or summary (default: "text")
+* **--format:** Format of the output: text or json (default: "text")
* **--no-dev:** Remove dev dependencies from the output
## run-script
@@ -982,10 +822,9 @@ If set to 1, this env allows running Composer when the Xdebug extension is enabl
### COMPOSER_AUTH
The `COMPOSER_AUTH` var allows you to set up authentication as an environment variable.
-The contents of the variable should be a JSON formatted object containing [http-basic,
-github-oauth, bitbucket-oauth, ... objects as needed](articles/authentication-for-private-packages.md),
-and following the
-[spec from the config](06-config.md).
+The contents of the variable should be a JSON formatted object containing http-basic,
+github-oauth, bitbucket-oauth, ... objects as needed, and following the
+[spec from the config](06-config.md#gitlab-oauth).
### COMPOSER_BIN_DIR
@@ -997,7 +836,7 @@ directory to something other than `vendor/bin`.
The `COMPOSER_CACHE_DIR` var allows you to change the Composer cache directory,
which is also configurable via the [`cache-dir`](06-config.md#cache-dir) option.
-By default, it points to `$COMPOSER_HOME/cache` on \*nix and macOS, and
+By default it points to `$COMPOSER_HOME/cache` on \*nix and macOS, and
`C:\Users\\AppData\Local\Composer` (or `%LOCALAPPDATA%/Composer`) on Windows.
### COMPOSER_CAFILE
@@ -1019,9 +858,7 @@ The `COMPOSER_HOME` var allows you to change the Composer home directory. This
is a hidden, global (per-user on the machine) directory that is shared between
all projects.
-Use `composer config --global home` to see the location of the home directory.
-
-By default, it points to `C:\Users\\AppData\Roaming\Composer` on Windows
+By default it points to `C:\Users\\AppData\Roaming\Composer` on Windows
and `/Users//.composer` on macOS. On \*nix systems that follow the [XDG Base
Directory Specifications](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html),
it points to `$XDG_CONFIG_HOME/composer`. On other \*nix systems, it points to
@@ -1066,23 +903,14 @@ commands) to finish executing. The default value is 300 seconds (5 minutes).
### COMPOSER_ROOT_VERSION
-By setting this var you can specify the version of the root package, if it
-cannot be guessed from VCS info and is not present in `composer.json`.
+By setting this var you can specify the version of the root package, if it can
+not be guessed from VCS info and is not present in `composer.json`.
### COMPOSER_VENDOR_DIR
By setting this var you can make Composer install the dependencies into a
directory other than `vendor`.
-### COMPOSER_RUNTIME_ENV
-
-This lets you hint under which environment Composer is running, which can help Composer
-work around some environment specific issues. The only value currently supported is
-`virtualbox`, which then enables some short `sleep()` calls to wait for the filesystem
-to have written files properly before we attempt reading them. You can set the
-environment variable if you use Vagrant or VirtualBox and experience issues with files not
-being found during installation even though they should be present.
-
### http_proxy or HTTP_PROXY
If you are using Composer from behind an HTTP proxy, you can use the standard
@@ -1099,22 +927,15 @@ similar use case), and need to support proxies, please provide the `CGI_HTTP_PRO
environment variable instead. See [httpoxy.org](https://httpoxy.org/) for further
details.
-### COMPOSER_MAX_PARALLEL_HTTP
-
-Set to an integer to configure how many files can be downloaded in parallel. This
-defaults to 12 and must be between 1 and 50. If your proxy has issues with
-concurrency maybe you want to lower this. Increasing it should generally not result
-in performance gains.
-
### HTTP_PROXY_REQUEST_FULLURI
-If you use a proxy, but it does not support the request_fulluri flag, then you
+If you use a proxy but it does not support the request_fulluri flag, then you
should set this env var to `false` or `0` to prevent Composer from setting the
request_fulluri option.
### HTTPS_PROXY_REQUEST_FULLURI
-If you use a proxy, but it does not support the request_fulluri flag for HTTPS
+If you use a proxy but it does not support the request_fulluri flag for HTTPS
requests, then you should set this env var to `false` or `0` to prevent Composer
from setting the request_fulluri option.
@@ -1132,17 +953,4 @@ The env var accepts domains, IP addresses, and IP address blocks in CIDR
notation. You can restrict the filter to a particular port (e.g. `:80`). You
can also set it to `*` to ignore the proxy for all HTTP requests.
-### COMPOSER_DISABLE_NETWORK
-
-If set to `1`, disables network access (best effort). This can be used for debugging or
-to run Composer on a plane or a starship with poor connectivity.
-
-If set to `prime`, GitHub VCS repositories will prime the cache, so it can then be used
-fully offline with `1`.
-
-### COMPOSER_DEBUG_EVENTS
-
-If set to `1`, outputs information about events being dispatched, which can be
-useful for plugin authors to identify what is firing when exactly.
-
← [Libraries](02-libraries.md) | [Schema](04-schema.md) →
diff --git a/app/vendor/composer/composer/doc/04-schema.md b/app/vendor/composer/composer/doc/04-schema.md
index 849e5ee68..8599d934b 100644
--- a/app/vendor/composer/composer/doc/04-schema.md
+++ b/app/vendor/composer/composer/doc/04-schema.md
@@ -1,10 +1,10 @@
-# The composer.json schema
+# The composer.json Schema
This chapter will explain all of the fields available in `composer.json`.
## JSON schema
-We have a [JSON schema](https://json-schema.org) that documents the format and
+We have a [JSON schema](http://json-schema.org) that documents the format and
can also be used to validate your `composer.json`. In fact, it is used by the
`validate` command. You can find it at: https://getcomposer.org/schema.json
@@ -34,12 +34,12 @@ separated by `/`. Examples:
* monolog/monolog
* igorw/event-source
-The name must be lowercased and consist of words separated by `-`, `.` or `_`.
-The complete name should match `^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$`.
+The name can contain any character, including white spaces, and it's case
+insensitive (`foo/bar` and `Foo/Bar` are considered the same package). In order
+to simplify its installation, it's recommended to define a short and lowercase
+name that doesn't include non-alphanumeric characters or white spaces.
-The `name` property is required for published packages (libraries).
-
-> **Note:** Before Composer version 2.0, a name could contain any character, including white spaces.
+Required for published packages (libraries).
### description
@@ -123,7 +123,7 @@ Optional.
### homepage
-A URL to the website of the project.
+An URL to the website of the project.
Optional.
@@ -160,7 +160,7 @@ The recommended notation for the most common licenses is (alphabetical):
Optional, but it is highly recommended to supply this. More identifiers are
listed at the [SPDX Open Source License Registry](https://spdx.org/licenses/).
-> **Note:** For closed-source software, you may use `"proprietary"` as the license identifier.
+For closed-source software, you may use `"proprietary"` as the license identifier.
An Example:
@@ -184,7 +184,7 @@ An Example for disjunctive licenses:
}
```
-Alternatively they can be separated with "or" and enclosed in parentheses;
+Alternatively they can be separated with "or" and enclosed in parenthesis;
```json
{
@@ -192,8 +192,8 @@ Alternatively they can be separated with "or" and enclosed in parentheses;
}
```
-Similarly, when multiple licenses need to be applied ("conjunctive license"),
-they should be separated with "and" and enclosed in parentheses.
+Similarly when multiple licenses need to be applied ("conjunctive license"),
+they should be separated with "and" and enclosed in parenthesis.
### authors
@@ -214,7 +214,7 @@ An example:
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
- "homepage": "https://www.naderman.de",
+ "homepage": "http://www.naderman.de",
"role": "Developer"
},
{
@@ -265,8 +265,8 @@ development of new functionality.
Each entry consists of the following
-* **type:** The type of funding, or the platform through which funding can be provided, e.g. patreon, opencollective, tidelift or github.
-* **url:** URL to a website with details, and a way to fund the package.
+* **type:** The type of funding or the platform through which funding can be provided, e.g. patreon, opencollective, tidelift or github.
+* **url:** URL to a website with details and a way to fund the package.
An example:
@@ -310,7 +310,7 @@ Example:
All links are optional fields.
`require` and `require-dev` additionally support _stability flags_ ([root-only](04-schema.md#root-package)).
-They take the form "_constraint_@_stability flag_".
+They take the form "_constraint_@_stability flag_".
These allow you to further restrict or expand the stability of a package beyond
the scope of the [minimum-stability](#minimum-stability) setting. You can apply
them to a constraint, or apply them to an empty _constraint_ if you want to
@@ -382,7 +382,7 @@ Example:
```json
{
"require" : {
- "php" : ">=7.4",
+ "php" : "^5.5 || ^7.0",
"ext-mbstring": "*"
}
}
@@ -401,19 +401,19 @@ Example:
#### require
-Map of packages required by this package. The package will not be installed
+Lists packages required by this package. The package will not be installed
unless those requirements can be met.
#### require-dev ([root-only](04-schema.md#root-package))
-Map of packages required for developing this package, or running
+Lists packages required for developing this package, or running
tests, etc. The dev requirements of the root package are installed by default.
Both `install` or `update` support the `--no-dev` option that prevents dev
dependencies from being installed.
#### conflict
-Map of packages that conflict with this version of this package. They
+Lists packages that conflict with this version of this package. They
will not be allowed to be installed together with your package.
Note that when specifying ranges like `<1.0 >=1.1` in a `conflict` link,
@@ -423,7 +423,7 @@ probably want to go for `<1.0 || >=1.1` in this case.
#### replace
-Map of packages that are replaced by this package. This allows you to fork a
+Lists packages that are replaced by this package. This allows you to fork a
package, publish it under a different name with its own version numbers, while
packages requiring the original package continue to work with your fork because
it replaces the original package.
@@ -441,12 +441,10 @@ that exact version, and not any other version, which would be incorrect.
#### provide
-Map of packages that are provided by this package. This is mostly
+List of other packages that are provided by this package. This is mostly
useful for implementations of common interfaces. A package could depend on
-some virtual package e.g. `psr/logger-implementation`, any library that implements
-this logger interface would list it in `provide`. Implementors can then
-be [found on Packagist.org](https://packagist.org/providers/psr/log-implementation).
-
+some virtual `logger-implementation` package, any library that implements
+this logger interface would list it in `provide`.
Using `provide` with the name of an actual package rather than a virtual one
implies that the code of that package is also shipped, in which case `replace`
is generally a better choice. A common convention for packages providing an
@@ -479,7 +477,7 @@ Example:
Autoload mapping for a PHP autoloader.
-[`PSR-4`](https://www.php-fig.org/psr/psr-4/) and [`PSR-0`](http://www.php-fig.org/psr/psr-0/)
+[`PSR-4`](http://www.php-fig.org/psr/psr-4/) and [`PSR-0`](http://www.php-fig.org/psr/psr-0/)
autoloading, `classmap` generation and `files` includes are supported.
PSR-4 is the recommended way since it offers greater ease of use (no need
@@ -618,18 +616,6 @@ Example:
}
```
-Wildcards (`*`) are also supported in a classmap paths, and expand to match any directory name:
-
-Example:
-
-```json
-{
- "autoload": {
- "classmap": ["src/addons/*/lib/", "3rd-party/*", "Something.php"]
- }
-}
-```
-
#### Files
If you want to require certain files explicitly on every request then you can use
@@ -790,6 +776,8 @@ The following repository types are supported:
using the `options` parameter.
* **vcs:** The version control system repository can fetch packages from git,
svn, fossil and hg repositories.
+* **pear:** With this you can import any pear repository into your Composer
+ project.
* **package:** If you depend on a project that does not have any support for
composer whatsoever you can define the package inline using a `package`
repository. You basically inline the `composer.json` object.
@@ -818,6 +806,10 @@ Example:
"type": "vcs",
"url": "https://github.com/Seldaek/monolog"
},
+ {
+ "type": "pear",
+ "url": "https://pear2.php.net"
+ },
{
"type": "package",
"package": {
@@ -897,21 +889,6 @@ A set of options for creating package archives.
The following options are supported:
-* **name:** Allows configuring base name for archive.
- By default (if not configured, and `--file` is not passed as command-line argument),
- `preg_replace('#[^a-z0-9-_]#i', '-', name)` is used.
-
-Example:
-
-```json
-{
- "name": "org/strangeName",
- "archive": {
- "name": "Strange_name"
- }
-}
-```
-
* **exclude:** Allows configuring a list of patterns for excluded paths. The
pattern syntax matches .gitignore files. A leading exclamation mark (!) will
result in any matching files to be included even if a previous pattern
@@ -942,7 +919,7 @@ It can be boolean or a package name/URL pointing to a recommended alternative.
Examples:
Use `"abandoned": true` to indicates this package is abandoned.
-Use `"abandoned": "monolog/monolog"` to indicates this package is abandoned, and the
+Use `"abandoned": "monolog/monolog"` to indicates this package is abandoned and the
recommended alternative is `monolog/monolog`.
Defaults to false.
@@ -957,7 +934,7 @@ that will NOT be handled as feature branches. This is an array of strings.
If you have non-numeric branch names, for example like "latest", "current", "latest-stable"
or something, that do not look like a version number, then Composer handles such branches
as feature branches. This means it searches for parent branches, that look like a version
-or ends at special branches (like master), and the root package version number becomes the
+or ends at special branches (like master) and the root package version number becomes the
version of the parent branch or at least master or something.
To handle non-numeric named branches as versions instead of searching for a parent branch
diff --git a/app/vendor/composer/composer/doc/05-repositories.md b/app/vendor/composer/composer/doc/05-repositories.md
index f8a68fa30..4c1c7e000 100644
--- a/app/vendor/composer/composer/doc/05-repositories.md
+++ b/app/vendor/composer/composer/doc/05-repositories.md
@@ -6,7 +6,7 @@ of repositories are available, and how they work.
## Concepts
Before we look at the different types of repositories that exist, we need to
-understand some basic concepts that Composer is built on.
+understand some of the basic concepts that Composer is built on.
### Package
@@ -41,7 +41,7 @@ be preferred.
A repository is a package source. It's a list of packages/versions. Composer
will look in all your repositories to find the packages your project requires.
-By default, only the Packagist.org repository is registered in Composer. You can
+By default only the Packagist repository is registered in Composer. You can
add more repositories to your project by declaring them in `composer.json`.
Repositories are only available to the root package and the repositories
@@ -49,12 +49,6 @@ defined in your dependencies will not be loaded. Read the
[FAQ entry](faqs/why-can't-composer-load-repositories-recursively.md) if you
want to learn why.
-When resolving dependencies, packages are looked up from repositories from
-top to bottom, and by default, as soon as a package is found in one, Composer
-stops looking in other repositories. Read the
-[repository priorities](articles/repository-priorities.md) article for more
-details and to see how to change this behavior.
-
## Types
### Composer
@@ -68,17 +62,6 @@ In the case of packagist, that file is located at `/packages.json`, so the URL o
the repository would be `repo.packagist.org`. For `example.org/packages.json` the
repository URL would be `example.org`.
-```json
-{
- "repositories": [
- {
- "type": "composer",
- "url": "https://example.org"
- }
- ]
-}
-```
-
#### packages
The only required field is `packages`. The JSON structure is as follows:
@@ -122,7 +105,7 @@ It may include any of the other fields specified in the [schema](04-schema.md).
The `notify-batch` field allows you to specify a URL that will be called
every time a user installs a package. The URL can be either an absolute path
-(that will use the same domain as the repository), or a fully qualified URL.
+(that will use the same domain as the repository) or a fully qualified URL.
An example value:
@@ -149,102 +132,6 @@ number.
This field is optional.
-### metadata-url, available-packages and available-package-patterns
-
-The `metadata-url` field allows you to provide a URL template to serve all
-packages which are in the repository. It must contain the placeholder
-`%package%`.
-
-This field is new in Composer v2, and is prioritised over the
-`provider-includes` and `providers-url` fields if both are present.
-For compatibility with both Composer v1 and v2 you ideally want
-to provide both. New repository implementations may only need to
-support v2 however.
-
-An example:
-
-```json
-{
- "metadata-url": "/p2/%package%.json"
-}
-```
-
-Whenever Composer looks for a package, it will replace `%package%` by the
-package name, and fetch that URL. If dev stability is allowed for the package,
-it will also load the URL again with `$packageName~dev` (e.g.
-`/p2/foo/bar~dev.json` to look for `foo/bar`'s dev versions).
-
-The `foo/bar.json` and `foo/bar~dev.json` files containing package versions
-MUST contain only versions for the foo/bar package, as
-`{"packages":{"foo/bar":[ ... versions here ... ]}}`.
-
-Caching is done via the use of If-Modified-Since header, so make sure you
-return Last-Modified headers and that they are accurate.
-
-The array of versions can also optionally be minified using
-`Composer\MetadataMinifier\MetadataMinifier::minify()` from
-[composer/metadata-minifier](https://packagist.org/packages/composer/metadata-minifier).
-If you do that, you should add a `"minified": "composer/2.0"` key
-at the top level to indicate to Composer it must expand the version
-list back into the original data. See
-https://repo.packagist.org/p2/monolog/monolog.json for an example.
-
-Any requested package which does not exist MUST return a 404 status code,
-which will indicate to Composer that this package does not exist in your
-repository. Make sure the 404 response is fast to avoid blocking Composer.
-Avoid redirects to alternative 404 pages.
-
-If your repository only has a small number of packages, and you want to avoid
-the 404-requests, you can also specify an `"available-packages"` key in
-`packages.json` which should be an array with all the package names that your
-repository contain. Alternatively you can specify an
-`"available-package-patterns"` key which is an array of package name patterns
-(with `*` matching any string, e.g. `vendor/*` would make composer look up
-every matching package name in this repository).
-
-This field is optional.
-
-### providers-api
-
-The `providers-api` field allows you to provide a URL template to serve all
-packages which provide a given package name, but not the package which has
-that name. It must contain the placeholder `%package%`.
-
-For example https://packagist.org/providers/monolog/monolog.json lists some
-package which have a "provide" rule for monolog/monolog, but it does not list
-monolog/monolog itself.
-
-```json
-{
- "providers-api": "https://packagist.org/providers/%package%.json",
-}
-```
-
-This field is optional.
-
-### list
-
-The `list` field allows you to return the names of packages which match a
-given field (or all names if no filter is present). It should accept an
-optional `?filter=xx` query param, which can contain `*` as wildcards matching
-any substring.
-
-Replace/provide rules should not be considered here.
-
-It must return an array of package names:
-```json
-{
- "packageNames": [
- "a/b",
- "c/d"
- ]
-}
-```
-
-See for example.
-
-This field is optional.
-
#### provider-includes and providers-url
The `provider-includes` field allows you to list a set of files that list
@@ -255,9 +142,6 @@ The `providers-url` describes how provider files are found on the server. It
is an absolute path from the repository root. It must contain the placeholders
`%package%` and `%hash%`.
-These fields are used by Composer v1, or if your repository does not have the
-`metadata-url` field set.
-
An example:
```json
@@ -316,7 +200,7 @@ from these systems.
There are a few use cases for this. The most common one is maintaining your
own fork of a third party library. If you are using a certain library for your
-project, and you decide to change something in the library, you will want your
+project and you decide to change something in the library, you will want your
project to use the patched version. If the library is on GitHub (this is the
case most of the time), you can fork it there and push your changes to
your fork. After that you update the project's `composer.json`. All you have
@@ -415,10 +299,23 @@ Please note:
#### BitBucket Driver Configuration
-> **Note that the repository endpoint for BitBucket needs to be https rather than git.**
+The BitBucket driver uses OAuth to access your private repositories via the BitBucket REST APIs and you will need to create an OAuth consumer to use the driver, please refer to [Atlassian's Documentation](https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html). You will need to fill the callback url with something to satisfy BitBucket, but the address does not need to go anywhere and is not used by Composer.
-After setting up your bitbucket repository, you will also need to
-[set up authentication](articles/authentication-for-private-packages.md#bitbucket-oauth).
+After creating an OAuth consumer in the BitBucket control panel, you need to setup your auth.json file with
+the credentials like this (more info [here](https://getcomposer.org/doc/06-config.md#bitbucket-oauth)):
+```json
+{
+ "bitbucket-oauth": {
+ "bitbucket.org": {
+ "consumer-key": "myKey",
+ "consumer-secret": "mySecret"
+ }
+ }
+}
+```
+**Note that the repository endpoint needs to be https rather than git.**
+
+Alternatively if you prefer not to have your OAuth credentials on your filesystem you may export the ```bitbucket-oauth``` block above to the [COMPOSER_AUTH](https://getcomposer.org/doc/03-cli.md#composer-auth) environment variable instead.
#### Subversion Options
@@ -481,6 +378,92 @@ for this server will be overwritten. To change this behavior by setting the
}
```
+### PEAR
+
+It is possible to install packages from any PEAR channel by using the `pear`
+repository. Composer will prefix all package names with `pear-{channelName}/`
+to avoid conflicts. All packages are also aliased with prefix
+`pear-{channelAlias}/`.
+
+Example using `pear2.php.net`:
+
+```json
+{
+ "repositories": [
+ {
+ "type": "pear",
+ "url": "https://pear2.php.net"
+ }
+ ],
+ "require": {
+ "pear-pear2.php.net/PEAR2_Text_Markdown": "*",
+ "pear-pear2/PEAR2_HTTP_Request": "*"
+ }
+}
+```
+
+In this case the short name of the channel is `pear2`, so the
+`PEAR2_HTTP_Request` package name becomes `pear-pear2/PEAR2_HTTP_Request`.
+
+> **Note:** The `pear` repository requires doing quite a few requests per
+> package, so this may considerably slow down the installation process.
+
+#### Custom vendor alias
+
+It is possible to alias PEAR channel packages with a custom vendor name.
+
+Example:
+
+Suppose you have a private PEAR repository and wish to use Composer to
+incorporate dependencies from a VCS. Your PEAR repository contains the
+following packages:
+
+ * `BasePackage`
+ * `IntermediatePackage`, which depends on `BasePackage`
+ * `TopLevelPackage1` and `TopLevelPackage2` which both depend
+ on `IntermediatePackage`
+
+Without a vendor alias, Composer will use the PEAR channel name as the
+vendor portion of the package name:
+
+ * `pear-pear.foobar.repo/BasePackage`
+ * `pear-pear.foobar.repo/IntermediatePackage`
+ * `pear-pear.foobar.repo/TopLevelPackage1`
+ * `pear-pear.foobar.repo/TopLevelPackage2`
+
+Suppose at a later time you wish to migrate your PEAR packages to a
+Composer repository and naming scheme, and adopt the vendor name of `foobar`.
+Projects using your PEAR packages would not see the updated packages, since
+they have a different vendor name (`foobar/IntermediatePackage` vs
+`pear-pear.foobar.repo/IntermediatePackage`).
+
+By specifying `vendor-alias` for the PEAR repository from the start, you can
+avoid this scenario and future-proof your package names.
+
+To illustrate, the following example would get the `BasePackage`,
+`TopLevelPackage1`, and `TopLevelPackage2` packages from your PEAR repository
+and `IntermediatePackage` from a Github repository:
+
+```json
+{
+ "repositories": [
+ {
+ "type": "git",
+ "url": "https://github.com/foobar/intermediate.git"
+ },
+ {
+ "type": "pear",
+ "url": "http://pear.foobar.repo",
+ "vendor-alias": "foobar"
+ }
+ ],
+ "require": {
+ "foobar/TopLevelPackage1": "*",
+ "foobar/TopLevelPackage2": "*"
+ }
+}
+```
+
### Package
If you want to use a project that does not support Composer through any of the
@@ -523,7 +506,7 @@ Here is an example for the smarty template engine:
}
```
-Typically, you would leave the source part off, as you don't really need it.
+Typically you would leave the source part off, as you don't really need it.
> **Note**: This repository type has a few limitations and should be avoided
> whenever possible:
@@ -593,7 +576,7 @@ package repository definitions. It will fetch all the packages that are
`require`d and dump a `packages.json` that is your `composer` repository.
Check [the satis GitHub repository](https://github.com/composer/satis) and
-the [handling private packages article](articles/handling-private-packages.md) for more
+the [Satis article](articles/handling-private-packages-with-satis.md) for more
information.
### Artifact
@@ -602,8 +585,8 @@ There are some cases, when there is no ability to have one of the previously
mentioned repository types online, even the VCS one. A typical example could be
cross-organisation library exchange through build artifacts. Of course, most
of the time these are private. To use these archives as-is, one can use a
-repository of type `artifact` with a folder containing ZIP or TAR archives of
-those private packages:
+repository of type `artifact` with a folder containing ZIP archives of those
+private packages:
```json
{
@@ -729,8 +712,8 @@ variables are parsed in both Windows and Linux/Mac notations. For example
`/home//git/mypackage`, equivalent to `$HOME/git/mypackage` or
`%USERPROFILE%/git/mypackage`.
-> **Note:** Repository paths can also contain wildcards like `*` and `?`.
-> For details, see the [PHP glob function](https://php.net/glob).
+> **Note:** Repository paths can also contain wildcards like ``*`` and ``?``.
+> For details, see the [PHP glob function](http://php.net/glob).
## Disabling Packagist.org
diff --git a/app/vendor/composer/composer/doc/06-config.md b/app/vendor/composer/composer/doc/06-config.md
index dffff2104..1761ac7c1 100644
--- a/app/vendor/composer/composer/doc/06-config.md
+++ b/app/vendor/composer/composer/doc/06-config.md
@@ -5,8 +5,7 @@ This chapter will describe the `config` section of the `composer.json`
## process-timeout
-The timeout in seconds for process executions, defaults to 300 (5mins).
-The duration processes like git clones can run before
+Defaults to `300`. The duration processes like git clones can run before
Composer assumes they died out. You may need to make this higher if you have a
slow connection or huge vendors.
@@ -31,7 +30,7 @@ in the PHP include path.
## preferred-install
-Defaults to `dist` and can be any of `source`, `dist` or `auto`. This option
+Defaults to `auto` and can be any of `source`, `dist` or `auto`. This option
allows you to set the install method Composer will prefer to use. Can
optionally be a hash of patterns for more granular install preferences.
@@ -48,16 +47,6 @@ optionally be a hash of patterns for more granular install preferences.
}
```
-- `source` means Composer will install packages from their `source` if there
- is one. This is typically a git clone or equivalent checkout of the version
- control system the package uses. This is useful if you want to make a bugfix
- to a project and get a local git clone of the dependency directly.
-- `auto` is the legacy behavior where Composer uses `source` automatically
- for dev versions, and `dist` otherwise.
-- `dist` (the default as of Composer 2.1) means Composer installs from `dist`,
- where possible. This is typically a zip file download, which is faster than
- cloning the entire repository.
-
> **Note:** Order matters. More specific patterns should be earlier than
> more relaxed patterns. When mixing the string notation with the hash
> configuration in global and package configurations the string notation
@@ -82,14 +71,9 @@ URL.
A list of domain names and oauth keys. For example using `{"github.com":
"oauthtoken"}` as the value of this option will use `oauthtoken` to access
private repositories on github and to circumvent the low IP-based rate limiting
-of their API. Composer may prompt for credentials when needed, but these can also be
-manually set. Read more on how to get an OAuth token for GitHub and cli syntax
-[here](articles/authentication-for-private-packages.md#github-oauth).
-
-## gitlab-domains
-
-Defaults to `["gitlab.com"]`. A list of domains of GitLab servers.
-This is used if you use the `gitlab` repository type.
+of their API. [Read
+more](articles/troubleshooting.md#api-rate-limit-and-oauth-tokens) on how to get
+an OAuth token for GitHub.
## gitlab-oauth
@@ -98,31 +82,14 @@ A list of domain names and oauth keys. For example using `{"gitlab.com":
private repositories on gitlab. Please note: If the package is not hosted at
gitlab.com the domain names must be also specified with the
[`gitlab-domains`](06-config.md#gitlab-domains) option.
-Further info can also be found [here](articles/authentication-for-private-packages.md#gitlab-oauth)
## gitlab-token
-A list of domain names and private tokens. Private token can be either simple
-string, or array with username and token. For example using `{"gitlab.com":
+A list of domain names and private tokens. For example using `{"gitlab.com":
"privatetoken"}` as the value of this option will use `privatetoken` to access
-private repositories on gitlab. Using `{"gitlab.com": {"username": "gitlabuser",
- "token": "privatetoken"}}` will use both username and token for gitlab deploy
-token functionality (https://docs.gitlab.com/ee/user/project/deploy_tokens/)
-Please note: If the package is not hosted at
+private repositories on gitlab. Please note: If the package is not hosted at
gitlab.com the domain names must be also specified with the
-[`gitlab-domains`](06-config.md#gitlab-domains) option. The token must have
-`api` or `read_api` scope.
-Further info can also be found [here](articles/authentication-for-private-packages.md#gitlab-token)
-
-## gitlab-protocol
-
-A protocol to force use of when creating a repository URL for the `source`
-value of the package metadata. One of `git` or `http`. (`https` is treated
-as a synonym for `http`.) Helpful when working with projects referencing
-private repositories which will later be cloned in GitLab CI jobs with a
-[GitLab CI_JOB_TOKEN](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html#predefined-variables-reference)
-using HTTP basic auth. By default, Composer will generate a git-over-SSH
-URL for private repositories and HTTP(S) only for public.
+[`gitlab-domains`](06-config.md#gitlab-domains) option.
## disable-tls
@@ -142,8 +109,8 @@ get a free SSL certificate is generally a better alternative.
## bitbucket-oauth
A list of domain names and consumers. For example using `{"bitbucket.org":
-{"consumer-key": "myKey", "consumer-secret": "mySecret"}}`.
-Read more [here](articles/authentication-for-private-packages.md#bitbucket-oauth).
+{"consumer-key": "myKey", "consumer-secret": "mySecret"}}`. [Read](https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html)
+how to set up a consumer on Bitbucket.
## cafile
@@ -162,7 +129,11 @@ capath must be a correctly hashed certificate directory.
A list of domain names and username/passwords to authenticate against them. For
example using `{"example.org": {"username": "alice", "password": "foo"}}` as the
value of this option will let Composer authenticate against example.org.
-More info can be found [here](articles/authentication-for-private-packages.md#http-basic).
+
+> **Note:** Authentication-related config options like `http-basic`, `bearer` and
+> `github-oauth` can also be specified inside a `auth.json` file that goes
+> besides your `composer.json`. That way you can gitignore it and every
+> developer can place their own credentials in there.
## bearer
@@ -176,21 +147,6 @@ Lets you fake platform packages (PHP and extensions) so that you can emulate a
production env or define your target platform in the config. Example: `{"php":
"7.0.3", "ext-something": "4.0.3"}`.
-This will make sure that no package requiring more than PHP 7.0.3 can be installed
-regardless of the actual PHP version you run locally. However it also means
-the dependencies are not checked correctly anymore, if you run PHP 5.6 it will
-install fine as it assumes 7.0.3, but then it will fail at runtime.
-
-Therefore if you use this it is recommended, and safer, to also run the
-[`check-platform-reqs`](03-cli.md#check-platform-reqs) command as part of your
-deployment strategy.
-
-If a dependency requires some extension that you do not have installed locally
-you may ignore it instead by passing `--ignore-platform-req=ext-foo` to `update`,
-`install` or `require`. In the long run though you should install required
-extensions as if you ignore one now and a new package you add a month later also
-requires it, you may introduce issues in production unknowingly.
-
## vendor-dir
Defaults to `vendor`. You can install dependencies into a different directory if
@@ -213,10 +169,9 @@ versions. See also [COMPOSER_HOME](03-cli.md#composer-home).
## cache-dir
Defaults to `C:\Users\\AppData\Local\Composer` on Windows,
-`/Users//Library/Caches/composer` on macOS, `$XDG_CACHE_HOME/composer`
-on unix systems that follow the XDG Base Directory Specifications, and
-`$home/cache` on other unix systems. Stores all the caches used by Composer.
-See also [COMPOSER_HOME](03-cli.md#composer-home).
+`$XDG_CACHE_HOME/composer` on unix systems that follow the XDG Base Directory
+Specifications, and `$home/cache` on other unix systems. Stores all the caches
+used by Composer. See also [COMPOSER_HOME](03-cli.md#composer-home).
## cache-files-dir
@@ -234,31 +189,26 @@ metadata for the `git`/`hg` types and to speed up installs.
## cache-files-ttl
-Defaults to `15552000` (6 months). Composer caches all dist (zip, tar, ...)
+Defaults to `15552000` (6 months). Composer caches all dist (zip, tar, ..)
packages that it downloads. Those are purged after six months of being unused by
default. This option allows you to tweak this duration (in seconds) or disable
it completely by setting it to 0.
## cache-files-maxsize
-Defaults to `300MiB`. Composer caches all dist (zip, tar, ...) packages that it
+Defaults to `300MiB`. Composer caches all dist (zip, tar, ..) packages that it
downloads. When the garbage collection is periodically ran, this is the maximum
size the cache will be able to use. Older (less used) files will be removed
first until the cache fits.
-## cache-read-only
-
-Defaults to `false`. Whether to use the Composer cache in read-only mode.
-
## bin-compat
Defaults to `auto`. Determines the compatibility of the binaries to be installed.
-If it is `auto` then Composer only installs .bat proxy files when on Windows or WSL. If
+If it is `auto` then Composer only installs .bat proxy files when on Windows. If
set to `full` then both .bat files for Windows and scripts for Unix-based
operating systems will be installed for each binary. This is mainly useful if you
-run Composer inside a linux VM but still want the `.bat` proxies available for use
-in the Windows host OS. If set to `symlink` Composer will always symlink even on
-Windows/WSL.
+run Composer inside a linux VM but still want the .bat proxies available for use
+in the Windows host OS.
## prepend-autoloader
@@ -300,6 +250,11 @@ used for GitHub Enterprise setups.
Defaults to `true`. If `false`, the OAuth tokens created to access the
github API will have a date instead of the machine hostname.
+## gitlab-domains
+
+Defaults to `["gitlab.com"]`. A list of domains of GitLab servers.
+This is used if you use the `gitlab` repository type.
+
## use-github-api
Defaults to `true`. Similar to the `no-api` key on a specific repository,
@@ -351,18 +306,4 @@ in the composer home, cache, and data directories.
Defaults to `true`. If set to `false`, Composer will not create a `composer.lock`
file.
-## platform-check
-
-Defaults to `php-only` which only checks the PHP version. Set to `true` to also
-check the presence of extension. If set to `false`, Composer will not create and
-require a `platform_check.php` file as part of the autoloader bootstrap.
-
-## secure-svn-domains
-
-Defaults to `[]`. Lists domains which should be trusted/marked as using a secure
-Subversion/SVN transport. By default svn:// protocol is seen as insecure and will
-throw, but you can set this config option to `["example.org"]` to allow using svn
-URLs on that hostname. This is a better/safer alternative to disabling `secure-http`
-altogether.
-
-← [Repositories](05-repositories.md) | [Runtime](07-runtime.md) →
+← [Repositories](05-repositories.md) | [Community](07-community.md) →
diff --git a/app/vendor/composer/composer/doc/07-community.md b/app/vendor/composer/composer/doc/07-community.md
new file mode 100644
index 000000000..4296f90cd
--- /dev/null
+++ b/app/vendor/composer/composer/doc/07-community.md
@@ -0,0 +1,35 @@
+# Community
+
+There are many people using Composer already, and quite a few of them are
+contributing.
+
+## Contributing
+
+If you would like to contribute to Composer, please read the
+[README](https://github.com/composer/composer) and
+[CONTRIBUTING](https://github.com/composer/composer/blob/master/.github/CONTRIBUTING.md)
+documents.
+
+The most important guidelines are described as follows:
+
+> All code contributions - including those of people having commit access - must
+> go through a pull request and approved by a core developer before being
+> merged. This is to ensure proper review of all the code.
+>
+> Fork the project, create a feature branch, and send us a pull request.
+>
+> To ensure a consistent code base, you should make sure the code follows
+> the [PSR-2 Coding Standards](http://www.php-fig.org/psr/psr-2/).
+
+## IRC / mailing list
+
+Mailing lists for [user support](https://groups.google.com/group/composer-users) and
+[development](https://groups.google.com/group/composer-dev).
+
+IRC channels are on irc.freenode.org: [#composer](irc://irc.freenode.org/composer)
+for users and [#composer-dev](irc://irc.freenode.org/composer-dev) for development.
+
+Stack Overflow has a growing collection of
+[Composer related questions](https://stackoverflow.com/questions/tagged/composer-php).
+
+← [Config](06-config.md)
diff --git a/app/vendor/composer/composer/doc/07-runtime.md b/app/vendor/composer/composer/doc/07-runtime.md
deleted file mode 100644
index 3e345ad38..000000000
--- a/app/vendor/composer/composer/doc/07-runtime.md
+++ /dev/null
@@ -1,155 +0,0 @@
-# Runtime Composer utilities
-
-While Composer is mostly used around your project to install its dependencies,
-there are a few things which are made available to you at runtime.
-
-If you need to rely on some of these in a specific version, you can require
-the `composer-runtime-api` package.
-
-## Autoload
-
-The autoloader is the most used one, and is already covered in our
-[basic usage guide](01-basic-usage.md#autoloading). It is available in all
-Composer versions.
-
-## Installed versions
-
-composer-runtime-api 2.0 introduced a new `Composer\InstalledVersions` class which offers
-a few static methods to inspect which versions are currently installed. This is
-automatically available to your code as long as you include the Composer autoloader.
-
-The main use cases for this class are the following:
-
-### Knowing whether package X (or virtual package) is present
-
-```php
-\Composer\InstalledVersions::isInstalled('vendor/package'); // returns bool
-\Composer\InstalledVersions::isInstalled('psr/log-implementation'); // returns bool
-```
-
-As of Composer 2.1, you may also check if something was installed via require-dev or not by
-passing false as second argument:
-
-```php
-\Composer\InstalledVersions::isInstalled('vendor/package'); // returns true assuming this package is installed
-\Composer\InstalledVersions::isInstalled('vendor/package', false); // returns true if vendor/package is in require, false if in require-dev
-```
-
-Note that this can not be used to check whether platform packages are installed.
-
-### Knowing whether package X is installed in version Y
-
-> **Note:** To use this, your package must require `"composer/semver": "^3.0"`.
-
-```php
-use Composer\Semver\VersionParser;
-
-\Composer\InstalledVersions::satisfies(new VersionParser, 'vendor/package', '2.0.*');
-\Composer\InstalledVersions::satisfies(new VersionParser, 'psr/log-implementation', '^1.0');
-```
-
-This will return true if e.g. vendor/package is installed in a version matching
-`2.0.*`, but also if the given package name is replaced or provided by some other
-package.
-
-### Knowing the version of package X
-
-> **Note:** This will return `null` if the package name you ask for is not itself installed
-> but merely provided or replaced by another package. We therefore recommend using satisfies()
-> in library code at least. In application code you have a bit more control and it is less
-> important.
-
-```php
-// returns a normalized version (e.g. 1.2.3.0) if vendor/package is installed,
-// or null if it is provided/replaced,
-// or throws OutOfBoundsException if the package is not installed at all
-\Composer\InstalledVersions::getVersion('vendor/package');
-```
-
-```php
-// returns the original version (e.g. v1.2.3) if vendor/package is installed,
-// or null if it is provided/replaced,
-// or throws OutOfBoundsException if the package is not installed at all
-\Composer\InstalledVersions::getPrettyVersion('vendor/package');
-```
-
-```php
-// returns the package dist or source reference (e.g. a git commit hash) if vendor/package is installed,
-// or null if it is provided/replaced,
-// or throws OutOfBoundsException if the package is not installed at all
-\Composer\InstalledVersions::getReference('vendor/package');
-```
-
-### Knowing a package's own installed version
-
-If you are only interested in getting a package's own version, e.g. in the source of acme/foo you want
-to know which version acme/foo is currently running to display that to the user, then it is
-acceptable to use getVersion/getPrettyVersion/getReference.
-
-The warning in the section above does not apply in this case as you are sure the package is present
-and not being replaced if your code is running.
-
-It is nonetheless a good idea to make sure you handle the `null` return value as gracefully as
-possible for safety.
-
-----
-
-A few other methods are available for more complex usages, please refer to the
-source/docblocks of [the class itself](https://github.com/composer/composer/blob/master/src/Composer/InstalledVersions.php).
-
-### Knowing the path in which a package is installed
-
-The `getInstallPath` method to retrieve a package's absolute install path.
-
-```php
-// returns an absolute path to the package installation location if vendor/package is installed,
-// or null if it is provided/replaced, or the package is a metapackage
-// or throws OutOfBoundsException if the package is not installed at all
-\Composer\InstalledVersions::getInstallPath('vendor/package');
-```
-
-> Available as of Composer 2.1 (i.e. `composer-runtime-api ^2.1`)
-
-### Knowing which packages of a given type are installed
-
-The `getInstalledPackagesByType` method accepts a package type (e.g. foo-plugin) and lists
-the packages of that type which are installed. You can then use the methods above to retrieve
-more information about each package if needed.
-
-This method should alleviate the need for custom installers placing plugins in a specific path
-instead of leaving them in the vendor dir. You can then find plugins to initialize at runtime
-via InstalledVersions, including their paths via getInstallPath if needed.
-
-```php
-\Composer\InstalledVersions::getInstalledPackagesByType('foo-plugin');
-```
-
-> Available as of Composer 2.1 (i.e. `composer-runtime-api ^2.1`)
-
-## Platform check
-
-composer-runtime-api 2.0 introduced a new `vendor/composer/platform_check.php` file, which
-is included automatically when you include the Composer autoloader.
-
-It verifies that platform requirements (i.e. php and php extensions) are fulfilled
-by the PHP process currently running. If the requirements are not met, the script
-prints a warning with the missing requirements and exits with code 104.
-
-To avoid an unexpected white page of death with some obscure PHP extension warning in
-production, you can run `composer check-platform-reqs` as part of your
-deployment/build and if that returns a non-0 code you should abort.
-
-The default value is `php-only` which only checks the PHP version.
-
-If you for some reason do not want to use this safety check, and would rather
-risk runtime errors when your code executes, you can disable this by setting the
-[`platform-check`](06-config.md#platform-check) config option to `false`.
-
-If you want the check to include verifying the presence of PHP extensions,
-set the config option to `true`. `ext-*` requirements will then be verified
-but for performance reasons Composer only checks the extension is present,
-not its exact version.
-
-`lib-*` requirements are never supported/checked by the platform check feature.
-
-← [Config](06-config.md) | [Community](08-community.md) →
diff --git a/app/vendor/composer/composer/doc/08-community.md b/app/vendor/composer/composer/doc/08-community.md
deleted file mode 100644
index 7c48a94a8..000000000
--- a/app/vendor/composer/composer/doc/08-community.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# Community
-
-There are many people using Composer already, and quite a few of them are
-contributing.
-
-## Contributing
-
-If you would like to contribute to Composer, please read the
-[README](https://github.com/composer/composer) and
-[CONTRIBUTING](https://github.com/composer/composer/blob/master/.github/CONTRIBUTING.md)
-documents.
-
-The most important guidelines are described as follows:
-
-> All code contributions - including those of people having commit access - must
-> go through a pull request and approved by a core developer before being
-> merged. This is to ensure proper review of all the code.
->
-> Fork the project, create a feature branch, and send us a pull request.
->
-> To ensure a consistent code base, you should make sure the code follows
-> the [PSR-2 Coding Standards](https://www.php-fig.org/psr/psr-2/).
-
-## Support
-
-The IRC channel is on irc.libera.chat: [#composer](ircs://irc.libera.chat:6697/composer).
-
-[Stack Overflow](https://stackoverflow.com/questions/tagged/composer-php) and
-[GitHub Discussions](https://github.com/composer/composer/discussions) both have a
-collection of Composer related questions.
-
-For paid support, we do provide Composer-related support via chat and email to
-[Private Packagist](https://packagist.com) customers.
-
-
-← [Config](07-runtime.md)
diff --git a/app/vendor/composer/composer/doc/articles/aliases.md b/app/vendor/composer/composer/doc/articles/aliases.md
index c03ec52f2..d36eb11ff 100644
--- a/app/vendor/composer/composer/doc/articles/aliases.md
+++ b/app/vendor/composer/composer/doc/articles/aliases.md
@@ -107,5 +107,5 @@ and alias it to `1.0.x-dev`.
> inline-aliased again in A's `composer.json`.
> **Note:** Inline aliasing should be avoided, especially for published
-> packages/libraries. If you found a bug, try to get your fix merged upstream.
+> packages/libraries. If you found a bug, try and get your fix merged upstream.
> This helps to avoid issues for users of your package.
diff --git a/app/vendor/composer/composer/doc/articles/authentication-for-private-packages.md b/app/vendor/composer/composer/doc/articles/authentication-for-private-packages.md
deleted file mode 100644
index bbc21ee0d..000000000
--- a/app/vendor/composer/composer/doc/articles/authentication-for-private-packages.md
+++ /dev/null
@@ -1,301 +0,0 @@
-
-
-# Authentication for privately hosted packages and repositories
-
-Your [private package server](handling-private-packages.md) or version control system is probably secured with one
-or more authentication options. In order to allow your project to have access to these
-packages and repositories you will have to tell Composer how to authenticate with the server that hosts them.
-
-# Authentication principles
-
-Whenever Composer encounters a protected Composer repository it will try to authenticate
-using already defined credentials first. When none of those credentials apply it will prompt
-for credentials and save them (or a token if Composer is able to retrieve one).
-
-|type|Generated by Prompt?|
-|---|---|
-|[http-basic](#http-basic)|yes|
-|[Inline http-basic](#inline-http-basic)|no|
-|[Custom header](#custom-token-authentication)|no|
-|[gitlab-oauth](#gitlab-oauth)|yes|
-|[gitlab-token](#gitlab-token)|yes|
-|[github-oauth](#github-oauth)|yes|
-|[bitbucket-oauth](#bitbucket-oauth)|yes|
-
-Sometimes automatic authentication is not possible, or you may want to predefine
-authentication credentials.
-
-Credentials can be stored on 3 different places; in an `auth.json` for the project, a global
-`auth.json` or in the `composer.json` itself.
-
-## Authentication in auth.json per project
-
-In this authentication storage method, an `auth.json` file will be present in the same folder
-as the projects' `composer.json` file. You can either create and edit this file using the
-command line or manually edit or create it.
-
-> **Note: Make sure the `auth.json` file is in `.gitignore`** to avoid
-> leaking credentials into your git history.
-
-## Global authentication credentials
-
-If you don't want to supply credentials for every project you work on, storing your credentials
-globally might be a better idea. These credentials are stored in a global `auth.json` in your
-Composer home directory.
-
-### Command line global credential editing
-
-For all authentication methods it is possible to edit them using the command line;
- - [http-basic](#command-line-http-basic)
- - [Inline http-basic](#command-line-inline-http-basic)
- - [gitlab-oauth](#command-line-gitlab-oauth)
- - [gitlab-token](#command-line-gitlab-token)
- - [github-oauth](#command-line-github-oauth)
- - [bitbucket-oauth](#command-line-bitbucket-oauth)
-
-### Manually editing global authentication credentials
-
-> **Note:** It is not recommended to manually edit your authentication options as this might
-> result in invalid json. Instead preferably use [the command line](#command-line-global-credential-editing).
-
-To manually edit it, run:
-
-```sh
-composer config --global --editor [--auth]
-```
-
-For specific authentication implementations, see their sections;
- - [http-basic](#manual-http-basic)
- - [Inline http-basic](#manual-inline-http-basic)
- - [custom header](#manual-custom-token-authentication)
- - [gitlab-oauth](#manual-gitlab-oauth)
- - [gitlab-token](#manual-gitlab-token)
- - [github-oauth](#manual-github-oauth)
- - [bitbucket-oauth](#manual-bitbucket-oauth)
-
-Manually editing this file instead of using the command line may result in invalid json errors.
-To fix this you need to open the file in an editor and fix the error. To find the location of
-your global `auth.json`, execute:
-
-```sh
-composer config --global home
-```
-
-The folder will contain your global `auth.json` if it exists.
-
-You can open this file in your favorite editor and fix the error.
-
-## Authentication in composer.json file itself
-
-> **Note:** **This is not recommended** as these credentials are visible
-> to anyone who has access to the composer.json, either when it is shared through
-> a version control system like git or when an attacker gains (read) access to
-> your production server files.
-
-It is also possible to add credentials to a `composer.json` on a per-project basis in the `config`
-section or directly in the repository definition.
-
-## Authentication using the COMPOSER_AUTH environment variable
-
-> **Note:** Using the command line environment variable method also has security implications.
-> These credentials will most likely be stored in memory,
-> and on be persisted to a file like `~/.bash_history`(linux) or `ConsoleHost_history.txt`
-> (PowerShell on Windows) when closing a session.
-
-The final option to supply Composer with credentials is to use the `COMPOSER_AUTH` environment variable.
-These variables can be either passed as command line variables or set in actual environment variables.
-Read more about the usage of this environment variable [here](../03-cli.md#composer-auth).
-
-# Authentication methods
-
-## http-basic
-
-### Command line http-basic
-
-```sh
-composer config [--global] http-basic.example.org username password
-```
-
-### Manual http-basic
-
-```sh
-composer config [--global] --editor --auth
-```
-
-```json
-{
- "http-basic": {
- "example.org": {
- "username": "username",
- "password": "password"
- }
- }
-}
-```
-
-## Inline http-basic
-
-For the inline http-basic authentication method the credentials are not stored in a separate
-`auth.json` in the project or globally, but in the `composer.json` or global configuration
-in the same place where the Composer repository definition is defined.
-
-Make sure that the username and password are encoded according to [RFC 3986](http://www.faqs.org/rfcs/rfc3986.html) (2.1. Percent-Encoding).
-If the username e.g. is an email address it needs to be passed as `name%40example.com`.
-
-### Command line inline http-basic
-
-```sh
-composer config [--global] repositories composer.unique-name https://username:password@repo.example.org
-```
-
-### Manual inline http-basic
-
-```sh
-composer config [--global] --editor
-```
-
-```json
-{
- "repositories": [
- {
- "type": "composer",
- "url": "https://username:password@example.org"
- }
- ]
-}
-```
-
-## Custom token authentication
-
-### Manual custom token authentication
-
-```sh
-composer config [--global] --editor
-```
-
-```json
-{
- "repositories": [
- {
- "type": "composer",
- "url": "https://example.org",
- "options": {
- "http": {
- "header": [
- "API-TOKEN: YOUR-API-TOKEN"
- ]
- }
- }
- }
- ]
-}
-```
-
-## gitlab-oauth
-
-> **Note:** For the gitlab authentication to work on private gitlab instances, the
-> [`gitlab-domains`](../06-config.md#gitlab-domains) section should also contain the url.
-
-### Command line gitlab-oauth
-
-```sh
-composer config [--global] gitlab-oauth.example.org token
-```
-
-### Manual gitlab-oauth
-
-```sh
-composer config [--global] --editor --auth
-```
-
-```json
-{
- "gitlab-oauth": {
- "example.org": "token"
- }
-}
-```
-
-## gitlab-token
-
-> **Note:** For the gitlab authentication to work on private gitlab instances, the
-> [`gitlab-domains`](../06-config.md#gitlab-domains) section should also contain the url.
-
-To create a new access token, go to your [access tokens section on GitLab](https://gitlab.com/-/profile/personal_access_tokens)
-(or the equivalent URL on your private instance) and create a new token. See also [the GitLab access token documentation](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#creating-a-personal-access-token) for more informations.
-
-When creating a gitlab token manually, make sure it has either the `read_api` or `api` scope.
-
-### Command line gitlab-token
-
-```sh
-composer config [--global] gitlab-token.example.org token
-```
-
-### Manual gitlab-token
-
-```sh
-composer config [--global] --editor --auth
-```
-
-```json
-{
- "gitlab-token": {
- "example.org": "token"
- }
-}
-```
-
-## github-oauth
-
-To create a new access token, head to your [token settings section on Github](https://github.com/settings/tokens) and [generate a new token](https://github.com/settings/tokens/new). For public repositories when rate limited, the `public_repo` scope is required, for private repositories the `repo:status` scope is needed.
-Read more about it [here](https://github.com/blog/1509-personal-api-tokens).
-
-### Command line github-oauth
-
-```sh
-composer config [--global] github-oauth.github.com token
-```
-
-### Manual github-oauth
-
-```sh
-composer config [--global] --editor --auth
-```
-
-```json
-{
- "github-oauth": {
- "github.com": "token"
- }
-}
-```
-
-## bitbucket-oauth
-
-The BitBucket driver uses OAuth to access your private repositories via the BitBucket REST APIs, and you will need to create an OAuth consumer to use the driver, please refer to [Atlassian's Documentation](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/). You will need to fill the callback url with something to satisfy BitBucket, but the address does not need to go anywhere and is not used by Composer.
-
-### Command line bitbucket-oauth
-
-```sh
-composer config [--global] bitbucket-oauth.bitbucket.org consumer-key consumer-secret
-```
-
-### Manual bitbucket-oauth
-
-```sh
-composer config [--global] --editor --auth
-```
-
-```json
-{
- "bitbucket-oauth": {
- "bitbucket.org": {
- "consumer-key": "key",
- "consumer-secret": "secret"
- }
- }
-}
-```
diff --git a/app/vendor/composer/composer/doc/articles/autoloader-optimization.md b/app/vendor/composer/composer/doc/articles/autoloader-optimization.md
index 07a0739bf..4479e9002 100644
--- a/app/vendor/composer/composer/doc/articles/autoloader-optimization.md
+++ b/app/vendor/composer/composer/doc/articles/autoloader-optimization.md
@@ -2,7 +2,7 @@
tagline: How to reduce the performance impact of the autoloader
-->
-# Autoloader optimization
+# Autoloader Optimization
By default, the Composer autoloader runs relatively fast. However, due to the way
PSR-4 and PSR-0 autoloading rules are set up, it needs to check the filesystem
@@ -48,7 +48,7 @@ There are no real trade-offs with this method. It should always be enabled in
production.
The only issue is it does not keep track of autoload misses (i.e. when
-it cannot find a given class), so those fallback to PSR-4 rules and can still
+it can not find a given class), so those fallback to PSR-4 rules and can still
result in slow filesystem checks. To solve this issue two Level 2 optimization
options exist, and you can decide to enable either if you have a lot of
class_exists checks that are done for classes that do not exist in your project.
@@ -78,7 +78,7 @@ also means that in case a class is generated at runtime for some reason, it will
not be allowed to be autoloaded. If your project or any of your dependencies does that
then you might experience "class not found" issues in production. Enable this with care.
-> Note: This cannot be combined with Level 2/B optimizations. You have to choose one as
+> Note: This can not be combined with Level 2/B optimizations. You have to choose one as
> they address the same issue in different ways.
## Optimization Level 2/B: APCu cache
@@ -97,15 +97,15 @@ This option adds an APCu cache as a fallback for the class map. It will not
automatically generate the class map though, so you should still enable Level 1
optimizations manually if you so desire.
-Whether a class is found or not, that fact is always cached in APCu, so it can be
+Whether a class is found or not, that fact is always cached in APCu so it can be
returned quickly on the next request.
### Trade-offs
This option requires APCu which may or may not be available to you. It also
-uses APCu memory for autoloading purposes, but it is safe to use and cannot
+uses APCu memory for autoloading purposes, but it is safe to use and can not
result in classes not being found like the authoritative class map
optimization above.
-> Note: This cannot be combined with Level 2/A optimizations. You have to choose one as
+> Note: This can not be combined with Level 2/A optimizations. You have to choose one as
> they address the same issue in different ways.
diff --git a/app/vendor/composer/composer/doc/articles/custom-installers.md b/app/vendor/composer/composer/doc/articles/custom-installers.md
index 9c0ee2b65..bf327428a 100644
--- a/app/vendor/composer/composer/doc/articles/custom-installers.md
+++ b/app/vendor/composer/composer/doc/articles/custom-installers.md
@@ -6,7 +6,7 @@
## Synopsis
-At times, it may be necessary for a package to require additional actions during
+At times it may be necessary for a package to require additional actions during
installation, such as installing packages outside of the default `vendor`
library.
@@ -149,7 +149,6 @@ source for the exact signature):
when the package needs to be removed.
* **getInstallPath()**, this method should return the location where the
package is to be installed, _relative from the location of composer.json._
- The path _must not end with a slash._
Example:
diff --git a/app/vendor/composer/composer/doc/articles/handling-private-packages-with-satis.md b/app/vendor/composer/composer/doc/articles/handling-private-packages-with-satis.md
new file mode 100644
index 000000000..f1c681afc
--- /dev/null
+++ b/app/vendor/composer/composer/doc/articles/handling-private-packages-with-satis.md
@@ -0,0 +1,356 @@
+
+
+# Handling private packages
+
+# Private Packagist
+
+[Private Packagist](https://packagist.com) is a commercial package hosting product
+offering professional support and web based management of private and public packages,
+and granular access permissions. Private Packagist provides mirroring for packages' zip
+files which makes installs faster and independent from third party systems - e.g.
+you can deploy even if GitHub is down because your zip files are mirrored.
+
+Private Packagist is available as a hosted SaaS solution or as an on-premise self-hosted
+package, providing an interactive set up experience.
+
+Some of Private Packagist's revenue is used to pay for Composer and Packagist.org
+development and hosting so using it is a good way to support the maintenance of
+these open source projects financially. You can find more information about how to
+set up your own package archive on [Packagist.com](https://packagist.com).
+
+# Satis
+
+Satis on the other hand is open source but only a static `composer` repository
+generator. It is a bit like an ultra-lightweight, static file-based version of
+packagist and can be used to host the metadata of your company's private
+packages, or your own. You can get it from
+[GitHub](https://github.com/composer/satis) or install via CLI:
+
+ php composer.phar create-project composer/satis --stability=dev --keep-vcs
+
+## Setup
+
+For example let's assume you have a few packages you want to reuse across your
+company but don't really want to open-source. You would first define a Satis
+configuration: a json file with an arbitrary name that lists your curated
+[repositories](../05-repositories.md).
+
+Here is an example configuration, you see that it holds a few VCS repositories,
+but those could be any types of [repositories](../05-repositories.md). Then it
+uses `"require-all": true` which selects all versions of all packages in the
+repositories you defined.
+
+The default file Satis looks for is `satis.json` in the root of the repository.
+
+```json
+{
+ "name": "My Repository",
+ "homepage": "http://packages.example.org",
+ "repositories": [
+ { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
+ { "type": "vcs", "url": "http://svn.example.org/private/repo" },
+ { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
+ ],
+ "require-all": true
+}
+```
+
+If you want to cherry pick which packages you want, you can list all the
+packages you want to have in your satis repository inside the classic composer
+`require` key, using a `"*"` constraint to make sure all versions are selected,
+or another constraint if you want really specific versions.
+
+```json
+{
+ "repositories": [
+ { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
+ { "type": "vcs", "url": "http://svn.example.org/private/repo" },
+ { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
+ ],
+ "require": {
+ "company/package": "*",
+ "company/package2": "*",
+ "company/package3": "2.0.0"
+ }
+}
+```
+
+Once you've done this, you run:
+
+ php bin/satis build
+
+When you ironed out that process, what you would typically do is run this
+command as a cron job on a server. It would then update all your package info
+much like Packagist does.
+
+Note that if your private packages are hosted on GitHub, your server should
+have an ssh key that gives it access to those packages, and then you should add
+the `--no-interaction` (or `-n`) flag to the command to make sure it falls back
+to ssh key authentication instead of prompting for a password. This is also a
+good trick for continuous integration servers.
+
+Set up a virtual-host that points to that `web/` directory, let's say it is
+`packages.example.org`. Alternatively, with PHP >= 5.4.0, you can use the
+built-in CLI server `php -S localhost:port -t satis-output-dir/` for a
+temporary solution.
+
+### Partial Updates
+
+You can tell Satis to selectively update only particular packages or process
+only a repository with a given URL. This cuts down the time it takes to rebuild
+the `package.json` file and is helpful if you use (custom) webhooks to trigger
+rebuilds whenever code is pushed into one of your repositories.
+
+To rebuild only particular packages, pass the package names on the command line
+like so:
+
+ php bin/satis build satis.json web/ this/package that/other-package
+
+Note that this will still need to pull and scan all of your VCS repositories
+because any VCS repository might contain (on any branch) one of the selected
+packages.
+
+If you want to scan only the selected package and not all VCS repositories you need
+to declare a *name* for all your package (this only work on VCS repositories type) :
+
+```json
+{
+ "repositories": [
+ { "name": "company/privaterepo", "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
+ { "name": "private/repo", "type": "vcs", "url": "http://svn.example.org/private/repo" },
+ { "name": "mycompany/privaterepo2", "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
+ ]
+}
+```
+
+If you want to scan only a single repository and update all packages found in
+it, pass the VCS repository URL as an optional argument:
+
+ php bin/satis build --repository-url https://only.my/repo.git satis.json web/
+
+## Usage
+
+In your projects all you need to add now is your own composer repository using
+the `packages.example.org` as URL, then you can require your private packages
+and everything should work smoothly. You don't need to copy all your
+repositories in every project anymore. Only that one unique repository that
+will update itself.
+
+```json
+{
+ "repositories": [ { "type": "composer", "url": "http://packages.example.org/" } ],
+ "require": {
+ "company/package": "1.2.0",
+ "company/package2": "1.5.2",
+ "company/package3": "dev-master"
+ }
+}
+```
+
+### Security
+
+To secure your private repository you can host it over SSH or SSL using a client
+certificate. In your project you can use the `options` parameter to specify the
+connection options for the server.
+
+Example using a custom repository using SSH (requires the SSH2 PECL extension):
+
+```json
+{
+ "repositories": [{
+ "type": "composer",
+ "url": "ssh2.sftp://example.org",
+ "options": {
+ "ssh2": {
+ "username": "composer",
+ "pubkey_file": "/home/composer/.ssh/id_rsa.pub",
+ "privkey_file": "/home/composer/.ssh/id_rsa"
+ }
+ }
+ }]
+}
+```
+
+> **Tip:** See [ssh2 context options] for more information.
+
+Example using SSL/TLS (HTTPS) using a client certificate:
+
+```json
+{
+ "repositories": [{
+ "type": "composer",
+ "url": "https://example.org",
+ "options": {
+ "ssl": {
+ "local_cert": "/home/composer/.ssl/composer.pem"
+ }
+ }
+ }]
+}
+```
+
+> **Tip:** See [ssl context options] for more information.
+
+Example using a custom HTTP Header field for token authentication:
+
+```json
+{
+ "repositories": [{
+ "type": "composer",
+ "url": "https://example.org",
+ "options": {
+ "http": {
+ "header": [
+ "API-TOKEN: YOUR-API-TOKEN"
+ ]
+ }
+ }
+ }]
+}
+```
+
+### Authentication
+
+When your private repositories are password protected, you can store the
+authentication details permanently. The first time Composer needs to
+authenticate against some domain it will prompt you for a username/password and
+then you will be asked whether you want to store it.
+
+The storage can be done either globally in the `COMPOSER_HOME/auth.json` file
+(`COMPOSER_HOME` defaults to `~/.composer` or `%APPDATA%/Composer` on Windows)
+or also in the project directory directly sitting besides your composer.json.
+
+You can also configure these by hand using the config command if you need to
+configure a production machine to be able to run non-interactive installs. For
+example to enter credentials for example.org one could type:
+
+ composer config http-basic.example.org username password
+
+That will store it in the current directory's auth.json, but if you want it
+available globally you can use the `--global` (`-g`) flag.
+
+### Downloads
+
+When GitHub, GitLab or BitBucket repositories are mirrored on your local satis, the
+build process will include the location of the downloads these platforms make
+available. This means that the repository and your setup depend on the
+availability of these services.
+
+At the same time, this implies that all code which is hosted somewhere else (on
+another service or for example in Subversion) will not have downloads available
+and thus installations usually take a lot longer.
+
+To enable your satis installation to create downloads for all (Git, Mercurial
+and Subversion) your packages, add the following to your `satis.json`:
+
+``` json
+{
+ "archive": {
+ "directory": "dist",
+ "format": "tar",
+ "prefix-url": "https://amazing.cdn.example.org",
+ "skip-dev": true
+ }
+}
+```
+
+#### Options explained
+
+ * `directory`: required, the location of the dist files (inside the
+ `output-dir`)
+ * `format`: optional, `zip` (default) or `tar`
+ * `prefix-url`: optional, location of the downloads, homepage (from
+ `satis.json`) followed by `directory` by default
+ * `skip-dev`: optional, `false` by default, when enabled (`true`) satis will
+ not create downloads for branches
+ * `absolute-directory`: optional, a _local_ directory where the dist files are
+ dumped instead of `output-dir`/`directory`
+ * `whitelist`: optional, if set as a list of package names, satis will only
+ dump the dist files of these packages
+ * `blacklist`: optional, if set as a list of package names, satis will not
+ dump the dist files of these packages
+ * `checksum`: optional, `true` by default, when disabled (`false`) satis will
+ not provide the sha1 checksum for the dist files
+
+Once enabled, all downloads (include those from GitHub and BitBucket) will be
+replaced with a _local_ version.
+
+#### prefix-url
+
+Prefixing the URL with another host is especially helpful if the downloads end
+up in a private Amazon S3 bucket or on a CDN host. A CDN would drastically
+improve download times and therefore package installation.
+
+Example: A `prefix-url` of `https://my-bucket.s3.amazonaws.com` (and
+`directory` set to `dist`) creates download URLs which look like the following:
+`https://my-bucket.s3.amazonaws.com/dist/vendor-package-version-ref.zip`.
+
+### Web outputs
+
+ * `output-html`: optional, `true` by default, when disabled (`false`) satis
+ will not generate the `output-dir`/index.html page.
+ * `twig-template`: optional, a path to a personalized [Twig] template for
+ the `output-dir`/index.html page.
+
+### Abandoned packages
+
+To enable your satis installation to indicate that some packages are abandoned,
+add the following to your `satis.json`:
+
+```json
+{
+ "abandoned": {
+ "company/package": true,
+ "company/package2": "company/newpackage"
+ }
+}
+```
+
+The `true` value indicates that the package is truly abandoned while the
+`"company/newpackage"` value specifies that the package is replaced by the
+`company/newpackage` package.
+
+Note that all packages set as abandoned in their own `composer.json` file will
+be marked abandoned as well.
+
+### Resolving dependencies
+
+It is possible to make satis automatically resolve and add all dependencies for
+your projects. This can be used with the Downloads functionality to have a
+complete local mirror of packages. Add the following to your `satis.json`:
+
+```json
+{
+ "require-dependencies": true,
+ "require-dev-dependencies": true
+}
+```
+
+When searching for packages, satis will attempt to resolve all the required
+packages from the listed repositories. Therefore, if you are requiring a
+package from Packagist, you will need to define it in your `satis.json`.
+
+Dev dependencies are packaged only if the `require-dev-dependencies` parameter
+is set to true.
+
+### Other options
+
+ * `providers`: optional, `false` by default, when enabled (`true`) each
+ package will be dumped into a separate include file which will be only
+ loaded by composer when the package is really required. Speeds up composer
+ handling for repositories with huge number of packages like f.i. packagist.
+ * `output-dir`: optional, defines where to output the repository files if not
+ provided as an argument when calling the `build` command.
+ * `config`: optional, lets you define all config options from composer, except
+ `archive-format` and `archive-dir` as the configuration is done through
+ [archive](#downloads) instead. See docs on [config schema] for more details.
+ * `notify-batch`: optional, specify a URL that will be called every time a
+ user installs a package. See [notify-batch].
+
+[ssh2 context options]: https://secure.php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-options
+[ssl context options]: https://secure.php.net/manual/en/context.ssl.php
+[Twig]: https://twig.sensiolabs.org/
+[config schema]: https://getcomposer.org/doc/04-schema.md#config
+[notify-batch]: https://getcomposer.org/doc/05-repositories.md#notify-batch
diff --git a/app/vendor/composer/composer/doc/articles/handling-private-packages.md b/app/vendor/composer/composer/doc/articles/handling-private-packages.md
deleted file mode 100644
index 6dd0b8ee9..000000000
--- a/app/vendor/composer/composer/doc/articles/handling-private-packages.md
+++ /dev/null
@@ -1,340 +0,0 @@
-
-
-# Handling private packages
-
-# Private Packagist
-
-[Private Packagist](https://packagist.com) is a commercial package hosting product
-offering professional support and web based management of private and public packages,
-and granular access permissions. Private Packagist provides mirroring for packages' zip
-files which makes installs faster and independent from third party systems - e.g.
-you can deploy even if GitHub is down because your zip files are mirrored.
-
-Private Packagist is available as a hosted SaaS solution or as an on-premise self-hosted
-package, providing an interactive set up experience.
-
-Some of Private Packagist's revenue is used to pay for Composer and Packagist.org
-development and hosting so using it is a good way to support the maintenance of
-these open source projects financially. You can find more information about how to
-set up your own package archive on [Packagist.com](https://packagist.com).
-
-# Satis
-
-Satis on the other hand is open source but only a static `composer` repository
-generator. It is a bit like an ultra-lightweight, static file-based version of
-packagist and can be used to host the metadata of your company's private
-packages, or your own. You can get it from
-[GitHub](https://github.com/composer/satis) or install via CLI:
-
- php composer.phar create-project composer/satis --stability=dev --keep-vcs
-
-## Setup
-
-For example let's assume you have a few packages you want to reuse across your
-company but don't really want to open-source. You would first define a Satis
-configuration: a json file with an arbitrary name that lists your curated
-[repositories](../05-repositories.md).
-
-Here is an example configuration, you see that it holds a few VCS repositories,
-but those could be any types of [repositories](../05-repositories.md). Then it
-uses `"require-all": true` which selects all versions of all packages in the
-repositories you defined.
-
-The default file Satis looks for is `satis.json` in the root of the repository.
-
-```json
-{
- "name": "My Repository",
- "homepage": "http://packages.example.org",
- "repositories": [
- { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
- { "type": "vcs", "url": "http://svn.example.org/private/repo" },
- { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
- ],
- "require-all": true
-}
-```
-
-If you want to cherry pick which packages you want, you can list all the
-packages you want to have in your satis repository inside the classic composer
-`require` key, using a `"*"` constraint to make sure all versions are selected,
-or another constraint if you want really specific versions.
-
-```json
-{
- "repositories": [
- { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
- { "type": "vcs", "url": "http://svn.example.org/private/repo" },
- { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
- ],
- "require": {
- "company/package": "*",
- "company/package2": "*",
- "company/package3": "2.0.0"
- }
-}
-```
-
-Once you've done this, you run:
-
- php bin/satis build
-
-When you ironed out that process, what you would typically do is run this
-command as a cron job on a server. It would then update all your package info
-much like Packagist does.
-
-Note that if your private packages are hosted on GitHub, your server should
-have an ssh key that gives it access to those packages, and then you should add
-the `--no-interaction` (or `-n`) flag to the command to make sure it falls back
-to ssh key authentication instead of prompting for a password. This is also a
-good trick for continuous integration servers.
-
-Set up a virtual-host that points to that `web/` directory, let's say it is
-`packages.example.org`. Alternatively, with PHP >= 5.4.0, you can use the
-built-in CLI server `php -S localhost:port -t satis-output-dir/` for a
-temporary solution.
-
-### Partial Updates
-
-You can tell Satis to selectively update only particular packages or process
-only a repository with a given URL. This cuts down the time it takes to rebuild
-the `package.json` file and is helpful if you use (custom) webhooks to trigger
-rebuilds whenever code is pushed into one of your repositories.
-
-To rebuild only particular packages, pass the package names on the command line
-like so:
-
- php bin/satis build satis.json web/ this/package that/other-package
-
-Note that this will still need to pull and scan all of your VCS repositories
-because any VCS repository might contain (on any branch) one of the selected
-packages.
-
-If you want to scan only the selected package and not all VCS repositories you need
-to declare a *name* for all your package (this only work on VCS repositories type) :
-
-```json
-{
- "repositories": [
- { "name": "company/privaterepo", "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
- { "name": "private/repo", "type": "vcs", "url": "http://svn.example.org/private/repo" },
- { "name": "mycompany/privaterepo2", "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
- ]
-}
-```
-
-If you want to scan only a single repository and update all packages found in
-it, pass the VCS repository URL as an optional argument:
-
- php bin/satis build --repository-url https://only.my/repo.git satis.json web/
-
-## Usage
-
-In your projects all you need to add now is your own composer repository using
-the `packages.example.org` as URL, then you can require your private packages
-and everything should work smoothly. You don't need to copy all your
-repositories in every project anymore. Only that one unique repository that
-will update itself.
-
-```json
-{
- "repositories": [ { "type": "composer", "url": "http://packages.example.org/" } ],
- "require": {
- "company/package": "1.2.0",
- "company/package2": "1.5.2",
- "company/package3": "dev-master"
- }
-}
-```
-
-### Security
-
-To secure your private repository you can host it over SSH or SSL using a client
-certificate. In your project you can use the `options` parameter to specify the
-connection options for the server.
-
-Example using a custom repository using SSH (requires the SSH2 PECL extension):
-
-```json
-{
- "repositories": [{
- "type": "composer",
- "url": "ssh2.sftp://example.org",
- "options": {
- "ssh2": {
- "username": "composer",
- "pubkey_file": "/home/composer/.ssh/id_rsa.pub",
- "privkey_file": "/home/composer/.ssh/id_rsa"
- }
- }
- }]
-}
-```
-
-> **Tip:** See [ssh2 context options] for more information.
-
-Example using SSL/TLS (HTTPS) using a client certificate:
-
-```json
-{
- "repositories": [{
- "type": "composer",
- "url": "https://example.org",
- "options": {
- "ssl": {
- "local_cert": "/home/composer/.ssl/composer.pem"
- }
- }
- }]
-}
-```
-
-> **Tip:** See [ssl context options] for more information.
-
-Example using a custom HTTP Header field for token authentication:
-
-```json
-{
- "repositories": [{
- "type": "composer",
- "url": "https://example.org",
- "options": {
- "http": {
- "header": [
- "API-TOKEN: YOUR-API-TOKEN"
- ]
- }
- }
- }]
-}
-```
-
-### Authentication
-
-Authentication can be handled in [several different ways](authentication-for-private-packages.md).
-
-### Downloads
-
-When GitHub, GitLab or BitBucket repositories are mirrored on your local satis, the
-build process will include the location of the downloads these platforms make
-available. This means that the repository and your setup depend on the
-availability of these services.
-
-At the same time, this implies that all code which is hosted somewhere else (on
-another service or for example in Subversion) will not have downloads available
-and thus installations usually take a lot longer.
-
-To enable your satis installation to create downloads for all (Git, Mercurial
-and Subversion) your packages, add the following to your `satis.json`:
-
-``` json
-{
- "archive": {
- "directory": "dist",
- "format": "tar",
- "prefix-url": "https://amazing.cdn.example.org",
- "skip-dev": true
- }
-}
-```
-
-#### Options explained
-
- * `directory`: required, the location of the dist files (inside the
- `output-dir`)
- * `format`: optional, `zip` (default) or `tar`
- * `prefix-url`: optional, location of the downloads, homepage (from
- `satis.json`) followed by `directory` by default
- * `skip-dev`: optional, `false` by default, when enabled (`true`) satis will
- not create downloads for branches
- * `absolute-directory`: optional, a _local_ directory where the dist files are
- dumped instead of `output-dir`/`directory`
- * `whitelist`: optional, if set as a list of package names, satis will only
- dump the dist files of these packages
- * `blacklist`: optional, if set as a list of package names, satis will not
- dump the dist files of these packages
- * `checksum`: optional, `true` by default, when disabled (`false`) satis will
- not provide the sha1 checksum for the dist files
-
-Once enabled, all downloads (include those from GitHub and BitBucket) will be
-replaced with a _local_ version.
-
-#### prefix-url
-
-Prefixing the URL with another host is especially helpful if the downloads end
-up in a private Amazon S3 bucket or on a CDN host. A CDN would drastically
-improve download times and therefore package installation.
-
-Example: A `prefix-url` of `https://my-bucket.s3.amazonaws.com` (and
-`directory` set to `dist`) creates download URLs which look like the following:
-`https://my-bucket.s3.amazonaws.com/dist/vendor-package-version-ref.zip`.
-
-### Web outputs
-
- * `output-html`: optional, `true` by default, when disabled (`false`) satis
- will not generate the `output-dir`/index.html page.
- * `twig-template`: optional, a path to a personalized [Twig] template for
- the `output-dir`/index.html page.
-
-### Abandoned packages
-
-To enable your satis installation to indicate that some packages are abandoned,
-add the following to your `satis.json`:
-
-```json
-{
- "abandoned": {
- "company/package": true,
- "company/package2": "company/newpackage"
- }
-}
-```
-
-The `true` value indicates that the package is truly abandoned while the
-`"company/newpackage"` value specifies that the package is replaced by the
-`company/newpackage` package.
-
-Note that all packages set as abandoned in their own `composer.json` file will
-be marked abandoned as well.
-
-### Resolving dependencies
-
-It is possible to make satis automatically resolve and add all dependencies for
-your projects. This can be used with the Downloads functionality to have a
-complete local mirror of packages. Add the following to your `satis.json`:
-
-```json
-{
- "require-dependencies": true,
- "require-dev-dependencies": true
-}
-```
-
-When searching for packages, satis will attempt to resolve all the required
-packages from the listed repositories. Therefore, if you are requiring a
-package from Packagist, you will need to define it in your `satis.json`.
-
-Dev dependencies are packaged only if the `require-dev-dependencies` parameter
-is set to true.
-
-### Other options
-
- * `providers`: optional, `false` by default, when enabled (`true`) each
- package will be dumped into a separate include file which will be only
- loaded by composer when the package is really required. Speeds up composer
- handling for repositories with huge number of packages like f.i. packagist.
- * `output-dir`: optional, defines where to output the repository files if not
- provided as an argument when calling the `build` command.
- * `config`: optional, lets you define all config options from composer, except
- `archive-format` and `archive-dir` as the configuration is done through
- [archive](#downloads) instead. See docs on [config schema] for more details.
- * `notify-batch`: optional, specify a URL that will be called every time a
- user installs a package. See [notify-batch].
-
-[ssh2 context options]: https://secure.php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-options
-[ssl context options]: https://secure.php.net/manual/en/context.ssl.php
-[Twig]: https://twig.sensiolabs.org/
-[config schema]: https://getcomposer.org/doc/04-schema.md#config
-[notify-batch]: https://getcomposer.org/doc/05-repositories.md#notify-batch
diff --git a/app/vendor/composer/composer/doc/articles/http-basic-authentication.md b/app/vendor/composer/composer/doc/articles/http-basic-authentication.md
new file mode 100644
index 000000000..fad17d28f
--- /dev/null
+++ b/app/vendor/composer/composer/doc/articles/http-basic-authentication.md
@@ -0,0 +1,59 @@
+
+
+# HTTP basic authentication
+
+Your [Satis or Private Packagist](handling-private-packages-with-satis.md) server
+could be secured with http basic authentication. In order to allow your project
+to have access to these packages you will have to tell composer how to
+authenticate with your credentials.
+
+The simplest way to provide your credentials is providing your set
+of credentials inline with the repository specification such as:
+
+```json
+{
+ "repositories": [
+ {
+ "type": "composer",
+ "url": "https://extremely:secret@repo.example.org"
+ }
+ ]
+}
+```
+
+This will basically teach composer how to authenticate automatically
+when reading packages from the provided composer repository.
+
+This does not work for everybody especially when you don't want to
+hard code your credentials into your composer.json. There is a second
+way to provide these details and it is via interaction. If you don't
+provide the authentication credentials composer will prompt you upon
+connection to enter the username and password.
+
+The third way if you want to pre-configure it is via an `auth.json` file
+located in your `COMPOSER_HOME` or besides your `composer.json`.
+
+The file should contain a set of hostnames followed each with their own
+username/password pairs, for example:
+
+```json
+{
+ "http-basic": {
+ "repo.example1.org": {
+ "username": "my-username1",
+ "password": "my-secret-password1"
+ },
+ "repo.example2.org": {
+ "username": "my-username2",
+ "password": "my-secret-password2"
+ }
+ }
+}
+```
+
+The main advantage of the auth.json file is that it can be gitignored so
+that every developer in your team can place their own credentials in there,
+which makes revocation of credentials much easier than if you all share the
+same.
diff --git a/app/vendor/composer/composer/doc/articles/plugins.md b/app/vendor/composer/composer/doc/articles/plugins.md
index df374405b..86e24d87b 100644
--- a/app/vendor/composer/composer/doc/articles/plugins.md
+++ b/app/vendor/composer/composer/doc/articles/plugins.md
@@ -9,7 +9,7 @@
You may wish to alter or expand Composer's functionality with your own. For
example if your environment poses special requirements on the behaviour of
Composer which do not apply to the majority of its users or if you wish to
-accomplish something with Composer in a way that is not desired by most users.
+accomplish something with composer in a way that is not desired by most users.
In these cases you could consider creating a plugin to handle your
specific logic.
@@ -30,29 +30,21 @@ requirements:
multiple plugins, this can be array of class names.
3. You must require the special package called `composer-plugin-api`
to define which Plugin API versions your plugin is compatible with.
- Requiring this package doesn't actually include any extra dependencies,
- it only specifies which version of the plugin API to use.
-
-> **Note:** When developing a plugin, although not required, it's useful to add
-> a require-dev dependency on `composer/composer` to have IDE auto completion on Composer classes.
The required version of the `composer-plugin-api` follows the same [rules][7]
as a normal package's.
-The current Composer plugin API version is `2.1.0`.
+The current composer plugin API version is 1.1.0.
An example of a valid plugin `composer.json` file (with the autoloading
-part omitted and an optional require-dev dependency on `composer/composer` for IDE auto completion):
+part omitted):
```json
{
"name": "my/plugin-package",
"type": "composer-plugin",
"require": {
- "composer-plugin-api": "^2.0"
- },
- "require-dev": {
- "composer/composer": "^2.0"
+ "composer-plugin-api": "^1.1"
},
"extra": {
"class": "My\\Plugin"
@@ -102,10 +94,6 @@ and have it return an array. The array key must be the
[event name](https://getcomposer.org/doc/articles/scripts.md#event-names)
and the value is the name of the method in this class to be called.
-> **Note:** If you don't know which event to listen to, you can run a Composer
-> command with the COMPOSER_DEBUG_EVENTS=1 environment variable set, which might
-> help you identify what event you are looking for.
-
```php
public static function getSubscribedEvents()
{
@@ -173,14 +161,6 @@ class AwsPlugin implements PluginInterface, EventSubscriberInterface
$this->io = $io;
}
- public function deactivate(Composer $composer, IOInterface $io)
- {
- }
-
- public function uninstall(Composer $composer, IOInterface $io)
- {
- }
-
public static function getSubscribedEvents()
{
return array(
@@ -195,7 +175,9 @@ class AwsPlugin implements PluginInterface, EventSubscriberInterface
$protocol = parse_url($event->getProcessedUrl(), PHP_URL_SCHEME);
if ($protocol === 's3') {
- // ...
+ $awsClient = new AwsClient($this->io, $this->composer->getConfig());
+ $s3RemoteFilesystem = new S3RemoteFilesystem($this->io, $event->getRemoteFilesystem()->getOptions(), $awsClient);
+ $event->setRemoteFilesystem($s3RemoteFilesystem);
}
}
}
@@ -241,7 +223,7 @@ class Plugin implements PluginInterface, Capable
### Command provider
The [`Composer\Plugin\Capability\CommandProvider`][9] capability allows to register
-additional commands for Composer:
+additional commands for Composer :
```php
You may pass the `--no-plugins` option to Composer commands to disable all
+> You may pass the `--no-plugins` option to composer commands to disable all
> installed plugins. This may be particularly helpful if any of the plugins
> causes errors and you wish to update or uninstall it.
-## Plugin Helpers
-
-As of Composer 2, due to the fact that DownloaderInterface can sometimes return Promises
-and have been split up in more steps than they used to, we provide a [SyncHelper][11]
-to make downloading and installing packages easier.
-
-## Plugin Extra Attributes
-
-A few special plugin capabilities can be unlocked using extra attributes in the plugin's composer.json.
-
-### class
-
-[See above](#plugin-package) for an explanation of the class attribute and how it works.
-
-### plugin-modifies-downloads
-
-Some special plugins need to update package download URLs before they get downloaded.
-
-As of Composer 2.0, all packages are downloaded before they get installed. This means
-on the first installation, your plugin is not yet installed when the download occurs,
-and it does not get a chance to update the URLs on time.
-
-Specifying `{"extra": {"plugin-modifies-downloads": true}}` in your composer.json will
-hint to Composer that the plugin should be installed on its own before proceeding with
-the rest of the package downloads. This slightly slows down the overall installation
-process however, so do not use it in plugins which do not absolutely require it.
-
[1]: ../04-schema.md#type
[2]: ../04-schema.md#extra
[3]: https://github.com/composer/composer/blob/master/src/Composer/Plugin/PluginInterface.php
@@ -333,4 +288,3 @@ process however, so do not use it in plugins which do not absolutely require it.
[8]: https://github.com/composer/composer/blob/master/src/Composer/Plugin/Capable.php
[9]: https://github.com/composer/composer/blob/master/src/Composer/Plugin/Capability/CommandProvider.php
[10]: https://symfony.com/doc/current/components/console.html
-[11]: https://github.com/composer/composer/blob/master/src/Composer/Util/SyncHelper.php
diff --git a/app/vendor/composer/composer/doc/articles/repository-priorities.md b/app/vendor/composer/composer/doc/articles/repository-priorities.md
deleted file mode 100644
index e0053a80b..000000000
--- a/app/vendor/composer/composer/doc/articles/repository-priorities.md
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-# Repository priorities
-
-## Canonical repositories
-
-When Composer resolves dependencies, it will look up a given package in the
-topmost repository. If that repository does not contain the package, it
-goes on to the next one, until one repository contains it and the process ends.
-
-Canonical repositories are better for a few reasons:
-
-- Performance wise, it is more efficient to stop looking for a package once it
-has been found somewhere. It also avoids loading duplicate packages in case
-the same package is present in several of your repositories.
-- Security wise, it is safer to treat them canonically as it means that packages you
-expect to come from your most important repositories will never be loaded from
-another repository instead. Let's
-say you have a private repository which is not canonical, and you require your
-private package `foo/bar ^2.0` for example. Now if someone publishes
-`foo/bar 2.999` to packagist.org, suddenly Composer will pick that package as it
-has a higher version than your latest release (say 2.4.3), and you end up installing
-something you may not have meant to. If the private repository is canonical
-however, that 2.999 version from packagist.org will not be considered at all.
-
-There are however a few cases where you may want to specifically load some packages
-from a given repository, but not all. Or you may want a given repository to not be
-canonical, and to be only preferred if it has higher package versions than the
-repositories defined below.
-
-## Default behavior
-
-By default in Composer 2.x all repositories are canonical. Composer 1.x treated
-all repositories as non-canonical.
-
-Another default is that the packagist.org repository is always added implicitly
-as the last repository, unless you [disable it](../05-repositories.md#disabling-packagist-org).
-
-## Making repositories non-canonical
-
-You can add the canonical option to any repository to disable this default behavior
-and make sure Composer keeps looking in other repositories, even if that repository
-contains a given package.
-
-```json
-{
- "repositories": [
- {
- "type": "composer",
- "url": "https://example.org",
- "canonical": false
- }
- ]
-}
-```
-
-## Filtering packages
-
-You can also filter packages which a repository will be able to load, either by
-selecting which ones you want, or by excluding those you do not want.
-
-For example here we want to pick only the package `foo/bar` and all the packages from
-`some-vendor/` from this composer repository.
-
-```json
-{
- "repositories": [
- {
- "type": "composer",
- "url": "https://example.org",
- "only": ["foo/bar", "some-vendor/*"]
- }
- ]
-}
-```
-
-And in this other example we exclude `toy/package` from a repository, which
-we may not want to load in this project.
-
-```json
-{
- "repositories": [
- {
- "type": "composer",
- "url": "https://example.org",
- "exclude": ["toy/package"]
- }
- ]
-}
-```
-
-Both `only` and `exclude` should be arrays of package names, which can also
-contain wildcards (`*`) which will match any characters.
diff --git a/app/vendor/composer/composer/doc/articles/resolving-merge-conflicts.md b/app/vendor/composer/composer/doc/articles/resolving-merge-conflicts.md
deleted file mode 100644
index 2ee30a6d1..000000000
--- a/app/vendor/composer/composer/doc/articles/resolving-merge-conflicts.md
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-# Resolving merge conflicts
-
-When working as a team on the same Composer project, you will eventually run into a scenario
-where multiple people added, updated or removed something in the `composer.json` and
-`composer.lock` files in multiple branches. When those branches are eventually merged
-together, you will get merge conflicts. Resolving these merge conflicts is not as straight
-forward as on other files, especially not regarding the `composer.lock` file.
-
-> **Note:** It might not immediately be obvious why text based merging is not possible for
-> lock files, so let's imagine the following example where we want to merge two branches;
->
-> - Branch 1 has added package A which requires package B. Package B is locked at version `1.0.0`.
-> - Branch 2 has added package C which conflicts with all versions below `1.2.0` of package B.
->
-> A text based merge would result in package A version `1.0.0`, package B version `1.0.0`
-> and package C version `1.0.0`. This is an invalid result, as the conflict of package C
-> was not considered and would require an upgrade of package B.
-
-## 1. Reapplying changes
-
-The safest method to merge Composer files is to accept the version from one branch and apply
-the changes from the other branch.
-
-An example where we have two branches:
-
-1. Package 'A' has been added
-2. Package 'B' has been removed and package 'C' is added.
-
-To resolve the conflict when we merge these two branches:
-
-- We choose the branch that has the most changes, and accept the `composer.json` and `composer.lock`
- files from that branch. In this case, we choose the composer files from branch 2.
-- We reapply the changes from the other branch (branch 1). In this case we have to run
- ```composer require package/A``` again.
-
-## 2. Validating your merged files
-
-Before committing, make sure the resulting `composer.json` and `composer.lock` files are valid.
-To do this, run the following commands:
-
-```sh
-composer validate
-composer install [--dry-run]
-```
-
-## Important considerations
-
-Keep in mind that whenever merge conflicts occur on the lock file, the information about the exact version
-new packages were locked on for one of the branches gets lost. When package A in branch 1 is constrained
-as `^1.2.0` and locked as `1.2.0`, it might get updated when branch 2 is used as baseline and a new
-`composer require package/A:^1.2.0` is executed, as that will use the most recent version that the
-constraint allows when possible. There might be a version 1.3.0 for that package available by now, which
-will now be used instead.
-
-Choosing the correct [version constraints](../articles/versions.md) and making sure the packages adhere
-to [semantic versioning](https://semver.org/) when using
-[next significant release operators](versions.md#next-significant-release-operators) should make sure
-that merging branches does not break anything by accidentally updating a dependency.
diff --git a/app/vendor/composer/composer/doc/articles/scripts.md b/app/vendor/composer/composer/doc/articles/scripts.md
index ae43f26a0..776c56bd0 100644
--- a/app/vendor/composer/composer/doc/articles/scripts.md
+++ b/app/vendor/composer/composer/doc/articles/scripts.md
@@ -29,7 +29,6 @@ Composer fires the following named events during its execution process:
the `install` command is executed without a lock file present.
- **post-update-cmd**: occurs after the `update` command has been executed, or
after the `install` command has been executed without a lock file present.
-- **pre-status-cmd**: occurs before the `status` command is executed.
- **post-status-cmd**: occurs after the `status` command has been executed.
- **pre-archive-cmd**: occurs before the `archive` command is executed.
- **post-archive-cmd**: occurs after the `archive` command has been executed.
@@ -38,15 +37,14 @@ Composer fires the following named events during its execution process:
- **post-autoload-dump**: occurs after the autoloader has been dumped, either
during `install`/`update`, or via the `dump-autoload` command.
- **post-root-package-install**: occurs after the root package has been
- installed during the `create-project` command (but before its
- dependencies are installed).
+ installed, during the `create-project` command.
- **post-create-project-cmd**: occurs after the `create-project` command has
been executed.
### Installer Events
-- **pre-operations-exec**: occurs before the install/upgrade/.. operations
- are executed when installing a lock file.
+- **pre-dependencies-solving**: occurs before the dependencies are resolved.
+- **post-dependencies-solving**: occurs after the dependencies have been resolved.
### Package Events
@@ -63,15 +61,11 @@ Composer fires the following named events during its execution process:
- **command**: occurs before any Composer Command is executed on the CLI. It
provides you with access to the input and output objects of the program.
- **pre-file-download**: occurs before files are downloaded and allows
- you to manipulate the `HttpDownloader` object prior to downloading files
+ you to manipulate the `RemoteFilesystem` object prior to downloading files
based on the URL to be downloaded.
-- **post-file-download**: occurs after package dist files are downloaded and
- allows you to perform additional checks on the file if required.
- **pre-command-run**: occurs before a command is executed and allows you to
manipulate the `InputInterface` object's options and arguments to tweak
a command's behavior.
-- **pre-pool-create**: occurs before the Pool of packages is created, and lets
- you filter the list of packages which is going to enter the Solver.
> **Note:** Composer makes no assumptions about the state of your dependencies
> prior to `install` or `update`. Therefore, you should not specify scripts
@@ -162,11 +156,10 @@ class MyClass
}
```
-**Note:** During a Composer `install` or `update` command run, a variable named
+**Note:** During a composer install or update process, a variable named
`COMPOSER_DEV_MODE` will be added to the environment. If the command was run
with the `--no-dev` flag, this variable will be set to 0, otherwise it will be
-set to 1. The variable is also available while `dump-autoload` runs, and it
-will be set to same as the last `install` or `update` was run in.
+set to 1.
## Event classes
@@ -178,15 +171,14 @@ Depending on the [script types](#event-names) you will get various event
subclasses containing various getters with relevant data and associated
objects:
-- Base class: [`Composer\EventDispatcher\Event`](https://github.com/composer/composer/blob/master/src/Composer/EventDispatcher/Event.php)
-- Command Events: [`Composer\Script\Event`](https://github.com/composer/composer/blob/master/src/Composer/Script/Event.php)
-- Installer Events: [`Composer\Installer\InstallerEvent`](https://github.com/composer/composer/blob/master/src/Composer/Installer/InstallerEvent.php)
-- Package Events: [`Composer\Installer\PackageEvent`](https://github.com/composer/composer/blob/master/src/Composer/Installer/PackageEvent.php)
+- Base class: [`Composer\EventDispatcher\Event`](https://getcomposer.org/apidoc/master/Composer/EventDispatcher/Event.html)
+- Command Events: [`Composer\Script\Event`](https://getcomposer.org/apidoc/master/Composer/Script/Event.html)
+- Installer Events: [`Composer\Installer\InstallerEvent`](https://getcomposer.org/apidoc/master/Composer/Installer/InstallerEvent.html)
+- Package Events: [`Composer\Installer\PackageEvent`](https://getcomposer.org/apidoc/master/Composer/Installer/PackageEvent.html)
- Plugin Events:
- - init: [`Composer\EventDispatcher\Event`](https://github.com/composer/composer/blob/master/src/Composer/EventDispatcher/Event.php)
- - command: [`Composer\Plugin\CommandEvent`](https://github.com/composer/composer/blob/master/src/Composer/Plugin/CommandEvent.php)
- - pre-file-download: [`Composer\Plugin\PreFileDownloadEvent`](https://github.com/composer/composer/blob/master/src/Composer/Plugin/PreFileDownloadEvent.php)
- - post-file-download: [`Composer\Plugin\PostFileDownloadEvent`](https://github.com/composer/composer/blob/master/src/Composer/Plugin/PostFileDownloadEvent.php)
+ - init: [`Composer\EventDispatcher\Event`](https://getcomposer.org/apidoc/master/Composer/EventDispatcher/Event.html)
+ - command: [`Composer\Plugin\CommandEvent`](https://getcomposer.org/apidoc/master/Composer/Plugin/CommandEvent.html)
+ - pre-file-download: [`Composer\Plugin\PreFileDownloadEvent`](https://getcomposer.org/apidoc/master/Composer/Plugin/PreFileDownloadEvent.html)
## Running scripts manually
@@ -377,7 +369,4 @@ You can set custom script descriptions with the following in your `composer.json
}
```
-The descriptions are used in `composer list` or `composer run -l` commands to
-describe what the scripts do when the command is run.
-
> **Note:** You can only set custom descriptions of custom commands.
diff --git a/app/vendor/composer/composer/doc/articles/troubleshooting.md b/app/vendor/composer/composer/doc/articles/troubleshooting.md
index 669d4ce55..33471cd53 100644
--- a/app/vendor/composer/composer/doc/articles/troubleshooting.md
+++ b/app/vendor/composer/composer/doc/articles/troubleshooting.md
@@ -7,22 +7,22 @@ This is a list of common pitfalls on using Composer, and how to avoid them.
## General
-1. When facing any kind of problems using Composer, be sure to **work with the
- latest version**. See [self-update](../03-cli.md#self-update) for details.
-
-2. Before asking anyone, run [`composer diagnose`](../03-cli.md#diagnose) to check
+1. Before asking anyone, run [`composer diagnose`](../03-cli.md#diagnose) to check
for common problems. If it all checks out, proceed to the next steps.
+2. When facing any kind of problems using Composer, be sure to **work with the
+ latest version**. See [self-update](../03-cli.md#self-update) for details.
+
3. Make sure you have no problems with your setup by running the installer's
checks via `curl -sS https://getcomposer.org/installer | php -- --check`.
-4. Try clearing Composer's cache by running `composer clear-cache`.
-
-5. Ensure you're **installing vendors straight from your `composer.json`** via
+4. Ensure you're **installing vendors straight from your `composer.json`** via
`rm -rf vendor && composer update -v` when troubleshooting, excluding any
possible interferences with existing vendor installations or `composer.lock`
entries.
+5. Try clearing Composer's cache by running `composer clear-cache`.
+
## Package not found
1. Double-check you **don't have typos** in your `composer.json` or repository
@@ -47,39 +47,32 @@ This is a list of common pitfalls on using Composer, and how to avoid them.
In this case add the `--with-dependencies` argument **or** add all dependencies which
need an update to the command.
-## Dependencies on the root package
+## Package not found on travis-ci.org
-When your root package depends on a package which ends up depending (directly or
-indirectly) back on the root package itself, issues can occur in two cases:
-
-1. During development, if you are on a branch like `dev-main` and the branch has no
- [branch-alias](aliases.md#branch-alias) defined, and the dependency on the root package
- requires version `^2.0` for example, the `dev-main` version will not satisfy it.
- The best solution here is to make sure you first define a branch alias.
+1. Check the ["Package not found"](#package-not-found) item above.
-2. In CI (Continuous Integration) runs, the problem might be that Composer is not able
- to detect the version of the root package properly. If it is a git clone it is
- generally alright and Composer will detect the version of the current branch,
- but some CIs do shallow clones so that process can fail when testing pull requests
- and feature branches. In these cases the branch alias may then not be recognized.
+2. If the package tested is a dependency of one of its dependencies (cyclic
+ dependency), the problem might be that Composer is not able to detect the version
+ of the package properly. If it is a git clone it is generally alright and Composer
+ will detect the version of the current branch, but travis does shallow clones so
+ that process can fail when testing pull requests and feature branches in general.
The best solution is to define the version you are on via an environment variable
- called COMPOSER_ROOT_VERSION. You set it to `dev-main` for example to define
- the root package's version as `dev-main`.
- Use for example: `COMPOSER_ROOT_VERSION=dev-main composer install` to export
- the variable only for the call to composer, or you can define it globally in the
- CI env vars.
+ called COMPOSER_ROOT_VERSION. You set it to `dev-master` for example to define
+ the root package's version as `dev-master`.
+ Use: `before_script: COMPOSER_ROOT_VERSION=dev-master composer install` to export
+ the variable for the call to composer.
## Package not found in a Jenkins-build
1. Check the ["Package not found"](#package-not-found) item above.
-
-2. The git-clone / checkout within Jenkins leaves the branch in a "detached HEAD"-state. As
- a result, Composer may not able to identify the version of the current checked out branch
- and may not be able to resolve a [dependency on the root package](#dependencies-on-the-root-package).
- To solve this problem, you can use the "Additional Behaviours" -> "Check out to specific local
- branch" in your Git-settings for your Jenkins-job, where your "local branch" shall be the same
- branch as you are checking out. Using this, the checkout will not be in detached state any more
- and the dependency on the root package should become satisfied.
+2. Reason for failing is similar to the problem which can occur on travis-ci.org: The
+ git-clone / checkout within Jenkins leaves the branch in a "detached HEAD"-state. As
+ a result, Composer is not able to identify the version of the current checked out branch
+ and may not be able to resolve a cyclic dependency. To solve this problem, you can use
+ the "Additional Behaviours" -> "Check out to specific local branch" in your Git-settings
+ for your Jenkins-job, where your "local branch" shall be the same branch as you are
+ checking out. Using this, the checkout will not be in detached state any more and cyclic
+ dependency is recognized correctly.
## I have a dependency which contains a "repositories" definition in its composer.json, but it seems to be ignored.
@@ -184,7 +177,12 @@ Because of GitHub's rate limits on their API it can happen that Composer prompts
for authentication asking your username and password so it can go ahead with its work.
If you would prefer not to provide your GitHub credentials to Composer you can
-manually create a token using the [procedure documented here](authentication-for-private-packages.md#github-oauth).
+manually create a token using the following procedure:
+
+1. [Create](https://github.com/settings/tokens) an OAuth token on GitHub.
+[Read more](https://github.com/blog/1509-personal-api-tokens) on this.
+
+2. Add it to the configuration running `composer config -g github-oauth.github.com `
Now Composer should install/update without asking for authentication.
@@ -209,7 +207,6 @@ To enable the swap you can use for example:
```sh
/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
/sbin/mkswap /var/swap.1
-/bin/chmod 0600 /var/swap.1
/sbin/swapon /var/swap.1
```
You can make a permanent swap file following this [tutorial](https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04).
diff --git a/app/vendor/composer/composer/doc/articles/versions.md b/app/vendor/composer/composer/doc/articles/versions.md
index 47f1f8910..8a46be8b3 100644
--- a/app/vendor/composer/composer/doc/articles/versions.md
+++ b/app/vendor/composer/composer/doc/articles/versions.md
@@ -80,19 +80,6 @@ In the above example, if you wanted to check out the `my-feature` branch, you wo
When branch names look like versions, we have to clarify for composer that we're trying to check out a branch and not a tag. In the above example, we have two version branches: `v1` and `v2`. To get Composer to check out one of these branches, you must specify a version constraint that looks like this: `v1.x-dev`. The `.x` is an arbitrary string that Composer requires to tell it that we're talking about the `v1` branch and not a `v1` tag (alternatively, you can name the branch `v1.x` instead of `v1`). In the case of a branch with a version-like name (`v1`, in this case), you append `-dev` as a suffix, rather than using `dev-` as a prefix.
-### Stabilities
-
-Composer recognizes the following stabilities (in order of stability): dev,
-alpha, beta, RC, and stable where RC stands for release candidate. The stability
-of a version is defined by its suffix e.g version `v1.1-BETA` has a stability of
-`beta` and `v1.1-RC1` has a stability of `RC`. If such a suffix is missing
-e.g. version `v1.1` then Composer considers that version `stable`. In addition
-to that Composer automatically adds a `-dev` suffix to all numeric branches and
-prefixes all other branches imported from a VCS repository with `dev-`. In both
-cases the stability `dev` gets assigned.
-
-Keeping this in mind will help you in the next section.
-
### Minimum Stability
There's one more thing that will affect which files are checked out of a library's VCS and added to your project: Composer allows you to specify stability constraints to limit which tags are considered valid. In the above example, note that the library released a beta and two release candidates for version `1.1` before the final official release. To receive these versions when running `composer install` or `composer update`, we have to explicitly tell Composer that we are ok with release candidates and beta releases (and alpha releases, if we want those). This can be done using either a project-wide `minimum-stability` value in `composer.json` or using "stability flags" in version constraints. Read more on the [schema page](../04-schema.md#minimum-stability).
@@ -124,18 +111,13 @@ will be treated as a **logical OR**. AND has higher precedence than OR.
> unexpectedly installing versions that break backwards compatibility.
> Consider using the [caret](#caret-version-range-) operator instead for safety.
-
-> **Note:** In older versions of Composer the single pipe (`|`) was the
-> recommended alternative to the **logical OR**. Thus for backwards compatibility
-> the single pipe (`|`) will still be treated as a **logical OR**.
-
Examples:
* `>=1.0`
* `>=1.0 <2.0`
* `>=1.0 <1.1 || >=1.2`
-### Hyphenated Version Range (` - `)
+### Hyphenated Version Range ( - )
Inclusive set of versions. Partial versions on the right include are completed
with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the
@@ -144,7 +126,7 @@ with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the
Example: `1.0 - 2.0`
-### Wildcard Version Range (`.*`)
+### Wildcard Version Range (.*)
You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of
`>=1.0 <1.1`.
@@ -153,7 +135,7 @@ Example: `1.0.*`
## Next Significant Release Operators
-### Tilde Version Range (`~`)
+### Tilde Version Range (~)
The `~` operator is best explained by example: `~1.2` is equivalent to
`>=1.2 <2.0.0`, while `~1.2.3` is equivalent to `>=1.2.3 <1.3.0`. As you can see
@@ -175,9 +157,9 @@ Example: `~1.2`
> it will not allow the major number to increase trying to keep backwards
> compatibility.
-### Caret Version Range (`^`)
+### Caret Version Range (^)
-The `^` operator behaves very similarly, but it sticks closer to semantic
+The `^` operator behaves very similarly but it sticks closer to semantic
versioning, and will always allow non-breaking updates. For example `^1.2.3`
is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should
break backwards compatibility. For pre-1.0 versions it also acts with safety
@@ -219,7 +201,7 @@ setting. All available stability flags are listed on the minimum-stability
section of the [schema page](../04-schema.md#minimum-stability).
## Summary
-```jsonc
+```json
"require": {
"vendor/package": "1.3.2", // exactly 1.3.2
diff --git a/app/vendor/composer/composer/doc/faqs/how-do-i-install-a-package-to-a-custom-path-for-my-framework.md b/app/vendor/composer/composer/doc/faqs/how-do-i-install-a-package-to-a-custom-path-for-my-framework.md
index 986fd5ec8..4f95aecc7 100644
--- a/app/vendor/composer/composer/doc/faqs/how-do-i-install-a-package-to-a-custom-path-for-my-framework.md
+++ b/app/vendor/composer/composer/doc/faqs/how-do-i-install-a-package-to-a-custom-path-for-my-framework.md
@@ -7,7 +7,7 @@ the default `vendor` folder by using
If you are a **package author** and want your package installed to a custom
directory, require `composer/installers` and set the appropriate `type`.
-Specifying the package type, will override the default installer path.
+Specifying the package type, will override the default installer path.
This is common if your package is intended for a specific framework such as
CakePHP, Drupal or WordPress. Here is an example composer.json file for a
WordPress theme:
@@ -46,7 +46,7 @@ for a module that uses composer/installers, as well as putting all packages of t
```
Now the package would be installed to your folder location, rather than the default
-composer/installers determined location. In addition, `installer-paths` is
+composer/installers determined location. In addition, `installer-paths` is
order-dependent, which means moving a package by name should come before the installer
path of a `type:*` that matches the same package.
diff --git a/app/vendor/composer/composer/doc/faqs/how-to-install-composer-programmatically.md b/app/vendor/composer/composer/doc/faqs/how-to-install-composer-programmatically.md
index 6299b6d40..3b378a5ab 100644
--- a/app/vendor/composer/composer/doc/faqs/how-to-install-composer-programmatically.md
+++ b/app/vendor/composer/composer/doc/faqs/how-to-install-composer-programmatically.md
@@ -9,7 +9,7 @@ An alternative is to use this script which only works with UNIX utilities:
```bash
#!/bin/sh
-EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
+EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
diff --git a/app/vendor/composer/composer/doc/faqs/should-i-commit-the-dependencies-in-my-vendor-directory.md b/app/vendor/composer/composer/doc/faqs/should-i-commit-the-dependencies-in-my-vendor-directory.md
index 67d4133d4..14da5f5e3 100644
--- a/app/vendor/composer/composer/doc/faqs/should-i-commit-the-dependencies-in-my-vendor-directory.md
+++ b/app/vendor/composer/composer/doc/faqs/should-i-commit-the-dependencies-in-my-vendor-directory.md
@@ -25,7 +25,7 @@ If you really feel like you must do this, you have a few options:
3. Remove the `.git` directory of every dependency after the installation, then
you can add them to your git repo. You can do that with `rm -rf vendor/**/.git`
in ZSH or `find vendor/ -type d -name ".git" -exec rm -rf {} \;` in Bash.
- But this means you will have to delete those dependencies from disk before
+ but this means you will have to delete those dependencies from disk before
running composer update.
4. Add a .gitignore rule (`/vendor/**/.git`) to ignore all the vendor `.git` folders.
This approach does not require that you delete dependencies from disk prior to
diff --git a/app/vendor/composer/composer/doc/faqs/why-are-unbound-version-constraints-a-bad-idea.md b/app/vendor/composer/composer/doc/faqs/why-are-unbound-version-constraints-a-bad-idea.md
index 2039fa81b..705f823f9 100644
--- a/app/vendor/composer/composer/doc/faqs/why-are-unbound-version-constraints-a-bad-idea.md
+++ b/app/vendor/composer/composer/doc/faqs/why-are-unbound-version-constraints-a-bad-idea.md
@@ -5,7 +5,7 @@ A version constraint without an upper bound such as `*`, `>=3.4` or
This includes major versions breaking backward compatibility.
Once a release of your package is tagged, you cannot tweak its dependencies
-anymore in case a dependency breaks BC - you have to do a new release, but the
+anymore in case a dependency breaks BC - you have to do a new release but the
previous one stays broken.
The only good alternative is to define an upper bound on your constraints,
@@ -16,6 +16,6 @@ For example instead of using `>=3.4` you should use `~3.4` which allows all
versions up to `3.999` but does not include `4.0` and above. The `^` operator
works very well with libraries following [semantic versioning](https://semver.org).
-**Note:** As a package maintainer, you can help your users
+**Note:** As a package maintainer, you can make the help your users
by providing an [alias version](../articles/aliases.md) for your development
branch to allow it to match bound constraints.
diff --git a/app/vendor/composer/composer/doc/faqs/why-can't-composer-load-repositories-recursively.md b/app/vendor/composer/composer/doc/faqs/why-can't-composer-load-repositories-recursively.md
index 1dff52c40..a39aff6fb 100644
--- a/app/vendor/composer/composer/doc/faqs/why-can't-composer-load-repositories-recursively.md
+++ b/app/vendor/composer/composer/doc/faqs/why-can't-composer-load-repositories-recursively.md
@@ -24,7 +24,7 @@ their package's packages, etc, then resolve requirements. It could work, but it
slows down the initialization a lot since VCS repos can each take a few seconds,
and it could end up in a completely broken state since many versions of a package
could define the same packages inside a package repository, but with different
-dist/source. There are many ways this could go wrong.
+dist/source. There are many many ways this could go wrong.
- Fetch the repositories of root package, then fetch the repositories of the
first level dependencies, then fetch the repositories of their dependencies, etc,
diff --git a/app/vendor/composer/composer/doc/fixtures/fixtures.md b/app/vendor/composer/composer/doc/fixtures/fixtures.md
index 051d5aad3..a245f8992 100644
--- a/app/vendor/composer/composer/doc/fixtures/fixtures.md
+++ b/app/vendor/composer/composer/doc/fixtures/fixtures.md
@@ -12,10 +12,11 @@ also be used as (initial) fixtures for tests.
All these repositories contain the following packages.
-* `foo/bar` versions `1.0.0`, `1.0.1` and `1.1.0`; `dev-default` and `1.0.x-dev` branches.
- On `dev-default` and in `1.1.0`, `bar/baz` `~1.0` is required.
-* `qux/quux` only has a `dev-default` branch. It `replace`s `gar/nix`.
-* `gar/nix` has a `1.0.0` version and a `dev-default` branch. It is being replaced
+* `foo/bar` versions 1.0.0, 1.0.1 and 1.1.0; dev-default and 1.0.x-dev branches.
+ On dev-default and in 1.1.0, `bar/baz` ~1.0 is required.
+* `qux/quux` only has a dev-default branch. It `replace`s `gar/nix`.
+* `gar/nix` has a 1.0.0 version and a dev-default branch. It is being replaced
by `qux/quux`.
-* `bar/baz` has a `1.0.0` version and `1.0.x-dev` as well as `dev-default` branches.
- Additionally, `1.1.x-dev` is a branch alias for `dev-default`.
+* `bar/baz` has a 1.0.0 version and 1.0.x-dev as well as dev-default branches.
+ Additionally, 1.1.x-dev is a branch alias for dev-default.
+
diff --git a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/bar/baz$923363b3c22e73abb2e3fd891c8156dd4d0821a97fd3e428bc910833e3e46dbe.json b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/bar/baz$923363b3c22e73abb2e3fd891c8156dd4d0821a97fd3e428bc910833e3e46dbe.json
index 77739fece..94a43b019 100644
--- a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/bar/baz$923363b3c22e73abb2e3fd891c8156dd4d0821a97fd3e428bc910833e3e46dbe.json
+++ b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/bar/baz$923363b3c22e73abb2e3fd891c8156dd4d0821a97fd3e428bc910833e3e46dbe.json
@@ -47,4 +47,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/foo/bar$4baabb3303afa3e34a4d3af18fb138e5f3b79029c1f8d9ab5b477ea15776ba0a.json b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/foo/bar$4baabb3303afa3e34a4d3af18fb138e5f3b79029c1f8d9ab5b477ea15776ba0a.json
index 378b04003..7dc7cc91e 100644
--- a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/foo/bar$4baabb3303afa3e34a4d3af18fb138e5f3b79029c1f8d9ab5b477ea15776ba0a.json
+++ b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/foo/bar$4baabb3303afa3e34a4d3af18fb138e5f3b79029c1f8d9ab5b477ea15776ba0a.json
@@ -74,4 +74,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/gar/nix$5d210670cb46c8364c8e3fb449967b9bea558b971e5b082f330ae4f1d484c321.json b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/gar/nix$5d210670cb46c8364c8e3fb449967b9bea558b971e5b082f330ae4f1d484c321.json
index 68e399351..512b8d882 100644
--- a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/gar/nix$5d210670cb46c8364c8e3fb449967b9bea558b971e5b082f330ae4f1d484c321.json
+++ b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/gar/nix$5d210670cb46c8364c8e3fb449967b9bea558b971e5b082f330ae4f1d484c321.json
@@ -47,4 +47,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/provider-active$1893a061e579543822389ecd12d791c612db0c05e22d90e9286e233cacd86ed8.json b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/provider-active$1893a061e579543822389ecd12d791c612db0c05e22d90e9286e233cacd86ed8.json
index 6c45294f8..b82eb418e 100644
--- a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/provider-active$1893a061e579543822389ecd12d791c612db0c05e22d90e9286e233cacd86ed8.json
+++ b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/provider-active$1893a061e579543822389ecd12d791c612db0c05e22d90e9286e233cacd86ed8.json
@@ -13,4 +13,4 @@
"sha256": "c142d1a07ca354be46b613f59f1d601923a5a00ccc5fcce50a77ecdd461eb72d"
}
}
-}
+}
\ No newline at end of file
diff --git a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/qux/quux$c142d1a07ca354be46b613f59f1d601923a5a00ccc5fcce50a77ecdd461eb72d.json b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/qux/quux$c142d1a07ca354be46b613f59f1d601923a5a00ccc5fcce50a77ecdd461eb72d.json
index dc1b84dce..014187206 100644
--- a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/qux/quux$c142d1a07ca354be46b613f59f1d601923a5a00ccc5fcce50a77ecdd461eb72d.json
+++ b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/p/qux/quux$c142d1a07ca354be46b613f59f1d601923a5a00ccc5fcce50a77ecdd461eb72d.json
@@ -19,4 +19,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/packages.json b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/packages.json
index 35fd6e30b..65968a861 100644
--- a/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/packages.json
+++ b/app/vendor/composer/composer/doc/fixtures/repo-composer-with-providers/packages.json
@@ -6,4 +6,4 @@
"sha256": "1893a061e579543822389ecd12d791c612db0c05e22d90e9286e233cacd86ed8"
}
}
-}
+}
\ No newline at end of file
diff --git a/app/vendor/composer/composer/res/composer-repository-schema.json b/app/vendor/composer/composer/res/composer-repository-schema.json
index adcc299d6..914d8e22a 100644
--- a/app/vendor/composer/composer/res/composer-repository-schema.json
+++ b/app/vendor/composer/composer/res/composer-repository-schema.json
@@ -1,5 +1,5 @@
{
- "$schema": "https://json-schema.org/draft-04/schema#",
+ "$schema": "http://json-schema.org/draft-04/schema#",
"description": "A representation of packages metadata.",
"type": "object",
"oneOf": [
diff --git a/app/vendor/composer/composer/res/composer-schema.json b/app/vendor/composer/composer/res/composer-schema.json
index bb86996e7..84fb8c6c7 100644
--- a/app/vendor/composer/composer/res/composer-schema.json
+++ b/app/vendor/composer/composer/res/composer-schema.json
@@ -1,12 +1,13 @@
{
- "$schema": "https://json-schema.org/draft-04/schema#",
- "title": "Package",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "name": "Package",
"type": "object",
+ "additionalProperties": false,
+ "required": [ "name", "description" ],
"properties": {
"name": {
"type": "string",
- "description": "Package name, including 'vendor-name/' prefix.",
- "pattern": "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$"
+ "description": "Package name, including 'vendor-name/' prefix."
},
"type": {
"description": "Package type, either 'library' for common packages, 'composer-plugin' for plugins, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.",
@@ -40,7 +41,7 @@
"version": {
"type": "string",
"description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.",
- "pattern": "^v?\\d+(\\.\\d+){0,3}|^dev-"
+ "pattern": "^v?\\d+(((\\.\\d+)?\\.\\d+)?\\.\\d+)?|^dev-"
},
"time": {
"type": "string",
@@ -143,10 +144,6 @@
"type": "string"
}
},
- "gitlab-protocol": {
- "enum": ["git", "http", "https"],
- "description": "A protocol to force use of when creating a repository URL for the `source` value of the package metadata. One of `git` or `http`. By default, Composer will generate a git URL for private repositories and http one for public repos."
- },
"bearer": {
"type": "object",
"description": "A hash of domain name => bearer authentication token, for example {\"example.com\":\"\"}.",
@@ -162,13 +159,6 @@
"type": "boolean",
"description": "Defaults to `true`. If set to true only HTTPS URLs are allowed to be downloaded via Composer. If you really absolutely need HTTP access to something then you can disable it, but using \"Let's Encrypt\" to get a free SSL certificate is generally a better alternative."
},
- "secure-svn-domains": {
- "type": "array",
- "description": "A list of domains which should be trusted/marked as using a secure Subversion/SVN transport. By default svn:// protocol is seen as insecure and will throw. This is a better/safer alternative to disabling `secure-http` altogether.",
- "items": {
- "type": "string"
- }
- },
"cafile": {
"type": "string",
"description": "A way to set the path to the openssl CA file. In PHP 5.6+ you should rather set this via openssl.cafile in php.ini, although PHP 5.6+ should be able to detect your system CA file automatically."
@@ -246,13 +236,9 @@
"type": ["string", "integer"],
"description": "The cache max size for the files cache, defaults to \"300MiB\"."
},
- "cache-read-only": {
- "type": ["boolean"],
- "description": "Whether to use the Composer cache in read-only mode."
- },
"bin-compat": {
- "enum": ["auto", "full", "symlink"],
- "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed), can be \"full\" (compatible with both Windows and Unix-based systems) and \"symlink\" (symlink also for WSL)."
+ "enum": ["auto", "full"],
+ "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
},
"discard-changes": {
"type": ["string", "boolean"],
@@ -319,10 +305,6 @@
"lock": {
"type": "boolean",
"description": "Defaults to true. If set to false, Composer will not create a composer.lock file."
- },
- "platform-check": {
- "type": ["boolean", "string"],
- "description": "Defaults to \"php-only\" which checks only the PHP version. Setting to true will also check the presence of required PHP extensions. If set to false, Composer will not create and require a platform_check.php file as part of the autoloader bootstrap."
}
}
},
@@ -360,7 +342,7 @@
},
"classmap": {
"type": "array",
- "description": "This is an array of paths that contain classes to be included in the class-map generation process."
+ "description": "This is an array of directories that contain classes to be included in the class-map generation process."
},
"files": {
"type": "array",
@@ -372,10 +354,6 @@
"type": ["object"],
"description": "Options for creating package archives for distribution.",
"properties": {
- "name": {
- "type": "string",
- "description": "A base name for archive."
- },
"exclude": {
"type": "array",
"description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
@@ -406,7 +384,7 @@
"minimum-stability": {
"type": ["string"],
"description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
- "enum": ["dev", "alpha", "beta", "rc", "RC", "stable"]
+ "pattern": "^dev|alpha|beta|rc|RC|stable$"
},
"prefer-stable": {
"type": ["boolean"],
@@ -578,10 +556,6 @@
"type": "string"
}
},
- "default-branch": {
- "type": ["boolean"],
- "description": "Internal use only, do not specify this in composer.json. Indicates whether this version is the default branch of the linked VCS repository. Defaults to false."
- },
"abandoned": {
"type": ["boolean", "string"],
"description": "Indicates whether this package has been abandoned, it can be boolean or a package name/URL pointing to a recommended alternative. Defaults to false."
@@ -647,7 +621,7 @@
},
"classmap": {
"type": "array",
- "description": "This is an array of paths that contain classes to be included in the class-map generation process."
+ "description": "This is an array of directories that contain classes to be included in the class-map generation process."
},
"files": {
"type": "array",
@@ -676,19 +650,6 @@
"properties": {
"type": { "type": "string", "enum": ["composer"] },
"url": { "type": "string" },
- "canonical": { "type": "boolean" },
- "only": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "exclude": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"options": {
"type": "object",
"additionalProperties": true
@@ -703,19 +664,6 @@
"properties": {
"type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
"url": { "type": "string" },
- "canonical": { "type": "boolean" },
- "only": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "exclude": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"no-api": { "type": "boolean" },
"secure-http": { "type": "boolean" },
"svn-cache-credentials": { "type": "boolean" },
@@ -736,19 +684,6 @@
"properties": {
"type": { "type": "string", "enum": ["path"] },
"url": { "type": "string" },
- "canonical": { "type": "boolean" },
- "only": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "exclude": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"options": {
"type": "object",
"properties": {
@@ -763,20 +698,7 @@
"required": ["type", "url"],
"properties": {
"type": { "type": "string", "enum": ["artifact"] },
- "url": { "type": "string" },
- "canonical": { "type": "boolean" },
- "only": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "exclude": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
+ "url": { "type": "string" }
}
},
"pear-repository": {
@@ -785,19 +707,6 @@
"properties": {
"type": { "type": "string", "enum": ["pear"] },
"url": { "type": "string" },
- "canonical": { "type": "boolean" },
- "only": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "exclude": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"vendor-alias": { "type": "string" }
}
},
@@ -806,19 +715,6 @@
"required": ["type", "package"],
"properties": {
"type": { "type": "string", "enum": ["package"] },
- "canonical": { "type": "boolean" },
- "only": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "exclude": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"package": {
"oneOf": [
{ "$ref": "#/definitions/inline-package" },
diff --git a/app/vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php b/app/vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php
index 47c888ab7..88d7046c6 100644
--- a/app/vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php
+++ b/app/vendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.php
@@ -18,16 +18,10 @@
use Composer\IO\IOInterface;
use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
-use Composer\Package\RootPackageInterface;
use Composer\Repository\InstalledRepositoryInterface;
-use Composer\Repository\PlatformRepository;
-use Composer\Semver\Constraint\Bound;
-use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Util\Filesystem;
-use Composer\Util\Platform;
use Composer\Script\ScriptEvents;
use Composer\Util\PackageSorter;
-use Composer\Json\JsonFile;
/**
* @author Igor Wiedler
@@ -41,14 +35,14 @@ class AutoloadGenerator
private $eventDispatcher;
/**
- * @var ?IOInterface
+ * @var IOInterface
*/
private $io;
/**
- * @var ?bool
+ * @var bool
*/
- private $devMode = null;
+ private $devMode = false;
/**
* @var bool
@@ -60,21 +54,11 @@ class AutoloadGenerator
*/
private $apcu = false;
- /**
- * @var string|null
- */
- private $apcuPrefix;
-
/**
* @var bool
*/
private $runScripts = false;
- /**
- * @var bool|array
- */
- private $ignorePlatformReqs = false;
-
public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
{
$this->eventDispatcher = $eventDispatcher;
@@ -100,13 +84,11 @@ public function setClassMapAuthoritative($classMapAuthoritative)
/**
* Whether or not generated autoloader considers APCu caching.
*
- * @param bool $apcu
- * @param string|null $apcuPrefix
+ * @param bool $apcu
*/
- public function setApcu($apcu, $apcuPrefix = null)
+ public function setApcu($apcu)
{
$this->apcu = (bool) $apcu;
- $this->apcuPrefix = $apcuPrefix !== null ? (string) $apcuPrefix : $apcuPrefix;
}
/**
@@ -119,53 +101,13 @@ public function setRunScripts($runScripts = true)
$this->runScripts = (bool) $runScripts;
}
- /**
- * Sets whether platform requirements should be ignored
- *
- * If this is set to true, the platform check file will not be generated
- * If this is set to false, the platform check file will be generated with all requirements
- * If this is set to string[], those packages will be ignored from the platform check file
- *
- * @param array|bool $ignorePlatformReqs
- */
- public function setIgnorePlatformRequirements($ignorePlatformReqs)
- {
- if (is_array($ignorePlatformReqs)) {
- $this->ignorePlatformReqs = array_filter($ignorePlatformReqs, function ($req) {
- return PlatformRepository::isPlatformPackage($req);
- });
- } else {
- $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
- }
- }
-
- public function dump(Config $config, InstalledRepositoryInterface $localRepo, RootPackageInterface $rootPackage, InstallationManager $installationManager, $targetDir, $scanPsrPackages = false, $suffix = '')
+ public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsrPackages = false, $suffix = '')
{
if ($this->classMapAuthoritative) {
// Force scanPsrPackages when classmap is authoritative
$scanPsrPackages = true;
}
-
- // auto-set devMode based on whether dev dependencies are installed or not
- if (null === $this->devMode) {
- // we assume no-dev mode if no vendor dir is present or it is too old to contain dev information
- $this->devMode = false;
-
- $installedJson = new JsonFile($config->get('vendor-dir').'/composer/installed.json');
- if ($installedJson->exists()) {
- $installedJson = $installedJson->read();
- if (isset($installedJson['dev'])) {
- $this->devMode = $installedJson['dev'];
- }
- }
- }
-
if ($this->runScripts) {
- // set COMPOSER_DEV_MODE in case not set yet so it is available in the dump-autoload event listeners
- if (!isset($_SERVER['COMPOSER_DEV_MODE'])) {
- Platform::putEnv('COMPOSER_DEV_MODE', $this->devMode ? '1' : '0');
- }
-
$this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
'optimize' => (bool) $scanPsrPackages,
));
@@ -215,16 +157,8 @@ public function dump(Config $config, InstalledRepositoryInterface $localRepo, Ro
EOF;
// Collect information from all packages.
- $devPackageNames = $localRepo->getDevPackageNames();
- $packageMap = $this->buildPackageMap($installationManager, $rootPackage, $localRepo->getCanonicalPackages());
- if ($this->devMode) {
- // if dev mode is enabled, then we do not filter any dev packages out so disable this entirely
- $filteredDevPackages = false;
- } else {
- // if the list of dev package names is available we use that straight, otherwise pass true which means use legacy algo to figure them out
- $filteredDevPackages = $devPackageNames ?: true;
- }
- $autoloads = $this->parseAutoloads($packageMap, $rootPackage, $filteredDevPackages);
+ $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
+ $autoloads = $this->parseAutoloads($packageMap, $mainPackage, $this->devMode === false);
// Process the 'psr-0' base directories.
foreach ($autoloads['psr-0'] as $namespace => $paths) {
@@ -264,9 +198,9 @@ public function dump(Config $config, InstalledRepositoryInterface $localRepo, Ro
// add custom psr-0 autoloading if the root package has a target dir
$targetDirLoader = null;
- $mainAutoload = $rootPackage->getAutoload();
- if ($rootPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
- $levels = substr_count($filesystem->normalizePath($rootPackage->getTargetDir()), '/') + 1;
+ $mainAutoload = $mainPackage->getAutoload();
+ if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
+ $levels = substr_count($filesystem->normalizePath($mainPackage->getTargetDir()), '/') + 1;
$prefixes = implode(', ', array_map(function ($prefix) {
return var_export($prefix, true);
}, array_keys($mainAutoload['psr-0'])));
@@ -342,7 +276,6 @@ public static function autoload(\$class)
);
}
- $classMap['Composer\\InstalledVersions'] = "\$vendorDir . '/composer/InstalledVersions.php',\n";
ksort($classMap);
foreach ($classMap as $class => $code) {
$classmapFile .= ' '.var_export($class, true).' => '.$code;
@@ -350,7 +283,7 @@ public static function autoload(\$class)
$classmapFile .= ");\n";
if (!$suffix) {
- if (!$config->get('autoloader-suffix') && Filesystem::isReadable($vendorPath.'/autoload.php')) {
+ if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
$content = file_get_contents($vendorPath.'/autoload.php');
if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
$suffix = $match[1];
@@ -362,40 +295,27 @@ public static function autoload(\$class)
}
}
- $filesystem->filePutContentsIfModified($targetDir.'/autoload_namespaces.php', $namespacesFile);
- $filesystem->filePutContentsIfModified($targetDir.'/autoload_psr4.php', $psr4File);
- $filesystem->filePutContentsIfModified($targetDir.'/autoload_classmap.php', $classmapFile);
+ $this->filePutContentsIfModified($targetDir.'/autoload_namespaces.php', $namespacesFile);
+ $this->filePutContentsIfModified($targetDir.'/autoload_psr4.php', $psr4File);
+ $this->filePutContentsIfModified($targetDir.'/autoload_classmap.php', $classmapFile);
$includePathFilePath = $targetDir.'/include_paths.php';
if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
- $filesystem->filePutContentsIfModified($includePathFilePath, $includePathFileContents);
+ $this->filePutContentsIfModified($includePathFilePath, $includePathFileContents);
} elseif (file_exists($includePathFilePath)) {
unlink($includePathFilePath);
}
$includeFilesFilePath = $targetDir.'/autoload_files.php';
if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
- $filesystem->filePutContentsIfModified($includeFilesFilePath, $includeFilesFileContents);
+ $this->filePutContentsIfModified($includeFilesFilePath, $includeFilesFileContents);
} elseif (file_exists($includeFilesFilePath)) {
unlink($includeFilesFilePath);
}
- $filesystem->filePutContentsIfModified($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
- $checkPlatform = $config->get('platform-check') && $this->ignorePlatformReqs !== true;
- $platformCheckContent = null;
- if ($checkPlatform) {
- $platformCheckContent = $this->getPlatformCheck($packageMap, $this->ignorePlatformReqs ?: array(), $config->get('platform-check'), $devPackageNames);
- if (null === $platformCheckContent) {
- $checkPlatform = false;
- }
- }
- if ($checkPlatform) {
- $filesystem->filePutContentsIfModified($targetDir.'/platform_check.php', $platformCheckContent);
- } elseif (file_exists($targetDir.'/platform_check.php')) {
- unlink($targetDir.'/platform_check.php');
- }
- $filesystem->filePutContentsIfModified($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
- $filesystem->filePutContentsIfModified($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion, $checkPlatform));
+ $this->filePutContentsIfModified($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
+ $this->filePutContentsIfModified($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
+ $this->filePutContentsIfModified($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
- $filesystem->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
- $filesystem->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
+ $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
+ $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
if ($this->runScripts) {
$this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
@@ -406,6 +326,16 @@ public static function autoload(\$class)
return count($classMap);
}
+ private function filePutContentsIfModified($path, $content)
+ {
+ $currentContent = @file_get_contents($path);
+ if (!$currentContent || ($currentContent != $content)) {
+ return file_put_contents($path, $content);
+ }
+
+ return 0;
+ }
+
private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $excluded, $namespaceFilter, $autoloadType, array $classMap, array &$ambiguousClasses, array &$scannedFiles)
{
foreach ($this->generateClassMap($dir, $excluded, $namespaceFilter, $autoloadType, true, $scannedFiles) as $class => $path) {
@@ -448,13 +378,10 @@ private function generateClassMap($dir, $excluded, $namespaceFilter, $autoloadTy
return ClassMapGenerator::createMap($dir, $excluded, $showAmbiguousWarning ? $this->io : null, $namespaceFilter, $autoloadType, $scannedFiles);
}
- /**
- * @param RootPackageInterface $rootPackage
- */
- public function buildPackageMap(InstallationManager $installationManager, PackageInterface $rootPackage, array $packages)
+ public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
{
// build package => install path map
- $packageMap = array(array($rootPackage, ''));
+ $packageMap = array(array($mainPackage, ''));
foreach ($packages as $package) {
if ($package instanceof AliasPackage) {
@@ -496,30 +423,26 @@ protected function validatePackage(PackageInterface $package)
/**
* Compiles an ordered list of namespace => path mappings
*
- * @param array $packageMap array of array(package, installDir-relative-to-composer.json)
- * @param RootPackageInterface $rootPackage root package instance
- * @param bool|string[] $filteredDevPackages If an array, the list of packages that must be removed. If bool, whether to filter out require-dev packages
- * @return array array('psr-0' => array('Ns\\Foo' => array('installDir')))
+ * @param array $packageMap array of array(package, installDir-relative-to-composer.json)
+ * @param PackageInterface $mainPackage root package instance
+ * @param bool $filterOutRequireDevPackages whether to filter out require-dev packages
+ * @return array array('psr-0' => array('Ns\\Foo' => array('installDir')))
*/
- public function parseAutoloads(array $packageMap, PackageInterface $rootPackage, $filteredDevPackages = false)
+ public function parseAutoloads(array $packageMap, PackageInterface $mainPackage, $filterOutRequireDevPackages = false)
{
- $rootPackageMap = array_shift($packageMap);
- if (is_array($filteredDevPackages)) {
- $packageMap = array_filter($packageMap, function ($item) use ($filteredDevPackages) {
- return !in_array($item[0]->getName(), $filteredDevPackages, true);
- });
- } elseif ($filteredDevPackages) {
- $packageMap = $this->filterPackageMap($packageMap, $rootPackage);
+ $mainPackageMap = array_shift($packageMap);
+ if ($filterOutRequireDevPackages) {
+ $packageMap = $this->filterPackageMap($packageMap, $mainPackage);
}
$sortedPackageMap = $this->sortPackageMap($packageMap);
- $sortedPackageMap[] = $rootPackageMap;
- array_unshift($packageMap, $rootPackageMap);
+ $sortedPackageMap[] = $mainPackageMap;
+ array_unshift($packageMap, $mainPackageMap);
- $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $rootPackage);
- $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $rootPackage);
- $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $rootPackage);
- $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $rootPackage);
- $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $rootPackage);
+ $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
+ $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
+ $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
+ $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
+ $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
krsort($psr0);
krsort($psr4);
@@ -539,9 +462,9 @@ public function parseAutoloads(array $packageMap, PackageInterface $rootPackage,
* @param array $autoloads see parseAutoloads return value
* @return ClassLoader
*/
- public function createLoader(array $autoloads, $vendorDir = null)
+ public function createLoader(array $autoloads)
{
- $loader = new ClassLoader($vendorDir);
+ $loader = new ClassLoader();
if (isset($autoloads['psr-0'])) {
foreach ($autoloads['psr-0'] as $namespace => $path) {
@@ -667,159 +590,7 @@ protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $
$baseDir = "'phar://' . " . $baseDir;
}
- return $baseDir . var_export($path, true);
- }
-
- protected function getPlatformCheck(array $packageMap, array $ignorePlatformReqs, $checkPlatform, array $devPackageNames)
- {
- $lowestPhpVersion = Bound::zero();
- $requiredExtensions = array();
- $extensionProviders = array();
-
- foreach ($packageMap as $item) {
- $package = $item[0];
- foreach (array_merge($package->getReplaces(), $package->getProvides()) as $link) {
- if (preg_match('{^ext-(.+)$}iD', $link->getTarget(), $match)) {
- $extensionProviders[$match[1]][] = $link->getConstraint() ?: new MatchAllConstraint();
- }
- }
- }
-
- foreach ($packageMap as $item) {
- $package = $item[0];
- // skip dev dependencies platform requirements as platform-check really should only be a production safeguard
- if (in_array($package->getName(), $devPackageNames, true)) {
- continue;
- }
-
- foreach ($package->getRequires() as $link) {
- if (in_array($link->getTarget(), $ignorePlatformReqs, true)) {
- continue;
- }
-
- if ('php' === $link->getTarget() && ($constraint = $link->getConstraint())) {
- if ($constraint->getLowerBound()->compareTo($lowestPhpVersion, '>')) {
- $lowestPhpVersion = $constraint->getLowerBound();
- }
- }
-
- if ($checkPlatform === true && preg_match('{^ext-(.+)$}iD', $link->getTarget(), $match)) {
- // skip extension checks if they have a valid provider/replacer
- if (isset($extensionProviders[$match[1]])) {
- foreach ($extensionProviders[$match[1]] as $provided) {
- if (!$link->getConstraint() || $provided->matches($link->getConstraint())) {
- continue 2;
- }
- }
- }
-
- if ($match[1] === 'zend-opcache') {
- $match[1] = 'zend opcache';
- }
-
- $extension = var_export($match[1], true);
- if ($match[1] === 'pcntl' || $match[1] === 'readline') {
- $requiredExtensions[$extension] = "PHP_SAPI !== 'cli' || extension_loaded($extension) || \$missingExtensions[] = $extension;\n";
- } else {
- $requiredExtensions[$extension] = "extension_loaded($extension) || \$missingExtensions[] = $extension;\n";
- }
- }
- }
- }
-
- ksort($requiredExtensions);
-
- $formatToPhpVersionId = function (Bound $bound) {
- if ($bound->isZero()) {
- return 0;
- }
-
- if ($bound->isPositiveInfinity()) {
- return 99999;
- }
-
- $version = str_replace('-', '.', $bound->getVersion());
- $chunks = array_map('intval', explode('.', $version));
-
- return $chunks[0] * 10000 + $chunks[1] * 100 + $chunks[2];
- };
-
- $formatToHumanReadable = function (Bound $bound) {
- if ($bound->isZero()) {
- return 0;
- }
-
- if ($bound->isPositiveInfinity()) {
- return 99999;
- }
-
- $version = str_replace('-', '.', $bound->getVersion());
- $chunks = explode('.', $version);
- $chunks = array_slice($chunks, 0, 3);
-
- return implode('.', $chunks);
- };
-
- $requiredPhp = '';
- $requiredPhpError = '';
- if (!$lowestPhpVersion->isZero()) {
- $operator = $lowestPhpVersion->isInclusive() ? '>=' : '>';
- $requiredPhp = 'PHP_VERSION_ID '.$operator.' '.$formatToPhpVersionId($lowestPhpVersion);
- $requiredPhpError = '"'.$operator.' '.$formatToHumanReadable($lowestPhpVersion).'"';
- }
-
- if ($requiredPhp) {
- $requiredPhp = <<= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if (\$useStaticLoader) {
- require __DIR__ . '/autoload_static.php';
+ require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
} else {
@@ -945,9 +704,9 @@ public static function getLoader()
}
if ($this->apcu) {
- $apcuPrefix = var_export(($this->apcuPrefix !== null ? $this->apcuPrefix : substr(base64_encode(md5(uniqid('', true), true)), 0, -3)), true);
+ $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
$file .= <<setApcuPrefix($apcuPrefix);
+ \$loader->setApcuPrefix('$apcuPrefix');
APCU;
}
@@ -1113,7 +872,7 @@ public static function getInitializer(ClassLoader \$loader)
INITIALIZER;
}
- protected function parseAutoloadsType(array $packageMap, $type, RootPackageInterface $rootPackage)
+ protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
{
$autoloads = array();
@@ -1121,7 +880,7 @@ protected function parseAutoloadsType(array $packageMap, $type, RootPackageInter
list($package, $installPath) = $item;
$autoload = $package->getAutoload();
- if ($this->devMode && $package === $rootPackage) {
+ if ($this->devMode && $package === $mainPackage) {
$autoload = array_merge_recursive($autoload, $package->getDevAutoload());
}
@@ -1129,15 +888,15 @@ protected function parseAutoloadsType(array $packageMap, $type, RootPackageInter
if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
continue;
}
- if (null !== $package->getTargetDir() && $package !== $rootPackage) {
+ if (null !== $package->getTargetDir() && $package !== $mainPackage) {
$installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
}
foreach ($autoload[$type] as $namespace => $paths) {
foreach ((array) $paths as $path) {
- if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !Filesystem::isReadable($installPath.'/'.$path)) {
+ if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
// remove target-dir from file paths of the root package
- if ($package === $rootPackage) {
+ if ($package === $mainPackage) {
$targetDir = str_replace('\\', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '', $package->getTargetDir())));
$path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
} else {
@@ -1151,7 +910,8 @@ protected function parseAutoloadsType(array $packageMap, $type, RootPackageInter
$path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
// add support for wildcards * and **
- $path = strtr($path, array('\\*\\*' => '.+?', '\\*' => '[^/]+?'));
+ $path = str_replace('\\*\\*', '.+?', $path);
+ $path = str_replace('\\*', '[^/]+?', $path);
// add support for up-level relative paths
$updir = null;
@@ -1181,8 +941,7 @@ function ($matches) use (&$updir) {
if ($type === 'files') {
$autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
continue;
- }
- if ($type === 'classmap') {
+ } elseif ($type === 'classmap') {
$autoloads[] = $relativePath;
continue;
}
@@ -1203,11 +962,11 @@ protected function getFileIdentifier(PackageInterface $package, $path)
/**
* Filters out dev-dependencies
*
- * @param array $packageMap
- * @param RootPackageInterface $rootPackage
+ * @param array $packageMap
+ * @param PackageInterface $mainPackage
* @return array
*/
- protected function filterPackageMap(array $packageMap, RootPackageInterface $rootPackage)
+ protected function filterPackageMap(array $packageMap, PackageInterface $mainPackage)
{
$packages = array();
$include = array();
@@ -1236,7 +995,7 @@ protected function filterPackageMap(array $packageMap, RootPackageInterface $roo
}
}
};
- $add($rootPackage);
+ $add($mainPackage);
return array_filter(
$packageMap,
@@ -1284,4 +1043,51 @@ protected function sortPackageMap(array $packageMap)
return $sortedPackageMap;
}
+
+ /**
+ * Copy file using stream_copy_to_stream to work around https://bugs.php.net/bug.php?id=6463
+ *
+ * @param string $source
+ * @param string $target
+ */
+ protected function safeCopy($source, $target)
+ {
+ if (!file_exists($target) || !file_exists($source) || !$this->filesAreEqual($source, $target)) {
+ $source = fopen($source, 'r');
+ $target = fopen($target, 'w+');
+
+ stream_copy_to_stream($source, $target);
+ fclose($source);
+ fclose($target);
+ }
+ }
+
+ /**
+ * compare 2 files
+ * https://stackoverflow.com/questions/3060125/can-i-use-file-get-contents-to-compare-two-files
+ */
+ private function filesAreEqual($a, $b)
+ {
+ // Check if filesize is different
+ if (filesize($a) !== filesize($b)) {
+ return false;
+ }
+
+ // Check if content is different
+ $ah = fopen($a, 'rb');
+ $bh = fopen($b, 'rb');
+
+ $result = true;
+ while (!feof($ah)) {
+ if (fread($ah, 8192) != fread($bh, 8192)) {
+ $result = false;
+ break;
+ }
+ }
+
+ fclose($ah);
+ fclose($bh);
+
+ return $result;
+ }
}
diff --git a/app/vendor/composer/composer/src/Composer/Autoload/ClassLoader.php b/app/vendor/composer/composer/src/Composer/Autoload/ClassLoader.php
index 0cd6055d1..03b9bb9c4 100644
--- a/app/vendor/composer/composer/src/Composer/Autoload/ClassLoader.php
+++ b/app/vendor/composer/composer/src/Composer/Autoload/ClassLoader.php
@@ -37,80 +37,26 @@
*
* @author Fabien Potencier
* @author Jordi Boggiano
- * @see https://www.php-fig.org/psr/psr-0/
- * @see https://www.php-fig.org/psr/psr-4/
+ * @see http://www.php-fig.org/psr/psr-0/
+ * @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
- /** @var ?string */
- private $vendorDir;
-
// PSR-4
- /**
- * @var array[]
- * @psalm-var array>
- */
private $prefixLengthsPsr4 = array();
- /**
- * @var array[]
- * @psalm-var array>
- */
private $prefixDirsPsr4 = array();
- /**
- * @var array[]
- * @psalm-var array
- */
private $fallbackDirsPsr4 = array();
// PSR-0
- /**
- * @var array[]
- * @psalm-var array>
- */
private $prefixesPsr0 = array();
- /**
- * @var array[]
- * @psalm-var array
- */
private $fallbackDirsPsr0 = array();
- /** @var bool */
private $useIncludePath = false;
-
- /**
- * @var string[]
- * @psalm-var array
- */
private $classMap = array();
-
- /** @var bool */
private $classMapAuthoritative = false;
-
- /**
- * @var bool[]
- * @psalm-var array
- */
private $missingClasses = array();
-
- /** @var ?string */
private $apcuPrefix;
- /**
- * @var self[]
- */
- private static $registeredLoaders = array();
-
- /**
- * @param ?string $vendorDir
- */
- public function __construct($vendorDir = null)
- {
- $this->vendorDir = $vendorDir;
- }
-
- /**
- * @return string[]
- */
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
@@ -120,47 +66,28 @@ public function getPrefixes()
return array();
}
- /**
- * @return array[]
- * @psalm-return array>
- */
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
- /**
- * @return array[]
- * @psalm-return array
- */
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
- /**
- * @return array[]
- * @psalm-return array
- */
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
- /**
- * @return string[] Array of classname => path
- * @psalm-var array
- */
public function getClassMap()
{
return $this->classMap;
}
/**
- * @param string[] $classMap Class to filename map
- * @psalm-param array $classMap
- *
- * @return void
+ * @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
@@ -175,11 +102,9 @@ public function addClassMap(array $classMap)
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 root directories
- * @param bool $prepend Whether to prepend the directories
- *
- * @return void
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
@@ -222,13 +147,11 @@ public function add($prefix, $paths, $prepend = false)
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param string[]|string $paths The PSR-4 base directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
- *
- * @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
@@ -272,10 +195,8 @@ public function addPsr4($prefix, $paths, $prepend = false)
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 base directories
- *
- * @return void
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
@@ -290,12 +211,10 @@ public function set($prefix, $paths)
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param string[]|string $paths The PSR-4 base directories
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
- *
- * @return void
*/
public function setPsr4($prefix, $paths)
{
@@ -315,8 +234,6 @@ public function setPsr4($prefix, $paths)
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
- *
- * @return void
*/
public function setUseIncludePath($useIncludePath)
{
@@ -339,8 +256,6 @@ public function getUseIncludePath()
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
- *
- * @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
@@ -361,8 +276,6 @@ public function isClassMapAuthoritative()
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
- *
- * @return void
*/
public function setApcuPrefix($apcuPrefix)
{
@@ -383,44 +296,25 @@ public function getApcuPrefix()
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
- *
- * @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
-
- if (null === $this->vendorDir) {
- return;
- }
-
- if ($prepend) {
- self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
- } else {
- unset(self::$registeredLoaders[$this->vendorDir]);
- self::$registeredLoaders[$this->vendorDir] = $this;
- }
}
/**
* Unregisters this instance as an autoloader.
- *
- * @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
-
- if (null !== $this->vendorDir) {
- unset(self::$registeredLoaders[$this->vendorDir]);
- }
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
- * @return true|null True if loaded, null otherwise
+ * @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
@@ -429,8 +323,6 @@ public function loadClass($class)
return true;
}
-
- return null;
}
/**
@@ -475,21 +367,6 @@ public function findFile($class)
return $file;
}
- /**
- * Returns the currently registered loaders indexed by their corresponding vendor directories.
- *
- * @return self[]
- */
- public static function getRegisteredLoaders()
- {
- return self::$registeredLoaders;
- }
-
- /**
- * @param string $class
- * @param string $ext
- * @return string|false
- */
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
@@ -561,10 +438,6 @@ private function findFileWithExtension($class, $ext)
* Scope isolated include.
*
* Prevents access to $this/self from included files.
- *
- * @param string $file
- * @return void
- * @private
*/
function includeFile($file)
{
diff --git a/app/vendor/composer/composer/src/Composer/Autoload/ClassMapGenerator.php b/app/vendor/composer/composer/src/Composer/Autoload/ClassMapGenerator.php
index dfe255a54..0724d5dd6 100644
--- a/app/vendor/composer/composer/src/Composer/Autoload/ClassMapGenerator.php
+++ b/app/vendor/composer/composer/src/Composer/Autoload/ClassMapGenerator.php
@@ -33,8 +33,8 @@ class ClassMapGenerator
/**
* Generate a class map file
*
- * @param \Traversable|array $dirs Directories or a single path to search in
- * @param string $file The name of the class map file
+ * @param \Traversable $dirs Directories or a single path to search in
+ * @param string $file The name of the class map file
*/
public static function dump($dirs, $file)
{
@@ -50,22 +50,22 @@ public static function dump($dirs, $file)
/**
* Iterate over all files in the given directory searching for classes
*
- * @param \Traversable|string|array $path The path to search in or an iterator
- * @param string $excluded Regex that matches file paths to be excluded from the classmap
- * @param ?IOInterface $io IO object
- * @param ?string $namespace Optional namespace prefix to filter by
- * @param ?string $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules
+ * @param \Iterator|string $path The path to search in or an iterator
+ * @param string $excluded Regex that matches file paths to be excluded from the classmap
+ * @param IOInterface $io IO object
+ * @param string $namespace Optional namespace prefix to filter by
+ * @param string $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules
*
* @throws \RuntimeException When the path is neither an existing file nor directory
* @return array A class map array
*/
public static function createMap($path, $excluded = null, IOInterface $io = null, $namespace = null, $autoloadType = null, &$scannedFiles = array())
{
- $basePath = $path;
if (is_string($path)) {
+ $basePath = $path;
if (is_file($path)) {
$path = array(new \SplFileInfo($path));
- } elseif (is_dir($path) || strpos($path, '*') !== false) {
+ } elseif (is_dir($path)) {
$path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
} else {
throw new \RuntimeException(
@@ -113,10 +113,10 @@ public static function createMap($path, $excluded = null, IOInterface $io = null
$classes = self::findClasses($filePath);
if (null !== $autoloadType) {
- $classes = self::filterByNamespace($classes, $filePath, $namespace, $autoloadType, $basePath, $io);
+ list($classes, $validClasses) = self::filterByNamespace($classes, $filePath, $namespace, $autoloadType, $basePath, $io);
// if no valid class was found in the file then we do not mark it as scanned as it might still be matched by another rule later
- if ($classes) {
+ if ($validClasses) {
$scannedFiles[$realPath] = true;
}
} else {
@@ -126,7 +126,8 @@ public static function createMap($path, $excluded = null, IOInterface $io = null
foreach ($classes as $class) {
// skip classes not within the given namespace prefix
- if (null === $autoloadType && null !== $namespace && '' !== $namespace && 0 !== strpos($class, $namespace)) {
+ // TODO enable in Composer v1.11 or 2.0 whichever comes first
+ if (/* null === $autoloadType && */ null !== $namespace && '' !== $namespace && 0 !== strpos($class, $namespace)) {
continue;
}
@@ -147,13 +148,13 @@ public static function createMap($path, $excluded = null, IOInterface $io = null
/**
* Remove classes which could not have been loaded by namespace autoloaders
*
- * @param array $classes found classes in given file
- * @param string $filePath current file
- * @param string $baseNamespace prefix of given autoload mapping
- * @param string $namespaceType psr-0|psr-4
- * @param string $basePath root directory of given autoload mapping
- * @param ?IOInterface $io IO object
- * @return array valid classes
+ * @param array $classes found classes in given file
+ * @param string $filePath current file
+ * @param string $baseNamespace prefix of given autoload mapping
+ * @param string $namespaceType psr-0|psr-4
+ * @param string $basePath root directory of given autoload mapping
+ * @param IOInterface $io IO object
+ * @return array valid classes
*/
private static function filterByNamespace($classes, $filePath, $baseNamespace, $namespaceType, $basePath, $io)
{
@@ -176,7 +177,8 @@ private static function filterByNamespace($classes, $filePath, $baseNamespace, $
$className = substr($class, $namespaceLength + 1);
$subPath = str_replace('\\', DIRECTORY_SEPARATOR, $namespace)
. str_replace('_', DIRECTORY_SEPARATOR, $className);
- } else {
+ }
+ else {
$subPath = str_replace('_', DIRECTORY_SEPARATOR, $class);
}
} elseif ('psr-4' === $namespaceType) {
@@ -194,15 +196,19 @@ private static function filterByNamespace($classes, $filePath, $baseNamespace, $
// warn only if no valid classes, else silently skip invalid
if (empty($validClasses)) {
foreach ($rejectedClasses as $class) {
- if ($io) {
- $io->writeError("Class $class located in ".preg_replace('{^'.preg_quote(getcwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. Skipping. ");
- }
+ trigger_error(
+ "Class $class located in ".preg_replace('{^'.preg_quote(getcwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. It will not autoload anymore in Composer v2.0.",
+ E_USER_DEPRECATED
+ );
}
- return array();
+ // TODO enable in Composer 2.0
+ //return array();
}
- return $validClasses;
+ // TODO enable in Composer 2.0 & unskip test in AutoloadGeneratorTest::testPSRToClassMapIgnoresNonPSRClasses
+ //return $validClasses;
+ return array($classes, $validClasses);
}
/**
@@ -215,7 +221,7 @@ private static function filterByNamespace($classes, $filePath, $baseNamespace, $
private static function findClasses($path)
{
$extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
- if (PHP_VERSION_ID >= 80100 || (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>='))) {
+ if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
$extraTypes .= '|enum';
}
@@ -225,7 +231,7 @@ private static function findClasses($path)
if (!$contents) {
if (!file_exists($path)) {
$message = 'File at "%s" does not exist, check your classmap definitions';
- } elseif (!Filesystem::isReadable($path)) {
+ } elseif (!is_readable($path)) {
$message = 'File at "%s" is not readable, check its permissions';
} elseif ('' === trim(file_get_contents($path))) {
// The input file was really empty and thus contains no classes
@@ -246,36 +252,11 @@ private static function findClasses($path)
}
// strip heredocs/nowdocs
- $heredocRegex = '{
- # opening heredoc/nowdoc delimiter (word-chars)
- <<<[ \t]*+([\'"]?)(\w++)\\1
- # needs to be followed by a newline
- (?:\r\n|\n|\r)
- # the meat of it, matching line by line until end delimiter
- (?:
- # a valid line is optional white-space (possessive match) not followed by the end delimiter, then anything goes for the rest of the line
- [\t ]*+(?!\\2 \b)[^\r\n]*+
- # end of line(s)
- [\r\n]++
- )*
- # end delimiter
- [\t ]*+ \\2 (?=\b)
- }x';
-
- // run first assuming the file is valid unicode
- $contentWithoutHeredoc = preg_replace($heredocRegex.'u', 'null', $contents);
- if (null === $contentWithoutHeredoc) {
- // run again without unicode support if the file failed to be parsed
- $contents = preg_replace($heredocRegex, 'null', $contents);
- } else {
- $contents = $contentWithoutHeredoc;
- }
- unset($contentWithoutHeredoc);
-
+ $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
// strip strings
$contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
// strip leading non-php code if needed
- if (strpos($contents, '') !== 0) {
+ if (substr($contents, 0, 2) !== '') {
$contents = preg_replace('{^.+?<\?}s', '', $contents, 1, $replacements);
if ($replacements === 0) {
return array();
diff --git a/app/vendor/composer/composer/src/Composer/Cache.php b/app/vendor/composer/composer/src/Composer/Cache.php
index a3aaebf57..069f59d5d 100644
--- a/app/vendor/composer/composer/src/Composer/Cache.php
+++ b/app/vendor/composer/composer/src/Composer/Cache.php
@@ -24,28 +24,25 @@
*/
class Cache
{
- private static $cacheCollected = null;
+ private static $cacheCollected = false;
private $io;
private $root;
private $enabled = true;
- private $allowlist;
+ private $allowList;
private $filesystem;
- private $readOnly;
/**
* @param IOInterface $io
* @param string $cacheDir location of the cache
- * @param string $allowlist List of characters that are allowed in path names (used in a regex character class)
+ * @param string $allowList List of characters that are allowed in path names (used in a regex character class)
* @param Filesystem $filesystem optional filesystem instance
- * @param bool $readOnly whether the cache is in readOnly mode
*/
- public function __construct(IOInterface $io, $cacheDir, $allowlist = 'a-z0-9.', Filesystem $filesystem = null, $readOnly = false)
+ public function __construct(IOInterface $io, $cacheDir, $allowList = 'a-z0-9.', Filesystem $filesystem = null)
{
$this->io = $io;
$this->root = rtrim($cacheDir, '/\\') . '/';
- $this->allowlist = $allowlist;
+ $this->allowList = $allowList;
$this->filesystem = $filesystem ?: new Filesystem();
- $this->readOnly = (bool) $readOnly;
if (!self::isUsable($cacheDir)) {
$this->enabled = false;
@@ -62,22 +59,6 @@ public function __construct(IOInterface $io, $cacheDir, $allowlist = 'a-z0-9.',
}
}
- /**
- * @param bool $readOnly
- */
- public function setReadOnly($readOnly)
- {
- $this->readOnly = (bool) $readOnly;
- }
-
- /**
- * @return bool
- */
- public function isReadOnly()
- {
- return $this->readOnly;
- }
-
public static function isUsable($path)
{
return !preg_match('{(^|[\\\\/])(\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path);
@@ -96,7 +77,7 @@ public function getRoot()
public function read($file)
{
if ($this->enabled) {
- $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file);
+ $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
if (file_exists($this->root . $file)) {
$this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
@@ -109,26 +90,25 @@ public function read($file)
public function write($file, $contents)
{
- if ($this->enabled && !$this->readOnly) {
- $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file);
+ if ($this->enabled) {
+ $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
$this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
- $tempFileName = $this->root . $file . uniqid('.', true) . '.tmp';
try {
- return file_put_contents($tempFileName, $contents) !== false && rename($tempFileName, $this->root . $file);
+ return file_put_contents($this->root . $file, $contents);
} catch (\ErrorException $e) {
$this->io->writeError('Failed to write into cache: '.$e->getMessage().' ', true, IOInterface::DEBUG);
if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
// Remove partial file.
- unlink($tempFileName);
+ unlink($this->root . $file);
$message = sprintf(
'Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available ',
- $tempFileName,
+ $this->root . $file,
$m[1],
$m[2],
- @disk_free_space(dirname($tempFileName))
+ @disk_free_space($this->root . dirname($file))
);
$this->io->writeError($message);
@@ -148,8 +128,8 @@ public function write($file, $contents)
*/
public function copyFrom($file, $source)
{
- if ($this->enabled && !$this->readOnly) {
- $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file);
+ if ($this->enabled) {
+ $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
$this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
if (!file_exists($source)) {
@@ -170,7 +150,7 @@ public function copyFrom($file, $source)
public function copyTo($file, $target)
{
if ($this->enabled) {
- $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file);
+ $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
if (file_exists($this->root . $file)) {
try {
touch($this->root . $file, filemtime($this->root . $file), time());
@@ -191,26 +171,13 @@ public function copyTo($file, $target)
public function gcIsNecessary()
{
- if (self::$cacheCollected) {
- return false;
- }
-
- self::$cacheCollected = true;
- if (getenv('COMPOSER_TEST_SUITE')) {
- return false;
- }
-
- if (PHP_VERSION_ID > 70000) {
- return !random_int(0, 50);
- }
-
- return !mt_rand(0, 50);
+ return (!self::$cacheCollected && !mt_rand(0, 50));
}
public function remove($file)
{
if ($this->enabled) {
- $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file);
+ $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
if (file_exists($this->root . $file)) {
return $this->filesystem->unlink($this->root . $file);
}
@@ -223,7 +190,6 @@ public function clear()
{
if ($this->enabled) {
$this->filesystem->emptyDirectory($this->root);
-
return true;
}
@@ -263,7 +229,7 @@ public function gc($ttl, $maxSize)
public function sha1($file)
{
if ($this->enabled) {
- $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file);
+ $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
if (file_exists($this->root . $file)) {
return sha1_file($this->root . $file);
}
@@ -275,7 +241,7 @@ public function sha1($file)
public function sha256($file)
{
if ($this->enabled) {
- $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file);
+ $file = preg_replace('{[^'.$this->allowList.']}i', '-', $file);
if (file_exists($this->root . $file)) {
return hash_file('sha256', $this->root . $file);
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/AboutCommand.php b/app/vendor/composer/composer/src/Composer/Command/AboutCommand.php
index 931c20e55..bf1fa0f9c 100644
--- a/app/vendor/composer/composer/src/Composer/Command/AboutCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/AboutCommand.php
@@ -12,7 +12,6 @@
namespace Composer\Command;
-use Composer\Composer;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -25,7 +24,7 @@ protected function configure()
{
$this
->setName('about')
- ->setDescription('Shows a short information about Composer.')
+ ->setDescription('Shows the short information about Composer.')
->setHelp(
<<php composer.phar about
@@ -36,11 +35,9 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
- $composerVersion = Composer::getVersion();
-
$this->getIO()->write(
<<Composer - Dependency Manager for PHP - version $composerVersion
+Composer - Dependency Manager for PHP
Composer is a dependency manager tracking local dependencies of your projects and libraries.
See https://getcomposer.org/ for more information.
EOT
diff --git a/app/vendor/composer/composer/src/Composer/Command/ArchiveCommand.php b/app/vendor/composer/composer/src/Composer/Command/ArchiveCommand.php
index 3acf4fd04..bbe18a653 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ArchiveCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ArchiveCommand.php
@@ -16,15 +16,12 @@
use Composer\IO\IOInterface;
use Composer\Config;
use Composer\Composer;
-use Composer\Package\CompletePackageInterface;
use Composer\Repository\CompositeRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Script\ScriptEvents;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Util\Filesystem;
-use Composer\Util\Loop;
-use Composer\Util\ProcessExecutor;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -49,7 +46,7 @@ protected function configure()
new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
.' Note that the format will be appended.'),
- new InputOption('ignore-filters', null, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
+ new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
))
->setHelp(
<<getArchiveManager();
} else {
$factory = new Factory;
- $process = new ProcessExecutor();
- $httpDownloader = Factory::createHttpDownloader($io, $config);
- $downloadManager = $factory->createDownloadManager($io, $config, $httpDownloader, $process);
- $archiveManager = $factory->createArchiveManager($config, $downloadManager, new Loop($httpDownloader, $process));
+ $downloadManager = $factory->createDownloadManager($io, $config);
+ $archiveManager = $factory->createArchiveManager($config, $downloadManager);
}
if ($packageName) {
@@ -141,9 +136,6 @@ protected function archive(IOInterface $io, Config $config, $packageName = null,
return 0;
}
- /**
- * @return CompletePackageInterface|false
- */
protected function selectPackage(IOInterface $io, $packageName, $version = null)
{
$io->writeError('Searching for the specified package. ');
@@ -175,10 +167,6 @@ protected function selectPackage(IOInterface $io, $packageName, $version = null)
return false;
}
- if (!$package instanceof CompletePackageInterface) {
- throw new \LogicException('Expected a CompletePackageInterface instance but found '.get_class($package));
- }
-
return $package;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/BaseCommand.php b/app/vendor/composer/composer/src/Composer/Command/BaseCommand.php
index b473fbe80..888b2a7f2 100644
--- a/app/vendor/composer/composer/src/Composer/Command/BaseCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/BaseCommand.php
@@ -19,20 +19,14 @@
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Plugin\PreCommandRunEvent;
-use Composer\Package\Version\VersionParser;
use Composer\Plugin\PluginEvents;
-use Composer\Util\Platform;
-use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Terminal;
/**
* Base class for Composer commands
*
- * @method Application getApplication()
- *
* @author Ryan Weaver
* @author Konstantin Kudryashov
*/
@@ -52,7 +46,7 @@ abstract class BaseCommand extends Command
* @param bool $required
* @param bool|null $disablePlugins
* @throws \RuntimeException
- * @return Composer|null
+ * @return Composer
*/
public function getComposer($required = true, $disablePlugins = null)
{
@@ -61,7 +55,6 @@ public function getComposer($required = true, $disablePlugins = null)
if ($application instanceof Application) {
/* @var $application Application */
$this->composer = $application->getComposer($required, $disablePlugins);
- /** @phpstan-ignore-next-line */
} elseif ($required) {
throw new \RuntimeException(
'Could not create a Composer\Composer instance, you must inject '.
@@ -110,8 +103,8 @@ public function getIO()
if (null === $this->io) {
$application = $this->getApplication();
if ($application instanceof Application) {
+ /* @var $application Application */
$this->io = $application->getIO();
- /** @phpstan-ignore-next-line */
} else {
$this->io = new NullIO();
}
@@ -178,96 +171,11 @@ protected function getPreferredInstallOptions(Config $config, InputInterface $in
break;
}
- if ($input->hasOption('prefer-install') && $input->getOption('prefer-install')) {
- if ($input->getOption('prefer-source')) {
- throw new \InvalidArgumentException('--prefer-source can not be used together with --prefer-install');
- }
- if ($input->getOption('prefer-dist')) {
- throw new \InvalidArgumentException('--prefer-dist can not be used together with --prefer-install');
- }
- switch ($input->getOption('prefer-install')) {
- case 'dist':
- $input->setOption('prefer-dist', true);
- break;
- case 'source':
- $input->setOption('prefer-source', true);
- break;
- case 'auto':
- $preferDist = false;
- $preferSource = false;
- break;
- default:
- throw new \UnexpectedValueException('--prefer-install accepts one of "dist", "source" or "auto", got '.$input->getOption('prefer-install'));
- }
- }
-
if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
$preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
- $preferDist = (bool) $input->getOption('prefer-dist');
+ $preferDist = $input->getOption('prefer-dist');
}
return array($preferSource, $preferDist);
}
-
- protected function formatRequirements(array $requirements)
- {
- $requires = array();
- $requirements = $this->normalizeRequirements($requirements);
- foreach ($requirements as $requirement) {
- if (!isset($requirement['version'])) {
- throw new \UnexpectedValueException('Option '.$requirement['name'] .' is missing a version constraint, use e.g. '.$requirement['name'].':^1.0');
- }
- $requires[$requirement['name']] = $requirement['version'];
- }
-
- return $requires;
- }
-
- protected function normalizeRequirements(array $requirements)
- {
- $parser = new VersionParser();
-
- return $parser->parseNameVersionPairs($requirements);
- }
-
- protected function renderTable(array $table, OutputInterface $output)
- {
- $renderer = new Table($output);
- $renderer->setStyle('compact');
- $rendererStyle = $renderer->getStyle();
- if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
- $rendererStyle->setVerticalBorderChars('');
- } else {
- // TODO remove in composer 2.2
- // @phpstan-ignore-next-line
- $rendererStyle->setVerticalBorderChar('');
- }
- $rendererStyle->setCellRowContentFormat('%s ');
- $renderer->setRows($table)->render();
- }
-
- protected function getTerminalWidth()
- {
- if (class_exists('Symfony\Component\Console\Terminal')) {
- $terminal = new Terminal();
- $width = $terminal->getWidth();
- } else {
- // For versions of Symfony console before 3.2
- // TODO remove in composer 2.2
- // @phpstan-ignore-next-line
- list($width) = $this->getApplication()->getTerminalDimensions();
- }
- if (null === $width) {
- // In case the width is not detected, we're probably running the command
- // outside of a real terminal, use space without a limit
- $width = PHP_INT_MAX;
- }
- if (Platform::isWindows()) {
- $width--;
- } else {
- $width = max(80, $width);
- }
-
- return $width;
- }
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php b/app/vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php
index 962c1b2ce..34de286f8 100644
--- a/app/vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php
@@ -12,20 +12,21 @@
namespace Composer\Command;
+use Composer\DependencyResolver\Pool;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
-use Composer\Package\RootPackage;
-use Composer\Repository\InstalledArrayRepository;
+use Composer\Repository\ArrayRepository;
use Composer\Repository\CompositeRepository;
-use Composer\Repository\RootPackageRepository;
-use Composer\Repository\InstalledRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Composer\Package\Version\VersionParser;
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
@@ -36,13 +37,25 @@
class BaseDependencyCommand extends BaseCommand
{
const ARGUMENT_PACKAGE = 'package';
- const ARGUMENT_CONSTRAINT = 'version';
+ const ARGUMENT_CONSTRAINT = 'constraint';
const OPTION_RECURSIVE = 'recursive';
const OPTION_TREE = 'tree';
- /** @var ?string[] */
protected $colors;
+ /**
+ * Set common options and arguments.
+ */
+ protected function configure()
+ {
+ $this->setDefinition(array(
+ new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
+ new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
+ new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
+ new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
+ ));
+ }
+
/**
* Execute the command.
*
@@ -58,32 +71,35 @@ protected function doExecute(InputInterface $input, OutputInterface $output, $in
$commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
+ // Prepare repositories and set up a pool
$platformOverrides = $composer->getConfig()->get('platform') ?: array();
- $installedRepo = new InstalledRepository(array(
- new RootPackageRepository($composer->getPackage()),
+ $repository = new CompositeRepository(array(
+ new ArrayRepository(array($composer->getPackage())),
$composer->getRepositoryManager()->getLocalRepository(),
new PlatformRepository(array(), $platformOverrides),
));
+ $pool = new Pool();
+ $pool->addRepository($repository);
// Parse package name and constraint
list($needle, $textConstraint) = array_pad(
explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
2,
- $input->hasArgument(self::ARGUMENT_CONSTRAINT) ? $input->getArgument(self::ARGUMENT_CONSTRAINT) : '*'
+ $input->getArgument(self::ARGUMENT_CONSTRAINT)
);
// Find packages that are or provide the requested package first
- $packages = $installedRepo->findPackagesWithReplacersAndProviders($needle);
+ $packages = $pool->whatProvides(strtolower($needle));
if (empty($packages)) {
throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
}
// If the version we ask for is not installed then we need to locate it in remote repos and add it.
// This is needed for why-not to resolve conflicts from an uninstalled version against installed packages.
- if (!$installedRepo->findPackage($needle, $textConstraint)) {
+ if (!$repository->findPackage($needle, $textConstraint)) {
$defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
- $installedRepo->addRepository(new InstalledArrayRepository(array(clone $match)));
+ $repository->addRepository(new ArrayRepository(array(clone $match)));
}
}
@@ -110,7 +126,7 @@ protected function doExecute(InputInterface $input, OutputInterface $output, $in
$recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
// Resolve dependencies
- $results = $installedRepo->getDependents($needles, $constraint, $inverted, $recursive);
+ $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
if (empty($results)) {
$extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
$this->getIO()->writeError(sprintf(
@@ -154,7 +170,7 @@ protected function printTable(OutputInterface $output, $results)
continue;
}
$doubles[$unique] = true;
- $version = $package->getPrettyVersion() === RootPackage::DEFAULT_PRETTY_VERSION ? '-' : $package->getPrettyVersion();
+ $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
$rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
if ($children) {
$queue = array_merge($queue, $children);
@@ -164,7 +180,17 @@ protected function printTable(OutputInterface $output, $results)
$table = array_merge($rows, $table);
} while (!empty($results));
- $this->renderTable($table, $output);
+ // Render table
+ $renderer = new Table($output);
+ $renderer->setStyle('compact');
+ $rendererStyle = $renderer->getStyle();
+ if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
+ $rendererStyle->setVerticalBorderChars('');
+ } else {
+ $rendererStyle->setVerticalBorderChar('');
+ }
+ $rendererStyle->setCellRowContentFormat('%s ');
+ $renderer->setRows($table)->render();
}
/**
@@ -203,14 +229,14 @@ protected function printTree($results, $prefix = '', $level = 1)
/**
* @var PackageInterface $package
* @var Link $link
- * @var array|bool $children
+ * @var array|bool $children
*/
list($package, $link, $children) = $result;
$color = $this->colors[$level % count($this->colors)];
$prevColor = $this->colors[($level - 1) % count($this->colors)];
$isLast = (++$idx == $count);
- $versionText = $package->getPrettyVersion() === RootPackage::DEFAULT_PRETTY_VERSION ? '' : $package->getPrettyVersion();
+ $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
$packageText = rtrim(sprintf('<%s>%s%1$s> %s', $color, $package->getPrettyName(), $versionText));
$linkText = sprintf('%s <%s>%s%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
$circularWarn = $children === false ? '(circular dependency aborted here)' : '';
diff --git a/app/vendor/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php b/app/vendor/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php
index 2f68a65cb..622882ceb 100644
--- a/app/vendor/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php
@@ -13,13 +13,13 @@
namespace Composer\Command;
use Composer\Package\Link;
+use Composer\Package\PackageInterface;
use Composer\Semver\Constraint\Constraint;
+use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Composer\Repository\PlatformRepository;
-use Composer\Repository\RootPackageRepository;
-use Composer\Repository\InstalledRepository;
class CheckPlatformReqsCommand extends BaseCommand
{
@@ -29,7 +29,6 @@ protected function configure()
->setDescription('Check that platform requirements are satisfied.')
->setDefinition(array(
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables checking of require-dev packages requirements.'),
- new InputOption('lock', null, InputOption::VALUE_NONE, 'Checks requirements only from the lock file, not from installed packages.'),
))
->setHelp(
<<getComposer();
- $requires = array();
- $removePackages = array();
- if ($input->getOption('lock')) {
- $this->getIO()->writeError('Checking '.($input->getOption('no-dev') ? 'non-dev ' : '').'platform requirements using the lock file ');
- $installedRepo = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'));
+ $requires = $composer->getPackage()->getRequires();
+ if ($input->getOption('no-dev')) {
+ $dependencies = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'))->getPackages();
} else {
- $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
+ $dependencies = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
// fallback to lockfile if installed repo is empty
- if (!$installedRepo->getPackages()) {
- $this->getIO()->writeError('No vendor dir present, checking '.($input->getOption('no-dev') ? 'non-dev ' : '').'platform requirements from the lock file ');
- $installedRepo = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'));
- } else {
- if ($input->getOption('no-dev')) {
- $removePackages = $installedRepo->getDevPackageNames();
- }
-
- $this->getIO()->writeError('Checking '.($input->getOption('no-dev') ? 'non-dev ' : '').'platform requirements for packages in the vendor dir ');
+ if (!$dependencies) {
+ $dependencies = $composer->getLocker()->getLockedRepository(true)->getPackages();
}
- }
- if (!$input->getOption('no-dev')) {
$requires += $composer->getPackage()->getDevRequires();
}
-
foreach ($requires as $require => $link) {
$requires[$require] = array($link);
}
- $installedRepo = new InstalledRepository(array($installedRepo, new RootPackageRepository($composer->getPackage())));
- foreach ($installedRepo->getPackages() as $package) {
- if (in_array($package->getName(), $removePackages, true)) {
- continue;
- }
+ foreach ($dependencies as $package) {
foreach ($package->getRequires() as $require => $link) {
$requires[$require][] = $link;
}
@@ -86,78 +69,62 @@ protected function execute(InputInterface $input, OutputInterface $output)
ksort($requires);
- $installedRepo->addRepository(new PlatformRepository(array(), array()));
+ $platformRepo = new PlatformRepository(array(), array());
+ $currentPlatformPackages = $platformRepo->getPackages();
+ $currentPlatformPackageMap = array();
+
+ /**
+ * @var PackageInterface $currentPlatformPackage
+ */
+ foreach ($currentPlatformPackages as $currentPlatformPackage) {
+ $currentPlatformPackageMap[$currentPlatformPackage->getName()] = $currentPlatformPackage;
+ }
$results = array();
+
$exitCode = 0;
/**
* @var Link[] $links
*/
foreach ($requires as $require => $links) {
- if (PlatformRepository::isPlatformPackage($require)) {
- $candidates = $installedRepo->findPackagesWithReplacersAndProviders($require);
- if ($candidates) {
- $reqResults = array();
- foreach ($candidates as $candidate) {
- $candidateConstraint = null;
- if ($candidate->getName() === $require) {
- $candidateConstraint = new Constraint('=', $candidate->getVersion());
- $candidateConstraint->setPrettyString($candidate->getPrettyVersion());
- } else {
- foreach (array_merge($candidate->getProvides(), $candidate->getReplaces()) as $link) {
- if ($link->getTarget() === $require) {
- $candidateConstraint = $link->getConstraint();
- break;
- }
- }
- }
-
- // safety check for phpstan, but it should not be possible to get a candidate out of findPackagesWithReplacersAndProviders without a constraint matching $require
- if (!$candidateConstraint) {
- continue;
- }
-
- foreach ($links as $link) {
- if (!$link->getConstraint()->matches($candidateConstraint)) {
- $reqResults[] = array(
- $candidate->getName() === $require ? $candidate->getPrettyName() : $require,
- $candidateConstraint->getPrettyString(),
- $link,
- 'failed '.($candidate->getName() === $require ? '' : ' provided by '.$candidate->getPrettyName().' '),
- );
-
- // skip to next candidate
- continue 2;
- }
+ if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $require)) {
+ if (isset($currentPlatformPackageMap[$require])) {
+ $pass = true;
+ $version = $currentPlatformPackageMap[$require]->getVersion();
+
+ foreach ($links as $link) {
+ if (!$link->getConstraint()->matches(new Constraint('=', $version))) {
+ $results[] = array(
+ $currentPlatformPackageMap[$require]->getPrettyName(),
+ $currentPlatformPackageMap[$require]->getPrettyVersion(),
+ $link,
+ 'failed ',
+ );
+ $pass = false;
+
+ $exitCode = max($exitCode, 1);
}
+ }
+ if ($pass) {
$results[] = array(
- $candidate->getName() === $require ? $candidate->getPrettyName() : $require,
- $candidateConstraint->getPrettyString(),
+ $currentPlatformPackageMap[$require]->getPrettyName(),
+ $currentPlatformPackageMap[$require]->getPrettyVersion(),
null,
- 'success '.($candidate->getName() === $require ? '' : ' provided by '.$candidate->getPrettyName().' '),
+ 'success ',
);
-
- // candidate matched, skip to next requirement
- continue 2;
}
-
- // show the first error from every failed candidate
- $results = array_merge($results, $reqResults);
- $exitCode = max($exitCode, 1);
-
- continue;
+ } else {
+ $results[] = array(
+ $require,
+ 'n/a',
+ $links[0],
+ 'missing ',
+ );
+
+ $exitCode = max($exitCode, 2);
}
-
- $results[] = array(
- $require,
- 'n/a',
- $links[0],
- 'missing ',
- );
-
- $exitCode = max($exitCode, 2);
}
}
@@ -168,6 +135,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
protected function printTable(OutputInterface $output, $results)
{
+ $table = array();
$rows = array();
foreach ($results as $result) {
/**
@@ -181,7 +149,18 @@ protected function printTable(OutputInterface $output, $results)
$status,
);
}
-
- $this->renderTable($rows, $output);
+ $table = array_merge($rows, $table);
+
+ // Render table
+ $renderer = new Table($output);
+ $renderer->setStyle('compact');
+ $rendererStyle = $renderer->getStyle();
+ if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
+ $rendererStyle->setVerticalBorderChars('');
+ } else {
+ $rendererStyle->setVerticalBorderChar('');
+ }
+ $rendererStyle->setCellRowContentFormat('%s ');
+ $renderer->setRows($table)->render();
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/ClearCacheCommand.php b/app/vendor/composer/composer/src/Composer/Command/ClearCacheCommand.php
index bdbdd80cf..2f511641e 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ClearCacheCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ClearCacheCommand.php
@@ -59,7 +59,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
continue;
}
$cache = new Cache($io, $cachePath);
- $cache->setReadOnly($config->get('cache-read-only'));
if (!$cache->isEnabled()) {
$io->writeError("Cache is not enabled ($key): $cachePath ");
diff --git a/app/vendor/composer/composer/src/Composer/Command/ConfigCommand.php b/app/vendor/composer/composer/src/Composer/Command/ConfigCommand.php
index 39b4604d3..be1743ba0 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ConfigCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ConfigCommand.php
@@ -12,7 +12,6 @@
namespace Composer\Command;
-use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\Silencer;
use Symfony\Component\Console\Input\InputInterface;
@@ -74,9 +73,6 @@ protected function configure()
new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
- new InputOption('json', 'j', InputOption::VALUE_NONE, 'JSON decode the setting value, to be used with extra.* keys'),
- new InputOption('merge', 'm', InputOption::VALUE_NONE, 'Merge the setting value with the current value, to be used with extra.* keys in combination with --json'),
- new InputOption('append', null, InputOption::VALUE_NONE, 'When adding a repository, append it (lowest priority) to the existing ones instead of prepending it (highest priority)'),
new InputArgument('setting-key', null, 'Setting key'),
new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
))
@@ -123,10 +119,6 @@ protected function configure()
%command.full_name% extra.property value
-Or to add a complex value you can use json with:
-
- %command.full_name% extra.property --json '{"foo":true, "bar": []}'
-
To edit the file in an external editor:
%command.full_name% --editor
@@ -244,7 +236,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$settingKey = $input->getArgument('setting-key');
- if (!$settingKey || !is_string($settingKey)) {
+ if (!$settingKey) {
return 0;
}
@@ -293,7 +285,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$value = $data;
} elseif (isset($data['config'][$settingKey])) {
$value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
- } elseif (isset($rawData[$settingKey]) && in_array($settingKey, $properties, true)) {
+ } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
$value = $rawData[$settingKey];
} else {
throw new \RuntimeException($settingKey.' is not defined');
@@ -330,14 +322,6 @@ function ($val) {
return $val;
},
),
- 'gitlab-protocol' => array(
- function ($val) {
- return in_array($val, array('git', 'http', 'https'), true);
- },
- function ($val) {
- return $val;
- },
- ),
'store-auths' => array(
function ($val) {
return in_array($val, array('true', 'false', 'prompt'), true);
@@ -390,7 +374,7 @@ function ($val) {
),
'bin-compat' => array(
function ($val) {
- return in_array($val, array('auto', 'full', 'symlink'));
+ return in_array($val, array('auto', 'full'));
},
function ($val) {
return $val;
@@ -420,7 +404,7 @@ function ($val) {
'secure-http' => array($booleanValidator, $booleanNormalizer),
'cafile' => array(
function ($val) {
- return file_exists($val) && Filesystem::isReadable($val);
+ return file_exists($val) && is_readable($val);
},
function ($val) {
return $val === 'null' ? null : $val;
@@ -428,7 +412,7 @@ function ($val) {
),
'capath' => array(
function ($val) {
- return is_dir($val) && Filesystem::isReadable($val);
+ return is_dir($val) && is_readable($val);
},
function ($val) {
return $val === 'null' ? null : $val;
@@ -437,18 +421,6 @@ function ($val) {
'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
'lock' => array($booleanValidator, $booleanNormalizer),
- 'platform-check' => array(
- function ($val) {
- return in_array($val, array('php-only', 'true', 'false', '1', '0'), true);
- },
- function ($val) {
- if ('php-only' === $val) {
- return 'php-only';
- }
-
- return $val !== 'false' && (bool) $val;
- },
- ),
);
$multiConfigValues = array(
'github-protocols' => array(
@@ -586,7 +558,7 @@ function ($vals) {
),
);
- if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || strpos($settingKey, 'extra.') === 0)) {
+ if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
throw new \InvalidArgumentException('The '.$settingKey.' property can not be set in the global config.json file. Use `composer global config` to apply changes to the global composer.json');
}
if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
@@ -617,7 +589,7 @@ function ($vals) {
$this->configSource->addRepository($matches[1], array(
'type' => $values[0],
'url' => $values[1],
- ), $input->getOption('append'));
+ ));
return 0;
}
@@ -626,13 +598,13 @@ function ($vals) {
$value = strtolower($values[0]);
if (true === $booleanValidator($value)) {
if (false === $booleanNormalizer($value)) {
- $this->configSource->addRepository($matches[1], false, $input->getOption('append'));
+ $this->configSource->addRepository($matches[1], false);
return 0;
}
} else {
$value = JsonFile::parseJson($values[0]);
- $this->configSource->addRepository($matches[1], $value, $input->getOption('append'));
+ $this->configSource->addRepository($matches[1], $value);
return 0;
}
@@ -649,21 +621,7 @@ function ($vals) {
return 0;
}
- $value = $values[0];
- if ($input->getOption('json')) {
- $value = JsonFile::parseJson($value);
- if ($input->getOption('merge')) {
- $currentValue = $this->configFile->read();
- $bits = explode('.', $settingKey);
- foreach ($bits as $bit) {
- $currentValue = isset($currentValue[$bit]) ? $currentValue[$bit] : null;
- }
- if (is_array($currentValue)) {
- $value = array_merge($currentValue, $value);
- }
- }
- }
- $this->configSource->addProperty($settingKey, $value);
+ $this->configSource->addProperty($settingKey, $values[0]);
return 0;
}
@@ -723,9 +681,6 @@ function ($vals) {
}
$this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
$this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
- } elseif ($matches[1] === 'gitlab-token' && 2 === count($values)) {
- $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
- $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'token' => $values[1]));
} elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token', 'bearer'), true)) {
if (1 !== count($values)) {
throw new \RuntimeException('Too many arguments, expected only one token');
diff --git a/app/vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php b/app/vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php
index b64b01e18..1e52674ba 100644
--- a/app/vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/CreateProjectCommand.php
@@ -16,17 +16,18 @@
use Composer\Factory;
use Composer\Installer;
use Composer\Installer\ProjectInstaller;
+use Composer\Installer\InstallationManager;
use Composer\Installer\SuggestedPackagesReporter;
use Composer\IO\IOInterface;
use Composer\Package\BasePackage;
+use Composer\DependencyResolver\Pool;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\Package\Version\VersionSelector;
use Composer\Package\AliasPackage;
use Composer\Repository\RepositoryFactory;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
-use Composer\Repository\InstalledArrayRepository;
-use Composer\Repository\RepositorySet;
+use Composer\Repository\InstalledFilesystemRepository;
use Composer\Script\ScriptEvents;
use Composer\Util\Silencer;
use Symfony\Component\Console\Input\InputArgument;
@@ -37,9 +38,8 @@
use Composer\Json\JsonFile;
use Composer\Config\JsonConfigSource;
use Composer\Util\Filesystem;
-use Composer\Util\Platform;
-use Composer\Util\ProcessExecutor;
use Composer\Package\Version\VersionParser;
+use Composer\EventDispatcher\EventDispatcher;
/**
* Install a package as new project into new directory.
@@ -67,11 +67,10 @@ protected function configure()
new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'),
- new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).'),
- new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories to look the package up, either by URL or using JSON arrays'),
+ new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
+ new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
- new InputOption('add-repository', null, InputOption::VALUE_NONE, 'Add the custom repository in the composer.json. If a lock file is present it will be deleted and an update will be run instead of install.'),
+ new InputOption('add-repository', null, InputOption::VALUE_NONE, 'Add the repository option to the composer.json.'),
new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
@@ -81,9 +80,7 @@ protected function configure()
new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'),
new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'),
new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
- new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
- new InputOption('ask', null, InputOption::VALUE_NONE, 'Whether to ask for project directory.'),
+ new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
))
->setHelp(
<<setOption('no-plugins', true);
}
- if ($input->isInteractive() && $input->getOption('ask')) {
- $parts = explode("/", strtolower($input->getArgument('package')), 2);
- $input->setArgument('directory', $io->ask('New project directory ['.array_pop($parts).' ]: '));
- }
-
- $ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
-
return $this->installProject(
$io,
$config,
@@ -153,64 +143,54 @@ protected function execute(InputInterface $input, OutputInterface $output)
$input->getOption('no-scripts'),
$input->getOption('no-progress'),
$input->getOption('no-install'),
- $ignorePlatformReqs,
+ $input->getOption('ignore-platform-reqs'),
!$input->getOption('no-secure-http'),
$input->getOption('add-repository')
);
}
- public function installProject(IOInterface $io, Config $config, InputInterface $input, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repositories = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, $secureHttp = true, $addRepository = false)
+ public function installProject(IOInterface $io, Config $config, InputInterface $input, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repository = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, $secureHttp = true, $addRepository = false)
{
$oldCwd = getcwd();
- if ($repositories !== null && !is_array($repositories)) {
- $repositories = (array) $repositories;
- }
-
// we need to manually load the configuration to pass the auth credentials to the io interface!
$io->loadConfiguration($config);
$this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
if ($packageName !== null) {
- $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repositories, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
+ $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
} else {
$installedFromVcs = false;
}
- if ($repositories !== null && $addRepository && is_file('composer.lock')) {
- unlink('composer.lock');
- }
-
$composer = Factory::create($io, null, $disablePlugins);
- $composer->getEventDispatcher()->setRunScripts(!$noScripts);
// add the repository to the composer.json and use it for the install run later
- if ($repositories !== null && $addRepository) {
- foreach ($repositories as $index => $repo) {
- $repoConfig = RepositoryFactory::configFromString($io, $composer->getConfig(), $repo, true);
- $composerJsonRepositoriesConfig = $composer->getConfig()->getRepositories();
- $name = RepositoryFactory::generateRepositoryName($index, $repoConfig, $composerJsonRepositoriesConfig);
- $configSource = new JsonConfigSource(new JsonFile('composer.json'));
-
- if (
- (isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
- || (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
- ) {
- $configSource->addRepository('packagist.org', false);
- } else {
- $configSource->addRepository($name, $repoConfig, false);
- }
+ if ($repository !== null && $addRepository) {
+ if ($composer->getLocker()->isLocked()) {
+ $io->writeError('Adding a repository when creating a project that provides a composer.lock file is not supported ');
- $composer = Factory::create($io, null, $disablePlugins);
+ return false;
}
+
+ $repoConfig = RepositoryFactory::configFromString($io, $composer->getConfig(), $repository, true);
+ $composerJsonRepositoriesConfig = $composer->getConfig()->getRepositories();
+ $name = RepositoryFactory::generateRepositoryName(0, $repoConfig, $composerJsonRepositoriesConfig);
+ $configSource = new JsonConfigSource(new JsonFile('composer.json'));
+ $configSource->addRepository($name, $repoConfig);
+
+ $composer = Factory::create($io, null, $disablePlugins);
}
- $process = new ProcessExecutor($io);
- $fs = new Filesystem($process);
+ $composer->getDownloadManager()->setOutputProgress(!$noProgress);
- // dispatch event
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
+ $fs = new Filesystem();
+
+ if ($noScripts === false) {
+ // dispatch event
+ $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
+ }
// use the new config including the newly installed project
$config = $composer->getConfig();
@@ -218,22 +198,17 @@ public function installProject(IOInterface $io, Config $config, InputInterface $
// install dependencies of the created project
if ($noInstall === false) {
- $composer->getInstallationManager()->setOutputProgress(!$noProgress);
-
$installer = Installer::create($io, $composer);
$installer->setPreferSource($preferSource)
->setPreferDist($preferDist)
->setDevMode($installDevPackages)
+ ->setRunScripts(!$noScripts)
->setIgnorePlatformRequirements($ignorePlatformReqs)
->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
->setOptimizeAutoloader($config->get('optimize-autoloader'))
->setClassMapAuthoritative($config->get('classmap-authoritative'))
->setApcuAutoloader($config->get('apcu-autoloader'));
- if (!$composer->getLocker()->isLocked()) {
- $installer->setUpdate(true);
- }
-
if ($disablePlugins) {
$installer->disablePlugins();
}
@@ -251,7 +226,7 @@ public function installProject(IOInterface $io, Config $config, InputInterface $
&& (
$input->getOption('remove-vcs')
|| !$io->isInteractive()
- || $io->askConfirmation('Do you want to remove the existing VCS (.git, .svn..) history? [Y,n ]? ')
+ || $io->askConfirmation('Do you want to remove the existing VCS (.git, .svn..) history? [Y,n ]? ', true)
)
) {
$finder = new Finder();
@@ -288,8 +263,10 @@ public function installProject(IOInterface $io, Config $config, InputInterface $
}
}
- // dispatch event
- $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
+ if ($noScripts === false) {
+ // dispatch event
+ $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
+ }
chdir($oldCwd);
$vendorComposerDir = $config->get('vendor-dir').'/composer';
@@ -304,12 +281,22 @@ public function installProject(IOInterface $io, Config $config, InputInterface $
return 0;
}
- protected function installRootPackage(IOInterface $io, Config $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, array $repositories = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $ignorePlatformReqs = false, $secureHttp = true)
+ protected function installRootPackage(IOInterface $io, Config $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repository = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $ignorePlatformReqs = false, $secureHttp = true)
{
if (!$secureHttp) {
$config->merge(array('config' => array('secure-http' => false)));
}
+ $composer = Factory::create($io, $config->all(), $disablePlugins);
+ $config = $composer->getConfig();
+ $rm = $composer->getRepositoryManager();
+
+ if (null === $repository) {
+ $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config, $rm));
+ } else {
+ $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true, $rm);
+ }
+
$parser = new VersionParser();
$requirements = $parser->parseNameVersionPairs(array($packageName));
$name = strtolower($requirements[0]['name']);
@@ -323,8 +310,7 @@ protected function installRootPackage(IOInterface $io, Config $config, $packageN
$directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
}
- $process = new ProcessExecutor($io);
- $fs = new Filesystem($process);
+ $fs = new Filesystem();
if (!$fs->isAbsolutePath($directory)) {
$directory = getcwd() . DIRECTORY_SEPARATOR . $directory;
}
@@ -334,16 +320,13 @@ protected function installRootPackage(IOInterface $io, Config $config, $packageN
if (file_exists($directory)) {
if (!is_dir($directory)) {
throw new \InvalidArgumentException('Cannot create project directory at "'.$directory.'", it exists as a file.');
- }
- if (!$fs->isDirEmpty($directory)) {
+ } elseif (!$fs->isDirEmpty($directory)) {
throw new \InvalidArgumentException('Project directory "'.$directory.'" is not empty.');
}
}
if (null === $stability) {
- if (null === $packageVersion) {
- $stability = 'stable';
- } elseif (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
+ if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
$stability = $match[1];
} else {
$stability = VersionParser::parseStability($packageVersion);
@@ -356,37 +339,28 @@ protected function installRootPackage(IOInterface $io, Config $config, $packageN
throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
}
- $composer = Factory::create($io, $config->all(), $disablePlugins);
- $config = $composer->getConfig();
- $rm = $composer->getRepositoryManager();
-
- $repositorySet = new RepositorySet($stability);
- if (null === $repositories) {
- $repositorySet->addRepository(new CompositeRepository(RepositoryFactory::defaultRepos($io, $config, $rm)));
- } else {
- foreach ($repositories as $repo) {
- $repoConfig = RepositoryFactory::configFromString($io, $config, $repo, true);
- if (
- (isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
- || (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
- ) {
- continue;
- }
- $repositorySet->addRepository(RepositoryFactory::createRepo($io, $config, $repoConfig, $rm));
- }
+ $pool = new Pool($stability);
+ $pool->addRepository($sourceRepo);
+
+ $phpVersion = null;
+ $prettyPhpVersion = null;
+ if (!$ignorePlatformReqs) {
+ $platformOverrides = $config->get('platform') ?: array();
+ // initialize $this->repos as it is used by the parent InitCommand
+ $platform = new PlatformRepository(array(), $platformOverrides);
+ $phpPackage = $platform->findPackage('php', '*');
+ $phpVersion = $phpPackage->getVersion();
+ $prettyPhpVersion = $phpPackage->getPrettyVersion();
}
- $platformOverrides = $config->get('platform') ?: array();
- $platformRepo = new PlatformRepository(array(), $platformOverrides);
-
// find the latest version if there are multiple
- $versionSelector = new VersionSelector($repositorySet, $platformRepo);
- $package = $versionSelector->findBestCandidate($name, $packageVersion, $stability, $ignorePlatformReqs);
+ $versionSelector = new VersionSelector($pool);
+ $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
if (!$package) {
$errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
- if (true !== $ignorePlatformReqs && $versionSelector->findBestCandidate($name, $packageVersion, $stability, true)) {
- throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version, PHP extensions and Composer version.');
+ if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
+ throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
}
throw new \InvalidArgumentException($errorMessage .'.');
@@ -404,22 +378,6 @@ protected function installRootPackage(IOInterface $io, Config $config, $packageN
});
}
}
- // handler Ctrl+C for Windows on PHP 7.4+
- if (function_exists('sapi_windows_set_ctrl_handler') && PHP_SAPI === 'cli') {
- @mkdir($directory, 0777, true);
- if ($realDir = realpath($directory)) {
- sapi_windows_set_ctrl_handler(function () use ($realDir) {
- $fs = new Filesystem();
- $fs->removeDirectory($realDir);
- exit(130);
- });
- }
- }
-
- // avoid displaying 9999999-dev as version if default-branch was selected
- if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
- $package = $package->getAliasOf();
- }
$io->writeError('Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ') ');
@@ -433,13 +391,13 @@ protected function installRootPackage(IOInterface $io, Config $config, $packageN
$dm = $composer->getDownloadManager();
$dm->setPreferSource($preferSource)
- ->setPreferDist($preferDist);
+ ->setPreferDist($preferDist)
+ ->setOutputProgress(!$noProgress);
- $projectInstaller = new ProjectInstaller($directory, $dm, $fs);
+ $projectInstaller = new ProjectInstaller($directory, $dm);
$im = $composer->getInstallationManager();
- $im->setOutputProgress(!$noProgress);
$im->addInstaller($projectInstaller);
- $im->execute(new InstalledArrayRepository(), array(new InstallOperation($package)));
+ $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
$im->notifyInstalls($io);
// collect suggestions
@@ -450,7 +408,8 @@ protected function installRootPackage(IOInterface $io, Config $config, $packageN
$io->writeError('Created project in ' . $directory . ' ');
chdir($directory);
- Platform::putEnv('COMPOSER_ROOT_VERSION', $package->getPrettyVersion());
+ $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
+ putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
return $installedFromVcs;
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/DependsCommand.php b/app/vendor/composer/composer/src/Composer/Command/DependsCommand.php
index c1ebe7eab..c350fde9b 100644
--- a/app/vendor/composer/composer/src/Composer/Command/DependsCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/DependsCommand.php
@@ -14,8 +14,6 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputOption;
/**
* @author Niels Keurentjes
@@ -27,15 +25,12 @@ class DependsCommand extends BaseDependencyCommand
*/
protected function configure()
{
+ parent::configure();
+
$this
->setName('depends')
->setAliases(array('why'))
->setDescription('Shows which packages cause the given package to be installed.')
- ->setDefinition(array(
- new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
- new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
- new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
- ))
->setHelp(
<<
*/
class DiagnoseCommand extends BaseCommand
{
- /** @var HttpDownloader */
- protected $httpDownloader;
+ /** @var RemoteFilesystem */
+ protected $rfs;
/** @var ProcessExecutor */
protected $process;
@@ -90,7 +86,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$config->merge(array('config' => array('secure-http' => false)));
$config->prohibitUrlByConfig('http://repo.packagist.org', new NullIO);
- $this->httpDownloader = Factory::createHttpDownloader($io, $config);
+ $this->rfs = Factory::createRemoteFilesystem($io, $config);
$this->process = new ProcessExecutor($io);
$io->write('Checking platform settings: ', false);
@@ -109,6 +105,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (!empty($opts['http']['proxy'])) {
$io->write('Checking HTTP proxy: ', false);
$this->outputResult($this->checkHttpProxy());
+ $io->write('Checking HTTP proxy support for request_fulluri: ', false);
+ $this->outputResult($this->checkHttpProxyFullUriRequestParam());
+ $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
+ $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
}
if ($oauth = $config->get('github-oauth')) {
@@ -148,7 +148,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$io->write('Checking disk free space: ', false);
$this->outputResult($this->checkDiskSpace($config));
- if (strpos(__FILE__, 'phar:') === 0) {
+ if ('phar:' === substr(__FILE__, 0, 5)) {
$io->write('Checking pubkeys: ', false);
$this->outputResult($this->checkPubKeys($config));
@@ -156,13 +156,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->outputResult($this->checkVersion($config));
}
- $io->write(sprintf('Composer version: %s ', Composer::getVersion()));
+ $io->write(sprintf('Composer version: %s ', Composer::VERSION));
$platformOverrides = $config->get('platform') ?: array();
$platformRepo = new PlatformRepository(array(), $platformOverrides);
$phpPkg = $platformRepo->findPackage('php', '*');
$phpVersion = $phpPkg->getPrettyVersion();
- if ($phpPkg instanceof CompletePackageInterface && false !== strpos($phpPkg->getDescription(), 'overridden')) {
+ if (false !== strpos($phpPkg->getDescription(), 'overridden')) {
$phpVersion .= ' - ' . $phpPkg->getDescription();
}
@@ -173,24 +173,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$io->write('OpenSSL version: ' . (defined('OPENSSL_VERSION_TEXT') ? ''.OPENSSL_VERSION_TEXT.' ' : 'missing '));
- $io->write('cURL version: ' . $this->getCurlVersion());
-
- $finder = new ExecutableFinder;
- $hasSystemUnzip = (bool) $finder->find('unzip');
- $bin7zip = '';
- if ($hasSystem7zip = (bool) $finder->find('7z', null, array('C:\Program Files\7-Zip'))) {
- $bin7zip = '7z';
- }
- if (!Platform::isWindows() && !$hasSystem7zip && $hasSystem7zip = (bool) $finder->find('7zz')) {
- $bin7zip = '7zz';
- }
-
- $io->write(
- 'zip: ' . (extension_loaded('zip') ? 'extension present ' : 'extension not loaded ')
- . ', ' . ($hasSystemUnzip ? 'unzip present ' : 'unzip not available ')
- . ', ' . ($hasSystem7zip ? '7-Zip present ('.$bin7zip.') ' : '7-Zip not available ')
- . (($hasSystem7zip || $hasSystemUnzip) && !function_exists('proc_open') ? ', proc_open is disabled or not present, unzip/7-z will not be usable ' : '')
- );
return $this->exitCode;
}
@@ -221,10 +203,6 @@ private function checkComposerSchema()
private function checkGit()
{
- if (!function_exists('proc_open')) {
- return 'proc_open is not available, git cannot be used ';
- }
-
$this->process->execute('git config color.ui', $output);
if (strtolower(trim($output)) === 'always') {
return 'Your git color.ui setting is set to always, this is known to create issues. Use "git config --global color.ui true" to set it correctly. ';
@@ -240,25 +218,26 @@ private function checkHttp($proto, Config $config)
return $result;
}
+ $disableTls = false;
$result = array();
if ($proto === 'https' && $config->get('disable-tls') === true) {
- $tlsWarning = 'Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks. ';
+ $disableTls = true;
+ $result[] = 'Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks. ';
+ }
+ if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
+ $result[] = 'Composer is configured to use SSL/TLS protection but the openssl extension is not available. ';
}
try {
- $this->httpDownloader->get($proto . '://repo.packagist.org/packages.json');
+ $this->rfs->getContents('packagist.org', $proto . '://repo.packagist.org/packages.json', false);
} catch (TransportException $e) {
- if ($hints = HttpDownloader::getExceptionHints($e)) {
- foreach ($hints as $hint) {
- $result[] = $hint;
- }
+ if (false !== strpos($e->getMessage(), 'cafile')) {
+ $result[] = '[' . get_class($e) . '] ' . $e->getMessage() . ' ';
+ $result[] = 'Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option. ';
+ $result[] = 'You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option. ';
+ } else {
+ array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
}
-
- $result[] = '[' . get_class($e) . '] ' . $e->getMessage() . ' ';
- }
-
- if (isset($tlsWarning)) {
- $result[] = $tlsWarning;
}
if (count($result) > 0) {
@@ -277,11 +256,11 @@ private function checkHttpProxy()
$protocol = extension_loaded('openssl') ? 'https' : 'http';
try {
- $json = $this->httpDownloader->get($protocol . '://repo.packagist.org/packages.json')->decodeJson();
+ $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/packages.json', false), true);
$hash = reset($json['provider-includes']);
$hash = $hash['sha256'];
$path = str_replace('%hash%', $hash, key($json['provider-includes']));
- $provider = $this->httpDownloader->get($protocol . '://repo.packagist.org/'.$path)->getBody();
+ $provider = $this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/'.$path, false);
if (hash('sha256', $provider) !== $hash) {
return 'It seems that your proxy is modifying http traffic on the fly';
@@ -293,6 +272,70 @@ private function checkHttpProxy()
return true;
}
+ /**
+ * Due to various proxy servers configurations, some servers can't handle non-standard HTTP "http_proxy_request_fulluri" parameter,
+ * and will return error 500/501 (as not implemented), see discussion @ https://github.com/composer/composer/pull/1825.
+ * This method will test, if you need to disable this parameter via setting extra environment variable in your system.
+ *
+ * @return bool|string
+ */
+ private function checkHttpProxyFullUriRequestParam()
+ {
+ $result = $this->checkConnectivity();
+ if ($result !== true) {
+ return $result;
+ }
+
+ $url = 'http://repo.packagist.org/packages.json';
+ try {
+ $this->rfs->getContents('packagist.org', $url, false);
+ } catch (TransportException $e) {
+ try {
+ $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
+ } catch (TransportException $e) {
+ return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
+ }
+
+ return 'It seems there is a problem with your proxy server, try setting the "HTTP_PROXY_REQUEST_FULLURI" and "HTTPS_PROXY_REQUEST_FULLURI" environment variables to "false"';
+ }
+
+ return true;
+ }
+
+ /**
+ * Due to various proxy servers configurations, some servers can't handle non-standard HTTP "http_proxy_request_fulluri" parameter,
+ * and will return error 500/501 (as not implemented), see discussion @ https://github.com/composer/composer/pull/1825.
+ * This method will test, if you need to disable this parameter via setting extra environment variable in your system.
+ *
+ * @return bool|string
+ */
+ private function checkHttpsProxyFullUriRequestParam()
+ {
+ $result = $this->checkConnectivity();
+ if ($result !== true) {
+ return $result;
+ }
+
+ if (!extension_loaded('openssl')) {
+ return 'You need the openssl extension installed for this check';
+ }
+
+ $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
+ try {
+ $this->rfs->getContents('github.com', $url, false);
+ } catch (TransportException $e) {
+ try {
+ $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
+ } catch (TransportException $e) {
+ return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
+ }
+
+ return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
+ }
+
+ return true;
+ }
+
private function checkGithubOauth($domain, $token)
{
$result = $this->checkConnectivity();
@@ -304,11 +347,9 @@ private function checkGithubOauth($domain, $token)
try {
$url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
- $this->httpDownloader->get($url, array(
+ return $this->rfs->getContents($domain, $url, false, array(
'retry-auth-failure' => false,
- ));
-
- return true;
+ )) ? true : 'Unexpected error';
} catch (\Exception $e) {
if ($e instanceof TransportException && $e->getCode() === 401) {
return 'The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it ';
@@ -336,7 +377,8 @@ private function getGithubRateLimit($domain, $token = null)
}
$url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
- $data = $this->httpDownloader->get($url, array('retry-auth-failure' => false))->decodeJson();
+ $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
+ $data = json_decode($json, true);
return $data['resources']['core'];
}
@@ -389,7 +431,7 @@ private function checkVersion($config)
return $result;
}
- $versionsUtil = new Versions($config, $this->httpDownloader);
+ $versionsUtil = new Versions($config, $this->rfs);
try {
$latest = $versionsUtil->getLatest();
} catch (\Exception $e) {
@@ -403,25 +445,8 @@ private function checkVersion($config)
return true;
}
- private function getCurlVersion()
- {
- if (extension_loaded('curl')) {
- if (!HttpDownloader::isCurlEnabled()) {
- return 'disabled via disable_functions, using php streams fallback, which reduces performance ';
- }
-
- $version = curl_version();
-
- return ''.$version['version'].' '.
- 'libz '.(isset($version['libz_version']) ? $version['libz_version'] : 'missing').' '.
- 'ssl '.(isset($version['ssl_version']) ? $version['ssl_version'] : 'missing').' ';
- }
-
- return 'missing, using php streams fallback, which reduces performance ';
- }
-
/**
- * @param bool|string|string[]|\Exception $result
+ * @param bool|string|\Exception $result
*/
private function outputResult($result)
{
@@ -553,7 +578,7 @@ private function checkPlatform()
if (filter_var(ini_get('xdebug.profiler_enabled'), FILTER_VALIDATE_BOOLEAN)) {
$warnings['xdebug_profile'] = true;
- } elseif (XdebugHandler::isXdebugActive()) {
+ } elseif (extension_loaded('xdebug')) {
$warnings['xdebug_loaded'] = true;
}
@@ -592,6 +617,20 @@ private function checkPlatform()
$text .= "Install either of them or recompile php without --disable-iconv";
break;
+ case 'unicode':
+ $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
+ $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
+ $text .= " detect_unicode = Off";
+ $displayIniMessage = true;
+ break;
+
+ case 'suhosin':
+ $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
+ $text .= "Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):".PHP_EOL;
+ $text .= " suhosin.executor.include.whitelist = phar ".$current;
+ $displayIniMessage = true;
+ break;
+
case 'php':
$text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
break;
@@ -614,9 +653,6 @@ private function checkPlatform()
$text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
$text .= "If possible you should enable it or recompile php with --with-openssl";
break;
-
- default:
- throw new \InvalidArgumentException(sprintf("DiagnoseCommand: Unknown error type \"%s\". Please report at https://github.com/composer/composer/issues/new.", $error));
}
$out($text, 'error');
}
@@ -681,9 +717,6 @@ private function checkPlatform()
$text = "The Windows OneDrive folder is not supported on PHP versions below 7.2.23 and 7.3.10.".PHP_EOL;
$text .= "Upgrade your PHP ({$current}) to use this location with Composer.".PHP_EOL;
break;
-
- default:
- throw new \InvalidArgumentException(sprintf("DiagnoseCommand: Unknown warning type \"%s\". Please report at https://github.com/composer/composer/issues/new.", $warning));
}
$out($text, 'comment');
}
@@ -696,15 +729,17 @@ private function checkPlatform()
return !$warnings && !$errors ? true : $output;
}
+
/**
* Check if allow_url_fopen is ON
*
- * @return true|string
+ * @return bool|string
*/
private function checkConnectivity()
{
if (!ini_get('allow_url_fopen')) {
- return 'Skipped because allow_url_fopen is missing. ';
+ $result = 'Skipped because allow_url_fopen is missing. ';
+ return $result;
}
return true;
diff --git a/app/vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php b/app/vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php
index c4b0b9926..9627b2a88 100644
--- a/app/vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php
@@ -34,11 +34,7 @@ protected function configure()
new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
- new InputOption('apcu-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu'),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables autoload-dev rules. Composer will by default infer this automatically according to the last install or update --no-dev state.'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules. Composer will by default infer this automatically according to the last install or update --no-dev state.'),
- new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
+ new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
))
->setHelp(
<<getComposer();
- $composer->getEventDispatcher()->setRunScripts(!$input->getOption('no-scripts'));
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
@@ -65,8 +60,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
- $apcuPrefix = $input->getOption('apcu-prefix');
- $apcu = $apcuPrefix !== null || $input->getOption('apcu') || $config->get('apcu-autoloader');
+ $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
if ($authoritative) {
$this->getIO()->write('Generating optimized autoload files (authoritative) ');
@@ -76,22 +70,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->getIO()->write('Generating autoload files ');
}
- $ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
-
$generator = $composer->getAutoloadGenerator();
- if ($input->getOption('no-dev')) {
- $generator->setDevMode(false);
- }
- if ($input->getOption('dev')) {
- if ($input->getOption('no-dev')) {
- throw new \InvalidArgumentException('You can not use both --no-dev and --dev as they conflict with each other.');
- }
- $generator->setDevMode(true);
- }
+ $generator->setDevMode(!$input->getOption('no-dev'));
$generator->setClassMapAuthoritative($authoritative);
- $generator->setRunScripts(true);
- $generator->setApcu($apcu, $apcuPrefix);
- $generator->setIgnorePlatformRequirements($ignorePlatformReqs);
+ $generator->setApcu($apcu);
+ $generator->setRunScripts(!$input->getOption('no-scripts'));
$numberOfClasses = $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
if ($authoritative) {
diff --git a/app/vendor/composer/composer/src/Composer/Command/ExecCommand.php b/app/vendor/composer/composer/src/Composer/Command/ExecCommand.php
index 167a2be0d..fba9e7e8a 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ExecCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ExecCommand.php
@@ -88,6 +88,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
$dispatcher = $composer->getEventDispatcher();
$dispatcher->addListener('__exec_command', $binary);
+ if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
+ $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
+ }
// If the CWD was modified, we restore it to what it was initially, as it was
// most likely modified by the global command, and we want exec to run in the local working directory
diff --git a/app/vendor/composer/composer/src/Composer/Command/FundCommand.php b/app/vendor/composer/composer/src/Composer/Command/FundCommand.php
index edba9e806..eb60ec577 100644
--- a/app/vendor/composer/composer/src/Composer/Command/FundCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/FundCommand.php
@@ -12,12 +12,9 @@
namespace Composer\Command;
-use Composer\Json\JsonFile;
-use Composer\Package\AliasPackage;
-use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
+use Composer\Package\AliasPackage;
use Composer\Repository\CompositeRepository;
-use Composer\Semver\Constraint\MatchAllConstraint;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -32,9 +29,6 @@ protected function configure()
{
$this->setName('fund')
->setDescription('Discover how to help fund the maintenance of your dependencies.')
- ->setDefinition(array(
- new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
- ))
;
}
@@ -45,38 +39,15 @@ protected function execute(InputInterface $input, OutputInterface $output)
$repo = $composer->getRepositoryManager()->getLocalRepository();
$remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
$fundings = array();
-
- $packagesToLoad = array();
foreach ($repo->getPackages() as $package) {
if ($package instanceof AliasPackage) {
continue;
}
- $packagesToLoad[$package->getName()] = new MatchAllConstraint();
- }
-
- // load all packages dev versions in parallel
- $result = $remoteRepos->loadPackages($packagesToLoad, array('dev' => BasePackage::STABILITY_DEV), array());
-
- // collect funding data from default branches
- foreach ($result['packages'] as $package) {
- if (
- !$package instanceof AliasPackage
- && $package instanceof CompletePackageInterface
- && $package->isDefaultBranch()
- && $package->getFunding()
- && isset($packagesToLoad[$package->getName()])
- ) {
- $fundings = $this->insertFundingData($fundings, $package);
- unset($packagesToLoad[$package->getName()]);
- }
- }
-
- // collect funding from installed packages if none was found in the default branch above
- foreach ($repo->getPackages() as $package) {
- if ($package instanceof AliasPackage || !isset($packagesToLoad[$package->getName()])) {
+ $latest = $remoteRepos->findPackage($package->getName(), 'dev-master');
+ if ($latest instanceof CompletePackageInterface && $latest->getFunding()) {
+ $fundings = $this->insertFundingData($fundings, $latest);
continue;
}
-
if ($package instanceof CompletePackageInterface && $package->getFunding()) {
$fundings = $this->insertFundingData($fundings, $package);
}
@@ -86,14 +57,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$io = $this->getIO();
- $format = $input->getOption('format');
- if (!in_array($format, array('text', 'json'))) {
- $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
-
- return 1;
- }
-
- if ($fundings && $format === 'text') {
+ if ($fundings) {
$prev = null;
$io->write('The following packages were found in your dependencies which publish funding information:');
@@ -116,8 +80,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
$io->write("");
$io->write("Please consider following these links and sponsoring the work of package authors!");
$io->write("Thank you!");
- } elseif ($format === 'json') {
- $io->write(JsonFile::encode($fundings));
} else {
$io->write("No funding links were found in your package dependencies. This doesn't mean they don't need your support!");
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/GlobalCommand.php b/app/vendor/composer/composer/src/Composer/Command/GlobalCommand.php
index c78ea7109..958643dee 100644
--- a/app/vendor/composer/composer/src/Composer/Command/GlobalCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/GlobalCommand.php
@@ -14,7 +14,6 @@
use Composer\Factory;
use Composer\Util\Filesystem;
-use Composer\Util\Platform;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\StringInput;
@@ -59,10 +58,6 @@ protected function configure()
public function run(InputInterface $input, OutputInterface $output)
{
- if (!method_exists($input, '__toString')) {
- throw new \LogicException('Expected an Input instance that is stringable, got '.get_class($input));
- }
-
// extract real command name
$tokens = preg_split('{\s+}', $input->__toString());
$args = array();
@@ -82,7 +77,8 @@ public function run(InputInterface $input, OutputInterface $output)
// The COMPOSER env var should not apply to the global execution scope
if (getenv('COMPOSER')) {
- Platform::clearEnv('COMPOSER');
+ putenv('COMPOSER');
+ unset($_SERVER['COMPOSER']);
}
// change to global dir
diff --git a/app/vendor/composer/composer/src/Composer/Command/HomeCommand.php b/app/vendor/composer/composer/src/Composer/Command/HomeCommand.php
index 8e43f39a4..b7d907066 100644
--- a/app/vendor/composer/composer/src/Composer/Command/HomeCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/HomeCommand.php
@@ -14,7 +14,7 @@
use Composer\Package\CompletePackageInterface;
use Composer\Repository\RepositoryInterface;
-use Composer\Repository\RootPackageRepository;
+use Composer\Repository\ArrayRepository;
use Composer\Repository\RepositoryFactory;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
@@ -157,7 +157,7 @@ private function initializeRepos()
if ($composer) {
return array_merge(
- array(new RootPackageRepository($composer->getPackage())), // root package
+ array(new ArrayRepository(array($composer->getPackage()))), // root package
array($composer->getRepositoryManager()->getLocalRepository()), // installed packages
$composer->getRepositoryManager()->getRepositories() // remotes
);
diff --git a/app/vendor/composer/composer/src/Composer/Command/InitCommand.php b/app/vendor/composer/composer/src/Composer/Command/InitCommand.php
index c8888f07e..1eacb2bff 100644
--- a/app/vendor/composer/composer/src/Composer/Command/InitCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/InitCommand.php
@@ -12,30 +12,23 @@
namespace Composer\Command;
+use Composer\DependencyResolver\Pool;
use Composer\Factory;
use Composer\Json\JsonFile;
-use Composer\Json\JsonValidationException;
use Composer\Package\BasePackage;
-use Composer\Package\CompletePackageInterface;
use Composer\Package\Package;
-use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\VersionSelector;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryFactory;
-use Composer\Repository\RepositorySet;
-use Composer\Util\Filesystem;
use Composer\Util\ProcessExecutor;
-use Composer\Semver\Constraint\Constraint;
-use Composer\Util\Silencer;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;
-use Symfony\Component\Console\Helper\FormatterHelper;
/**
* @author Justin Rainbow
@@ -43,14 +36,14 @@
*/
class InitCommand extends BaseCommand
{
- /** @var ?CompositeRepository */
+ /** @var CompositeRepository */
protected $repos;
- /** @var array */
+ /** @var array */
private $gitConfig;
- /** @var RepositorySet[] */
- private $repositorySets;
+ /** @var Pool[] */
+ private $pools;
/**
* {@inheritdoc}
@@ -72,7 +65,6 @@ protected function configure()
new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
- new InputOption('autoload', 'a', InputOption::VALUE_REQUIRED, 'Add PSR-4 autoload mapping. Maps your package\'s namespace to the provided directory. (Expects a relative path, e.g. src/)'),
))
->setHelp(
<<getIO();
- $allowlist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license', 'autoload');
- $options = array_filter(array_intersect_key($input->getOptions(), array_flip($allowlist)));
-
- if (isset($options['name']) && !preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $options['name'])) {
- throw new \InvalidArgumentException(
- 'The package name '.$options['name'].' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
- );
- }
+ $allowList = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
+ $options = array_filter(array_intersect_key($input->getOptions(), array_flip($allowList)));
if (isset($options['author'])) {
$options['authors'] = $this->formatAuthors($options['author']);
@@ -112,7 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
if ($repositories) {
$config = Factory::createConfig($io);
foreach ($repositories as $repo) {
- $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo, true);
+ $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
}
}
@@ -133,58 +119,19 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
- // --autoload - create autoload object
- $autoloadPath = null;
- if (isset($options['autoload'])) {
- $autoloadPath = $options['autoload'];
- $namespace = $this->namespaceFromPackageName($input->getOption('name'));
- $options['autoload'] = (object) array(
- 'psr-4' => array(
- $namespace . '\\' => $autoloadPath,
- ),
- );
- }
-
$file = new JsonFile(Factory::getComposerFile());
- $json = JsonFile::encode($options);
+ $json = $file->encode($options);
if ($input->isInteractive()) {
$io->writeError(array('', $json, ''));
- if (!$io->askConfirmation('Do you confirm generation [yes ]? ')) {
+ if (!$io->askConfirmation('Do you confirm generation [yes ]? ', true)) {
$io->writeError('Command aborted ');
return 1;
}
- } else {
- if (json_encode($options) === '{"require":{}}') {
- throw new \RuntimeException('You have to run this command in interactive mode, or specify at least some data using --name, --require, etc.');
- }
-
- $io->writeError('Writing '.$file->getPath());
}
$file->write($options);
- try {
- $file->validateSchema(JsonFile::LAX_SCHEMA);
- } catch (JsonValidationException $e) {
- $io->writeError('Schema validation error, aborting ');
- $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
- $io->writeError($e->getMessage() . ':' . PHP_EOL . $errors);
- Silencer::call('unlink', $file->getPath());
-
- return 1;
- }
-
- // --autoload - Create src folder
- if ($autoloadPath) {
- $filesystem = new Filesystem();
- $filesystem->ensureDirectoryExists($autoloadPath);
-
- // dump-autoload only for projects without added dependencies.
- if (!$this->hasDependencies($options)) {
- $this->runDumpAutoloadCommand($output);
- }
- }
if ($input->isInteractive() && is_dir('.git')) {
$ignoreFile = realpath('.gitignore');
@@ -196,23 +143,15 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (!$this->hasVendorIgnore($ignoreFile)) {
$question = 'Would you like the vendor directory added to your .gitignore [yes ]? ';
- if ($io->askConfirmation($question)) {
+ if ($io->askConfirmation($question, true)) {
$this->addVendorIgnore($ignoreFile);
}
}
}
$question = 'Would you like to install dependencies now [yes ]? ';
- if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question)) {
- $this->updateDependencies($output);
- }
-
- // --autoload - Show post-install configuration info
- if ($autoloadPath) {
- $namespace = $this->namespaceFromPackageName($input->getOption('name'));
-
- $io->writeError('PSR-4 autoloading configured. Use "namespace '.$namespace.'; " in '.$autoloadPath);
- $io->writeError('Include the Composer autoloader with: require \'vendor/autoload.php\'; ');
+ if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question, true)) {
+ $this->installDependencies($output);
}
return 0;
@@ -225,7 +164,6 @@ protected function interact(InputInterface $input, OutputInterface $output)
{
$git = $this->getGitConfig();
$io = $this->getIO();
- /** @var FormatterHelper $formatter */
$formatter = $this->getHelperSet()->get('formatter');
// initialize repos if configured
@@ -235,7 +173,7 @@ protected function interact(InputInterface $input, OutputInterface $output)
$repos = array(new PlatformRepository);
$createDefaultPackagistRepo = true;
foreach ($repositories as $repo) {
- $repoConfig = RepositoryFactory::configFromString($io, $config, $repo, true);
+ $repoConfig = RepositoryFactory::configFromString($io, $config, $repo);
if (
(isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
|| (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
@@ -291,6 +229,12 @@ protected function interact(InputInterface $input, OutputInterface $output)
$name .= '/' . $name;
}
$name = strtolower($name);
+ } else {
+ if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $name)) {
+ throw new \InvalidArgumentException(
+ 'The package name '.$name.' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
+ );
+ }
}
$name = $io->askAndValidate(
@@ -333,7 +277,7 @@ function ($value) use ($name) {
$author_email = $git['user.email'];
}
- if (isset($author_name, $author_email)) {
+ if (isset($author_name) && isset($author_email)) {
$author = sprintf('%s <%s>', $author_name, $author_email);
}
}
@@ -401,61 +345,23 @@ function ($value) use ($minimumStability) {
// prepare to resolve dependencies
$repos = $this->getRepos();
$preferredStability = $minimumStability ?: 'stable';
- $platformRepo = null;
- if ($repos instanceof CompositeRepository) {
- foreach ($repos->getRepositories() as $candidateRepo) {
- if ($candidateRepo instanceof PlatformRepository) {
- $platformRepo = $candidateRepo;
- break;
- }
- }
- }
+ $phpVersion = $repos->findPackage('php', '*')->getPrettyVersion();
$question = 'Would you like to define your dependencies (require) interactively [yes ]? ';
$require = $input->getOption('require');
$requirements = array();
- if ($require || $io->askConfirmation($question)) {
- $requirements = $this->determineRequirements($input, $output, $require, $platformRepo, $preferredStability);
+ if ($require || $io->askConfirmation($question, true)) {
+ $requirements = $this->determineRequirements($input, $output, $require, $phpVersion, $preferredStability);
}
$input->setOption('require', $requirements);
$question = 'Would you like to define your dev dependencies (require-dev) interactively [yes ]? ';
$requireDev = $input->getOption('require-dev');
$devRequirements = array();
- if ($requireDev || $io->askConfirmation($question)) {
- $devRequirements = $this->determineRequirements($input, $output, $requireDev, $platformRepo, $preferredStability);
+ if ($requireDev || $io->askConfirmation($question, true)) {
+ $devRequirements = $this->determineRequirements($input, $output, $requireDev, $phpVersion, $preferredStability);
}
$input->setOption('require-dev', $devRequirements);
-
- // --autoload - input and validation
- $autoload = $input->getOption('autoload') ?: 'src/';
- $namespace = $this->namespaceFromPackageName($input->getOption('name'));
- $autoload = $io->askAndValidate(
- 'Add PSR-4 autoload mapping? Maps namespace "'.$namespace.'" to the entered relative path. ['.$autoload.' , n to skip]: ',
- function ($value) use ($autoload) {
- if (null === $value) {
- return $autoload;
- }
-
- if ($value === 'n' || $value === 'no') {
- return;
- }
-
- $value = $value ?: $autoload;
-
- if (!preg_match('{^[^/][A-Za-z0-9\-_/]+/$}', $value)) {
- throw new \InvalidArgumentException(sprintf(
- 'The src folder name "%s" is invalid. Please add a relative path with tailing forward slash. [A-Za-z0-9_-/]+/',
- $value
- ));
- }
-
- return $value;
- },
- null,
- $autoload
- );
- $input->setOption('autoload', $autoload);
}
/**
@@ -497,7 +403,7 @@ protected function getRepos()
return $this->repos;
}
- final protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), PlatformRepository $platformRepo = null, $preferredStability = 'stable', $checkProvidedVersions = true, $fixed = false)
+ final protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true, $fixed = false)
{
if ($requires) {
$requires = $this->normalizeRequirements($requires);
@@ -507,7 +413,7 @@ final protected function determineRequirements(InputInterface $input, OutputInte
foreach ($requires as $requirement) {
if (!isset($requirement['version'])) {
// determine the best version automatically
- list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $platformRepo, $preferredStability, null, null, $fixed);
+ list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, null, null, $fixed);
$requirement['version'] = $version;
// replace package name from packagist.org
@@ -520,7 +426,7 @@ final protected function determineRequirements(InputInterface $input, OutputInte
));
} else {
// check that the specified version/constraint exists before we proceed
- list($name) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $platformRepo, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev', $fixed);
+ list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev', $fixed);
// replace package name from packagist.org
$requirement['name'] = $name;
@@ -641,7 +547,7 @@ final protected function determineRequirements(InputInterface $input, OutputInte
);
if (false === $constraint) {
- list(, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $platformRepo, $preferredStability);
+ list($name, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $phpVersion, $preferredStability);
$io->writeError(sprintf(
'Using version %s for %s ',
@@ -668,32 +574,15 @@ protected function formatAuthors($author)
return array($this->parseAuthorString($author));
}
- /**
- * Extract namespace from package's vendor name.
- *
- * new_projects.acme-extra/package-name becomes "NewProjectsAcmeExtra\PackageName"
- *
- * @param string $packageName
- *
- * @return string|null
- */
- public function namespaceFromPackageName($packageName)
+ protected function formatRequirements(array $requirements)
{
- if (!$packageName || strpos($packageName, '/') === false) {
- return null;
+ $requires = array();
+ $requirements = $this->normalizeRequirements($requirements);
+ foreach ($requirements as $requirement) {
+ $requires[$requirement['name']] = $requirement['version'];
}
- $namespace = array_map(
- function ($part) {
- $part = preg_replace('/[^a-z0-9]/i', ' ', $part);
- $part = ucwords($part);
-
- return str_replace(' ', '', $part);
- },
- explode('/', $packageName)
- );
-
- return join('\\', $namespace);
+ return $requires;
}
protected function getGitConfig()
@@ -705,11 +594,10 @@ protected function getGitConfig()
$finder = new ExecutableFinder();
$gitBin = $finder->find('git');
- // TODO in v2.3 always call with an array
+ // TODO in v3 always call with an array
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
$cmd = new Process(array($gitBin, 'config', '-l'));
} else {
- // @phpstan-ignore-next-line
$cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
}
$cmd->run();
@@ -761,13 +649,20 @@ protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
return false;
}
+ protected function normalizeRequirements(array $requirements)
+ {
+ $parser = new VersionParser();
+
+ return $parser->parseNameVersionPairs($requirements);
+ }
+
protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
{
$contents = "";
if (file_exists($ignoreFile)) {
$contents = file_get_contents($ignoreFile);
- if (strpos($contents, "\n") !== 0) {
+ if ("\n" !== substr($contents, 0, -1)) {
$contents .= "\n";
}
}
@@ -790,16 +685,16 @@ protected function isValidEmail($email)
return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
}
- private function getRepositorySet(InputInterface $input, $minimumStability = null)
+ private function getPool(InputInterface $input, $minimumStability = null)
{
$key = $minimumStability ?: 'default';
- if (!isset($this->repositorySets[$key])) {
- $this->repositorySets[$key] = $repositorySet = new RepositorySet($minimumStability ?: $this->getMinimumStability($input));
- $repositorySet->addRepository($this->getRepos());
+ if (!isset($this->pools[$key])) {
+ $this->pools[$key] = $pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
+ $pool->addRepository($this->getRepos());
}
- return $this->repositorySets[$key];
+ return $this->pools[$key];
}
private function getMinimumStability(InputInterface $input)
@@ -809,7 +704,7 @@ private function getMinimumStability(InputInterface $input)
}
$file = Factory::getComposerFile();
- if (is_file($file) && Filesystem::isReadable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
+ if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
if (!empty($composer['minimum-stability'])) {
return VersionParser::normalizeStability($composer['minimum-stability']);
}
@@ -825,7 +720,7 @@ private function getMinimumStability(InputInterface $input)
*
* @param InputInterface $input
* @param string $name
- * @param PlatformRepository|null $platformRepo
+ * @param string|null $phpVersion
* @param string $preferredStability
* @param string|null $requiredVersion
* @param string $minimumStability
@@ -833,86 +728,61 @@ private function getMinimumStability(InputInterface $input)
* @throws \InvalidArgumentException
* @return array name version
*/
- private function findBestVersionAndNameForPackage(InputInterface $input, $name, PlatformRepository $platformRepo = null, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null, $fixed = null)
+ private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null, $fixed = null)
{
- // handle ignore-platform-reqs flag if present
- $ignorePlatformReqs = false;
- if ($input->hasOption('ignore-platform-reqs') && $input->hasOption('ignore-platform-req')) {
- $ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
- }
+ // find the latest version allowed in this pool
+ $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
+ $ignorePlatformReqs = $input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs');
- // find the latest version allowed in this repo set
- $versionSelector = new VersionSelector($this->getRepositorySet($input, $minimumStability), $platformRepo);
- $effectiveMinimumStability = $minimumStability ?: $this->getMinimumStability($input);
+ // ignore phpVersion if platform requirements are ignored
+ if ($ignorePlatformReqs) {
+ $phpVersion = null;
+ }
- $package = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, $ignorePlatformReqs);
+ $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
if (!$package) {
// platform packages can not be found in the pool in versions other than the local platform's has
// so if platform reqs are ignored we just take the user's word for it
- if ((true === $ignorePlatformReqs || (is_array($ignorePlatformReqs) && in_array($name, $ignorePlatformReqs))) && PlatformRepository::isPlatformPackage($name)) {
+ if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
return array($name, $requiredVersion ?: '*');
}
// Check whether the PHP version was the problem
- if (true !== $ignorePlatformReqs && ($candidate = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, true))) {
+ if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
throw new \InvalidArgumentException(sprintf(
- 'Package %s%s has a PHP requirement incompatible with your PHP version, PHP extensions and Composer version' . $this->getPlatformExceptionDetails($candidate, $platformRepo),
+ 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)',
$name,
- $requiredVersion ? ' at version '.$requiredVersion : ''
- ));
- }
- // Check whether the minimum stability was the problem but the package exists
- if ($package = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, $ignorePlatformReqs, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) {
- // we must first verify if a valid package would be found in a lower priority repository
- if ($allReposPackage = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, $ignorePlatformReqs, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) {
- throw new \InvalidArgumentException(
- 'Package '.$name.' exists in '.$allReposPackage->getRepository()->getRepoName().' and '.$package->getRepository()->getRepoName().' which has a higher repository priority. The packages with higher priority do not match your minimum-stability and are therefore not installable. See https://getcomposer.org/repoprio for details and assistance.'
- );
- }
-
- throw new \InvalidArgumentException(sprintf(
- 'Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.',
- $name,
- $effectiveMinimumStability
+ $requiredVersion,
+ $phpVersion
));
}
// Check whether the required version was the problem
- if ($requiredVersion && $package = $versionSelector->findBestCandidate($name, null, $preferredStability, $ignorePlatformReqs)) {
- // we must first verify if a valid package would be found in a lower priority repository
- if ($allReposPackage = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, false, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) {
- throw new \InvalidArgumentException(
- 'Package '.$name.' exists in '.$allReposPackage->getRepository()->getRepoName().' and '.$package->getRepository()->getRepoName().' which has a higher repository priority. The packages with higher priority do not match your constraint and are therefore not installable. See https://getcomposer.org/repoprio for details and assistance.'
- );
- }
-
+ if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
throw new \InvalidArgumentException(sprintf(
- 'Could not find package %s in a version matching "%s" and a stability matching "'.$effectiveMinimumStability.'".',
+ 'Could not find package %s in a version matching %s',
$name,
$requiredVersion
));
}
- // Check whether the PHP version was the problem for all versions
- if (true !== $ignorePlatformReqs && ($candidate = $versionSelector->findBestCandidate($name, null, $preferredStability, true, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES))) {
- $additional = '';
- if (false === $versionSelector->findBestCandidate($name, null, $preferredStability, true)) {
- $additional = PHP_EOL.PHP_EOL.'Additionally, the package was only found with a stability of "'.$candidate->getStability().'" while your minimum stability is "'.$effectiveMinimumStability.'".';
- }
-
+ // Check whether the PHP version was the problem
+ if ($phpVersion && $versionSelector->findBestCandidate($name)) {
throw new \InvalidArgumentException(sprintf(
- 'Could not find package %s in any version matching your PHP version, PHP extensions and Composer version' . $this->getPlatformExceptionDetails($candidate, $platformRepo) . '%s',
+ 'Could not find package %s in any version matching your PHP version (%s)',
$name,
- $additional
+ $phpVersion
));
}
// Check for similar names/typos
$similar = $this->findSimilar($name);
if ($similar) {
- if (in_array($name, $similar, true)) {
+ // Check whether the minimum stability was the problem but the package exists
+ if ($requiredVersion === null && in_array($name, $similar, true)) {
throw new \InvalidArgumentException(sprintf(
- "Could not find package %s. It was however found via repository search, which indicates a consistency issue with the repository.",
- $name
+ 'Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.',
+ $name,
+ $this->getMinimumStability($input)
));
}
@@ -926,7 +796,7 @@ private function findBestVersionAndNameForPackage(InputInterface $input, $name,
throw new \InvalidArgumentException(sprintf(
'Could not find a matching version of package %s. Check the package spelling, your version constraint and that the package is available in a stability which matches your minimum-stability (%s).',
$name,
- $effectiveMinimumStability
+ $this->getMinimumStability($input)
));
}
@@ -936,39 +806,6 @@ private function findBestVersionAndNameForPackage(InputInterface $input, $name,
);
}
- private function getPlatformExceptionDetails(PackageInterface $candidate, PlatformRepository $platformRepo = null)
- {
- $details = array();
- if (!$platformRepo) {
- return '';
- }
-
- foreach ($candidate->getRequires() as $link) {
- if (!PlatformRepository::isPlatformPackage($link->getTarget())) {
- continue;
- }
- $platformPkg = $platformRepo->findPackage($link->getTarget(), '*');
- if (!$platformPkg) {
- $details[] = $candidate->getPrettyName().' '.$candidate->getPrettyVersion().' requires '.$link->getTarget().' '.$link->getPrettyConstraint().' but it is not present.';
- continue;
- }
- if (!$link->getConstraint()->matches(new Constraint('==', $platformPkg->getVersion()))) {
- $platformPkgVersion = $platformPkg->getPrettyVersion();
- $platformExtra = $platformPkg->getExtra();
- if (isset($platformExtra['config.platform']) && $platformPkg instanceof CompletePackageInterface) {
- $platformPkgVersion .= ' ('.$platformPkg->getDescription().')';
- }
- $details[] = $candidate->getPrettyName().' '.$candidate->getPrettyVersion().' requires '.$link->getTarget().' '.$link->getPrettyConstraint().' which does not match your installed version '.$platformPkgVersion.'.';
- }
- }
-
- if (!$details) {
- return '';
- }
-
- return ':'.PHP_EOL.' - ' . implode(PHP_EOL.' - ', $details);
- }
-
private function findSimilar($package)
{
try {
@@ -993,26 +830,15 @@ private function findSimilar($package)
return array_keys(array_slice($similarPackages, 0, 5));
}
- private function updateDependencies($output)
+ private function installDependencies($output)
{
try {
- $updateCommand = $this->getApplication()->find('update');
- $this->getApplication()->resetComposer();
- $updateCommand->run(new ArrayInput(array()), $output);
+ $installCommand = $this->getApplication()->find('install');
+ $installCommand->run(new ArrayInput(array()), $output);
} catch (\Exception $e) {
- $this->getIO()->writeError('Could not update dependencies. Run `composer update` to see more information.');
+ $this->getIO()->writeError('Could not install dependencies. Run `composer install` to see more information.');
}
- }
- private function runDumpAutoloadCommand($output)
- {
- try {
- $command = $this->getApplication()->find('dump-autoload');
- $this->getApplication()->resetComposer();
- $command->run(new ArrayInput(array()), $output);
- } catch (\Exception $e) {
- $this->getIO()->writeError('Could not run dump-autoload.');
- }
}
private function hasDependencies($options)
diff --git a/app/vendor/composer/composer/src/Composer/Command/InstallCommand.php b/app/vendor/composer/composer/src/Composer/Command/InstallCommand.php
index eda9c25cf..32fb1bdc6 100644
--- a/app/vendor/composer/composer/src/Composer/Command/InstallCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/InstallCommand.php
@@ -15,7 +15,6 @@
use Composer\Installer;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
-use Composer\Util\HttpDownloader;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
@@ -37,23 +36,20 @@ protected function configure()
->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
->setDefinition(array(
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'),
- new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).'),
+ new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'DEPRECATED: Enables installation of require-dev packages (enabled by default, only present for BC).'),
- new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'),
+ new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
+ new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('no-install', null, InputOption::VALUE_NONE, 'Do not use, only defined here to catch misuse of the install command.'),
+ new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
- new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
- new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
+ new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
))
->setHelp(
@@ -74,31 +70,23 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = $this->getIO();
- if ($input->getOption('dev')) {
- $io->writeError('You are using the deprecated option "--dev". It has no effect and will break in Composer 3. ');
- }
- if ($input->getOption('no-suggest')) {
- $io->writeError('You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3. ');
- }
-
if ($args = $input->getArgument('packages')) {
$io->writeError('Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json. ');
return 1;
}
- if ($input->getOption('no-install')) {
- $io->writeError('Invalid option "--no-install". Use "composer update --no-install" instead if you are trying to update the composer.lock file. ');
+ if ($input->getOption('no-custom-installers')) {
+ $io->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead. ');
+ $input->setOption('no-plugins', true);
+ }
- return 1;
+ if ($input->getOption('dev')) {
+ $io->writeError('You are using the deprecated option "dev". Dev packages are installed by default now. ');
}
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
- $composer->getEventDispatcher()->setRunScripts(!$input->getOption('no-scripts'));
-
- if ((!$composer->getLocker() || !$composer->getLocker()->isLocked()) && !HttpDownloader::isCurlEnabled()) {
- $io->writeError('Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled. ');
- }
+ $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
@@ -110,12 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
- $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
- $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
-
- $ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
-
- $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress'));
+ $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
$install
->setDryRun($input->getOption('dry-run'))
@@ -124,10 +107,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
->setPreferDist($preferDist)
->setDevMode(!$input->getOption('no-dev'))
->setDumpAutoloader(!$input->getOption('no-autoloader'))
+ ->setRunScripts(!$input->getOption('no-scripts'))
+ ->setSkipSuggest($input->getOption('no-suggest'))
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
- ->setApcuAutoloader($apcu, $apcuPrefix)
- ->setIgnorePlatformRequirements($ignorePlatformReqs)
+ ->setApcuAutoloader($apcu)
+ ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
;
if ($input->getOption('no-plugins')) {
diff --git a/app/vendor/composer/composer/src/Composer/Command/LicensesCommand.php b/app/vendor/composer/composer/src/Composer/Command/LicensesCommand.php
index b4544cf50..85cb64a7f 100644
--- a/app/vendor/composer/composer/src/Composer/Command/LicensesCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/LicensesCommand.php
@@ -21,7 +21,6 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Style\SymfonyStyle;
/**
* @author Benoît Merlet
@@ -34,7 +33,7 @@ protected function configure()
->setName('licenses')
->setDescription('Shows information about licenses of dependencies.')
->setDefinition(array(
- new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text, json or summary', 'text'),
+ new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
))
->setHelp(
@@ -81,8 +80,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (method_exists($tableStyle, 'setVerticalBorderChars')) {
$tableStyle->setVerticalBorderChars('');
} else {
- // TODO remove in composer 2.2
- // @phpstan-ignore-next-line
$tableStyle->setVerticalBorderChar('');
}
$tableStyle->setCellRowContentFormat('%s ');
@@ -114,31 +111,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
)));
break;
- case 'summary':
- $usedLicenses = array();
- foreach ($packages as $package) {
- $license = $package->getLicense();
- $licenseName = $license[0];
- if (!isset($usedLicenses[$licenseName])) {
- $usedLicenses[$licenseName] = 0;
- }
- $usedLicenses[$licenseName]++;
- }
-
- // Sort licenses so that the most used license will appear first
- arsort($usedLicenses, SORT_NUMERIC);
-
- $rows = array();
- foreach ($usedLicenses as $usedLicense => $numberOfDependencies) {
- $rows[] = array($usedLicense, $numberOfDependencies);
- }
-
- $symfonyIo = new SymfonyStyle($input, $output);
- $symfonyIo->table(
- array('License', 'Number of dependencies'),
- $rows
- );
- break;
default:
throw new \RuntimeException(sprintf('Unsupported format "%s". See help for supported formats.', $format));
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/OutdatedCommand.php b/app/vendor/composer/composer/src/Composer/Command/OutdatedCommand.php
index ace1631d8..599087246 100644
--- a/app/vendor/composer/composer/src/Composer/Command/OutdatedCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/OutdatedCommand.php
@@ -32,13 +32,11 @@ protected function configure()
new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
- new InputOption('locked', null, InputOption::VALUE_NONE, 'Shows updates for packages from the lock file, regardless of what is currently in vendor dir'),
new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
))
->setHelp(
<<getOption('minor-only')) {
$args['--minor-only'] = true;
}
- if ($input->getOption('locked')) {
- $args['--locked'] = true;
- }
- if ($input->getOption('no-dev')) {
- $args['--no-dev'] = true;
- }
$args['--format'] = $input->getOption('format');
$args['--ignore'] = $input->getOption('ignore');
diff --git a/app/vendor/composer/composer/src/Composer/Command/ProhibitsCommand.php b/app/vendor/composer/composer/src/Composer/Command/ProhibitsCommand.php
index 9931a881b..1e18e5e23 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ProhibitsCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ProhibitsCommand.php
@@ -14,8 +14,6 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputOption;
/**
* @author Niels Keurentjes
@@ -27,16 +25,12 @@ class ProhibitsCommand extends BaseDependencyCommand
*/
protected function configure()
{
+ parent::configure();
+
$this
->setName('prohibits')
->setAliases(array('why-not'))
->setDescription('Shows which packages prevent the given package from being installed.')
- ->setDefinition(array(
- new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
- new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::REQUIRED, 'Version constraint, which version you expected to be installed'),
- new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
- new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
- ))
->setHelp(
<<
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\Command;
-
-use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\UninstallOperation;
-use Composer\DependencyResolver\Transaction;
-use Composer\Package\AliasPackage;
-use Composer\Package\BasePackage;
-use Composer\Plugin\CommandEvent;
-use Composer\Plugin\PluginEvents;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Output\OutputInterface;
-
-/**
- * @author Jordi Boggiano
- */
-class ReinstallCommand extends BaseCommand
-{
- protected function configure()
- {
- $this
- ->setName('reinstall')
- ->setDescription('Uninstalls and reinstalls the given package names')
- ->setDefinition(array(
- new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'),
- new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).'),
- new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
- new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
- new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
- new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
- new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
- new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
- new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
- new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'List of package names to reinstall, can include a wildcard (*) to match any substring.'),
- ))
- ->setHelp(
- <<reinstall command looks up installed packages by name,
-uninstalls them and reinstalls them. This lets you do a clean install
-of a package if you messed with its files, or if you wish to change
-the installation type using --prefer-install.
-
-php composer.phar reinstall acme/foo "acme/bar-*"
-
-Read more at https://getcomposer.org/doc/03-cli.md#reinstall
-EOT
- )
- ;
- }
-
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $io = $this->getIO();
-
- $composer = $this->getComposer(true, $input->getOption('no-plugins'));
- $composer->getEventDispatcher()->setRunScripts(!$input->getOption('no-scripts'));
-
- $localRepo = $composer->getRepositoryManager()->getLocalRepository();
- $packagesToReinstall = array();
- $packageNamesToReinstall = array();
- foreach ($input->getArgument('packages') as $pattern) {
- $patternRegexp = BasePackage::packageNameToRegexp($pattern);
- $matched = false;
- foreach ($localRepo->getCanonicalPackages() as $package) {
- if (preg_match($patternRegexp, $package->getName())) {
- $matched = true;
- $packagesToReinstall[] = $package;
- $packageNamesToReinstall[] = $package->getName();
- }
- }
-
- if (!$matched) {
- $io->writeError('Pattern "' . $pattern . '" does not match any currently installed packages. ');
- }
- }
-
- if (!$packagesToReinstall) {
- $io->writeError('Found no packages to reinstall, aborting. ');
-
- return 1;
- }
-
- $uninstallOperations = array();
- foreach ($packagesToReinstall as $package) {
- $uninstallOperations[] = new UninstallOperation($package);
- }
-
- // make sure we have a list of install operations ordered by dependency/plugins
- $presentPackages = $localRepo->getPackages();
- $resultPackages = $presentPackages;
- foreach ($presentPackages as $index => $package) {
- if (in_array($package->getName(), $packageNamesToReinstall, true)) {
- unset($presentPackages[$index]);
- }
- }
- $transaction = new Transaction($presentPackages, $resultPackages);
- $installOperations = $transaction->getOperations();
-
- // reverse-sort the uninstalls based on the install order
- $installOrder = array();
- foreach ($installOperations as $index => $op) {
- if ($op instanceof InstallOperation && !$op->getPackage() instanceof AliasPackage) {
- $installOrder[$op->getPackage()->getName()] = $index;
- }
- }
- usort($uninstallOperations, function ($a, $b) use ($installOrder) {
- return $installOrder[$b->getPackage()->getName()] - $installOrder[$a->getPackage()->getName()];
- });
-
- $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'reinstall', $input, $output);
- $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
-
- $config = $composer->getConfig();
- list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
-
- $installationManager = $composer->getInstallationManager();
- $downloadManager = $composer->getDownloadManager();
- $package = $composer->getPackage();
-
- $ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
-
- $installationManager->setOutputProgress(!$input->getOption('no-progress'));
- if ($input->getOption('no-plugins')) {
- $installationManager->disablePlugins();
- }
-
- $downloadManager->setPreferSource($preferSource);
- $downloadManager->setPreferDist($preferDist);
-
- $installationManager->execute($localRepo, $uninstallOperations, true);
- $installationManager->execute($localRepo, $installOperations, true);
-
- if (!$input->getOption('no-autoloader')) {
- $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
- $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
- $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
- $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
-
- $generator = $composer->getAutoloadGenerator();
- $generator->setClassMapAuthoritative($authoritative);
- $generator->setApcu($apcu, $apcuPrefix);
- $generator->setIgnorePlatformRequirements($ignorePlatformReqs);
- $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
- }
-
- return 0;
- }
-}
diff --git a/app/vendor/composer/composer/src/Composer/Command/RemoveCommand.php b/app/vendor/composer/composer/src/Composer/Command/RemoveCommand.php
index 3cd865126..e6a2fbfb3 100644
--- a/app/vendor/composer/composer/src/Composer/Command/RemoveCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/RemoveCommand.php
@@ -13,7 +13,6 @@
namespace Composer\Command;
use Composer\Config\JsonConfigSource;
-use Composer\DependencyResolver\Request;
use Composer\Installer;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
@@ -39,23 +38,16 @@ protected function configure()
->setDefinition(array(
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
- new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies (implies --no-install).'),
- new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'),
+ new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
- new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
- new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
- new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'),
+ new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
- new InputOption('unused', null, InputOption::VALUE_NONE, 'Remove all packages which are locked but not required by any other package.'),
- new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
+ new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
- new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
))
->setHelp(
<<getOption('unused')) {
- $composer = $this->getComposer();
- $locker = $composer->getLocker();
- if (!$locker->isLocked()) {
- throw new \UnexpectedValueException('A valid composer.lock file is required to run this command with --unused');
- }
-
- $lockedPackages = $locker->getLockedRepository()->getPackages();
-
- $required = array();
- foreach (array_merge($composer->getPackage()->getRequires(), $composer->getPackage()->getDevRequires()) as $link) {
- $required[$link->getTarget()] = true;
- }
-
- do {
- $found = false;
- foreach ($lockedPackages as $index => $package) {
- foreach ($package->getNames() as $name) {
- if (isset($required[$name])) {
- foreach ($package->getRequires() as $link) {
- $required[$link->getTarget()] = true;
- }
- $found = true;
- unset($lockedPackages[$index]);
- break;
- }
- }
- }
- } while ($found);
-
- $unused = array();
- foreach ($lockedPackages as $package) {
- $unused[] = $package->getName();
- }
- $input->setArgument('packages', array_merge($input->getArgument('packages'), $unused));
-
- if (!$input->getArgument('packages')) {
- $this->getIO()->writeError('No unused packages to remove ');
- $this->setCode(function () {
- return 0;
- });
- }
- }
- }
-
protected function execute(InputInterface $input, OutputInterface $output)
{
$packages = $input->getArgument('packages');
@@ -147,44 +92,26 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
- $dryRun = $input->getOption('dry-run');
- $toRemove = array();
foreach ($packages as $package) {
if (isset($composer[$type][$package])) {
- if ($dryRun) {
- $toRemove[$type][] = $composer[$type][$package];
- } else {
- $json->removeLink($type, $composer[$type][$package]);
- }
+ $json->removeLink($type, $composer[$type][$package]);
} elseif (isset($composer[$altType][$package])) {
$io->writeError('' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . ' ');
if ($io->isInteractive()) {
- if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [yes ]? ')) {
- if ($dryRun) {
- $toRemove[$altType][] = $composer[$altType][$package];
- } else {
- $json->removeLink($altType, $composer[$altType][$package]);
- }
+ if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [yes ]? ', true)) {
+ $json->removeLink($altType, $composer[$altType][$package]);
}
}
} elseif (isset($composer[$type]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) {
foreach ($matches as $matchedPackage) {
- if ($dryRun) {
- $toRemove[$type][] = $matchedPackage;
- } else {
- $json->removeLink($type, $matchedPackage);
- }
+ $json->removeLink($type, $matchedPackage);
}
} elseif (isset($composer[$altType]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) {
foreach ($matches as $matchedPackage) {
$io->writeError('' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . ' ');
if ($io->isInteractive()) {
- if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [yes ]? ')) {
- if ($dryRun) {
- $toRemove[$altType][] = $matchedPackage;
- } else {
- $json->removeLink($altType, $matchedPackage);
- }
+ if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [yes ]? ', true)) {
+ $json->removeLink($altType, $matchedPackage);
}
}
}
@@ -193,8 +120,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
- $io->writeError(''.$file.' has been updated ');
-
if ($input->getOption('no-update')) {
return 0;
}
@@ -202,85 +127,37 @@ protected function execute(InputInterface $input, OutputInterface $output)
// Update packages
$this->resetComposer();
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
- $composer->getEventDispatcher()->setRunScripts(!$input->getOption('no-scripts'));
-
- if ($dryRun) {
- $rootPackage = $composer->getPackage();
- $links = array(
- 'require' => $rootPackage->getRequires(),
- 'require-dev' => $rootPackage->getDevRequires(),
- );
- foreach ($toRemove as $type => $names) {
- foreach ($names as $name) {
- unset($links[$type][$name]);
- }
- }
- $rootPackage->setRequires($links['require']);
- $rootPackage->setDevRequires($links['require-dev']);
- }
+ $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress'));
-
$install = Installer::create($io, $composer);
$updateDevMode = !$input->getOption('update-no-dev');
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
- $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
- $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
-
- $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
- $flags = '';
- if ($input->getOption('update-with-all-dependencies') || $input->getOption('with-all-dependencies')) {
- $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
- $flags .= ' --with-all-dependencies';
- } elseif ($input->getOption('no-update-with-dependencies')) {
- $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
- $flags .= ' --with-dependencies';
- }
-
- $io->writeError('Running composer update '.implode(' ', $packages).$flags.' ');
-
- $ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
+ $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
$install
->setVerbose($input->getOption('verbose'))
->setDevMode($updateDevMode)
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
- ->setApcuAutoloader($apcu, $apcuPrefix)
+ ->setApcuAutoloader($apcu)
->setUpdate(true)
- ->setInstall(!$input->getOption('no-install'))
- ->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)
- ->setIgnorePlatformRequirements($ignorePlatformReqs)
- ->setDryRun($dryRun)
+ ->setUpdateAllowList($packages)
+ ->setAllowListTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
+ ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
+ ->setRunScripts(!$input->getOption('no-scripts'))
;
- // if no lock is present, we do not do a partial update as
- // this is not supported by the Installer
- if ($composer->getLocker()->isLocked()) {
- $install->setUpdateAllowList($packages);
- }
-
$status = $install->run();
if ($status !== 0) {
$io->writeError("\n".'Removal failed, reverting '.$file.' to its original content. ');
file_put_contents($jsonFile->getPath(), $composerBackup);
}
- if (!$dryRun) {
- foreach ($packages as $package) {
- if ($composer->getRepositoryManager()->getLocalRepository()->findPackages($package)) {
- $io->writeError('Removal failed, '.$package.' is still present, it may be required by another package. See `composer why '.$package.'`. ');
-
- return 2;
- }
- }
- }
-
return $status;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/RequireCommand.php b/app/vendor/composer/composer/src/Composer/Command/RequireCommand.php
index 578e2a208..039250766 100644
--- a/app/vendor/composer/composer/src/Composer/Command/RequireCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/RequireCommand.php
@@ -12,8 +12,6 @@
namespace Composer\Command;
-use Composer\DependencyResolver\Request;
-use Composer\Util\Filesystem;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
@@ -23,8 +21,6 @@
use Composer\Json\JsonFile;
use Composer\Json\JsonManipulator;
use Composer\Package\Version\VersionParser;
-use Composer\Package\Loader\ArrayLoader;
-use Composer\Package\BasePackage;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Repository\CompositeRepository;
@@ -38,20 +34,10 @@
*/
class RequireCommand extends InitCommand
{
- /** @var bool */
private $newlyCreated;
- /** @var bool */
- private $firstRequire;
- /** @var JsonFile */
private $json;
- /** @var string */
private $file;
- /** @var string */
private $composerBackup;
- /** @var string file name */
- private $lock;
- /** @var ?string contents before modification if the lock file exists */
- private $lockBackup;
protected function configure()
{
@@ -61,30 +47,23 @@ protected function configure()
->setDefinition(array(
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Optional package name can also include a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
- new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'),
- new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).'),
+ new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'),
- new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'),
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies (implies --no-install).'),
- new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'),
+ new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
+ new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
- new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
- new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
- new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-dependencies'),
- new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'),
- new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
+ new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
+ new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
+ new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
- new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
))
->setHelp(
<<file = Factory::getComposerFile();
$io = $this->getIO();
- if ($input->getOption('no-suggest')) {
- $io->writeError('You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3. ');
- }
-
$this->newlyCreated = !file_exists($this->file);
if ($this->newlyCreated && !file_put_contents($this->file, "{\n}\n")) {
$io->writeError(''.$this->file.' could not be created. ');
return 1;
}
- if (!Filesystem::isReadable($this->file)) {
+ // check for readability by reading the file as is_readable can not be trusted on network-mounts
+ // see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
+ if (!is_readable($this->file) && false === Silencer::call('file_get_contents', $this->file)) {
$io->writeError(''.$this->file.' is not readable. ');
return 1;
@@ -136,9 +113,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$this->json = new JsonFile($this->file);
- $this->lock = Factory::getLockFile($this->file);
$this->composerBackup = file_get_contents($this->json->getPath());
- $this->lockBackup = file_exists($this->lock) ? file_get_contents($this->lock) : null;
// check for writability by writing to the file as is_writable can not be trusted on network-mounts
// see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
@@ -173,7 +148,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$platformOverrides = $composer->getConfig()->get('platform') ?: array();
// initialize $this->repos as it is used by the parent InitCommand
$this->repos = new CompositeRepository(array_merge(
- array($platformRepo = new PlatformRepository(array(), $platformOverrides)),
+ array(new PlatformRepository(array(), $platformOverrides)),
$repos
));
@@ -183,19 +158,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
$preferredStability = $composer->getPackage()->getMinimumStability();
}
+ $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
try {
- $requirements = $this->determineRequirements(
- $input,
- $output,
- $input->getArgument('packages'),
- $platformRepo,
- $preferredStability,
- !$input->getOption('no-update'),
- $input->getOption('fixed')
- );
+ $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update'), $input->getOption('fixed'));
} catch (\Exception $e) {
if ($this->newlyCreated) {
- throw new \RuntimeException('No composer.json present in the current directory ('.$this->file.'), this may be the cause of the following exception.', 0, $e);
+ throw new \RuntimeException('No composer.json present in the current directory, this may be the cause of the following exception.', 0, $e);
}
throw $e;
@@ -216,47 +184,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
$versionParser->parseConstraints($constraint);
}
- $inconsistentRequireKeys = $this->getInconsistentRequireKeys($requirements, $requireKey);
- if (count($inconsistentRequireKeys) > 0) {
- foreach ($inconsistentRequireKeys as $package) {
- $io->warning(sprintf(
- '%s is currently present in the %s key and you ran the command %s the --dev flag, which would move it to the %s key.',
- $package,
- $removeKey,
- $input->getOption('dev') ? 'with' : 'without',
- $requireKey
- ));
- }
-
- if ($io->isInteractive()) {
- if (!$io->askConfirmation(sprintf('Do you want to move %s? [no ]? ', count($inconsistentRequireKeys) > 1 ? 'these requirements' : 'this requirement'), false)) {
- if (!$io->askConfirmation(sprintf('Do you want to re-run the command %s --dev? [yes ]? ', $input->getOption('dev') ? 'without' : 'with'), true)) {
- return 0;
- }
-
- list($requireKey, $removeKey) = array($removeKey, $requireKey);
- }
- }
- }
-
$sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
- $this->firstRequire = $this->newlyCreated;
- if (!$this->firstRequire) {
- $composerDefinition = $this->json->read();
- if (empty($composerDefinition['require']) && empty($composerDefinition['require-dev'])) {
- $this->firstRequire = true;
- }
- }
-
- if (!$input->getOption('dry-run') && !$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) {
+ if (!$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) {
$composerDefinition = $this->json->read();
foreach ($requirements as $package => $version) {
$composerDefinition[$requireKey][$package] = $version;
unset($composerDefinition[$removeKey][$package]);
- if (isset($composerDefinition[$removeKey]) && count($composerDefinition[$removeKey]) === 0) {
- unset($composerDefinition[$removeKey]);
- }
}
$this->json->write($composerDefinition);
}
@@ -268,123 +202,49 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
try {
- return $this->doUpdate($input, $output, $io, $requirements, $requireKey, $removeKey);
+ return $this->doUpdate($input, $output, $io, $requirements);
} catch (\Exception $e) {
$this->revertComposerFile(false);
throw $e;
}
}
- private function getInconsistentRequireKeys(array $newRequirements, $requireKey)
- {
- $requireKeys = $this->getPackagesByRequireKey();
- $inconsistentRequirements = array();
- foreach ($requireKeys as $package => $packageRequireKey) {
- if (!isset($newRequirements[$package])) {
- continue;
- }
- if ($requireKey !== $packageRequireKey) {
- $inconsistentRequirements[] = $package;
- }
- }
-
- return $inconsistentRequirements;
- }
-
- private function getPackagesByRequireKey()
- {
- $composerDefinition = $this->json->read();
- $require = array();
- $requireDev = array();
-
- if (isset($composerDefinition['require'])) {
- $require = $composerDefinition['require'];
- }
-
- if (isset($composerDefinition['require-dev'])) {
- $requireDev = $composerDefinition['require-dev'];
- }
-
- return array_merge(
- array_fill_keys(array_keys($require), 'require'),
- array_fill_keys(array_keys($requireDev), 'require-dev')
- );
- }
-
- private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements, $requireKey, $removeKey)
+ private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements)
{
// Update packages
$this->resetComposer();
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
- $composer->getEventDispatcher()->setRunScripts(!$input->getOption('no-scripts'));
-
- if ($input->getOption('dry-run')) {
- $rootPackage = $composer->getPackage();
- $links = array(
- 'require' => $rootPackage->getRequires(),
- 'require-dev' => $rootPackage->getDevRequires(),
- );
- $loader = new ArrayLoader();
- $newLinks = $loader->parseLinks($rootPackage->getName(), $rootPackage->getPrettyVersion(), BasePackage::$supportedLinkTypes[$requireKey]['method'], $requirements);
- $links[$requireKey] = array_merge($links[$requireKey], $newLinks);
- foreach ($requirements as $package => $constraint) {
- unset($links[$removeKey][$package]);
- }
- $rootPackage->setRequires($links['require']);
- $rootPackage->setDevRequires($links['require-dev']);
- }
+ $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
$updateDevMode = !$input->getOption('update-no-dev');
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
- $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
- $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
-
- $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
- $flags = '';
- if ($input->getOption('update-with-all-dependencies') || $input->getOption('with-all-dependencies')) {
- $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
- $flags .= ' --with-all-dependencies';
- } elseif ($input->getOption('update-with-dependencies') || $input->getOption('with-dependencies')) {
- $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
- $flags .= ' --with-dependencies';
- }
-
- $io->writeError('Running composer update '.implode(' ', array_keys($requirements)).$flags.' ');
+ $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress'));
-
$install = Installer::create($io, $composer);
- $ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
- list($preferSource, $preferDist) = $this->getPreferredInstallOptions($composer->getConfig(), $input);
-
$install
- ->setDryRun($input->getOption('dry-run'))
->setVerbose($input->getOption('verbose'))
- ->setPreferSource($preferSource)
- ->setPreferDist($preferDist)
+ ->setPreferSource($input->getOption('prefer-source'))
+ ->setPreferDist($input->getOption('prefer-dist'))
->setDevMode($updateDevMode)
+ ->setRunScripts(!$input->getOption('no-scripts'))
+ ->setSkipSuggest($input->getOption('no-suggest'))
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
- ->setApcuAutoloader($apcu, $apcuPrefix)
+ ->setApcuAutoloader($apcu)
->setUpdate(true)
- ->setInstall(!$input->getOption('no-install'))
- ->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)
- ->setIgnorePlatformRequirements($ignorePlatformReqs)
+ ->setUpdateAllowList(array_keys($requirements))
+ ->setAllowListTransitiveDependencies($input->getOption('update-with-dependencies'))
+ ->setAllowListAllDependencies($input->getOption('update-with-all-dependencies'))
+ ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
->setPreferStable($input->getOption('prefer-stable'))
->setPreferLowest($input->getOption('prefer-lowest'))
;
- // if no lock is present, or the file is brand new, we do not do a
- // partial update as this is not supported by the Installer
- if (!$this->firstRequire && $composer->getLocker()->isLocked()) {
- $install->setUpdateAllowList(array_keys($requirements));
- }
-
$status = $install->run();
if ($status !== 0) {
$this->revertComposerFile(false);
@@ -408,8 +268,6 @@ private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $
}
}
- $manipulator->removeMainKeyIfEmpty($removeKey);
-
file_put_contents($json->getPath(), $manipulator->getContents());
return true;
@@ -427,19 +285,9 @@ public function revertComposerFile($hardExit = true)
if ($this->newlyCreated) {
$io->writeError("\n".'Installation failed, deleting '.$this->file.'. ');
unlink($this->json->getPath());
- if (file_exists($this->lock)) {
- unlink($this->lock);
- }
} else {
- $msg = ' to its ';
- if ($this->lockBackup) {
- $msg = ' and '.$this->lock.' to their ';
- }
- $io->writeError("\n".'Installation failed, reverting '.$this->file.$msg.'original content. ');
+ $io->writeError("\n".'Installation failed, reverting '.$this->file.' to its original content. ');
file_put_contents($this->json->getPath(), $this->composerBackup);
- if ($this->lockBackup) {
- file_put_contents($this->lock, $this->lockBackup);
- }
}
if ($hardExit) {
diff --git a/app/vendor/composer/composer/src/Composer/Command/RunScriptCommand.php b/app/vendor/composer/composer/src/Composer/Command/RunScriptCommand.php
index 81b625786..1d1b6be76 100644
--- a/app/vendor/composer/composer/src/Composer/Command/RunScriptCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/RunScriptCommand.php
@@ -15,11 +15,11 @@
use Composer\Script\Event as ScriptEvent;
use Composer\Script\ScriptEvents;
use Composer\Util\ProcessExecutor;
-use Composer\Util\Platform;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Helper\Table;
/**
* @author Fabien Potencier
@@ -27,7 +27,7 @@
class RunScriptCommand extends BaseCommand
{
/**
- * @var string[] Array with command events
+ * @var array Array with command events
*/
protected $scriptEvents = array(
ScriptEvents::PRE_INSTALL_CMD,
@@ -74,8 +74,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('list')) {
return $this->listScripts($output);
- }
- if (!$input->getArgument('script')) {
+ } elseif (!$input->getArgument('script')) {
throw new \RuntimeException('Missing required argument "script"');
}
@@ -104,8 +103,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
ProcessExecutor::setTimeout((int) $timeout);
}
- Platform::putEnv('COMPOSER_DEV_MODE', $devMode ? '1' : '0');
-
return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
}
@@ -133,7 +130,16 @@ protected function listScripts(OutputInterface $output)
$table[] = array(' '.$name, $description);
}
- $this->renderTable($table, $output);
+ $renderer = new Table($output);
+ $renderer->setStyle('compact');
+ $rendererStyle = $renderer->getStyle();
+ if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
+ $rendererStyle->setVerticalBorderChars('');
+ } else {
+ $rendererStyle->setVerticalBorderChar('');
+ }
+ $rendererStyle->setCellRowContentFormat('%s ');
+ $renderer->setRows($table)->render();
return 0;
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/ScriptAliasCommand.php b/app/vendor/composer/composer/src/Composer/Command/ScriptAliasCommand.php
index 63f0f9e6a..455f7420c 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ScriptAliasCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ScriptAliasCommand.php
@@ -22,9 +22,7 @@
*/
class ScriptAliasCommand extends BaseCommand
{
- /** @var string */
private $script;
- /** @var string */
private $description;
public function __construct($script, $description)
diff --git a/app/vendor/composer/composer/src/Composer/Command/SearchCommand.php b/app/vendor/composer/composer/src/Composer/Command/SearchCommand.php
index 8b51d530a..0e8aa60e4 100644
--- a/app/vendor/composer/composer/src/Composer/Command/SearchCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/SearchCommand.php
@@ -13,7 +13,6 @@
namespace Composer\Command;
use Composer\Factory;
-use Composer\Json\JsonFile;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
@@ -29,6 +28,12 @@
*/
class SearchCommand extends BaseCommand
{
+ protected $matches;
+ protected $lowMatches = array();
+ protected $tokens;
+ protected $output;
+ protected $onlyName;
+
protected function configure()
{
$this
@@ -37,7 +42,6 @@ protected function configure()
->setDefinition(array(
new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
- new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
))
->setHelp(
@@ -56,14 +60,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
// init repos
$platformRepo = new PlatformRepository;
$io = $this->getIO();
-
- $format = $input->getOption('format');
- if (!in_array($format, array('text', 'json'))) {
- $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
-
- return 1;
- }
-
if (!($composer = $this->getComposer(false))) {
$composer = Factory::create($this->getIO(), array(), $input->hasParameterOption('--no-plugins'));
}
@@ -80,25 +76,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
$flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
$results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
- if ($results && $format === 'text') {
- $width = $this->getTerminalWidth();
-
- $nameLength = 0;
- foreach ($results as $result) {
- $nameLength = max(strlen($result['name']), $nameLength);
- }
- $nameLength += 1;
- foreach ($results as $result) {
- $description = isset($result['description']) ? $result['description'] : '';
- $remaining = $width - $nameLength - 2;
- if (strlen($description) > $remaining) {
- $description = substr($description, 0, $remaining - 3) . '...';
- }
-
- $io->write(str_pad($result['name'], $nameLength, ' ') . $description);
- }
- } elseif ($format === 'json') {
- $io->write(JsonFile::encode($results));
+ foreach ($results as $result) {
+ $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
}
return 0;
diff --git a/app/vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php b/app/vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php
index 70e65d252..686a48b02 100644
--- a/app/vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/SelfUpdateCommand.php
@@ -21,7 +21,6 @@
use Composer\SelfUpdate\Versions;
use Composer\IO\IOInterface;
use Composer\Downloader\FilesystemException;
-use Composer\Downloader\TransportException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
@@ -81,9 +80,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$io = $this->getIO();
- $httpDownloader = Factory::createHttpDownloader($io, $config);
+ $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
- $versionsUtil = new Versions($config, $httpDownloader);
+ $versionsUtil = new Versions($config, $remoteFilesystem);
// switch channel if requested
$requestedChannel = null;
@@ -125,8 +124,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
$composeUser = posix_getpwuid(posix_geteuid());
$homeOwner = posix_getpwuid(fileowner($home));
- if (isset($composeUser['name'], $homeOwner['name']) && $composeUser['name'] !== $homeOwner['name']) {
- $io->writeError('You are running Composer as "'.$composeUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'" ');
+ if (isset($composeUser['name']) && isset($homeOwner['name']) && $composeUser['name'] !== $homeOwner['name']) {
+ $io->writeError('You are running composer as "'.$composeUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'" ');
}
}
@@ -167,7 +166,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
- if ($requestedChannel && is_numeric($requestedChannel) && strpos($latestStable['version'], $requestedChannel) !== 0) {
+ if ($requestedChannel && is_numeric($requestedChannel) && substr($latestStable['version'], 0, 1) !== $requestedChannel) {
$io->writeError('Warning: You forced the install of '.$latestVersion.' via --'.$requestedChannel.', but '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended. ');
}
@@ -185,7 +184,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (Composer::VERSION === $updateVersion) {
$io->writeError(
sprintf(
- 'You are already using the latest available Composer version %s (%s channel). ',
+ 'You are already using composer version %s (%s channel). ',
$updateVersion,
$channelString
)
@@ -210,18 +209,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
$updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
- $io->write(sprintf("Upgrading to version %s (%s channel).", $updateVersion, $channelString));
+ $io->write(sprintf("Updating to version %s (%s channel).", $updateVersion, $channelString));
$remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
- try {
- $signature = $httpDownloader->get($remoteFilename.'.sig')->getBody();
- } catch (TransportException $e) {
- if ($e->getStatusCode() === 404) {
- throw new \InvalidArgumentException('Version "'.$updateVersion.'" could not be found.', 0, $e);
- }
- throw $e;
- }
+ $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
$io->writeError(' ', false);
- $httpDownloader->copy($remoteFilename, $tempFilename);
+ $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
$io->writeError('');
if (!file_exists($tempFilename) || !$signature) {
@@ -381,7 +373,7 @@ protected function rollback(OutputInterface $output, $rollbackDir, $localFilenam
if (!is_file($oldFile)) {
throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
}
- if (!Filesystem::isReadable($oldFile)) {
+ if (!is_readable($oldFile)) {
throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
}
@@ -397,11 +389,11 @@ protected function rollback(OutputInterface $output, $rollbackDir, $localFilenam
/**
* Checks if the downloaded/rollback phar is valid then moves it
*
- * @param string $localFilename The composer.phar location
- * @param string $newFilename The downloaded or backup phar
- * @param string $backupTarget The filename to use for the backup
- * @throws FilesystemException If the file cannot be moved
- * @return bool Whether the phar is valid and has been moved
+ * @param string $localFilename The composer.phar location
+ * @param string $newFilename The downloaded or backup phar
+ * @param string $backupTarget The filename to use for the backup
+ * @throws \FilesystemException If the file cannot be moved
+ * @return bool Whether the phar is valid and has been moved
*/
protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
{
@@ -425,14 +417,7 @@ protected function setLocalPhar($localFilename, $newFilename, $backupTarget = nu
}
try {
- if (Platform::isWindows()) {
- // use copy to apply permissions from the destination directory
- // as rename uses source permissions and may block other users
- copy($newFilename, $localFilename);
- @unlink($newFilename);
- } else {
- rename($newFilename, $localFilename);
- }
+ rename($newFilename, $localFilename);
return true;
} catch (\Exception $e) {
@@ -479,24 +464,26 @@ protected function getLastBackupVersion($rollbackDir)
protected function getOldInstallationFinder($rollbackDir)
{
- return Finder::create()
+ $finder = Finder::create()
->depth(0)
->files()
->name('*' . self::OLD_INSTALL_EXT)
->in($rollbackDir);
+
+ return $finder;
}
/**
* Validates the downloaded/backup phar file
*
- * @param string $pharFile The downloaded or backup phar
- * @param null|string $error Set by method on failure
+ * @param string $pharFile The downloaded or backup phar
+ * @param null|string $error Set by method on failure
*
* Code taken from getcomposer.org/installer. Any changes should be made
* there and replicated here
*
+ * @return bool If the operation succeeded
* @throws \Exception
- * @return bool If the operation succeeded
*/
protected function validatePhar($pharFile, &$error)
{
@@ -541,11 +528,11 @@ protected function isWindowsNonAdminUser()
/**
* Invokes a UAC prompt to update composer.phar as an admin
*
- * Uses a .vbs script to elevate and run the cmd.exe copy command.
+ * Uses a .vbs script to elevate and run the cmd.exe move command.
*
- * @param string $localFilename The composer.phar location
- * @param string $newFilename The downloaded or backup phar
- * @return bool Whether composer.phar has been updated
+ * @param string $localFilename The composer.phar location
+ * @param string $newFilename The downloaded or backup phar
+ * @return bool Whether composer.phar has been updated
*/
protected function tryAsWindowsAdmin($localFilename, $newFilename)
{
@@ -567,13 +554,13 @@ protected function tryAsWindowsAdmin($localFilename, $newFilename)
$checksum = hash_file('sha256', $newFilename);
- // cmd's internal copy is fussy about backslashes
+ // cmd's internal move is fussy about backslashes
$source = str_replace('/', '\\', $newFilename);
$destination = str_replace('/', '\\', $localFilename);
$vbs = <<writeError('Operation succeeded. ');
- @unlink($newFilename);
} else {
- $io->writeError('Operation failed.'.$helpMessage.' ');
- }
+ $io->writeError('Operation failed (file not written). '.$helpMessage.' ');
+ };
return $result;
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/ShowCommand.php b/app/vendor/composer/composer/src/Composer/Command/ShowCommand.php
index 057edc40e..40d4f5981 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ShowCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ShowCommand.php
@@ -14,33 +14,31 @@
use Composer\Composer;
use Composer\DependencyResolver\DefaultPolicy;
+use Composer\DependencyResolver\Pool;
use Composer\Json\JsonFile;
use Composer\Package\BasePackage;
use Composer\Package\CompletePackageInterface;
-use Composer\Package\Link;
-use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\VersionSelector;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
-use Composer\Repository\InstalledArrayRepository;
+use Composer\Repository\ArrayRepository;
use Composer\Repository\ComposerRepository;
use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryFactory;
-use Composer\Repository\InstalledRepository;
use Composer\Repository\RepositoryInterface;
-use Composer\Repository\RepositorySet;
-use Composer\Repository\RootPackageRepository;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Semver;
use Composer\Spdx\SpdxLicenses;
+use Composer\Util\Platform;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Terminal;
/**
* @author Robert Schönthal
@@ -52,11 +50,10 @@ class ShowCommand extends BaseCommand
{
/** @var VersionParser */
protected $versionParser;
- /** @var string[] */
protected $colors;
- /** @var ?RepositorySet */
- private $repositorySet;
+ /** @var Pool */
+ private $pool;
protected function configure()
{
@@ -68,7 +65,6 @@ protected function configure()
new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
- new InputOption('locked', null, InputOption::VALUE_NONE, 'List all locked packages'),
new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
@@ -83,7 +79,6 @@ protected function configure()
new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
- new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
))
->setHelp(
<<getConfig()->get('platform') ?: array();
}
$platformRepo = new PlatformRepository(array(), $platformOverrides);
- $lockedRepo = null;
+ $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
if ($input->getOption('self')) {
$package = $this->getComposer()->getPackage();
if ($input->getOption('name-only')) {
$io->write($package->getName());
-
return 0;
}
- $repos = $installedRepo = new InstalledRepository(array(new RootPackageRepository($package)));
+ $repos = $installedRepo = new ArrayRepository(array($package));
} elseif ($input->getOption('platform')) {
- $repos = $installedRepo = new InstalledRepository(array($platformRepo));
+ $repos = $installedRepo = $platformRepo;
} elseif ($input->getOption('available')) {
- $installedRepo = new InstalledRepository(array($platformRepo));
+ $installedRepo = $platformRepo;
if ($composer) {
$repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
- $installedRepo->addRepository($composer->getRepositoryManager()->getLocalRepository());
} else {
$defaultRepos = RepositoryFactory::defaultRepos($io);
$repos = new CompositeRepository($defaultRepos);
@@ -177,41 +170,16 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
} elseif ($input->getOption('all') && $composer) {
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
- $locker = $composer->getLocker();
- if ($locker->isLocked()) {
- $lockedRepo = $locker->getLockedRepository(true);
- $installedRepo = new InstalledRepository(array($lockedRepo, $localRepo, $platformRepo));
- } else {
- $installedRepo = new InstalledRepository(array($localRepo, $platformRepo));
- }
+ $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
$repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
} elseif ($input->getOption('all')) {
$defaultRepos = RepositoryFactory::defaultRepos($io);
$io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
- $installedRepo = new InstalledRepository(array($platformRepo));
+ $installedRepo = $platformRepo;
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
- } elseif ($input->getOption('locked')) {
- if (!$composer || !$composer->getLocker()->isLocked()) {
- throw new \UnexpectedValueException('A valid composer.json and composer.lock files is required to run this command with --locked');
- }
- $locker = $composer->getLocker();
- $lockedRepo = $locker->getLockedRepository(!$input->getOption('no-dev'));
- $repos = $installedRepo = new InstalledRepository(array($lockedRepo));
} else {
- // --installed / default case
- if (!$composer) {
- $composer = $this->getComposer();
- }
- $rootPkg = $composer->getPackage();
- $repos = $installedRepo = new InstalledRepository(array($composer->getRepositoryManager()->getLocalRepository()));
-
- if ($input->getOption('no-dev')) {
- $packages = $this->filterRequiredPackages($installedRepo, $rootPkg);
- $repos = $installedRepo = new InstalledRepository(array(new InstalledArrayRepository(array_map(function ($pkg) {
- return clone $pkg;
- }, $packages))));
- }
-
+ $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
+ $rootPkg = $this->getComposer()->getPackage();
if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
$io->writeError('No dependencies installed. Try running composer install or update. ');
}
@@ -237,7 +205,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (empty($package)) {
$options = $input->getOptions();
if (!isset($options['working-dir']) || !file_exists('composer.json')) {
- if (PlatformRepository::isPlatformPackage($input->getArgument('package')) && !$input->getOption('platform')) {
+ if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $input->getArgument('package')) && !$input->getOption('platform')) {
throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found, try using --platform (-p) to show platform packages.');
}
throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
@@ -263,15 +231,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
} else {
$latestPackage = null;
if ($input->getOption('latest')) {
- $latestPackage = $this->findLatestPackage($package, $composer, $platformRepo, $input->getOption('minor-only'));
+ $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
}
- if (
- $input->getOption('outdated')
- && $input->getOption('strict')
- && $latestPackage
- && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion()
- && (!$latestPackage instanceof CompletePackageInterface || !$latestPackage->isAbandoned())
- ) {
+ if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
$exitCode = 1;
}
if ($input->getOption('path')) {
@@ -312,11 +274,16 @@ protected function execute(InputInterface $input, OutputInterface $output)
return 0;
}
+ if ($repos instanceof CompositeRepository) {
+ $repos = $repos->getRepositories();
+ } elseif (!is_array($repos)) {
+ $repos = array($repos);
+ }
+
// list packages
$packages = array();
- $packageFilterRegex = null;
if (null !== $packageFilter) {
- $packageFilterRegex = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
+ $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
}
$packageListFilter = array();
@@ -324,24 +291,45 @@ protected function execute(InputInterface $input, OutputInterface $output)
$packageListFilter = $this->getRootRequires();
}
+ if (class_exists('Symfony\Component\Console\Terminal')) {
+ $terminal = new Terminal();
+ $width = $terminal->getWidth();
+ } else {
+ // For versions of Symfony console before 3.2
+ list($width) = $this->getApplication()->getTerminalDimensions();
+ }
+ if (null === $width) {
+ // In case the width is not detected, we're probably running the command
+ // outside of a real terminal, use space without a limit
+ $width = PHP_INT_MAX;
+ }
+ if (Platform::isWindows()) {
+ $width--;
+ } else {
+ $width = max(80, $width);
+ }
+
if ($input->getOption('path') && null === $composer) {
$io->writeError('No composer.json found in the current directory, disabling "path" option');
$input->setOption('path', false);
}
- foreach ($repos->getRepositories() as $repo) {
+ foreach ($repos as $repo) {
if ($repo === $platformRepo) {
$type = 'platform';
- } elseif ($lockedRepo !== null && $repo === $lockedRepo) {
- $type = 'locked';
- } elseif ($repo === $installedRepo || in_array($repo, $installedRepo->getRepositories(), true)) {
+ } elseif (
+ $repo === $installedRepo
+ || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
+ ) {
$type = 'installed';
} else {
$type = 'available';
}
- if ($repo instanceof ComposerRepository) {
- foreach ($repo->getPackageNames($packageFilter) as $name) {
- $packages[$type][$name] = $name;
+ if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
+ foreach ($repo->getProviderNames() as $name) {
+ if (!$packageFilter || preg_match($packageFilter, $name)) {
+ $packages[$type][$name] = $name;
+ }
}
} else {
foreach ($repo->getPackages() as $package) {
@@ -349,10 +337,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
|| !is_object($packages[$type][$package->getName()])
|| version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
) {
- while ($package instanceof AliasPackage) {
- $package = $package->getAliasOf();
- }
- if (!$packageFilterRegex || preg_match($packageFilterRegex, $package->getName())) {
+ if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
$packages[$type][$package->getName()] = $package;
}
@@ -367,12 +352,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
$showMinorOnly = $input->getOption('minor-only');
$ignoredPackages = array_map('strtolower', $input->getOption('ignore'));
$indent = $showAllTypes ? ' ' : '';
- /** @var PackageInterface[] $latestPackages */
$latestPackages = array();
$exitCode = 0;
$viewData = array();
$viewMetaData = array();
- foreach (array('platform' => true, 'locked' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
+ foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
if (isset($packages[$type])) {
ksort($packages[$type]);
@@ -381,7 +365,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
if ($showLatest && $showVersion) {
foreach ($packages[$type] as $package) {
if (is_object($package)) {
- $latestPackage = $this->findLatestPackage($package, $composer, $platformRepo, $showMinorOnly);
+ $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
if ($latestPackage === false) {
continue;
}
@@ -408,13 +392,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
// Determine if Composer is checking outdated dependencies and if current package should trigger non-default exit code
- $packageIsUpToDate = $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && (!$latestPackage instanceof CompletePackageInterface || !$latestPackage->isAbandoned());
+ $packageIsUpToDate = $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned();
$packageIsIgnored = \in_array($package->getPrettyName(), $ignoredPackages, true);
if ($input->getOption('outdated') && ($packageIsUpToDate || $packageIsIgnored)) {
continue;
- }
-
- if ($input->getOption('outdated') || $input->getOption('strict')) {
+ } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
$hasOutdatedPackages = true;
}
@@ -436,7 +418,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
}
- if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) {
+ if ($latestPackage && $latestPackage->isAbandoned()) {
$replacement = is_string($latestPackage->getReplacementPackage())
? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
: 'No replacement was suggested';
@@ -468,26 +450,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
if ('json' === $format) {
$io->write(JsonFile::encode($viewData));
} else {
- if ($input->getOption('latest') && array_filter($viewData)) {
- if (!$io->isDecorated()) {
- $io->writeError('Legend:');
- $io->writeError('! patch or minor release available - update recommended');
- $io->writeError('~ major release available - update possible');
- if (!$input->getOption('outdated')) {
- $io->writeError('= up to date version');
- }
- } else {
- $io->writeError('Color legend: ');
- $io->writeError('- patch or minor release available - update recommended');
- $io->writeError('- major release available - update possible');
- if (!$input->getOption('outdated')) {
- $io->writeError('- up to date version');
- }
- }
- }
-
- $width = $this->getTerminalWidth();
-
foreach ($viewData as $type => $packages) {
$nameLength = $viewMetaData[$type]['nameLength'];
$versionLength = $viewMetaData[$type]['versionLength'];
@@ -570,32 +532,32 @@ protected function getVersionStyle(PackageInterface $latestPackage, PackageInter
/**
* finds a package by name and version if provided
*
- * @param InstalledRepository $installedRepo
+ * @param RepositoryInterface $installedRepo
* @param RepositoryInterface $repos
* @param string $name
* @param ConstraintInterface|string $version
* @throws \InvalidArgumentException
* @return array array(CompletePackageInterface, array of versions)
*/
- protected function getPackage(InstalledRepository $installedRepo, RepositoryInterface $repos, $name, $version = null)
+ protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
{
$name = strtolower($name);
$constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
$policy = new DefaultPolicy();
- $repositorySet = new RepositorySet('dev');
- $repositorySet->allowInstalledRepositories();
- $repositorySet->addRepository($repos);
+ $pool = new Pool('dev');
+ $pool->addRepository($repos);
$matchedPackage = null;
$versions = array();
- if (PlatformRepository::isPlatformPackage($name)) {
- $pool = $repositorySet->createPoolWithAllPackages();
- } else {
- $pool = $repositorySet->createPoolForPackage($name);
- }
$matches = $pool->whatProvides($name, $constraint);
foreach ($matches as $index => $package) {
+ // skip providers/replacers
+ if ($package->getName() !== $name) {
+ unset($matches[$index]);
+ continue;
+ }
+
// select an exact match if it is in the installed repo and no specific version was required
if (null === $version && $installedRepo->hasPackage($package)) {
$matchedPackage = $package;
@@ -606,7 +568,7 @@ protected function getPackage(InstalledRepository $installedRepo, RepositoryInte
}
// select preferred package according to policy rules
- if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, $matches)) {
+ if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
$matchedPackage = $pool->literalToPackage($preferred[0]);
}
@@ -618,16 +580,16 @@ protected function getPackage(InstalledRepository $installedRepo, RepositoryInte
*
* @param CompletePackageInterface $package
* @param array $versions
- * @param InstalledRepository $installedRepo
+ * @param RepositoryInterface $installedRepo
* @param PackageInterface|null $latestPackage
*/
- protected function printPackageInfo(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, PackageInterface $latestPackage = null)
+ protected function printPackageInfo(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
{
$io = $this->getIO();
$this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
- $this->printLinks($package, Link::TYPE_REQUIRE);
- $this->printLinks($package, Link::TYPE_DEV_REQUIRE, 'requires (dev)');
+ $this->printLinks($package, 'requires');
+ $this->printLinks($package, 'devRequires', 'requires (dev)');
if ($package->getSuggests()) {
$io->write("\nsuggests ");
@@ -636,9 +598,9 @@ protected function printPackageInfo(CompletePackageInterface $package, array $ve
}
}
- $this->printLinks($package, Link::TYPE_PROVIDE);
- $this->printLinks($package, Link::TYPE_CONFLICT);
- $this->printLinks($package, Link::TYPE_REPLACE);
+ $this->printLinks($package, 'provides');
+ $this->printLinks($package, 'conflicts');
+ $this->printLinks($package, 'replaces');
}
/**
@@ -646,10 +608,10 @@ protected function printPackageInfo(CompletePackageInterface $package, array $ve
*
* @param CompletePackageInterface $package
* @param array $versions
- * @param InstalledRepository $installedRepo
+ * @param RepositoryInterface $installedRepo
* @param PackageInterface|null $latestPackage
*/
- protected function printMeta(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, PackageInterface $latestPackage = null)
+ protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
{
$io = $this->getIO();
$io->write('name : ' . $package->getPrettyName());
@@ -672,7 +634,7 @@ protected function printMeta(CompletePackageInterface $package, array $versions,
}
$io->write('names : ' . implode(', ', $package->getNames()));
- if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) {
+ if ($latestPackage->isAbandoned()) {
$replacement = ($latestPackage->getReplacementPackage() !== null)
? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
: null;
@@ -694,7 +656,11 @@ protected function printMeta(CompletePackageInterface $package, array $versions,
foreach ($package->getAutoload() as $type => $autoloads) {
$io->write('' . $type . ' ');
- if ($type === 'psr-0' || $type === 'psr-4') {
+ if ($type === 'psr-0') {
+ foreach ($autoloads as $name => $path) {
+ $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
+ }
+ } elseif ($type === 'psr-4') {
foreach ($autoloads as $name => $path) {
$io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
}
@@ -714,21 +680,19 @@ protected function printMeta(CompletePackageInterface $package, array $versions,
*
* @param CompletePackageInterface $package
* @param array $versions
- * @param InstalledRepository $installedRepo
+ * @param RepositoryInterface $installedRepo
*/
- protected function printVersions(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo)
+ protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
{
- $versions = array_keys($versions);
- $versions = Semver::rsort($versions);
+ uasort($versions, 'version_compare');
+ $versions = array_keys(array_reverse($versions));
// highlight installed version
- if ($installedPackages = $installedRepo->findPackages($package->getName())) {
- foreach ($installedPackages as $installedPackage) {
- $installedVersion = $installedPackage->getPrettyVersion();
- $key = array_search($installedVersion, $versions);
- if (false !== $key) {
- $versions[$key] = '* ' . $installedVersion . ' ';
- }
+ if ($installedRepo->hasPackage($package)) {
+ $installedVersion = $package->getPrettyVersion();
+ $key = array_search($installedVersion, $versions);
+ if (false !== $key) {
+ $versions[$key] = '* ' . $installedVersion . ' ';
}
}
@@ -792,10 +756,10 @@ protected function printLicenses(CompletePackageInterface $package)
*
* @param CompletePackageInterface $package
* @param array $versions
- * @param InstalledRepository $installedRepo
+ * @param RepositoryInterface $installedRepo
* @param PackageInterface|null $latestPackage
*/
- protected function printPackageInfoAsJson(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, PackageInterface $latestPackage = null)
+ protected function printPackageInfoAsJson(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
{
$json = array(
'name' => $package->getPrettyName(),
@@ -803,7 +767,7 @@ protected function printPackageInfoAsJson(CompletePackageInterface $package, arr
'keywords' => $package->getKeywords() ?: array(),
'type' => $package->getType(),
'homepage' => $package->getHomepage(),
- 'names' => $package->getNames(),
+ 'names' => $package->getNames()
);
$json = $this->appendVersions($json, $versions);
@@ -819,7 +783,7 @@ protected function printPackageInfoAsJson(CompletePackageInterface $package, arr
$json['source'] = array(
'type' => $package->getSourceType(),
'url' => $package->getSourceUrl(),
- 'reference' => $package->getSourceReference(),
+ 'reference' => $package->getSourceReference()
);
}
@@ -827,7 +791,7 @@ protected function printPackageInfoAsJson(CompletePackageInterface $package, arr
$json['dist'] = array(
'type' => $package->getDistType(),
'url' => $package->getDistUrl(),
- 'reference' => $package->getDistReference(),
+ 'reference' => $package->getDistReference()
);
}
@@ -838,7 +802,7 @@ protected function printPackageInfoAsJson(CompletePackageInterface $package, arr
}
}
- if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) {
+ if ($latestPackage->isAbandoned()) {
$json['replacement'] = $latestPackage->getReplacementPackage();
}
@@ -885,7 +849,7 @@ private function appendLicenses($json, CompletePackageInterface $package)
return array(
'name' => $license[0],
'osi' => $licenseId,
- 'url' => $license[2],
+ 'url' => $license[2]
);
}, $licenses);
}
@@ -924,7 +888,7 @@ private function appendAutoload($json, CompletePackageInterface $package)
private function appendLinks($json, CompletePackageInterface $package)
{
- foreach (Link::$TYPES as $linkType) {
+ foreach (array('requires', 'devRequires', 'provides', 'conflicts', 'replaces') as $linkType) {
$json = $this->appendLink($json, $package, $linkType);
}
@@ -1015,15 +979,15 @@ protected function displayPackageTree(array $arrayTree)
/**
* Generate the package tree
*
- * @param PackageInterface $package
- * @param InstalledRepository $installedRepo
- * @param RepositoryInterface $remoteRepos
+ * @param PackageInterface $package
+ * @param RepositoryInterface $installedRepo
+ * @param RepositoryInterface $distantRepos
* @return array
*/
protected function generatePackageTree(
PackageInterface $package,
- InstalledRepository $installedRepo,
- RepositoryInterface $remoteRepos
+ RepositoryInterface $installedRepo,
+ RepositoryInterface $distantRepos
) {
$requires = $package->getRequires();
ksort($requires);
@@ -1036,7 +1000,7 @@ protected function generatePackageTree(
'version' => $require->getPrettyConstraint(),
);
- $deepChildren = $this->addTree($requireName, $require, $installedRepo, $remoteRepos, $packagesInTree);
+ $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree);
if ($deepChildren) {
$treeChildDesc['requires'] = $deepChildren;
@@ -1047,7 +1011,7 @@ protected function generatePackageTree(
$tree = array(
'name' => $package->getPrettyName(),
'version' => $package->getPrettyVersion(),
- 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : '',
+ 'description' => $package->getDescription(),
);
if ($children) {
@@ -1060,10 +1024,10 @@ protected function generatePackageTree(
/**
* Display a package tree
*
- * @param array|string $package
- * @param array $packagesInTree
- * @param string $previousTreeBar
- * @param int $level
+ * @param PackageInterface|string $package
+ * @param array $packagesInTree
+ * @param string $previousTreeBar
+ * @param int $level
*/
protected function displayTree(
$package,
@@ -1072,7 +1036,7 @@ protected function displayTree(
$level = 1
) {
$previousTreeBar = str_replace('├', '│', $previousTreeBar);
- if (is_array($package) && isset($package['requires'])) {
+ if (isset($package['requires'])) {
$requires = $package['requires'];
$treeBar = $previousTreeBar . ' ├';
$i = 0;
@@ -1113,26 +1077,26 @@ protected function displayTree(
/**
* Display a package tree
*
- * @param string $name
- * @param Link $link
- * @param InstalledRepository $installedRepo
- * @param RepositoryInterface $remoteRepos
- * @param array $packagesInTree
+ * @param string $name
+ * @param PackageInterface|string $package
+ * @param RepositoryInterface $installedRepo
+ * @param RepositoryInterface $distantRepos
+ * @param array $packagesInTree
* @return array
*/
protected function addTree(
$name,
- Link $link,
- InstalledRepository $installedRepo,
- RepositoryInterface $remoteRepos,
+ $package,
+ RepositoryInterface $installedRepo,
+ RepositoryInterface $distantRepos,
array $packagesInTree
) {
$children = array();
- list($package) = $this->getPackage(
+ list($package, $versions) = $this->getPackage(
$installedRepo,
- $remoteRepos,
+ $distantRepos,
$name,
- $link->getPrettyConstraint() === 'self.version' ? $link->getConstraint() : $link->getPrettyConstraint()
+ $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint()
);
if (is_object($package)) {
$requires = $package->getRequires();
@@ -1147,7 +1111,7 @@ protected function addTree(
if (!in_array($requireName, $currentTree, true)) {
$currentTree[] = $requireName;
- $deepChildren = $this->addTree($requireName, $require, $installedRepo, $remoteRepos, $currentTree);
+ $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $currentTree);
if ($deepChildren) {
$treeChildDesc['requires'] = $deepChildren;
}
@@ -1200,18 +1164,18 @@ private function writeTreeLine($line)
/**
* Given a package, this finds the latest package matching it
*
- * @param PackageInterface $package
- * @param Composer $composer
- * @param PlatformRepository $platformRepo
- * @param bool $minorOnly
+ * @param PackageInterface $package
+ * @param Composer $composer
+ * @param string $phpVersion
+ * @param bool $minorOnly
*
- * @return PackageInterface|false
+ * @return PackageInterface|null
*/
- private function findLatestPackage(PackageInterface $package, Composer $composer, PlatformRepository $platformRepo, $minorOnly = false)
+ private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
{
- // find the latest version allowed in this repo set
+ // find the latest version allowed in this pool
$name = $package->getName();
- $versionSelector = new VersionSelector($this->getRepositorySet($composer), $platformRepo);
+ $versionSelector = new VersionSelector($this->getPool($composer));
$stability = $composer->getPackage()->getMinimumStability();
$flags = $composer->getPackage()->getStabilityFlags();
if (isset($flags[$name])) {
@@ -1232,51 +1196,16 @@ private function findLatestPackage(PackageInterface $package, Composer $composer
$targetVersion = '^' . $package->getVersion();
}
- $candidate = $versionSelector->findBestCandidate($name, $targetVersion, $bestStability);
- while ($candidate instanceof AliasPackage) {
- $candidate = $candidate->getAliasOf();
- }
-
- return $candidate;
+ return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
}
- /**
- * @return RepositorySet
- */
- private function getRepositorySet(Composer $composer)
+ private function getPool(Composer $composer)
{
- if (!$this->repositorySet) {
- $this->repositorySet = new RepositorySet($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
- $this->repositorySet->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
- }
-
- return $this->repositorySet;
- }
-
- /**
- * Find package requires and child requires
- *
- * @param RepositoryInterface $repo
- * @param PackageInterface $package
- * @param array $bucket
- * @return array
- */
- private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
- {
- $requires = $package->getRequires();
-
- foreach ($repo->getPackages() as $candidate) {
- foreach ($candidate->getNames() as $name) {
- if (isset($requires[$name])) {
- if (!in_array($candidate, $bucket, true)) {
- $bucket[] = $candidate;
- $bucket = $this->filterRequiredPackages($repo, $candidate, $bucket);
- }
- break;
- }
- }
+ if (!$this->pool) {
+ $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
+ $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
}
- return $bucket;
+ return $this->pool;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/StatusCommand.php b/app/vendor/composer/composer/src/Composer/Command/StatusCommand.php
index ede91ac13..6e07ed5d9 100644
--- a/app/vendor/composer/composer/src/Composer/Command/StatusCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/StatusCommand.php
@@ -73,7 +73,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// Dispatch pre-status-command
$composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
- $exitCode = $this->doExecute($input);
+ $exitCode = $this->doExecute($input, $output);
// Dispatch post-status-command
$composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
@@ -82,10 +82,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
/**
- * @param InputInterface $input
+ * @param InputInterface $input
+ * @param OutputInterface $output
* @return int
*/
- private function doExecute(InputInterface $input)
+ private function doExecute(InputInterface $input, OutputInterface $output)
{
// init repos
$composer = $this->getComposer();
@@ -106,7 +107,7 @@ private function doExecute(InputInterface $input)
// list packages
foreach ($installedRepo->getCanonicalPackages() as $package) {
- $downloader = $dm->getDownloaderForPackage($package);
+ $downloader = $dm->getDownloaderForInstalledPackage($package);
$targetDir = $im->getInstallPath($package);
if ($downloader instanceof ChangeReportInterface) {
@@ -120,7 +121,7 @@ private function doExecute(InputInterface $input)
}
if ($downloader instanceof VcsCapableDownloaderInterface) {
- if ($downloader->getVcsReference($package, $targetDir)) {
+ if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
switch ($package->getInstallationSource()) {
case 'source':
$previousRef = $package->getSourceReference();
diff --git a/app/vendor/composer/composer/src/Composer/Command/SuggestsCommand.php b/app/vendor/composer/composer/src/Composer/Command/SuggestsCommand.php
index cb1f4e9a6..0769f62f9 100644
--- a/app/vendor/composer/composer/src/Composer/Command/SuggestsCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/SuggestsCommand.php
@@ -13,9 +13,6 @@
namespace Composer\Command;
use Composer\Repository\PlatformRepository;
-use Composer\Repository\RootPackageRepository;
-use Composer\Repository\InstalledRepository;
-use Composer\Installer\SuggestedPackagesReporter;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -29,10 +26,8 @@ protected function configure()
->setName('suggests')
->setDescription('Shows package suggestions.')
->setDefinition(array(
- new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package (default)'),
+ new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
- new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show suggestions from all dependencies, including transitive ones'),
- new InputOption('list', null, InputOption::VALUE_NONE, 'Show only list of suggested package names'),
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
))
@@ -41,63 +36,118 @@ protected function configure()
The %command.name% command shows a sorted list of suggested packages.
+Enabling -v implies --by-package --by-suggestion , showing both lists.
+
Read more at https://getcomposer.org/doc/03-cli.md#suggests
EOT
)
;
}
- /**
- * {@inheritDoc}
- */
protected function execute(InputInterface $input, OutputInterface $output)
{
- $composer = $this->getComposer();
-
- $installedRepos = array(
- new RootPackageRepository(clone $composer->getPackage()),
- );
-
- $locker = $composer->getLocker();
- if ($locker->isLocked()) {
- $installedRepos[] = new PlatformRepository(array(), $locker->getPlatformOverrides());
- $installedRepos[] = $locker->getLockedRepository(!$input->getOption('no-dev'));
- } else {
- $installedRepos[] = new PlatformRepository(array(), $composer->getConfig()->get('platform') ?: array());
- $installedRepos[] = $composer->getRepositoryManager()->getLocalRepository();
+ $lock = $this->getComposer()->getLocker()->getLockData();
+
+ if (empty($lock)) {
+ throw new \RuntimeException('Lockfile seems to be empty?');
}
- $installedRepo = new InstalledRepository($installedRepos);
- $reporter = new SuggestedPackagesReporter($this->getIO());
+ $packages = $lock['packages'];
+
+ if (!$input->getOption('no-dev')) {
+ $packages += $lock['packages-dev'];
+ }
$filter = $input->getArgument('packages');
- $packages = $installedRepo->getPackages();
- $packages[] = $composer->getPackage();
+
+ // First assemble lookup list of packages that are installed, replaced or provided
+ $installed = array();
foreach ($packages as $package) {
- if (!empty($filter) && !in_array($package->getName(), $filter)) {
- continue;
+ $installed[] = $package['name'];
+
+ if (!empty($package['provide'])) {
+ $installed = array_merge($installed, array_keys($package['provide']));
}
- $reporter->addSuggestionsFromPackage($package);
+ if (!empty($package['replace'])) {
+ $installed = array_merge($installed, array_keys($package['replace']));
+ }
}
- // Determine output mode, default is by-package
- $mode = SuggestedPackagesReporter::MODE_BY_PACKAGE;
+ // Undub and sort the install list into a sorted lookup array
+ $installed = array_flip($installed);
+ ksort($installed);
+
+ // Init platform repo
+ $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
- // if by-suggestion is given we override the default
+ // Next gather all suggestions that are not in that list
+ $suggesters = array();
+ $suggested = array();
+ foreach ($packages as $package) {
+ $packageName = $package['name'];
+ if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
+ continue;
+ }
+ foreach ($package['suggest'] as $suggestion => $reason) {
+ if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
+ continue;
+ }
+ if (!isset($installed[$suggestion])) {
+ $suggesters[$packageName][$suggestion] = $reason;
+ $suggested[$suggestion][$packageName] = $reason;
+ }
+ }
+ }
+ ksort($suggesters);
+ ksort($suggested);
+
+ // Determine output mode
+ $mode = 0;
+ $io = $this->getIO();
+ if ($input->getOption('by-package') || $io->isVerbose()) {
+ $mode |= 1;
+ }
if ($input->getOption('by-suggestion')) {
- $mode = SuggestedPackagesReporter::MODE_BY_SUGGESTION;
+ $mode |= 2;
}
- // unless by-package is also present then we enable both
- if ($input->getOption('by-package')) {
- $mode |= SuggestedPackagesReporter::MODE_BY_PACKAGE;
+
+ // Simple mode
+ if ($mode === 0) {
+ foreach (array_keys($suggested) as $suggestion) {
+ $io->write(sprintf('%s ', $suggestion));
+ }
+
+ return 0;
}
- // list is exclusive and overrides everything else
- if ($input->getOption('list')) {
- $mode = SuggestedPackagesReporter::MODE_LIST;
+
+ // Grouped by package
+ if ($mode & 1) {
+ foreach ($suggesters as $suggester => $suggestions) {
+ $io->write(sprintf('%s suggests:', $suggester));
+
+ foreach ($suggestions as $suggestion => $reason) {
+ $io->write(sprintf(' - %s : %s', $suggestion, $reason ?: '*'));
+ }
+ $io->write('');
+ }
}
- $reporter->output($mode, $installedRepo, empty($filter) && !$input->getOption('all') ? $composer->getPackage() : null);
+ // Grouped by suggestion
+ if ($mode & 2) {
+ // Improve readability in full mode
+ if ($mode & 1) {
+ $io->write(str_repeat('-', 78));
+ }
+ foreach ($suggested as $suggestion => $suggesters) {
+ $io->write(sprintf('%s is suggested by:', $suggestion));
+
+ foreach ($suggesters as $suggester => $reason) {
+ $io->write(sprintf(' - %s : %s', $suggester, $reason ?: '*'));
+ }
+ $io->write('');
+ }
+ }
return 0;
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/UpdateCommand.php b/app/vendor/composer/composer/src/Composer/Command/UpdateCommand.php
index 0fe582299..44f1e7dea 100644
--- a/app/vendor/composer/composer/src/Composer/Command/UpdateCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/UpdateCommand.php
@@ -13,16 +13,10 @@
namespace Composer\Command;
use Composer\Composer;
-use Composer\DependencyResolver\Request;
use Composer\Installer;
use Composer\IO\IOInterface;
-use Composer\Package\Loader\RootPackageLoader;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
-use Composer\Package\Version\VersionParser;
-use Composer\Util\HttpDownloader;
-use Composer\Semver\Constraint\MultiConstraint;
-use Composer\Package\Link;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -44,28 +38,24 @@ protected function configure()
->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
->setDefinition(array(
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
- new InputOption('with', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Temporary version constraint to add, e.g. foo/bar:1.0.0 or foo/bar=1.0.0'),
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
- new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'),
- new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).'),
+ new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
- new InputOption('dev', null, InputOption::VALUE_NONE, 'DEPRECATED: Enables installation of require-dev packages (enabled by default, only present for BC).'),
+ new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
- new InputOption('lock', null, InputOption::VALUE_NONE, 'Overwrites the lock file hash to suppress warning about the lock file being out of date without updating package versions. Package metadata like mirrors and URLs are updated if they changed.'),
- new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'),
+ new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
+ new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
- new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'),
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
- new InputOption('with-dependencies', 'w', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, except those which are root requirements.'),
- new InputOption('with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, including those which are root requirements.'),
+ new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
+ new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of allowed packages to the allow list, except those defined in root package.'),
+ new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of allowed packages to the allow list, including those defined in root package.'),
new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
- new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'),
- new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'),
- new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'),
+ new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
@@ -89,14 +79,6 @@ protected function configure()
php composer.phar update vendor/package1 foo/* [...]
-To run an update with more restrictive constraints you can use:
-
-php composer.phar update --with vendor/package:1.0.*
-
-To run a partial update with more restrictive constraints you can use the shorthand:
-
-php composer.phar update vendor/package:1.0.*
-
To select packages names interactively with auto-completion use -i .
Read more at https://getcomposer.org/doc/03-cli.md#update-u
@@ -108,93 +90,42 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = $this->getIO();
- if ($input->getOption('dev')) {
- $io->writeError('You are using the deprecated option "--dev". It has no effect and will break in Composer 3. ');
+ if ($input->getOption('no-custom-installers')) {
+ $io->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead. ');
+ $input->setOption('no-plugins', true);
}
- if ($input->getOption('no-suggest')) {
- $io->writeError('You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3. ');
+
+ if ($input->getOption('dev')) {
+ $io->writeError('You are using the deprecated option "dev". Dev packages are installed by default now. ');
}
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
- $composer->getEventDispatcher()->setRunScripts(!$input->getOption('no-scripts'));
-
- if (!HttpDownloader::isCurlEnabled()) {
- $io->writeError('Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled. ');
- }
$packages = $input->getArgument('packages');
- $reqs = $this->formatRequirements($input->getOption('with'));
-
- // extract --with shorthands from the allowlist
- if ($packages) {
- $allowlistPackagesWithRequirements = array_filter($packages, function ($pkg) {
- return preg_match('{\S+[ =:]\S+}', $pkg) > 0;
- });
- foreach ($this->formatRequirements($allowlistPackagesWithRequirements) as $package => $constraint) {
- $reqs[$package] = $constraint;
- }
-
- // replace the foo/bar:req by foo/bar in the allowlist
- foreach ($allowlistPackagesWithRequirements as $package) {
- $packageName = preg_replace('{^([^ =:]+)[ =:].*$}', '$1', $package);
- $index = array_search($package, $packages);
- $packages[$index] = $packageName;
- }
- }
-
- $rootPackage = $composer->getPackage();
- $rootRequires = $rootPackage->getRequires();
- $rootDevRequires = $rootPackage->getDevRequires();
- foreach ($reqs as $package => $constraint) {
- if (isset($rootRequires[$package])) {
- $rootRequires[$package] = $this->appendConstraintToLink($rootRequires[$package], $constraint);
- } elseif (isset($rootDevRequires[$package])) {
- $rootDevRequires[$package] = $this->appendConstraintToLink($rootDevRequires[$package], $constraint);
- } else {
- throw new \UnexpectedValueException('Only root package requirements can receive temporary constraints and '.$package.' is not one');
- }
- }
- $rootPackage->setRequires($rootRequires);
- $rootPackage->setDevRequires($rootDevRequires);
- $rootPackage->setReferences(RootPackageLoader::extractReferences($reqs, $rootPackage->getReferences()));
- $rootPackage->setStabilityFlags(RootPackageLoader::extractStabilityFlags($reqs, $rootPackage->getMinimumStability(), $rootPackage->getStabilityFlags()));
if ($input->getOption('interactive')) {
$packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
}
if ($input->getOption('root-reqs')) {
- $requires = array_keys($rootRequires);
+ $require = array_keys($composer->getPackage()->getRequires());
if (!$input->getOption('no-dev')) {
- $requires = array_merge($requires, array_keys($rootDevRequires));
+ $requireDev = array_keys($composer->getPackage()->getDevRequires());
+ $require = array_merge($require, $requireDev);
}
if (!empty($packages)) {
- $packages = array_intersect($packages, $requires);
+ $packages = array_intersect($packages, $require);
} else {
- $packages = $requires;
+ $packages = $require;
}
}
- // the arguments lock/nothing/mirrors are not package names but trigger a mirror update instead
- // they are further mutually exclusive with listing actual package names
- $filteredPackages = array_filter($packages, function ($package) {
- return !in_array($package, array('lock', 'nothing', 'mirrors'), true);
- });
- $updateMirrors = $input->getOption('lock') || count($filteredPackages) != count($packages);
- $packages = $filteredPackages;
-
- if ($updateMirrors && !empty($packages)) {
- $io->writeError('You cannot simultaneously update only a selection of packages and regenerate the lock file metadata. ');
-
- return -1;
- }
+ $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
- $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress'));
-
$install = Installer::create($io, $composer);
$config = $composer->getConfig();
@@ -202,17 +133,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
$authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
- $apcuPrefix = $input->getOption('apcu-autoloader-prefix');
- $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
-
- $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED;
- if ($input->getOption('with-all-dependencies')) {
- $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
- } elseif ($input->getOption('with-dependencies')) {
- $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
- }
-
- $ignorePlatformReqs = $input->getOption('ignore-platform-reqs') ?: ($input->getOption('ignore-platform-req') ?: false);
+ $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
$install
->setDryRun($input->getOption('dry-run'))
@@ -221,15 +142,16 @@ protected function execute(InputInterface $input, OutputInterface $output)
->setPreferDist($preferDist)
->setDevMode(!$input->getOption('no-dev'))
->setDumpAutoloader(!$input->getOption('no-autoloader'))
+ ->setRunScripts(!$input->getOption('no-scripts'))
+ ->setSkipSuggest($input->getOption('no-suggest'))
->setOptimizeAutoloader($optimize)
->setClassMapAuthoritative($authoritative)
- ->setApcuAutoloader($apcu, $apcuPrefix)
+ ->setApcuAutoloader($apcu)
->setUpdate(true)
- ->setInstall(!$input->getOption('no-install'))
- ->setUpdateMirrors($updateMirrors)
- ->setUpdateAllowList($packages)
- ->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)
- ->setIgnorePlatformRequirements($ignorePlatformReqs)
+ ->setUpdateAllowList($input->getOption('lock') ? array('lock') : $packages)
+ ->setAllowListTransitiveDependencies($input->getOption('with-dependencies'))
+ ->setAllowListAllDependencies($input->getOption('with-all-dependencies'))
+ ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
->setPreferStable($input->getOption('prefer-stable'))
->setPreferLowest($input->getOption('prefer-lowest'))
;
@@ -297,27 +219,10 @@ private function getPackagesInteractively(IOInterface $io, InputInterface $input
if ($io->askConfirmation(sprintf(
'Would you like to continue and update the above package%s [yes ]? ',
1 === count($packages) ? '' : 's'
- ))) {
+ ), true)) {
return $packages;
}
throw new \RuntimeException('Installation aborted.');
}
-
- private function appendConstraintToLink(Link $link, $constraint)
- {
- $parser = new VersionParser;
- $oldPrettyString = $link->getConstraint()->getPrettyString();
- $newConstraint = MultiConstraint::create(array($link->getConstraint(), $parser->parseConstraints($constraint)));
- $newConstraint->setPrettyString($oldPrettyString.', '.$constraint);
-
- return new Link(
- $link->getSource(),
- $link->getTarget(),
- $newConstraint,
- /** @phpstan-ignore-next-line */
- $link->getDescription(),
- $link->getPrettyConstraint() . ', ' . $constraint
- );
- }
}
diff --git a/app/vendor/composer/composer/src/Composer/Command/ValidateCommand.php b/app/vendor/composer/composer/src/Composer/Command/ValidateCommand.php
index fdb424423..6ab95ed1c 100644
--- a/app/vendor/composer/composer/src/Composer/Command/ValidateCommand.php
+++ b/app/vendor/composer/composer/src/Composer/Command/ValidateCommand.php
@@ -16,10 +16,7 @@
use Composer\Package\Loader\ValidatingArrayLoader;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
-use Composer\Repository\InstalledRepository;
-use Composer\Repository\PlatformRepository;
use Composer\Util\ConfigValidator;
-use Composer\Util\Filesystem;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -45,7 +42,6 @@ protected function configure()
new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not validate requires for overly strict/loose constraints'),
new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
- new InputOption('no-check-version', null, InputOption::VALUE_NONE, 'Do not report a warning if the version field is present'),
new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file'),
@@ -80,7 +76,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
return 3;
}
- if (!Filesystem::isReadable($file)) {
+ if (!is_readable($file)) {
$io->writeError('' . $file . ' is not readable. ');
return 3;
@@ -90,47 +86,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
$checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
$checkPublish = !$input->getOption('no-check-publish');
$checkLock = !$input->getOption('no-check-lock');
- $checkVersion = $input->getOption('no-check-version') ? 0 : ConfigValidator::CHECK_VERSION;
$isStrict = $input->getOption('strict');
- list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll, $checkVersion);
+ list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
$lockErrors = array();
$composer = Factory::create($io, $file, $input->hasParameterOption('--no-plugins'));
$locker = $composer->getLocker();
if ($locker->isLocked() && !$locker->isFresh()) {
- $lockErrors[] = '- The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update` or `composer update `.';
- }
-
- if ($locker->isLocked()) {
- $missingRequirements = false;
- $sets = array(
- array('repo' => $locker->getLockedRepository(false), 'method' => 'getRequires', 'description' => 'Required'),
- array('repo' => $locker->getLockedRepository(true), 'method' => 'getDevRequires', 'description' => 'Required (in require-dev)'),
- );
- foreach ($sets as $set) {
- $installedRepo = new InstalledRepository(array($set['repo']));
-
- foreach (call_user_func(array($composer->getPackage(), $set['method'])) as $link) {
- if (PlatformRepository::isPlatformPackage($link->getTarget())) {
- continue;
- }
- if (!$installedRepo->findPackagesWithReplacersAndProviders($link->getTarget(), $link->getConstraint())) {
- if ($results = $installedRepo->findPackagesWithReplacersAndProviders($link->getTarget())) {
- $provider = reset($results);
- $lockErrors[] = '- ' . $set['description'].' package "' . $link->getTarget() . '" is in the lock file as "'.$provider->getPrettyVersion().'" but that does not satisfy your constraint "'.$link->getPrettyConstraint().'".';
- } else {
- $lockErrors[] = '- ' . $set['description'].' package "' . $link->getTarget() . '" is not present in the lock file.';
- }
- $missingRequirements = true;
- }
- }
- }
-
- if ($missingRequirements) {
- $lockErrors[] = 'This usually happens when composer files are incorrectly merged or the composer.json file is manually edited.';
- $lockErrors[] = 'Read more about correctly resolving merge conflicts https://getcomposer.org/doc/articles/resolving-merge-conflicts.md';
- $lockErrors[] = 'and prefer using the "require" command over editing the composer.json file directly https://getcomposer.org/doc/03-cli.md#require';
- }
+ $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update` or `composer update `.';
}
$this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
@@ -144,7 +107,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$path = $composer->getInstallationManager()->getInstallPath($package);
$file = $path . '/composer.json';
if (is_dir($path) && file_exists($file)) {
- list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll, $checkVersion);
+ list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
$this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
@@ -157,8 +120,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
$eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
+ $exitCode = max($eventCode, $exitCode);
- return max($eventCode, $exitCode);
+ return $exitCode;
}
private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
@@ -168,62 +132,36 @@ private function outputResult($io, $name, &$errors, &$warnings, $checkPublish =
if ($errors) {
$io->writeError('' . $name . ' is invalid, the following errors/warnings were found: ');
} elseif ($publishErrors) {
- $io->writeError('' . $name . ' is valid for simple usage with Composer but has ');
- $io->writeError('strict errors that make it unable to be published as a package ');
+ $io->writeError('' . $name . ' is valid for simple usage with composer but has ');
+ $io->writeError('strict errors that make it unable to be published as a package: ');
$doPrintSchemaUrl = $printSchemaUrl;
} elseif ($warnings) {
$io->writeError('' . $name . ' is valid, but with a few warnings ');
$doPrintSchemaUrl = $printSchemaUrl;
- } elseif ($lockErrors) {
- $io->write('' . $name . ' is valid but your composer.lock has some '.($checkLock ? 'errors' : 'warnings').' ');
} else {
$io->write('' . $name . ' is valid ');
+ // if ($lockErrors) then they will be displayed below
}
if ($doPrintSchemaUrl) {
$io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema ');
}
- if ($errors) {
- $errors = array_map(function ($err) {
- return '- ' . $err;
- }, $errors);
- array_unshift($errors, '# General errors');
- }
- if ($warnings) {
- $warnings = array_map(function ($err) {
- return '- ' . $err;
- }, $warnings);
- array_unshift($warnings, '# General warnings');
- }
-
// Avoid setting the exit code to 1 in case --strict and --no-check-publish/--no-check-lock are combined
$extraWarnings = array();
// If checking publish errors, display them as errors, otherwise just show them as warnings
- if ($publishErrors) {
- $publishErrors = array_map(function ($err) {
- return '- ' . $err;
- }, $publishErrors);
-
- if ($checkPublish) {
- array_unshift($publishErrors, '# Publish errors');
- $errors = array_merge($errors, $publishErrors);
- } else {
- array_unshift($publishErrors, '# Publish warnings');
- $extraWarnings = array_merge($extraWarnings, $publishErrors);
- }
+ if ($checkPublish) {
+ $errors = array_merge($errors, $publishErrors);
+ } else {
+ $extraWarnings = array_merge($extraWarnings, $publishErrors);
}
// If checking lock errors, display them as errors, otherwise just show them as warnings
- if ($lockErrors) {
- if ($checkLock) {
- array_unshift($lockErrors, '# Lock file errors');
- $errors = array_merge($errors, $lockErrors);
- } else {
- array_unshift($lockErrors, '# Lock file warnings');
- $extraWarnings = array_merge($extraWarnings, $lockErrors);
- }
+ if ($checkLock) {
+ $errors = array_merge($errors, $lockErrors);
+ } else {
+ $extraWarnings = array_merge($extraWarnings, $lockErrors);
}
$messages = array(
@@ -233,11 +171,7 @@ private function outputResult($io, $name, &$errors, &$warnings, $checkPublish =
foreach ($messages as $style => $msgs) {
foreach ($msgs as $msg) {
- if (strpos($msg, '#') === 0) {
- $io->writeError('<' . $style . '>' . $msg . '' . $style . '>');
- } else {
- $io->writeError($msg);
- }
+ $io->writeError('<' . $style . '>' . $msg . '' . $style . '>');
}
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Compiler.php b/app/vendor/composer/composer/src/Composer/Compiler.php
index 8476a529f..651b2deb9 100644
--- a/app/vendor/composer/composer/src/Composer/Compiler.php
+++ b/app/vendor/composer/composer/src/Composer/Compiler.php
@@ -13,6 +13,7 @@
namespace Composer;
use Composer\Json\JsonFile;
+use Composer\Spdx\SpdxLicenses;
use Composer\CaBundle\CaBundle;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Process;
@@ -43,25 +44,13 @@ public function compile($pharFile = 'composer.phar')
unlink($pharFile);
}
- // TODO in v2.3 always call with an array
- if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
- $process = new Process(array('git', 'log', '--pretty="%H"', '-n1', 'HEAD'), __DIR__);
- } else {
- // @phpstan-ignore-next-line
- $process = new Process('git log --pretty="%H" -n1 HEAD', __DIR__);
- }
+ $process = new Process('git log --pretty="%H" -n1 HEAD', __DIR__);
if ($process->run() != 0) {
throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.');
}
$this->version = trim($process->getOutput());
- // TODO in v2.3 always call with an array
- if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
- $process = new Process(array('git', 'log', '-n1', '--pretty=%ci', 'HEAD'), __DIR__);
- } else {
- // @phpstan-ignore-next-line
- $process = new Process('git log -n1 --pretty=%ci HEAD', __DIR__);
- }
+ $process = new Process('git log -n1 --pretty=%ci HEAD', __DIR__);
if ($process->run() != 0) {
throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.');
}
@@ -69,13 +58,7 @@ public function compile($pharFile = 'composer.phar')
$this->versionDate = new \DateTime(trim($process->getOutput()));
$this->versionDate->setTimezone(new \DateTimeZone('UTC'));
- // TODO in v2.3 always call with an array
- if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
- $process = new Process(array('git', 'describe', '--tags', '--exact-match', 'HEAD'), __DIR__);
- } else {
- // @phpstan-ignore-next-line
- $process = new Process('git describe --tags --exact-match HEAD');
- }
+ $process = new Process('git describe --tags --exact-match HEAD');
if ($process->run() == 0) {
$this->version = trim($process->getOutput());
} else {
@@ -89,7 +72,7 @@ public function compile($pharFile = 'composer.phar')
}
$phar = new \Phar($pharFile, 0, 'composer.phar');
- $phar->setSignatureAlgorithm(\Phar::SHA512);
+ $phar->setSignatureAlgorithm(\Phar::SHA1);
$phar->startBuffering();
@@ -97,83 +80,72 @@ public function compile($pharFile = 'composer.phar')
return strcmp(strtr($a->getRealPath(), '\\', '/'), strtr($b->getRealPath(), '\\', '/'));
};
- // Add Composer sources
$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('*.php')
->notName('Compiler.php')
->notName('ClassLoader.php')
- ->notName('InstalledVersions.php')
->in(__DIR__.'/..')
->sort($finderSort)
;
+
foreach ($finder as $file) {
$this->addFile($phar, $file);
}
- // Add runtime utilities separately to make sure they retains the docblocks as these will get copied into projects
$this->addFile($phar, new \SplFileInfo(__DIR__ . '/Autoload/ClassLoader.php'), false);
- $this->addFile($phar, new \SplFileInfo(__DIR__ . '/InstalledVersions.php'), false);
- // Add Composer resources
$finder = new Finder();
$finder->files()
+ ->name('*.json')
->in(__DIR__.'/../../res')
+ ->in(SpdxLicenses::getResourcesDir())
->sort($finderSort)
;
+
foreach ($finder as $file) {
$this->addFile($phar, $file, false);
}
+ $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../../vendor/symfony/console/Resources/bin/hiddeninput.exe'), false);
+ $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../../vendor/symfony/polyfill-mbstring/Resources/mb_convert_variables.php8'), false);
- // Add vendor files
$finder = new Finder();
$finder->files()
->ignoreVCS(true)
- ->notPath('/\/(composer\.(json|lock)|[A-Z]+\.md|\.gitignore|appveyor.yml|phpunit\.xml\.dist|phpstan\.neon\.dist|phpstan-config\.neon)$/')
- ->notPath('/bin\/(jsonlint|validate-json|simple-phpunit)(\.bat)?$/')
- ->notPath('symfony/debug/Resources/ext/')
- ->notPath('justinrainbow/json-schema/demo/')
- ->notPath('justinrainbow/json-schema/dist/')
- ->notPath('composer/installed.json')
- ->notPath('composer/LICENSE')
+ ->name('*.php')
+ ->name('LICENSE')
->exclude('Tests')
->exclude('tests')
->exclude('docs')
- ->in(__DIR__.'/../../vendor/')
+ ->in(__DIR__.'/../../vendor/symfony/')
+ ->in(__DIR__.'/../../vendor/seld/jsonlint/')
+ ->in(__DIR__.'/../../vendor/justinrainbow/json-schema/')
+ ->in(__DIR__.'/../../vendor/composer/spdx-licenses/')
+ ->in(__DIR__.'/../../vendor/composer/semver/')
+ ->in(__DIR__.'/../../vendor/composer/ca-bundle/')
+ ->in(__DIR__.'/../../vendor/composer/xdebug-handler/')
+ ->in(__DIR__.'/../../vendor/psr/')
->sort($finderSort)
;
- $extraFiles = array(
- realpath(__DIR__ . '/../../vendor/composer/spdx-licenses/res/spdx-exceptions.json'),
- realpath(__DIR__ . '/../../vendor/composer/spdx-licenses/res/spdx-licenses.json'),
- realpath(CaBundle::getBundledCaBundlePath()),
- realpath(__DIR__ . '/../../vendor/symfony/console/Resources/bin/hiddeninput.exe'),
- realpath(__DIR__ . '/../../vendor/symfony/polyfill-mbstring/Resources/mb_convert_variables.php8'),
- );
- $unexpectedFiles = array();
-
foreach ($finder as $file) {
- if (in_array(realpath($file), $extraFiles, true)) {
- unset($extraFiles[array_search(realpath($file), $extraFiles, true)]);
- } elseif (!preg_match('{([/\\\\]LICENSE|\.php)$}', $file)) {
- $unexpectedFiles[] = (string) $file;
- }
-
- if (preg_match('{\.php[\d.]*$}', $file)) {
- $this->addFile($phar, $file);
- } else {
- $this->addFile($phar, $file, false);
- }
+ $this->addFile($phar, $file);
}
- if ($extraFiles) {
- throw new \RuntimeException('These files were expected but not added to the phar, they might be excluded or gone from the source package:'.PHP_EOL.implode(PHP_EOL, $extraFiles));
- }
- if ($unexpectedFiles) {
- throw new \RuntimeException('These files were unexpectedly added to the phar, make sure they are excluded or listed in $extraFiles:'.PHP_EOL.implode(PHP_EOL, $unexpectedFiles));
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/autoload.php'));
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_namespaces.php'));
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_psr4.php'));
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_classmap.php'));
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_files.php'));
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_real.php'));
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_static.php'));
+ if (file_exists(__DIR__.'/../../vendor/composer/include_paths.php')) {
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/include_paths.php'));
}
+ $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/ClassLoader.php'));
+
+ $this->addFile($phar, new \SplFileInfo(CaBundle::getBundledCaBundlePath()), false);
- // Add bin/composer
$this->addComposerBin($phar);
// Stubs
@@ -191,7 +163,7 @@ public function compile($pharFile = 'composer.phar')
// re-sign the phar with reproducible timestamp / signature
$util = new Timestamps($pharFile);
$util->updateTimestamps($this->versionDate);
- $util->save($pharFile, \Phar::SHA512);
+ $util->save($pharFile, \Phar::SHA1);
Linter::lint($pharFile);
}
@@ -222,14 +194,9 @@ private function addFile($phar, $file, $strip = true)
}
if ($path === 'src/Composer/Composer.php') {
- $content = strtr(
- $content,
- array(
- '@package_version@' => $this->version,
- '@package_branch_alias_version@' => $this->branchAliasVersion,
- '@release_date@' => $this->versionDate->format('Y-m-d H:i:s'),
- )
- );
+ $content = str_replace('@package_version@', $this->version, $content);
+ $content = str_replace('@package_branch_alias_version@', $this->branchAliasVersion, $content);
+ $content = str_replace('@release_date@', $this->versionDate->format('Y-m-d H:i:s'), $content);
$content = preg_replace('{SOURCE_VERSION = \'[^\']+\';}', 'SOURCE_VERSION = \'\';', $content);
}
@@ -302,11 +269,6 @@ private function getStub()
}
}
-if (!class_exists('Phar')) {
- echo 'PHP\'s phar extension is missing. Composer requires it to run. Enable the extension or recompile php without --disable-phar then try again.' . PHP_EOL;
- exit(1);
-}
-
Phar::mapPhar('composer.phar');
EOF;
diff --git a/app/vendor/composer/composer/src/Composer/Composer.php b/app/vendor/composer/composer/src/Composer/Composer.php
index 29136f995..4544d60ba 100644
--- a/app/vendor/composer/composer/src/Composer/Composer.php
+++ b/app/vendor/composer/composer/src/Composer/Composer.php
@@ -14,7 +14,6 @@
use Composer\Package\RootPackageInterface;
use Composer\Package\Locker;
-use Composer\Util\Loop;
use Composer\Repository\RepositoryManager;
use Composer\Installer\InstallationManager;
use Composer\Plugin\PluginManager;
@@ -51,9 +50,9 @@ class Composer
* const RELEASE_DATE = '@release_date@';
* const SOURCE_VERSION = '1.8-dev+source';
*/
- const VERSION = '2.1.8';
+ const VERSION = '1.10.22';
const BRANCH_ALIAS_VERSION = '';
- const RELEASE_DATE = '2021-09-15 13:55:14';
+ const RELEASE_DATE = '2021-04-27 13:10:45';
const SOURCE_VERSION = '';
/**
@@ -65,7 +64,7 @@ class Composer
*
* @var string
*/
- const RUNTIME_API_VERSION = '2.1.0';
+ const RUNTIME_API_VERSION = '1.0.0';
public static function getVersion()
{
@@ -83,19 +82,14 @@ public static function getVersion()
}
/**
- * @var RootPackageInterface
+ * @var Package\RootPackageInterface
*/
private $package;
/**
- * @var ?Locker
+ * @var Locker
*/
- private $locker = null;
-
- /**
- * @var Loop
- */
- private $loop;
+ private $locker;
/**
* @var Repository\RepositoryManager
@@ -138,7 +132,7 @@ public static function getVersion()
private $archiveManager;
/**
- * @param RootPackageInterface $package
+ * @param Package\RootPackageInterface $package
* @return void
*/
public function setPackage(RootPackageInterface $package)
@@ -147,7 +141,7 @@ public function setPackage(RootPackageInterface $package)
}
/**
- * @return RootPackageInterface
+ * @return Package\RootPackageInterface
*/
public function getPackage()
{
@@ -171,7 +165,7 @@ public function getConfig()
}
/**
- * @param Locker $locker
+ * @param Package\Locker $locker
*/
public function setLocker(Locker $locker)
{
@@ -179,7 +173,7 @@ public function setLocker(Locker $locker)
}
/**
- * @return ?Locker
+ * @return Package\Locker
*/
public function getLocker()
{
@@ -187,23 +181,7 @@ public function getLocker()
}
/**
- * @param Loop $loop
- */
- public function setLoop(Loop $loop)
- {
- $this->loop = $loop;
- }
-
- /**
- * @return Loop
- */
- public function getLoop()
- {
- return $this->loop;
- }
-
- /**
- * @param RepositoryManager $manager
+ * @param Repository\RepositoryManager $manager
*/
public function setRepositoryManager(RepositoryManager $manager)
{
@@ -211,7 +189,7 @@ public function setRepositoryManager(RepositoryManager $manager)
}
/**
- * @return RepositoryManager
+ * @return Repository\RepositoryManager
*/
public function getRepositoryManager()
{
@@ -219,7 +197,7 @@ public function getRepositoryManager()
}
/**
- * @param DownloadManager $manager
+ * @param Downloader\DownloadManager $manager
*/
public function setDownloadManager(DownloadManager $manager)
{
@@ -227,7 +205,7 @@ public function setDownloadManager(DownloadManager $manager)
}
/**
- * @return DownloadManager
+ * @return Downloader\DownloadManager
*/
public function getDownloadManager()
{
@@ -251,7 +229,7 @@ public function getArchiveManager()
}
/**
- * @param InstallationManager $manager
+ * @param Installer\InstallationManager $manager
*/
public function setInstallationManager(InstallationManager $manager)
{
@@ -259,7 +237,7 @@ public function setInstallationManager(InstallationManager $manager)
}
/**
- * @return InstallationManager
+ * @return Installer\InstallationManager
*/
public function getInstallationManager()
{
@@ -267,7 +245,7 @@ public function getInstallationManager()
}
/**
- * @param PluginManager $manager
+ * @param Plugin\PluginManager $manager
*/
public function setPluginManager(PluginManager $manager)
{
@@ -275,7 +253,7 @@ public function setPluginManager(PluginManager $manager)
}
/**
- * @return PluginManager
+ * @return Plugin\PluginManager
*/
public function getPluginManager()
{
@@ -299,7 +277,7 @@ public function getEventDispatcher()
}
/**
- * @param AutoloadGenerator $autoloadGenerator
+ * @param Autoload\AutoloadGenerator $autoloadGenerator
*/
public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
{
@@ -307,7 +285,7 @@ public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
}
/**
- * @return AutoloadGenerator
+ * @return Autoload\AutoloadGenerator
*/
public function getAutoloadGenerator()
{
diff --git a/app/vendor/composer/composer/src/Composer/Config.php b/app/vendor/composer/composer/src/Composer/Config.php
index 4cb7ab8ae..b305fe371 100644
--- a/app/vendor/composer/composer/src/Composer/Config.php
+++ b/app/vendor/composer/composer/src/Composer/Config.php
@@ -28,10 +28,9 @@ class Config
public static $defaultConfig = array(
'process-timeout' => 300,
'use-include-path' => false,
- 'preferred-install' => 'dist',
+ 'preferred-install' => 'auto',
'notify-on-install' => true,
'github-protocols' => array('https', 'ssh', 'git'),
- 'gitlab-protocol' => null,
'vendor-dir' => 'vendor',
'bin-dir' => '{$vendor-dir}/bin',
'cache-dir' => '{$home}/cache',
@@ -42,7 +41,6 @@ class Config
'cache-ttl' => 15552000, // 6 months
'cache-files-ttl' => null, // fallback to cache-ttl
'cache-files-maxsize' => '300MiB',
- 'cache-read-only' => false,
'bin-compat' => 'auto',
'discard-changes' => false,
'autoloader-suffix' => null,
@@ -55,7 +53,6 @@ class Config
'bitbucket-expose-hostname' => true,
'disable-tls' => false,
'secure-http' => true,
- 'secure-svn-domains' => array(),
'cafile' => null,
'capath' => null,
'github-expose-hostname' => true,
@@ -67,7 +64,6 @@ class Config
'htaccess-protect' => true,
'use-github-api' => true,
'lock' => true,
- 'platform-check' => 'php-only',
// valid keys without defaults (auth config stuff):
// bitbucket-oauth
// github-oauth
@@ -80,7 +76,8 @@ class Config
public static $defaultRepositories = array(
'packagist.org' => array(
'type' => 'composer',
- 'url' => 'https://repo.packagist.org',
+ 'url' => 'https?://repo.packagist.org',
+ 'allow_ssl_downgrade' => true,
),
);
@@ -139,8 +136,6 @@ public function merge($config)
foreach ($config['config'] as $key => $val) {
if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic', 'bearer')) && isset($this->config[$key])) {
$this->config[$key] = array_merge($this->config[$key], $val);
- } elseif (in_array($key, array('gitlab-domains', 'github-domains')) && isset($this->config[$key])) {
- $this->config[$key] = array_unique(array_merge($this->config[$key], $val));
} elseif ('preferred-install' === $key && isset($this->config[$key])) {
if (is_array($val) || is_array($this->config[$key])) {
if (is_string($val)) {
@@ -181,11 +176,6 @@ public function merge($config)
continue;
}
- // auto-deactivate the default packagist.org repo if it gets redefined
- if (isset($repository['type'], $repository['url']) && $repository['type'] === 'composer' && preg_match('{^https?://(?:[a-z0-9-.]+\.)?packagist.org(/|$)}', $repository['url'])) {
- $this->disableRepoByName('packagist.org');
- }
-
// store repo
if (is_int($name)) {
$this->repositories[] = $repository;
@@ -220,7 +210,6 @@ public function getRepositories()
public function get($key, $flags = 0)
{
switch ($key) {
- // strings/paths with env var and {$refs} support
case 'vendor-dir':
case 'bin-dir':
case 'process-timeout':
@@ -244,40 +233,20 @@ public function get($key, $flags = 0)
return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
- // booleans with env var support
- case 'cache-read-only':
case 'htaccess-protect':
- // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config
- $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
-
- $val = $this->getComposerEnv($env);
- if (false === $val) {
- $val = $this->config[$key];
- }
-
- return $val !== 'false' && (bool) $val;
-
- // booleans without env var support
- case 'disable-tls':
- case 'secure-http':
- case 'use-github-api':
- case 'lock':
- // special case for secure-http
- if ($key === 'secure-http' && $this->get('disable-tls') === true) {
- return false;
+ $value = $this->getComposerEnv('COMPOSER_HTACCESS_PROTECT');
+ if (false === $value) {
+ $value = $this->config[$key];
}
+ return $value !== 'false' && (bool) $value;
- return $this->config[$key] !== 'false' && (bool) $this->config[$key];
-
- // ints without env var support
case 'cache-ttl':
return (int) $this->config[$key];
- // numbers with kb/mb/gb support, without env var support
case 'cache-files-maxsize':
if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
throw new \RuntimeException(
- "Could not parse the value of '$key': {$this->config[$key]}"
+ "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
);
}
$size = $matches[1];
@@ -299,7 +268,6 @@ public function get($key, $flags = 0)
return $size;
- // special cases below
case 'cache-files-ttl':
if (isset($this->config[$key])) {
return (int) $this->config[$key];
@@ -315,9 +283,9 @@ public function get($key, $flags = 0)
case 'bin-compat':
$value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
- if (!in_array($value, array('auto', 'full', 'symlink'))) {
+ if (!in_array($value, array('auto', 'full'))) {
throw new \RuntimeException(
- "Invalid value for 'bin-compat': {$value}. Expected auto, full or symlink"
+ "Invalid value for 'bin-compat': {$value}. Expected auto, full"
);
}
@@ -357,6 +325,18 @@ public function get($key, $flags = 0)
return $protos;
+ case 'disable-tls':
+ return $this->config[$key] !== 'false' && (bool) $this->config[$key];
+ case 'secure-http':
+ if ($this->get('disable-tls') === true) {
+ return false;
+ }
+
+ return $this->config[$key] !== 'false' && (bool) $this->config[$key];
+ case 'use-github-api':
+ return $this->config[$key] !== 'false' && (bool) $this->config[$key];
+ case 'lock':
+ return $this->config[$key] !== 'false' && (bool) $this->config[$key];
default:
if (!isset($this->config[$key])) {
return null;
@@ -476,20 +456,10 @@ public function prohibitUrlByConfig($url, IOInterface $io = null)
// Extract scheme and throw exception on known insecure protocols
$scheme = parse_url($url, PHP_URL_SCHEME);
- $hostname = parse_url($url, PHP_URL_HOST);
if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
if ($this->get('secure-http')) {
- if ($scheme === 'svn') {
- if (in_array($hostname, $this->get('secure-svn-domains'), true)) {
- return;
- }
-
- throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-svn-domains for details.");
- }
-
throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
- }
- if ($io) {
+ } elseif ($io) {
$host = parse_url($url, PHP_URL_HOST);
if (!isset($this->warnedHosts[$host])) {
$io->writeError("Warning: Accessing $host over $scheme which is an insecure protocol. ");
diff --git a/app/vendor/composer/composer/src/Composer/Config/ConfigSourceInterface.php b/app/vendor/composer/composer/src/Composer/Config/ConfigSourceInterface.php
index e1ef38de0..a00e989bb 100644
--- a/app/vendor/composer/composer/src/Composer/Config/ConfigSourceInterface.php
+++ b/app/vendor/composer/composer/src/Composer/Config/ConfigSourceInterface.php
@@ -23,10 +23,10 @@ interface ConfigSourceInterface
/**
* Add a repository
*
- * @param string $name Name
- * @param array|false $config Configuration
+ * @param string $name Name
+ * @param array $config Configuration
*/
- public function addRepository($name, $config, $append = true);
+ public function addRepository($name, $config);
/**
* Remove a repository
@@ -38,7 +38,7 @@ public function removeRepository($name);
/**
* Add a config setting
*
- * @param string $name Name
+ * @param string $name Name
* @param string|array $value Value
*/
public function addConfigSetting($name, $value);
diff --git a/app/vendor/composer/composer/src/Composer/Config/JsonConfigSource.php b/app/vendor/composer/composer/src/Composer/Config/JsonConfigSource.php
index 4be155782..6084d66e8 100644
--- a/app/vendor/composer/composer/src/Composer/Config/JsonConfigSource.php
+++ b/app/vendor/composer/composer/src/Composer/Config/JsonConfigSource.php
@@ -14,8 +14,6 @@
use Composer\Json\JsonFile;
use Composer\Json\JsonManipulator;
-use Composer\Json\JsonValidationException;
-use Composer\Util\Filesystem;
use Composer\Util\Silencer;
/**
@@ -59,9 +57,9 @@ public function getName()
/**
* {@inheritdoc}
*/
- public function addRepository($name, $config, $append = true)
+ public function addRepository($name, $config)
{
- $this->manipulateJson('addRepository', $name, $config, $append, function (&$config, $repo, $repoConfig) use ($append) {
+ $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
// if converting from an array format to hashmap format, and there is a {"packagist.org":false} repo, we have
// to convert it to "packagist.org": false key on the hashmap otherwise it fails schema validation
if (isset($config['repositories'])) {
@@ -77,11 +75,7 @@ public function addRepository($name, $config, $append = true)
}
}
- if ($append) {
- $config['repositories'][$repo] = $repoConfig;
- } else {
- $config['repositories'] = array($repo => $repoConfig) + $config['repositories'];
- }
+ $config['repositories'][$repo] = $repoConfig;
});
}
@@ -141,7 +135,7 @@ public function removeConfigSetting($name)
public function addProperty($name, $value)
{
$this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
- if (strpos($key, 'extra.') === 0 || strpos($key, 'scripts.') === 0) {
+ if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
$bits = explode('.', $key);
$last = array_pop($bits);
$arr = &$config[reset($bits)];
@@ -163,8 +157,9 @@ public function addProperty($name, $value)
*/
public function removeProperty($name)
{
+ $authConfig = $this->authConfig;
$this->manipulateJson('removeProperty', $name, function (&$config, $key) {
- if (strpos($key, 'extra.') === 0 || strpos($key, 'scripts.') === 0) {
+ if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
$bits = explode('.', $key);
$last = array_pop($bits);
$arr = &$config[reset($bits)];
@@ -198,8 +193,7 @@ public function removeLink($type, $name)
{
$this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
unset($config[$type][$name]);
- });
- $this->manipulateJson('removeMainKeyIfEmpty', $type, function (&$config, $type) {
+
if (0 === count($config[$type])) {
unset($config[$type]);
}
@@ -218,7 +212,7 @@ protected function manipulateJson($method, $args, $fallback)
throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
}
- if (!Filesystem::isReadable($this->file->getPath())) {
+ if (!is_readable($this->file->getPath())) {
throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
}
@@ -253,35 +247,14 @@ protected function manipulateJson($method, $args, $fallback)
$this->arrayUnshiftRef($args, $config);
call_user_func_array($fallback, $args);
// avoid ending up with arrays for keys that should be objects
- foreach (array('require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev', 'scripts', 'scripts-descriptions', 'support') as $prop) {
- if (isset($config[$prop]) && $config[$prop] === array()) {
- $config[$prop] = new \stdClass;
- }
- }
- foreach (array('psr-0', 'psr-4') as $prop) {
- if (isset($config['autoload'][$prop]) && $config['autoload'][$prop] === array()) {
- $config['autoload'][$prop] = new \stdClass;
- }
- if (isset($config['autoload-dev'][$prop]) && $config['autoload-dev'][$prop] === array()) {
- $config['autoload-dev'][$prop] = new \stdClass;
- }
- }
- foreach (array('platform', 'http-basic', 'bearer', 'gitlab-token', 'gitlab-oauth', 'github-oauth', 'preferred-install') as $prop) {
- if (isset($config['config'][$prop]) && $config['config'][$prop] === array()) {
- $config['config'][$prop] = new \stdClass;
+ foreach (array('require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev') as $linkType) {
+ if (isset($config[$linkType]) && $config[$linkType] === array()) {
+ $config[$linkType] = new \stdClass;
}
}
$this->file->write($config);
}
- try {
- $this->file->validateSchema(JsonFile::LAX_SCHEMA);
- } catch (JsonValidationException $e) {
- // restore contents to the original state
- file_put_contents($this->file->getPath(), $contents);
- throw new \RuntimeException('Failed to update composer.json with a valid format, reverting to the original content. Please report an issue to us with details (command you run and a copy of your composer.json).', 0, $e);
- }
-
if ($newFile) {
Silencer::call('chmod', $this->file->getPath(), 0600);
}
@@ -292,7 +265,7 @@ protected function manipulateJson($method, $args, $fallback)
*
* @param array $array
* @param mixed $value
- * @return int
+ * @return array
*/
private function arrayUnshiftRef(&$array, &$value)
{
diff --git a/app/vendor/composer/composer/src/Composer/Console/Application.php b/app/vendor/composer/composer/src/Composer/Console/Application.php
index bdc9b2a32..bc1cf0993 100644
--- a/app/vendor/composer/composer/src/Composer/Console/Application.php
+++ b/app/vendor/composer/composer/src/Composer/Console/Application.php
@@ -13,7 +13,6 @@
namespace Composer\Console;
use Composer\IO\NullIO;
-use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\Silencer;
use Symfony\Component\Console\Application as BaseApplication;
@@ -23,7 +22,6 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
-use Seld\JsonLint\ParsingException;
use Composer\Command;
use Composer\Composer;
use Composer\Factory;
@@ -31,11 +29,8 @@
use Composer\IO\ConsoleIO;
use Composer\Json\JsonValidationException;
use Composer\Util\ErrorHandler;
-use Composer\Util\HttpDownloader;
use Composer\EventDispatcher\ScriptExecutionException;
use Composer\Exception\NoSslException;
-use Composer\XdebugHandler\XdebugHandler;
-use Symfony\Component\Process\Exception\ProcessTimedOutException;
/**
* The console application that handles the commands
@@ -47,7 +42,7 @@
class Application extends BaseApplication
{
/**
- * @var ?Composer
+ * @var Composer
*/
protected $composer;
@@ -56,7 +51,6 @@ class Application extends BaseApplication
*/
protected $io;
- /** @var string */
private static $logo = ' ______
/ ____/___ ____ ___ ____ ____ ________ _____
/ / / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
@@ -65,23 +59,21 @@ class Application extends BaseApplication
/_/
';
- /** @var bool */
private $hasPluginCommands = false;
- /** @var bool */
private $disablePluginsByDefault = false;
/**
* @var string Store the initial working directory at startup time
*/
- private $initialWorkingDirectory;
+ private $initialWorkingDirectory = '';
public function __construct()
{
static $shutdownRegistered = false;
if (function_exists('ini_set') && extension_loaded('xdebug')) {
- ini_set('xdebug.show_exception_trace', '0');
- ini_set('xdebug.scream', '0');
+ ini_set('xdebug.show_exception_trace', false);
+ ini_set('xdebug.scream', false);
}
if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
@@ -89,13 +81,6 @@ public function __construct()
}
if (!$shutdownRegistered) {
- if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
- pcntl_async_signals(true);
- pcntl_signal(SIGINT, function ($sig) {
- exit(130);
- });
- }
-
$shutdownRegistered = true;
register_shutdown_function(function () {
@@ -135,20 +120,19 @@ public function doRun(InputInterface $input, OutputInterface $output)
{
$this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
- if (getenv('COMPOSER_NO_INTERACTION') || !Platform::isTty(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'))) {
+ if (getenv('COMPOSER_NO_INTERACTION')) {
$input->setInteractive(false);
}
$io = $this->io = new ConsoleIO($input, $output, new HelperSet(array(
new QuestionHelper(),
)));
-
- // Register error handler again to pass it the IO instance
ErrorHandler::register($io);
if ($input->hasParameterOption('--no-cache')) {
$io->writeError('Disabling cache usage', true, IOInterface::DEBUG);
- Platform::putEnv('COMPOSER_CACHE_DIR', Platform::isWindows() ? 'nul' : '/dev/null');
+ $_SERVER['COMPOSER_CACHE_DIR'] = Platform::isWindows() ? 'nul' : '/dev/null';
+ putenv('COMPOSER_CACHE_DIR='.$_SERVER['COMPOSER_CACHE_DIR']);
}
// switch working dir
@@ -165,8 +149,8 @@ public function doRun(InputInterface $input, OutputInterface $output)
try {
$commandName = $this->find($name)->getName();
} catch (CommandNotFoundException $e) {
- // we'll check command validity again later after plugins are loaded
- $commandName = false;
+ // we'll check command validity again later after plugins are loaded
+ $commandName = false;
} catch (\InvalidArgumentException $e) {
}
}
@@ -179,7 +163,7 @@ public function doRun(InputInterface $input, OutputInterface $output)
// abort when we reach the home dir or top of the filesystem
while (dirname($dir) !== $dir && $dir !== $home) {
if (file_exists($dir.'/'.Factory::getComposerFile())) {
- if ($io->askConfirmation('No composer.json in current directory, do you want to use the one at '.$dir.'? [Y,n ]? ')) {
+ if ($io->askConfirmation('No composer.json in current directory, do you want to use the one at '.$dir.'? [Y,n ]? ', true)) {
$oldWorkingDir = getcwd();
chdir($dir);
}
@@ -189,17 +173,7 @@ public function doRun(InputInterface $input, OutputInterface $output)
}
}
- // avoid loading plugins/initializing the Composer instance earlier than necessary if no plugin command is needed
- // if showing the version, we never need plugin commands
- $mayNeedPluginCommand = false === $input->hasParameterOption(array('--version', '-V'))
- && (
- // not a composer command, so try loading plugin ones
- false === $commandName
- // list command requires plugin commands to show them
- || in_array($commandName, array('', 'list'), true)
- );
-
- if ($mayNeedPluginCommand && !$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
+ if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
try {
foreach ($this->getPluginCommands() as $command) {
if ($this->has($command->getName())) {
@@ -210,20 +184,6 @@ public function doRun(InputInterface $input, OutputInterface $output)
}
} catch (NoSslException $e) {
// suppress these as they are not relevant at this point
- } catch (ParsingException $e) {
- $details = $e->getDetails();
-
- $file = realpath(Factory::getComposerFile());
-
- $line = null;
- if ($details && isset($details['line'])) {
- $line = $details['line'];
- }
-
- $ghe = new GithubActionError($this->io);
- $ghe->emit($e->getMessage(), $file, $line);
-
- throw $e;
}
$this->hasPluginCommands = true;
@@ -253,12 +213,12 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
$io->writeError('Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended. ');
}
- if (XdebugHandler::isXdebugActive() && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
- $io->writeError('Composer is operating slower than normal because you have Xdebug enabled. See https://getcomposer.org/xdebug ');
+ if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
+ $io->writeError('You are running composer with Xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug ');
}
if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
- $io->writeError(sprintf('Warning: This development build of Composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version. ', $_SERVER['PHP_SELF']));
+ $io->writeError(sprintf('Warning: This development build of composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version. ', $_SERVER['PHP_SELF']));
}
if (
@@ -270,12 +230,6 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
if (function_exists('posix_getuid') && posix_getuid() === 0) {
if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
$io->writeError('Do not run Composer as root/super user! See https://getcomposer.org/root for details ');
-
- if ($io->isInteractive()) {
- if (!$io->askConfirmation('Continue as root/super user [yes ]? ')) {
- return 1;
- }
- }
}
if ($uid = (int) getenv('SUDO_UID')) {
// Silently clobber any sudo credentials on the invoking user to avoid privilege escalations later on
@@ -297,7 +251,7 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
// add non-standard scripts as own commands
$file = Factory::getComposerFile();
- if (is_file($file) && Filesystem::isReadable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
+ if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
if (isset($composer['scripts']) && is_array($composer['scripts'])) {
foreach ($composer['scripts'] as $script => $dummy) {
if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
@@ -326,9 +280,8 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
$result = parent::doRun($input, $output);
- // chdir back to $oldWorkingDir if set
if (isset($oldWorkingDir)) {
- Silencer::call('chdir', $oldWorkingDir);
+ chdir($oldWorkingDir);
}
if (isset($startTime)) {
@@ -339,15 +292,10 @@ function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknow
return $result;
} catch (ScriptExecutionException $e) {
- return (int) $e->getCode();
+ return $e->getCode();
} catch (\Exception $e) {
- $ghe = new GithubActionError($this->io);
- $ghe->emit($e->getMessage());
-
$this->hintCommonErrors($e);
-
restore_error_handler();
-
throw $e;
}
}
@@ -401,25 +349,13 @@ private function hintCommonErrors($exception)
$io->writeError('The following exception is caused by a lack of memory or swap, or not having swap configured ', true, IOInterface::QUIET);
$io->writeError('Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details ', true, IOInterface::QUIET);
}
-
- if ($exception instanceof ProcessTimedOutException) {
- $io->writeError('The following exception is caused by a process timeout ', true, IOInterface::QUIET);
- $io->writeError('Check https://getcomposer.org/doc/06-config.md#process-timeout for details ', true, IOInterface::QUIET);
- }
-
- if ($hints = HttpDownloader::getExceptionHints($exception)) {
- foreach ($hints as $hint) {
- $io->writeError($hint, true, IOInterface::QUIET);
- }
- }
}
/**
* @param bool $required
* @param bool|null $disablePlugins
* @throws JsonValidationException
- * @throws \InvalidArgumentException
- * @return ?\Composer\Composer If $required is true then the return value is guaranteed
+ * @return \Composer\Composer
*/
public function getComposer($required = true, $disablePlugins = null)
{
@@ -433,16 +369,12 @@ public function getComposer($required = true, $disablePlugins = null)
} catch (\InvalidArgumentException $e) {
if ($required) {
$this->io->writeError($e->getMessage());
- // TODO composer 2.3 simplify to $this->areExceptionsCaught()
- if (!method_exists($this, 'areExceptionsCaught') || $this->areExceptionsCaught()) {
- exit(1);
- }
- throw $e;
+ exit(1);
}
} catch (JsonValidationException $e) {
- if ($required) {
- throw $e;
- }
+ $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
+ $message = $e->getMessage() . ':' . PHP_EOL . $errors;
+ throw new JsonValidationException($message);
}
}
@@ -455,7 +387,7 @@ public function getComposer($required = true, $disablePlugins = null)
public function resetComposer()
{
$this->composer = null;
- if (method_exists($this->getIO(), 'resetAuthentications')) {
+ if ($this->getIO() && method_exists($this->getIO(), 'resetAuthentications')) {
$this->getIO()->resetAuthentications();
}
}
@@ -506,10 +438,9 @@ protected function getDefaultCommands()
new Command\OutdatedCommand(),
new Command\CheckPlatformReqsCommand(),
new Command\FundCommand(),
- new Command\ReinstallCommand(),
));
- if (strpos(__FILE__, 'phar:') === 0) {
+ if ('phar:' === substr(__FILE__, 0, 5)) {
$commands[] = new Command\SelfUpdateCommand();
}
@@ -554,7 +485,7 @@ private function getPluginCommands()
$composer = $this->getComposer(false, false);
if (null === $composer) {
- $composer = Factory::createGlobal($this->io);
+ $composer = Factory::createGlobal($this->io, false);
}
if (null !== $composer) {
@@ -577,7 +508,7 @@ private function getPluginCommands()
}
/**
- * Get the working directory at startup time
+ * Get the working directoy at startup time
*
* @return string
*/
diff --git a/app/vendor/composer/composer/src/Composer/Console/GithubActionError.php b/app/vendor/composer/composer/src/Composer/Console/GithubActionError.php
deleted file mode 100644
index c862dd9be..000000000
--- a/app/vendor/composer/composer/src/Composer/Console/GithubActionError.php
+++ /dev/null
@@ -1,50 +0,0 @@
-
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\Console;
-
-use Composer\IO\IOInterface;
-
-final class GithubActionError
-{
- /**
- * @var IOInterface
- */
- protected $io;
-
- public function __construct(IOInterface $io)
- {
- $this->io = $io;
- }
-
- /**
- * @param string $message
- * @param null|string $file
- * @param null|int $line
- */
- public function emit($message, $file = null, $line = null)
- {
- if (getenv('GITHUB_ACTIONS') && !getenv('COMPOSER_TESTS_ARE_RUNNING')) {
- // newlines need to be encoded
- // see https://github.com/actions/starter-workflows/issues/68#issuecomment-581479448
- $message = str_replace("\n", '%0A', $message);
-
- if ($file && $line) {
- $this->io->write("::error file=". $file .",line=". $line ."::". $message);
- } elseif ($file) {
- $this->io->write("::error file=". $file ."::". $message);
- } else {
- $this->io->write("::error ::". $message);
- }
- }
- }
-}
diff --git a/app/vendor/composer/composer/src/Composer/Console/HtmlOutputFormatter.php b/app/vendor/composer/composer/src/Composer/Console/HtmlOutputFormatter.php
index acef97325..994fcbcd5 100644
--- a/app/vendor/composer/composer/src/Composer/Console/HtmlOutputFormatter.php
+++ b/app/vendor/composer/composer/src/Composer/Console/HtmlOutputFormatter.php
@@ -19,7 +19,6 @@
*/
class HtmlOutputFormatter extends OutputFormatter
{
- /** @var array */
private static $availableForegroundColors = array(
30 => 'black',
31 => 'red',
@@ -30,7 +29,6 @@ class HtmlOutputFormatter extends OutputFormatter
36 => 'cyan',
37 => 'white',
);
- /** @var array */
private static $availableBackgroundColors = array(
40 => 'black',
41 => 'red',
@@ -41,7 +39,6 @@ class HtmlOutputFormatter extends OutputFormatter
46 => 'cyan',
47 => 'white',
);
- /** @var array */
private static $availableOptions = array(
1 => 'bold',
4 => 'underscore',
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php
index 799a0a1fa..e2773501f 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Decisions.php
@@ -16,21 +16,17 @@
* Stores decisions on installing, removing or keeping packages
*
* @author Nils Adermann
- * @implements \Iterator
*/
class Decisions implements \Iterator, \Countable
{
const DECISION_LITERAL = 0;
const DECISION_REASON = 1;
- /** @var Pool */
protected $pool;
- /** @var array */
protected $decisionMap;
- /** @var array */
protected $decisionQueue = array();
- public function __construct(Pool $pool)
+ public function __construct($pool)
{
$this->pool = $pool;
$this->decisionMap = array();
@@ -112,17 +108,17 @@ public function atOffset($queueOffset)
public function validOffset($queueOffset)
{
- return $queueOffset >= 0 && $queueOffset < \count($this->decisionQueue);
+ return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
}
public function lastReason()
{
- return $this->decisionQueue[\count($this->decisionQueue) - 1][self::DECISION_REASON];
+ return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
}
public function lastLiteral()
{
- return $this->decisionQueue[\count($this->decisionQueue) - 1][self::DECISION_LITERAL];
+ return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
}
public function reset()
@@ -134,7 +130,7 @@ public function reset()
public function resetToOffset($offset)
{
- while (\count($this->decisionQueue) > $offset + 1) {
+ while (count($this->decisionQueue) > $offset + 1) {
$decision = array_pop($this->decisionQueue);
$this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
}
@@ -146,37 +142,31 @@ public function revertLast()
array_pop($this->decisionQueue);
}
- #[\ReturnTypeWillChange]
public function count()
{
- return \count($this->decisionQueue);
+ return count($this->decisionQueue);
}
- #[\ReturnTypeWillChange]
public function rewind()
{
end($this->decisionQueue);
}
- #[\ReturnTypeWillChange]
public function current()
{
return current($this->decisionQueue);
}
- #[\ReturnTypeWillChange]
public function key()
{
return key($this->decisionQueue);
}
- #[\ReturnTypeWillChange]
public function next()
{
- prev($this->decisionQueue);
+ return prev($this->decisionQueue);
}
- #[\ReturnTypeWillChange]
public function valid()
{
return false !== current($this->decisionQueue);
@@ -184,7 +174,7 @@ public function valid()
public function isEmpty()
{
- return \count($this->decisionQueue) === 0;
+ return count($this->decisionQueue) === 0;
}
protected function addDecision($literal, $level)
@@ -207,21 +197,15 @@ protected function addDecision($literal, $level)
}
}
- public function toString(Pool $pool = null)
+ public function __toString()
{
$decisionMap = $this->decisionMap;
ksort($decisionMap);
$str = '[';
foreach ($decisionMap as $packageId => $level) {
- $str .= (($pool) ? $pool->literalToPackage($packageId) : $packageId).':'.$level.',';
+ $str .= $packageId.':'.$level.',';
}
$str .= ']';
-
return $str;
}
-
- public function __toString()
- {
- return $this->toString();
- }
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php
index 832a009e5..d7d386801 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php
@@ -12,9 +12,9 @@
namespace Composer\DependencyResolver;
+use Composer\Package\PackageInterface;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
-use Composer\Package\PackageInterface;
use Composer\Semver\Constraint\Constraint;
/**
@@ -23,9 +23,7 @@
*/
class DefaultPolicy implements PolicyInterface
{
- /** @var bool */
private $preferStable;
- /** @var bool */
private $preferLowest;
public function __construct($preferStable = false, $preferLowest = false)
@@ -46,33 +44,54 @@ public function versionCompare(PackageInterface $a, PackageInterface $b, $operat
return $constraint->matchSpecific($version, true);
}
- public function selectPreferredPackages(Pool $pool, array $literals, $requiredPackage = null)
+ public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
+ {
+ $packages = array();
+
+ foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
+ if ($candidate !== $package) {
+ $packages[] = $candidate;
+ }
+ }
+
+ return $packages;
+ }
+
+ public function getPriority(Pool $pool, PackageInterface $package)
+ {
+ return $pool->getPriority($package->getRepository());
+ }
+
+ public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
{
- $packages = $this->groupLiteralsByName($pool, $literals);
- $policy = $this;
+ $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
- foreach ($packages as &$nameLiterals) {
- usort($nameLiterals, function ($a, $b) use ($policy, $pool, $requiredPackage) {
- return $policy->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
+ foreach ($packages as &$literals) {
+ $policy = $this;
+ usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
+ return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
});
}
- foreach ($packages as &$sortedLiterals) {
- $sortedLiterals = $this->pruneToBestVersion($pool, $sortedLiterals);
- $sortedLiterals = $this->pruneRemoteAliases($pool, $sortedLiterals);
+ foreach ($packages as &$literals) {
+ $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
+
+ $literals = $this->pruneToBestVersion($pool, $literals);
+
+ $literals = $this->pruneRemoteAliases($pool, $literals);
}
- $selected = \call_user_func_array('array_merge', array_values($packages));
+ $selected = call_user_func_array('array_merge', array_values($packages));
// now sort the result across all packages to respect replaces across packages
- usort($selected, function ($a, $b) use ($policy, $pool, $requiredPackage) {
- return $policy->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
+ usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
+ return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
});
return $selected;
}
- protected function groupLiteralsByName(Pool $pool, $literals)
+ protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
{
$packages = array();
foreach ($literals as $literal) {
@@ -81,7 +100,12 @@ protected function groupLiteralsByName(Pool $pool, $literals)
if (!isset($packages[$packageName])) {
$packages[$packageName] = array();
}
- $packages[$packageName][] = $literal;
+
+ if (isset($installedMap[abs($literal)])) {
+ array_unshift($packages[$packageName], $literal);
+ } else {
+ $packages[$packageName][] = $literal;
+ }
}
return $packages;
@@ -90,49 +114,61 @@ protected function groupLiteralsByName(Pool $pool, $literals)
/**
* @protected
*/
- public function compareByPriority(Pool $pool, BasePackage $a, BasePackage $b, $requiredPackage = null, $ignoreReplace = false)
+ public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
{
- // prefer aliases to the original package
- if ($a->getName() === $b->getName()) {
- $aAliased = $a instanceof AliasPackage;
- $bAliased = $b instanceof AliasPackage;
- if ($aAliased && !$bAliased) {
- return -1; // use a
- }
- if (!$aAliased && $bAliased) {
- return 1; // use b
+ if ($a->getRepository() === $b->getRepository()) {
+ // prefer aliases to the original package
+ if ($a->getName() === $b->getName()) {
+ $aAliased = $a instanceof AliasPackage;
+ $bAliased = $b instanceof AliasPackage;
+ if ($aAliased && !$bAliased) {
+ return -1; // use a
+ }
+ if (!$aAliased && $bAliased) {
+ return 1; // use b
+ }
}
- }
- if (!$ignoreReplace) {
- // return original, not replaced
- if ($this->replaces($a, $b)) {
- return 1; // use b
- }
- if ($this->replaces($b, $a)) {
- return -1; // use a
- }
+ if (!$ignoreReplace) {
+ // return original, not replaced
+ if ($this->replaces($a, $b)) {
+ return 1; // use b
+ }
+ if ($this->replaces($b, $a)) {
+ return -1; // use a
+ }
- // for replacers not replacing each other, put a higher prio on replacing
- // packages with the same vendor as the required package
- if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
- $requiredVendor = substr($requiredPackage, 0, $pos);
+ // for replacers not replacing each other, put a higher prio on replacing
+ // packages with the same vendor as the required package
+ if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
+ $requiredVendor = substr($requiredPackage, 0, $pos);
- $aIsSameVendor = strpos($a->getName(), $requiredVendor) === 0;
- $bIsSameVendor = strpos($b->getName(), $requiredVendor) === 0;
+ $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
+ $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
- if ($bIsSameVendor !== $aIsSameVendor) {
- return $aIsSameVendor ? -1 : 1;
+ if ($bIsSameVendor !== $aIsSameVendor) {
+ return $aIsSameVendor ? -1 : 1;
+ }
}
}
+
+ // priority equal, sort by package id to make reproducible
+ if ($a->id === $b->id) {
+ return 0;
+ }
+
+ return ($a->id < $b->id) ? -1 : 1;
+ }
+
+ if (isset($installedMap[$a->id])) {
+ return -1;
}
- // priority equal, sort by package id to make reproducible
- if ($a->id === $b->id) {
- return 0;
+ if (isset($installedMap[$b->id])) {
+ return 1;
}
- return ($a->id < $b->id) ? -1 : 1;
+ return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
}
/**
@@ -141,11 +177,11 @@ public function compareByPriority(Pool $pool, BasePackage $a, BasePackage $b, $r
* Replace constraints are ignored. This method should only be used for
* prioritisation, not for actual constraint verification.
*
- * @param BasePackage $source
- * @param BasePackage $target
+ * @param PackageInterface $source
+ * @param PackageInterface $target
* @return bool
*/
- protected function replaces(BasePackage $source, BasePackage $target)
+ protected function replaces(PackageInterface $source, PackageInterface $target)
{
foreach ($source->getReplaces() as $link) {
if ($link->getTarget() === $target->getName()
@@ -182,6 +218,37 @@ protected function pruneToBestVersion(Pool $pool, $literals)
return $bestLiterals;
}
+ /**
+ * Assumes that installed packages come first and then all highest priority packages
+ */
+ protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
+ {
+ $selected = array();
+
+ $priority = null;
+
+ foreach ($literals as $literal) {
+ $package = $pool->literalToPackage($literal);
+
+ if (isset($installedMap[$package->id])) {
+ $selected[] = $literal;
+ continue;
+ }
+
+ if (null === $priority) {
+ $priority = $this->getPriority($pool, $package);
+ }
+
+ if ($this->getPriority($pool, $package) != $priority) {
+ break;
+ }
+
+ $selected[] = $literal;
+ }
+
+ return $selected;
+ }
+
/**
* Assumes that locally aliased (in root package requires) packages take priority over branch-alias ones
*
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php
index 61d95275f..df8a2a003 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php
@@ -12,24 +12,25 @@
namespace Composer\DependencyResolver;
-use Composer\Package\BasePackage;
+use Composer\Package\PackageInterface;
use Composer\Package\Link;
-use Composer\Semver\Constraint\ConstraintInterface;
/**
* @author Nils Adermann
*/
class GenericRule extends Rule
{
- /** @var int[] */
protected $literals;
/**
- * @param int[] $literals
+ * @param array $literals
+ * @param int $reason A RULE_* constant describing the reason for generating this rule
+ * @param Link|PackageInterface $reasonData
+ * @param array $job The job this rule was created from
*/
- public function __construct(array $literals, $reason, $reasonData)
+ public function __construct(array $literals, $reason, $reasonData, $job = null)
{
- parent::__construct($reason, $reasonData);
+ parent::__construct($reason, $reasonData, $job);
// sort all packages ascending by id
sort($literals);
@@ -64,7 +65,7 @@ public function equals(Rule $rule)
public function isAssertion()
{
- return 1 === \count($this->literals);
+ return 1 === count($this->literals);
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php
deleted file mode 100644
index daefc12b9..000000000
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php
+++ /dev/null
@@ -1,30 +0,0 @@
-
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\DependencyResolver;
-
-use Composer\Repository\RepositoryInterface;
-
-/**
- * @author Nils Adermann
- * @internal
- */
-class LocalRepoTransaction extends Transaction
-{
- public function __construct(RepositoryInterface $lockedRepository, $localRepository)
- {
- parent::__construct(
- $localRepository->getPackages(),
- $lockedRepository->getPackages()
- );
- }
-}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/LockTransaction.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/LockTransaction.php
deleted file mode 100644
index 3a3d94505..000000000
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/LockTransaction.php
+++ /dev/null
@@ -1,148 +0,0 @@
-
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\DependencyResolver;
-
-use Composer\Package\AliasPackage;
-use Composer\Package\BasePackage;
-use Composer\Package\Package;
-
-/**
- * @author Nils Adermann
- * @internal
- */
-class LockTransaction extends Transaction
-{
- /**
- * packages in current lock file, platform repo or otherwise present
- *
- * Indexed by spl_object_hash
- *
- * @var array
- */
- protected $presentMap;
-
- /**
- * Packages which cannot be mapped, platform repo, root package, other fixed repos
- *
- * Indexed by package id
- *
- * @var array
- */
- protected $unlockableMap;
-
- /**
- * @var array{dev: BasePackage[], non-dev: BasePackage[], all: BasePackage[]}
- */
- protected $resultPackages;
-
- /**
- * @param array $presentMap
- * @param array $unlockableMap
- */
- public function __construct(Pool $pool, array $presentMap, array $unlockableMap, Decisions $decisions)
- {
- $this->presentMap = $presentMap;
- $this->unlockableMap = $unlockableMap;
-
- $this->setResultPackages($pool, $decisions);
- parent::__construct($this->presentMap, $this->resultPackages['all']);
- }
-
- // TODO make this a bit prettier instead of the two text indexes?
- public function setResultPackages(Pool $pool, Decisions $decisions)
- {
- $this->resultPackages = array('all' => array(), 'non-dev' => array(), 'dev' => array());
- foreach ($decisions as $i => $decision) {
- $literal = $decision[Decisions::DECISION_LITERAL];
-
- if ($literal > 0) {
- $package = $pool->literalToPackage($literal);
-
- $this->resultPackages['all'][] = $package;
- if (!isset($this->unlockableMap[$package->id])) {
- $this->resultPackages['non-dev'][] = $package;
- }
- }
- }
- }
-
- public function setNonDevPackages(LockTransaction $extractionResult)
- {
- $packages = $extractionResult->getNewLockPackages(false);
-
- $this->resultPackages['dev'] = $this->resultPackages['non-dev'];
- $this->resultPackages['non-dev'] = array();
-
- foreach ($packages as $package) {
- foreach ($this->resultPackages['dev'] as $i => $resultPackage) {
- // TODO this comparison is probably insufficient, aliases, what about modified versions? I guess they aren't possible?
- if ($package->getName() == $resultPackage->getName()) {
- $this->resultPackages['non-dev'][] = $resultPackage;
- unset($this->resultPackages['dev'][$i]);
- }
- }
- }
- }
-
- // TODO additionalFixedRepository needs to be looked at here as well?
- public function getNewLockPackages($devMode, $updateMirrors = false)
- {
- $packages = array();
- foreach ($this->resultPackages[$devMode ? 'dev' : 'non-dev'] as $package) {
- if (!$package instanceof AliasPackage) {
- // if we're just updating mirrors we need to reset references to the same as currently "present" packages' references to keep the lock file as-is
- // we do not reset references if the currently present package didn't have any, or if the type of VCS has changed
- if ($updateMirrors && !isset($this->presentMap[spl_object_hash($package)])) {
- foreach ($this->presentMap as $presentPackage) {
- if ($package->getName() == $presentPackage->getName() && $package->getVersion() == $presentPackage->getVersion()) {
- if ($presentPackage->getSourceReference() && $presentPackage->getSourceType() === $package->getSourceType()) {
- $package->setSourceDistReferences($presentPackage->getSourceReference());
- }
- if ($presentPackage->getReleaseDate() && $package instanceof Package) {
- $package->setReleaseDate($presentPackage->getReleaseDate());
- }
- }
- }
- }
- $packages[] = $package;
- }
- }
-
- return $packages;
- }
-
- /**
- * Checks which of the given aliases from composer.json are actually in use for the lock file
- */
- public function getAliases($aliases)
- {
- $usedAliases = array();
-
- foreach ($this->resultPackages['all'] as $package) {
- if ($package instanceof AliasPackage) {
- foreach ($aliases as $index => $alias) {
- if ($alias['package'] === $package->getName()) {
- $usedAliases[] = $alias;
- unset($aliases[$index]);
- }
- }
- }
- }
-
- usort($usedAliases, function ($a, $b) {
- return strcmp($a['package'], $b['package']);
- });
-
- return $usedAliases;
- }
-}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php
deleted file mode 100644
index 16a7bd9e2..000000000
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php
+++ /dev/null
@@ -1,105 +0,0 @@
-
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\DependencyResolver;
-
-use Composer\Package\BasePackage;
-use Composer\Package\Link;
-
-/**
- * @author Nils Adermann
- *
- * MultiConflictRule([A, B, C]) acts as Rule([-A, -B]), Rule([-A, -C]), Rule([-B, -C])
- */
-class MultiConflictRule extends Rule
-{
- /** @var int[] */
- protected $literals;
-
- /**
- * @param int[] $literals
- */
- public function __construct(array $literals, $reason, $reasonData)
- {
- parent::__construct($reason, $reasonData);
-
- if (\count($literals) < 3) {
- throw new \RuntimeException("multi conflict rule requires at least 3 literals");
- }
-
- // sort all packages ascending by id
- sort($literals);
-
- $this->literals = $literals;
- }
-
- public function getLiterals()
- {
- return $this->literals;
- }
-
- public function getHash()
- {
- $data = unpack('ihash', md5('c:'.implode(',', $this->literals), true));
-
- return $data['hash'];
- }
-
- /**
- * Checks if this rule is equal to another one
- *
- * Ignores whether either of the rules is disabled.
- *
- * @param Rule $rule The rule to check against
- * @return bool Whether the rules are equal
- */
- public function equals(Rule $rule)
- {
- if ($rule instanceof MultiConflictRule) {
- return $this->literals === $rule->getLiterals();
- }
-
- return false;
- }
-
- public function isAssertion()
- {
- return false;
- }
-
- public function disable()
- {
- throw new \RuntimeException("Disabling multi conflict rules is not possible. Please contact composer at https://github.com/composer/composer to let us debug what lead to this situation.");
- }
-
- /**
- * Formats a rule as a string of the format (Literal1|Literal2|...)
- *
- * @return string
- */
- public function __toString()
- {
- // TODO multi conflict?
- $result = $this->isDisabled() ? 'disabled(multi(' : '(multi(';
-
- foreach ($this->literals as $i => $literal) {
- if ($i != 0) {
- $result .= '|';
- }
- $result .= $literal;
- }
-
- $result .= '))';
-
- return $result;
- }
-}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.php
index 6eefbd5bb..08c659c49 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.php
@@ -19,17 +19,20 @@
*
* @author Konstantin Kudryashov
*/
-class InstallOperation extends SolverOperation implements OperationInterface
+class InstallOperation extends SolverOperation
{
- const TYPE = 'install';
+ protected $package;
/**
- * @var PackageInterface
+ * Initializes operation.
+ *
+ * @param PackageInterface $package package instance
+ * @param string $reason operation reason
*/
- protected $package;
-
- public function __construct(PackageInterface $package)
+ public function __construct(PackageInterface $package, $reason = null)
{
+ parent::__construct($reason);
+
$this->package = $package;
}
@@ -44,15 +47,20 @@ public function getPackage()
}
/**
- * {@inheritDoc}
+ * Returns job type.
+ *
+ * @return string
*/
- public function show($lock)
+ public function getJobType()
{
- return self::format($this->package, $lock);
+ return 'install';
}
- public static function format(PackageInterface $package, $lock = false)
+ /**
+ * {@inheritDoc}
+ */
+ public function __toString()
{
- return ($lock ? 'Locking ' : 'Installing ').''.$package->getPrettyName().' ('.$package->getFullPrettyVersion().' )';
+ return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php
index a1aa1219f..920e54e67 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php
@@ -13,41 +13,55 @@
namespace Composer\DependencyResolver\Operation;
use Composer\Package\AliasPackage;
+use Composer\Package\PackageInterface;
/**
* Solver install operation.
*
* @author Nils Adermann
*/
-class MarkAliasInstalledOperation extends SolverOperation implements OperationInterface
+class MarkAliasInstalledOperation extends SolverOperation
{
- const TYPE = 'markAliasInstalled';
+ protected $package;
/**
- * @var AliasPackage
+ * Initializes operation.
+ *
+ * @param AliasPackage $package package instance
+ * @param string $reason operation reason
*/
- protected $package;
-
- public function __construct(AliasPackage $package)
+ public function __construct(AliasPackage $package, $reason = null)
{
+ parent::__construct($reason);
+
$this->package = $package;
}
/**
* Returns package instance.
*
- * @return AliasPackage
+ * @return PackageInterface
*/
public function getPackage()
{
return $this->package;
}
+ /**
+ * Returns job type.
+ *
+ * @return string
+ */
+ public function getJobType()
+ {
+ return 'markAliasInstalled';
+ }
+
/**
* {@inheritDoc}
*/
- public function show($lock)
+ public function __toString()
{
- return 'Marking '.$this->package->getPrettyName().' ('.$this->package->getFullPrettyVersion().' ) as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->package->getAliasOf()->getFullPrettyVersion().' )';
+ return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php
index d0c193478..77f3aef8c 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php
@@ -13,41 +13,55 @@
namespace Composer\DependencyResolver\Operation;
use Composer\Package\AliasPackage;
+use Composer\Package\PackageInterface;
/**
* Solver install operation.
*
* @author Nils Adermann
*/
-class MarkAliasUninstalledOperation extends SolverOperation implements OperationInterface
+class MarkAliasUninstalledOperation extends SolverOperation
{
- const TYPE = 'markAliasUninstalled';
+ protected $package;
/**
- * @var AliasPackage
+ * Initializes operation.
+ *
+ * @param AliasPackage $package package instance
+ * @param string $reason operation reason
*/
- protected $package;
-
- public function __construct(AliasPackage $package)
+ public function __construct(AliasPackage $package, $reason = null)
{
+ parent::__construct($reason);
+
$this->package = $package;
}
/**
* Returns package instance.
*
- * @return AliasPackage
+ * @return PackageInterface
*/
public function getPackage()
{
return $this->package;
}
+ /**
+ * Returns job type.
+ *
+ * @return string
+ */
+ public function getJobType()
+ {
+ return 'markAliasUninstalled';
+ }
+
/**
* {@inheritDoc}
*/
- public function show($lock)
+ public function __toString()
{
- return 'Marking '.$this->package->getPrettyName().' ('.$this->package->getFullPrettyVersion().' ) as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->package->getAliasOf()->getFullPrettyVersion().' )';
+ return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php
index b0cc29b6d..330cbceb1 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php
@@ -20,19 +20,18 @@
interface OperationInterface
{
/**
- * Returns operation type.
+ * Returns job type.
*
* @return string
*/
- public function getOperationType();
+ public function getJobType();
/**
- * Serializes the operation in a human readable format
+ * Returns operation reason.
*
- * @param bool $lock Whether this is an operation on the lock file
* @return string
*/
- public function show($lock);
+ public function getReason();
/**
* Serializes the operation in a human readable format
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php
index 7ab87fe8a..e1a68585e 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php
@@ -12,30 +12,39 @@
namespace Composer\DependencyResolver\Operation;
+use Composer\Package\PackageInterface;
+
/**
- * Abstract operation class.
+ * Abstract solver operation class.
*
- * @author Aleksandr Bezpiatov
+ * @author Konstantin Kudryashov
*/
abstract class SolverOperation implements OperationInterface
{
- const TYPE = null;
+ protected $reason;
/**
- * Returns operation type.
+ * Initializes operation.
*
- * @return string
+ * @param string $reason operation reason
*/
- public function getOperationType()
+ public function __construct($reason = null)
{
- return static::TYPE;
+ $this->reason = $reason;
}
/**
- * {@inheritDoc}
+ * Returns operation reason.
+ *
+ * @return string
*/
- public function __toString()
+ public function getReason()
+ {
+ return $this->reason;
+ }
+
+ protected function formatVersion(PackageInterface $package)
{
- return $this->show(false);
+ return $package->getFullPrettyVersion();
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php
index 585fdb1e5..b4a73811e 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php
@@ -19,17 +19,20 @@
*
* @author Konstantin Kudryashov
*/
-class UninstallOperation extends SolverOperation implements OperationInterface
+class UninstallOperation extends SolverOperation
{
- const TYPE = 'uninstall';
+ protected $package;
/**
- * @var PackageInterface
+ * Initializes operation.
+ *
+ * @param PackageInterface $package package instance
+ * @param string $reason operation reason
*/
- protected $package;
-
- public function __construct(PackageInterface $package)
+ public function __construct(PackageInterface $package, $reason = null)
{
+ parent::__construct($reason);
+
$this->package = $package;
}
@@ -44,15 +47,20 @@ public function getPackage()
}
/**
- * {@inheritDoc}
+ * Returns job type.
+ *
+ * @return string
*/
- public function show($lock)
+ public function getJobType()
{
- return self::format($this->package, $lock);
+ return 'uninstall';
}
- public static function format(PackageInterface $package, $lock = false)
+ /**
+ * {@inheritDoc}
+ */
+ public function __toString()
{
- return 'Removing '.$package->getPrettyName().' ('.$package->getFullPrettyVersion().' )';
+ return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.php
index 543c8e783..8cfc6b700 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.php
@@ -20,26 +20,22 @@
*
* @author Konstantin Kudryashov
*/
-class UpdateOperation extends SolverOperation implements OperationInterface
+class UpdateOperation extends SolverOperation
{
- const TYPE = 'update';
-
- /**
- * @var PackageInterface
- */
protected $initialPackage;
-
- /**
- * @var PackageInterface
- */
protected $targetPackage;
/**
+ * Initializes update operation.
+ *
* @param PackageInterface $initial initial package
* @param PackageInterface $target target package (updated)
+ * @param string $reason update reason
*/
- public function __construct(PackageInterface $initial, PackageInterface $target)
+ public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
{
+ parent::__construct($reason);
+
$this->initialPackage = $initial;
$this->targetPackage = $target;
}
@@ -65,28 +61,23 @@ public function getTargetPackage()
}
/**
- * {@inheritDoc}
+ * Returns job type.
+ *
+ * @return string
*/
- public function show($lock)
+ public function getJobType()
{
- return self::format($this->initialPackage, $this->targetPackage, $lock);
+ return 'update';
}
- public static function format(PackageInterface $initialPackage, PackageInterface $targetPackage, $lock = false)
+ /**
+ * {@inheritDoc}
+ */
+ public function __toString()
{
- $fromVersion = $initialPackage->getFullPrettyVersion();
- $toVersion = $targetPackage->getFullPrettyVersion();
-
- if ($fromVersion === $toVersion && $initialPackage->getSourceReference() !== $targetPackage->getSourceReference()) {
- $fromVersion = $initialPackage->getFullPrettyVersion(true, PackageInterface::DISPLAY_SOURCE_REF);
- $toVersion = $targetPackage->getFullPrettyVersion(true, PackageInterface::DISPLAY_SOURCE_REF);
- } elseif ($fromVersion === $toVersion && $initialPackage->getDistReference() !== $targetPackage->getDistReference()) {
- $fromVersion = $initialPackage->getFullPrettyVersion(true, PackageInterface::DISPLAY_DIST_REF);
- $toVersion = $targetPackage->getFullPrettyVersion(true, PackageInterface::DISPLAY_DIST_REF);
- }
-
- $actionName = VersionParser::isUpgrade($initialPackage->getVersion(), $targetPackage->getVersion()) ? 'Upgrading' : 'Downgrading';
+ $actionName = VersionParser::isUpgrade($this->initialPackage->getVersion(), $this->targetPackage->getVersion()) ? 'Updating' : 'Downgrading';
- return $actionName.' '.$initialPackage->getPrettyName().' ('.$fromVersion.' => '.$toVersion.' )';
+ return $actionName.' '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
+ $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php
index b10a43e9f..3464bd594 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php
@@ -21,5 +21,7 @@ interface PolicyInterface
{
public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
- public function selectPreferredPackages(Pool $pool, array $literals, $requiredPackage = null);
+ public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
+
+ public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Pool.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Pool.php
index 733b0edf5..8021275b6 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Pool.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Pool.php
@@ -12,66 +12,157 @@
namespace Composer\DependencyResolver;
+use Composer\Package\BasePackage;
+use Composer\Package\AliasPackage;
use Composer\Package\Version\VersionParser;
-use Composer\Semver\CompilingMatcher;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\Constraint;
-use Composer\Package\BasePackage;
+use Composer\Semver\Constraint\EmptyConstraint;
+use Composer\Repository\RepositoryInterface;
+use Composer\Repository\CompositeRepository;
+use Composer\Repository\ComposerRepository;
+use Composer\Repository\InstalledRepositoryInterface;
+use Composer\Repository\PlatformRepository;
+use Composer\Package\PackageInterface;
/**
- * A package pool contains all packages for dependency resolution
+ * A package pool contains repositories that provide packages.
*
* @author Nils Adermann
* @author Jordi Boggiano
*/
class Pool implements \Countable
{
- /** @var BasePackage[] */
+ const MATCH_NAME = -1;
+ const MATCH_NONE = 0;
+ const MATCH = 1;
+ const MATCH_PROVIDE = 2;
+ const MATCH_REPLACE = 3;
+ const MATCH_FILTERED = 4;
+
+ protected $repositories = array();
+ protected $providerRepos = array();
protected $packages = array();
- /** @var array */
protected $packageByName = array();
- /** @var VersionParser */
+ protected $packageByExactName = array();
+ protected $acceptableStabilities;
+ protected $stabilityFlags;
protected $versionParser;
- /** @var array> */
protected $providerCache = array();
- /** @var BasePackage[] */
- protected $unacceptableFixedOrLockedPackages;
+ protected $filterRequires;
+ protected $whitelist = null; // TODO 2.0 rename to allowList
+ protected $id = 1;
- public function __construct(array $packages = array(), array $unacceptableFixedOrLockedPackages = array())
+ public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
{
$this->versionParser = new VersionParser;
- $this->setPackages($packages);
- $this->unacceptableFixedOrLockedPackages = $unacceptableFixedOrLockedPackages;
+ $this->acceptableStabilities = array();
+ foreach (BasePackage::$stabilities as $stability => $value) {
+ if ($value <= BasePackage::$stabilities[$minimumStability]) {
+ $this->acceptableStabilities[$stability] = $value;
+ }
+ }
+ $this->stabilityFlags = $stabilityFlags;
+ $this->filterRequires = $filterRequires;
+ foreach ($filterRequires as $name => $constraint) {
+ if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
+ unset($this->filterRequires[$name]);
+ }
+ }
}
- private function setPackages(array $packages)
+ public function setAllowList($allowList)
{
- $id = 1;
+ // call original method for BC
+ $this->setWhitelist($allowList);
+ }
- foreach ($packages as $package) {
- $this->packages[] = $package;
+ /**
+ * @deprecated use setAllowList instead
+ */
+ public function setWhitelist($whitelist)
+ {
+ $this->whitelist = $whitelist;
+ $this->providerCache = array();
+ }
- $package->id = $id++;
+ /**
+ * Adds a repository and its packages to this package pool
+ *
+ * @param RepositoryInterface $repo A package repository
+ * @param array $rootAliases
+ */
+ public function addRepository(RepositoryInterface $repo, $rootAliases = array())
+ {
+ if ($repo instanceof CompositeRepository) {
+ $repos = $repo->getRepositories();
+ } else {
+ $repos = array($repo);
+ }
- foreach ($package->getNames() as $provided) {
- $this->packageByName[$provided][] = $package;
+ foreach ($repos as $repo) {
+ $this->repositories[] = $repo;
+
+ $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
+
+ if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
+ $this->providerRepos[] = $repo;
+ $repo->setRootAliases($rootAliases);
+ $repo->resetPackageIds();
+ } else {
+ foreach ($repo->getPackages() as $package) {
+ $names = $package->getNames();
+ $stability = $package->getStability();
+ if ($exempt || $this->isPackageAcceptable($names, $stability)) {
+ $package->setId($this->id++);
+ $this->packages[] = $package;
+ $this->packageByExactName[$package->getName()][$package->id] = $package;
+
+ foreach ($names as $provided) {
+ $this->packageByName[$provided][] = $package;
+ }
+
+ // handle root package aliases
+ $name = $package->getName();
+ if (isset($rootAliases[$name][$package->getVersion()])) {
+ $alias = $rootAliases[$name][$package->getVersion()];
+ if ($package instanceof AliasPackage) {
+ $package = $package->getAliasOf();
+ }
+ $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
+ $aliasPackage->setRootPackageAlias(true);
+ $aliasPackage->setId($this->id++);
+
+ $package->getRepository()->addPackage($aliasPackage);
+ $this->packages[] = $aliasPackage;
+ $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
+
+ foreach ($aliasPackage->getNames() as $name) {
+ $this->packageByName[$name][] = $aliasPackage;
+ }
+ }
+ }
+ }
}
}
}
- /**
- * @return BasePackage[]
- */
- public function getPackages()
+ public function getPriority(RepositoryInterface $repo)
{
- return $this->packages;
+ $priority = array_search($repo, $this->repositories, true);
+
+ if (false === $priority) {
+ throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
+ }
+
+ return -$priority;
}
/**
* Retrieves the package object for a given package id.
*
- * @param int $id
- * @return BasePackage
+ * @param int $id
+ * @return PackageInterface
*/
public function packageById($id)
{
@@ -81,48 +172,117 @@ public function packageById($id)
/**
* Returns how many packages have been loaded into the pool
*/
- #[\ReturnTypeWillChange]
public function count()
{
- return \count($this->packages);
+ return count($this->packages);
}
/**
* Searches all packages providing the given package name and match the constraint
*
- * @param string $name The package name to be searched for
- * @param ConstraintInterface $constraint A constraint that all returned
- * packages must match or null to return all
- * @return BasePackage[] A set of packages
+ * @param string $name The package name to be searched for
+ * @param ConstraintInterface $constraint A constraint that all returned
+ * packages must match or null to return all
+ * @param bool $mustMatchName Whether the name of returned packages
+ * must match the given name
+ * @param bool $bypassFilters If enabled, filterRequires and stability matching is ignored
+ * @return PackageInterface[] A set of packages
*/
- public function whatProvides($name, ConstraintInterface $constraint = null)
+ public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
{
- $key = (string) $constraint;
+ if ($bypassFilters) {
+ return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
+ }
+
+ $key = ((int) $mustMatchName).$constraint;
if (isset($this->providerCache[$name][$key])) {
return $this->providerCache[$name][$key];
}
- return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint);
+ return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
}
/**
* @see whatProvides
*/
- private function computeWhatProvides($name, $constraint)
+ private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
{
- if (!isset($this->packageByName[$name])) {
- return array();
+ $candidates = array();
+
+ foreach ($this->providerRepos as $repo) {
+ foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
+ $candidates[] = $candidate;
+ if ($candidate->id < 1) {
+ $candidate->setId($this->id++);
+ $this->packages[$this->id - 2] = $candidate;
+ }
+ }
+ }
+
+ if ($mustMatchName) {
+ $candidates = array_filter($candidates, function ($candidate) use ($name) {
+ return $candidate->getName() == $name;
+ });
+ if (isset($this->packageByExactName[$name])) {
+ $candidates = array_merge($candidates, $this->packageByExactName[$name]);
+ }
+ } elseif (isset($this->packageByName[$name])) {
+ $candidates = array_merge($candidates, $this->packageByName[$name]);
}
- $matches = array();
+ $matches = $provideMatches = array();
+ $nameMatch = false;
- foreach ($this->packageByName[$name] as $candidate) {
- if ($this->match($candidate, $name, $constraint)) {
- $matches[] = $candidate;
+ foreach ($candidates as $candidate) {
+ $aliasOfCandidate = null;
+
+ // alias packages are not white listed, make sure that the package
+ // being aliased is white listed
+ if ($candidate instanceof AliasPackage) {
+ $aliasOfCandidate = $candidate->getAliasOf();
+ }
+
+ if ($this->whitelist !== null && !$bypassFilters && (
+ (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
+ ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
+ )) {
+ continue;
}
+ switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
+ case self::MATCH_NONE:
+ break;
+
+ case self::MATCH_NAME:
+ $nameMatch = true;
+ break;
+
+ case self::MATCH:
+ $nameMatch = true;
+ $matches[] = $candidate;
+ break;
+
+ case self::MATCH_PROVIDE:
+ $provideMatches[] = $candidate;
+ break;
+
+ case self::MATCH_REPLACE:
+ $matches[] = $candidate;
+ break;
+
+ case self::MATCH_FILTERED:
+ break;
+
+ default:
+ throw new \UnexpectedValueException('Unexpected match type');
+ }
+ }
+
+ // if a package with the required name exists, we ignore providers
+ if ($nameMatch) {
+ return $matches;
}
- return $matches;
+ return array_merge($matches, $provideMatches);
}
public function literalToPackage($literal)
@@ -145,22 +305,53 @@ public function literalToPrettyString($literal, $installedMap)
return $prefix.' '.$package->getPrettyString();
}
+ public function isPackageAcceptable($name, $stability)
+ {
+ foreach ((array) $name as $n) {
+ // allow if package matches the global stability requirement and has no exception
+ if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
+ return true;
+ }
+
+ // allow if package matches the package-specific stability flag
+ if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Checks if the package matches the given constraint directly or through
* provided or replaced packages
*
- * @param BasePackage $candidate
- * @param string $name Name of the package to be matched
- * @param ConstraintInterface $constraint The constraint to verify
- * @return bool
+ * @param PackageInterface $candidate
+ * @param string $name Name of the package to be matched
+ * @param ConstraintInterface $constraint The constraint to verify
+ * @return int One of the MATCH* constants of this class or 0 if there is no match
*/
- public function match(BasePackage $candidate, $name, ConstraintInterface $constraint = null)
+ public function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
{
$candidateName = $candidate->getName();
$candidateVersion = $candidate->getVersion();
+ $isDev = $candidate->getStability() === 'dev';
+ $isAlias = $candidate instanceof AliasPackage;
+
+ if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
+ $requireFilter = $this->filterRequires[$name];
+ } else {
+ $requireFilter = new EmptyConstraint;
+ }
if ($candidateName === $name) {
- return $constraint === null || CompilingMatcher::match($constraint, Constraint::OP_EQ, $candidateVersion);
+ $pkgConstraint = new Constraint('==', $candidateVersion);
+
+ if ($constraint === null || $constraint->matches($pkgConstraint)) {
+ return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
+ }
+
+ return self::MATCH_NAME;
}
$provides = $candidate->getProvides();
@@ -170,43 +361,27 @@ public function match(BasePackage $candidate, $name, ConstraintInterface $constr
if (isset($replaces[0]) || isset($provides[0])) {
foreach ($provides as $link) {
if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
- return true;
+ return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
}
}
foreach ($replaces as $link) {
if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
- return true;
+ return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
}
}
- return false;
+ return self::MATCH_NONE;
}
if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
- return true;
+ return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
}
if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
- return true;
- }
-
- return false;
- }
-
- public function isUnacceptableFixedOrLockedPackage(BasePackage $package)
- {
- return \in_array($package, $this->unacceptableFixedOrLockedPackages, true);
- }
-
- public function __toString()
- {
- $str = "Pool:\n";
-
- foreach ($this->packages as $package) {
- $str .= '- '.str_pad((string) $package->id, 6, ' ', STR_PAD_LEFT).': '.$package->getName()."\n";
+ return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
}
- return $str;
+ return self::MATCH_NONE;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php
deleted file mode 100644
index 97159a3c8..000000000
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php
+++ /dev/null
@@ -1,548 +0,0 @@
-
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\DependencyResolver;
-
-use Composer\EventDispatcher\EventDispatcher;
-use Composer\IO\IOInterface;
-use Composer\Package\AliasPackage;
-use Composer\Package\BasePackage;
-use Composer\Package\CompleteAliasPackage;
-use Composer\Package\CompletePackage;
-use Composer\Package\CompletePackageInterface;
-use Composer\Package\PackageInterface;
-use Composer\Package\Version\StabilityFilter;
-use Composer\Plugin\PluginEvents;
-use Composer\Plugin\PrePoolCreateEvent;
-use Composer\Repository\PlatformRepository;
-use Composer\Repository\RootPackageRepository;
-use Composer\Semver\CompilingMatcher;
-use Composer\Semver\Constraint\Constraint;
-use Composer\Semver\Constraint\ConstraintInterface;
-use Composer\Semver\Constraint\MatchAllConstraint;
-use Composer\Semver\Constraint\MultiConstraint;
-use Composer\Semver\Intervals;
-
-/**
- * @author Nils Adermann
- */
-class PoolBuilder
-{
- /**
- * @var int[]
- * @phpstan-var array
- */
- private $acceptableStabilities;
- /**
- * @var int[]
- * @phpstan-var array
- */
- private $stabilityFlags;
- /**
- * @var array[]
- * @phpstan-var array>
- */
- private $rootAliases;
- /**
- * @var string[]
- * @phpstan-var array
- */
- private $rootReferences;
- /**
- * @var ?EventDispatcher
- */
- private $eventDispatcher;
- /**
- * @var IOInterface
- */
- private $io;
- /**
- * @var array[]
- * @phpstan-var array
- */
- private $aliasMap = array();
- /**
- * @var ConstraintInterface[]
- * @phpstan-var array
- */
- private $packagesToLoad = array();
- /**
- * @var ConstraintInterface[]
- * @phpstan-var array
- */
- private $loadedPackages = array();
- /**
- * @var array[]
- * @phpstan-var array>>
- */
- private $loadedPerRepo = array();
- /**
- * @var PackageInterface[]
- */
- private $packages = array();
- /**
- * @var PackageInterface[]
- * @phpstan-var list
- */
- private $unacceptableFixedOrLockedPackages = array();
- /** @var string[] */
- private $updateAllowList = array();
- /** @var array */
- private $skippedLoad = array();
-
- /**
- * Keeps a list of dependencies which are root requirements, and as such
- * have already their maximum required range loaded and can not be
- * extended by markPackageNameForLoading
- *
- * Packages get cleared from this list if they get unlocked as in that case
- * we need to actually load them
- *
- * @var array
- */
- private $maxExtendedReqs = array();
- /**
- * @var array
- * @phpstan-var array
- */
- private $updateAllowWarned = array();
-
- /** @var int */
- private $indexCounter = 0;
-
- /**
- * @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
- * @phpstan-param array $acceptableStabilities
- * @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
- * @phpstan-param array $stabilityFlags
- * @param array[] $rootAliases
- * @phpstan-param array> $rootAliases
- * @param string[] $rootReferences an array of package name => source reference
- * @phpstan-param array $rootReferences
- */
- public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, IOInterface $io, EventDispatcher $eventDispatcher = null)
- {
- $this->acceptableStabilities = $acceptableStabilities;
- $this->stabilityFlags = $stabilityFlags;
- $this->rootAliases = $rootAliases;
- $this->rootReferences = $rootReferences;
- $this->eventDispatcher = $eventDispatcher;
- $this->io = $io;
- }
-
- public function buildPool(array $repositories, Request $request)
- {
- if ($request->getUpdateAllowList()) {
- $this->updateAllowList = $request->getUpdateAllowList();
- $this->warnAboutNonMatchingUpdateAllowList($request);
-
- foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) {
- if (!$this->isUpdateAllowed($lockedPackage)) {
- $request->lockPackage($lockedPackage);
- $lockedName = $lockedPackage->getName();
- // remember which packages we skipped loading remote content for in this partial update
- $this->skippedLoad[$lockedName] = $lockedName;
- foreach ($lockedPackage->getReplaces() as $link) {
- $this->skippedLoad[$link->getTarget()] = $lockedName;
- }
- }
- }
- }
-
- foreach ($request->getFixedOrLockedPackages() as $package) {
- // using MatchAllConstraint here because fixed packages do not need to retrigger
- // loading any packages
- $this->loadedPackages[$package->getName()] = new MatchAllConstraint();
-
- // replace means conflict, so if a fixed package replaces a name, no need to load that one, packages would conflict anyways
- foreach ($package->getReplaces() as $link) {
- $this->loadedPackages[$link->getTarget()] = new MatchAllConstraint();
- }
-
- // TODO in how far can we do the above for conflicts? It's more tricky cause conflicts can be limited to
- // specific versions while replace is a conflict with all versions of the name
-
- if (
- $package->getRepository() instanceof RootPackageRepository
- || $package->getRepository() instanceof PlatformRepository
- || StabilityFilter::isPackageAcceptable($this->acceptableStabilities, $this->stabilityFlags, $package->getNames(), $package->getStability())
- ) {
- $this->loadPackage($request, $package, false);
- } else {
- $this->unacceptableFixedOrLockedPackages[] = $package;
- }
- }
-
- foreach ($request->getRequires() as $packageName => $constraint) {
- // fixed and locked packages have already been added, so if a root require needs one of them, no need to do anything
- if (isset($this->loadedPackages[$packageName])) {
- continue;
- }
-
- $this->packagesToLoad[$packageName] = $constraint;
- $this->maxExtendedReqs[$packageName] = true;
- }
-
- // clean up packagesToLoad for anything we manually marked loaded above
- foreach ($this->packagesToLoad as $name => $constraint) {
- if (isset($this->loadedPackages[$name])) {
- unset($this->packagesToLoad[$name]);
- }
- }
-
- while (!empty($this->packagesToLoad)) {
- $this->loadPackagesMarkedForLoading($request, $repositories);
- }
-
- foreach ($this->packages as $i => $package) {
- // we check all alias related packages at once, so no need to check individual aliases
- // isset also checks non-null value
- if (!$package instanceof AliasPackage) {
- $constraint = new Constraint('==', $package->getVersion());
- $aliasedPackages = array($i => $package);
- if (isset($this->aliasMap[spl_object_hash($package)])) {
- $aliasedPackages += $this->aliasMap[spl_object_hash($package)];
- }
-
- $found = false;
- foreach ($aliasedPackages as $packageOrAlias) {
- if (CompilingMatcher::match($constraint, Constraint::OP_EQ, $packageOrAlias->getVersion())) {
- $found = true;
- }
- }
- if (!$found) {
- foreach ($aliasedPackages as $index => $packageOrAlias) {
- unset($this->packages[$index]);
- }
- }
- }
- }
-
- if ($this->eventDispatcher) {
- $prePoolCreateEvent = new PrePoolCreateEvent(
- PluginEvents::PRE_POOL_CREATE,
- $repositories,
- $request,
- $this->acceptableStabilities,
- $this->stabilityFlags,
- $this->rootAliases,
- $this->rootReferences,
- $this->packages,
- $this->unacceptableFixedOrLockedPackages
- );
- $this->eventDispatcher->dispatch($prePoolCreateEvent->getName(), $prePoolCreateEvent);
- $this->packages = $prePoolCreateEvent->getPackages();
- $this->unacceptableFixedOrLockedPackages = $prePoolCreateEvent->getUnacceptableFixedPackages();
- }
-
- $pool = new Pool($this->packages, $this->unacceptableFixedOrLockedPackages);
-
- $this->aliasMap = array();
- $this->packagesToLoad = array();
- $this->loadedPackages = array();
- $this->loadedPerRepo = array();
- $this->packages = array();
- $this->unacceptableFixedOrLockedPackages = array();
- $this->maxExtendedReqs = array();
- $this->skippedLoad = array();
- $this->indexCounter = 0;
-
- Intervals::clear();
-
- return $pool;
- }
-
- private function markPackageNameForLoading(Request $request, $name, ConstraintInterface $constraint)
- {
- // Skip platform requires at this stage
- if (PlatformRepository::isPlatformPackage($name)) {
- return;
- }
-
- // Root require (which was not unlocked) already loaded the maximum range so no
- // need to check anything here
- if (isset($this->maxExtendedReqs[$name])) {
- return;
- }
-
- // Root requires can not be overruled by dependencies so there is no point in
- // extending the loaded constraint for those.
- // This is triggered when loading a root require which was locked but got unlocked, then
- // we make sure that we load at most the intervals covered by the root constraint.
- $rootRequires = $request->getRequires();
- if (isset($rootRequires[$name]) && !Intervals::isSubsetOf($constraint, $rootRequires[$name])) {
- $constraint = $rootRequires[$name];
- }
-
- // Not yet loaded or already marked for a reload, set the constraint to be loaded
- if (!isset($this->loadedPackages[$name])) {
- // Maybe it was already marked before but not loaded yet. In that case
- // we have to extend the constraint (we don't check if they are identical because
- // MultiConstraint::create() will optimize anyway)
- if (isset($this->packagesToLoad[$name])) {
- // Already marked for loading and this does not expand the constraint to be loaded, nothing to do
- if (Intervals::isSubsetOf($constraint, $this->packagesToLoad[$name])) {
- return;
- }
-
- // extend the constraint to be loaded
- $constraint = Intervals::compactConstraint(MultiConstraint::create(array($this->packagesToLoad[$name], $constraint), false));
- }
-
- $this->packagesToLoad[$name] = $constraint;
-
- return;
- }
-
- // No need to load this package with this constraint because it is
- // a subset of the constraint with which we have already loaded packages
- if (Intervals::isSubsetOf($constraint, $this->loadedPackages[$name])) {
- return;
- }
-
- // We have already loaded that package but not in the constraint that's
- // required. We extend the constraint and mark that package as not being loaded
- // yet so we get the required package versions
- $this->packagesToLoad[$name] = Intervals::compactConstraint(MultiConstraint::create(array($this->loadedPackages[$name], $constraint), false));
- unset($this->loadedPackages[$name]);
- }
-
- private function loadPackagesMarkedForLoading(Request $request, $repositories)
- {
- foreach ($this->packagesToLoad as $name => $constraint) {
- $this->loadedPackages[$name] = $constraint;
- }
-
- $packageBatch = $this->packagesToLoad;
- $this->packagesToLoad = array();
-
- foreach ($repositories as $repoIndex => $repository) {
- if (empty($packageBatch)) {
- break;
- }
-
- // these repos have their packages fixed or locked if they need to be loaded so we
- // never need to load anything else from them
- if ($repository instanceof PlatformRepository || $repository === $request->getLockedRepository()) {
- continue;
- }
- $result = $repository->loadPackages($packageBatch, $this->acceptableStabilities, $this->stabilityFlags, isset($this->loadedPerRepo[$repoIndex]) ? $this->loadedPerRepo[$repoIndex] : array());
-
- foreach ($result['namesFound'] as $name) {
- // avoid loading the same package again from other repositories once it has been found
- unset($packageBatch[$name]);
- }
- foreach ($result['packages'] as $package) {
- $this->loadedPerRepo[$repoIndex][$package->getName()][$package->getVersion()] = $package;
- $this->loadPackage($request, $package);
- }
- }
- }
-
- private function loadPackage(Request $request, BasePackage $package, $propagateUpdate = true)
- {
- $index = $this->indexCounter++;
- $this->packages[$index] = $package;
-
- if ($package instanceof AliasPackage) {
- $this->aliasMap[spl_object_hash($package->getAliasOf())][$index] = $package;
- }
-
- $name = $package->getName();
-
- // we're simply setting the root references on all versions for a name here and rely on the solver to pick the
- // right version. It'd be more work to figure out which versions and which aliases of those versions this may
- // apply to
- if (isset($this->rootReferences[$name])) {
- // do not modify the references on already locked or fixed packages
- if (!$request->isLockedPackage($package) && !$request->isFixedPackage($package)) {
- $package->setSourceDistReferences($this->rootReferences[$name]);
- }
- }
-
- // if propogateUpdate is false we are loading a fixed or locked package, root aliases do not apply as they are
- // manually loaded as separate packages in this case
- if ($propagateUpdate && isset($this->rootAliases[$name][$package->getVersion()])) {
- $alias = $this->rootAliases[$name][$package->getVersion()];
- if ($package instanceof AliasPackage) {
- $basePackage = $package->getAliasOf();
- } else {
- $basePackage = $package;
- }
- if ($basePackage instanceof CompletePackage) {
- $aliasPackage = new CompleteAliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']);
- } else {
- $aliasPackage = new AliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']);
- }
- $aliasPackage->setRootPackageAlias(true);
-
- $newIndex = $this->indexCounter++;
- $this->packages[$newIndex] = $aliasPackage;
- $this->aliasMap[spl_object_hash($aliasPackage->getAliasOf())][$newIndex] = $aliasPackage;
- }
-
- foreach ($package->getRequires() as $link) {
- $require = $link->getTarget();
- $linkConstraint = $link->getConstraint();
-
- // if the required package is loaded as a locked package only and hasn't had its deps analyzed
- if (isset($this->skippedLoad[$require])) {
- // if we're doing a full update or this is a partial update with transitive deps and we're currently
- // looking at a package which needs to be updated we need to unlock the package we now know is a
- // dependency of another package which we are trying to update, and then attempt to load it again
- if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) {
- if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $this->skippedLoad[$require])) {
- $this->unlockPackage($request, $require);
- $this->markPackageNameForLoading($request, $require, $linkConstraint);
- } elseif (!isset($this->updateAllowWarned[$this->skippedLoad[$require]])) {
- $this->updateAllowWarned[$this->skippedLoad[$require]] = true;
- $this->io->writeError('Dependency "'.$this->skippedLoad[$require].'" is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies. ');
- }
- }
- } else {
- $this->markPackageNameForLoading($request, $require, $linkConstraint);
- }
- }
-
- // if we're doing a partial update with deps we also need to unlock packages which are being replaced in case
- // they are currently locked and thus prevent this updateable package from being installable/updateable
- if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) {
- foreach ($package->getReplaces() as $link) {
- $replace = $link->getTarget();
- if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) {
- if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $this->skippedLoad[$replace])) {
- $this->unlockPackage($request, $replace);
- $this->markPackageNameForLoading($request, $replace, $link->getConstraint());
- } elseif (!$request->getUpdateAllowTransitiveRootDependencies() && $this->isRootRequire($request, $replace) && !isset($this->updateAllowWarned[$replace])) {
- $this->updateAllowWarned[$replace] = true;
- $this->io->writeError('Dependency "'.$replace.'" is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies. ');
- }
- }
- }
- }
- }
-
- /**
- * Checks if a particular name is required directly in the request
- *
- * @return bool
- */
- private function isRootRequire(Request $request, $name)
- {
- $rootRequires = $request->getRequires();
-
- return isset($rootRequires[$name]);
- }
-
- /**
- * Checks whether the update allow list allows this package in the lock file to be updated
- * @return bool
- */
- private function isUpdateAllowed(PackageInterface $package)
- {
- // Path repo packages are never loaded from lock, to force them to always remain in sync
- // unless symlinking is disabled in which case we probably should rather treat them like
- // regular packages
- if ($package->getDistType() === 'path') {
- $transportOptions = $package->getTransportOptions();
- if (!isset($transportOptions['symlink']) || $transportOptions['symlink'] !== false) {
- return true;
- }
- }
-
- foreach ($this->updateAllowList as $pattern => $void) {
- $patternRegexp = BasePackage::packageNameToRegexp($pattern);
- if (preg_match($patternRegexp, $package->getName())) {
- return true;
- }
- }
-
- return false;
- }
-
- private function warnAboutNonMatchingUpdateAllowList(Request $request)
- {
- foreach ($this->updateAllowList as $pattern => $void) {
- $patternRegexp = BasePackage::packageNameToRegexp($pattern);
- // update pattern matches a locked package? => all good
- foreach ($request->getLockedRepository()->getPackages() as $package) {
- if (preg_match($patternRegexp, $package->getName())) {
- continue 2;
- }
- }
- // update pattern matches a root require? => all good, probably a new package
- foreach ($request->getRequires() as $packageName => $constraint) {
- if (preg_match($patternRegexp, $packageName)) {
- continue 2;
- }
- }
- if (strpos($pattern, '*') !== false) {
- $this->io->writeError('Pattern "' . $pattern . '" listed for update does not match any locked packages. ');
- } else {
- $this->io->writeError('Package "' . $pattern . '" listed for update is not locked. ');
- }
- }
- }
-
- /**
- * Reverts the decision to use a locked package if a partial update with transitive dependencies
- * found that this package actually needs to be updated
- */
- private function unlockPackage(Request $request, $name)
- {
- if (
- // if we unfixed a replaced package name, we also need to unfix the replacer itself
- $this->skippedLoad[$name] !== $name
- // as long as it was not unfixed yet
- && isset($this->skippedLoad[$this->skippedLoad[$name]])
- ) {
- $this->unlockPackage($request, $this->skippedLoad[$name]);
- }
-
- unset($this->skippedLoad[$name], $this->loadedPackages[$name], $this->maxExtendedReqs[$name]);
-
- // remove locked package by this name which was already initialized
- foreach ($request->getLockedPackages() as $lockedPackage) {
- if (!($lockedPackage instanceof AliasPackage) && $lockedPackage->getName() === $name) {
- if (false !== $index = array_search($lockedPackage, $this->packages, true)) {
- $request->unlockPackage($lockedPackage);
- $this->removeLoadedPackage($request, $lockedPackage, $index);
-
- // make sure that any requirements for this package by other locked or fixed packages are now
- // also loaded, as they were previously ignored because the locked (now unlocked) package already
- // satisfied their requirements
- foreach ($request->getFixedOrLockedPackages() as $fixedOrLockedPackage) {
- if ($fixedOrLockedPackage !== $lockedPackage && isset($this->skippedLoad[$fixedOrLockedPackage->getName()])) {
- foreach ($fixedOrLockedPackage->getRequires() as $requireLink) {
- if ($requireLink->getTarget() === $lockedPackage->getName()) {
- $this->markPackageNameForLoading($request, $lockedPackage->getName(), $requireLink->getConstraint());
- }
- }
- }
- }
- }
- }
- }
- }
-
- private function removeLoadedPackage(Request $request, PackageInterface $package, $index)
- {
- unset($this->packages[$index]);
- if (isset($this->aliasMap[spl_object_hash($package)])) {
- foreach ($this->aliasMap[spl_object_hash($package)] as $aliasIndex => $aliasPackage) {
- $request->unlockPackage($aliasPackage);
- unset($this->packages[$aliasIndex]);
- }
- unset($this->aliasMap[spl_object_hash($package)]);
- }
- }
-}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Problem.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Problem.php
index 35ce3b045..df289a4c1 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Problem.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Problem.php
@@ -13,13 +13,6 @@
namespace Composer\DependencyResolver;
use Composer\Package\CompletePackageInterface;
-use Composer\Package\AliasPackage;
-use Composer\Package\RootPackageInterface;
-use Composer\Repository\RepositorySet;
-use Composer\Repository\LockArrayRepository;
-use Composer\Semver\Constraint\Constraint;
-use Composer\Semver\Constraint\ConstraintInterface;
-use Composer\Package\Version\VersionParser;
/**
* Represents a problem detected while solving dependencies
@@ -30,19 +23,25 @@ class Problem
{
/**
* A map containing the id of each rule part of this problem as a key
- * @var array
+ * @var array
*/
protected $reasonSeen;
/**
- * A set of reasons for the problem, each is a rule or a root require and a rule
- * @var array>
+ * A set of reasons for the problem, each is a rule or a job and a rule
+ * @var array
*/
protected $reasons = array();
- /** @var int */
protected $section = 0;
+ protected $pool;
+
+ public function __construct(Pool $pool)
+ {
+ $this->pool = $pool;
+ }
+
/**
* Add a rule as a reason
*
@@ -50,7 +49,10 @@ class Problem
*/
public function addRule(Rule $rule)
{
- $this->addReason(spl_object_hash($rule), $rule);
+ $this->addReason(spl_object_hash($rule), array(
+ 'rule' => $rule,
+ 'job' => $rule->getJob(),
+ ));
}
/**
@@ -66,405 +68,189 @@ public function getReasons()
/**
* A human readable textual representation of the problem's reasons
*
- * @param array $installedMap A map of all present packages
+ * @param array $installedMap A map of all installed packages
* @return string
*/
- public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, array $installedMap = array(), array $learnedPool = array())
+ public function getPrettyString(array $installedMap = array())
{
- // TODO doesn't this entirely defeat the purpose of the problem sections? what's the point of sections?
$reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
if (count($reasons) === 1) {
reset($reasons);
- $rule = current($reasons);
+ $reason = current($reasons);
- if (!in_array($rule->getReason(), array(Rule::RULE_ROOT_REQUIRE, Rule::RULE_FIXED), true)) {
- throw new \LogicException("Single reason problems must contain a request rule.");
- }
+ $job = $reason['job'];
- $reasonData = $rule->getReasonData();
- $packageName = $reasonData['packageName'];
- $constraint = $reasonData['constraint'];
+ $packageName = $job['packageName'];
+ $constraint = $job['constraint'];
if (isset($constraint)) {
- $packages = $pool->whatProvides($packageName, $constraint);
+ $packages = $this->pool->whatProvides($packageName, $constraint);
} else {
$packages = array();
}
- if (empty($packages)) {
- return "\n ".implode(self::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $packageName, $constraint));
- }
- }
-
- return self::formatDeduplicatedRules($reasons, ' ', $repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool);
- }
+ if ($job && $job['cmd'] === 'install' && empty($packages)) {
- /**
- * @internal
- */
- public static function formatDeduplicatedRules($rules, $indent, RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, array $installedMap = array(), array $learnedPool = array())
- {
- $messages = array();
- $templates = array();
- $parser = new VersionParser;
- $deduplicatableRuleTypes = array(Rule::RULE_PACKAGE_REQUIRES, Rule::RULE_PACKAGE_CONFLICT);
- foreach ($rules as $rule) {
- $message = $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool);
- if (in_array($rule->getReason(), $deduplicatableRuleTypes, true) && preg_match('{^(?P\S+) (?P\S+) (?Prequires|conflicts)}', $message, $m)) {
- $template = preg_replace('{^\S+ \S+ }', '%s%s ', $message);
- $messages[] = $template;
- $templates[$template][$m[1]][$parser->normalize($m[2])] = $m[2];
- } elseif ($message !== '') {
- $messages[] = $message;
- }
- }
+ // handle php/hhvm
+ if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
+ $version = phpversion();
+ $available = $this->pool->whatProvides($packageName);
- $result = array();
- foreach (array_unique($messages) as $message) {
- if (isset($templates[$message])) {
- foreach ($templates[$message] as $package => $versions) {
- uksort($versions, 'version_compare');
- if (!$isVerbose) {
- $versions = self::condenseVersionList($versions, 1);
- }
- if (count($versions) > 1) {
- // remove the s from requires/conflicts to correct grammar
- $message = preg_replace('{^(%s%s (?:require|conflict))s}', '$1', $message);
- $result[] = sprintf($message, $package, '['.implode(', ', $versions).']');
- } else {
- $result[] = sprintf($message, $package, ' '.reset($versions));
+ if (count($available)) {
+ $firstAvailable = reset($available);
+ $version = $firstAvailable->getPrettyVersion();
+ $extra = $firstAvailable->getExtra();
+ if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
+ $version .= '; ' . $firstAvailable->getDescription();
+ }
}
- }
- } else {
- $result[] = $message;
- }
- }
-
- return "\n$indent- ".implode("\n$indent- ", $result);
- }
-
- public function isCausedByLock(RepositorySet $repositorySet, Request $request, Pool $pool)
- {
- foreach ($this->reasons as $sectionRules) {
- foreach ($sectionRules as $rule) {
- if ($rule->isCausedByLock($repositorySet, $request, $pool)) {
- return true;
- }
- }
- }
- }
-
- /**
- * Store a reason descriptor but ignore duplicates
- *
- * @param string $id A canonical identifier for the reason
- * @param Rule $reason The reason descriptor
- */
- protected function addReason($id, Rule $reason)
- {
- // TODO: if a rule is part of a problem description in two sections, isn't this going to remove a message
- // that is important to understand the issue?
- if (!isset($this->reasonSeen[$id])) {
- $this->reasonSeen[$id] = true;
- $this->reasons[$this->section][] = $reason;
- }
- }
-
- public function nextSection()
- {
- $this->section++;
- }
-
- /**
- * @internal
- */
- public static function getMissingPackageReason(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, $packageName, $constraint = null)
- {
- // handle php/hhvm
- if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
- $version = self::getPlatformPackageVersion($pool, $packageName, phpversion());
+ $msg = "\n - This package requires ".$packageName.$this->constraintToText($constraint).' but ';
- $msg = "- Root composer.json requires ".$packageName.self::constraintToText($constraint).' but ';
-
- if (defined('HHVM_VERSION') || ($packageName === 'hhvm' && count($pool->whatProvides($packageName)) > 0)) {
- return array($msg, 'your HHVM version does not satisfy that requirement.');
- }
+ if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
+ return $msg . 'your HHVM version does not satisfy that requirement.';
+ }
- if ($packageName === 'hhvm') {
- return array($msg, 'HHVM was not detected on this machine, make sure it is in your PATH.');
- }
+ if ($packageName === 'hhvm') {
+ return $msg . 'you are running this with PHP and not HHVM.';
+ }
- return array($msg, 'your '.$packageName.' version ('. $version .') does not satisfy that requirement.');
- }
+ return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
+ }
- // handle php extensions
- if (0 === stripos($packageName, 'ext-')) {
- if (false !== strpos($packageName, ' ')) {
- return array('- ', "PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.');
- }
+ // handle php extensions
+ if (0 === stripos($packageName, 'ext-')) {
+ if (false !== strpos($packageName, ' ')) {
+ return "\n - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.';
+ }
- $ext = substr($packageName, 4);
- $version = self::getPlatformPackageVersion($pool, $packageName, phpversion($ext) ?: '0');
+ $ext = substr($packageName, 4);
+ $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
- $error = extension_loaded($ext) ? 'it has the wrong version ('.$version.') installed' : 'it is missing from your system';
+ return "\n - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
+ }
- return array("- Root composer.json requires PHP extension ".$packageName.self::constraintToText($constraint).' but ', $error.'. Install or enable PHP\'s '.$ext.' extension.');
- }
+ // handle linked libs
+ if (0 === stripos($packageName, 'lib-')) {
+ if (strtolower($packageName) === 'lib-icu') {
+ $error = extension_loaded('intl') ? 'has the wrong version installed, try upgrading the intl extension.' : 'is missing from your system, make sure the intl extension is loaded.';
- // handle linked libs
- if (0 === stripos($packageName, 'lib-')) {
- if (strtolower($packageName) === 'lib-icu') {
- $error = extension_loaded('intl') ? 'it has the wrong version installed, try upgrading the intl extension.' : 'it is missing from your system, make sure the intl extension is loaded.';
+ return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error;
+ }
- return array("- Root composer.json requires linked library ".$packageName.self::constraintToText($constraint).' but ', $error);
- }
+ return "\n - The requested linked library ".$packageName.$this->constraintToText($constraint).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
+ }
- return array("- Root composer.json requires linked library ".$packageName.self::constraintToText($constraint).' but ', 'it has the wrong version installed or is missing from your system, make sure to load the extension providing it.');
- }
+ if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
+ $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
- $lockedPackage = null;
- foreach ($request->getLockedPackages() as $package) {
- if ($package->getName() === $packageName) {
- $lockedPackage = $package;
- if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
- return array("- ", $package->getPrettyName().' is fixed to '.$package->getPrettyVersion().' (lock file version) by a partial update but that version is rejected by your minimum-stability. Make sure you list it as an argument for the update command.');
+ return "\n - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
}
- break;
- }
- }
- // first check if the actual requested package is found in normal conditions
- // if so it must mean it is rejected by another constraint than the one given here
- if ($packages = $repositorySet->findPackages($packageName, $constraint)) {
- $rootReqs = $repositorySet->getRootRequires();
- if (isset($rootReqs[$packageName])) {
- $filtered = array_filter($packages, function ($p) use ($rootReqs, $packageName) {
- return $rootReqs[$packageName]->matches(new Constraint('==', $p->getVersion()));
- });
- if (0 === count($filtered)) {
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose).' but '.(self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts').' with your root composer.json require ('.$rootReqs[$packageName]->getPrettyString().').');
+ if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) {
+ return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
}
- }
- if ($lockedPackage) {
- $fixedConstraint = new Constraint('==', $lockedPackage->getVersion());
- $filtered = array_filter($packages, function ($p) use ($fixedConstraint) {
- return $fixedConstraint->matches(new Constraint('==', $p->getVersion()));
- });
- if (0 === count($filtered)) {
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose).' but the package is fixed to '.$lockedPackage->getPrettyVersion().' (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.');
+ if ($providers = $this->pool->whatProvides($packageName, null, true, true)) {
+ return "\n - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
}
- }
- $nonLockedPackages = array_filter($packages, function ($p) {
- return !$p->getRepository() instanceof LockArrayRepository;
- });
-
- if (!$nonLockedPackages) {
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose).' in the lock file but not in remote repositories, make sure you avoid updating this package to keep the one from the lock file.');
+ return "\n - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.';
}
-
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose).' but these were not loaded, likely because '.(self::hasMultipleNames($packages) ? 'they conflict' : 'it conflicts').' with another require.');
}
- // check if the package is found when bypassing stability checks
- if ($packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) {
- // we must first verify if a valid package would be found in a lower priority repository
- if ($allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) {
- return self::computeCheckForLowerPrioRepo($isVerbose, $packageName, $constraint, $packages, $allReposPackages, 'minimum-stability');
- }
-
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose).' but '.(self::hasMultipleNames($packages) ? 'these do' : 'it does').' not match your minimum-stability.');
- }
+ $messages = array();
- // check if the package is found when bypassing the constraint and stability checks
- if ($packages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) {
- // we must first verify if a valid package would be found in a lower priority repository
- if ($allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) {
- return self::computeCheckForLowerPrioRepo($isVerbose, $packageName, $constraint, $packages, $allReposPackages, 'constraint');
- }
+ foreach ($reasons as $reason) {
+ $rule = $reason['rule'];
+ $job = $reason['job'];
- $suffix = '';
- if ($constraint instanceof Constraint && $constraint->getVersion() === 'dev-master') {
- foreach ($packages as $candidate) {
- if (in_array($candidate->getVersion(), array('dev-default', 'dev-main'), true)) {
- $suffix = ' Perhaps dev-master was renamed to '.$candidate->getPrettyVersion().'?';
- break;
- }
+ if ($job) {
+ $messages[] = $this->jobToText($job);
+ } elseif ($rule) {
+ if ($rule instanceof Rule) {
+ $messages[] = $rule->getPrettyString($this->pool, $installedMap);
}
}
-
- // check if the root package is a name match and hint the dependencies on root troubleshooting article
- $allReposPackages = $packages;
- $topPackage = reset($allReposPackages);
- if ($topPackage instanceof RootPackageInterface) {
- $suffix = ' See https://getcomposer.org/dep-on-root for details and assistance.';
- }
-
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose).' but '.(self::hasMultipleNames($packages) ? 'these do' : 'it does').' not match the constraint.' . $suffix);
- }
-
- if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
- $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
-
- return array("- Root composer.json requires $packageName, it ", 'could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.');
- }
-
- if ($providers = $repositorySet->getProviders($packageName)) {
- $maxProviders = 20;
- $providersStr = implode(array_map(function ($p) {
- $description = $p['description'] ? ' '.substr($p['description'], 0, 100) : '';
-
- return " - ${p['name']}".$description."\n";
- }, count($providers) > $maxProviders + 1 ? array_slice($providers, 0, $maxProviders) : $providers));
- if (count($providers) > $maxProviders + 1) {
- $providersStr .= ' ... and '.(count($providers) - $maxProviders).' more.'."\n";
- }
-
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint).", it ", "could not be found in any version, but the following packages provide it:\n".$providersStr." Consider requiring one of these to satisfy the $packageName requirement.");
}
- return array("- Root composer.json requires $packageName, it ", "could not be found in any version, there may be a typo in the package name.");
+ return "\n - ".implode("\n - ", $messages);
}
/**
- * @internal
+ * Store a reason descriptor but ignore duplicates
+ *
+ * @param string $id A canonical identifier for the reason
+ * @param string $reason The reason descriptor
*/
- public static function getPackageList(array $packages, $isVerbose)
+ protected function addReason($id, $reason)
{
- $prepared = array();
- $hasDefaultBranch = array();
- foreach ($packages as $package) {
- $prepared[$package->getName()]['name'] = $package->getPrettyName();
- $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion().($package instanceof AliasPackage ? ' (alias of '.$package->getAliasOf()->getPrettyVersion().')' : '');
- if ($package->isDefaultBranch()) {
- $hasDefaultBranch[$package->getName()] = true;
- }
- }
- foreach ($prepared as $name => $package) {
- // remove the implicit default branch alias to avoid cruft in the display
- if (isset($package['versions'][VersionParser::DEFAULT_BRANCH_ALIAS], $hasDefaultBranch[$name])) {
- unset($package['versions'][VersionParser::DEFAULT_BRANCH_ALIAS]);
- }
-
- uksort($package['versions'], 'version_compare');
-
- if (!$isVerbose) {
- $package['versions'] = self::condenseVersionList($package['versions'], 4);
- }
- $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
+ if (!isset($this->reasonSeen[$id])) {
+ $this->reasonSeen[$id] = true;
+ $this->reasons[$this->section][] = $reason;
}
-
- return implode(', ', $prepared);
}
- private static function getPlatformPackageVersion(Pool $pool, $packageName, $version)
+ public function nextSection()
{
- $available = $pool->whatProvides($packageName);
-
- if (count($available)) {
- $firstAvailable = reset($available);
- $version = $firstAvailable->getPrettyVersion();
- $extra = $firstAvailable->getExtra();
- if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
- $version .= '; ' . str_replace('Package ', '', $firstAvailable->getDescription());
- }
- }
-
- return $version;
+ $this->section++;
}
/**
- * @param string[] $versions an array of pretty versions, with normalized versions as keys
- * @return list a list of pretty versions and '...' where versions were removed
+ * Turns a job into a human readable description
+ *
+ * @param array $job
+ * @return string
*/
- private static function condenseVersionList(array $versions, $max, $maxDev = 16)
+ protected function jobToText($job)
{
- if (count($versions) <= $max) {
- return $versions;
- }
+ $packageName = $job['packageName'];
+ $constraint = $job['constraint'];
+ switch ($job['cmd']) {
+ case 'install':
+ $packages = $this->pool->whatProvides($packageName, $constraint);
+ if (!$packages) {
+ return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint);
+ }
- $filtered = array();
- $byMajor = array();
- foreach ($versions as $version => $pretty) {
- if (0 === stripos($version, 'dev-')) {
- $byMajor['dev'][] = $pretty;
- } else {
- $byMajor[preg_replace('{^(\d+)\..*}', '$1', $version)][] = $pretty;
- }
+ return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.';
+ case 'update':
+ return 'Update request for '.$packageName.$this->constraintToText($constraint).'.';
+ case 'remove':
+ return 'Removal request for '.$packageName.$this->constraintToText($constraint).'';
}
- foreach ($byMajor as $majorVersion => $versionsForMajor) {
- $maxVersions = $majorVersion === 'dev' ? $maxDev : $max;
- if (count($versionsForMajor) > $maxVersions) {
- // output only 1st and last versions
- $filtered[] = $versionsForMajor[0];
- $filtered[] = '...';
- $filtered[] = $versionsForMajor[count($versionsForMajor) - 1];
- } else {
- $filtered = array_merge($filtered, $versionsForMajor);
- }
- }
-
- return $filtered;
- }
- private static function hasMultipleNames(array $packages)
- {
- $name = null;
- foreach ($packages as $package) {
- if ($name === null || $name === $package->getName()) {
- $name = $package->getName();
- } else {
- return true;
- }
+ if (isset($constraint)) {
+ $packages = $this->pool->whatProvides($packageName, $constraint);
+ } else {
+ $packages = array();
}
- return false;
+ return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])';
}
- private static function computeCheckForLowerPrioRepo($isVerbose, $packageName, $constraint, array $higherRepoPackages, array $allReposPackages, $reason)
+ protected function getPackageList($packages)
{
- $nextRepoPackages = array();
- $nextRepo = null;
-
- foreach ($allReposPackages as $package) {
- if ($nextRepo === null || $nextRepo === $package->getRepository()) {
- $nextRepoPackages[] = $package;
- $nextRepo = $package->getRepository();
- } else {
- break;
- }
- }
-
- if ($higherRepoPackages) {
- $topPackage = reset($higherRepoPackages);
- if ($topPackage instanceof RootPackageInterface) {
- return array(
- "- Root composer.json requires $packageName".self::constraintToText($constraint).', it is ',
- 'satisfiable by '.self::getPackageList($nextRepoPackages, $isVerbose).' from '.$nextRepo->getRepoName().' but '.$topPackage->getPrettyName().' is the root package and cannot be modified. See https://getcomposer.org/dep-on-root for details and assistance.',
- );
- }
+ $prepared = array();
+ foreach ($packages as $package) {
+ $prepared[$package->getName()]['name'] = $package->getPrettyName();
+ $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
}
-
- if ($nextRepo instanceof LockArrayRepository) {
- $singular = count($higherRepoPackages) === 1;
-
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', it is ',
- 'found '.self::getPackageList($nextRepoPackages, $isVerbose).' in the lock file and '.self::getPackageList($higherRepoPackages, $isVerbose).' from '.reset($higherRepoPackages)->getRepository()->getRepoName().' but ' . ($singular ? 'it does' : 'these do') . ' not match your '.$reason.' and ' . ($singular ? 'is' : 'are') . ' therefore not installable. Make sure you either fix the '.$reason.' or avoid updating this package to keep the one from the lock file.', );
+ foreach ($prepared as $name => $package) {
+ $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
}
- return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', it is ', 'satisfiable by '.self::getPackageList($nextRepoPackages, $isVerbose).' from '.$nextRepo->getRepoName().' but '.self::getPackageList($higherRepoPackages, $isVerbose).' from '.reset($higherRepoPackages)->getRepository()->getRepoName().' has higher repository priority. The packages with higher priority do not match your '.$reason.' and are therefore not installable. See https://getcomposer.org/repoprio for details and assistance.');
+ return implode(', ', $prepared);
}
/**
- * Turns a constraint into text usable in a sentence describing a request
+ * Turns a constraint into text usable in a sentence describing a job
*
- * @param ?ConstraintInterface $constraint
+ * @param \Composer\Semver\Constraint\ConstraintInterface $constraint
* @return string
*/
- protected static function constraintToText($constraint)
+ protected function constraintToText($constraint)
{
return $constraint ? ' '.$constraint->getPrettyString() : '';
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Request.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Request.php
index 3514bd4c8..85dc9c4d0 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Request.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Request.php
@@ -12,194 +12,67 @@
namespace Composer\DependencyResolver;
-use Composer\Package\Package;
-use Composer\Package\PackageInterface;
-use Composer\Repository\LockArrayRepository;
use Composer\Semver\Constraint\ConstraintInterface;
-use Composer\Semver\Constraint\MatchAllConstraint;
/**
* @author Nils Adermann
*/
class Request
{
- /**
- * Identifies a partial update for listed packages only, all dependencies will remain at locked versions
- */
- const UPDATE_ONLY_LISTED = 0;
-
- /**
- * Identifies a partial update for listed packages and recursively all their dependencies, however dependencies
- * also directly required by the root composer.json and their dependencies will remain at the locked version.
- */
- const UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE = 1;
-
- /**
- * Identifies a partial update for listed packages and recursively all their dependencies, even dependencies
- * also directly required by the root composer.json will be updated.
- */
- const UPDATE_LISTED_WITH_TRANSITIVE_DEPS = 2;
+ protected $jobs;
- /** @var ?LockArrayRepository */
- protected $lockedRepository;
- /** @var array */
- protected $requires = array();
- /** @var array */
- protected $fixedPackages = array();
- /** @var array */
- protected $lockedPackages = array();
- /** @var array */
- protected $fixedLockedPackages = array();
- /** @var string[] */
- protected $updateAllowList = array();
- /** @var false|self::UPDATE_* */
- protected $updateAllowTransitiveDependencies = false;
-
- public function __construct(LockArrayRepository $lockedRepository = null)
+ public function __construct()
{
- $this->lockedRepository = $lockedRepository;
+ $this->jobs = array();
}
- public function requireName($packageName, ConstraintInterface $constraint = null)
+ public function install($packageName, ConstraintInterface $constraint = null)
{
- $packageName = strtolower($packageName);
-
- if ($constraint === null) {
- $constraint = new MatchAllConstraint();
- }
- if (isset($this->requires[$packageName])) {
- throw new \LogicException('Overwriting requires seems like a bug ('.$packageName.' '.$this->requires[$packageName]->getPrettyString().' => '.$constraint->getPrettyString().', check why it is happening, might be a root alias');
- }
- $this->requires[$packageName] = $constraint;
+ $this->addJob($packageName, 'install', $constraint);
}
- /**
- * Mark a package as currently present and having to remain installed
- *
- * This is used for platform packages which cannot be modified by Composer. A rule enforcing their installation is
- * generated for dependency resolution. Partial updates with dependencies cannot in any way modify these packages.
- */
- public function fixPackage(PackageInterface $package)
+ public function update($packageName, ConstraintInterface $constraint = null)
{
- $this->fixedPackages[spl_object_hash($package)] = $package;
+ $this->addJob($packageName, 'update', $constraint);
}
- /**
- * Mark a package as locked to a specific version but removable
- *
- * This is used for lock file packages which need to be treated similar to fixed packages by the pool builder in
- * that by default they should really only have the currently present version loaded and no remote alternatives.
- *
- * However unlike fixed packages there will not be a special rule enforcing their installation for the solver, so
- * if nothing requires these packages they will be removed. Additionally in a partial update these packages can be
- * unlocked, meaning other versions can be installed if explicitly requested as part of the update.
- */
- public function lockPackage(PackageInterface $package)
+ public function remove($packageName, ConstraintInterface $constraint = null)
{
- $this->lockedPackages[spl_object_hash($package)] = $package;
+ $this->addJob($packageName, 'remove', $constraint);
}
/**
- * Marks a locked package fixed. So it's treated irremovable like a platform package.
+ * Mark an existing package as being installed and having to remain installed
+ *
+ * These jobs will not be tempered with by the solver
*
- * This is necessary for the composer install step which verifies the lock file integrity and should not allow
- * removal of any packages. At the same time lock packages there cannot simply be marked fixed, as error reporting
- * would then report them as platform packages, so this still marks them as locked packages at the same time.
+ * @param string $packageName
+ * @param ConstraintInterface|null $constraint
*/
- public function fixLockedPackage(PackageInterface $package)
- {
- $this->fixedPackages[spl_object_hash($package)] = $package;
- $this->fixedLockedPackages[spl_object_hash($package)] = $package;
- }
-
- public function unlockPackage(PackageInterface $package)
+ public function fix($packageName, ConstraintInterface $constraint = null)
{
- unset($this->lockedPackages[spl_object_hash($package)]);
+ $this->addJob($packageName, 'install', $constraint, true);
}
- public function setUpdateAllowList($updateAllowList, $updateAllowTransitiveDependencies)
+ protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
{
- $this->updateAllowList = $updateAllowList;
- $this->updateAllowTransitiveDependencies = $updateAllowTransitiveDependencies;
- }
-
- public function getUpdateAllowList()
- {
- return $this->updateAllowList;
- }
-
- public function getUpdateAllowTransitiveDependencies()
- {
- return $this->updateAllowTransitiveDependencies !== self::UPDATE_ONLY_LISTED;
- }
-
- public function getUpdateAllowTransitiveRootDependencies()
- {
- return $this->updateAllowTransitiveDependencies === self::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
- }
-
- public function getRequires()
- {
- return $this->requires;
- }
-
- public function getFixedPackages()
- {
- return $this->fixedPackages;
- }
-
- public function isFixedPackage(PackageInterface $package)
- {
- return isset($this->fixedPackages[spl_object_hash($package)]);
- }
-
- public function getLockedPackages()
- {
- return $this->lockedPackages;
- }
-
- public function isLockedPackage(PackageInterface $package)
- {
- return isset($this->lockedPackages[spl_object_hash($package)]) || isset($this->fixedLockedPackages[spl_object_hash($package)]);
- }
-
- public function getFixedOrLockedPackages()
- {
- return array_merge($this->fixedPackages, $this->lockedPackages);
- }
-
- // TODO look into removing the packageIds option, the only place true is used is for the installed map in the solver problems
- // some locked packages may not be in the pool so they have a package->id of -1
- public function getPresentMap($packageIds = false)
- {
- $presentMap = array();
-
- if ($this->lockedRepository) {
- foreach ($this->lockedRepository->getPackages() as $package) {
- $presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
- }
- }
-
- foreach ($this->fixedPackages as $package) {
- $presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
- }
+ $packageName = strtolower($packageName);
- return $presentMap;
+ $this->jobs[] = array(
+ 'cmd' => $cmd,
+ 'packageName' => $packageName,
+ 'constraint' => $constraint,
+ 'fixed' => $fixed,
+ );
}
- public function getFixedPackagesMap()
+ public function updateAll()
{
- $fixedPackagesMap = array();
-
- foreach ($this->fixedPackages as $package) {
- $fixedPackagesMap[$package->getId()] = $package;
- }
-
- return $fixedPackagesMap;
+ $this->jobs[] = array('cmd' => 'update-all');
}
- public function getLockedRepository()
+ public function getJobs()
{
- return $this->lockedRepository;
+ return $this->jobs;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule.php
index edc486496..82c9c499c 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule.php
@@ -12,57 +12,51 @@
namespace Composer\DependencyResolver;
+use Composer\Package\CompletePackage;
use Composer\Package\Link;
-use Composer\Package\BasePackage;
-use Composer\Package\AliasPackage;
-use Composer\Repository\RepositorySet;
-use Composer\Repository\PlatformRepository;
-use Composer\Package\Version\VersionParser;
-use Composer\Semver\Constraint\Constraint;
-use Composer\Semver\Constraint\ConstraintInterface;
+use Composer\Package\PackageInterface;
/**
* @author Nils Adermann
* @author Ruben Gonzalez
- * @phpstan-type ReasonData Link|BasePackage|string|int|array{packageName: string, constraint: ConstraintInterface}|array{package: BasePackage}
*/
abstract class Rule
{
- // reason constants and // their reason data contents
- const RULE_ROOT_REQUIRE = 2; // array{packageName: string, constraint: ConstraintInterface}
- const RULE_FIXED = 3; // array{package: BasePackage}
- const RULE_PACKAGE_CONFLICT = 6; // Link
- const RULE_PACKAGE_REQUIRES = 7; // Link
- const RULE_PACKAGE_SAME_NAME = 10; // string (package name)
- const RULE_LEARNED = 12; // int (rule id)
- const RULE_PACKAGE_ALIAS = 13; // BasePackage
- const RULE_PACKAGE_INVERSE_ALIAS = 14; // BasePackage
+ // reason constants
+ const RULE_INTERNAL_ALLOW_UPDATE = 1;
+ const RULE_JOB_INSTALL = 2;
+ const RULE_JOB_REMOVE = 3;
+ const RULE_PACKAGE_CONFLICT = 6;
+ const RULE_PACKAGE_REQUIRES = 7;
+ const RULE_PACKAGE_OBSOLETES = 8;
+ const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
+ const RULE_PACKAGE_SAME_NAME = 10;
+ const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
+ const RULE_LEARNED = 12;
+ const RULE_PACKAGE_ALIAS = 13;
// bitfield defs
const BITFIELD_TYPE = 0;
const BITFIELD_REASON = 8;
const BITFIELD_DISABLED = 16;
- /** @var int */
protected $bitfield;
- /** @var Request */
- protected $request;
- /**
- * @var Link|BasePackage|ConstraintInterface|string
- * @phpstan-var ReasonData
- */
+ protected $job;
protected $reasonData;
/**
- * @param self::RULE_* $reason A RULE_* constant describing the reason for generating this rule
- * @param Link|BasePackage|ConstraintInterface|string $reasonData
- *
- * @phpstan-param ReasonData $reasonData
+ * @param int $reason A RULE_* constant describing the reason for generating this rule
+ * @param Link|PackageInterface $reasonData
+ * @param array $job The job this rule was created from
*/
- public function __construct($reason, $reasonData)
+ public function __construct($reason, $reasonData, $job = null)
{
$this->reasonData = $reasonData;
+ if ($job) {
+ $this->job = $job;
+ }
+
$this->bitfield = (0 << self::BITFIELD_DISABLED) |
($reason << self::BITFIELD_REASON) |
(255 << self::BITFIELD_TYPE);
@@ -72,7 +66,10 @@ abstract public function getLiterals();
abstract public function getHash();
- abstract public function __toString();
+ public function getJob()
+ {
+ return $this->job;
+ }
abstract public function equals(Rule $rule);
@@ -86,26 +83,15 @@ public function getReasonData()
return $this->reasonData;
}
- /**
- * @return ?string
- */
public function getRequiredPackage()
{
- $reason = $this->getReason();
-
- if ($reason === self::RULE_ROOT_REQUIRE) {
- return $this->reasonData['packageName'];
- }
-
- if ($reason === self::RULE_FIXED) {
- return $this->reasonData['package']->getName();
+ if ($this->getReason() === self::RULE_JOB_INSTALL) {
+ return $this->reasonData;
}
- if ($reason === self::RULE_PACKAGE_REQUIRES) {
+ if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
return $this->reasonData->getTarget();
}
-
- return null;
}
public function setType($type)
@@ -140,257 +126,119 @@ public function isEnabled()
abstract public function isAssertion();
- public function isCausedByLock(RepositorySet $repositorySet, Request $request, Pool $pool)
+ public function getPrettyString(Pool $pool, array $installedMap = array())
{
- if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
- if (PlatformRepository::isPlatformPackage($this->reasonData->getTarget())) {
- return false;
- }
- if ($request->getLockedRepository()) {
- foreach ($request->getLockedRepository()->getPackages() as $package) {
- if ($package->getName() === $this->reasonData->getTarget()) {
- if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
- return true;
- }
- if (!$this->reasonData->getConstraint()->matches(new Constraint('=', $package->getVersion()))) {
- return true;
- }
- // required package was locked but has been unlocked and still matches
- if (!$request->isLockedPackage($package)) {
- return true;
- }
- break;
- }
- }
- }
- }
+ $literals = $this->getLiterals();
- if ($this->getReason() === self::RULE_ROOT_REQUIRE) {
- if (PlatformRepository::isPlatformPackage($this->reasonData['packageName'])) {
- return false;
- }
- if ($request->getLockedRepository()) {
- foreach ($request->getLockedRepository()->getPackages() as $package) {
- if ($package->getName() === $this->reasonData['packageName']) {
- if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
- return true;
- }
- if (!$this->reasonData['constraint']->matches(new Constraint('=', $package->getVersion()))) {
- return true;
- }
- break;
- }
- }
+ $ruleText = '';
+ foreach ($literals as $i => $literal) {
+ if ($i != 0) {
+ $ruleText .= '|';
}
+ $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
}
- return false;
- }
-
- public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, array $installedMap = array(), array $learnedPool = array())
- {
- $literals = $this->getLiterals();
-
switch ($this->getReason()) {
- case self::RULE_ROOT_REQUIRE:
- $packageName = $this->reasonData['packageName'];
- $constraint = $this->reasonData['constraint'];
-
- $packages = $pool->whatProvides($packageName, $constraint);
- if (!$packages) {
- return 'No package found to satisfy root composer.json require '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '');
- }
-
- $packagesNonAlias = array_values(array_filter($packages, function ($p) {
- return !($p instanceof AliasPackage);
- }));
- if (count($packagesNonAlias) === 1) {
- $package = $packagesNonAlias[0];
- if ($request->isLockedPackage($package)) {
- return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion()." and an update of this package was not requested.";
- }
- }
+ case self::RULE_INTERNAL_ALLOW_UPDATE:
+ return $ruleText;
- return 'Root composer.json requires '.$packageName.($constraint ? ' '.$constraint->getPrettyString() : '').' -> satisfiable by '.$this->formatPackagesUnique($pool, $packages, $isVerbose).'.';
+ case self::RULE_JOB_INSTALL:
+ return "Install command rule ($ruleText)";
- case self::RULE_FIXED:
- $package = $this->deduplicateDefaultBranchAlias($this->reasonData['package']);
-
- if ($request->isLockedPackage($package)) {
- return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion().' and an update of this package was not requested.';
- }
-
- return $package->getPrettyName().' is present at version '.$package->getPrettyVersion() . ' and cannot be modified by Composer';
+ case self::RULE_JOB_REMOVE:
+ return "Remove command rule ($ruleText)";
case self::RULE_PACKAGE_CONFLICT:
- $package1 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0]));
- $package2 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1]));
-
- $conflictTarget = $package1->getPrettyString();
- if ($reasonData = $this->getReasonData()) {
- // swap literals if they are not in the right order with package2 being the conflicter
- if ($reasonData->getSource() === $package1->getName()) {
- list($package2, $package1) = array($package1, $package2);
- }
-
- // if the conflict is not directly against the package but something it provides/replaces,
- // we try to find that link to display a better message
- if ($reasonData->getTarget() !== $package1->getName()) {
- $provideType = null;
- $provided = null;
- foreach ($package1->getProvides() as $provide) {
- if ($provide->getTarget() === $reasonData->getTarget()) {
- $provideType = 'provides';
- $provided = $provide->getPrettyConstraint();
- break;
- }
- }
- foreach ($package1->getReplaces() as $replace) {
- if ($replace->getTarget() === $reasonData->getTarget()) {
- $provideType = 'replaces';
- $provided = $replace->getPrettyConstraint();
- break;
- }
- }
- if (null !== $provideType) {
- $conflictTarget = $reasonData->getTarget().' '.$reasonData->getPrettyConstraint().' ('.$package1->getPrettyString().' '.$provideType.' '.$reasonData->getTarget().' '.$provided.')';
- }
- }
- }
+ $package1 = $pool->literalToPackage($literals[0]);
+ $package2 = $pool->literalToPackage($literals[1]);
- return $package2->getPrettyString().' conflicts with '.$conflictTarget.'.';
+ return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
case self::RULE_PACKAGE_REQUIRES:
$sourceLiteral = array_shift($literals);
- $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
- /** @var Link */
- $reasonData = $this->reasonData;
+ $sourcePackage = $pool->literalToPackage($sourceLiteral);
$requires = array();
foreach ($literals as $literal) {
$requires[] = $pool->literalToPackage($literal);
}
- $text = $reasonData->getPrettyString($sourcePackage);
+ $text = $this->reasonData->getPrettyString($sourcePackage);
if ($requires) {
- $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose) . '.';
+ $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
} else {
- $targetName = $reasonData->getTarget();
+ $targetName = $this->reasonData->getTarget();
- $reason = Problem::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $targetName, $this->reasonData->getConstraint());
+ if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
+ // handle php/hhvm
+ if (defined('HHVM_VERSION')) {
+ return $text . ' -> your HHVM version does not satisfy that requirement.';
+ }
- return $text . ' -> ' . $reason[1];
- }
+ $packages = $pool->whatProvides($targetName);
+ $package = count($packages) ? current($packages) : phpversion();
- return $text;
+ if ($targetName === 'hhvm') {
+ if ($package instanceof CompletePackage) {
+ return $text . ' -> your HHVM version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
+ } else {
+ return $text . ' -> you are running this with PHP and not HHVM.';
+ }
+ }
- case self::RULE_PACKAGE_SAME_NAME:
- $packageNames = array();
- foreach ($literals as $literal) {
- $package = $pool->literalToPackage($literal);
- $packageNames[$package->getName()] = true;
- }
- $replacedName = $this->reasonData;
- if (count($packageNames) > 1) {
- $reason = null;
+ if (!($package instanceof CompletePackage)) {
+ return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
+ }
- if (!isset($packageNames[$replacedName])) {
- $reason = 'They '.(count($literals) == 2 ? 'both' : 'all').' replace '.$replacedName.' and thus cannot coexist.';
- } else {
- $replacerNames = $packageNames;
- unset($replacerNames[$replacedName]);
- $replacerNames = array_keys($replacerNames);
+ $extra = $package->getExtra();
- if (count($replacerNames) == 1) {
- $reason = $replacerNames[0] . ' replaces ';
+ if (!empty($extra['config.platform'])) {
+ $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
} else {
- $reason = '['.implode(', ', $replacerNames).'] replace ';
+ $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
}
- $reason .= $replacedName.' and thus cannot coexist with it.';
- }
- $installedPackages = array();
- $removablePackages = array();
- foreach ($literals as $literal) {
- if (isset($installedMap[abs($literal)])) {
- $installedPackages[] = $pool->literalToPackage($literal);
- } else {
- $removablePackages[] = $pool->literalToPackage($literal);
- }
+ return $text;
}
- if ($installedPackages && $removablePackages) {
- return $this->formatPackagesUnique($pool, $removablePackages, $isVerbose).' cannot be installed as that would require removing '.$this->formatPackagesUnique($pool, $installedPackages, $isVerbose).'. '.$reason;
- }
+ if (0 === strpos($targetName, 'ext-')) {
+ // handle php extensions
+ $ext = substr($targetName, 4);
+ $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
- return 'Only one of these can be installed: '.$this->formatPackagesUnique($pool, $literals, $isVerbose).'. '.$reason;
- }
+ return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
+ }
- return 'You can only install one version of a package, so only one of these can be installed: ' . $this->formatPackagesUnique($pool, $literals, $isVerbose) . '.';
- case self::RULE_LEARNED:
- /** @TODO currently still generates way too much output to be helpful, and in some cases can even lead to endless recursion */
- // if (isset($learnedPool[$this->reasonData])) {
- // echo $this->reasonData."\n";
- // $learnedString = ', learned rules:' . Problem::formatDeduplicatedRules($learnedPool[$this->reasonData], ' ', $repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool);
- // } else {
- // $learnedString = ' (reasoning unavailable)';
- // }
- $learnedString = ' (conflict analysis result)';
-
- if (count($literals) === 1) {
- $ruleText = $pool->literalToPrettyString($literals[0], $installedMap);
- } else {
- $groups = array();
- foreach ($literals as $literal) {
- $package = $pool->literalToPackage($literal);
- if (isset($installedMap[$package->id])) {
- $group = $literal > 0 ? 'keep' : 'remove';
- } else {
- $group = $literal > 0 ? 'install' : 'don\'t install';
- }
+ if (0 === strpos($targetName, 'lib-')) {
+ // handle linked libs
+ $lib = substr($targetName, 4);
- $groups[$group][] = $this->deduplicateDefaultBranchAlias($package);
- }
- $ruleTexts = array();
- foreach ($groups as $group => $packages) {
- $ruleTexts[] = $group . (count($packages) > 1 ? ' one of' : '').' ' . $this->formatPackagesUnique($pool, $packages, $isVerbose);
+ return $text . ' -> the requested linked library '.$lib.' has the wrong version installed or is missing from your system, make sure to have the extension providing it.';
}
- $ruleText = implode(' | ', $ruleTexts);
- }
-
- return 'Conclusion: '.$ruleText.$learnedString;
- case self::RULE_PACKAGE_ALIAS:
- $aliasPackage = $pool->literalToPackage($literals[0]);
+ if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
+ return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
+ }
- // avoid returning content like "9999999-dev is an alias of dev-master" as it is useless
- if ($aliasPackage->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
- return '';
+ return $text . ' -> no matching package found.';
}
- $package = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1]));
- return $aliasPackage->getPrettyString() .' is an alias of '.$package->getPrettyString().' and thus requires it to be installed too.';
- case self::RULE_PACKAGE_INVERSE_ALIAS:
- // inverse alias rules work the other way around than above
- $aliasPackage = $pool->literalToPackage($literals[1]);
-
- // avoid returning content like "9999999-dev is an alias of dev-master" as it is useless
- if ($aliasPackage->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
- return '';
- }
- $package = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0]));
+ return $text;
- return $aliasPackage->getPrettyString() .' is an alias of '.$package->getPrettyString().' and must be installed with it.';
+ case self::RULE_PACKAGE_OBSOLETES:
+ return $ruleText;
+ case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
+ return $ruleText;
+ case self::RULE_PACKAGE_SAME_NAME:
+ return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
+ case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
+ return $ruleText;
+ case self::RULE_LEARNED:
+ return 'Conclusion: '.$ruleText;
+ case self::RULE_PACKAGE_ALIAS:
+ return $ruleText;
default:
- $ruleText = '';
- foreach ($literals as $i => $literal) {
- if ($i != 0) {
- $ruleText .= '|';
- }
- $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
- }
-
return '('.$ruleText.')';
}
}
@@ -401,23 +249,20 @@ public function getPrettyString(RepositorySet $repositorySet, Request $request,
*
* @return string
*/
- protected function formatPackagesUnique($pool, array $packages, $isVerbose)
+ protected function formatPackagesUnique($pool, array $packages)
{
- foreach ($packages as $index => $package) {
- if (!\is_object($package)) {
- $packages[$index] = $pool->literalToPackage($package);
+ $prepared = array();
+ foreach ($packages as $package) {
+ if (!is_object($package)) {
+ $package = $pool->literalToPackage($package);
}
+ $prepared[$package->getName()]['name'] = $package->getPrettyName();
+ $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
}
-
- return Problem::getPackageList($packages, $isVerbose);
- }
-
- private function deduplicateDefaultBranchAlias(BasePackage $package)
- {
- if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
- $package = $package->getAliasOf();
+ foreach ($prepared as $name => $package) {
+ $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
}
- return $package;
+ return implode(', ', $prepared);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php
index 6a4c599ce..6bf47db34 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php
@@ -12,7 +12,7 @@
namespace Composer\DependencyResolver;
-use Composer\Package\BasePackage;
+use Composer\Package\PackageInterface;
use Composer\Package\Link;
/**
@@ -20,18 +20,19 @@
*/
class Rule2Literals extends Rule
{
- /** @var int */
protected $literal1;
- /** @var int */
protected $literal2;
/**
- * @param int $literal1
- * @param int $literal2
+ * @param int $literal1
+ * @param int $literal2
+ * @param int $reason A RULE_* constant describing the reason for generating this rule
+ * @param Link|PackageInterface $reasonData
+ * @param array $job The job this rule was created from
*/
- public function __construct($literal1, $literal2, $reason, $reasonData)
+ public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
{
- parent::__construct($reason, $reasonData);
+ parent::__construct($reason, $reasonData, $job);
if ($literal1 < $literal2) {
$this->literal1 = $literal1;
@@ -42,13 +43,11 @@ public function __construct($literal1, $literal2, $reason, $reasonData)
}
}
- /** @return int[] */
public function getLiterals()
{
return array($this->literal1, $this->literal2);
}
- /** @return string */
public function getHash()
{
return $this->literal1.','.$this->literal2;
@@ -78,7 +77,7 @@ public function equals(Rule $rule)
}
$literals = $rule->getLiterals();
- if (2 != \count($literals)) {
+ if (2 != count($literals)) {
return false;
}
@@ -93,7 +92,6 @@ public function equals(Rule $rule)
return true;
}
- /** @return false */
public function isAssertion()
{
return false;
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php
index ba9aeaee2..bf4de0d7c 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSet.php
@@ -12,48 +12,44 @@
namespace Composer\DependencyResolver;
-use Composer\Repository\RepositorySet;
-
/**
* @author Nils Adermann
- * @implements \IteratorAggregate
*/
class RuleSet implements \IteratorAggregate, \Countable
{
// highest priority => lowest number
const TYPE_PACKAGE = 0;
- const TYPE_REQUEST = 1;
+ const TYPE_JOB = 1;
const TYPE_LEARNED = 4;
/**
* READ-ONLY: Lookup table for rule id to rule object
*
- * @var array
+ * @var Rule[]
*/
- public $ruleById = array();
+ public $ruleById;
- /** @var array<255|0|1|4, string> */
protected static $types = array(
255 => 'UNKNOWN',
self::TYPE_PACKAGE => 'PACKAGE',
- self::TYPE_REQUEST => 'REQUEST',
+ self::TYPE_JOB => 'JOB',
self::TYPE_LEARNED => 'LEARNED',
);
- /** @var array */
protected $rules;
+ protected $nextRuleId;
- /** @var int */
- protected $nextRuleId = 0;
-
- /** @var array */
- protected $rulesByHash = array();
+ protected $rulesByHash;
public function __construct()
{
+ $this->nextRuleId = 0;
+
foreach ($this->getTypes() as $type) {
$this->rules[$type] = array();
}
+
+ $this->rulesByHash = array();
}
public function add(Rule $rule, $type)
@@ -67,7 +63,7 @@ public function add(Rule $rule, $type)
// Do not add if rule already exists
if (isset($this->rulesByHash[$hash])) {
$potentialDuplicates = $this->rulesByHash[$hash];
- if (\is_array($potentialDuplicates)) {
+ if (is_array($potentialDuplicates)) {
foreach ($potentialDuplicates as $potentialDuplicate) {
if ($rule->equals($potentialDuplicate)) {
return;
@@ -92,7 +88,7 @@ public function add(Rule $rule, $type)
if (!isset($this->rulesByHash[$hash])) {
$this->rulesByHash[$hash] = $rule;
- } elseif (\is_array($this->rulesByHash[$hash])) {
+ } elseif (is_array($this->rulesByHash[$hash])) {
$this->rulesByHash[$hash][] = $rule;
} else {
$originalRule = $this->rulesByHash[$hash];
@@ -100,7 +96,6 @@ public function add(Rule $rule, $type)
}
}
- #[\ReturnTypeWillChange]
public function count()
{
return $this->nextRuleId;
@@ -111,34 +106,23 @@ public function ruleById($id)
return $this->ruleById[$id];
}
- /** @return array */
public function getRules()
{
return $this->rules;
}
- /**
- * @return RuleSetIterator
- */
- #[\ReturnTypeWillChange]
public function getIterator()
{
return new RuleSetIterator($this->getRules());
}
- /**
- * @param self::TYPE_*|array $types
- * @return RuleSetIterator
- */
public function getIteratorFor($types)
{
- if (!\is_array($types)) {
+ if (!is_array($types)) {
$types = array($types);
}
$allRules = $this->getRules();
-
- /** @var array $rules */
$rules = array();
foreach ($types as $type) {
@@ -150,7 +134,7 @@ public function getIteratorFor($types)
public function getIteratorWithout($types)
{
- if (!\is_array($types)) {
+ if (!is_array($types)) {
$types = array($types);
}
@@ -163,7 +147,6 @@ public function getIteratorWithout($types)
return new RuleSetIterator($rules);
}
- /** @return array{0: 0, 1: 1, 2: 4} */
public function getTypes()
{
$types = self::$types;
@@ -172,13 +155,13 @@ public function getTypes()
return array_keys($types);
}
- public function getPrettyString(RepositorySet $repositorySet = null, Request $request = null, Pool $pool = null, $isVerbose = false)
+ public function getPrettyString(Pool $pool = null)
{
$string = "\n";
foreach ($this->rules as $type => $rules) {
$string .= str_pad(self::$types[$type], 8, ' ') . ": ";
foreach ($rules as $rule) {
- $string .= ($repositorySet && $request && $pool ? $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose) : $rule)."\n";
+ $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
}
$string .= "\n\n";
}
@@ -188,6 +171,6 @@ public function getPrettyString(RepositorySet $repositorySet = null, Request $re
public function __toString()
{
- return $this->getPrettyString();
+ return $this->getPrettyString(null);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php
index 245f1fdda..8638440bd 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php
@@ -12,33 +12,30 @@
namespace Composer\DependencyResolver;
-use Composer\Package\BasePackage;
-use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
+use Composer\Package\AliasPackage;
use Composer\Repository\PlatformRepository;
/**
* @author Nils Adermann
- * @phpstan-import-type ReasonData from Rule
*/
class RuleSetGenerator
{
- /** @var PolicyInterface */
protected $policy;
- /** @var Pool */
protected $pool;
- /** @var RuleSet */
protected $rules;
- /** @var array */
- protected $addedMap = array();
- /** @var array */
- protected $addedPackagesByNames = array();
+ protected $jobs;
+ protected $installedMap;
+ protected $allowListedMap;
+ protected $addedMap;
+ protected $conflictAddedMap;
+ protected $addedPackages;
+ protected $addedPackagesByNames;
public function __construct(PolicyInterface $policy, Pool $pool)
{
$this->policy = $policy;
$this->pool = $pool;
- $this->rules = new RuleSet;
}
/**
@@ -47,17 +44,15 @@ public function __construct(PolicyInterface $policy, Pool $pool)
* This rule is of the form (-A|B|C), where B and C are the providers of
* one requirement of the package A.
*
- * @param BasePackage $package The package with a requirement
- * @param array $providers The providers of the requirement
- * @param Rule::RULE_* $reason A RULE_* constant describing the
- * reason for generating this rule
- * @param mixed $reasonData Any data, e.g. the requirement name,
- * that goes with the reason
- * @return Rule|null The generated rule or null if tautological
- *
- * @phpstan-param ReasonData $reasonData
+ * @param PackageInterface $package The package with a requirement
+ * @param array $providers The providers of the requirement
+ * @param int $reason A RULE_* constant describing the
+ * reason for generating this rule
+ * @param mixed $reasonData Any data, e.g. the requirement name,
+ * that goes with the reason
+ * @return Rule|null The generated rule or null if tautological
*/
- protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData = null)
+ protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
{
$literals = array(-$package->id);
@@ -78,22 +73,36 @@ protected function createRequireRule(BasePackage $package, array $providers, $re
* The rule is (A|B|C) with A, B and C different packages. If the given
* set of packages is empty an impossible rule is generated.
*
- * @param BasePackage[] $packages The set of packages to choose from
- * @param Rule::RULE_* $reason A RULE_* constant describing the reason for
- * generating this rule
- * @param array $reasonData Additional data like the root require or fix request info
- * @return Rule The generated rule
- *
- * @phpstan-param ReasonData $reasonData
+ * @param array $packages The set of packages to choose from
+ * @param int $reason A RULE_* constant describing the reason for
+ * generating this rule
+ * @param array $job The job this rule was created from
+ * @return Rule The generated rule
*/
- protected function createInstallOneOfRule(array $packages, $reason, $reasonData)
+ protected function createInstallOneOfRule(array $packages, $reason, $job)
{
$literals = array();
foreach ($packages as $package) {
$literals[] = $package->id;
}
- return new GenericRule($literals, $reason, $reasonData);
+ return new GenericRule($literals, $reason, $job['packageName'], $job);
+ }
+
+ /**
+ * Creates a rule to remove a package
+ *
+ * The rule for a package A is (-A).
+ *
+ * @param PackageInterface $package The package to be removed
+ * @param int $reason A RULE_* constant describing the
+ * reason for generating this rule
+ * @param array $job The job this rule was created from
+ * @return Rule The generated rule
+ */
+ protected function createRemoveRule(PackageInterface $package, $reason, $job)
+ {
+ return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
}
/**
@@ -102,17 +111,15 @@ protected function createInstallOneOfRule(array $packages, $reason, $reasonData)
* The rule for conflicting packages A and B is (-A|-B). A is called the issuer
* and B the provider.
*
- * @param BasePackage $issuer The package declaring the conflict
- * @param BasePackage $provider The package causing the conflict
- * @param Rule::RULE_* $reason A RULE_* constant describing the
- * reason for generating this rule
- * @param mixed $reasonData Any data, e.g. the package name, that
- * goes with the reason
- * @return Rule|null The generated rule
- *
- * @phpstan-param ReasonData $reasonData
+ * @param PackageInterface $issuer The package declaring the conflict
+ * @param PackageInterface $provider The package causing the conflict
+ * @param int $reason A RULE_* constant describing the
+ * reason for generating this rule
+ * @param mixed $reasonData Any data, e.g. the package name, that
+ * goes with the reason
+ * @return Rule|null The generated rule
*/
- protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData = null)
+ protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
{
// ignore self conflict
if ($issuer === $provider) {
@@ -122,20 +129,6 @@ protected function createRule2Literals(BasePackage $issuer, BasePackage $provide
return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
}
- protected function createMultiConflictRule(array $packages, $reason, $reasonData = null)
- {
- $literals = array();
- foreach ($packages as $package) {
- $literals[] = -$package->id;
- }
-
- if (\count($literals) == 2) {
- return new Rule2Literals($literals[0], $literals[1], $reason, $reasonData);
- }
-
- return new MultiConflictRule($literals, $reason, $reasonData);
- }
-
/**
* Adds a rule unless it duplicates an existing one of any type
*
@@ -154,40 +147,71 @@ private function addRule($type, Rule $newRule = null)
$this->rules->add($newRule, $type);
}
- protected function addRulesForPackage(BasePackage $package, $ignorePlatformReqs)
+ protected function allowListFromPackage(PackageInterface $package)
+ {
+ // call original method for BC
+ $this->whitelistFromPackage($package);
+ }
+
+ /**
+ * @deprecated use whitelistFromPackage instead
+ */
+ protected function whitelistFromPackage(PackageInterface $package)
{
- /** @var \SplQueue */
$workQueue = new \SplQueue;
$workQueue->enqueue($package);
while (!$workQueue->isEmpty()) {
$package = $workQueue->dequeue();
- if (isset($this->addedMap[$package->id])) {
+ if (isset($this->allowListedMap[$package->id])) {
continue;
}
- $this->addedMap[$package->id] = $package;
+ $this->allowListedMap[$package->id] = true;
- if (!$package instanceof AliasPackage) {
- foreach ($package->getNames(false) as $name) {
- $this->addedPackagesByNames[$name][] = $package;
+ foreach ($package->getRequires() as $link) {
+ $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
+
+ foreach ($possibleRequires as $require) {
+ $workQueue->enqueue($require);
}
- } else {
- $workQueue->enqueue($package->getAliasOf());
- $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($package->getAliasOf()), Rule::RULE_PACKAGE_ALIAS, $package));
+ }
- // aliases must be installed with their main package, so create a rule the other way around as well
- $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package->getAliasOf(), array($package), Rule::RULE_PACKAGE_INVERSE_ALIAS, $package->getAliasOf()));
+ $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
- // if alias package has no self.version requires, its requirements do not
- // need to be added as the aliased package processing will take care of it
- if (!$package->hasSelfVersionRequires()) {
+ foreach ($obsoleteProviders as $provider) {
+ if ($provider === $package) {
continue;
}
+
+ if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
+ $workQueue->enqueue($provider);
+ }
+ }
+ }
+ }
+
+ protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
+ {
+ $workQueue = new \SplQueue;
+ $workQueue->enqueue($package);
+
+ while (!$workQueue->isEmpty()) {
+ /** @var PackageInterface $package */
+ $package = $workQueue->dequeue();
+ if (isset($this->addedMap[$package->id])) {
+ continue;
+ }
+
+ $this->addedMap[$package->id] = true;
+
+ $this->addedPackages[] = $package;
+ foreach ($package->getNames() as $name) {
+ $this->addedPackagesByNames[$name][] = $package;
}
foreach ($package->getRequires() as $link) {
- if ((true === $ignorePlatformReqs || (is_array($ignorePlatformReqs) && in_array($link->getTarget(), $ignorePlatformReqs, true))) && PlatformRepository::isPlatformPackage($link->getTarget())) {
+ if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
continue;
}
@@ -199,118 +223,172 @@ protected function addRulesForPackage(BasePackage $package, $ignorePlatformReqs)
$workQueue->enqueue($require);
}
}
+
+ $packageName = $package->getName();
+ $obsoleteProviders = $this->pool->whatProvides($packageName, null);
+
+ foreach ($obsoleteProviders as $provider) {
+ if ($provider === $package) {
+ continue;
+ }
+
+ if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
+ $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
+ } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
+ $reason = ($packageName == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
+ $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $package));
+ }
+ }
}
}
protected function addConflictRules($ignorePlatformReqs = false)
{
- /** @var BasePackage $package */
- foreach ($this->addedMap as $package) {
+ /** @var PackageInterface $package */
+ foreach ($this->addedPackages as $package) {
foreach ($package->getConflicts() as $link) {
- // even if conlict ends up being with an alias, there would be at least one actual package by this name
if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
continue;
}
- if ((true === $ignorePlatformReqs || (is_array($ignorePlatformReqs) && in_array($link->getTarget(), $ignorePlatformReqs, true))) && PlatformRepository::isPlatformPackage($link->getTarget())) {
+ if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
continue;
}
- $conflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
+ /** @var PackageInterface $possibleConflict */
+ foreach ($this->addedPackagesByNames[$link->getTarget()] as $possibleConflict) {
+ $conflictMatch = $this->pool->match($possibleConflict, $link->getTarget(), $link->getConstraint(), true);
- foreach ($conflicts as $conflict) {
- // define the conflict rule for regular packages, for alias packages it's only needed if the name
- // matches the conflict exactly, otherwise the name match is by provide/replace which means the
- // package which this is an alias of will conflict anyway, so no need to create additional rules
- if (!$conflict instanceof AliasPackage || $conflict->getName() === $link->getTarget()) {
- $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
+ if ($conflictMatch === Pool::MATCH || $conflictMatch === Pool::MATCH_REPLACE) {
+ $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $possibleConflict, Rule::RULE_PACKAGE_CONFLICT, $link));
}
+
}
}
- }
- foreach ($this->addedPackagesByNames as $name => $packages) {
- if (\count($packages) > 1) {
- $reason = Rule::RULE_PACKAGE_SAME_NAME;
- $this->addRule(RuleSet::TYPE_PACKAGE, $this->createMultiConflictRule($packages, $reason, $name));
- }
- }
- }
+ // check obsoletes and implicit obsoletes of a package
+ $isInstalled = isset($this->installedMap[$package->id]);
- protected function addRulesForRequest(Request $request, $ignorePlatformReqs)
- {
- foreach ($request->getFixedPackages() as $package) {
- if ($package->id == -1) {
- // fixed package was not added to the pool as it did not pass the stability requirements, this is fine
- if ($this->pool->isUnacceptableFixedOrLockedPackage($package)) {
+ foreach ($package->getReplaces() as $link) {
+ if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
continue;
}
- // otherwise, looks like a bug
- throw new \LogicException("Fixed package ".$package->getPrettyString()." was not added to solver pool.");
+ /** @var PackageInterface $possibleConflict */
+ foreach ($this->addedPackagesByNames[$link->getTarget()] as $provider) {
+ if ($provider === $package) {
+ continue;
+ }
+
+ if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
+ $reason = $isInstalled ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
+ $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
+ }
+ }
}
+ }
+ }
- $this->addRulesForPackage($package, $ignorePlatformReqs);
+ protected function obsoleteImpossibleForAlias($package, $provider)
+ {
+ $packageIsAlias = $package instanceof AliasPackage;
+ $providerIsAlias = $provider instanceof AliasPackage;
- $rule = $this->createInstallOneOfRule(array($package), Rule::RULE_FIXED, array(
- 'package' => $package,
- ));
- $this->addRule(RuleSet::TYPE_REQUEST, $rule);
- }
+ $impossible = (
+ ($packageIsAlias && $package->getAliasOf() === $provider) ||
+ ($providerIsAlias && $provider->getAliasOf() === $package) ||
+ ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
+ );
- foreach ($request->getRequires() as $packageName => $constraint) {
- if ((true === $ignorePlatformReqs || (is_array($ignorePlatformReqs) && in_array($packageName, $ignorePlatformReqs, true))) && PlatformRepository::isPlatformPackage($packageName)) {
- continue;
- }
+ return $impossible;
+ }
- $packages = $this->pool->whatProvides($packageName, $constraint);
- if ($packages) {
- foreach ($packages as $package) {
- $this->addRulesForPackage($package, $ignorePlatformReqs);
- }
+ protected function allowListFromJobs()
+ {
+ // call original method for BC
+ $this->whitelistFromJobs();
+ }
- $rule = $this->createInstallOneOfRule($packages, Rule::RULE_ROOT_REQUIRE, array(
- 'packageName' => $packageName,
- 'constraint' => $constraint,
- ));
- $this->addRule(RuleSet::TYPE_REQUEST, $rule);
+ /**
+ * @deprecated use allowListFromJobs instead
+ */
+ protected function whitelistFromJobs()
+ {
+ foreach ($this->jobs as $job) {
+ switch ($job['cmd']) {
+ case 'install':
+ $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
+ foreach ($packages as $package) {
+ $this->allowListFromPackage($package);
+ }
+ break;
}
}
}
- protected function addRulesForRootAliases($ignorePlatformReqs)
+ protected function addRulesForJobs($ignorePlatformReqs)
{
- foreach ($this->pool->getPackages() as $package) {
- // ensure that rules for root alias packages and aliases of packages which were loaded are also loaded
- // even if the alias itself isn't required, otherwise a package could be installed without its alias which
- // leads to unexpected behavior
- if (!isset($this->addedMap[$package->id]) &&
- $package instanceof AliasPackage &&
- ($package->isRootPackageAlias() || isset($this->addedMap[$package->getAliasOf()->id]))
- ) {
- $this->addRulesForPackage($package, $ignorePlatformReqs);
+ foreach ($this->jobs as $job) {
+ switch ($job['cmd']) {
+ case 'install':
+ if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
+ break;
+ }
+
+ $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
+ if ($packages) {
+ foreach ($packages as $package) {
+ if (!isset($this->installedMap[$package->id])) {
+ $this->addRulesForPackage($package, $ignorePlatformReqs);
+ }
+ }
+
+ $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
+ $this->addRule(RuleSet::TYPE_JOB, $rule);
+ }
+ break;
+ case 'remove':
+ // remove all packages with this name including uninstalled
+ // ones to make sure none of them are picked as replacements
+ $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
+ foreach ($packages as $package) {
+ $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
+ $this->addRule(RuleSet::TYPE_JOB, $rule);
+ }
+ break;
}
}
}
- /**
- * @param bool|array $ignorePlatformReqs
- */
- public function getRulesFor(Request $request, $ignorePlatformReqs = false)
+ public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
{
- $this->addRulesForRequest($request, $ignorePlatformReqs);
+ $this->jobs = $jobs;
+ $this->rules = new RuleSet;
+ $this->installedMap = $installedMap;
- $this->addRulesForRootAliases($ignorePlatformReqs);
+ $this->allowListedMap = array();
+ foreach ($this->installedMap as $package) {
+ $this->allowListFromPackage($package);
+ }
+ $this->allowListFromJobs();
- $this->addConflictRules($ignorePlatformReqs);
+ $this->pool->setAllowList($this->allowListedMap);
- // Remove references to packages
- $this->addedMap = $this->addedPackagesByNames = array();
+ $this->addedMap = array();
+ $this->conflictAddedMap = array();
+ $this->addedPackages = array();
+ $this->addedPackagesByNames = array();
+ foreach ($this->installedMap as $package) {
+ $this->addRulesForPackage($package, $ignorePlatformReqs);
+ }
- $rules = $this->rules;
+ $this->addRulesForJobs($ignorePlatformReqs);
- $this->rules = new RuleSet;
+ $this->addConflictRules($ignorePlatformReqs);
+
+ // Remove references to packages
+ $this->addedPackages = $this->addedPackagesByNames = null;
- return $rules;
+ return $this->rules;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php
index 2726253d2..8c048624f 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php
@@ -14,25 +14,16 @@
/**
* @author Nils Adermann
- * @implements \Iterator
*/
class RuleSetIterator implements \Iterator
{
- /** @var array */
protected $rules;
- /** @var array */
protected $types;
- /** @var int */
protected $currentOffset;
- /** @var RuleSet::TYPE_*|-1 */
protected $currentType;
- /** @var int */
protected $currentTypeOffset;
- /**
- * @param array $rules
- */
public function __construct(array $rules)
{
$this->rules = $rules;
@@ -42,19 +33,16 @@ public function __construct(array $rules)
$this->rewind();
}
- #[\ReturnTypeWillChange]
public function current()
{
return $this->rules[$this->currentType][$this->currentOffset];
}
- #[\ReturnTypeWillChange]
public function key()
{
return $this->currentType;
}
- #[\ReturnTypeWillChange]
public function next()
{
$this->currentOffset++;
@@ -63,7 +51,7 @@ public function next()
return;
}
- if ($this->currentOffset >= \count($this->rules[$this->currentType])) {
+ if ($this->currentOffset >= count($this->rules[$this->currentType])) {
$this->currentOffset = 0;
do {
@@ -75,11 +63,10 @@ public function next()
}
$this->currentType = $this->types[$this->currentTypeOffset];
- } while (isset($this->types[$this->currentTypeOffset]) && !\count($this->rules[$this->currentType]));
+ } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
}
}
- #[\ReturnTypeWillChange]
public function rewind()
{
$this->currentOffset = 0;
@@ -96,12 +83,12 @@ public function rewind()
}
$this->currentType = $this->types[$this->currentTypeOffset];
- } while (isset($this->types[$this->currentTypeOffset]) && !\count($this->rules[$this->currentType]));
+ } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
}
- #[\ReturnTypeWillChange]
public function valid()
{
- return isset($this->rules[$this->currentType], $this->rules[$this->currentType][$this->currentOffset]);
+ return isset($this->rules[$this->currentType])
+ && isset($this->rules[$this->currentType][$this->currentOffset]);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php
index 52795ea89..2fea0d6ee 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php
@@ -19,10 +19,11 @@
* method to set the internal iterator to a particular offset.
*
* @author Nils Adermann
- * @extends \SplDoublyLinkedList
*/
class RuleWatchChain extends \SplDoublyLinkedList
{
+ protected $offset = 0;
+
/**
* Moves the internal iterator to the specified offset
*
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php
index 76b6abb55..31a22414d 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php
@@ -24,7 +24,6 @@
*/
class RuleWatchGraph
{
- /** @var array */
protected $watchChains = array();
/**
@@ -45,22 +44,12 @@ public function insert(RuleWatchNode $node)
return;
}
- if (!$node->getRule() instanceof MultiConflictRule) {
- foreach (array($node->watch1, $node->watch2) as $literal) {
- if (!isset($this->watchChains[$literal])) {
- $this->watchChains[$literal] = new RuleWatchChain;
- }
-
- $this->watchChains[$literal]->unshift($node);
+ foreach (array($node->watch1, $node->watch2) as $literal) {
+ if (!isset($this->watchChains[$literal])) {
+ $this->watchChains[$literal] = new RuleWatchChain;
}
- } else {
- foreach ($node->getRule()->getLiterals() as $literal) {
- if (!isset($this->watchChains[$literal])) {
- $this->watchChains[$literal] = new RuleWatchChain;
- }
- $this->watchChains[$literal]->unshift($node);
- }
+ $this->watchChains[$literal]->unshift($node);
}
}
@@ -103,40 +92,28 @@ public function propagateLiteral($decidedLiteral, $level, $decisions)
$chain->rewind();
while ($chain->valid()) {
$node = $chain->current();
- if (!$node->getRule() instanceof MultiConflictRule) {
- $otherWatch = $node->getOtherWatch($literal);
+ $otherWatch = $node->getOtherWatch($literal);
- if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
- $ruleLiterals = $node->getRule()->getLiterals();
+ if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
+ $ruleLiterals = $node->getRule()->getLiterals();
- $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
- return $literal !== $ruleLiteral &&
- $otherWatch !== $ruleLiteral &&
- !$decisions->conflict($ruleLiteral);
- });
+ $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
+ return $literal !== $ruleLiteral &&
+ $otherWatch !== $ruleLiteral &&
+ !$decisions->conflict($ruleLiteral);
+ });
- if ($alternativeLiterals) {
- reset($alternativeLiterals);
- $this->moveWatch($literal, current($alternativeLiterals), $node);
- continue;
- }
-
- if ($decisions->conflict($otherWatch)) {
- return $node->getRule();
- }
-
- $decisions->decide($otherWatch, $level, $node->getRule());
+ if ($alternativeLiterals) {
+ reset($alternativeLiterals);
+ $this->moveWatch($literal, current($alternativeLiterals), $node);
+ continue;
}
- } else {
- foreach ($node->getRule()->getLiterals() as $otherLiteral) {
- if ($literal !== $otherLiteral && !$decisions->satisfy($otherLiteral)) {
- if ($decisions->conflict($otherLiteral)) {
- return $node->getRule();
- }
-
- $decisions->decide($otherLiteral, $level, $node->getRule());
- }
+
+ if ($decisions->conflict($otherWatch)) {
+ return $node->getRule();
}
+
+ $decisions->decide($otherWatch, $level, $node->getRule());
}
$chain->next();
@@ -151,10 +128,10 @@ public function propagateLiteral($decidedLiteral, $level, $decisions)
* The rule node's watched literals are updated accordingly.
*
* @param int $fromLiteral A literal the node used to watch
- * @param int $toLiteral A literal the node should watch now
- * @param RuleWatchNode $node The rule node to be moved
+ * @param int $toLiteral A literal the node should watch now
+ * @param RuleWatchNode $node The rule node to be moved
*/
- protected function moveWatch($fromLiteral, $toLiteral, RuleWatchNode $node)
+ protected function moveWatch($fromLiteral, $toLiteral, $node)
{
if (!isset($this->watchChains[$toLiteral])) {
$this->watchChains[$toLiteral] = new RuleWatchChain;
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php
index 24fccd8d3..eeaa54162 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php
@@ -21,12 +21,9 @@
*/
class RuleWatchNode
{
- /** @var int */
public $watch1;
- /** @var int */
public $watch2;
- /** @var Rule */
protected $rule;
/**
@@ -34,13 +31,13 @@ class RuleWatchNode
*
* @param Rule $rule The rule to wrap
*/
- public function __construct(Rule $rule)
+ public function __construct($rule)
{
$this->rule = $rule;
$literals = $rule->getLiterals();
- $literalCount = \count($literals);
+ $literalCount = count($literals);
$this->watch1 = $literalCount > 0 ? $literals[0] : 0;
$this->watch2 = $literalCount > 1 ? $literals[1] : 0;
}
@@ -58,7 +55,7 @@ public function watch2OnHighest(Decisions $decisions)
$literals = $this->rule->getLiterals();
// if there are only 2 elements, both are being watched anyway
- if (\count($literals) < 3 || $this->rule instanceof MultiConflictRule) {
+ if (count($literals) < 3) {
return;
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php
index 7454ea74e..a046a7a92 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php
@@ -13,7 +13,7 @@
namespace Composer\DependencyResolver;
use Composer\IO\IOInterface;
-use Composer\Package\PackageInterface;
+use Composer\Repository\RepositoryInterface;
use Composer\Repository\PlatformRepository;
/**
@@ -28,16 +28,23 @@ class Solver
protected $policy;
/** @var Pool */
protected $pool;
-
+ /** @var RepositoryInterface */
+ protected $installed;
/** @var RuleSet */
protected $rules;
+ /** @var RuleSetGenerator */
+ protected $ruleSetGenerator;
+ /** @var array */
+ protected $jobs;
+ /** @var int[] */
+ protected $updateMap = array();
/** @var RuleWatchGraph */
protected $watchGraph;
/** @var Decisions */
protected $decisions;
- /** @var PackageInterface[] */
- protected $fixedMap;
+ /** @var int[] */
+ protected $installedMap;
/** @var int */
protected $propagateIndex;
@@ -45,9 +52,9 @@ class Solver
protected $branches = array();
/** @var Problem[] */
protected $problems = array();
- /** @var array */
+ /** @var array */
protected $learnedPool = array();
- /** @var array */
+ /** @var array */
protected $learnedWhy = array();
/** @var bool */
@@ -57,15 +64,18 @@ class Solver
protected $io;
/**
- * @param PolicyInterface $policy
- * @param Pool $pool
- * @param IOInterface $io
+ * @param PolicyInterface $policy
+ * @param Pool $pool
+ * @param RepositoryInterface $installed
+ * @param IOInterface $io
*/
- public function __construct(PolicyInterface $policy, Pool $pool, IOInterface $io)
+ public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
{
$this->io = $io;
$this->policy = $policy;
$this->pool = $pool;
+ $this->installed = $installed;
+ $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
}
/**
@@ -73,21 +83,16 @@ public function __construct(PolicyInterface $policy, Pool $pool, IOInterface $io
*/
public function getRuleSetSize()
{
- return \count($this->rules);
- }
-
- public function getPool()
- {
- return $this->pool;
+ return count($this->rules);
}
// aka solver_makeruledecisions
private function makeAssertionRuleDecisions()
{
- $decisionStart = \count($this->decisions) - 1;
+ $decisionStart = count($this->decisions) - 1;
- $rulesCount = \count($this->rules);
+ $rulesCount = count($this->rules);
for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
$rule = $this->rules->ruleById[$ruleIndex];
@@ -116,23 +121,23 @@ private function makeAssertionRuleDecisions()
$conflict = $this->decisions->decisionRule($literal);
if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
- $problem = new Problem();
+ $problem = new Problem($this->pool);
$problem->addRule($rule);
$problem->addRule($conflict);
- $rule->disable();
+ $this->disableProblem($rule);
$this->problems[] = $problem;
continue;
}
- // conflict with another root require/fixed package
- $problem = new Problem();
+ // conflict with another job
+ $problem = new Problem($this->pool);
$problem->addRule($rule);
$problem->addRule($conflict);
- // push all of our rules (can only be root require/fixed package rules)
+ // push all of our rules (can only be job rules)
// asserting this literal on the problem stack
- foreach ($this->rules->getIteratorFor(RuleSet::TYPE_REQUEST) as $assertRule) {
+ foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
continue;
}
@@ -143,8 +148,9 @@ private function makeAssertionRuleDecisions()
if (abs($literal) !== abs($assertRuleLiteral)) {
continue;
}
+
$problem->addRule($assertRule);
- $assertRule->disable();
+ $this->disableProblem($assertRule);
}
$this->problems[] = $problem;
@@ -153,47 +159,63 @@ private function makeAssertionRuleDecisions()
}
}
- protected function setupFixedMap(Request $request)
+ protected function setupInstalledMap()
{
- $this->fixedMap = array();
- foreach ($request->getFixedPackages() as $package) {
- $this->fixedMap[$package->id] = $package;
+ $this->installedMap = array();
+ foreach ($this->installed->getPackages() as $package) {
+ $this->installedMap[$package->id] = $package;
}
}
/**
- * @param Request $request
- * @param bool|array $ignorePlatformReqs
+ * @param bool $ignorePlatformReqs
*/
- protected function checkForRootRequireProblems(Request $request, $ignorePlatformReqs)
+ protected function checkForRootRequireProblems($ignorePlatformReqs)
{
- foreach ($request->getRequires() as $packageName => $constraint) {
- if ((true === $ignorePlatformReqs || (is_array($ignorePlatformReqs) && in_array($packageName, $ignorePlatformReqs, true))) && PlatformRepository::isPlatformPackage($packageName)) {
- continue;
- }
+ foreach ($this->jobs as $job) {
+ switch ($job['cmd']) {
+ case 'update':
+ $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
+ foreach ($packages as $package) {
+ if (isset($this->installedMap[$package->id])) {
+ $this->updateMap[$package->id] = true;
+ }
+ }
+ break;
- if (!$this->pool->whatProvides($packageName, $constraint)) {
- $problem = new Problem();
- $problem->addRule(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => $packageName, 'constraint' => $constraint)));
- $this->problems[] = $problem;
+ case 'update-all':
+ foreach ($this->installedMap as $package) {
+ $this->updateMap[$package->id] = true;
+ }
+ break;
+
+ case 'install':
+ if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
+ break;
+ }
+
+ if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
+ $problem = new Problem($this->pool);
+ $problem->addRule(new GenericRule(array(), null, null, $job));
+ $this->problems[] = $problem;
+ }
+ break;
}
}
}
/**
- * @param Request $request
- * @param bool|array $ignorePlatformReqs
- * @return LockTransaction
+ * @param Request $request
+ * @param bool $ignorePlatformReqs
+ * @return array
*/
public function solve(Request $request, $ignorePlatformReqs = false)
{
- $this->setupFixedMap($request);
+ $this->jobs = $request->getJobs();
- $this->io->writeError('Generating rules', true, IOInterface::DEBUG);
- $ruleSetGenerator = new RuleSetGenerator($this->policy, $this->pool);
- $this->rules = $ruleSetGenerator->getRulesFor($request, $ignorePlatformReqs);
- unset($ruleSetGenerator);
- $this->checkForRootRequireProblems($request, $ignorePlatformReqs);
+ $this->setupInstalledMap();
+ $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
+ $this->checkForRootRequireProblems($ignorePlatformReqs);
$this->decisions = new Decisions($this->pool);
$this->watchGraph = new RuleWatchGraph;
@@ -201,20 +223,29 @@ public function solve(Request $request, $ignorePlatformReqs = false)
$this->watchGraph->insert(new RuleWatchNode($rule));
}
- /* make decisions based on root require/fix assertions */
+ /* make decisions based on job/update assertions */
$this->makeAssertionRuleDecisions();
$this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
$before = microtime(true);
- $this->runSat();
+ $this->runSat(true);
$this->io->writeError('', true, IOInterface::DEBUG);
$this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
+ // decide to remove everything that's installed and undecided
+ foreach ($this->installedMap as $packageId => $void) {
+ if ($this->decisions->undecided($packageId)) {
+ $this->decisions->decide(-$packageId, 1, null);
+ }
+ }
+
if ($this->problems) {
- throw new SolverProblemsException($this->problems, $this->learnedPool);
+ throw new SolverProblemsException($this->problems, $this->installedMap);
}
- return new LockTransaction($this->pool, $request->getPresentMap(), $request->getFixedPackagesMap(), $this->decisions);
+ $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
+
+ return $transaction->getOperations();
}
/**
@@ -268,10 +299,10 @@ private function revert($level)
}
$this->decisions->revertLast();
- $this->propagateIndex = \count($this->decisions);
+ $this->propagateIndex = count($this->decisions);
}
- while (!empty($this->branches) && $this->branches[\count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
+ while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
array_pop($this->branches);
}
}
@@ -291,10 +322,11 @@ private function revert($level)
*
* @param int $level
* @param string|int $literal
+ * @param bool $disableRules
* @param Rule $rule
* @return int
*/
- private function setPropagateLearn($level, $literal, Rule $rule)
+ private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
{
$level++;
@@ -308,7 +340,7 @@ private function setPropagateLearn($level, $literal, Rule $rule)
}
if ($level == 1) {
- return $this->analyzeUnsolvable($rule);
+ return $this->analyzeUnsolvable($rule, $disableRules);
}
// conflict
@@ -318,8 +350,7 @@ private function setPropagateLearn($level, $literal, Rule $rule)
throw new SolverBugException(
"Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
);
- }
- if (!$newRule) {
+ } elseif (!$newRule) {
throw new SolverBugException(
"No rule was learned from analyzing $rule at level $level."
);
@@ -346,22 +377,23 @@ private function setPropagateLearn($level, $literal, Rule $rule)
/**
* @param int $level
* @param array $decisionQueue
+ * @param bool $disableRules
* @param Rule $rule
* @return int
*/
- private function selectAndInstall($level, array $decisionQueue, Rule $rule)
+ private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
{
// choose best package to install from decisionQueue
- $literals = $this->policy->selectPreferredPackages($this->pool, $decisionQueue, $rule->getRequiredPackage());
+ $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
$selectedLiteral = array_shift($literals);
// if there are multiple candidates, then branch
- if (\count($literals)) {
+ if (count($literals)) {
$this->branches[] = array($literals, $level);
}
- return $this->setPropagateLearn($level, $selectedLiteral, $rule);
+ return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
}
/**
@@ -378,19 +410,14 @@ protected function analyze($level, Rule $rule)
$seen = array();
$learnedLiterals = array(null);
- $decisionId = \count($this->decisions);
+ $decisionId = count($this->decisions);
$this->learnedPool[] = array();
while (true) {
- $this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
+ $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
foreach ($rule->getLiterals() as $literal) {
- // multiconflictrule is really a bunch of rules in one, so some may not have finished propagating yet
- if ($rule instanceof MultiConflictRule && !$this->decisions->decided($literal)) {
- continue;
- }
-
// skip the one true literal
if ($this->decisions->satisfy($literal)) {
continue;
@@ -416,7 +443,6 @@ protected function analyze($level, Rule $rule)
}
}
}
- unset($literal);
$l1retry = true;
while ($l1retry) {
@@ -464,35 +490,6 @@ protected function analyze($level, Rule $rule)
// only level 1 marks left
$l1num++;
$l1retry = true;
- } else {
- $decision = $this->decisions->atOffset($decisionId);
- $rule = $decision[Decisions::DECISION_REASON];
-
- if ($rule instanceof MultiConflictRule) {
- // there is only ever exactly one positive decision in a multiconflict rule
- foreach ($rule->getLiterals() as $literal) {
- if (!isset($seen[abs($literal)]) && $this->decisions->satisfy(-$literal)) {
- $this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
- $l = $this->decisions->decisionLevel($literal);
- if (1 === $l) {
- $l1num++;
- } elseif ($level === $l) {
- $num++;
- } else {
- // not level1 or conflict level, add to new rule
- $learnedLiterals[] = $literal;
-
- if ($l > $ruleLevel) {
- $ruleLevel = $l;
- }
- }
- $seen[abs($literal)] = true;
- break;
- }
- }
-
- $l1retry = true;
- }
}
}
@@ -500,7 +497,7 @@ protected function analyze($level, Rule $rule)
$rule = $decision[Decisions::DECISION_REASON];
}
- $why = \count($this->learnedPool) - 1;
+ $why = count($this->learnedPool) - 1;
if (!$learnedLiterals[0]) {
throw new SolverBugException(
@@ -513,19 +510,19 @@ protected function analyze($level, Rule $rule)
return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
}
- private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule, array &$ruleSeen)
+ /**
+ * @param Problem $problem
+ * @param Rule $conflictRule
+ */
+ private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
{
- $why = spl_object_hash($conflictRule);
- $ruleSeen[$why] = true;
-
if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
+ $why = spl_object_hash($conflictRule);
$learnedWhy = $this->learnedWhy[$why];
$problemRules = $this->learnedPool[$learnedWhy];
foreach ($problemRules as $problemRule) {
- if (!isset($ruleSeen[spl_object_hash($problemRule)])) {
- $this->analyzeUnsolvableRule($problem, $problemRule, $ruleSeen);
- }
+ $this->analyzeUnsolvableRule($problem, $problemRule);
}
return;
@@ -542,16 +539,15 @@ private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule, arr
/**
* @param Rule $conflictRule
+ * @param bool $disableRules
* @return int
*/
- private function analyzeUnsolvable(Rule $conflictRule)
+ private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
{
- $problem = new Problem();
+ $problem = new Problem($this->pool);
$problem->addRule($conflictRule);
- $ruleSeen = array();
-
- $this->analyzeUnsolvableRule($problem, $conflictRule, $ruleSeen);
+ $this->analyzeUnsolvableRule($problem, $conflictRule);
$this->problems[] = $problem;
@@ -577,7 +573,7 @@ private function analyzeUnsolvable(Rule $conflictRule)
$why = $decision[Decisions::DECISION_REASON];
$problem->addRule($why);
- $this->analyzeUnsolvableRule($problem, $why, $ruleSeen);
+ $this->analyzeUnsolvableRule($problem, $why);
$literals = $why->getLiterals();
@@ -590,9 +586,52 @@ private function analyzeUnsolvable(Rule $conflictRule)
}
}
+ if ($disableRules) {
+ foreach ($this->problems[count($this->problems) - 1] as $reason) {
+ $this->disableProblem($reason['rule']);
+ }
+
+ $this->resetSolver();
+
+ return 1;
+ }
+
return 0;
}
+ /**
+ * @param Rule $why
+ */
+ private function disableProblem(Rule $why)
+ {
+ $job = $why->getJob();
+
+ if (!$job) {
+ $why->disable();
+
+ return;
+ }
+
+ // disable all rules of this job
+ foreach ($this->rules as $rule) {
+ /** @var Rule $rule */
+ if ($job === $rule->getJob()) {
+ $rule->disable();
+ }
+ }
+ }
+
+ private function resetSolver()
+ {
+ $this->decisions->reset();
+
+ $this->propagateIndex = 0;
+ $this->branches = array();
+
+ $this->enableDisableLearnedRules();
+ $this->makeAssertionRuleDecisions();
+ }
+
/**
* enable/disable learnt rules
*
@@ -622,20 +661,29 @@ private function enableDisableLearnedRules()
}
}
- private function runSat()
+ /**
+ * @param bool $disableRules
+ */
+ private function runSat($disableRules = true)
{
$this->propagateIndex = 0;
/*
* here's the main loop:
* 1) propagate new decisions (only needed once)
- * 2) fulfill root requires/fixed packages
+ * 2) fulfill jobs
* 3) fulfill all unresolved rules
* 4) minimalize solution if we had choices
* if we encounter a problem, we rewind to a safe level and restart
* with step 1
*/
+ $decisionQueue = array();
+ /**
+ * @todo this makes $disableRules always false; determine the rationale and possibly remove dead code?
+ */
+ $disableRules = array();
+
$level = 1;
$systemLevel = $level + 1;
@@ -643,7 +691,7 @@ private function runSat()
if (1 === $level) {
$conflictRule = $this->propagate($level);
if (null !== $conflictRule) {
- if ($this->analyzeUnsolvable($conflictRule)) {
+ if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
continue;
}
@@ -651,9 +699,9 @@ private function runSat()
}
}
- // handle root require/fixed package rules
+ // handle job rules
if ($level < $systemLevel) {
- $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_REQUEST);
+ $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
foreach ($iterator as $rule) {
if ($rule->isEnabled()) {
$decisionQueue = array();
@@ -669,22 +717,27 @@ private function runSat()
}
}
- if ($noneSatisfied && \count($decisionQueue)) {
- // if any of the options in the decision queue are fixed, only use those
- $prunedQueue = array();
- foreach ($decisionQueue as $literal) {
- if (isset($this->fixedMap[abs($literal)])) {
- $prunedQueue[] = $literal;
+ if ($noneSatisfied && count($decisionQueue)) {
+ // prune all update packages until installed version
+ // except for requested updates
+ if (count($this->installed) != count($this->updateMap)) {
+ $prunedQueue = array();
+ foreach ($decisionQueue as $literal) {
+ if (isset($this->installedMap[abs($literal)])) {
+ $prunedQueue[] = $literal;
+ if (isset($this->updateMap[abs($literal)])) {
+ $prunedQueue = $decisionQueue;
+ break;
+ }
+ }
}
- }
- if (!empty($prunedQueue)) {
$decisionQueue = $prunedQueue;
}
}
- if ($noneSatisfied && \count($decisionQueue)) {
+ if ($noneSatisfied && count($decisionQueue)) {
$oLevel = $level;
- $level = $this->selectAndInstall($level, $decisionQueue, $rule);
+ $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
if (0 === $level) {
return;
@@ -698,7 +751,7 @@ private function runSat()
$systemLevel = $level + 1;
- // root requires/fixed packages left
+ // jobs left
$iterator->next();
if ($iterator->valid()) {
continue;
@@ -709,7 +762,7 @@ private function runSat()
$systemLevel = $level;
}
- $rulesCount = \count($this->rules);
+ $rulesCount = count($this->rules);
$pass = 1;
$this->io->writeError('Looking at all rules.', true, IOInterface::DEBUG);
@@ -756,18 +809,18 @@ private function runSat()
}
// need to have at least 2 item to pick from
- if (\count($decisionQueue) < 2) {
+ if (count($decisionQueue) < 2) {
continue;
}
- $level = $this->selectAndInstall($level, $decisionQueue, $rule);
+ $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
if (0 === $level) {
return;
}
// something changed, so look at all rules again
- $rulesCount = \count($this->rules);
+ $rulesCount = count($this->rules);
$n = -1;
}
@@ -776,13 +829,13 @@ private function runSat()
}
// minimization step
- if (\count($this->branches)) {
+ if (count($this->branches)) {
$lastLiteral = null;
$lastLevel = null;
$lastBranchIndex = 0;
$lastBranchOffset = 0;
- for ($i = \count($this->branches) - 1; $i >= 0; $i--) {
+ for ($i = count($this->branches) - 1; $i >= 0; $i--) {
list($literals, $l) = $this->branches[$i];
foreach ($literals as $offset => $literal) {
@@ -803,7 +856,7 @@ private function runSat()
$why = $this->decisions->lastReason();
- $level = $this->setPropagateLearn($level, $lastLiteral, $why);
+ $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
if ($level == 0) {
return;
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php
index 93eab3e63..142895697 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php
@@ -13,79 +13,41 @@
namespace Composer\DependencyResolver;
use Composer\Util\IniHelper;
-use Composer\Repository\RepositorySet;
-use Composer\Package\PackageInterface;
/**
* @author Nils Adermann
*/
class SolverProblemsException extends \RuntimeException
{
- /** @var Problem[] */
protected $problems;
- /** @var array */
- protected $learnedPool;
-
- /**
- * @param Problem[] $problems
- * @param array $learnedPool
- */
- public function __construct(array $problems, array $learnedPool)
+ protected $installedMap;
+
+ public function __construct(array $problems, array $installedMap)
{
$this->problems = $problems;
- $this->learnedPool = $learnedPool;
+ $this->installedMap = $installedMap;
- parent::__construct('Failed resolving dependencies with '.count($problems).' problems, call getPrettyString to get formatted details', 2);
+ parent::__construct($this->createMessage(), 2);
}
- public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, $isDevExtraction = false)
+ protected function createMessage()
{
- $installedMap = $request->getPresentMap(true);
+ $text = "\n";
$hasExtensionProblems = false;
- $isCausedByLock = false;
-
- $problems = array();
- foreach ($this->problems as $problem) {
- $problems[] = $problem->getPrettyString($repositorySet, $request, $pool, $isVerbose, $installedMap, $this->learnedPool)."\n";
+ foreach ($this->problems as $i => $problem) {
+ $text .= " Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
$hasExtensionProblems = true;
}
-
- $isCausedByLock |= $problem->isCausedByLock($repositorySet, $request, $pool);
}
- $i = 1;
- $text = "\n";
- foreach (array_unique($problems) as $problem) {
- $text .= " Problem ".($i++).$problem;
- }
-
- $hints = array();
- if (!$isDevExtraction && (strpos($text, 'could not be found') || strpos($text, 'no matching package found'))) {
- $hints[] = "Potential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead for further common problems.";
+ if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
+ $text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead for further common problems.";
}
if ($hasExtensionProblems) {
- $hints[] = $this->createExtensionHint();
- }
-
- if ($isCausedByLock && !$isDevExtraction && !$request->getUpdateAllowTransitiveRootDependencies()) {
- $hints[] = "Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.";
- }
-
- if (strpos($text, 'found composer-plugin-api[2.0.0] but it does not match') && strpos($text, '- ocramius/package-versions')) {
- $hints[] = "ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4. \nIf you can not upgrade PHP you can require composer/package-versions-deprecated to resolve this with PHP 7.0+.";
- }
-
- if (!class_exists('PHPUnit\Framework\TestCase', false)) {
- if (strpos($text, 'found composer-plugin-api[2.0.0] but it does not match')) {
- $hints[] = "You are using Composer 2, which some of your plugins seem to be incompatible with. Make sure you update your plugins or report a plugin-issue to ask them to support Composer 2.";
- }
- }
-
- if ($hints) {
- $text .= "\n" . implode("\n\n", $hints);
+ $text .= $this->createExtensionHint();
}
return $text;
@@ -104,9 +66,9 @@ private function createExtensionHint()
return '';
}
- $text = "To enable extensions, verify that they are enabled in your .ini files:\n - ";
+ $text = "\n To enable extensions, verify that they are enabled in your .ini files:\n - ";
$text .= implode("\n - ", $paths);
- $text .= "\nYou can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
+ $text .= "\n You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
return $text;
}
@@ -114,9 +76,8 @@ private function createExtensionHint()
private function hasExtensionProblems(array $reasonSets)
{
foreach ($reasonSets as $reasonSet) {
- foreach ($reasonSet as $rule) {
- $required = $rule->getRequiredPackage();
- if (null !== $required && 0 === strpos($required, 'ext-')) {
+ foreach ($reasonSet as $reason) {
+ if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
return true;
}
}
diff --git a/app/vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php b/app/vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php
index 1cda16927..c8d3bbe53 100644
--- a/app/vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php
+++ b/app/vendor/composer/composer/src/Composer/DependencyResolver/Transaction.php
@@ -13,213 +13,161 @@
namespace Composer\DependencyResolver;
use Composer\Package\AliasPackage;
-use Composer\Package\Link;
-use Composer\Package\PackageInterface;
-use Composer\Repository\PlatformRepository;
-use Composer\DependencyResolver\Operation\OperationInterface;
/**
* @author Nils Adermann
- * @internal
*/
class Transaction
{
- /**
- * @var OperationInterface[]
- */
- protected $operations;
-
- /**
- * Packages present at the beginning of the transaction
- * @var PackageInterface[]
- */
- protected $presentPackages;
-
- /**
- * Package set resulting from this transaction
- * @var array
- */
- protected $resultPackageMap;
-
- /**
- * @var array
- */
- protected $resultPackagesByName = array();
-
- public function __construct($presentPackages, $resultPackages)
+ protected $policy;
+ protected $pool;
+ protected $installedMap;
+ protected $decisions;
+ protected $transaction;
+
+ public function __construct($policy, $pool, $installedMap, $decisions)
{
- $this->presentPackages = $presentPackages;
- $this->setResultPackageMaps($resultPackages);
- $this->operations = $this->calculateOperations();
+ $this->policy = $policy;
+ $this->pool = $pool;
+ $this->installedMap = $installedMap;
+ $this->decisions = $decisions;
+ $this->transaction = array();
}
- /** @return OperationInterface[] */
public function getOperations()
{
- return $this->operations;
- }
+ $installMeansUpdateMap = $this->findUpdates();
- private function setResultPackageMaps($resultPackages)
- {
- $packageSort = function (PackageInterface $a, PackageInterface $b) {
- // sort alias packages by the same name behind their non alias version
- if ($a->getName() == $b->getName()) {
- if ($a instanceof AliasPackage != $b instanceof AliasPackage) {
- return $a instanceof AliasPackage ? -1 : 1;
- }
- // if names are the same, compare version, e.g. to sort aliases reliably, actual order does not matter
- return strcmp($b->getVersion(), $a->getVersion());
+ $updateMap = array();
+ $installMap = array();
+ $uninstallMap = array();
+
+ foreach ($this->decisions as $i => $decision) {
+ $literal = $decision[Decisions::DECISION_LITERAL];
+ $reason = $decision[Decisions::DECISION_REASON];
+
+ $package = $this->pool->literalToPackage($literal);
+
+ // wanted & installed || !wanted & !installed
+ if (($literal > 0) == isset($this->installedMap[$package->id])) {
+ continue;
}
- return strcmp($b->getName(), $a->getName());
- };
+ if ($literal > 0) {
+ if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
+ $source = $installMeansUpdateMap[abs($literal)];
- $this->resultPackageMap = array();
- foreach ($resultPackages as $package) {
- $this->resultPackageMap[spl_object_hash($package)] = $package;
- foreach ($package->getNames() as $name) {
- $this->resultPackagesByName[$name][] = $package;
+ $updateMap[$package->id] = array(
+ 'package' => $package,
+ 'source' => $source,
+ 'reason' => $reason,
+ );
+
+ // avoid updates to one package from multiple origins
+ unset($installMeansUpdateMap[abs($literal)]);
+ $ignoreRemove[$source->id] = true;
+ } else {
+ $installMap[$package->id] = array(
+ 'package' => $package,
+ 'reason' => $reason,
+ );
+ }
}
}
- uasort($this->resultPackageMap, $packageSort);
- foreach ($this->resultPackagesByName as $name => $packages) {
- uasort($this->resultPackagesByName[$name], $packageSort);
+ foreach ($this->decisions as $i => $decision) {
+ $literal = $decision[Decisions::DECISION_LITERAL];
+ $reason = $decision[Decisions::DECISION_REASON];
+ $package = $this->pool->literalToPackage($literal);
+
+ if ($literal <= 0 &&
+ isset($this->installedMap[$package->id]) &&
+ !isset($ignoreRemove[$package->id])) {
+ $uninstallMap[$package->id] = array(
+ 'package' => $package,
+ 'reason' => $reason,
+ );
+ }
}
- }
- protected function calculateOperations()
- {
- $operations = array();
+ $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
- $presentPackageMap = array();
- $removeMap = array();
- $presentAliasMap = array();
- $removeAliasMap = array();
- foreach ($this->presentPackages as $package) {
- if ($package instanceof AliasPackage) {
- $presentAliasMap[$package->getName().'::'.$package->getVersion()] = $package;
- $removeAliasMap[$package->getName().'::'.$package->getVersion()] = $package;
- } else {
- $presentPackageMap[$package->getName()] = $package;
- $removeMap[$package->getName()] = $package;
- }
- }
+ return $this->transaction;
+ }
- $stack = $this->getRootPackages();
+ protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
+ {
+ $queue = array_map(
+ function ($operation) {
+ return $operation['package'];
+ },
+ $this->findRootPackages($installMap, $updateMap)
+ );
$visited = array();
- $processed = array();
- while (!empty($stack)) {
- $package = array_pop($stack);
+ while (!empty($queue)) {
+ $package = array_pop($queue);
+ $packageId = $package->id;
- if (isset($processed[spl_object_hash($package)])) {
- continue;
- }
+ if (!isset($visited[$packageId])) {
+ $queue[] = $package;
- if (!isset($visited[spl_object_hash($package)])) {
- $visited[spl_object_hash($package)] = true;
-
- $stack[] = $package;
if ($package instanceof AliasPackage) {
- $stack[] = $package->getAliasOf();
+ $queue[] = $package->getAliasOf();
} else {
foreach ($package->getRequires() as $link) {
- $possibleRequires = $this->getProvidersInResult($link);
+ $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
foreach ($possibleRequires as $require) {
- $stack[] = $require;
+ $queue[] = $require;
}
}
}
- } elseif (!isset($processed[spl_object_hash($package)])) {
- $processed[spl_object_hash($package)] = true;
- if ($package instanceof AliasPackage) {
- $aliasKey = $package->getName().'::'.$package->getVersion();
- if (isset($presentAliasMap[$aliasKey])) {
- unset($removeAliasMap[$aliasKey]);
- } else {
- $operations[] = new Operation\MarkAliasInstalledOperation($package);
- }
- } else {
- if (isset($presentPackageMap[$package->getName()])) {
- $source = $presentPackageMap[$package->getName()];
-
- // do we need to update?
- // TODO different for lock?
- if ($package->getVersion() != $presentPackageMap[$package->getName()]->getVersion() ||
- $package->getDistReference() !== $presentPackageMap[$package->getName()]->getDistReference() ||
- $package->getSourceReference() !== $presentPackageMap[$package->getName()]->getSourceReference()
- ) {
- $operations[] = new Operation\UpdateOperation($source, $package);
- }
- unset($removeMap[$package->getName()]);
- } else {
- $operations[] = new Operation\InstallOperation($package);
- unset($removeMap[$package->getName()]);
- }
+ $visited[$package->id] = true;
+ } else {
+ if (isset($installMap[$packageId])) {
+ $this->install(
+ $installMap[$packageId]['package'],
+ $installMap[$packageId]['reason']
+ );
+ unset($installMap[$packageId]);
+ }
+ if (isset($updateMap[$packageId])) {
+ $this->update(
+ $updateMap[$packageId]['source'],
+ $updateMap[$packageId]['package'],
+ $updateMap[$packageId]['reason']
+ );
+ unset($updateMap[$packageId]);
}
}
}
- foreach ($removeMap as $name => $package) {
- array_unshift($operations, new Operation\UninstallOperation($package));
- }
- foreach ($removeAliasMap as $nameVersion => $package) {
- $operations[] = new Operation\MarkAliasUninstalledOperation($package);
+ foreach ($uninstallMap as $uninstall) {
+ $this->uninstall($uninstall['package'], $uninstall['reason']);
}
-
- $operations = $this->movePluginsToFront($operations);
- // TODO fix this:
- // we have to do this again here even though the above stack code did it because moving plugins moves them before uninstalls
- $operations = $this->moveUninstallsToFront($operations);
-
- // TODO skip updates which don't update? is this needed? we shouldn't schedule this update in the first place?
- /*
- if ('update' === $opType) {
- $targetPackage = $operation->getTargetPackage();
- if ($targetPackage->isDev()) {
- $initialPackage = $operation->getInitialPackage();
- if ($targetPackage->getVersion() === $initialPackage->getVersion()
- && (!$targetPackage->getSourceReference() || $targetPackage->getSourceReference() === $initialPackage->getSourceReference())
- && (!$targetPackage->getDistReference() || $targetPackage->getDistReference() === $initialPackage->getDistReference())
- ) {
- $this->io->writeError(' - Skipping update of ' . $targetPackage->getPrettyName() . ' to the same reference-locked version', true, IOInterface::DEBUG);
- $this->io->writeError('', true, IOInterface::DEBUG);
-
- continue;
- }
- }
- }*/
-
- return $this->operations = $operations;
}
- /**
- * Determine which packages in the result are not required by any other packages in it.
- *
- * These serve as a starting point to enumerate packages in a topological order despite potential cycles.
- * If there are packages with a cycle on the top level the package with the lowest name gets picked
- *
- * @return array
- */
- protected function getRootPackages()
+ protected function findRootPackages($installMap, $updateMap)
{
- $roots = $this->resultPackageMap;
+ $packages = $installMap + $updateMap;
+ $roots = $packages;
- foreach ($this->resultPackageMap as $packageHash => $package) {
- if (!isset($roots[$packageHash])) {
+ foreach ($packages as $packageId => $operation) {
+ $package = $operation['package'];
+
+ if (!isset($roots[$packageId])) {
continue;
}
foreach ($package->getRequires() as $link) {
- $possibleRequires = $this->getProvidersInResult($link);
+ $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
foreach ($possibleRequires as $require) {
if ($require !== $package) {
- unset($roots[spl_object_hash($require)]);
+ unset($roots[$require->id]);
}
}
}
@@ -228,115 +176,69 @@ protected function getRootPackages()
return $roots;
}
- protected function getProvidersInResult(Link $link)
+ protected function findUpdates()
{
- if (!isset($this->resultPackagesByName[$link->getTarget()])) {
- return array();
- }
+ $installMeansUpdateMap = array();
- return $this->resultPackagesByName[$link->getTarget()];
- }
+ foreach ($this->decisions as $i => $decision) {
+ $literal = $decision[Decisions::DECISION_LITERAL];
+ $package = $this->pool->literalToPackage($literal);
- /**
- * Workaround: if your packages depend on plugins, we must be sure
- * that those are installed / updated first; else it would lead to packages
- * being installed multiple times in different folders, when running Composer
- * twice.
- *
- * While this does not fix the root-causes of https://github.com/composer/composer/issues/1147,
- * it at least fixes the symptoms and makes usage of composer possible (again)
- * in such scenarios.
- *
- * @param OperationInterface[] $operations
- * @return OperationInterface[] reordered operation list
- */
- private function movePluginsToFront(array $operations)
- {
- $dlModifyingPluginsNoDeps = array();
- $dlModifyingPluginsWithDeps = array();
- $dlModifyingPluginRequires = array();
- $pluginsNoDeps = array();
- $pluginsWithDeps = array();
- $pluginRequires = array();
-
- foreach (array_reverse($operations, true) as $idx => $op) {
- if ($op instanceof Operation\InstallOperation) {
- $package = $op->getPackage();
- } elseif ($op instanceof Operation\UpdateOperation) {
- $package = $op->getTargetPackage();
- } else {
+ if ($package instanceof AliasPackage) {
continue;
}
- $isDownloadsModifyingPlugin = $package->getType() === 'composer-plugin' && ($extra = $package->getExtra()) && isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === true;
+ // !wanted & installed
+ if ($literal <= 0 && isset($this->installedMap[$package->id])) {
+ $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
- // is this a downloads modifying plugin or a dependency of one?
- if ($isDownloadsModifyingPlugin || count(array_intersect($package->getNames(), $dlModifyingPluginRequires))) {
- // get the package's requires, but filter out any platform requirements
- $requires = array_filter(array_keys($package->getRequires()), function ($req) {
- return !PlatformRepository::isPlatformPackage($req);
- });
+ $literals = array($package->id);
- // is this a plugin with no meaningful dependencies?
- if ($isDownloadsModifyingPlugin && !count($requires)) {
- // plugins with no dependencies go to the very front
- array_unshift($dlModifyingPluginsNoDeps, $op);
- } else {
- // capture the requirements for this package so those packages will be moved up as well
- $dlModifyingPluginRequires = array_merge($dlModifyingPluginRequires, $requires);
- // move the operation to the front
- array_unshift($dlModifyingPluginsWithDeps, $op);
+ foreach ($updates as $update) {
+ $literals[] = $update->id;
}
- unset($operations[$idx]);
- continue;
+ foreach ($literals as $updateLiteral) {
+ if ($updateLiteral !== $literal) {
+ $installMeansUpdateMap[abs($updateLiteral)] = $package;
+ }
+ }
}
+ }
- // is this package a plugin?
- $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
+ return $installMeansUpdateMap;
+ }
- // is this a plugin or a dependency of a plugin?
- if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
- // get the package's requires, but filter out any platform requirements
- $requires = array_filter(array_keys($package->getRequires()), function ($req) {
- return !PlatformRepository::isPlatformPackage($req);
- });
+ protected function install($package, $reason)
+ {
+ if ($package instanceof AliasPackage) {
+ return $this->markAliasInstalled($package, $reason);
+ }
- // is this a plugin with no meaningful dependencies?
- if ($isPlugin && !count($requires)) {
- // plugins with no dependencies go to the very front
- array_unshift($pluginsNoDeps, $op);
- } else {
- // capture the requirements for this package so those packages will be moved up as well
- $pluginRequires = array_merge($pluginRequires, $requires);
- // move the operation to the front
- array_unshift($pluginsWithDeps, $op);
- }
+ $this->transaction[] = new Operation\InstallOperation($package, $reason);
+ }
- unset($operations[$idx]);
- }
+ protected function update($from, $to, $reason)
+ {
+ $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
+ }
+
+ protected function uninstall($package, $reason)
+ {
+ if ($package instanceof AliasPackage) {
+ return $this->markAliasUninstalled($package, $reason);
}
- return array_merge($dlModifyingPluginsNoDeps, $dlModifyingPluginsWithDeps, $pluginsNoDeps, $pluginsWithDeps, $operations);
+ $this->transaction[] = new Operation\UninstallOperation($package, $reason);
}
- /**
- * Removals of packages should be executed before installations in
- * case two packages resolve to the same path (due to custom installers)
- *
- * @param OperationInterface[] $operations
- * @return OperationInterface[] reordered operation list
- */
- private function moveUninstallsToFront(array $operations)
+ protected function markAliasInstalled($package, $reason)
{
- $uninstOps = array();
- foreach ($operations as $idx => $op) {
- if ($op instanceof Operation\UninstallOperation || $op instanceof Operation\MarkAliasUninstalledOperation) {
- $uninstOps[] = $op;
- unset($operations[$idx]);
- }
- }
+ $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
+ }
- return array_merge($uninstOps, $operations);
+ protected function markAliasUninstalled($package, $reason)
+ {
+ $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php
index f3e444d59..d041a7f88 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php
@@ -14,8 +14,7 @@
use Composer\Package\PackageInterface;
use Symfony\Component\Finder\Finder;
-use React\Promise\PromiseInterface;
-use Composer\DependencyResolver\Operation\InstallOperation;
+use Composer\IO\IOInterface;
/**
* Base downloader for archives
@@ -31,164 +30,79 @@ abstract class ArchiveDownloader extends FileDownloader
* @throws \RuntimeException
* @throws \UnexpectedValueException
*/
- public function install(PackageInterface $package, $path, $output = true)
+ public function download(PackageInterface $package, $path, $output = true)
{
- if ($output) {
- $this->io->writeError(" - " . InstallOperation::format($package) . $this->getInstallOperationAppendix($package, $path));
- }
-
- $vendorDir = $this->config->get('vendor-dir');
-
- // clean up the target directory, unless it contains the vendor dir, as the vendor dir contains
- // the archive to be extracted. This is the case when installing with create-project in the current directory
- // but in that case we ensure the directory is empty already in ProjectInstaller so no need to empty it here.
- if (false === strpos($this->filesystem->normalizePath($vendorDir), $this->filesystem->normalizePath($path.DIRECTORY_SEPARATOR))) {
- $this->filesystem->emptyDirectory($path);
- }
-
- do {
- $temporaryDir = $vendorDir.'/composer/'.substr(md5(uniqid('', true)), 0, 8);
- } while (is_dir($temporaryDir));
+ $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
+ $retries = 3;
+ while ($retries--) {
+ $fileName = parent::download($package, $path, $output);
- $this->addCleanupPath($package, $temporaryDir);
- // avoid cleaning up $path if installing in "." for eg create-project as we can not
- // delete the directory we are currently in on windows
- if (!is_dir($path) || realpath($path) !== getcwd()) {
- $this->addCleanupPath($package, $path);
- }
-
- $this->filesystem->ensureDirectoryExists($temporaryDir);
- $fileName = $this->getFileName($package, $path);
-
- $filesystem = $this->filesystem;
- $self = $this;
+ if ($output) {
+ $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
+ }
- $cleanup = function () use ($path, $filesystem, $temporaryDir, $package, $self) {
- // remove cache if the file was corrupted
- $self->clearLastCacheWrite($package);
+ try {
+ $this->filesystem->ensureDirectoryExists($temporaryDir);
+ try {
+ $this->extract($fileName, $temporaryDir);
+ } catch (\Exception $e) {
+ // remove cache if the file was corrupted
+ parent::clearLastCacheWrite($package);
+ throw $e;
+ }
- // clean up
- $filesystem->removeDirectory($temporaryDir);
- if (is_dir($path) && realpath($path) !== getcwd()) {
- $filesystem->removeDirectory($path);
- }
- $self->removeCleanupPath($package, $temporaryDir);
- $self->removeCleanupPath($package, realpath($path));
- };
-
- $promise = null;
- try {
- $promise = $this->extract($package, $fileName, $temporaryDir);
- } catch (\Exception $e) {
- $cleanup();
- throw $e;
- }
+ $this->filesystem->unlink($fileName);
- if (!$promise instanceof PromiseInterface) {
- $promise = \React\Promise\resolve();
- }
+ $contentDir = $this->getFolderContent($temporaryDir);
- return $promise->then(function () use ($self, $package, $filesystem, $fileName, $temporaryDir, $path) {
- $filesystem->unlink($fileName);
-
- /**
- * Returns the folder content, excluding .DS_Store
- *
- * @param string $dir Directory
- * @return \SplFileInfo[]
- */
- $getFolderContent = function ($dir) {
- $finder = Finder::create()
- ->ignoreVCS(false)
- ->ignoreDotFiles(false)
- ->notName('.DS_Store')
- ->depth(0)
- ->in($dir);
-
- return iterator_to_array($finder);
- };
- $renameRecursively = null;
- /**
- * Renames (and recursively merges if needed) a folder into another one
- *
- * For custom installers, where packages may share paths, and given Composer 2's parallelism, we need to make sure
- * that the source directory gets merged into the target one if the target exists. Otherwise rename() by default would
- * put the source into the target e.g. src/ => target/src/ (assuming target exists) instead of src/ => target/
- *
- * @param string $from Directory
- * @param string $to Directory
- * @return void
- */
- $renameRecursively = function ($from, $to) use ($filesystem, $getFolderContent, $package, &$renameRecursively) {
- $contentDir = $getFolderContent($from);
+ // only one dir in the archive, extract its contents out of it
+ if (1 === count($contentDir) && is_dir(reset($contentDir))) {
+ $contentDir = $this->getFolderContent((string) reset($contentDir));
+ }
// move files back out of the temp dir
foreach ($contentDir as $file) {
$file = (string) $file;
- if (is_dir($to . '/' . basename($file))) {
- if (!is_dir($file)) {
- throw new \RuntimeException('Installing '.$package.' would lead to overwriting the '.$to.'/'.basename($file).' directory with a file from the package, invalid operation.');
- }
- $renameRecursively($file, $to . '/' . basename($file));
- } else {
- $filesystem->rename($file, $to . '/' . basename($file));
- }
+ $this->filesystem->rename($file, $path . '/' . basename($file));
}
- };
- $renameAsOne = false;
- if (!file_exists($path)) {
- $renameAsOne = true;
- } elseif ($filesystem->isDirEmpty($path)) {
- try {
- if ($filesystem->removeDirectoryPhp($path)) {
- $renameAsOne = true;
- }
- } catch (\RuntimeException $e) {
- // ignore error, and simply do not renameAsOne
+ $this->filesystem->removeDirectory($temporaryDir);
+ if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
+ $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
}
- }
-
- $contentDir = $getFolderContent($temporaryDir);
- $singleDirAtTopLevel = 1 === count($contentDir) && is_dir(reset($contentDir));
-
- if ($renameAsOne) {
- // if the target $path is clear, we can rename the whole package in one go instead of looping over the contents
- if ($singleDirAtTopLevel) {
- $extractedDir = (string) reset($contentDir);
- } else {
- $extractedDir = $temporaryDir;
+ if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
+ $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
}
- $filesystem->rename($extractedDir, $path);
- } else {
- // only one dir in the archive, extract its contents out of it
- $from = $temporaryDir;
- if ($singleDirAtTopLevel) {
- $from = (string) reset($contentDir);
+ } catch (\Exception $e) {
+ // clean up
+ $this->filesystem->removeDirectory($path);
+ $this->filesystem->removeDirectory($temporaryDir);
+
+ // retry downloading if we have an invalid zip file
+ if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
+ $this->io->writeError('');
+ if ($this->io->isDebug()) {
+ $this->io->writeError(' Invalid zip file ('.$e->getMessage().'), retrying...');
+ } else {
+ $this->io->writeError(' Invalid zip file, retrying...');
+ }
+ usleep(500000);
+ continue;
}
- $renameRecursively($from, $path);
+ throw $e;
}
- $promise = $filesystem->removeDirectoryAsync($temporaryDir);
-
- return $promise->then(function () use ($self, $package, $path, $temporaryDir) {
- $self->removeCleanupPath($package, $temporaryDir);
- $self->removeCleanupPath($package, $path);
- });
- }, function ($e) use ($cleanup) {
- $cleanup();
-
- throw $e;
- });
+ break;
+ }
}
/**
- * {@inheritDoc}
+ * {@inheritdoc}
*/
- protected function getInstallOperationAppendix(PackageInterface $package, $path)
+ protected function getFileName(PackageInterface $package, $path)
{
- return ': Extracting archive';
+ return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
}
/**
@@ -198,7 +112,24 @@ protected function getInstallOperationAppendix(PackageInterface $package, $path)
* @param string $path Directory
*
* @throws \UnexpectedValueException If can not extract downloaded file to path
- * @return PromiseInterface|null
*/
- abstract protected function extract(PackageInterface $package, $file, $path);
+ abstract protected function extract($file, $path);
+
+ /**
+ * Returns the folder content, excluding dotfiles
+ *
+ * @param string $dir Directory
+ * @return \SplFileInfo[]
+ */
+ private function getFolderContent($dir)
+ {
+ $finder = Finder::create()
+ ->ignoreVCS(false)
+ ->ignoreDotFiles(false)
+ ->notName('.DS_Store')
+ ->depth(0)
+ ->in($dir);
+
+ return iterator_to_array($finder);
+ }
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/DownloadManager.php b/app/vendor/composer/composer/src/Composer/Downloader/DownloadManager.php
index 7616229cb..15c00a6e6 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/DownloadManager.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/DownloadManager.php
@@ -15,8 +15,6 @@
use Composer\Package\PackageInterface;
use Composer\IO\IOInterface;
use Composer\Util\Filesystem;
-use Composer\Exception\IrrecoverableDownloadException;
-use React\Promise\PromiseInterface;
/**
* Downloaders manager.
@@ -25,17 +23,11 @@
*/
class DownloadManager
{
- /** @var IOInterface */
private $io;
- /** @var bool */
private $preferDist = false;
- /** @var bool */
- private $preferSource;
- /** @var array */
+ private $preferSource = false;
private $packagePreferences = array();
- /** @var Filesystem */
private $filesystem;
- /** @var array */
private $downloaders = array();
/**
@@ -91,6 +83,22 @@ public function setPreferences(array $preferences)
return $this;
}
+ /**
+ * Sets whether to output download progress information for all registered
+ * downloaders
+ *
+ * @param bool $outputProgress
+ * @return DownloadManager
+ */
+ public function setOutputProgress($outputProgress)
+ {
+ foreach ($this->downloaders as $downloader) {
+ $downloader->setOutputProgress($outputProgress);
+ }
+
+ return $this;
+ }
+
/**
* Sets installer downloader for a specific installation type.
*
@@ -132,12 +140,12 @@ public function getDownloader($type)
* wrong type
* @return DownloaderInterface|null
*/
- public function getDownloaderForPackage(PackageInterface $package)
+ public function getDownloaderForInstalledPackage(PackageInterface $package)
{
$installationSource = $package->getInstallationSource();
if ('metapackage' === $package->getType()) {
- return null;
+ return;
}
if ('dist' === $installationSource) {
@@ -146,7 +154,7 @@ public function getDownloaderForPackage(PackageInterface $package)
$downloader = $this->getDownloader($package->getSourceType());
} else {
throw new \InvalidArgumentException(
- 'Package '.$package.' does not have an installation source set'
+ 'Package '.$package.' seems not been installed properly'
);
}
@@ -163,122 +171,64 @@ public function getDownloaderForPackage(PackageInterface $package)
return $downloader;
}
- public function getDownloaderType(DownloaderInterface $downloader)
- {
- return array_search($downloader, $this->downloaders);
- }
-
/**
* Downloads package into target dir.
*
- * @param PackageInterface $package package instance
- * @param string $targetDir target dir
- * @param PackageInterface|null $prevPackage previous package instance in case of updates
+ * @param PackageInterface $package package instance
+ * @param string $targetDir target dir
+ * @param bool $preferSource prefer installation from source
*
* @throws \InvalidArgumentException if package have no urls to download from
* @throws \RuntimeException
- * @return PromiseInterface
*/
- public function download(PackageInterface $package, $targetDir, PackageInterface $prevPackage = null)
+ public function download(PackageInterface $package, $targetDir, $preferSource = null)
{
- $targetDir = $this->normalizeTargetDir($targetDir);
- $this->filesystem->ensureDirectoryExists(dirname($targetDir));
-
- $sources = $this->getAvailableSources($package, $prevPackage);
-
- $io = $this->io;
- $self = $this;
+ $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
+ $sourceType = $package->getSourceType();
+ $distType = $package->getDistType();
- $download = function ($retry = false) use (&$sources, $io, $package, $self, $targetDir, &$download, $prevPackage) {
- $source = array_shift($sources);
- if ($retry) {
- $io->writeError(' Now trying to download from ' . $source . ' ');
- }
- $package->setInstallationSource($source);
+ $sources = array();
+ if ($sourceType) {
+ $sources[] = 'source';
+ }
+ if ($distType) {
+ $sources[] = 'dist';
+ }
- $downloader = $self->getDownloaderForPackage($package);
- if (!$downloader) {
- return \React\Promise\resolve();
- }
+ if (empty($sources)) {
+ throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
+ }
- $handleError = function ($e) use ($sources, $source, $package, $io, $download) {
- if ($e instanceof \RuntimeException && !$e instanceof IrrecoverableDownloadException) {
- if (!$sources) {
- throw $e;
- }
+ if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
+ $sources = array_reverse($sources);
+ }
- $io->writeError(
- ' Failed to download '.
- $package->getPrettyName().
- ' from ' . $source . ': '.
- $e->getMessage().' '
- );
+ $this->filesystem->ensureDirectoryExists($targetDir);
- return $download(true);
+ foreach ($sources as $i => $source) {
+ if (isset($e)) {
+ $this->io->writeError(' Now trying to download from ' . $source . ' ');
+ }
+ $package->setInstallationSource($source);
+ try {
+ $downloader = $this->getDownloaderForInstalledPackage($package);
+ if ($downloader) {
+ $downloader->download($package, $targetDir);
+ }
+ break;
+ } catch (\RuntimeException $e) {
+ if ($i === count($sources) - 1) {
+ throw $e;
}
- throw $e;
- };
-
- try {
- $result = $downloader->download($package, $targetDir, $prevPackage);
- } catch (\Exception $e) {
- return $handleError($e);
+ $this->io->writeError(
+ ' Failed to download '.
+ $package->getPrettyName().
+ ' from ' . $source . ': '.
+ $e->getMessage().' '
+ );
}
- if (!$result instanceof PromiseInterface) {
- return \React\Promise\resolve($result);
- }
-
- $res = $result->then(function ($res) {
- return $res;
- }, $handleError);
-
- return $res;
- };
-
- return $download();
- }
-
- /**
- * Prepares an operation execution
- *
- * @param string $type one of install/update/uninstall
- * @param PackageInterface $package package instance
- * @param string $targetDir target dir
- * @param PackageInterface|null $prevPackage previous package instance in case of updates
- *
- * @return PromiseInterface|null
- */
- public function prepare($type, PackageInterface $package, $targetDir, PackageInterface $prevPackage = null)
- {
- $targetDir = $this->normalizeTargetDir($targetDir);
- $downloader = $this->getDownloaderForPackage($package);
- if ($downloader) {
- return $downloader->prepare($type, $package, $targetDir, $prevPackage);
}
-
- return \React\Promise\resolve();
- }
-
- /**
- * Installs package into target dir.
- *
- * @param PackageInterface $package package instance
- * @param string $targetDir target dir
- *
- * @throws \InvalidArgumentException if package have no urls to download from
- * @throws \RuntimeException
- * @return PromiseInterface|null
- */
- public function install(PackageInterface $package, $targetDir)
- {
- $targetDir = $this->normalizeTargetDir($targetDir);
- $downloader = $this->getDownloaderForPackage($package);
- if ($downloader) {
- return $downloader->install($package, $targetDir);
- }
-
- return \React\Promise\resolve();
}
/**
@@ -289,52 +239,51 @@ public function install(PackageInterface $package, $targetDir)
* @param string $targetDir target dir
*
* @throws \InvalidArgumentException if initial package is not installed
- * @return PromiseInterface|null
*/
public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
{
- $targetDir = $this->normalizeTargetDir($targetDir);
- $downloader = $this->getDownloaderForPackage($target);
- $initialDownloader = $this->getDownloaderForPackage($initial);
+ $downloader = $this->getDownloaderForInstalledPackage($initial);
+ if (!$downloader) {
+ return;
+ }
- // no downloaders present means update from metapackage to metapackage, nothing to do
- if (!$initialDownloader && !$downloader) {
- return \React\Promise\resolve();
+ $installationSource = $initial->getInstallationSource();
+
+ if ('dist' === $installationSource) {
+ $initialType = $initial->getDistType();
+ $targetType = $target->getDistType();
+ } else {
+ $initialType = $initial->getSourceType();
+ $targetType = $target->getSourceType();
}
- // if we have a downloader present before, but not after, the package became a metapackage and its files should be removed
- if (!$downloader) {
- return $initialDownloader->remove($initial, $targetDir);
+ // upgrading from a dist stable package to a dev package, force source reinstall
+ if ($target->isDev() && 'dist' === $installationSource) {
+ $downloader->remove($initial, $targetDir);
+ $this->download($target, $targetDir);
+
+ return;
}
- $initialType = $this->getDownloaderType($initialDownloader);
- $targetType = $this->getDownloaderType($downloader);
if ($initialType === $targetType) {
+ $target->setInstallationSource($installationSource);
try {
- return $downloader->update($initial, $target, $targetDir);
+ $downloader->update($initial, $target, $targetDir);
+
+ return;
} catch (\RuntimeException $e) {
if (!$this->io->isInteractive()) {
throw $e;
}
$this->io->writeError(' Update failed ('.$e->getMessage().') ');
- if (!$this->io->askConfirmation(' Would you like to try reinstalling the package instead [yes ]? ')) {
+ if (!$this->io->askConfirmation(' Would you like to try reinstalling the package instead [yes ]? ', true)) {
throw $e;
}
}
}
- // if downloader type changed, or update failed and user asks for reinstall,
- // we wipe the dir and do a new install instead of updating it
- $promise = $initialDownloader->remove($initial, $targetDir);
- if ($promise) {
- $self = $this;
-
- return $promise->then(function ($res) use ($self, $target, $targetDir) {
- return $self->install($target, $targetDir);
- });
- }
-
- return $this->install($target, $targetDir);
+ $downloader->remove($initial, $targetDir);
+ $this->download($target, $targetDir, 'source' === $installationSource);
}
/**
@@ -342,39 +291,13 @@ public function update(PackageInterface $initial, PackageInterface $target, $tar
*
* @param PackageInterface $package package instance
* @param string $targetDir target dir
- *
- * @return PromiseInterface|null
*/
public function remove(PackageInterface $package, $targetDir)
{
- $targetDir = $this->normalizeTargetDir($targetDir);
- $downloader = $this->getDownloaderForPackage($package);
+ $downloader = $this->getDownloaderForInstalledPackage($package);
if ($downloader) {
- return $downloader->remove($package, $targetDir);
+ $downloader->remove($package, $targetDir);
}
-
- return \React\Promise\resolve();
- }
-
- /**
- * Cleans up a failed operation
- *
- * @param string $type one of install/update/uninstall
- * @param PackageInterface $package package instance
- * @param string $targetDir target dir
- * @param PackageInterface|null $prevPackage previous package instance in case of updates
- *
- * @return PromiseInterface|null
- */
- public function cleanup($type, PackageInterface $package, $targetDir, PackageInterface $prevPackage = null)
- {
- $targetDir = $this->normalizeTargetDir($targetDir);
- $downloader = $this->getDownloaderForPackage($package);
- if ($downloader) {
- return $downloader->cleanup($type, $package, $targetDir, $prevPackage);
- }
-
- return \React\Promise\resolve();
}
/**
@@ -399,65 +322,4 @@ protected function resolvePackageInstallPreference(PackageInterface $package)
return $package->isDev() ? 'source' : 'dist';
}
-
- /**
- * @return string[]
- * @phpstan-return array<'dist'|'source'>&non-empty-array
- */
- private function getAvailableSources(PackageInterface $package, PackageInterface $prevPackage = null)
- {
- $sourceType = $package->getSourceType();
- $distType = $package->getDistType();
-
- // add source before dist by default
- $sources = array();
- if ($sourceType) {
- $sources[] = 'source';
- }
- if ($distType) {
- $sources[] = 'dist';
- }
-
- if (empty($sources)) {
- throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
- }
-
- if (
- $prevPackage
- // if we are updating, we want to keep the same source as the previously installed package (if available in the new one)
- && in_array($prevPackage->getInstallationSource(), $sources, true)
- // unless the previous package was stable dist (by default) and the new package is dev, then we allow the new default to take over
- && !(!$prevPackage->isDev() && $prevPackage->getInstallationSource() === 'dist' && $package->isDev())
- ) {
- $prevSource = $prevPackage->getInstallationSource();
- usort($sources, function ($a, $b) use ($prevSource) {
- return $a === $prevSource ? -1 : 1;
- });
-
- return $sources;
- }
-
- // reverse sources in case dist is the preferred source for this package
- if (!$this->preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
- $sources = array_reverse($sources);
- }
-
- return $sources;
- }
-
- /**
- * Downloaders expect a /path/to/dir without trailing slash
- *
- * If any Installer provides a path with a trailing slash, this can cause bugs so make sure we remove them
- *
- * @return string
- */
- private function normalizeTargetDir($dir)
- {
- if ($dir === '\\' || $dir === '/') {
- return $dir;
- }
-
- return rtrim($dir, '\\/');
- }
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/DownloaderInterface.php b/app/vendor/composer/composer/src/Composer/Downloader/DownloaderInterface.php
index ef2357958..713bf36dc 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/DownloaderInterface.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/DownloaderInterface.php
@@ -13,7 +13,6 @@
namespace Composer\Downloader;
use Composer\Package\PackageInterface;
-use React\Promise\PromiseInterface;
/**
* Downloader interface.
@@ -31,68 +30,35 @@ interface DownloaderInterface
public function getInstallationSource();
/**
- * This should do any network-related tasks to prepare for an upcoming install/update
+ * Downloads specific package into specific folder.
*
- * @return PromiseInterface|null
+ * @param PackageInterface $package package instance
+ * @param string $path download path
*/
- public function download(PackageInterface $package, $path, PackageInterface $prevPackage = null);
-
- /**
- * Do anything that needs to be done between all downloads have been completed and the actual operation is executed
- *
- * All packages get first downloaded, then all together prepared, then all together installed/updated/uninstalled. Therefore
- * for error recovery it is important to avoid failing during install/update/uninstall as much as possible, and risky things or
- * user prompts should happen in the prepare step rather. In case of failure, cleanup() will be called so that changes can
- * be undone as much as possible.
- *
- * @param string $type one of install/update/uninstall
- * @param PackageInterface $package package instance
- * @param string $path download path
- * @param PackageInterface $prevPackage previous package instance in case of an update
- * @return PromiseInterface|null
- */
- public function prepare($type, PackageInterface $package, $path, PackageInterface $prevPackage = null);
-
- /**
- * Installs specific package into specific folder.
- *
- * @param PackageInterface $package package instance
- * @param string $path download path
- * @return PromiseInterface|null
- */
- public function install(PackageInterface $package, $path);
+ public function download(PackageInterface $package, $path);
/**
* Updates specific package in specific folder from initial to target version.
*
- * @param PackageInterface $initial initial package
- * @param PackageInterface $target updated package
- * @param string $path download path
- * @return PromiseInterface|null
+ * @param PackageInterface $initial initial package
+ * @param PackageInterface $target updated package
+ * @param string $path download path
*/
public function update(PackageInterface $initial, PackageInterface $target, $path);
/**
* Removes specific package from specific folder.
*
- * @param PackageInterface $package package instance
- * @param string $path download path
- * @return PromiseInterface|null
+ * @param PackageInterface $package package instance
+ * @param string $path download path
*/
public function remove(PackageInterface $package, $path);
/**
- * Do anything to cleanup changes applied in the prepare or install/update/uninstall steps
- *
- * Note that cleanup will be called for all packages, either after install/update/uninstall is complete,
- * or if any package failed any operation. This is to give all installers a change to cleanup things
- * they did previously, so you need to keep track of changes applied in the installer/downloader themselves.
+ * Sets whether to output download progress information or not
*
- * @param string $type one of install/update/uninstall
- * @param PackageInterface $package package instance
- * @param string $path download path
- * @param PackageInterface $prevPackage previous package instance in case of an update
- * @return PromiseInterface|null
+ * @param bool $outputProgress
+ * @return DownloaderInterface
*/
- public function cleanup($type, PackageInterface $package, $path, PackageInterface $prevPackage = null);
+ public function setOutputProgress($outputProgress);
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/FileDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/FileDownloader.php
index e915d6995..819fbcefb 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/FileDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/FileDownloader.php
@@ -14,24 +14,18 @@
use Composer\Config;
use Composer\Cache;
+use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
-use Composer\Exception\IrrecoverableDownloadException;
use Composer\Package\Comparer\Comparer;
-use Composer\DependencyResolver\Operation\UpdateOperation;
-use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\Package\PackageInterface;
+use Composer\Package\Version\VersionParser;
use Composer\Plugin\PluginEvents;
-use Composer\Plugin\PostFileDownloadEvent;
use Composer\Plugin\PreFileDownloadEvent;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Util\Filesystem;
-use Composer\Util\Silencer;
-use Composer\Util\HttpDownloader;
+use Composer\Util\RemoteFilesystem;
use Composer\Util\Url as UrlUtil;
-use Composer\Util\ProcessExecutor;
-use React\Promise\PromiseInterface;
/**
* Base downloader for files
@@ -43,51 +37,35 @@
*/
class FileDownloader implements DownloaderInterface, ChangeReportInterface
{
- /** @var IOInterface */
protected $io;
- /** @var Config */
protected $config;
- /** @var HttpDownloader */
- protected $httpDownloader;
- /** @var Filesystem */
+ protected $rfs;
protected $filesystem;
- /** @var ?Cache */
protected $cache;
- /** @var ?EventDispatcher */
- protected $eventDispatcher;
- /** @var ProcessExecutor */
- protected $process;
- /**
- * @private this is only public for php 5.3 support in closures
- *
- * @var array Map of package name to cache key
- */
- public $lastCacheWrites = array();
- /** @var array Map of package name to list of paths */
- private $additionalCleanupPaths = array();
+ protected $outputProgress = true;
+ private $lastCacheWrites = array();
+ private $eventDispatcher;
/**
* Constructor.
*
- * @param IOInterface $io The IO instance
- * @param Config $config The config
- * @param HttpDownloader $httpDownloader The remote filesystem
- * @param EventDispatcher $eventDispatcher The event dispatcher
- * @param Cache $cache Cache instance
- * @param Filesystem $filesystem The filesystem
+ * @param IOInterface $io The IO instance
+ * @param Config $config The config
+ * @param EventDispatcher $eventDispatcher The event dispatcher
+ * @param Cache $cache Optional cache instance
+ * @param RemoteFilesystem $rfs The remote filesystem
+ * @param Filesystem $filesystem The filesystem
*/
- public function __construct(IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $eventDispatcher = null, Cache $cache = null, Filesystem $filesystem = null, ProcessExecutor $process = null)
+ public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
{
$this->io = $io;
$this->config = $config;
$this->eventDispatcher = $eventDispatcher;
- $this->httpDownloader = $httpDownloader;
+ $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
+ $this->filesystem = $filesystem ?: new Filesystem();
$this->cache = $cache;
- $this->process = $process ?: new ProcessExecutor($io);
- $this->filesystem = $filesystem ?: new Filesystem($this->process);
if ($this->cache && $this->cache->gcIsNecessary()) {
- $this->io->writeError('Running cache garbage collection', true, IOInterface::VERY_VERBOSE);
$this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
}
}
@@ -103,256 +81,127 @@ public function getInstallationSource()
/**
* {@inheritDoc}
*/
- public function download(PackageInterface $package, $path, PackageInterface $prevPackage = null, $output = true)
+ public function download(PackageInterface $package, $path, $output = true)
{
if (!$package->getDistUrl()) {
throw new \InvalidArgumentException('The given package is missing url information');
}
- $cacheKeyGenerator = function (PackageInterface $package, $key) {
- $cacheKey = sha1($key);
-
- return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
- };
-
- $retries = 3;
- $distUrls = $package->getDistUrls();
- /** @var array $urls */
- $urls = array();
- foreach ($distUrls as $index => $url) {
- $processedUrl = $this->processUrl($package, $url);
- $urls[$index] = array(
- 'base' => $url,
- 'processed' => $processedUrl,
- // we use the complete download url here to avoid conflicting entries
- // from different packages, which would potentially allow a given package
- // in a third party repo to pre-populate the cache for the same package in
- // packagist for example.
- 'cacheKey' => $cacheKeyGenerator($package, $processedUrl),
- );
+ if ($output) {
+ $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . " ): ", false);
}
- $fileName = $this->getFileName($package, $path);
- $this->filesystem->ensureDirectoryExists($path);
- $this->filesystem->ensureDirectoryExists(dirname($fileName));
-
- $io = $this->io;
- $cache = $this->cache;
- $httpDownloader = $this->httpDownloader;
- $eventDispatcher = $this->eventDispatcher;
- $filesystem = $this->filesystem;
- $self = $this;
-
- $accept = null;
- $reject = null;
- $download = function () use ($io, $output, $httpDownloader, $cache, $cacheKeyGenerator, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject, $self) {
- /** @var array{base: string, processed: string, cacheKey: string} $url */
- $url = reset($urls);
- $index = key($urls);
-
- if ($eventDispatcher) {
- $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $httpDownloader, $url['processed'], 'package', $package);
- $eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
- if ($preFileDownloadEvent->getCustomCacheKey() !== null) {
- $url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getCustomCacheKey());
- } elseif ($preFileDownloadEvent->getProcessedUrl() !== $url['processed']) {
- $url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getProcessedUrl());
+ $urls = $package->getDistUrls();
+ while ($url = array_shift($urls)) {
+ try {
+ $fileName = $this->doDownload($package, $path, $url);
+ break;
+ } catch (\Exception $e) {
+ if ($this->io->isDebug()) {
+ $this->io->writeError('');
+ $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
+ } elseif (count($urls)) {
+ $this->io->writeError('');
+ $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
}
- $url['processed'] = $preFileDownloadEvent->getProcessedUrl();
- }
-
- $urls[$index] = $url;
- $checksum = $package->getDistSha1Checksum();
- $cacheKey = $url['cacheKey'];
-
- // use from cache if it is present and has a valid checksum or we have no checksum to check against
- if ($cache && (!$checksum || $checksum === $cache->sha1($cacheKey)) && $cache->copyTo($cacheKey, $fileName)) {
- if ($output) {
- $io->writeError(" - Loading " . $package->getName() . " (" . $package->getFullPrettyVersion() . " ) from cache", true, IOInterface::VERY_VERBOSE);
- }
- // mark the file as having been written in cache even though it is only read from cache, so that if
- // the cache is corrupt the archive will be deleted and the next attempt will re-download it
- // see https://github.com/composer/composer/issues/10028
- if (!$cache->isReadOnly()) {
- $self->lastCacheWrites[$package->getName()] = $cacheKey;
+ if (!count($urls)) {
+ throw $e;
}
- $result = \React\Promise\resolve($fileName);
- } else {
- if ($output) {
- $io->writeError(" - Downloading " . $package->getName() . " (" . $package->getFullPrettyVersion() . " )");
- }
-
- $result = $httpDownloader->addCopy($url['processed'], $fileName, $package->getTransportOptions())
- ->then($accept, $reject);
}
+ }
- return $result->then(function ($result) use ($fileName, $checksum, $url, $package, $eventDispatcher) {
- // in case of retry, the first call's Promise chain finally calls this twice at the end,
- // once with $result being the returned $fileName from $accept, and then once for every
- // failed request with a null result, which can be skipped.
- if (null === $result) {
- return $fileName;
- }
-
- if (!file_exists($fileName)) {
- throw new \UnexpectedValueException($url['base'].' could not be saved to '.$fileName.', make sure the'
- .' directory is writable and you have internet connectivity');
- }
-
- if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
- throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url['base'].')');
- }
-
- if ($eventDispatcher) {
- $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, $fileName, $checksum, $url['processed'], 'package', $package);
- $eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent);
- }
-
- return $fileName;
- });
- };
-
- $accept = function ($response) use ($cache, $package, $fileName, $self, &$urls) {
- $url = reset($urls);
- $cacheKey = $url['cacheKey'];
+ if ($output) {
+ $this->io->writeError('');
+ }
- if ($cache && !$cache->isReadOnly()) {
- $self->lastCacheWrites[$package->getName()] = $cacheKey;
- $cache->copyFrom($cacheKey, $fileName);
- }
+ return $fileName;
+ }
- $response->collect();
+ protected function doDownload(PackageInterface $package, $path, $url)
+ {
+ $this->filesystem->emptyDirectory($path);
- return $fileName;
- };
+ $fileName = $this->getFileName($package, $path);
- $reject = function ($e) use ($io, &$urls, $download, $fileName, $package, &$retries, $filesystem, $self) {
- // clean up
- if (file_exists($fileName)) {
- $filesystem->unlink($fileName);
- }
- $self->clearLastCacheWrite($package);
+ $processedUrl = $this->processUrl($package, $url);
+ $origin = RemoteFilesystem::getOrigin($processedUrl);
- if ($e instanceof IrrecoverableDownloadException) {
- throw $e;
- }
+ $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
+ if ($this->eventDispatcher) {
+ $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
+ }
+ $rfs = $preFileDownloadEvent->getRemoteFilesystem();
- if ($e instanceof MaxFileSizeExceededException) {
- throw $e;
- }
+ try {
+ $checksum = $package->getDistSha1Checksum();
+ $cacheKey = $this->getCacheKey($package, $processedUrl);
- if ($e instanceof TransportException) {
- // if we got an http response with a proper code, then requesting again will probably not help, abort
- if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
- $retries = 0;
+ // use from cache if it is present and has a valid checksum or we have no checksum to check against
+ if ($this->cache && (!$checksum || $checksum === $this->cache->sha1($cacheKey)) && $this->cache->copyTo($cacheKey, $fileName)) {
+ $this->io->writeError('Loading from cache', false);
+ } else {
+ // download if cache restore failed
+ if (!$this->outputProgress) {
+ $this->io->writeError('Downloading', false);
}
- }
-
- // special error code returned when network is being artificially disabled
- if ($e instanceof TransportException && $e->getStatusCode() === 499) {
- $retries = 0;
- $urls = array();
- }
-
- if ($retries) {
- usleep(500000);
- $retries--;
-
- return $download();
- }
- array_shift($urls);
- if ($urls) {
- if ($io->isDebug()) {
- $io->writeError(' Failed downloading '.$package->getName().': ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
- $io->writeError(' Trying the next URL for '.$package->getName());
- } else {
- $io->writeError(' Failed downloading '.$package->getName().', trying the next URL ('.$e->getCode().': '.$e->getMessage().')');
+ // try to download 3 times then fail hard
+ $retries = 3;
+ while ($retries--) {
+ try {
+ $rfs->copy($origin, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
+ break;
+ } catch (TransportException $e) {
+ // if we got an http response with a proper code, then requesting again will probably not help, abort
+ if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
+ throw $e;
+ }
+ $this->io->writeError('');
+ $this->io->writeError(' Download failed, retrying...', true, IOInterface::VERBOSE);
+ usleep(500000);
+ }
}
- $retries = 3;
- usleep(100000);
+ if (!$this->outputProgress) {
+ $this->io->writeError(' (100% )', false);
+ }
- return $download();
+ if ($this->cache) {
+ $this->lastCacheWrites[$package->getName()] = $cacheKey;
+ $this->cache->copyFrom($cacheKey, $fileName);
+ }
}
- throw $e;
- };
-
- return $download();
- }
-
- /**
- * {@inheritDoc}
- */
- public function prepare($type, PackageInterface $package, $path, PackageInterface $prevPackage = null)
- {
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- public function cleanup($type, PackageInterface $package, $path, PackageInterface $prevPackage = null)
- {
- $fileName = $this->getFileName($package, $path);
- if (file_exists($fileName)) {
- $this->filesystem->unlink($fileName);
- }
-
- $dirsToCleanUp = array(
- $this->config->get('vendor-dir').'/composer/',
- $this->config->get('vendor-dir'),
- $path,
- );
-
- if (isset($this->additionalCleanupPaths[$package->getName()])) {
- foreach ($this->additionalCleanupPaths[$package->getName()] as $path) {
- $this->filesystem->remove($path);
+ if (!file_exists($fileName)) {
+ throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
+ .' directory is writable and you have internet connectivity');
}
- }
- foreach ($dirsToCleanUp as $dir) {
- if (is_dir($dir) && $this->filesystem->isDirEmpty($dir) && realpath($dir) !== getcwd()) {
- $this->filesystem->removeDirectoryPhp($dir);
+ if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
+ throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
}
+ } catch (\Exception $e) {
+ // clean up
+ $this->filesystem->removeDirectory($path);
+ $this->clearLastCacheWrite($package);
+ throw $e;
}
- return \React\Promise\resolve();
+ return $fileName;
}
/**
* {@inheritDoc}
*/
- public function install(PackageInterface $package, $path, $output = true)
+ public function setOutputProgress($outputProgress)
{
- if ($output) {
- $this->io->writeError(" - " . InstallOperation::format($package));
- }
-
- $this->filesystem->emptyDirectory($path);
- $this->filesystem->ensureDirectoryExists($path);
- $this->filesystem->rename($this->getFileName($package, $path), $path . '/' . pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME));
-
- if ($package->getBinaries()) {
- // Single files can not have a mode set like files in archives
- // so we make sure if the file is a binary that it is executable
- foreach ($package->getBinaries() as $bin) {
- if (file_exists($path . '/' . $bin) && !is_executable($path . '/' . $bin)) {
- Silencer::call('chmod', $path . '/' . $bin, 0777 & ~umask());
- }
- }
- }
+ $this->outputProgress = $outputProgress;
- return \React\Promise\resolve();
+ return $this;
}
- /**
- * TODO mark private in v3
- * @protected This is public due to PHP 5.3
- */
- public function clearLastCacheWrite(PackageInterface $package)
+ protected function clearLastCacheWrite(PackageInterface $package)
{
if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
$this->cache->remove($this->lastCacheWrites[$package->getName()]);
@@ -360,48 +209,22 @@ public function clearLastCacheWrite(PackageInterface $package)
}
}
- /**
- * TODO mark private in v3
- * @protected This is public due to PHP 5.3
- */
- public function addCleanupPath(PackageInterface $package, $path)
- {
- $this->additionalCleanupPaths[$package->getName()][] = $path;
- }
-
- /**
- * TODO mark private in v3
- * @protected This is public due to PHP 5.3
- */
- public function removeCleanupPath(PackageInterface $package, $path)
- {
- if (isset($this->additionalCleanupPaths[$package->getName()])) {
- $idx = array_search($path, $this->additionalCleanupPaths[$package->getName()]);
- if (false !== $idx) {
- unset($this->additionalCleanupPaths[$package->getName()][$idx]);
- }
- }
- }
-
/**
* {@inheritDoc}
*/
public function update(PackageInterface $initial, PackageInterface $target, $path)
{
- $this->io->writeError(" - " . UpdateOperation::format($initial, $target) . $this->getInstallOperationAppendix($target, $path));
+ $name = $target->getName();
+ $from = $initial->getFullPrettyVersion();
+ $to = $target->getFullPrettyVersion();
- $promise = $this->remove($initial, $path, false);
- if (!$promise instanceof PromiseInterface) {
- $promise = \React\Promise\resolve();
- }
- $self = $this;
- $io = $this->io;
+ $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
+ $this->io->writeError(" - " . $actionName . " " . $name . " (" . $from . " => " . $to . " ): ", false);
- return $promise->then(function () use ($self, $target, $path) {
- $promise = $self->install($target, $path, false);
+ $this->remove($initial, $path, false);
+ $this->download($target, $path, false);
- return $promise;
- });
+ $this->io->writeError('');
}
/**
@@ -410,15 +233,11 @@ public function update(PackageInterface $initial, PackageInterface $target, $pat
public function remove(PackageInterface $package, $path, $output = true)
{
if ($output) {
- $this->io->writeError(" - " . UninstallOperation::format($package));
+ $this->io->writeError(" - Removing " . $package->getName() . " (" . $package->getFullPrettyVersion() . " )");
+ }
+ if (!$this->filesystem->removeDirectory($path)) {
+ throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
}
- $promise = $this->filesystem->removeDirectoryAsync($path);
-
- return $promise->then(function ($result) use ($path) {
- if (!$result) {
- throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
- }
- });
}
/**
@@ -430,19 +249,7 @@ public function remove(PackageInterface $package, $path, $output = true)
*/
protected function getFileName(PackageInterface $package, $path)
{
- return rtrim($this->config->get('vendor-dir').'/composer/tmp-'.md5($package.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
- }
-
- /**
- * Gets appendix message to add to the "- Upgrading x" string being output on update
- *
- * @param PackageInterface $package package instance
- * @param string $path download path
- * @return string
- */
- protected function getInstallOperationAppendix(PackageInterface $package, $path)
- {
- return '';
+ return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
}
/**
@@ -466,6 +273,17 @@ protected function processUrl(PackageInterface $package, $url)
return $url;
}
+ private function getCacheKey(PackageInterface $package, $processedUrl)
+ {
+ // we use the complete download url here to avoid conflicting entries
+ // from different packages, which would potentially allow a given package
+ // in a third party repo to pre-populate the cache for the same package in
+ // packagist for example.
+ $cacheKey = sha1($processedUrl);
+
+ return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
+ }
+
/**
* {@inheritDoc}
* @throws \RuntimeException
@@ -473,22 +291,15 @@ protected function processUrl(PackageInterface $package, $url)
public function getLocalChanges(PackageInterface $package, $targetDir)
{
$prevIO = $this->io;
+ $prevProgress = $this->outputProgress;
$this->io = new NullIO;
$this->io->loadConfiguration($this->config);
+ $this->outputProgress = false;
$e = null;
- $output = '';
- $targetDir = Filesystem::trimTrailingSlash($targetDir);
try {
- if (is_dir($targetDir.'_compare')) {
- $this->filesystem->removeDirectory($targetDir.'_compare');
- }
-
- $this->download($package, $targetDir.'_compare', null, false);
- $this->httpDownloader->wait();
- $this->install($package, $targetDir.'_compare', false);
- $this->process->wait();
+ $this->download($package, $targetDir.'_compare', false);
$comparer = new Comparer();
$comparer->setSource($targetDir.'_compare');
@@ -500,6 +311,7 @@ public function getLocalChanges(PackageInterface $package, $targetDir)
}
$this->io = $prevIO;
+ $this->outputProgress = $prevProgress;
if ($e) {
throw $e;
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php
index d96c4f4ff..57ee85965 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/FossilDownloader.php
@@ -23,15 +23,7 @@ class FossilDownloader extends VcsDownloader
/**
* {@inheritDoc}
*/
- protected function doDownload(PackageInterface $package, $path, $url, PackageInterface $prevPackage = null)
- {
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- protected function doInstall(PackageInterface $package, $path, $url)
+ public function doDownload(PackageInterface $package, $path, $url)
{
// Ensure we are allowed to use this URL by config
$this->config->prohibitUrlByConfig($url, $this->io);
@@ -52,18 +44,17 @@ protected function doInstall(PackageInterface $package, $path, $url)
if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
}
-
- return \React\Promise\resolve();
}
/**
* {@inheritDoc}
*/
- protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
+ public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
{
// Ensure we are allowed to use this URL by config
$this->config->prohibitUrlByConfig($url, $this->io);
+ $url = ProcessExecutor::escape($url);
$ref = ProcessExecutor::escape($target->getSourceReference());
$this->io->writeError(" Updating to ".$target->getSourceReference());
@@ -75,8 +66,6 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
}
-
- return \React\Promise\resolve();
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/GitDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/GitDownloader.php
index f8e157894..88cb4b475 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/GitDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/GitDownloader.php
@@ -17,7 +17,6 @@
use Composer\Package\PackageInterface;
use Composer\Util\Filesystem;
use Composer\Util\Git as GitUtil;
-use Composer\Util\Url;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
use Composer\Cache;
@@ -27,25 +26,9 @@
*/
class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
{
- /**
- * @var bool[]
- * @phpstan-var array
- */
- private $hasStashedChanges = array();
- /**
- * @var bool[]
- * @phpstan-var array
- */
- private $hasDiscardedChanges = array();
- /**
- * @var GitUtil
- */
+ private $hasStashedChanges = false;
+ private $hasDiscardedChanges = false;
private $gitUtil;
- /**
- * @var array
- * @phpstan-var array>
- */
- private $cachedPackages = array();
public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
{
@@ -56,32 +39,7 @@ public function __construct(IOInterface $io, Config $config, ProcessExecutor $pr
/**
* {@inheritDoc}
*/
- protected function doDownload(PackageInterface $package, $path, $url, PackageInterface $prevPackage = null)
- {
- GitUtil::cleanEnv();
-
- $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
- $gitVersion = GitUtil::getVersion($this->process);
-
- // --dissociate option is only available since git 2.3.0-rc0
- if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) {
- $this->io->writeError(" - Syncing " . $package->getName() . " (" . $package->getFullPrettyVersion() . " ) into cache");
- $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
- $ref = $package->getSourceReference();
- if ($this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref) && is_dir($cachePath)) {
- $this->cachedPackages[$package->getId()][$ref] = true;
- }
- } elseif (null === $gitVersion) {
- throw new \RuntimeException('git was not found in your PATH, skipping source download');
- }
-
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- protected function doInstall(PackageInterface $package, $path, $url)
+ public function doDownload(PackageInterface $package, $path, $url)
{
GitUtil::cleanEnv();
$path = $this->normalizePath($path);
@@ -89,20 +47,31 @@ protected function doInstall(PackageInterface $package, $path, $url)
$ref = $package->getSourceReference();
$flag = Platform::isWindows() ? '/D ' : '';
- if (!empty($this->cachedPackages[$package->getId()][$ref])) {
- $msg = "Cloning ".$this->getShortHash($ref).' from cache';
- $command =
- 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
- . '&& cd '.$flag.'%path% '
- . '&& git remote set-url origin -- %sanitizedUrl% && git remote add composer -- %sanitizedUrl%';
- } else {
- $msg = "Cloning ".$this->getShortHash($ref);
- $command = 'git clone --no-checkout -- %url% %path% && cd '.$flag.'%path% && git remote add composer -- %url% && git fetch composer && git remote set-url origin -- %sanitizedUrl% && git remote set-url composer -- %sanitizedUrl%';
- if (getenv('COMPOSER_DISABLE_NETWORK')) {
- throw new \RuntimeException('The required git reference for '.$package->getName().' is not in cache and network is disabled, aborting');
+ // --dissociate option is only available since git 2.3.0-rc0
+ $gitVersion = GitUtil::getVersion($this->process);
+ $msg = "Cloning ".$this->getShortHash($ref);
+
+ $command = 'git clone --no-checkout -- %url% %path% && cd '.$flag.'%path% && git remote add composer -- %url% && git fetch composer && git remote set-url origin -- %sanitizedUrl% && git remote set-url composer -- %sanitizedUrl%';
+ if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) {
+ $this->io->writeError('', true, IOInterface::DEBUG);
+ $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
+ try {
+ if (!$this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref)) {
+ $this->io->writeError('Failed to update '.$url.' in cache, package installation for '.$package->getPrettyName().' might fail. ');
+ }
+ if (is_dir($cachePath)) {
+ $command =
+ 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
+ . '&& cd '.$flag.'%path% '
+ . '&& git remote set-url origin -- %sanitizedUrl% && git remote add composer -- %sanitizedUrl%';
+ $msg = "Cloning ".$this->getShortHash($ref).' from cache';
+ }
+ } catch (\RuntimeException $e) {
+ if (0 === strpos(get_class($e), 'PHPUnit')) {
+ throw $e;
+ }
}
}
-
$this->io->writeError($msg);
$commandCallable = function ($url) use ($path, $command, $cachePath) {
@@ -131,47 +100,39 @@ protected function doInstall(PackageInterface $package, $path, $url)
}
$package->setSourceReference($newRef);
}
-
- return \React\Promise\resolve();
}
/**
* {@inheritDoc}
*/
- protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
+ public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
{
GitUtil::cleanEnv();
- $path = $this->normalizePath($path);
if (!$this->hasMetadataRepository($path)) {
throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
}
- $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
- $ref = $target->getSourceReference();
-
- if (!empty($this->cachedPackages[$target->getId()][$ref])) {
- $msg = "Checking out ".$this->getShortHash($ref).' from cache';
- $command = '(git rev-parse --quiet --verify %ref% || (git remote set-url composer -- %cachePath% && git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %sanitizedUrl%';
- } else {
- $msg = "Checking out ".$this->getShortHash($ref);
- $command = '(git remote set-url composer -- %url% && git rev-parse --quiet --verify %ref% || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %sanitizedUrl%';
- if (getenv('COMPOSER_DISABLE_NETWORK')) {
- throw new \RuntimeException('The required git reference for '.$target->getName().' is not in cache and network is disabled, aborting');
+ $updateOriginUrl = false;
+ if (
+ 0 === $this->process->execute('git remote -v', $output, $path)
+ && preg_match('{^origin\s+(?P\S+)}m', $output, $originMatch)
+ && preg_match('{^composer\s+(?P\S+)}m', $output, $composerMatch)
+ ) {
+ if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
+ $updateOriginUrl = true;
}
}
- $this->io->writeError($msg);
-
- $commandCallable = function ($url) use ($ref, $command, $cachePath) {
- return str_replace(
- array('%url%', '%ref%', '%cachePath%', '%sanitizedUrl%'),
- array(
- ProcessExecutor::escape($url),
- ProcessExecutor::escape($ref.'^{commit}'),
- ProcessExecutor::escape($cachePath),
- ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url)),
- ),
- $command
+ $ref = $target->getSourceReference();
+ $this->io->writeError(" Checking out ".$this->getShortHash($ref));
+ $command = '(git remote set-url composer -- %s && git rev-parse --quiet --verify %s || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %s';
+
+ $commandCallable = function ($url) use ($command, $ref) {
+ return sprintf(
+ $command,
+ ProcessExecutor::escape($url),
+ ProcessExecutor::escape($ref.'^{commit}'),
+ ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url))
);
};
@@ -183,21 +144,9 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
$target->setSourceReference($newRef);
}
- $updateOriginUrl = false;
- if (
- 0 === $this->process->execute('git remote -v', $output, $path)
- && preg_match('{^origin\s+(?P\S+)}m', $output, $originMatch)
- && preg_match('{^composer\s+(?P\S+)}m', $output, $composerMatch)
- ) {
- if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
- $updateOriginUrl = true;
- }
- }
if ($updateOriginUrl) {
$this->updateOriginUrl($path, $target->getSourceUrl());
}
-
- return \React\Promise\resolve();
}
/**
@@ -207,7 +156,7 @@ public function getLocalChanges(PackageInterface $package, $path)
{
GitUtil::cleanEnv();
if (!$this->hasMetadataRepository($path)) {
- return null;
+ return;
}
$command = 'git status --porcelain --untracked-files=no';
@@ -223,7 +172,7 @@ public function getUnpushedChanges(PackageInterface $package, $path)
GitUtil::cleanEnv();
$path = $this->normalizePath($path);
if (!$this->hasMetadataRepository($path)) {
- return null;
+ return;
}
$command = 'git show-ref --head -d';
@@ -234,32 +183,26 @@ public function getUnpushedChanges(PackageInterface $package, $path)
$refs = trim($output);
if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
// could not match the HEAD for some reason
- return null;
+ return;
}
$headRef = $match[1];
if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
// not on a branch, we are either on a not-modified tag or some sort of detached head, so skip this
- return null;
+ return;
}
- $candidateBranches = $matches[1];
// use the first match as branch name for now
- $branch = $candidateBranches[0];
+ $branch = $matches[1][0];
$unpushedChanges = null;
- $branchNotFoundError = false;
// do two passes, as if we find anything we want to fetch and then re-try
for ($i = 0; $i <= 1; $i++) {
- $remoteBranches = array();
-
- // try to find matching branch names in remote repos
- foreach ($candidateBranches as $candidate) {
- if (preg_match_all('{^[a-f0-9]+ refs/remotes/((?:[^/]+)/'.preg_quote($candidate).')$}mi', $refs, $matches)) {
- foreach ($matches[1] as $match) {
- $branch = $candidate;
- $remoteBranches[] = $match;
- }
+ // try to find the a matching branch name in the composer remote
+ foreach ($matches[1] as $candidate) {
+ if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
+ $branch = $candidate;
+ $remoteBranch = $match[1];
break;
}
}
@@ -267,40 +210,21 @@ public function getUnpushedChanges(PackageInterface $package, $path)
// if it doesn't exist, then we assume it is an unpushed branch
// this is bad as we have no reference point to do a diff so we just bail listing
// the branch as being unpushed
- if (!$remoteBranches) {
- $unpushedChanges = 'Branch ' . $branch . ' could not be found on any remote and appears to be unpushed';
- $branchNotFoundError = true;
+ if (!isset($remoteBranch)) {
+ $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
} else {
- // if first iteration found no remote branch but it has now found some, reset $unpushedChanges
- // so we get the real diff output no matter its length
- if ($branchNotFoundError) {
- $unpushedChanges = null;
+ $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
+ if (0 !== $this->process->execute($command, $output, $path)) {
+ throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
}
- foreach ($remoteBranches as $remoteBranch) {
- $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
- if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- $output = trim($output);
- // keep the shortest diff from all remote branches we compare against
- if ($unpushedChanges === null || strlen($output) < strlen($unpushedChanges)) {
- $unpushedChanges = $output;
- }
- }
+ $unpushedChanges = trim($output) ?: null;
}
- // first pass and we found unpushed changes, fetch from all remotes to make sure we have up to date
+ // first pass and we found unpushed changes, fetch from both remotes to make sure we have up to date
// remotes and then try again as outdated remotes can sometimes cause false-positives
if ($unpushedChanges && $i === 0) {
- $this->process->execute('git fetch --all', $output, $path);
-
- // update list of refs after fetching
- $command = 'git show-ref --head -d';
- if (0 !== $this->process->execute($command, $output, $path)) {
- throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
- }
- $refs = trim($output);
+ $this->process->execute('git fetch composer && git fetch origin', $output, $path);
}
// abort after first pass if we didn't find anything
@@ -348,7 +272,7 @@ protected function cleanChanges(PackageInterface $package, $path, $update)
$changes = array_map(function ($elem) {
return ' '.$elem;
}, preg_split('{\s*\r?\n\s*}', $changes));
- $this->io->writeError(' '.$package->getPrettyName().' has modified files: ');
+ $this->io->writeError(' The package has modified files: ');
$this->io->writeError(array_slice($changes, 0, 10));
if (count($changes) > 10) {
$this->io->writeError(' ' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list ');
@@ -381,7 +305,7 @@ protected function cleanChanges(PackageInterface $package, $path, $update)
case '?':
default:
- help :
+ help:
$this->io->writeError(array(
' y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
' n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
@@ -403,15 +327,15 @@ protected function cleanChanges(PackageInterface $package, $path, $update)
protected function reapplyChanges($path)
{
$path = $this->normalizePath($path);
- if (!empty($this->hasStashedChanges[$path])) {
- unset($this->hasStashedChanges[$path]);
+ if ($this->hasStashedChanges) {
+ $this->hasStashedChanges = false;
$this->io->writeError(' Re-applying stashed changes ');
if (0 !== $this->process->execute('git stash pop', $output, $path)) {
throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
}
}
- unset($this->hasDiscardedChanges[$path]);
+ $this->hasDiscardedChanges = false;
}
/**
@@ -426,7 +350,7 @@ protected function reapplyChanges($path)
*/
protected function updateToCommit($path, $reference, $branch, $date)
{
- $force = !empty($this->hasDiscardedChanges[$path]) || !empty($this->hasStashedChanges[$path]) ? '-f ' : '';
+ $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
// This uses the "--" sequence to separate branch from file parameters.
//
@@ -449,7 +373,7 @@ protected function updateToCommit($path, $reference, $branch, $date)
) {
$command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
if (0 === $this->process->execute($command, $output, $path)) {
- return null;
+ return;
}
}
@@ -462,16 +386,19 @@ protected function updateToCommit($path, $reference, $branch, $date)
$command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
$fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
- $resetCommand = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
-
- if (0 === $this->process->execute("($command || $fallbackCommand) && $resetCommand", $output, $path)) {
- return null;
+ if (0 === $this->process->execute($command, $output, $path)
+ || 0 === $this->process->execute($fallbackCommand, $output, $path)
+ ) {
+ $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
+ if (0 === $this->process->execute($command, $output, $path)) {
+ return;
+ }
}
}
$command = sprintf($template, ProcessExecutor::escape($gitRef));
if (0 === $this->process->execute($command, $output, $path)) {
- return null;
+ return;
}
// reference was not found (prints "fatal: reference is not a tree: $ref")
@@ -479,7 +406,7 @@ protected function updateToCommit($path, $reference, $branch, $date)
$this->io->writeError(' '.$reference.' is gone (history was rewritten?) ');
}
- throw new \RuntimeException(Url::sanitize('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
+ throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
}
protected function updateOriginUrl($path, $url)
@@ -518,42 +445,42 @@ protected function getCommitLogs($fromReference, $toReference, $path)
}
/**
- * @param string $path
+ * @param string $path
* @throws \RuntimeException
*/
protected function discardChanges($path)
{
$path = $this->normalizePath($path);
if (0 !== $this->process->execute('git clean -df && git reset --hard', $output, $path)) {
- throw new \RuntimeException("Could not reset changes\n\n:".$output);
+ throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
}
- $this->hasDiscardedChanges[$path] = true;
+ $this->hasDiscardedChanges = true;
}
/**
- * @param string $path
+ * @param string $path
* @throws \RuntimeException
*/
protected function stashChanges($path)
{
$path = $this->normalizePath($path);
if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
- throw new \RuntimeException("Could not stash changes\n\n:".$output);
+ throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
}
- $this->hasStashedChanges[$path] = true;
+ $this->hasStashedChanges = true;
}
/**
- * @param string $path
+ * @param string $path
* @throws \RuntimeException
*/
protected function viewDiff($path)
{
$path = $this->normalizePath($path);
if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
- throw new \RuntimeException("Could not view diff\n\n:".$output);
+ throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
}
$this->io->writeError($output);
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php
index df0cc908e..b7c6de3f7 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/GzipDownloader.php
@@ -12,9 +12,14 @@
namespace Composer\Downloader;
+use Composer\Config;
+use Composer\Cache;
+use Composer\EventDispatcher\EventDispatcher;
use Composer\Package\PackageInterface;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
+use Composer\Util\RemoteFilesystem;
+use Composer\IO\IOInterface;
/**
* GZip archive downloader.
@@ -23,24 +28,31 @@
*/
class GzipDownloader extends ArchiveDownloader
{
- protected function extract(PackageInterface $package, $file, $path)
+ protected $process;
+
+ public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
+ {
+ $this->process = $process ?: new ProcessExecutor($io);
+ parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
+ }
+
+ protected function extract($file, $path)
{
- $filename = pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_FILENAME);
- $targetFilepath = $path . DIRECTORY_SEPARATOR . $filename;
+ $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
// Try to use gunzip on *nix
if (!Platform::isWindows()) {
$command = 'gzip -cd -- ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
if (0 === $this->process->execute($command, $ignoredOutput)) {
- return \React\Promise\resolve();
+ return;
}
if (extension_loaded('zlib')) {
// Fallback to using the PHP extension.
$this->extractUsingExt($file, $targetFilepath);
- return \React\Promise\resolve();
+ return;
}
$processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
@@ -49,8 +61,14 @@ protected function extract(PackageInterface $package, $file, $path)
// Windows version of PHP has built-in support of gzip functions
$this->extractUsingExt($file, $targetFilepath);
+ }
- return \React\Promise\resolve();
+ /**
+ * {@inheritdoc}
+ */
+ protected function getFileName(PackageInterface $package, $path)
+ {
+ return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
}
private function extractUsingExt($file, $targetFilepath)
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/HgDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/HgDownloader.php
index f68ed8c8f..0be3374f6 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/HgDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/HgDownloader.php
@@ -24,19 +24,7 @@ class HgDownloader extends VcsDownloader
/**
* {@inheritDoc}
*/
- protected function doDownload(PackageInterface $package, $path, $url, PackageInterface $prevPackage = null)
- {
- if (null === HgUtils::getVersion($this->process)) {
- throw new \RuntimeException('hg was not found in your PATH, skipping source download');
- }
-
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- protected function doInstall(PackageInterface $package, $path, $url)
+ public function doDownload(PackageInterface $package, $path, $url)
{
$hgUtils = new HgUtils($this->io, $this->config, $this->process);
@@ -51,14 +39,12 @@ protected function doInstall(PackageInterface $package, $path, $url)
if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
}
-
- return \React\Promise\resolve();
}
/**
* {@inheritDoc}
*/
- protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
+ public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
{
$hgUtils = new HgUtils($this->io, $this->config, $this->process);
@@ -74,8 +60,6 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
};
$hgUtils->runCommand($command, $url, $path);
-
- return \React\Promise\resolve();
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php b/app/vendor/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php
deleted file mode 100644
index b7adad1b6..000000000
--- a/app/vendor/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php
+++ /dev/null
@@ -1,17 +0,0 @@
-
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\Downloader;
-
-class MaxFileSizeExceededException extends TransportException
-{
-}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/PathDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/PathDownloader.php
index be1b1262d..1e614b6bd 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/PathDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/PathDownloader.php
@@ -18,11 +18,10 @@
use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser;
use Composer\Util\Platform;
-use Composer\Util\Filesystem;
+use Composer\Util\ProcessExecutor;
+use Composer\Util\Filesystem as ComposerFilesystem;
use Symfony\Component\Filesystem\Exception\IOException;
-use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
-use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\UninstallOperation;
+use Symfony\Component\Filesystem\Filesystem;
/**
* Download a package from a local path.
@@ -38,9 +37,8 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
/**
* {@inheritdoc}
*/
- public function download(PackageInterface $package, $path, PackageInterface $prevPackage = null, $output = true)
+ public function download(PackageInterface $package, $path, $output = true)
{
- $path = Filesystem::trimTrailingSlash($path);
$url = $package->getDistUrl();
$realUrl = realpath($url);
if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
@@ -52,7 +50,15 @@ public function download(PackageInterface $package, $path, PackageInterface $pre
}
if (realpath($path) === $realUrl) {
- return \React\Promise\resolve();
+ if ($output) {
+ $this->io->writeError(sprintf(
+ ' - Installing %s (%s ): Source already present',
+ $package->getName(),
+ $package->getFullPrettyVersion()
+ ));
+ }
+
+ return;
}
if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
@@ -68,46 +74,49 @@ public function download(PackageInterface $package, $path, PackageInterface $pre
));
}
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritdoc}
- */
- public function install(PackageInterface $package, $path, $output = true)
- {
- $path = Filesystem::trimTrailingSlash($path);
- $url = $package->getDistUrl();
- $realUrl = realpath($url);
+ // Get the transport options with default values
+ $transportOptions = $package->getTransportOptions() + array('symlink' => null, 'relative' => true);
- if (realpath($path) === $realUrl) {
- if ($output) {
- $this->io->writeError(" - " . InstallOperation::format($package) . $this->getInstallOperationAppendix($package, $path));
- }
+ // When symlink transport option is null, both symlink and mirror are allowed
+ $currentStrategy = self::STRATEGY_SYMLINK;
+ $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
- return \React\Promise\resolve();
+ $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
+ if ($mirrorPathRepos) {
+ $currentStrategy = self::STRATEGY_MIRROR;
}
- // Get the transport options with default values
- $transportOptions = $package->getTransportOptions() + array('relative' => true);
+ if (true === $transportOptions['symlink']) {
+ $currentStrategy = self::STRATEGY_SYMLINK;
+ $allowedStrategies = array(self::STRATEGY_SYMLINK);
+ } elseif (false === $transportOptions['symlink']) {
+ $currentStrategy = self::STRATEGY_MIRROR;
+ $allowedStrategies = array(self::STRATEGY_MIRROR);
+ }
- list($currentStrategy, $allowedStrategies) = $this->computeAllowedStrategies($transportOptions);
+ // Check we can use junctions safely if we are on Windows
+ if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) {
+ $currentStrategy = self::STRATEGY_MIRROR;
+ $allowedStrategies = array(self::STRATEGY_MIRROR);
+ }
- $symfonyFilesystem = new SymfonyFilesystem();
+ $fileSystem = new Filesystem();
$this->filesystem->removeDirectory($path);
if ($output) {
- $this->io->writeError(" - " . InstallOperation::format($package).': ', false);
+ $this->io->writeError(sprintf(
+ ' - Installing %s (%s ): ',
+ $package->getName(),
+ $package->getFullPrettyVersion()
+ ), false);
}
$isFallback = false;
- if (self::STRATEGY_SYMLINK === $currentStrategy) {
+ if (self::STRATEGY_SYMLINK == $currentStrategy) {
try {
if (Platform::isWindows()) {
// Implement symlinks as NTFS junctions on Windows
- if ($output) {
- $this->io->writeError(sprintf('Junctioning from %s', $url), false);
- }
+ $this->io->writeError(sprintf('Junctioning from %s', $url), false);
$this->filesystem->junction($realUrl, $path);
} else {
$absolutePath = $path;
@@ -116,21 +125,17 @@ public function install(PackageInterface $package, $path, $output = true)
}
$shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
$path = rtrim($path, "/");
- if ($output) {
- $this->io->writeError(sprintf('Symlinking from %s', $url), false);
- }
+ $this->io->writeError(sprintf('Symlinking from %s', $url), false);
if ($transportOptions['relative']) {
- $symfonyFilesystem->symlink($shortestPath, $path);
+ $fileSystem->symlink($shortestPath, $path);
} else {
- $symfonyFilesystem->symlink($realUrl, $path);
+ $fileSystem->symlink($realUrl, $path);
}
}
} catch (IOException $e) {
if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
- if ($output) {
- $this->io->writeError('');
- $this->io->writeError(' Symlink failed, fallback to use mirroring! ');
- }
+ $this->io->writeError('');
+ $this->io->writeError(' Symlink failed, fallback to use mirroring! ');
$currentStrategy = self::STRATEGY_MIRROR;
$isFallback = true;
} else {
@@ -140,21 +145,16 @@ public function install(PackageInterface $package, $path, $output = true)
}
// Fallback if symlink failed or if symlink is not allowed for the package
- if (self::STRATEGY_MIRROR === $currentStrategy) {
- $realUrl = $this->filesystem->normalizePath($realUrl);
+ if (self::STRATEGY_MIRROR == $currentStrategy) {
+ $fs = new ComposerFilesystem();
+ $realUrl = $fs->normalizePath($realUrl);
- if ($output) {
- $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? ' ' : '', $url), false);
- }
+ $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? ' ' : '', $url), false);
$iterator = new ArchivableFilesFinder($realUrl, array());
- $symfonyFilesystem->mirror($realUrl, $path, $iterator);
- }
-
- if ($output) {
- $this->io->writeError('');
+ $fileSystem->mirror($realUrl, $path, $iterator);
}
- return \React\Promise\resolve();
+ $this->io->writeError('');
}
/**
@@ -162,44 +162,32 @@ public function install(PackageInterface $package, $path, $output = true)
*/
public function remove(PackageInterface $package, $path, $output = true)
{
- $path = Filesystem::trimTrailingSlash($path);
+ $realUrl = realpath($package->getDistUrl());
+
+ if (realpath($path) === $realUrl) {
+ if ($output) {
+ $this->io->writeError(" - Removing " . $package->getName() . " (" . $package->getFullPrettyVersion() . " ), source is still present in $path");
+ }
+
+ return;
+ }
+
/**
- * realpath() may resolve Windows junctions to the source path, so we'll check for a junction first
- * to prevent a false positive when checking if the dist and install paths are the same.
- * See https://bugs.php.net/bug.php?id=77639
- *
* For junctions don't blindly rely on Filesystem::removeDirectory as it may be overzealous. If a process
* inadvertently locks the file the removal will fail, but it would fall back to recursive delete which
* is disastrous within a junction. So in that case we have no other real choice but to fail hard.
*/
if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
if ($output) {
- $this->io->writeError(" - " . UninstallOperation::format($package).", source is still present in $path");
+ $this->io->writeError(" - Removing junction for " . $package->getName() . " (" . $package->getFullPrettyVersion() . " )");
}
if (!$this->filesystem->removeJunction($path)) {
$this->io->writeError(" Could not remove junction at " . $path . " - is another process locking it? ");
throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
}
-
- return \React\Promise\resolve();
+ } else {
+ parent::remove($package, $path, $output);
}
-
- // ensure that the source path (dist url) is not the same as the install path, which
- // can happen when using custom installers, see https://github.com/composer/composer/pull/9116
- // not using realpath here as we do not want to resolve the symlink to the original dist url
- // it points to
- $fs = new Filesystem;
- $absPath = $fs->isAbsolutePath($path) ? $path : getcwd() . '/' . $path;
- $absDistUrl = $fs->isAbsolutePath($package->getDistUrl()) ? $package->getDistUrl() : getcwd() . '/' . $package->getDistUrl();
- if ($fs->normalizePath($absPath) === $fs->normalizePath($absDistUrl)) {
- if ($output) {
- $this->io->writeError(" - " . UninstallOperation::format($package).", source is still present in $path");
- }
-
- return \React\Promise\resolve();
- }
-
- return parent::remove($package, $path, $output);
}
/**
@@ -207,71 +195,14 @@ public function remove(PackageInterface $package, $path, $output = true)
*/
public function getVcsReference(PackageInterface $package, $path)
{
- $path = Filesystem::trimTrailingSlash($path);
$parser = new VersionParser;
- $guesser = new VersionGuesser($this->config, $this->process, $parser);
+ $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
$dumper = new ArrayDumper;
$packageConfig = $dumper->dump($package);
if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
return $packageVersion['commit'];
}
-
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- protected function getInstallOperationAppendix(PackageInterface $package, $path)
- {
- $realUrl = realpath($package->getDistUrl());
-
- if (realpath($path) === $realUrl) {
- return ': Source already present';
- }
-
- list($currentStrategy) = $this->computeAllowedStrategies($package->getTransportOptions());
-
- if ($currentStrategy === self::STRATEGY_SYMLINK) {
- if (Platform::isWindows()) {
- return ': Junctioning from '.$package->getDistUrl();
- }
-
- return ': Symlinking from '.$package->getDistUrl();
- }
-
- return ': Mirroring from '.$package->getDistUrl();
- }
-
- private function computeAllowedStrategies(array $transportOptions)
- {
- // When symlink transport option is null, both symlink and mirror are allowed
- $currentStrategy = self::STRATEGY_SYMLINK;
- $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
-
- $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
- if ($mirrorPathRepos) {
- $currentStrategy = self::STRATEGY_MIRROR;
- }
-
- $symlinkOption = isset($transportOptions['symlink']) ? $transportOptions['symlink'] : null;
-
- if (true === $symlinkOption) {
- $currentStrategy = self::STRATEGY_SYMLINK;
- $allowedStrategies = array(self::STRATEGY_SYMLINK);
- } elseif (false === $symlinkOption) {
- $currentStrategy = self::STRATEGY_MIRROR;
- $allowedStrategies = array(self::STRATEGY_MIRROR);
- }
-
- // Check we can use junctions safely if we are on Windows
- if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) {
- $currentStrategy = self::STRATEGY_MIRROR;
- $allowedStrategies = array(self::STRATEGY_MIRROR);
- }
-
- return array($currentStrategy, $allowedStrategies);
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/PearPackageExtractor.php b/app/vendor/composer/composer/src/Composer/Downloader/PearPackageExtractor.php
new file mode 100644
index 000000000..5eaf3edcd
--- /dev/null
+++ b/app/vendor/composer/composer/src/Composer/Downloader/PearPackageExtractor.php
@@ -0,0 +1,266 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Downloader;
+
+use Composer\Util\Filesystem;
+
+/**
+ * Extractor for pear packages.
+ *
+ * Composer cannot rely on tar files structure when place it inside package target dir. Correct source files
+ * disposition must be read from package.xml
+ * This extract pear package source files to target dir.
+ *
+ * @author Alexey Prilipko
+ */
+class PearPackageExtractor
+{
+ private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
+ /** @var Filesystem */
+ private $filesystem;
+ private $file;
+
+ public function __construct($file)
+ {
+ if (!is_file($file)) {
+ throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
+ }
+
+ $this->filesystem = new Filesystem();
+ $this->file = $file;
+ }
+
+ /**
+ * Installs PEAR source files according to package.xml definitions and removes extracted files
+ *
+ * @param string $target target install location. all source installation would be performed relative to target path.
+ * @param array $roles types of files to install. default role for PEAR source files are 'php'.
+ * @param array $vars used for replacement tasks
+ * @throws \RuntimeException
+ * @throws \UnexpectedValueException
+ */
+ public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
+ {
+ $extractionPath = $target.'/tarball';
+
+ try {
+ $archive = new \PharData($this->file);
+ $archive->extractTo($extractionPath, null, true);
+
+ if (!is_file($this->combine($extractionPath, '/package.xml'))) {
+ throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
+ }
+
+ $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
+ $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
+ $this->filesystem->removeDirectory($extractionPath);
+ } catch (\Exception $exception) {
+ throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
+ }
+ }
+
+ /**
+ * Perform copy actions on files
+ *
+ * @param array $files array of copy actions ('from', 'to') with relative paths
+ * @param string $source path to source dir.
+ * @param string $target path to destination dir
+ * @param array $roles array [role => roleRoot] relative root for files having that role
+ * @param array $vars list of values can be used for replacement tasks
+ */
+ private function copyFiles($files, $source, $target, $roles, $vars)
+ {
+ foreach ($files as $file) {
+ $from = $this->combine($source, $file['from']);
+ $to = $this->combine($target, $roles[$file['role']]);
+ $to = $this->combine($to, $file['to']);
+ $tasks = $file['tasks'];
+ $this->copyFile($from, $to, $tasks, $vars);
+ }
+ }
+
+ private function copyFile($from, $to, $tasks, $vars)
+ {
+ if (!is_file($from)) {
+ throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
+ }
+
+ $this->filesystem->ensureDirectoryExists(dirname($to));
+
+ if (0 == count($tasks)) {
+ $copied = copy($from, $to);
+ } else {
+ $content = file_get_contents($from);
+ $replacements = array();
+ foreach ($tasks as $task) {
+ $pattern = $task['from'];
+ $varName = $task['to'];
+ if (isset($vars[$varName])) {
+ if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
+ $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
+ } else {
+ $replacements[$pattern] = $vars[$varName];
+ }
+ }
+ }
+ $content = strtr($content, $replacements);
+
+ $copied = file_put_contents($to, $content);
+ }
+
+ if (false === $copied) {
+ throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
+ }
+ }
+
+ /**
+ * Builds list of copy and list of remove actions that would transform extracted PEAR tarball into installed package.
+ *
+ * @param string $source string path to extracted files
+ * @param array $roles array [role => roleRoot] relative root for files having that role
+ * @param array $vars list of values can be used for replacement tasks
+ * @throws \RuntimeException
+ * @return array array of 'source' => 'target', where source is location of file in the tarball (relative to source
+ * path, and target is destination of file (also relative to $source path)
+ */
+ private function buildCopyActions($source, array $roles, $vars)
+ {
+ /** @var \SimpleXmlElement $package */
+ $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
+ if (false === $package) {
+ throw new \RuntimeException('Package definition file is not valid.');
+ }
+
+ $packageSchemaVersion = $package['version'];
+ if ('1.0' == $packageSchemaVersion) {
+ $children = $package->release->filelist->children();
+ $packageName = (string) $package->name;
+ $packageVersion = (string) $package->release->version;
+ $sourceDir = $packageName . '-' . $packageVersion;
+ $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
+ } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
+ $children = $package->contents->children();
+ $packageName = (string) $package->name;
+ $packageVersion = (string) $package->version->release;
+ $sourceDir = $packageName . '-' . $packageVersion;
+ $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
+
+ $namespaces = $package->getNamespaces();
+ $package->registerXPathNamespace('ns', $namespaces['']);
+ $releaseNodes = $package->xpath('ns:phprelease');
+ $this->applyRelease($result, $releaseNodes, $vars);
+ } else {
+ throw new \RuntimeException('Unsupported schema version of package definition file.');
+ }
+
+ return $result;
+ }
+
+ private function applyRelease(&$actions, $releaseNodes, $vars)
+ {
+ foreach ($releaseNodes as $releaseNode) {
+ $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
+ if ($requiredOs && $vars['os'] != $requiredOs) {
+ continue;
+ }
+
+ if ($releaseNode->filelist) {
+ foreach ($releaseNode->filelist->children() as $action) {
+ if ('install' == $action->getName()) {
+ $name = (string) $action['name'];
+ $as = (string) $action['as'];
+ if (isset($actions[$name])) {
+ $actions[$name]['to'] = $as;
+ }
+ } elseif ('ignore' == $action->getName()) {
+ $name = (string) $action['name'];
+ unset($actions[$name]);
+ } else {
+ // unknown action
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
+ {
+ $result = array();
+
+ // enumerating files
+ foreach ($children as $child) {
+ /** @var $child \SimpleXMLElement */
+ if ($child->getName() == 'dir') {
+ $dirSource = $this->combine($source, (string) $child['name']);
+ $dirTarget = $child['baseinstalldir'] ?: $target;
+ $dirRole = $child['role'] ?: $role;
+ $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
+ $result = array_merge($result, $dirFiles);
+ } elseif ($child->getName() == 'file') {
+ $fileRole = (string) $child['role'] ?: $role;
+ if (isset($targetRoles[$fileRole])) {
+ $fileName = (string) ($child['name'] ?: $child[0]); // $child[0] means text content
+ $fileSource = $this->combine($source, $fileName);
+ $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
+ if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
+ $fileTarget = $packageName . '/' . $fileTarget;
+ }
+ $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
+ {
+ $result = array();
+
+ // enumerating files
+ foreach ($children as $child) {
+ /** @var $child \SimpleXMLElement */
+ if ('dir' == $child->getName()) {
+ $dirSource = $this->combine($source, $child['name']);
+ $dirTarget = $child['baseinstalldir'] ?: $target;
+ $dirRole = $child['role'] ?: $role;
+ $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
+ $result = array_merge($result, $dirFiles);
+ } elseif ('file' == $child->getName()) {
+ $fileRole = (string) $child['role'] ?: $role;
+ if (isset($targetRoles[$fileRole])) {
+ $fileSource = $this->combine($source, (string) $child['name']);
+ $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
+ $fileTasks = array();
+ foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
+ if ('replace' == $taskNode->getName()) {
+ $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
+ }
+ }
+ if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
+ $fileTarget = $packageName . '/' . $fileTarget;
+ }
+ $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ private function combine($left, $right)
+ {
+ return rtrim($left, '/') . '/' . ltrim($right, '/');
+ }
+}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/PerforceDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/PerforceDownloader.php
index dc30f8361..92091e2c9 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/PerforceDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/PerforceDownloader.php
@@ -27,15 +27,7 @@ class PerforceDownloader extends VcsDownloader
/**
* {@inheritDoc}
*/
- protected function doDownload(PackageInterface $package, $path, $url, PackageInterface $prevPackage = null)
- {
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- public function doInstall(PackageInterface $package, $path, $url)
+ public function doDownload(PackageInterface $package, $path, $url)
{
$ref = $package->getSourceReference();
$label = $this->getLabelFromSourceReference($ref);
@@ -48,8 +40,6 @@ public function doInstall(PackageInterface $package, $path, $url)
$this->perforce->connectClient();
$this->perforce->syncCodeBase($label);
$this->perforce->cleanupClientSpec();
-
- return \React\Promise\resolve();
}
private function getLabelFromSourceReference($ref)
@@ -86,9 +76,9 @@ private function getRepoConfig(VcsRepository $repository)
/**
* {@inheritDoc}
*/
- protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
+ public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
{
- return $this->doInstall($target, $path, $url);
+ $this->doDownload($target, $path, $url);
}
/**
@@ -96,9 +86,7 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
*/
public function getLocalChanges(PackageInterface $package, $path)
{
- $this->io->writeError('Perforce driver does not check for local changes before overriding');
-
- return null;
+ $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/PharDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/PharDownloader.php
index 89ef4363f..13fec244b 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/PharDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/PharDownloader.php
@@ -12,8 +12,6 @@
namespace Composer\Downloader;
-use Composer\Package\PackageInterface;
-
/**
* Downloader for phar files
*
@@ -24,7 +22,7 @@ class PharDownloader extends ArchiveDownloader
/**
* {@inheritDoc}
*/
- protected function extract(PackageInterface $package, $file, $path)
+ protected function extract($file, $path)
{
// Can throw an UnexpectedValueException
$archive = new \Phar($file);
@@ -34,7 +32,5 @@ protected function extract(PackageInterface $package, $file, $path)
* https://github.com/koto/phar-util
* http://blog.kotowicz.net/2010/08/hardening-php-how-to-securely-include.html
*/
-
- return \React\Promise\resolve();
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/RarDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/RarDownloader.php
index e11366421..1a4a39619 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/RarDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/RarDownloader.php
@@ -12,10 +12,14 @@
namespace Composer\Downloader;
+use Composer\Config;
+use Composer\Cache;
+use Composer\EventDispatcher\EventDispatcher;
use Composer\Util\IniHelper;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
-use Composer\Package\PackageInterface;
+use Composer\Util\RemoteFilesystem;
+use Composer\IO\IOInterface;
use RarArchive;
/**
@@ -27,7 +31,15 @@
*/
class RarDownloader extends ArchiveDownloader
{
- protected function extract(PackageInterface $package, $file, $path)
+ protected $process;
+
+ public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
+ {
+ $this->process = $process ?: new ProcessExecutor($io);
+ parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
+ }
+
+ protected function extract($file, $path)
{
$processError = null;
@@ -36,7 +48,7 @@ protected function extract(PackageInterface $package, $file, $path)
$command = 'unrar x -- ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
if (0 === $this->process->execute($command, $ignoredOutput)) {
- return \React\Promise\resolve();
+ return;
}
$processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
@@ -75,7 +87,5 @@ protected function extract(PackageInterface $package, $file, $path)
}
$rarArchive->close();
-
- return \React\Promise\resolve();
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/SvnDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/SvnDownloader.php
index f36b04917..4c26a6050 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/SvnDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/SvnDownloader.php
@@ -23,27 +23,12 @@
*/
class SvnDownloader extends VcsDownloader
{
- /** @var bool */
protected $cacheCredentials = true;
/**
* {@inheritDoc}
*/
- protected function doDownload(PackageInterface $package, $path, $url, PackageInterface $prevPackage = null)
- {
- SvnUtil::cleanEnv();
- $util = new SvnUtil($url, $this->io, $this->config, $this->process);
- if (null === $util->binaryVersion()) {
- throw new \RuntimeException('svn was not found in your PATH, skipping source download');
- }
-
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- protected function doInstall(PackageInterface $package, $path, $url)
+ public function doDownload(PackageInterface $package, $path, $url)
{
SvnUtil::cleanEnv();
$ref = $package->getSourceReference();
@@ -57,15 +42,13 @@ protected function doInstall(PackageInterface $package, $path, $url)
}
$this->io->writeError(" Checking out ".$package->getSourceReference());
- $this->execute($package, $url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
-
- return \React\Promise\resolve();
+ $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
}
/**
* {@inheritDoc}
*/
- protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
+ public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
{
SvnUtil::cleanEnv();
$ref = $target->getSourceReference();
@@ -74,16 +57,14 @@ protected function doUpdate(PackageInterface $initial, PackageInterface $target,
throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
}
- $util = new SvnUtil($url, $this->io, $this->config, $this->process);
+ $util = new SvnUtil($url, $this->io, $this->config);
$flags = "";
if (version_compare($util->binaryVersion(), '1.7.0', '>=')) {
$flags .= ' --ignore-ancestry';
}
$this->io->writeError(" Checking out " . $ref);
- $this->execute($target, $url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
-
- return \React\Promise\resolve();
+ $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
}
/**
@@ -112,15 +93,15 @@ public function getLocalChanges(PackageInterface $package, $path)
* @throws \RuntimeException
* @return string
*/
- protected function execute(PackageInterface $package, $baseUrl, $command, $url, $cwd = null, $path = null)
+ protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
{
- $util = new SvnUtil($baseUrl, $this->io, $this->config, $this->process);
+ $util = new SvnUtil($baseUrl, $this->io, $this->config);
$util->setCacheCredentials($this->cacheCredentials);
try {
return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
} catch (\RuntimeException $e) {
throw new \RuntimeException(
- $package->getPrettyName().' could not be downloaded, '.$e->getMessage()
+ 'Package could not be downloaded, '.$e->getMessage()
);
}
}
@@ -146,7 +127,7 @@ protected function cleanChanges(PackageInterface $package, $path, $update)
return ' '.$elem;
}, preg_split('{\s*\r?\n\s*}', $changes));
$countChanges = count($changes);
- $this->io->writeError(sprintf(' '.$package->getPrettyName().' has modified file%s: ', $countChanges === 1 ? '' : 's'));
+ $this->io->writeError(sprintf(' The package has modified file%s: ', $countChanges === 1 ? '' : 's'));
$this->io->writeError(array_slice($changes, 0, 10));
if ($countChanges > 10) {
$remainingChanges = $countChanges - 10;
@@ -189,7 +170,7 @@ protected function cleanChanges(PackageInterface $package, $path, $update)
*/
protected function getCommitLogs($fromReference, $toReference, $path)
{
- if (preg_match('{@(\d+)$}', $fromReference) && preg_match('{@(\d+)$}', $toReference)) {
+ if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
// retrieve the svn base url from the checkout folder
$command = sprintf('svn info --non-interactive --xml -- %s', ProcessExecutor::escape($path));
if (0 !== $this->process->execute($command, $output, $path)) {
@@ -213,7 +194,7 @@ protected function getCommitLogs($fromReference, $toReference, $path)
$command = sprintf('svn log -r%s:%s --incremental', ProcessExecutor::escape($fromRevision), ProcessExecutor::escape($toRevision));
- $util = new SvnUtil($baseUrl, $this->io, $this->config, $this->process);
+ $util = new SvnUtil($baseUrl, $this->io, $this->config);
$util->setCacheCredentials($this->cacheCredentials);
try {
return $util->executeLocal($command, $path, null, $this->io->isVerbose());
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/TarDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/TarDownloader.php
index 65346030e..34c43da5f 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/TarDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/TarDownloader.php
@@ -12,8 +12,6 @@
namespace Composer\Downloader;
-use Composer\Package\PackageInterface;
-
/**
* Downloader for tar files: tar, tar.gz or tar.bz2
*
@@ -24,12 +22,10 @@ class TarDownloader extends ArchiveDownloader
/**
* {@inheritDoc}
*/
- protected function extract(PackageInterface $package, $file, $path)
+ protected function extract($file, $path)
{
// Can throw an UnexpectedValueException
$archive = new \PharData($file);
$archive->extractTo($path, null, true);
-
- return \React\Promise\resolve();
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/TransportException.php b/app/vendor/composer/composer/src/Composer/Downloader/TransportException.php
index a478e5807..c682df080 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/TransportException.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/TransportException.php
@@ -17,14 +17,9 @@
*/
class TransportException extends \RuntimeException
{
- /** @var ?array */
protected $headers;
- /** @var ?string */
protected $response;
- /** @var ?int */
protected $statusCode;
- /** @var ?array */
- protected $responseInfo = array();
public function setHeaders($headers)
{
@@ -55,20 +50,4 @@ public function getStatusCode()
{
return $this->statusCode;
}
-
- /**
- * @return array
- */
- public function getResponseInfo()
- {
- return $this->responseInfo;
- }
-
- /**
- * @param array $responseInfo
- */
- public function setResponseInfo(array $responseInfo)
- {
- $this->responseInfo = $responseInfo;
- }
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php
index 53c573679..aa666058e 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/VcsDownloader.php
@@ -20,10 +20,6 @@
use Composer\Util\ProcessExecutor;
use Composer\IO\IOInterface;
use Composer\Util\Filesystem;
-use React\Promise\PromiseInterface;
-use Composer\DependencyResolver\Operation\UpdateOperation;
-use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\UninstallOperation;
/**
* @author Jordi Boggiano
@@ -38,8 +34,6 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
protected $process;
/** @var Filesystem */
protected $filesystem;
- /** @var array */
- protected $hasCleanedChanges = array();
public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
{
@@ -60,85 +54,44 @@ public function getInstallationSource()
/**
* {@inheritDoc}
*/
- public function download(PackageInterface $package, $path, PackageInterface $prevPackage = null)
+ public function download(PackageInterface $package, $path)
{
if (!$package->getSourceReference()) {
throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
}
- $urls = $this->prepareUrls($package->getSourceUrls());
+ $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . " ): ", false);
+ $this->filesystem->emptyDirectory($path);
+ $urls = $package->getSourceUrls();
while ($url = array_shift($urls)) {
try {
- return $this->doDownload($package, $path, $url, $prevPackage);
- } catch (\Exception $e) {
- // rethrow phpunit exceptions to avoid hard to debug bug failures
- if ($e instanceof \PHPUnit\Framework\Exception) {
- throw $e;
- }
- if ($this->io->isDebug()) {
- $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
- } elseif (count($urls)) {
- $this->io->writeError(' Failed, trying the next URL');
- }
- if (!count($urls)) {
- throw $e;
+ if (Filesystem::isLocalPath($url)) {
+ // realpath() below will not understand
+ // url that starts with "file://"
+ $needle = 'file://';
+ $isFileProtocol = false;
+ if (0 === strpos($url, $needle)) {
+ $url = substr($url, strlen($needle));
+ $isFileProtocol = true;
+ }
+
+ // realpath() below will not understand %20 spaces etc.
+ if (false !== strpos($url, '%')) {
+ $url = rawurldecode($url);
+ }
+
+ $url = realpath($url);
+
+ if ($isFileProtocol) {
+ $url = $needle . $url;
+ }
}
- }
- }
-
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- public function prepare($type, PackageInterface $package, $path, PackageInterface $prevPackage = null)
- {
- if ($type === 'update') {
- $this->cleanChanges($prevPackage, $path, true);
- $this->hasCleanedChanges[$prevPackage->getUniqueName()] = true;
- } elseif ($type === 'install') {
- $this->filesystem->emptyDirectory($path);
- } elseif ($type === 'uninstall') {
- $this->cleanChanges($package, $path, false);
- }
-
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- public function cleanup($type, PackageInterface $package, $path, PackageInterface $prevPackage = null)
- {
- if ($type === 'update' && isset($this->hasCleanedChanges[$prevPackage->getUniqueName()])) {
- $this->reapplyChanges($path);
- unset($this->hasCleanedChanges[$prevPackage->getUniqueName()]);
- }
-
- return \React\Promise\resolve();
- }
-
- /**
- * {@inheritDoc}
- */
- public function install(PackageInterface $package, $path)
- {
- if (!$package->getSourceReference()) {
- throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
- }
-
- $this->io->writeError(" - " . InstallOperation::format($package).': ', false);
-
- $urls = $this->prepareUrls($package->getSourceUrls());
- while ($url = array_shift($urls)) {
- try {
- $this->doInstall($package, $path, $url);
+ $this->doDownload($package, $path, $url);
break;
} catch (\Exception $e) {
// rethrow phpunit exceptions to avoid hard to debug bug failures
- if ($e instanceof \PHPUnit\Framework\Exception) {
+ if ($e instanceof \PHPUnit_Framework_Exception) {
throw $e;
}
if ($this->io->isDebug()) {
@@ -151,8 +104,6 @@ public function install(PackageInterface $package, $path)
}
}
}
-
- return \React\Promise\resolve();
}
/**
@@ -164,20 +115,40 @@ public function update(PackageInterface $initial, PackageInterface $target, $pat
throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
}
- $this->io->writeError(" - " . UpdateOperation::format($initial, $target).': ', false);
+ $name = $target->getName();
+ if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
+ if ($target->getSourceType() === 'svn') {
+ $from = $initial->getSourceReference();
+ $to = $target->getSourceReference();
+ } else {
+ $from = substr($initial->getSourceReference(), 0, 7);
+ $to = substr($target->getSourceReference(), 0, 7);
+ }
+ $name .= ' '.$initial->getPrettyVersion();
+ } else {
+ $from = $initial->getFullPrettyVersion();
+ $to = $target->getFullPrettyVersion();
+ }
+
+ $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
+ $this->io->writeError(" - " . $actionName . " " . $name . " (" . $from . " => " . $to . " ): ", false);
- $urls = $this->prepareUrls($target->getSourceUrls());
+ $this->cleanChanges($initial, $path, true);
+ $urls = $target->getSourceUrls();
$exception = null;
while ($url = array_shift($urls)) {
try {
+ if (Filesystem::isLocalPath($url)) {
+ $url = realpath($url);
+ }
$this->doUpdate($initial, $target, $path, $url);
$exception = null;
break;
} catch (\Exception $exception) {
// rethrow phpunit exceptions to avoid hard to debug bug failures
- if ($exception instanceof \PHPUnit\Framework\Exception) {
+ if ($exception instanceof \PHPUnit_Framework_Exception) {
throw $exception;
}
if ($this->io->isDebug()) {
@@ -188,6 +159,8 @@ public function update(PackageInterface $initial, PackageInterface $target, $pat
}
}
+ $this->reapplyChanges($path);
+
// print the commit logs if in verbose mode and VCS metadata is present
// because in case of missing metadata code would trigger another exception
if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
@@ -215,8 +188,6 @@ public function update(PackageInterface $initial, PackageInterface $target, $pat
if (!$urls && $exception) {
throw $exception;
}
-
- return \React\Promise\resolve();
}
/**
@@ -224,15 +195,20 @@ public function update(PackageInterface $initial, PackageInterface $target, $pat
*/
public function remove(PackageInterface $package, $path)
{
- $this->io->writeError(" - " . UninstallOperation::format($package));
-
- $promise = $this->filesystem->removeDirectoryAsync($path);
+ $this->io->writeError(" - Removing " . $package->getName() . " (" . $package->getPrettyVersion() . " )");
+ $this->cleanChanges($package, $path, false);
+ if (!$this->filesystem->removeDirectory($path)) {
+ throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
+ }
+ }
- return $promise->then(function ($result) use ($path) {
- if (!$result) {
- throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
- }
- });
+ /**
+ * Download progress information is not available for all VCS downloaders.
+ * {@inheritDoc}
+ */
+ public function setOutputProgress($outputProgress)
+ {
+ return $this;
}
/**
@@ -248,8 +224,6 @@ public function getVcsReference(PackageInterface $package, $path)
if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
return $packageVersion['commit'];
}
-
- return null;
}
/**
@@ -267,12 +241,10 @@ protected function cleanChanges(PackageInterface $package, $path, $update)
if (null !== $this->getLocalChanges($package, $path)) {
throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
}
-
- return \React\Promise\resolve();
}
/**
- * Reapply previously stashes changes if applicable, only called after an update (regardless if successful or not)
+ * Guarantee that no changes have been made to the local copy
*
* @param string $path
* @throws \RuntimeException in case the operation must be aborted or the patch does not apply cleanly
@@ -281,28 +253,14 @@ protected function reapplyChanges($path)
{
}
- /**
- * Downloads data needed to run an install/update later
- *
- * @param PackageInterface $package package instance
- * @param string $path download path
- * @param string $url package url
- * @param PackageInterface|null $prevPackage previous package (in case of an update)
- *
- * @return PromiseInterface|null
- */
- abstract protected function doDownload(PackageInterface $package, $path, $url, PackageInterface $prevPackage = null);
-
/**
* Downloads specific package into specific folder.
*
* @param PackageInterface $package package instance
* @param string $path download path
* @param string $url package url
- *
- * @return PromiseInterface|null
*/
- abstract protected function doInstall(PackageInterface $package, $path, $url);
+ abstract protected function doDownload(PackageInterface $package, $path, $url);
/**
* Updates specific package in specific folder from initial to target version.
@@ -311,8 +269,6 @@ abstract protected function doInstall(PackageInterface $package, $path, $url);
* @param PackageInterface $target updated package
* @param string $path download path
* @param string $url package url
- *
- * @return PromiseInterface|null
*/
abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
@@ -334,36 +290,4 @@ abstract protected function getCommitLogs($fromReference, $toReference, $path);
* @return bool
*/
abstract protected function hasMetadataRepository($path);
-
- /**
- * @return string[]
- */
- private function prepareUrls(array $urls)
- {
- foreach ($urls as $index => $url) {
- if (Filesystem::isLocalPath($url)) {
- // realpath() below will not understand
- // url that starts with "file://"
- $fileProtocol = 'file://';
- $isFileProtocol = false;
- if (0 === strpos($url, $fileProtocol)) {
- $url = substr($url, strlen($fileProtocol));
- $isFileProtocol = true;
- }
-
- // realpath() below will not understand %20 spaces etc.
- if (false !== strpos($url, '%')) {
- $url = rawurldecode($url);
- }
-
- $urls[$index] = realpath($url);
-
- if ($isFileProtocol) {
- $urls[$index] = $fileProtocol . $urls[$index];
- }
- }
- }
-
- return $urls;
- }
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/XzDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/XzDownloader.php
index 7e69a52bc..4a9b854d3 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/XzDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/XzDownloader.php
@@ -12,8 +12,13 @@
namespace Composer\Downloader;
+use Composer\Config;
+use Composer\Cache;
+use Composer\EventDispatcher\EventDispatcher;
use Composer\Package\PackageInterface;
use Composer\Util\ProcessExecutor;
+use Composer\Util\RemoteFilesystem;
+use Composer\IO\IOInterface;
/**
* Xz archive downloader.
@@ -23,16 +28,33 @@
*/
class XzDownloader extends ArchiveDownloader
{
- protected function extract(PackageInterface $package, $file, $path)
+ protected $process;
+
+ public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
+ {
+ $this->process = $process ?: new ProcessExecutor($io);
+
+ parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
+ }
+
+ protected function extract($file, $path)
{
$command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
if (0 === $this->process->execute($command, $ignoredOutput)) {
- return \React\Promise\resolve();
+ return;
}
$processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
throw new \RuntimeException($processError);
}
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getFileName(PackageInterface $package, $path)
+ {
+ return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
+ }
}
diff --git a/app/vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php b/app/vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php
index 2a93c9f9c..8aca21e59 100644
--- a/app/vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php
+++ b/app/vendor/composer/composer/src/Composer/Downloader/ZipDownloader.php
@@ -12,12 +12,16 @@
namespace Composer\Downloader;
+use Composer\Config;
+use Composer\Cache;
+use Composer\EventDispatcher\EventDispatcher;
use Composer\Package\PackageInterface;
use Composer\Util\IniHelper;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
+use Composer\Util\RemoteFilesystem;
+use Composer\IO\IOInterface;
use Symfony\Component\Process\ExecutableFinder;
-use React\Promise\PromiseInterface;
use ZipArchive;
/**
@@ -25,56 +29,37 @@
*/
class ZipDownloader extends ArchiveDownloader
{
- /** @var array */
- private static $unzipCommands;
- /** @var bool */
+ protected static $hasSystemUnzip;
private static $hasZipArchive;
- /** @var bool */
private static $isWindows;
- /** @var ZipArchive|null */
+ protected $process;
private $zipArchiveObject;
+ public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
+ {
+ $this->process = $process ?: new ProcessExecutor($io);
+ parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
+ }
+
/**
* {@inheritDoc}
*/
- public function download(PackageInterface $package, $path, PackageInterface $prevPackage = null, $output = true)
+ public function download(PackageInterface $package, $path, $output = true)
{
- if (null === self::$unzipCommands) {
- self::$unzipCommands = array();
+ if (null === self::$hasSystemUnzip) {
$finder = new ExecutableFinder;
- if (Platform::isWindows() && ($cmd = $finder->find('7z', null, array('C:\Program Files\7-Zip')))) {
- self::$unzipCommands[] = array('7z', ProcessExecutor::escape($cmd).' x -bb0 -y %s -o%s');
- }
- if ($cmd = $finder->find('unzip')) {
- self::$unzipCommands[] = array('unzip', ProcessExecutor::escape($cmd).' -qq %s -d %s');
- }
- if (!Platform::isWindows() && ($cmd = $finder->find('7z'))) { // 7z linux/macOS support is only used if unzip is not present
- self::$unzipCommands[] = array('7z', ProcessExecutor::escape($cmd).' x -bb0 -y %s -o%s');
- }
- if (!Platform::isWindows() && ($cmd = $finder->find('7zz'))) { // 7zz linux/macOS support is only used if unzip is not present
- self::$unzipCommands[] = array('7zz', ProcessExecutor::escape($cmd).' x -bb0 -y %s -o%s');
- }
- }
-
- $procOpenMissing = false;
- if (!function_exists('proc_open')) {
- self::$unzipCommands = array();
- $procOpenMissing = true;
+ self::$hasSystemUnzip = (bool) $finder->find('unzip');
}
if (null === self::$hasZipArchive) {
self::$hasZipArchive = class_exists('ZipArchive');
}
- if (!self::$hasZipArchive && !self::$unzipCommands) {
+ if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
// php.ini path is added to the error message to help users find the correct file
$iniMessage = IniHelper::getMessage();
- if ($procOpenMissing) {
- $error = "The zip extension is missing and unzip/7z commands cannot be called as proc_open is disabled, skipping.\n" . $iniMessage;
- } else {
- $error = "The zip extension and unzip/7z commands are both missing, skipping.\n" . $iniMessage;
- }
+ $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
throw new \RuntimeException($error);
}
@@ -82,100 +67,85 @@ public function download(PackageInterface $package, $path, PackageInterface $pre
if (null === self::$isWindows) {
self::$isWindows = Platform::isWindows();
- if (!self::$isWindows && !self::$unzipCommands) {
- if ($procOpenMissing) {
- $this->io->writeError("proc_open is disabled so 'unzip' and '7z' commands cannot be used, zip files are being unpacked using the PHP zip extension. ");
- $this->io->writeError("This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost. ");
- $this->io->writeError("Enabling proc_open and installing 'unzip' or '7z' may remediate them. ");
- } else {
- $this->io->writeError("As there is no 'unzip' nor '7z' command installed zip files are being unpacked using the PHP zip extension. ");
- $this->io->writeError("This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost. ");
- $this->io->writeError("Installing 'unzip' or '7z' may remediate them. ");
- }
+ if (!self::$isWindows && !self::$hasSystemUnzip) {
+ $this->io->writeError("As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension. ");
+ $this->io->writeError("This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost. ");
+ $this->io->writeError("Installing 'unzip' may remediate them. ");
}
}
- return parent::download($package, $path, $prevPackage, $output);
+ return parent::download($package, $path, $output);
}
/**
* extract $file to $path with "unzip" command
*
- * @param string $file File to extract
- * @param string $path Path where to extract file
- * @return PromiseInterface
+ * @param string $file File to extract
+ * @param string $path Path where to extract file
+ * @param bool $isLastChance If true it is called as a fallback and should throw an exception
+ * @return bool Success status
*/
- private function extractWithSystemUnzip(PackageInterface $package, $file, $path)
+ protected function extractWithSystemUnzip($file, $path, $isLastChance)
{
- // Force Exception throwing if the other alternative extraction method is not available
- $isLastChance = !self::$hasZipArchive;
+ if (!self::$hasZipArchive) {
+ // Force Exception throwing if the Other alternative is not available
+ $isLastChance = true;
+ }
- if (!self::$unzipCommands) {
+ if (!self::$hasSystemUnzip && !$isLastChance) {
// This was call as the favorite extract way, but is not available
// We switch to the alternative
- return $this->extractWithZipArchive($package, $file, $path);
- }
-
- $commandSpec = reset(self::$unzipCommands);
- $command = sprintf($commandSpec[1], ProcessExecutor::escape($file), ProcessExecutor::escape($path));
- // normalize separators to backslashes to avoid problems with 7-zip on windows
- // see https://github.com/composer/composer/issues/10058
- if (Platform::isWindows()) {
- $command = sprintf($commandSpec[1], ProcessExecutor::escape(strtr($file, '/', '\\')), ProcessExecutor::escape(strtr($path, '/', '\\')));
+ return $this->extractWithZipArchive($file, $path, true);
}
- $executable = $commandSpec[0];
+ $processError = null;
+ // When called after a ZipArchive failed, perhaps there is some files to overwrite
+ $overwrite = $isLastChance ? '-o' : '';
- $self = $this;
- $io = $this->io;
- $tryFallback = function ($processError) use ($isLastChance, $io, $self, $file, $path, $package, $executable) {
- if ($isLastChance) {
- throw $processError;
- }
+ $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
- if (!is_file($file)) {
- $io->writeError(' '.$processError->getMessage().' ');
- $io->writeError(' This most likely is due to a custom installer plugin not handling the returned Promise from the downloader ');
- $io->writeError(' See https://github.com/composer/installers/commit/5006d0c28730ade233a8f42ec31ac68fb1c5c9bb for an example fix ');
- } else {
- $io->writeError(' '.$processError->getMessage().' ');
- $io->writeError(' The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
- $io->writeError(' Unzip with '.$executable.' command failed, falling back to ZipArchive class');
+ try {
+ if (0 === $exitCode = $this->process->execute($command, $ignoredOutput)) {
+ return true;
}
- return $self->extractWithZipArchive($package, $file, $path);
- };
+ $processError = new \RuntimeException('Failed to execute ('.$exitCode.') '.$command."\n\n".$this->process->getErrorOutput());
+ } catch (\Exception $e) {
+ $processError = $e;
+ }
- try {
- $promise = $this->process->executeAsync($command);
+ if ($isLastChance) {
+ throw $processError;
+ }
- return $promise->then(function ($process) use ($tryFallback, $command, $package, $file) {
- if (!$process->isSuccessful()) {
- $output = $process->getErrorOutput();
- $output = str_replace(', '.$file.'.zip or '.$file.'.ZIP', '', $output);
+ $this->io->writeError(' '.$processError->getMessage());
+ $this->io->writeError(' The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
+ $this->io->writeError(' Unzip with unzip command failed, falling back to ZipArchive class');
- return $tryFallback(new \RuntimeException('Failed to extract '.$package->getName().': ('.$process->getExitCode().') '.$command."\n\n".$output));
- }
- });
- } catch (\Exception $e) {
- return $tryFallback($e);
- } catch (\Throwable $e) {
- return $tryFallback($e);
- }
+ return $this->extractWithZipArchive($file, $path, true);
}
/**
* extract $file to $path with ZipArchive
*
- * @param string $file File to extract
- * @param string $path Path where to extract file
- * @return PromiseInterface
- *
- * TODO v3 should make this private once we can drop PHP 5.3 support
- * @protected
+ * @param string $file File to extract
+ * @param string $path Path where to extract file
+ * @param bool $isLastChance If true it is called as a fallback and should throw an exception
+ * @return bool Success status
*/
- public function extractWithZipArchive(PackageInterface $package, $file, $path)
+ protected function extractWithZipArchive($file, $path, $isLastChance)
{
+ if (!self::$hasSystemUnzip) {
+ // Force Exception throwing if the Other alternative is not available
+ $isLastChance = true;
+ }
+
+ if (!self::$hasZipArchive && !$isLastChance) {
+ // This was call as the favorite extract way, but is not available
+ // We switch to the alternative
+ return $this->extractWithSystemUnzip($file, $path, true);
+ }
+
$processError = null;
$zipArchive = $this->zipArchiveObject ?: new ZipArchive();
@@ -186,7 +156,7 @@ public function extractWithZipArchive(PackageInterface $package, $file, $path)
if (true === $extractResult) {
$zipArchive->close();
- return \React\Promise\resolve();
+ return true;
}
$processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
@@ -197,26 +167,32 @@ public function extractWithZipArchive(PackageInterface $package, $file, $path)
$processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
} catch (\Exception $e) {
$processError = $e;
- } catch (\Throwable $e) {
- $processError = $e;
}
- throw $processError;
+ if ($isLastChance) {
+ throw $processError;
+ }
+
+ $this->io->writeError(' '.$processError->getMessage());
+ $this->io->writeError(' Unzip with ZipArchive class failed, falling back to unzip command');
+
+ return $this->extractWithSystemUnzip($file, $path, true);
}
/**
* extract $file to $path
*
- * @param string $file File to extract
- * @param string $path Path where to extract file
- * @return PromiseInterface|null
- *
- * TODO v3 should make this private once we can drop PHP 5.3 support
- * @protected
+ * @param string $file File to extract
+ * @param string $path Path where to extract file
*/
- public function extract(PackageInterface $package, $file, $path)
+ public function extract($file, $path)
{
- return $this->extractWithSystemUnzip($package, $file, $path);
+ // Each extract calls its alternative if not available or fails
+ if (self::$isWindows) {
+ $this->extractWithZipArchive($file, $path, false);
+ } else {
+ $this->extractWithSystemUnzip($file, $path, false);
+ }
}
/**
diff --git a/app/vendor/composer/composer/src/Composer/EventDispatcher/Event.php b/app/vendor/composer/composer/src/Composer/EventDispatcher/Event.php
index 51cfda4f8..2091f6be0 100644
--- a/app/vendor/composer/composer/src/Composer/EventDispatcher/Event.php
+++ b/app/vendor/composer/composer/src/Composer/EventDispatcher/Event.php
@@ -25,12 +25,12 @@ class Event
protected $name;
/**
- * @var string[] Arguments passed by the user, these will be forwarded to CLI script handlers
+ * @var array Arguments passed by the user, these will be forwarded to CLI script handlers
*/
protected $args;
/**
- * @var mixed[] Flags usable in PHP script handlers
+ * @var array Flags usable in PHP script handlers
*/
protected $flags;
@@ -42,9 +42,9 @@ class Event
/**
* Constructor.
*
- * @param string $name The event name
- * @param string[] $args Arguments passed by the user
- * @param mixed[] $flags Optional flags to pass data not as argument
+ * @param string $name The event name
+ * @param array $args Arguments passed by the user
+ * @param array $flags Optional flags to pass data not as argument
*/
public function __construct($name, array $args = array(), array $flags = array())
{
@@ -66,7 +66,7 @@ public function getName()
/**
* Returns the event's arguments.
*
- * @return string[] The event arguments
+ * @return array The event arguments
*/
public function getArguments()
{
@@ -76,7 +76,7 @@ public function getArguments()
/**
* Returns the event's flags.
*
- * @return mixed[] The event flags
+ * @return array The event flags
*/
public function getFlags()
{
diff --git a/app/vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php b/app/vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php
index ca23a1bdd..52b26d98e 100644
--- a/app/vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php
+++ b/app/vendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php
@@ -12,21 +12,20 @@
namespace Composer\EventDispatcher;
-use Composer\DependencyResolver\Transaction;
+use Composer\DependencyResolver\PolicyInterface;
+use Composer\DependencyResolver\Pool;
+use Composer\DependencyResolver\Request;
use Composer\Installer\InstallerEvent;
use Composer\IO\IOInterface;
use Composer\Composer;
-use Composer\Util\Platform;
use Composer\DependencyResolver\Operation\OperationInterface;
-use Composer\Repository\RepositoryInterface;
+use Composer\Repository\CompositeRepository;
use Composer\Script;
use Composer\Installer\PackageEvent;
use Composer\Installer\BinaryInstaller;
use Composer\Util\ProcessExecutor;
use Composer\Script\Event as ScriptEvent;
-use Composer\Autoload\ClassLoader;
use Symfony\Component\Process\PhpExecutableFinder;
-use Symfony\Component\Process\ExecutableFinder;
/**
* The Event Dispatcher.
@@ -43,19 +42,11 @@
*/
class EventDispatcher
{
- /** @var Composer */
protected $composer;
- /** @var IOInterface */
protected $io;
- /** @var ?ClassLoader */
protected $loader;
- /** @var ProcessExecutor */
protected $process;
- /** @var array>> */
- protected $listeners = array();
- /** @var bool */
- protected $runScripts = true;
- /** @var list */
+ protected $listeners;
private $eventStack;
/**
@@ -73,18 +64,6 @@ public function __construct(Composer $composer, IOInterface $io, ProcessExecutor
$this->eventStack = array();
}
- /**
- * Set whether script handlers are active or not
- *
- * @param bool $runScripts
- */
- public function setRunScripts($runScripts = true)
- {
- $this->runScripts = (bool) $runScripts;
-
- return $this;
- }
-
/**
* Dispatch an event
*
@@ -120,34 +99,40 @@ public function dispatchScript($eventName, $devMode = false, $additionalArgs = a
/**
* Dispatch a package event.
*
- * @param string $eventName The constant in PackageEvents
- * @param bool $devMode Whether or not we are in dev mode
- * @param RepositoryInterface $localRepo The installed repository
- * @param array $operations The list of operations
- * @param OperationInterface $operation The package being installed/updated/removed
+ * @param string $eventName The constant in PackageEvents
+ * @param bool $devMode Whether or not we are in dev mode
+ * @param PolicyInterface $policy The policy
+ * @param Pool $pool The pool
+ * @param CompositeRepository $installedRepo The installed repository
+ * @param Request $request The request
+ * @param array $operations The list of operations
+ * @param OperationInterface $operation The package being installed/updated/removed
*
* @return int return code of the executed script if any, for php scripts a false return
* value is changed to 1, anything else to 0
*/
- public function dispatchPackageEvent($eventName, $devMode, RepositoryInterface $localRepo, array $operations, OperationInterface $operation)
+ public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
{
- return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $localRepo, $operations, $operation));
+ return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
}
/**
* Dispatch a installer event.
*
- * @param string $eventName The constant in InstallerEvents
- * @param bool $devMode Whether or not we are in dev mode
- * @param bool $executeOperations True if operations will be executed, false in --dry-run
- * @param Transaction $transaction The transaction contains the list of operations
+ * @param string $eventName The constant in InstallerEvents
+ * @param bool $devMode Whether or not we are in dev mode
+ * @param PolicyInterface $policy The policy
+ * @param Pool $pool The pool
+ * @param CompositeRepository $installedRepo The installed repository
+ * @param Request $request The request
+ * @param array $operations The list of operations
*
* @return int return code of the executed script if any, for php scripts a false return
* value is changed to 1, anything else to 0
*/
- public function dispatchInstallerEvent($eventName, $devMode, $executeOperations, Transaction $transaction)
+ public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
{
- return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $executeOperations, $transaction));
+ return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
}
/**
@@ -160,189 +145,132 @@ public function dispatchInstallerEvent($eventName, $devMode, $executeOperations,
*/
protected function doDispatch(Event $event)
{
- if (getenv('COMPOSER_DEBUG_EVENTS')) {
- $details = null;
- if ($event instanceof PackageEvent) {
- $details = (string) $event->getOperation();
- }
- $this->io->writeError('Dispatching '.$event->getName().' '.($details ? ' ('.$details.')' : '').' event');
- }
-
$listeners = $this->getListeners($event);
$this->pushEvent($event);
- try {
- $returnMax = 0;
- foreach ($listeners as $callable) {
- $return = 0;
- $this->ensureBinDirIsInPath();
+ $return = 0;
+ foreach ($listeners as $callable) {
- if (!is_string($callable)) {
- if (!is_callable($callable)) {
- $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
+ $this->ensureBinDirIsInPath();
- throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
- }
- if (is_array($callable) && (is_string($callable[0]) || is_object($callable[0])) && is_string($callable[1])) {
- $this->io->writeError(sprintf('> %s: %s', $event->getName(), (is_object($callable[0]) ? get_class($callable[0]) : $callable[0]).'->'.$callable[1]), true, IOInterface::VERBOSE);
- }
- $return = false === call_user_func($callable, $event) ? 1 : 0;
- } elseif ($this->isComposerScript($callable)) {
- $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
-
- $script = explode(' ', substr($callable, 1));
- $scriptName = $script[0];
- unset($script[0]);
-
- $args = array_merge($script, $event->getArguments());
- $flags = $event->getFlags();
- if (strpos($callable, '@composer ') === 0) {
- $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . ' ' . implode(' ', $args);
- if (0 !== ($exitCode = $this->executeTty($exec))) {
- $this->io->writeError(sprintf('Script %s handling the %s event returned with error code '.$exitCode.' ', $callable, $event->getName()), true, IOInterface::QUIET);
-
- throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
- }
- } else {
- if (!$this->getListeners(new Event($scriptName))) {
- $this->io->writeError(sprintf('You made a reference to a non-existent script %s ', $callable), true, IOInterface::QUIET);
- }
+ if (!is_string($callable)) {
+ if (!is_callable($callable)) {
+ $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
- try {
- /** @var InstallerEvent $event */
- $scriptEvent = new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags);
- $scriptEvent->setOriginatingEvent($event);
- $return = $this->dispatch($scriptName, $scriptEvent);
- } catch (ScriptExecutionException $e) {
- $this->io->writeError(sprintf('Script %s was called via %s ', $callable, $event->getName()), true, IOInterface::QUIET);
- throw $e;
- }
- }
- } elseif ($this->isPhpScript($callable)) {
- $className = substr($callable, 0, strpos($callable, '::'));
- $methodName = substr($callable, strpos($callable, '::') + 2);
+ throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
+ }
+ $event = $this->checkListenerExpectedEvent($callable, $event);
+ $return = false === call_user_func($callable, $event) ? 1 : 0;
+ } elseif ($this->isComposerScript($callable)) {
+ $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
+
+ $script = explode(' ', substr($callable, 1));
+ $scriptName = $script[0];
+ unset($script[0]);
+
+ $args = array_merge($script, $event->getArguments());
+ $flags = $event->getFlags();
+ if (substr($callable, 0, 10) === '@composer ') {
+ $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
+ if (0 !== ($exitCode = $this->process->execute($exec))) {
+ $this->io->writeError(sprintf('Script %s handling the %s event returned with error code '.$exitCode.' ', $callable, $event->getName()), true, IOInterface::QUIET);
- if (!class_exists($className)) {
- $this->io->writeError('Class '.$className.' is not autoloadable, can not call '.$event->getName().' script ', true, IOInterface::QUIET);
- continue;
+ throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
}
- if (!is_callable($callable)) {
- $this->io->writeError('Method '.$callable.' is not callable, can not call '.$event->getName().' script ', true, IOInterface::QUIET);
- continue;
+ } else {
+ if (!$this->getListeners(new Event($scriptName))) {
+ $this->io->writeError(sprintf('You made a reference to a non-existent script %s ', $callable), true, IOInterface::QUIET);
}
try {
- $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
- } catch (\Exception $e) {
- $message = "Script %s handling the %s event terminated with an exception";
- $this->io->writeError(''.sprintf($message, $callable, $event->getName()).' ', true, IOInterface::QUIET);
+ $scriptEvent = new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags);
+ $scriptEvent->setOriginatingEvent($event);
+ $return = $this->dispatch($scriptName, $scriptEvent);
+ } catch (ScriptExecutionException $e) {
+ $this->io->writeError(sprintf('Script %s was called via %s ', $callable, $event->getName()), true, IOInterface::QUIET);
throw $e;
}
- } else {
- $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
- $exec = $callable . ($args === '' ? '' : ' '.$args);
- if ($this->io->isVerbose()) {
- $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
- } elseif ($event->getName() !== '__exec_command') {
- // do not output the command being run when using `composer exec` as it is fairly obvious the user is running it
- $this->io->writeError(sprintf('> %s', $exec));
- }
-
- $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
- if ($possibleLocalBinaries) {
- foreach ($possibleLocalBinaries as $localExec) {
- if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
- $caller = BinaryInstaller::determineBinaryCaller($localExec);
- $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
- break;
- }
- }
- }
+ }
+ } elseif ($this->isPhpScript($callable)) {
+ $className = substr($callable, 0, strpos($callable, '::'));
+ $methodName = substr($callable, strpos($callable, '::') + 2);
- if (strpos($exec, '@putenv ') === 0) {
- if (false === strpos($exec, '=')) {
- Platform::clearEnv(substr($exec, 8));
- } else {
- list($var, $value) = explode('=', substr($exec, 8), 2);
- Platform::putEnv($var, $value);
- }
+ if (!class_exists($className)) {
+ $this->io->writeError('Class '.$className.' is not autoloadable, can not call '.$event->getName().' script ', true, IOInterface::QUIET);
+ continue;
+ }
+ if (!is_callable($callable)) {
+ $this->io->writeError('Method '.$callable.' is not callable, can not call '.$event->getName().' script ', true, IOInterface::QUIET);
+ continue;
+ }
- continue;
- }
- if (strpos($exec, '@php ') === 0) {
- $pathAndArgs = substr($exec, 5);
- if (Platform::isWindows()) {
- $pathAndArgs = preg_replace_callback('{^\S+}', function ($path) {
- return str_replace('/', '\\', $path[0]);
- }, $pathAndArgs);
- }
- // match somename (not in quote, and not a qualified path) and if it is not a valid path from CWD then try to find it
- // in $PATH. This allows support for `@php foo` where foo is a binary name found in PATH but not an actual relative path
- $matched = preg_match('{^[^\'"\s/\\\\]+}', $pathAndArgs, $match);
- if ($matched && !file_exists($match[0])) {
- $finder = new ExecutableFinder;
- if ($pathToExec = $finder->find($match[0])) {
- $pathAndArgs = $pathToExec . substr($pathAndArgs, strlen($match[0]));
- }
- }
- $exec = $this->getPhpExecCommand() . ' ' . $pathAndArgs;
- } else {
- $finder = new PhpExecutableFinder();
- $phpPath = $finder->find(false);
- if ($phpPath) {
- Platform::putEnv('PHP_BINARY', $phpPath);
- }
+ try {
+ $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
+ } catch (\Exception $e) {
+ $message = "Script %s handling the %s event terminated with an exception";
+ $this->io->writeError(''.sprintf($message, $callable, $event->getName()).' ', true, IOInterface::QUIET);
+ throw $e;
+ }
+ } else {
+ $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
+ $exec = $callable . ($args === '' ? '' : ' '.$args);
+ if ($this->io->isVerbose()) {
+ $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
+ } else {
+ $this->io->writeError(sprintf('> %s', $exec));
+ }
- if (Platform::isWindows()) {
- $exec = preg_replace_callback('{^\S+}', function ($path) {
- return str_replace('/', '\\', $path[0]);
- }, $exec);
+ $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
+ if ($possibleLocalBinaries) {
+ foreach ($possibleLocalBinaries as $localExec) {
+ if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
+ $caller = BinaryInstaller::determineBinaryCaller($localExec);
+ $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
+ break;
}
}
+ }
- // if composer is being executed, make sure it runs the expected composer from current path
- // resolution, even if bin-dir contains composer too because the project requires composer/composer
- // see https://github.com/composer/composer/issues/8748
- if (strpos($exec, 'composer ') === 0) {
- $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($exec, 8);
- }
+ if (substr($exec, 0, 8) === '@putenv ') {
+ putenv(substr($exec, 8));
+ list($var, $value) = explode('=', substr($exec, 8), 2);
+ $_SERVER[$var] = $value;
- if (0 !== ($exitCode = $this->executeTty($exec))) {
- $this->io->writeError(sprintf('Script %s handling the %s event returned with error code '.$exitCode.' ', $callable, $event->getName()), true, IOInterface::QUIET);
-
- throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
+ continue;
+ } elseif (substr($exec, 0, 5) === '@php ') {
+ $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
+ } else {
+ $finder = new PhpExecutableFinder();
+ $phpPath = $finder->find(false);
+ if ($phpPath) {
+ $_SERVER['PHP_BINARY'] = $phpPath;
+ putenv('PHP_BINARY=' . $_SERVER['PHP_BINARY']);
}
}
- $returnMax = max($returnMax, $return);
+ // if composer is being executed, make sure it runs the expected composer from current path
+ // resolution, even if bin-dir contains composer too because the project requires composer/composer
+ // see https://github.com/composer/composer/issues/8748
+ if (substr($exec, 0, 9) === 'composer ') {
+ $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($exec, 8);
+ }
+
+ if (0 !== ($exitCode = $this->process->execute($exec))) {
+ $this->io->writeError(sprintf('Script %s handling the %s event returned with error code '.$exitCode.' ', $callable, $event->getName()), true, IOInterface::QUIET);
- if ($event->isPropagationStopped()) {
- break;
+ throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
}
}
- } catch (\Exception $e) { // TODO Composer 2.2 turn all this into a finally
- $this->popEvent();
- throw $e;
- } catch (\Throwable $e) {
- $this->popEvent();
-
- throw $e;
+ if ($event->isPropagationStopped()) {
+ break;
+ }
}
$this->popEvent();
- return $returnMax;
- }
-
- protected function executeTty($exec)
- {
- if ($this->io->isInteractive()) {
- return $this->process->executeTty($exec);
- }
-
- return $this->process->execute($exec);
+ return $return;
}
protected function getPhpExecCommand()
@@ -368,6 +296,8 @@ protected function getPhpExecCommand()
*/
protected function executeEventPhpScript($className, $methodName, Event $event)
{
+ $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
+
if ($this->io->isVerbose()) {
$this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
} else {
@@ -377,6 +307,102 @@ protected function executeEventPhpScript($className, $methodName, Event $event)
return $className::$methodName($event);
}
+ /**
+ * @param mixed $target
+ * @param Event $event
+ * @return Event
+ */
+ protected function checkListenerExpectedEvent($target, Event $event)
+ {
+ if (in_array($event->getName(), array(
+ 'init',
+ 'command',
+ 'pre-file-download',
+ ), true)) {
+ return $event;
+ }
+
+ try {
+ $reflected = new \ReflectionParameter($target, 0);
+ } catch (\Exception $e) {
+ return $event;
+ }
+
+ $expected = null;
+ $isClass = false;
+ if (\PHP_VERSION_ID >= 70000) {
+ $reflectionType = $reflected->getType();
+ if ($reflectionType) {
+ $expected = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string)$reflectionType;
+ $isClass = !$reflectionType->isBuiltin();
+ }
+ } else {
+ $expected = $reflected->getClass() ? $reflected->getClass()->getName() : null;
+ $isClass = null !== $expected;
+ }
+
+ if (!$isClass) {
+ return $event;
+ }
+
+ // BC support
+ if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
+ trigger_error('The callback '.$this->serializeCallback($target).' declared at '.$reflected->getDeclaringFunction()->getFileName().' accepts a '.$expected.' but '.$event->getName().' events use a '.get_class($event).' instance. Please adjust your type hint accordingly, see https://getcomposer.org/doc/articles/scripts.md#event-classes', E_USER_DEPRECATED);
+ $event = new \Composer\Script\CommandEvent(
+ $event->getName(),
+ $event->getComposer(),
+ $event->getIO(),
+ $event->isDevMode(),
+ $event->getArguments()
+ );
+ }
+ if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
+ trigger_error('The callback '.$this->serializeCallback($target).' declared at '.$reflected->getDeclaringFunction()->getFileName().' accepts a '.$expected.' but '.$event->getName().' events use a '.get_class($event).' instance. Please adjust your type hint accordingly, see https://getcomposer.org/doc/articles/scripts.md#event-classes', E_USER_DEPRECATED);
+ $event = new \Composer\Script\PackageEvent(
+ $event->getName(),
+ $event->getComposer(),
+ $event->getIO(),
+ $event->isDevMode(),
+ $event->getPolicy(),
+ $event->getPool(),
+ $event->getInstalledRepo(),
+ $event->getRequest(),
+ $event->getOperations(),
+ $event->getOperation()
+ );
+ }
+ if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
+ trigger_error('The callback '.$this->serializeCallback($target).' declared at '.$reflected->getDeclaringFunction()->getFileName().' accepts a '.$expected.' but '.$event->getName().' events use a '.get_class($event).' instance. Please adjust your type hint accordingly, see https://getcomposer.org/doc/articles/scripts.md#event-classes', E_USER_DEPRECATED);
+ $event = new \Composer\Script\Event(
+ $event->getName(),
+ $event->getComposer(),
+ $event->getIO(),
+ $event->isDevMode(),
+ $event->getArguments(),
+ $event->getFlags()
+ );
+ }
+
+ return $event;
+ }
+
+ private function serializeCallback($cb)
+ {
+ if (is_array($cb) && count($cb) === 2) {
+ if (is_object($cb[0])) {
+ $cb[0] = get_class($cb[0]);
+ }
+ if (is_string($cb[0]) && is_string($cb[1])) {
+ $cb = implode('::', $cb);
+ }
+ }
+ if (is_string($cb)) {
+ return $cb;
+ }
+
+ return var_export($cb, true);
+ }
+
/**
* Add a listener for a particular event
*
@@ -389,22 +415,6 @@ public function addListener($eventName, $listener, $priority = 0)
$this->listeners[$eventName][$priority][] = $listener;
}
- /**
- * @param callable|object $listener A callable or an object instance for which all listeners should be removed
- */
- public function removeListener($listener)
- {
- foreach ($this->listeners as $eventName => $priorities) {
- foreach ($priorities as $priority => $listeners) {
- foreach ($listeners as $index => $candidate) {
- if ($listener === $candidate || (is_array($candidate) && is_object($listener) && $candidate[0] === $listener)) {
- unset($this->listeners[$eventName][$priority][$index]);
- }
- }
- }
- }
- }
-
/**
* Adds object methods as listeners for the events in getSubscribedEvents
*
@@ -435,7 +445,7 @@ public function addSubscriber(EventSubscriberInterface $subscriber)
*/
protected function getListeners(Event $event)
{
- $scriptListeners = $this->runScripts ? $this->getScriptListeners($event) : array();
+ $scriptListeners = $this->getScriptListeners($event);
if (!isset($this->listeners[$event->getName()][0])) {
$this->listeners[$event->getName()][0] = array();
@@ -488,8 +498,8 @@ protected function getScriptListeners(Event $event)
$packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
$packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
$map = $generator->parseAutoloads($packageMap, $package);
- $this->loader = $generator->createLoader($map, $this->composer->getConfig()->get('vendor-dir'));
- $this->loader->register(false);
+ $this->loader = $generator->createLoader($map);
+ $this->loader->register();
return $scripts[$event->getName()];
}
@@ -513,7 +523,7 @@ protected function isPhpScript($callable)
*/
protected function isComposerScript($callable)
{
- return strpos($callable, '@') === 0 && strpos($callable, '@php ') !== 0 && strpos($callable, '@putenv ') !== 0;
+ return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5) && '@putenv ' !== substr($callable, 0, 8);
}
/**
@@ -521,7 +531,7 @@ protected function isComposerScript($callable)
*
* @param Event $event
* @throws \RuntimeException
- * @return int
+ * @return number
*/
protected function pushEvent(Event $event)
{
@@ -555,7 +565,8 @@ private function ensureBinDirIsInPath()
if (is_dir($binDir)) {
$binDir = realpath($binDir);
if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
- Platform::putEnv($pathStr, $binDir.PATH_SEPARATOR.getenv($pathStr));
+ $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
+ putenv($pathStr.'='.$_SERVER[$pathStr]);
}
}
}
diff --git a/app/vendor/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php b/app/vendor/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php
deleted file mode 100644
index 72a833c72..000000000
--- a/app/vendor/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php
+++ /dev/null
@@ -1,20 +0,0 @@
-
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\Exception;
-
-/**
- * @author Jordi Boggiano
- */
-class IrrecoverableDownloadException extends \RuntimeException
-{
-}
diff --git a/app/vendor/composer/composer/src/Composer/Exception/NoSslException.php b/app/vendor/composer/composer/src/Composer/Exception/NoSslException.php
index 55c81fea9..017cac382 100644
--- a/app/vendor/composer/composer/src/Composer/Exception/NoSslException.php
+++ b/app/vendor/composer/composer/src/Composer/Exception/NoSslException.php
@@ -13,8 +13,6 @@
namespace Composer\Exception;
/**
- * Specific exception for Composer\Util\HttpDownloader creation.
- *
* @author Jordi Boggiano
*/
class NoSslException extends \RuntimeException
diff --git a/app/vendor/composer/composer/src/Composer/Factory.php b/app/vendor/composer/composer/src/Composer/Factory.php
index d67ccf29a..acb483294 100644
--- a/app/vendor/composer/composer/src/Composer/Factory.php
+++ b/app/vendor/composer/composer/src/Composer/Factory.php
@@ -17,15 +17,13 @@
use Composer\IO\IOInterface;
use Composer\Package\Archiver;
use Composer\Package\Version\VersionGuesser;
-use Composer\Package\RootPackageInterface;
use Composer\Repository\RepositoryManager;
use Composer\Repository\RepositoryFactory;
use Composer\Repository\WritableRepositoryInterface;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor;
-use Composer\Util\HttpDownloader;
-use Composer\Util\Loop;
+use Composer\Util\RemoteFilesystem;
use Composer\Util\Silencer;
use Composer\Plugin\PluginEvents;
use Composer\EventDispatcher\Event;
@@ -37,8 +35,6 @@
use Composer\Autoload\AutoloadGenerator;
use Composer\Package\Version\VersionParser;
use Composer\Downloader\TransportException;
-use Composer\Json\JsonValidationException;
-use Composer\Repository\InstalledRepositoryInterface;
use Seld\JsonLint\JsonParser;
/**
@@ -71,29 +67,18 @@ protected static function getHomeDir()
}
$userDir = self::getUserDir();
- $dirs = array();
+ if (is_dir($userDir . '/.composer')) {
+ return $userDir . '/.composer';
+ }
if (self::useXdg()) {
// XDG Base Directory Specifications
- $xdgConfig = getenv('XDG_CONFIG_HOME');
- if (!$xdgConfig) {
- $xdgConfig = $userDir . '/.config';
- }
+ $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
- $dirs[] = $xdgConfig . '/composer';
+ return $xdgConfig . '/composer';
}
- $dirs[] = $userDir . '/.composer';
-
- // select first dir which exists of: $XDG_CONFIG_HOME/composer or ~/.composer
- foreach ($dirs as $dir) {
- if (Silencer::call('is_dir', $dir)) {
- return $dir;
- }
- }
-
- // if none exists, we default to first defined one (XDG one if system uses it, or ~/.composer otherwise)
- return $dirs[0];
+ return $userDir . '/.composer';
}
/**
@@ -123,15 +108,6 @@ protected static function getCacheDir($home)
}
$userDir = self::getUserDir();
- if (PHP_OS === 'Darwin') {
- // Migrate existing cache dir in old location if present
- if (is_dir($home . '/cache') && !is_dir($userDir . '/Library/Caches/composer')) {
- Silencer::call('rename', $home . '/cache', $userDir . '/Library/Caches/composer');
- }
-
- return $userDir . '/Library/Caches/composer';
- }
-
if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
return $home . '/cache';
}
@@ -246,13 +222,6 @@ public static function getComposerFile()
return trim(getenv('COMPOSER')) ?: './composer.json';
}
- public static function getLockFile($composerFile)
- {
- return "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
- ? substr($composerFile, 0, -4).'lock'
- : $composerFile . '.lock';
- }
-
public static function createAdditionalStyles()
{
return array(
@@ -274,6 +243,14 @@ public static function createOutput()
return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
}
+ /**
+ * @deprecated Use Composer\Repository\RepositoryFactory::defaultRepos instead
+ */
+ public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
+ {
+ return RepositoryFactory::defaultRepos($io, $config, $rm);
+ }
+
/**
* Creates a Composer instance
*
@@ -306,17 +283,11 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
} else {
$message = 'Composer could not find the config file: '.$localConfig;
}
- $instructions = $fullLoad ? 'To initialize a project, please create a composer.json file. See https://getcomposer.org/basic-usage' : '';
+ $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
}
- try {
- $file->validateSchema(JsonFile::LAX_SCHEMA);
- } catch (JsonValidationException $e) {
- $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
- $message = $e->getMessage() . ':' . PHP_EOL . $errors;
- throw new JsonValidationException($message);
- }
+ $file->validateSchema(JsonFile::LAX_SCHEMA);
$jsonParser = new JsonParser;
try {
$jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
@@ -332,7 +303,7 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
$config = static::createConfig($io, $cwd);
$config->merge($localConfig);
if (isset($composerFile)) {
- $io->writeError('Loading config file ' . $composerFile .' ('.realpath($composerFile).')', true, IOInterface::DEBUG);
+ $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
$config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
$localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
@@ -352,26 +323,21 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
if ($fullLoad) {
// load auth configs into the IO instance
$io->loadConfiguration($config);
-
- // load existing Composer\InstalledVersions instance if available
- if (!class_exists('Composer\InstalledVersions', false) && file_exists($installedVersionsPath = $config->get('vendor-dir').'/composer/InstalledVersions.php')) {
- include $installedVersionsPath;
- }
}
- $httpDownloader = self::createHttpDownloader($io, $config);
- $process = new ProcessExecutor($io);
- $loop = new Loop($httpDownloader, $process);
- $composer->setLoop($loop);
+ $rfs = self::createRemoteFilesystem($io, $config);
// initialize event dispatcher
- $dispatcher = new EventDispatcher($composer, $io, $process);
+ $dispatcher = new EventDispatcher($composer, $io);
$composer->setEventDispatcher($dispatcher);
// initialize repository manager
- $rm = RepositoryFactory::manager($io, $config, $httpDownloader, $dispatcher, $process);
+ $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
$composer->setRepositoryManager($rm);
+ // load local repository
+ $this->addLocalRepository($io, $rm, $vendorDir);
+
// force-set the version of the global package if not defined as
// guessing it adds no value and only takes time
if (!$fullLoad && !isset($localConfig['version'])) {
@@ -380,21 +346,18 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
// load package
$parser = new VersionParser;
- $guesser = new VersionGuesser($config, $process, $parser);
- $loader = $this->loadRootPackage($rm, $config, $parser, $guesser, $io);
+ $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
+ $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io);
$package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
$composer->setPackage($package);
- // load local repository
- $this->addLocalRepository($io, $rm, $vendorDir, $package, $process);
-
// initialize installation manager
- $im = $this->createInstallationManager($loop, $io, $dispatcher);
+ $im = $this->createInstallationManager();
$composer->setInstallationManager($im);
if ($fullLoad) {
// initialize download manager
- $dm = $this->createDownloadManager($io, $config, $httpDownloader, $process, $dispatcher);
+ $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
$composer->setDownloadManager($dm);
// initialize autoload generator
@@ -402,12 +365,12 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
$composer->setAutoloadGenerator($generator);
// initialize archive manager
- $am = $this->createArchiveManager($config, $dm, $loop);
+ $am = $this->createArchiveManager($config, $dm);
$composer->setArchiveManager($am);
}
// add installers to the manager (must happen after download manager is created since they read it out of $composer)
- $this->createDefaultInstallers($im, $composer, $io, $process);
+ $this->createDefaultInstallers($im, $composer, $io);
if ($fullLoad) {
$globalComposer = null;
@@ -423,9 +386,11 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
// init locker if possible
if ($fullLoad && isset($composerFile)) {
- $lockFile = self::getLockFile($composerFile);
+ $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
+ ? substr($composerFile, 0, -4).'lock'
+ : $composerFile . '.lock';
- $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $im, file_get_contents($composerFile), $process);
+ $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
$composer->setLocker($locker);
}
@@ -435,16 +400,18 @@ public function createComposer(IOInterface $io, $localConfig = null, $disablePlu
// once everything is initialized we can
// purge packages from local repos if they have been deleted on the filesystem
- $this->purgePackages($rm->getLocalRepository(), $im);
+ if ($rm->getLocalRepository()) {
+ $this->purgePackages($rm->getLocalRepository(), $im);
+ }
}
return $composer;
}
/**
- * @param IOInterface $io IO instance
- * @param bool $disablePlugins Whether plugins should not be loaded
- * @return Composer|null
+ * @param IOInterface $io IO instance
+ * @param bool $disablePlugins Whether plugins should not be loaded
+ * @return Composer
*/
public static function createGlobal(IOInterface $io, $disablePlugins = false)
{
@@ -457,14 +424,9 @@ public static function createGlobal(IOInterface $io, $disablePlugins = false)
* @param Repository\RepositoryManager $rm
* @param string $vendorDir
*/
- protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir, RootPackageInterface $rootPackage, ProcessExecutor $process = null)
+ protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
{
- $fs = null;
- if ($process) {
- $fs = new Filesystem($process);
- }
-
- $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io), true, $rootPackage, $fs));
+ $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
}
/**
@@ -489,17 +451,14 @@ protected function createGlobalComposer(IOInterface $io, Config $config, $disabl
* @param EventDispatcher $eventDispatcher
* @return Downloader\DownloadManager
*/
- public function createDownloadManager(IOInterface $io, Config $config, HttpDownloader $httpDownloader, ProcessExecutor $process, EventDispatcher $eventDispatcher = null)
+ public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
{
$cache = null;
if ($config->get('cache-files-ttl') > 0) {
$cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
- $cache->setReadOnly($config->get('cache-read-only'));
}
- $fs = new Filesystem($process);
-
- $dm = new Downloader\DownloadManager($io, false, $fs);
+ $dm = new Downloader\DownloadManager($io);
switch ($preferred = $config->get('preferred-install')) {
case 'dist':
$dm->setPreferDist(true);
@@ -517,19 +476,22 @@ public function createDownloadManager(IOInterface $io, Config $config, HttpDownl
$dm->setPreferences($preferred);
}
- $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $process, $fs));
- $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $process, $fs));
- $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $process, $fs));
- $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $process, $fs));
- $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config, $process, $fs));
- $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
- $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
- $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
- $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
- $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
- $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
- $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
- $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process));
+ $executor = new ProcessExecutor($io);
+ $fs = new Filesystem($executor);
+
+ $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
+ $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
+ $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
+ $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
+ $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
+ $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
+ $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
+ $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
+ $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
+ $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
+ $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
+ $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
+ $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
return $dm;
}
@@ -539,9 +501,15 @@ public function createDownloadManager(IOInterface $io, Config $config, HttpDownl
* @param Downloader\DownloadManager $dm Manager use to download sources
* @return Archiver\ArchiveManager
*/
- public function createArchiveManager(Config $config, Downloader\DownloadManager $dm, Loop $loop)
+ public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
{
- $am = new Archiver\ArchiveManager($dm, $loop);
+ if (null === $dm) {
+ $io = new IO\NullIO();
+ $io->loadConfiguration($config);
+ $dm = $this->createDownloadManager($io, $config);
+ }
+
+ $am = new Archiver\ArchiveManager($dm);
$am->addArchiver(new Archiver\ZipArchiver);
$am->addArchiver(new Archiver\PharArchiver);
@@ -563,9 +531,9 @@ protected function createPluginManager(IOInterface $io, Composer $composer, Comp
/**
* @return Installer\InstallationManager
*/
- public function createInstallationManager(Loop $loop, IOInterface $io, EventDispatcher $eventDispatcher = null)
+ protected function createInstallationManager()
{
- return new Installer\InstallationManager($loop, $io, $eventDispatcher);
+ return new Installer\InstallationManager();
}
/**
@@ -573,21 +541,19 @@ public function createInstallationManager(Loop $loop, IOInterface $io, EventDisp
* @param Composer $composer
* @param IO\IOInterface $io
*/
- protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io, ProcessExecutor $process = null)
+ protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
{
- $fs = new Filesystem($process);
- $binaryInstaller = new Installer\BinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $fs);
-
- $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null, $fs, $binaryInstaller));
- $im->addInstaller(new Installer\PluginInstaller($io, $composer, $fs, $binaryInstaller));
+ $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
+ $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
+ $im->addInstaller(new Installer\PluginInstaller($io, $composer));
$im->addInstaller(new Installer\MetapackageInstaller($io));
}
/**
- * @param InstalledRepositoryInterface $repo repository to purge packages from
+ * @param WritableRepositoryInterface $repo repository to purge packages from
* @param Installer\InstallationManager $im manager to check whether packages are still installed
*/
- protected function purgePackages(InstalledRepositoryInterface $repo, Installer\InstallationManager $im)
+ protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
{
foreach ($repo->getPackages() as $package) {
if (!$im->isPackageInstalled($repo, $package)) {
@@ -596,11 +562,6 @@ protected function purgePackages(InstalledRepositoryInterface $repo, Installer\I
}
}
- protected function loadRootPackage(RepositoryManager $rm, Config $config, VersionParser $parser, VersionGuesser $guesser, IOInterface $io)
- {
- return new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io);
- }
-
/**
* @param IOInterface $io IO instance
* @param mixed $config either a configuration array or a filename to read from, if null it will read from
@@ -616,14 +577,12 @@ public static function create(IOInterface $io, $config = null, $disablePlugins =
}
/**
- * If you are calling this in a plugin, you probably should instead use $composer->getLoop()->getHttpDownloader()
- *
- * @param IOInterface $io IO instance
- * @param Config $config Config instance
- * @param array $options Array of options passed directly to HttpDownloader constructor
- * @return HttpDownloader
+ * @param IOInterface $io IO instance
+ * @param Config $config Config instance
+ * @param array $options Array of options passed directly to RemoteFilesystem constructor
+ * @return RemoteFilesystem
*/
- public static function createHttpDownloader(IOInterface $io, Config $config, $options = array())
+ public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
{
static $warned = false;
$disableTls = false;
@@ -631,7 +590,7 @@ public static function createHttpDownloader(IOInterface $io, Config $config, $op
if (isset($_SERVER['argv']) && in_array('disable-tls', $_SERVER['argv']) && (in_array('conf', $_SERVER['argv']) || in_array('config', $_SERVER['argv']))) {
$warned = true;
$disableTls = !extension_loaded('openssl');
- } elseif ($config->get('disable-tls') === true) {
+ } elseif ($config && $config->get('disable-tls') === true) {
if (!$warned) {
$io->writeError('You are running Composer with SSL/TLS protection disabled. ');
}
@@ -641,18 +600,18 @@ public static function createHttpDownloader(IOInterface $io, Config $config, $op
throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
. 'If you can not enable the openssl extension, you can disable this error, at your own risk, by setting the \'disable-tls\' option to true.');
}
- $httpDownloaderOptions = array();
+ $remoteFilesystemOptions = array();
if ($disableTls === false) {
- if ($config->get('cafile')) {
- $httpDownloaderOptions['ssl']['cafile'] = $config->get('cafile');
+ if ($config && $config->get('cafile')) {
+ $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
}
- if ($config->get('capath')) {
- $httpDownloaderOptions['ssl']['capath'] = $config->get('capath');
+ if ($config && $config->get('capath')) {
+ $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
}
- $httpDownloaderOptions = array_replace_recursive($httpDownloaderOptions, $options);
+ $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
}
try {
- $httpDownloader = new HttpDownloader($io, $config, $httpDownloaderOptions, $disableTls);
+ $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
} catch (TransportException $e) {
if (false !== strpos($e->getMessage(), 'cafile')) {
$io->write('Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option. ');
@@ -665,7 +624,7 @@ public static function createHttpDownloader(IOInterface $io, Config $config, $op
throw $e;
}
- return $httpDownloader;
+ return $remoteFilesystem;
}
/**
@@ -674,15 +633,11 @@ public static function createHttpDownloader(IOInterface $io, Config $config, $op
private static function useXdg()
{
foreach (array_keys($_SERVER) as $key) {
- if (strpos($key, 'XDG_') === 0) {
+ if (substr($key, 0, 4) === 'XDG_') {
return true;
}
}
- if (Silencer::call('is_dir', '/etc/xdg')) {
- return true;
- }
-
return false;
}
diff --git a/app/vendor/composer/composer/src/Composer/IO/BaseIO.php b/app/vendor/composer/composer/src/Composer/IO/BaseIO.php
index 380902fa7..013597450 100644
--- a/app/vendor/composer/composer/src/Composer/IO/BaseIO.php
+++ b/app/vendor/composer/composer/src/Composer/IO/BaseIO.php
@@ -14,11 +14,11 @@
use Composer\Config;
use Composer\Util\ProcessExecutor;
+use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
-abstract class BaseIO implements IOInterface
+abstract class BaseIO implements IOInterface, LoggerInterface
{
- /** @var array */
protected $authentications = array();
/**
@@ -138,9 +138,7 @@ public function loadConfiguration(Config $config)
}
foreach ($gitlabToken as $domain => $token) {
- $username = is_array($token) && array_key_exists("username", $token) ? $token["username"] : $token;
- $password = is_array($token) && array_key_exists("token", $token) ? $token["token"] : 'private-token';
- $this->checkAndSetAuthentication($domain, $username, $password);
+ $this->checkAndSetAuthentication($domain, $token, 'private-token');
}
// reload http basic credentials from config if available
@@ -157,78 +155,126 @@ public function loadConfiguration(Config $config)
}
/**
- * {@inheritDoc}
+ * System is unusable.
+ *
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function emergency($message, array $context = array())
{
- $this->log(LogLevel::EMERGENCY, $message, $context);
+ return $this->log(LogLevel::EMERGENCY, $message, $context);
}
/**
- * {@inheritDoc}
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function alert($message, array $context = array())
{
- $this->log(LogLevel::ALERT, $message, $context);
+ return $this->log(LogLevel::ALERT, $message, $context);
}
/**
- * {@inheritDoc}
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function critical($message, array $context = array())
{
- $this->log(LogLevel::CRITICAL, $message, $context);
+ return $this->log(LogLevel::CRITICAL, $message, $context);
}
/**
- * {@inheritDoc}
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function error($message, array $context = array())
{
- $this->log(LogLevel::ERROR, $message, $context);
+ return $this->log(LogLevel::ERROR, $message, $context);
}
/**
- * {@inheritDoc}
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function warning($message, array $context = array())
{
- $this->log(LogLevel::WARNING, $message, $context);
+ return $this->log(LogLevel::WARNING, $message, $context);
}
/**
- * {@inheritDoc}
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function notice($message, array $context = array())
{
- $this->log(LogLevel::NOTICE, $message, $context);
+ return $this->log(LogLevel::NOTICE, $message, $context);
}
/**
- * {@inheritDoc}
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function info($message, array $context = array())
{
- $this->log(LogLevel::INFO, $message, $context);
+ return $this->log(LogLevel::INFO, $message, $context);
}
/**
- * {@inheritDoc}
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function debug($message, array $context = array())
{
- $this->log(LogLevel::DEBUG, $message, $context);
+ return $this->log(LogLevel::DEBUG, $message, $context);
}
/**
- * {@inheritDoc}
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ * @return null
*/
public function log($level, $message, array $context = array())
{
if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
- $this->writeError(''.$message.' ');
+ $this->writeError(''.$message.' ', true, self::NORMAL);
} elseif ($level === LogLevel::WARNING) {
- $this->writeError(''.$message.' ');
+ $this->writeError(''.$message.' ', true, self::NORMAL);
} elseif ($level === LogLevel::NOTICE) {
$this->writeError(''.$message.' ', true, self::VERBOSE);
} elseif ($level === LogLevel::INFO) {
diff --git a/app/vendor/composer/composer/src/Composer/IO/BufferIO.php b/app/vendor/composer/composer/src/Composer/IO/BufferIO.php
index e86500e2d..db4671341 100644
--- a/app/vendor/composer/composer/src/Composer/IO/BufferIO.php
+++ b/app/vendor/composer/composer/src/Composer/IO/BufferIO.php
@@ -24,11 +24,6 @@
*/
class BufferIO extends ConsoleIO
{
- /** @var StringInput */
- protected $input;
- /** @var StreamOutput */
- protected $output;
-
/**
* @param string $input
* @param int $verbosity
@@ -78,7 +73,7 @@ public function setUserInputs(array $inputs)
private function createStream(array $inputs)
{
- $stream = fopen('php://memory', 'r+');
+ $stream = fopen('php://memory', 'r+', false);
foreach ($inputs as $input) {
fwrite($stream, $input.PHP_EOL);
diff --git a/app/vendor/composer/composer/src/Composer/IO/ConsoleIO.php b/app/vendor/composer/composer/src/Composer/IO/ConsoleIO.php
index d6aa538c1..925a528be 100644
--- a/app/vendor/composer/composer/src/Composer/IO/ConsoleIO.php
+++ b/app/vendor/composer/composer/src/Composer/IO/ConsoleIO.php
@@ -14,7 +14,6 @@
use Composer\Question\StrictConfirmationQuestion;
use Symfony\Component\Console\Helper\HelperSet;
-use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -36,9 +35,9 @@ class ConsoleIO extends BaseIO
/** @var HelperSet */
protected $helperSet;
/** @var string */
- protected $lastMessage = '';
+ protected $lastMessage;
/** @var string */
- protected $lastMessageErr = '';
+ protected $lastMessageErr;
/** @var float */
private $startTime;
@@ -159,6 +158,13 @@ private function doWrite($messages, $newline, $stderr, $verbosity, $raw = false)
return;
}
+ // hack to keep our usage BC with symfony<2.8 versions
+ // this removes the quiet output but there is no way around it
+ // see https://github.com/composer/composer/pull/4913
+ if (OutputInterface::VERBOSITY_QUIET === 0) {
+ $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
+ }
+
if ($raw) {
if ($sfVerbosity === OutputInterface::OUTPUT_NORMAL) {
$sfVerbosity = OutputInterface::OUTPUT_RAW;
@@ -247,15 +253,6 @@ private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
}
}
- /**
- * @param int $max
- * @return ProgressBar
- */
- public function getProgressBar($max = 0)
- {
- return new ProgressBar($this->getErrorOutput(), $max);
- }
-
/**
* {@inheritDoc}
*/
diff --git a/app/vendor/composer/composer/src/Composer/IO/IOInterface.php b/app/vendor/composer/composer/src/Composer/IO/IOInterface.php
index fd2a2d503..5766ba479 100644
--- a/app/vendor/composer/composer/src/Composer/IO/IOInterface.php
+++ b/app/vendor/composer/composer/src/Composer/IO/IOInterface.php
@@ -13,14 +13,13 @@
namespace Composer\IO;
use Composer\Config;
-use Psr\Log\LoggerInterface;
/**
* The Input/Output helper interface.
*
* @author François Pluchino
*/
-interface IOInterface extends LoggerInterface
+interface IOInterface
{
const QUIET = 1;
const NORMAL = 2;
@@ -81,24 +80,6 @@ public function write($messages, $newline = true, $verbosity = self::NORMAL);
*/
public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
- /**
- * Writes a message to the output, without formatting it.
- *
- * @param string|array $messages The message as an array of lines or a single string
- * @param bool $newline Whether to add a newline or not
- * @param int $verbosity Verbosity level from the VERBOSITY_* constants
- */
- public function writeRaw($messages, $newline = true, $verbosity = self::NORMAL);
-
- /**
- * Writes a message to the error output, without formatting it.
- *
- * @param string|array $messages The message as an array of lines or a single string
- * @param bool $newline Whether to add a newline or not
- * @param int $verbosity Verbosity level from the VERBOSITY_* constants
- */
- public function writeErrorRaw($messages, $newline = true, $verbosity = self::NORMAL);
-
/**
* Overwrites a previous message to the output.
*
@@ -126,7 +107,7 @@ public function overwriteError($messages, $newline = true, $size = null, $verbos
* @param string $default The default answer if none is given by the user
*
* @throws \RuntimeException If there is no data to read in the input stream
- * @return string|null The user answer
+ * @return string The user answer
*/
public function ask($question, $default = null);
@@ -164,7 +145,7 @@ public function askAndValidate($question, $validator, $attempts = null, $default
*
* @param string $question The question to ask
*
- * @return string|null The answer
+ * @return string The answer
*/
public function askAndHideAnswer($question);
@@ -179,7 +160,7 @@ public function askAndHideAnswer($question);
* @param bool $multiselect Select more than one value separated by comma
*
* @throws \InvalidArgumentException
- * @return int|string|array|bool The selected value or values (the key of the choices array)
+ * @return int|string|array The selected value or values (the key of the choices array)
*/
public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
diff --git a/app/vendor/composer/composer/src/Composer/IO/NullIO.php b/app/vendor/composer/composer/src/Composer/IO/NullIO.php
index 9dc9d3a0f..cc6d5eba1 100644
--- a/app/vendor/composer/composer/src/Composer/IO/NullIO.php
+++ b/app/vendor/composer/composer/src/Composer/IO/NullIO.php
@@ -106,7 +106,7 @@ public function askConfirmation($question, $default = true)
/**
* {@inheritDoc}
*/
- public function askAndValidate($question, $validator, $attempts = null, $default = null)
+ public function askAndValidate($question, $validator, $attempts = false, $default = null)
{
return $default;
}
diff --git a/app/vendor/composer/composer/src/Composer/InstalledVersions.php b/app/vendor/composer/composer/src/Composer/InstalledVersions.php
deleted file mode 100644
index 7c5502ca4..000000000
--- a/app/vendor/composer/composer/src/Composer/InstalledVersions.php
+++ /dev/null
@@ -1,337 +0,0 @@
-
- * Jordi Boggiano
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer;
-
-use Composer\Autoload\ClassLoader;
-use Composer\Semver\VersionParser;
-
-/**
- * This class is copied in every Composer installed project and available to all
- *
- * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
- *
- * To require its presence, you can require `composer-runtime-api ^2.0`
- */
-class InstalledVersions
-{
- private static $installed;
- private static $canGetVendors;
- private static $installedByVendor = array();
-
- /**
- * Returns a list of all package names which are present, either by being installed, replaced or provided
- *
- * @return string[]
- * @psalm-return list
- */
- public static function getInstalledPackages()
- {
- $packages = array();
- foreach (self::getInstalled() as $installed) {
- $packages[] = array_keys($installed['versions']);
- }
-
- if (1 === \count($packages)) {
- return $packages[0];
- }
-
- return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
- }
-
- /**
- * Returns a list of all package names with a specific type e.g. 'library'
- *
- * @param string $type
- * @return string[]
- * @psalm-return list
- */
- public static function getInstalledPackagesByType($type)
- {
- $packagesByType = array();
-
- foreach (self::getInstalled() as $installed) {
- foreach ($installed['versions'] as $name => $package) {
- if (isset($package['type']) && $package['type'] === $type) {
- $packagesByType[] = $name;
- }
- }
- }
-
- return $packagesByType;
- }
-
- /**
- * Checks whether the given package is installed
- *
- * This also returns true if the package name is provided or replaced by another package
- *
- * @param string $packageName
- * @param bool $includeDevRequirements
- * @return bool
- */
- public static function isInstalled($packageName, $includeDevRequirements = true)
- {
- foreach (self::getInstalled() as $installed) {
- if (isset($installed['versions'][$packageName])) {
- return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
- }
- }
-
- return false;
- }
-
- /**
- * Checks whether the given package satisfies a version constraint
- *
- * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
- *
- * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
- *
- * @param VersionParser $parser Install composer/semver to have access to this class and functionality
- * @param string $packageName
- * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
- * @return bool
- */
- public static function satisfies(VersionParser $parser, $packageName, $constraint)
- {
- $constraint = $parser->parseConstraints($constraint);
- $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
-
- return $provided->matches($constraint);
- }
-
- /**
- * Returns a version constraint representing all the range(s) which are installed for a given package
- *
- * It is easier to use this via isInstalled() with the $constraint argument if you need to check
- * whether a given version of a package is installed, and not just whether it exists
- *
- * @param string $packageName
- * @return string Version constraint usable with composer/semver
- */
- public static function getVersionRanges($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- $ranges = array();
- if (isset($installed['versions'][$packageName]['pretty_version'])) {
- $ranges[] = $installed['versions'][$packageName]['pretty_version'];
- }
- if (array_key_exists('aliases', $installed['versions'][$packageName])) {
- $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
- }
- if (array_key_exists('replaced', $installed['versions'][$packageName])) {
- $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
- }
- if (array_key_exists('provided', $installed['versions'][$packageName])) {
- $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
- }
-
- return implode(' || ', $ranges);
- }
-
- throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @param string $packageName
- * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
- */
- public static function getVersion($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- if (!isset($installed['versions'][$packageName]['version'])) {
- return null;
- }
-
- return $installed['versions'][$packageName]['version'];
- }
-
- throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @param string $packageName
- * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
- */
- public static function getPrettyVersion($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- if (!isset($installed['versions'][$packageName]['pretty_version'])) {
- return null;
- }
-
- return $installed['versions'][$packageName]['pretty_version'];
- }
-
- throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @param string $packageName
- * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
- */
- public static function getReference($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- if (!isset($installed['versions'][$packageName]['reference'])) {
- return null;
- }
-
- return $installed['versions'][$packageName]['reference'];
- }
-
- throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @param string $packageName
- * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
- */
- public static function getInstallPath($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
- }
-
- throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @return array
- * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
- */
- public static function getRootPackage()
- {
- $installed = self::getInstalled();
-
- return $installed[0]['root'];
- }
-
- /**
- * Returns the raw installed.php data for custom implementations
- *
- * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
- * @return array[]
- * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}
- */
- public static function getRawData()
- {
- @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
-
- if (null === self::$installed) {
- // only require the installed.php file if this file is loaded from its dumped location,
- // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
- if (substr(__DIR__, -8, 1) !== 'C') {
- self::$installed = include __DIR__ . '/installed.php';
- } else {
- self::$installed = array();
- }
- }
-
- return self::$installed;
- }
-
- /**
- * Returns the raw data of all installed.php which are currently loaded for custom implementations
- *
- * @return array[]
- * @psalm-return list}>
- */
- public static function getAllRawData()
- {
- return self::getInstalled();
- }
-
- /**
- * Lets you reload the static array from another file
- *
- * This is only useful for complex integrations in which a project needs to use
- * this class but then also needs to execute another project's autoloader in process,
- * and wants to ensure both projects have access to their version of installed.php.
- *
- * A typical case would be PHPUnit, where it would need to make sure it reads all
- * the data it needs from this class, then call reload() with
- * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
- * the project in which it runs can then also use this class safely, without
- * interference between PHPUnit's dependencies and the project's dependencies.
- *
- * @param array[] $data A vendor/composer/installed.php data set
- * @return void
- *
- * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data
- */
- public static function reload($data)
- {
- self::$installed = $data;
- self::$installedByVendor = array();
- }
-
- /**
- * @return array[]
- * @psalm-return list