mirror of
https://github.com/getgrav/grav.git
synced 2025-12-05 15:29:57 +01:00
Compare commits
9 Commits
3ddc548d51
...
bcd93c321b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcd93c321b | ||
|
|
8bd711f6b1 | ||
|
|
fa707eb7eb | ||
|
|
18d285ec36 | ||
|
|
04c6bdf287 | ||
|
|
48343d7714 | ||
|
|
9c27496cc1 | ||
|
|
fd51d33d3f | ||
|
|
7304612d3a |
@@ -26,6 +26,7 @@
|
||||
"symfony/polyfill-php80": "^1.23",
|
||||
"symfony/polyfill-php81": "^1.23",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"psr/cache": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/http-server-middleware": "^1.0",
|
||||
"psr/container": "~1.1.0",
|
||||
@@ -55,7 +56,8 @@
|
||||
"league/climate": "^3.6",
|
||||
"miljar/php-exif": "^0.6",
|
||||
"composer/ca-bundle": "^1.2",
|
||||
"dragonmantank/cron-expression": "^3.3",
|
||||
"dragonmantank/cron-expression": "~3.3.0",
|
||||
"symfony/deprecation-contracts": "^2.2",
|
||||
"willdurand/negotiation": "^3.0",
|
||||
"itsgoingd/clockwork": "^5.0",
|
||||
"symfony/http-client": "^4.4",
|
||||
@@ -64,13 +66,15 @@
|
||||
"multiavatar/multiavatar-php": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"behat/gherkin": "~4.10.0",
|
||||
"codeception/codeception": "^4.1",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpunit/php-code-coverage": "~9.2",
|
||||
"getgrav/markdowndocs": "^2.0",
|
||||
"codeception/module-asserts": "^1.3",
|
||||
"codeception/module-phpbrowser": "^1.0"
|
||||
"codeception/module-phpbrowser": "^1.0",
|
||||
"doctrine/instantiator": "^1.4"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/polyfill-php72": "*",
|
||||
@@ -87,7 +91,10 @@
|
||||
"ext-exif": "Needed to use exif data from images."
|
||||
},
|
||||
"config": {
|
||||
"apcu-autoloader": true
|
||||
"apcu-autoloader": true,
|
||||
"audit": {
|
||||
"block-insecure": false
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
295
composer.lock
generated
295
composer.lock
generated
@@ -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": "8d681f74b0bd1f5099bb8fbf788ab3eb",
|
||||
"content-hash": "2d55f03bde4cf99b4790e878792a9ce0",
|
||||
"packages": [
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
"version": "1.5.8",
|
||||
"version": "1.5.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/ca-bundle.git",
|
||||
"reference": "719026bb30813accb68271fee7e39552a58e9f65"
|
||||
"reference": "1905981ee626e6f852448b7aaa978f8666c5bc54"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/719026bb30813accb68271fee7e39552a58e9f65",
|
||||
"reference": "719026bb30813accb68271fee7e39552a58e9f65",
|
||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/1905981ee626e6f852448b7aaa978f8666c5bc54",
|
||||
"reference": "1905981ee626e6f852448b7aaa978f8666c5bc54",
|
||||
"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.5.8"
|
||||
"source": "https://github.com/composer/ca-bundle/tree/1.5.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -76,7 +76,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-08-20T18:49:47+00:00"
|
||||
"time": "2025-11-06T11:46:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/semver",
|
||||
@@ -255,6 +255,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"abandoned": true,
|
||||
"time": "2022-05-20T20:06:54+00:00"
|
||||
},
|
||||
{
|
||||
@@ -377,16 +378,16 @@
|
||||
},
|
||||
{
|
||||
"name": "donatj/phpuseragentparser",
|
||||
"version": "v1.10.0",
|
||||
"version": "v1.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/donatj/PhpUserAgent.git",
|
||||
"reference": "3ba73057d2a4a275badb88b7708e91e159c40367"
|
||||
"reference": "c98541c5198bb75564d7db4a8971773bc848361e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/donatj/PhpUserAgent/zipball/3ba73057d2a4a275badb88b7708e91e159c40367",
|
||||
"reference": "3ba73057d2a4a275badb88b7708e91e159c40367",
|
||||
"url": "https://api.github.com/repos/donatj/PhpUserAgent/zipball/c98541c5198bb75564d7db4a8971773bc848361e",
|
||||
"reference": "c98541c5198bb75564d7db4a8971773bc848361e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -431,7 +432,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/donatj/PhpUserAgent/issues",
|
||||
"source": "https://github.com/donatj/PhpUserAgent/tree/v1.10.0"
|
||||
"source": "https://github.com/donatj/PhpUserAgent/tree/v1.11.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -447,20 +448,20 @@
|
||||
"type": "ko_fi"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-30T15:45:03+00:00"
|
||||
"time": "2025-09-10T21:58:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
"version": "v3.4.0",
|
||||
"version": "v3.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dragonmantank/cron-expression.git",
|
||||
"reference": "8c784d071debd117328803d86b2097615b457500"
|
||||
"reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500",
|
||||
"reference": "8c784d071debd117328803d86b2097615b457500",
|
||||
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
|
||||
"reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -473,14 +474,10 @@
|
||||
"require-dev": {
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"phpstan/phpstan-webmozart-assert": "^1.0",
|
||||
"phpunit/phpunit": "^7.0|^8.0|^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Cron\\": "src/Cron/"
|
||||
@@ -504,7 +501,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dragonmantank/cron-expression/issues",
|
||||
"source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0"
|
||||
"source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -512,7 +509,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-09T13:47:03+00:00"
|
||||
"time": "2023-08-10T19:36:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "erusev/parsedown",
|
||||
@@ -903,16 +900,16 @@
|
||||
},
|
||||
{
|
||||
"name": "itsgoingd/clockwork",
|
||||
"version": "v5.3.4",
|
||||
"version": "v5.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/itsgoingd/clockwork.git",
|
||||
"reference": "c27ad77a08a9e58bf0049de46969fa4fe3b506e5"
|
||||
"reference": "d928483e231f042dbff9258795cb17aadaebc7d0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/c27ad77a08a9e58bf0049de46969fa4fe3b506e5",
|
||||
"reference": "c27ad77a08a9e58bf0049de46969fa4fe3b506e5",
|
||||
"url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/d928483e231f042dbff9258795cb17aadaebc7d0",
|
||||
"reference": "d928483e231f042dbff9258795cb17aadaebc7d0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -967,7 +964,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/itsgoingd/clockwork/issues",
|
||||
"source": "https://github.com/itsgoingd/clockwork/tree/v5.3.4"
|
||||
"source": "https://github.com/itsgoingd/clockwork/tree/v5.3.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -975,7 +972,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-09T15:57:21+00:00"
|
||||
"time": "2025-09-14T15:34:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/climate",
|
||||
@@ -2090,16 +2087,16 @@
|
||||
},
|
||||
{
|
||||
"name": "rhukster/dom-sanitizer",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rhukster/dom-sanitizer.git",
|
||||
"reference": "c2a98f27ad742668b254282ccc5581871d0fb601"
|
||||
"reference": "757e4d6ac03afe9afa4f97cbef453fc5c25f0729"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rhukster/dom-sanitizer/zipball/c2a98f27ad742668b254282ccc5581871d0fb601",
|
||||
"reference": "c2a98f27ad742668b254282ccc5581871d0fb601",
|
||||
"url": "https://api.github.com/repos/rhukster/dom-sanitizer/zipball/757e4d6ac03afe9afa4f97cbef453fc5c25f0729",
|
||||
"reference": "757e4d6ac03afe9afa4f97cbef453fc5c25f0729",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2129,9 +2126,9 @@
|
||||
"description": "A simple but effective DOM/SVG/MathML Sanitizer for PHP 7.4+",
|
||||
"support": {
|
||||
"issues": "https://github.com/rhukster/dom-sanitizer/issues",
|
||||
"source": "https://github.com/rhukster/dom-sanitizer/tree/1.0.7"
|
||||
"source": "https://github.com/rhukster/dom-sanitizer/tree/1.0.8"
|
||||
},
|
||||
"time": "2023-11-06T16:46:48+00:00"
|
||||
"time": "2024-04-15T08:48:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rockettheme/toolbox",
|
||||
@@ -2426,6 +2423,73 @@
|
||||
],
|
||||
"time": "2022-07-20T09:59:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v2.5.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "605389f2a7e5625f273b53960dc46aeaf9c62918"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918",
|
||||
"reference": "605389f2a7e5625f273b53960dc46aeaf9c62918",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "2.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"function.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": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4"
|
||||
},
|
||||
"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": "2024-09-25T14:11:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v4.4.44",
|
||||
@@ -3391,28 +3455,28 @@
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "1.11.0",
|
||||
"version": "1.12.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozarts/assert.git",
|
||||
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
|
||||
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
|
||||
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68",
|
||||
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
"ext-filter": "*",
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan": "<0.12.20",
|
||||
"vimeo/psalm": "<4.6.1 || 4.6.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5.13"
|
||||
"suggest": {
|
||||
"ext-intl": "",
|
||||
"ext-simplexml": "",
|
||||
"ext-spl": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@@ -3443,9 +3507,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/webmozarts/assert/issues",
|
||||
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
|
||||
"source": "https://github.com/webmozarts/assert/tree/1.12.1"
|
||||
},
|
||||
"time": "2022-06-03T18:03:27+00:00"
|
||||
"time": "2025-10-29T15:56:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "willdurand/negotiation",
|
||||
@@ -4548,16 +4612,11 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.12.28",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9"
|
||||
},
|
||||
"version": "1.12.32",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/fcf8b71aeab4e1a1131d1783cef97b23a51b87a9",
|
||||
"reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8",
|
||||
"reference": "2770dcdf5078d0b0d53f94317e06affe88419aa8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4602,7 +4661,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-07-17T17:15:39+00:00"
|
||||
"time": "2025-09-30T10:16:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-deprecation-rules",
|
||||
@@ -4972,16 +5031,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.6.25",
|
||||
"version": "9.6.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "049c011e01be805202d8eebedef49f769a8ec7b7"
|
||||
"reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/049c011e01be805202d8eebedef49f769a8ec7b7",
|
||||
"reference": "049c011e01be805202d8eebedef49f769a8ec7b7",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9ecfec57835a5581bc888ea7e13b51eb55ab9dd3",
|
||||
"reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5006,7 +5065,7 @@
|
||||
"sebastian/comparator": "^4.0.9",
|
||||
"sebastian/diff": "^4.0.6",
|
||||
"sebastian/environment": "^5.1.5",
|
||||
"sebastian/exporter": "^4.0.6",
|
||||
"sebastian/exporter": "^4.0.8",
|
||||
"sebastian/global-state": "^5.0.8",
|
||||
"sebastian/object-enumerator": "^4.0.4",
|
||||
"sebastian/resource-operations": "^3.0.4",
|
||||
@@ -5055,7 +5114,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.25"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.29"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5079,7 +5138,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-08-20T14:38:31+00:00"
|
||||
"time": "2025-09-24T06:29:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-client",
|
||||
@@ -5574,16 +5633,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "4.0.6",
|
||||
"version": "4.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "78c00df8f170e02473b682df15bfcdacc3d32d72"
|
||||
"reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72",
|
||||
"reference": "78c00df8f170e02473b682df15bfcdacc3d32d72",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c",
|
||||
"reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5639,15 +5698,27 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6"
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://liberapay.com/sebastianbergmann",
|
||||
"type": "liberapay"
|
||||
},
|
||||
{
|
||||
"url": "https://thanks.dev/u/gh/sebastianbergmann",
|
||||
"type": "thanks_dev"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/sebastian/exporter",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-02T06:33:00+00:00"
|
||||
"time": "2025-09-24T06:03:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
@@ -6270,73 +6341,6 @@
|
||||
],
|
||||
"time": "2024-09-25T14:11:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v2.5.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "605389f2a7e5625f273b53960dc46aeaf9c62918"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918",
|
||||
"reference": "605389f2a7e5625f273b53960dc46aeaf9c62918",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "2.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"function.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": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4"
|
||||
},
|
||||
"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": "2024-09-25T14:11:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v5.4.48",
|
||||
@@ -6477,16 +6481,16 @@
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.2.3",
|
||||
"version": "1.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/theseer/tokenizer.git",
|
||||
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
|
||||
"reference": "b7489ce515e168639d17feec34b8847c326b0b3c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
|
||||
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c",
|
||||
"reference": "b7489ce515e168639d17feec34b8847c326b0b3c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6515,7 +6519,7 @@
|
||||
"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.3"
|
||||
"source": "https://github.com/theseer/tokenizer/tree/1.3.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6523,7 +6527,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-03T12:36:25+00:00"
|
||||
"time": "2025-11-17T20:03:58+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
@@ -6542,8 +6546,5 @@
|
||||
"ext-gd": "*"
|
||||
},
|
||||
"platform-dev": {},
|
||||
"platform-overrides": {
|
||||
"php": "7.3.6"
|
||||
},
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.9.0"
|
||||
}
|
||||
|
||||
@@ -1614,6 +1614,15 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
updates.safe_upgrade_snapshot_limit:
|
||||
type: number
|
||||
label: PLUGIN_ADMIN.SAFE_UPGRADE_SNAPSHOT_LIMIT
|
||||
help: PLUGIN_ADMIN.SAFE_UPGRADE_SNAPSHOT_LIMIT_HELP
|
||||
default: 5
|
||||
validate:
|
||||
type: int
|
||||
min: 0
|
||||
|
||||
http_section:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.HTTP_SECTION
|
||||
|
||||
@@ -205,6 +205,7 @@ gpm:
|
||||
|
||||
updates:
|
||||
safe_upgrade: true # Enable guarded staging+rollback pipeline for Grav self-updates
|
||||
safe_upgrade_snapshot_limit: 5 # Maximum number of safe-upgrade snapshots to retain (0 = unlimited)
|
||||
|
||||
http:
|
||||
method: auto # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL
|
||||
|
||||
@@ -124,3 +124,5 @@ PLUGIN_ADMIN:
|
||||
UPDATES_SECTION: Updates
|
||||
SAFE_UPGRADE: Safe self-upgrade
|
||||
SAFE_UPGRADE_HELP: When enabled, Grav core updates use staged installation with automatic rollback support.
|
||||
SAFE_UPGRADE_SNAPSHOT_LIMIT: Safe-upgrade snapshots to keep
|
||||
SAFE_UPGRADE_SNAPSHOT_LIMIT_HELP: Maximum number of snapshots to retain for safe upgrades (0 disables pruning).
|
||||
|
||||
@@ -51,6 +51,7 @@ class Security
|
||||
{
|
||||
if (Grav::instance()['config']->get('security.sanitize_svg')) {
|
||||
$sanitizer = new DOMSanitizer(DOMSanitizer::SVG);
|
||||
$sanitizer->addDisallowedAttributes(['href', 'xlink:href']);
|
||||
$sanitized = $sanitizer->sanitize($svg);
|
||||
if (is_string($sanitized)) {
|
||||
$svg = $sanitized;
|
||||
@@ -70,6 +71,7 @@ class Security
|
||||
{
|
||||
if (file_exists($file) && Grav::instance()['config']->get('security.sanitize_svg')) {
|
||||
$sanitizer = new DOMSanitizer(DOMSanitizer::SVG);
|
||||
$sanitizer->addDisallowedAttributes(['href', 'xlink:href']);
|
||||
$original_svg = file_get_contents($file);
|
||||
$clean_svg = $sanitizer->sanitize($original_svg);
|
||||
|
||||
|
||||
@@ -168,13 +168,11 @@ class SafeUpgradeService
|
||||
$psrLogConflicts = $this->detectPsrLogConflicts();
|
||||
$monologConflicts = $this->detectMonologConflicts();
|
||||
|
||||
// Only enforce plugin updates for major/minor upgrades
|
||||
// For patch upgrades, just warn but don't block
|
||||
if ($pending) {
|
||||
if ($isMajorMinorUpgrade) {
|
||||
$warnings[] = 'One or more plugins/themes are not up to date and must be updated for major version upgrades.';
|
||||
$warnings[] = 'Because this is a major Grav upgrade, update pending plugins and themes before continuing.';
|
||||
} else {
|
||||
$warnings[] = 'One or more plugins/themes are not up to date.';
|
||||
$warnings[] = 'Pending plugin/theme updates detected. Update them before running Grav upgrade.';
|
||||
}
|
||||
}
|
||||
if ($psrLogConflicts) {
|
||||
|
||||
@@ -693,6 +693,17 @@ abstract class Utils
|
||||
header('Content-Disposition: attachment; filename="' . ($options['download_name'] ?? $file_parts['basename']) . '"');
|
||||
}
|
||||
|
||||
if ($grav['config']->get('system.cache.enabled')) {
|
||||
$expires = $options['expires'] ?? $grav['config']->get('system.pages.expires');
|
||||
if ($expires > 0) {
|
||||
$expires_date = gmdate('D, d M Y H:i:s T', time() + $expires);
|
||||
header('Cache-Control: max-age=' . $expires);
|
||||
header('Expires: ' . $expires_date);
|
||||
header('Pragma: cache');
|
||||
}
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($file)));
|
||||
}
|
||||
|
||||
// multipart-download and download resuming support
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
[$a, $range] = explode('=', $_SERVER['HTTP_RANGE'], 2);
|
||||
@@ -705,7 +716,7 @@ abstract class Utils
|
||||
$range_end = (int)$range_end;
|
||||
}
|
||||
$new_length = $range_end - $range + 1;
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
http_response_code(206);
|
||||
header("Content-Length: {$new_length}");
|
||||
header("Content-Range: bytes {$range}-{$range_end}/{$size}");
|
||||
} else {
|
||||
@@ -714,19 +725,10 @@ abstract class Utils
|
||||
header('Content-Length: ' . $size);
|
||||
|
||||
if ($grav['config']->get('system.cache.enabled')) {
|
||||
$expires = $options['expires'] ?? $grav['config']->get('system.pages.expires');
|
||||
if ($expires > 0) {
|
||||
$expires_date = gmdate('D, d M Y H:i:s T', time() + $expires);
|
||||
header('Cache-Control: max-age=' . $expires);
|
||||
header('Expires: ' . $expires_date);
|
||||
header('Pragma: cache');
|
||||
}
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($file)));
|
||||
|
||||
// Return 304 Not Modified if the file is already cached in the browser
|
||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
|
||||
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($file)) {
|
||||
header('HTTP/1.1 304 Not Modified');
|
||||
strtotime((string) $_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($file)) {
|
||||
http_response_code(304);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use function date;
|
||||
use function count;
|
||||
use function is_callable;
|
||||
use function strlen;
|
||||
use function stripos;
|
||||
|
||||
/**
|
||||
* Class SelfupgradeCommand
|
||||
@@ -396,6 +397,21 @@ class SelfupgradeCommand extends GpmCommand
|
||||
$conflicts = $preflight['psr_log_conflicts'] ?? [];
|
||||
$monologConflicts = $preflight['monolog_conflicts'] ?? [];
|
||||
$warnings = $preflight['warnings'] ?? [];
|
||||
$isMajorMinorUpgrade = $preflight['is_major_minor_upgrade'] ?? null;
|
||||
if ($isMajorMinorUpgrade === null && $this->upgrader) {
|
||||
$local = $this->upgrader->getLocalVersion();
|
||||
$remote = $this->upgrader->getRemoteVersion();
|
||||
$localParts = explode('.', $local);
|
||||
$remoteParts = explode('.', $remote);
|
||||
|
||||
$localMajor = (int)($localParts[0] ?? 0);
|
||||
$localMinor = (int)($localParts[1] ?? 0);
|
||||
$remoteMajor = (int)($remoteParts[0] ?? 0);
|
||||
$remoteMinor = (int)($remoteParts[1] ?? 0);
|
||||
|
||||
$isMajorMinorUpgrade = ($localMajor !== $remoteMajor) || ($localMinor !== $remoteMinor);
|
||||
}
|
||||
$isMajorMinorUpgrade = (bool)$isMajorMinorUpgrade;
|
||||
|
||||
if ($warnings) {
|
||||
$io->newLine();
|
||||
@@ -419,25 +435,7 @@ class SelfupgradeCommand extends GpmCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($pending) {
|
||||
// Use the is_major_minor_upgrade flag from preflight result if available
|
||||
$isMajorMinorUpgrade = $preflight['is_major_minor_upgrade'] ?? false;
|
||||
|
||||
// Fall back to calculating it if not provided (for backwards compatibility)
|
||||
if (!isset($preflight['is_major_minor_upgrade']) && $this->upgrader) {
|
||||
$local = $this->upgrader->getLocalVersion();
|
||||
$remote = $this->upgrader->getRemoteVersion();
|
||||
$localParts = explode('.', $local);
|
||||
$remoteParts = explode('.', $remote);
|
||||
|
||||
$localMajor = (int)($localParts[0] ?? 0);
|
||||
$localMinor = (int)($localParts[1] ?? 0);
|
||||
$remoteMajor = (int)($remoteParts[0] ?? 0);
|
||||
$remoteMinor = (int)($remoteParts[1] ?? 0);
|
||||
|
||||
$isMajorMinorUpgrade = ($localMajor !== $remoteMajor) || ($localMinor !== $remoteMinor);
|
||||
}
|
||||
|
||||
if ($pending && $isMajorMinorUpgrade) {
|
||||
$local = $this->upgrader ? $this->upgrader->getLocalVersion() : 'unknown';
|
||||
$remote = $this->upgrader ? $this->upgrader->getRemoteVersion() : 'unknown';
|
||||
|
||||
@@ -450,15 +448,9 @@ class SelfupgradeCommand extends GpmCommand
|
||||
$io->writeln(sprintf(' - %s (%s) %s → %s', $slug, $type, $current, $available));
|
||||
}
|
||||
|
||||
if ($isMajorMinorUpgrade) {
|
||||
// For major/minor upgrades, this is EXPECTED behavior - updating plugins first is REQUIRED
|
||||
$io->writeln(' › For major version upgrades (v' . $local . ' → v' . $remote . '), plugins must be updated to their latest');
|
||||
$io->writeln(' compatible versions BEFORE upgrading Grav core to ensure compatibility.');
|
||||
$io->writeln(' Please run `bin/gpm update` to update these packages, then retry self-upgrade.');
|
||||
} else {
|
||||
// For patch upgrades, this shouldn't normally happen but plugins still need updating
|
||||
$io->writeln(' › Please run `bin/gpm update` to bring these packages current before upgrading Grav.');
|
||||
}
|
||||
$io->writeln(' › For major version upgrades (v' . $local . ' → v' . $remote . '), plugins must be updated to their latest');
|
||||
$io->writeln(' compatible versions BEFORE upgrading Grav core to ensure compatibility.');
|
||||
$io->writeln(' Please run `bin/gpm update` to update these packages, then retry self-upgrade.');
|
||||
|
||||
$proceed = false;
|
||||
if (!$this->all_yes) {
|
||||
|
||||
@@ -20,13 +20,16 @@ use Grav\Common\Plugins;
|
||||
use Grav\Common\Yaml;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
use function array_slice;
|
||||
use function basename;
|
||||
use function class_exists;
|
||||
use function count;
|
||||
use function date;
|
||||
use function dirname;
|
||||
use function explode;
|
||||
use function floor;
|
||||
use function function_exists;
|
||||
use function file_get_contents;
|
||||
use function glob;
|
||||
use function iterator_to_array;
|
||||
use function is_dir;
|
||||
@@ -42,6 +45,7 @@ use function array_fill_keys;
|
||||
use function array_map;
|
||||
use function array_pad;
|
||||
use function array_key_exists;
|
||||
use function rsort;
|
||||
use function sort;
|
||||
use function sprintf;
|
||||
use function strtolower;
|
||||
@@ -161,6 +165,8 @@ final class Install
|
||||
private static $forceSafeUpgrade = null;
|
||||
/** @var bool */
|
||||
private static $allowPendingOverride = false;
|
||||
/** @var int|null */
|
||||
private static $snapshotLimit = null;
|
||||
/** @var callable|null */
|
||||
private $progressCallback = null;
|
||||
/** @var array|null */
|
||||
@@ -430,6 +436,35 @@ ERR;
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getSafeUpgradeSnapshotLimit(): int
|
||||
{
|
||||
if (null !== self::$snapshotLimit) {
|
||||
return self::$snapshotLimit;
|
||||
}
|
||||
|
||||
$limit = 5;
|
||||
|
||||
try {
|
||||
$grav = Grav::instance();
|
||||
if ($grav && isset($grav['config'])) {
|
||||
$configured = $grav['config']->get('system.updates.safe_upgrade_snapshot_limit');
|
||||
if ($configured !== null) {
|
||||
$limit = (int)$configured;
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// ignore bootstrap failures
|
||||
}
|
||||
|
||||
if ($limit < 0) {
|
||||
$limit = 0;
|
||||
}
|
||||
|
||||
self::$snapshotLimit = $limit;
|
||||
|
||||
return $limit;
|
||||
}
|
||||
|
||||
private function captureCoreSnapshot(string $targetVersion): ?array
|
||||
{
|
||||
$entries = $this->collectSnapshotEntries();
|
||||
@@ -484,6 +519,7 @@ ERR;
|
||||
|
||||
$this->persistSnapshotManifest($manifest);
|
||||
$this->lastManifest = $manifest;
|
||||
$this->pruneOldSnapshots($snapshotRoot);
|
||||
|
||||
return $manifest;
|
||||
}
|
||||
@@ -596,6 +632,83 @@ ERR;
|
||||
}
|
||||
}
|
||||
|
||||
private function pruneOldSnapshots(?string $snapshotRoot): void
|
||||
{
|
||||
$limit = $this->getSafeUpgradeSnapshotLimit();
|
||||
if ($limit <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$manifestDir = GRAV_ROOT . '/user/data/upgrades';
|
||||
$files = glob($manifestDir . '/*.json');
|
||||
if (!$files) {
|
||||
return;
|
||||
}
|
||||
|
||||
rsort($files);
|
||||
if (count($files) <= $limit) {
|
||||
return;
|
||||
}
|
||||
|
||||
$obsolete = array_slice($files, $limit);
|
||||
$removed = 0;
|
||||
|
||||
foreach ($obsolete as $manifestPath) {
|
||||
$manifest = null;
|
||||
try {
|
||||
$contents = @file_get_contents($manifestPath);
|
||||
if ($contents !== false) {
|
||||
$decoded = json_decode($contents, true);
|
||||
if (is_array($decoded)) {
|
||||
$manifest = $decoded;
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// ignore malformed manifests
|
||||
}
|
||||
|
||||
$snapshotId = $manifest['id'] ?? basename($manifestPath, '.json');
|
||||
$backupPath = $manifest['backup_path'] ?? null;
|
||||
|
||||
if ($backupPath && is_dir($backupPath)) {
|
||||
try {
|
||||
Folder::delete($backupPath);
|
||||
} catch (\Throwable $e) {
|
||||
error_log('[Grav Upgrade] Unable to delete snapshot directory ' . $backupPath . ': ' . $e->getMessage());
|
||||
}
|
||||
} elseif ($snapshotRoot && $snapshotId) {
|
||||
$candidate = $snapshotRoot . '/' . $snapshotId;
|
||||
if (is_dir($candidate)) {
|
||||
try {
|
||||
Folder::delete($candidate);
|
||||
} catch (\Throwable $e) {
|
||||
error_log('[Grav Upgrade] Unable to delete snapshot directory ' . $candidate . ': ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!@unlink($manifestPath)) {
|
||||
error_log('[Grav Upgrade] Unable to remove snapshot manifest: ' . $manifestPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
$removed++;
|
||||
}
|
||||
|
||||
if ($removed > 0) {
|
||||
$this->relayProgress(
|
||||
'snapshot',
|
||||
sprintf(
|
||||
'Pruned %d old snapshot%s (keeping latest %d).',
|
||||
$removed,
|
||||
$removed === 1 ? '' : 's',
|
||||
$limit
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return void
|
||||
@@ -604,7 +717,7 @@ ERR;
|
||||
public function finalize(): void
|
||||
{
|
||||
$start = microtime(true);
|
||||
$this->relayProgress('postflight', 'Running postflight tasks...', null);
|
||||
$this->relayProgress('finalizing', 'Running postflight tasks...', null);
|
||||
// Finalize can be run without installing Grav first.
|
||||
if (null === $this->updater) {
|
||||
$versions = Versions::instance(USER_DIR . 'config/versions.yaml');
|
||||
@@ -624,7 +737,7 @@ ERR;
|
||||
}
|
||||
|
||||
$elapsed = microtime(true) - $start;
|
||||
$this->relayProgress('postflight', sprintf('Postflight tasks complete in %.3fs.', $elapsed), null);
|
||||
$this->relayProgress('finalizing', sprintf('Postflight tasks complete in %.3fs.', $elapsed), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -777,7 +890,7 @@ ERR;
|
||||
private function runPreflightChecks(string $targetVersion): array
|
||||
{
|
||||
$start = microtime(true);
|
||||
$this->relayProgress('preflight', 'Running preflight checks...', null);
|
||||
$this->relayProgress('initializing', 'Running preflight checks...', null);
|
||||
$report = [
|
||||
'warnings' => [],
|
||||
'psr_log_conflicts' => [],
|
||||
@@ -795,14 +908,12 @@ ERR;
|
||||
if (self::$allowPendingOverride) {
|
||||
$report['warnings'][] = 'Pending plugin/theme updates ignored for this upgrade run.';
|
||||
} elseif ($report['is_major_minor_upgrade']) {
|
||||
$report['blocking'][] = 'Plugin and theme updates must be applied before upgrading Grav.';
|
||||
} else {
|
||||
$report['warnings'][] = 'Pending plugin/theme updates detected; updating before upgrading Grav is recommended.';
|
||||
$report['blocking'][] = 'Pending plugin/theme updates detected. Because this is a major Grav upgrade, update them before continuing.';
|
||||
}
|
||||
}
|
||||
|
||||
$elapsed = microtime(true) - $start;
|
||||
$this->relayProgress('preflight', sprintf('Preflight checks complete in %.3fs.', $elapsed), null);
|
||||
$this->relayProgress('initializing', sprintf('Preflight checks complete in %.3fs.', $elapsed), null);
|
||||
|
||||
return $report;
|
||||
}
|
||||
@@ -888,7 +999,7 @@ ERR;
|
||||
}
|
||||
}
|
||||
|
||||
$this->relayProgress('preflight', sprintf('Detected %d updatable packages (including symlinks).', count($pending)), null);
|
||||
$this->relayProgress('initializing', sprintf('Detected %d updatable packages (including symlinks).', count($pending)), null);
|
||||
|
||||
return $pending;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class SelfupgradeCommandTest extends \Codeception\TestCase\Test
|
||||
public function testHandlePreflightReportAbortsOnPendingWhenDeclined(): void
|
||||
{
|
||||
$command = new TestSelfupgradeCommand();
|
||||
[$style] = $this->injectIo($command);
|
||||
[$style] = $this->injectIo($command, [false]);
|
||||
$this->setAllYes($command, false);
|
||||
|
||||
$result = $command->runHandle([
|
||||
|
||||
Reference in New Issue
Block a user