Fix lost form submissions on archives, the unlocked update finish and six more
Update Symfony to 7.4.23 (12 advisories in 8 packages). - A form can be sent from /beitraege, /kategorie/... and /schlagwort/...; it answered 404 before anything was stored or mailed. - Booleans reach the database as integers, so MySQL in strict mode accepts form submissions, task switches and plugin states. - A stepped form with a required multiple choice shows its message instead of stopping on a TypeError. - The second update step runs under the update lock; a concurrent finish no longer rolls a successful update back. - Accordion entries and gallery images can be selected from the editor panel again. - Category and tag names are escaped in the archive heading. - Restoring a published page from the bin needs the publisher role. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
1 parent
441e629e80
commit
d464c82ac8
17 files changed
+324
-168
No files matched your search
Generated
+151
-151
@@ -748,16 +748,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache",
|
"name": "symfony/cache",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/cache.git",
|
"url": "https://github.com/symfony/cache.git",
|
||||||
"reference": "f0024b7dd1e6d4f2f34b08c1a61c6c7d33febad7"
|
"reference": "bbaa2ca4a93a94532285bdd5a0caf225d34ff578"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/cache/zipball/f0024b7dd1e6d4f2f34b08c1a61c6c7d33febad7",
|
"url": "https://api.github.com/repos/symfony/cache/zipball/bbaa2ca4a93a94532285bdd5a0caf225d34ff578",
|
||||||
"reference": "f0024b7dd1e6d4f2f34b08c1a61c6c7d33febad7",
|
"reference": "bbaa2ca4a93a94532285bdd5a0caf225d34ff578",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -827,7 +827,7 @@
|
|||||||
"psr6"
|
"psr6"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/cache/tree/v7.4.22"
|
"source": "https://github.com/symfony/cache/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -847,20 +847,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-28T10:54:34+00:00"
|
"time": "2026-11-01T22:26:51+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache-contracts",
|
"name": "symfony/cache-contracts",
|
||||||
"version": "v3.7.1",
|
"version": "v3.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/cache-contracts.git",
|
"url": "https://github.com/symfony/cache-contracts.git",
|
||||||
"reference": "9789738bc19af1106dc54d6afba9a0b467516cf2"
|
"reference": "af26a91232085b7edd4e04be62f75e7c25159ece"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/cache-contracts/zipball/9789738bc19af1106dc54d6afba9a0b467516cf2",
|
"url": "https://api.github.com/repos/symfony/cache-contracts/zipball/af26a91232085b7edd4e04be62f75e7c25159ece",
|
||||||
"reference": "9789738bc19af1106dc54d6afba9a0b467516cf2",
|
"reference": "af26a91232085b7edd4e04be62f75e7c25159ece",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -874,7 +874,7 @@
|
|||||||
"name": "symfony/contracts"
|
"name": "symfony/contracts"
|
||||||
},
|
},
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "3.7-dev"
|
"dev-main": "3.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -907,7 +907,7 @@
|
|||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/cache-contracts/tree/v3.7.1"
|
"source": "https://github.com/symfony/cache-contracts/tree/v3.8.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -927,7 +927,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-05T06:23:12+00:00"
|
"time": "2026-09-26T07:05:14+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/clock",
|
"name": "symfony/clock",
|
||||||
@@ -1009,16 +1009,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/config",
|
"name": "symfony/config",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/config.git",
|
"url": "https://github.com/symfony/config.git",
|
||||||
"reference": "d7f9d7495992429d916aea42d1a4d76a12dfa29f"
|
"reference": "8ef666abf731e85e59cf478929dda6c7cb2fa9c4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/config/zipball/d7f9d7495992429d916aea42d1a4d76a12dfa29f",
|
"url": "https://api.github.com/repos/symfony/config/zipball/8ef666abf731e85e59cf478929dda6c7cb2fa9c4",
|
||||||
"reference": "d7f9d7495992429d916aea42d1a4d76a12dfa29f",
|
"reference": "8ef666abf731e85e59cf478929dda6c7cb2fa9c4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1064,7 +1064,7 @@
|
|||||||
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
|
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/config/tree/v7.4.22"
|
"source": "https://github.com/symfony/config/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1084,20 +1084,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-25T14:40:16+00:00"
|
"time": "2026-11-04T08:27:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "8012f842110b414fd1cc641adb0ed8423353b0bb"
|
"reference": "81957c2440c05c962fe8291f318de6e85f8db330"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/8012f842110b414fd1cc641adb0ed8423353b0bb",
|
"url": "https://api.github.com/repos/symfony/console/zipball/81957c2440c05c962fe8291f318de6e85f8db330",
|
||||||
"reference": "8012f842110b414fd1cc641adb0ed8423353b0bb",
|
"reference": "81957c2440c05c962fe8291f318de6e85f8db330",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1162,7 +1162,7 @@
|
|||||||
"terminal"
|
"terminal"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/console/tree/v7.4.22"
|
"source": "https://github.com/symfony/console/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1182,20 +1182,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-28T11:08:27+00:00"
|
"time": "2026-11-03T21:47:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/dependency-injection",
|
"name": "symfony/dependency-injection",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/dependency-injection.git",
|
"url": "https://github.com/symfony/dependency-injection.git",
|
||||||
"reference": "f98a1b0625d5608a723481fa104b5473e6b18ebd"
|
"reference": "4df0d83a8253d95b222c2f136b9dca3a1a9451a7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f98a1b0625d5608a723481fa104b5473e6b18ebd",
|
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/4df0d83a8253d95b222c2f136b9dca3a1a9451a7",
|
||||||
"reference": "f98a1b0625d5608a723481fa104b5473e6b18ebd",
|
"reference": "4df0d83a8253d95b222c2f136b9dca3a1a9451a7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1246,7 +1246,7 @@
|
|||||||
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/dependency-injection/tree/v7.4.22"
|
"source": "https://github.com/symfony/dependency-injection/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1266,20 +1266,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-25T14:40:16+00:00"
|
"time": "2026-11-01T17:38:00+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/deprecation-contracts",
|
"name": "symfony/deprecation-contracts",
|
||||||
"version": "v3.7.1",
|
"version": "v3.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||||
"reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d"
|
"reference": "feb1edf4e546af3b85c5caebe8359a20db230ca3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d",
|
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/feb1edf4e546af3b85c5caebe8359a20db230ca3",
|
||||||
"reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d",
|
"reference": "feb1edf4e546af3b85c5caebe8359a20db230ca3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1292,7 +1292,7 @@
|
|||||||
"name": "symfony/contracts"
|
"name": "symfony/contracts"
|
||||||
},
|
},
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "3.7-dev"
|
"dev-main": "3.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -1317,7 +1317,7 @@
|
|||||||
"description": "A generic function and convention to trigger deprecation notices",
|
"description": "A generic function and convention to trigger deprecation notices",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1"
|
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.8.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1337,7 +1337,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-05T06:23:12+00:00"
|
"time": "2026-09-16T14:15:10+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/dotenv",
|
"name": "symfony/dotenv",
|
||||||
@@ -1586,16 +1586,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher-contracts",
|
"name": "symfony/event-dispatcher-contracts",
|
||||||
"version": "v3.7.1",
|
"version": "v3.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
|
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
|
||||||
"reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e"
|
"reference": "658e29751424da3ef4758c60f769e59d1b2981eb"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c7de7a00ffb67842132da02ea92988a39ccd9f4e",
|
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/658e29751424da3ef4758c60f769e59d1b2981eb",
|
||||||
"reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e",
|
"reference": "658e29751424da3ef4758c60f769e59d1b2981eb",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1609,7 +1609,7 @@
|
|||||||
"name": "symfony/contracts"
|
"name": "symfony/contracts"
|
||||||
},
|
},
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "3.7-dev"
|
"dev-main": "3.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -1642,7 +1642,7 @@
|
|||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.1"
|
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.8.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1662,20 +1662,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-05T06:23:12+00:00"
|
"time": "2026-09-16T14:15:10+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
"version": "v7.4.21",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/filesystem.git",
|
"url": "https://github.com/symfony/filesystem.git",
|
||||||
"reference": "fd0e3462be6d32a0d130e8423e4940a7688162d8"
|
"reference": "53d609da66578dad5a39fe290e8f924ec8f05e93"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/fd0e3462be6d32a0d130e8423e4940a7688162d8",
|
"url": "https://api.github.com/repos/symfony/filesystem/zipball/53d609da66578dad5a39fe290e8f924ec8f05e93",
|
||||||
"reference": "fd0e3462be6d32a0d130e8423e4940a7688162d8",
|
"reference": "53d609da66578dad5a39fe290e8f924ec8f05e93",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1712,7 +1712,7 @@
|
|||||||
"description": "Provides basic utilities for the filesystem",
|
"description": "Provides basic utilities for the filesystem",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/filesystem/tree/v7.4.21"
|
"source": "https://github.com/symfony/filesystem/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1732,20 +1732,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-06T20:05:19+00:00"
|
"time": "2026-11-04T08:27:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/finder.git",
|
"url": "https://github.com/symfony/finder.git",
|
||||||
"reference": "e13420a8e0a76bdde1e7be09f923e62ad13739f2"
|
"reference": "c723f990aefe8c1053b18374faf4231eba84f518"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/finder/zipball/e13420a8e0a76bdde1e7be09f923e62ad13739f2",
|
"url": "https://api.github.com/repos/symfony/finder/zipball/c723f990aefe8c1053b18374faf4231eba84f518",
|
||||||
"reference": "e13420a8e0a76bdde1e7be09f923e62ad13739f2",
|
"reference": "c723f990aefe8c1053b18374faf4231eba84f518",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1780,7 +1780,7 @@
|
|||||||
"description": "Finds files and directories via an intuitive fluent interface",
|
"description": "Finds files and directories via an intuitive fluent interface",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/finder/tree/v7.4.22"
|
"source": "https://github.com/symfony/finder/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1800,20 +1800,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-19T16:56:54+00:00"
|
"time": "2026-11-02T10:56:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/framework-bundle",
|
"name": "symfony/framework-bundle",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/framework-bundle.git",
|
"url": "https://github.com/symfony/framework-bundle.git",
|
||||||
"reference": "17d23a62561b493b85486c9ae8c2752f36303b2c"
|
"reference": "6a749f2c37cb9def53793633ec72958aaad4b359"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/framework-bundle/zipball/17d23a62561b493b85486c9ae8c2752f36303b2c",
|
"url": "https://api.github.com/repos/symfony/framework-bundle/zipball/6a749f2c37cb9def53793633ec72958aaad4b359",
|
||||||
"reference": "17d23a62561b493b85486c9ae8c2752f36303b2c",
|
"reference": "6a749f2c37cb9def53793633ec72958aaad4b359",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1828,7 +1828,7 @@
|
|||||||
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
||||||
"symfony/filesystem": "^7.1|^8.0",
|
"symfony/filesystem": "^7.1|^8.0",
|
||||||
"symfony/finder": "^6.4|^7.0|^8.0",
|
"symfony/finder": "^6.4|^7.0|^8.0",
|
||||||
"symfony/http-foundation": "^7.4|^8.0",
|
"symfony/http-foundation": "^7.4.23|^8.1.11",
|
||||||
"symfony/http-kernel": "^7.4|^8.0",
|
"symfony/http-kernel": "^7.4|^8.0",
|
||||||
"symfony/polyfill-mbstring": "~1.0",
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
"symfony/polyfill-php85": "^1.32",
|
"symfony/polyfill-php85": "^1.32",
|
||||||
@@ -1937,7 +1937,7 @@
|
|||||||
"description": "Provides a tight integration between Symfony components and the Symfony full-stack framework",
|
"description": "Provides a tight integration between Symfony components and the Symfony full-stack framework",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/framework-bundle/tree/v7.4.22"
|
"source": "https://github.com/symfony/framework-bundle/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1957,20 +1957,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-26T21:52:50+00:00"
|
"time": "2026-11-04T07:46:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-foundation",
|
"name": "symfony/http-foundation",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-foundation.git",
|
"url": "https://github.com/symfony/http-foundation.git",
|
||||||
"reference": "63eda1d0c4de229d6b3e825709e49dd5c149699a"
|
"reference": "7fb73cffa06e2bcc2cb523fcccb1e8174106b206"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/63eda1d0c4de229d6b3e825709e49dd5c149699a",
|
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/7fb73cffa06e2bcc2cb523fcccb1e8174106b206",
|
||||||
"reference": "63eda1d0c4de229d6b3e825709e49dd5c149699a",
|
"reference": "7fb73cffa06e2bcc2cb523fcccb1e8174106b206",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2019,7 +2019,7 @@
|
|||||||
"description": "Defines an object-oriented layer for the HTTP specification",
|
"description": "Defines an object-oriented layer for the HTTP specification",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/http-foundation/tree/v7.4.22"
|
"source": "https://github.com/symfony/http-foundation/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -2039,20 +2039,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-27T13:26:03+00:00"
|
"time": "2026-11-04T08:27:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-kernel",
|
"name": "symfony/http-kernel",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-kernel.git",
|
"url": "https://github.com/symfony/http-kernel.git",
|
||||||
"reference": "87e727b33983238d3f2ea50f9f62265499ca1a6d"
|
"reference": "94c57f4c5c45a311d244a0aeadb72b14ee41d25d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/87e727b33983238d3f2ea50f9f62265499ca1a6d",
|
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/94c57f4c5c45a311d244a0aeadb72b14ee41d25d",
|
||||||
"reference": "87e727b33983238d3f2ea50f9f62265499ca1a6d",
|
"reference": "94c57f4c5c45a311d244a0aeadb72b14ee41d25d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2138,7 +2138,7 @@
|
|||||||
"description": "Provides a structured process for converting a Request into a Response",
|
"description": "Provides a structured process for converting a Request into a Response",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/http-kernel/tree/v7.4.22"
|
"source": "https://github.com/symfony/http-kernel/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -2158,7 +2158,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-28T18:18:28+00:00"
|
"time": "2026-11-04T11:26:18+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/mailer",
|
"name": "symfony/mailer",
|
||||||
@@ -3064,16 +3064,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/property-access",
|
"name": "symfony/property-access",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/property-access.git",
|
"url": "https://github.com/symfony/property-access.git",
|
||||||
"reference": "b45cfcfe0abdbba37350645dae148be29b94f25a"
|
"reference": "4dce45112d7a31d530d2e0e69143fc88eaa1521f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/b45cfcfe0abdbba37350645dae148be29b94f25a",
|
"url": "https://api.github.com/repos/symfony/property-access/zipball/4dce45112d7a31d530d2e0e69143fc88eaa1521f",
|
||||||
"reference": "b45cfcfe0abdbba37350645dae148be29b94f25a",
|
"reference": "4dce45112d7a31d530d2e0e69143fc88eaa1521f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3121,7 +3121,7 @@
|
|||||||
"reflection"
|
"reflection"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/property-access/tree/v7.4.22"
|
"source": "https://github.com/symfony/property-access/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3141,20 +3141,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-26T21:52:50+00:00"
|
"time": "2026-11-01T19:17:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/property-info",
|
"name": "symfony/property-info",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/property-info.git",
|
"url": "https://github.com/symfony/property-info.git",
|
||||||
"reference": "25c1b823ee4e0995e57e49bc0160c43ea199a7b5"
|
"reference": "1eeaa666bcd1864b883b98cad9e5188064ddac26"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/property-info/zipball/25c1b823ee4e0995e57e49bc0160c43ea199a7b5",
|
"url": "https://api.github.com/repos/symfony/property-info/zipball/1eeaa666bcd1864b883b98cad9e5188064ddac26",
|
||||||
"reference": "25c1b823ee4e0995e57e49bc0160c43ea199a7b5",
|
"reference": "1eeaa666bcd1864b883b98cad9e5188064ddac26",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3211,7 +3211,7 @@
|
|||||||
"validator"
|
"validator"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/property-info/tree/v7.4.22"
|
"source": "https://github.com/symfony/property-info/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3231,20 +3231,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-25T14:40:16+00:00"
|
"time": "2026-11-02T10:56:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/rate-limiter",
|
"name": "symfony/rate-limiter",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/rate-limiter.git",
|
"url": "https://github.com/symfony/rate-limiter.git",
|
||||||
"reference": "97a013c93ce39c70ace5316499c0d8aaec43a7f6"
|
"reference": "a65b8280000598b80b4456004280a56fdad011b3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/rate-limiter/zipball/97a013c93ce39c70ace5316499c0d8aaec43a7f6",
|
"url": "https://api.github.com/repos/symfony/rate-limiter/zipball/a65b8280000598b80b4456004280a56fdad011b3",
|
||||||
"reference": "97a013c93ce39c70ace5316499c0d8aaec43a7f6",
|
"reference": "a65b8280000598b80b4456004280a56fdad011b3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3285,7 +3285,7 @@
|
|||||||
"rate-limiter"
|
"rate-limiter"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/rate-limiter/tree/v7.4.22"
|
"source": "https://github.com/symfony/rate-limiter/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3305,20 +3305,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-20T19:25:08+00:00"
|
"time": "2026-11-01T19:17:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/routing",
|
"name": "symfony/routing",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/routing.git",
|
"url": "https://github.com/symfony/routing.git",
|
||||||
"reference": "f79ed6fbf60d9e32d358054f1915295f3b8a6f7a"
|
"reference": "0000ade604b7bc798cb1e75edf6f17df48185f73"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/routing/zipball/f79ed6fbf60d9e32d358054f1915295f3b8a6f7a",
|
"url": "https://api.github.com/repos/symfony/routing/zipball/0000ade604b7bc798cb1e75edf6f17df48185f73",
|
||||||
"reference": "f79ed6fbf60d9e32d358054f1915295f3b8a6f7a",
|
"reference": "0000ade604b7bc798cb1e75edf6f17df48185f73",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3370,7 +3370,7 @@
|
|||||||
"url"
|
"url"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/routing/tree/v7.4.22"
|
"source": "https://github.com/symfony/routing/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3390,20 +3390,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-26T21:52:50+00:00"
|
"time": "2026-11-04T08:27:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/security-bundle",
|
"name": "symfony/security-bundle",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/security-bundle.git",
|
"url": "https://github.com/symfony/security-bundle.git",
|
||||||
"reference": "0323d198b93b3ec4fd0e31a5e84516c2b28261d7"
|
"reference": "1cb338633172a5ce2fb92b31f5d39315f4aa4c00"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/security-bundle/zipball/0323d198b93b3ec4fd0e31a5e84516c2b28261d7",
|
"url": "https://api.github.com/repos/symfony/security-bundle/zipball/1cb338633172a5ce2fb92b31f5d39315f4aa4c00",
|
||||||
"reference": "0323d198b93b3ec4fd0e31a5e84516c2b28261d7",
|
"reference": "1cb338633172a5ce2fb92b31f5d39315f4aa4c00",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3415,7 +3415,7 @@
|
|||||||
"symfony/dependency-injection": "^6.4.11|^7.1.4|^8.0",
|
"symfony/dependency-injection": "^6.4.11|^7.1.4|^8.0",
|
||||||
"symfony/deprecation-contracts": "^2.5|^3",
|
"symfony/deprecation-contracts": "^2.5|^3",
|
||||||
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
||||||
"symfony/http-foundation": "^6.4|^7.0|^8.0",
|
"symfony/http-foundation": "^6.4.50|^7.4.23|^8.1.11",
|
||||||
"symfony/http-kernel": "^6.4.13|^7.1.6|^8.0",
|
"symfony/http-kernel": "^6.4.13|^7.1.6|^8.0",
|
||||||
"symfony/password-hasher": "^6.4|^7.0|^8.0",
|
"symfony/password-hasher": "^6.4|^7.0|^8.0",
|
||||||
"symfony/security-core": "^7.4.22|^8.1.10",
|
"symfony/security-core": "^7.4.22|^8.1.10",
|
||||||
@@ -3483,7 +3483,7 @@
|
|||||||
"description": "Provides a tight integration of the Security component into the Symfony full-stack framework",
|
"description": "Provides a tight integration of the Security component into the Symfony full-stack framework",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/security-bundle/tree/v7.4.22"
|
"source": "https://github.com/symfony/security-bundle/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3503,20 +3503,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-27T13:52:57+00:00"
|
"time": "2026-11-04T08:27:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/security-core",
|
"name": "symfony/security-core",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/security-core.git",
|
"url": "https://github.com/symfony/security-core.git",
|
||||||
"reference": "4efce2a1e6c3d686bf0ec9a098e425d53dc3e674"
|
"reference": "c93b2194c0255496c2c0ac999821fa7f5296c7cc"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/security-core/zipball/4efce2a1e6c3d686bf0ec9a098e425d53dc3e674",
|
"url": "https://api.github.com/repos/symfony/security-core/zipball/c93b2194c0255496c2c0ac999821fa7f5296c7cc",
|
||||||
"reference": "4efce2a1e6c3d686bf0ec9a098e425d53dc3e674",
|
"reference": "c93b2194c0255496c2c0ac999821fa7f5296c7cc",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3575,7 +3575,7 @@
|
|||||||
"description": "Symfony Security Component - Core Library",
|
"description": "Symfony Security Component - Core Library",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/security-core/tree/v7.4.22"
|
"source": "https://github.com/symfony/security-core/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3595,7 +3595,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-25T14:40:16+00:00"
|
"time": "2026-11-01T19:17:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/security-csrf",
|
"name": "symfony/security-csrf",
|
||||||
@@ -3673,16 +3673,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/security-http",
|
"name": "symfony/security-http",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/security-http.git",
|
"url": "https://github.com/symfony/security-http.git",
|
||||||
"reference": "0020c7563c188bade070cf4bc83be3ee75ceab29"
|
"reference": "ea0623a02764025268bd928810f012767ea1965a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/security-http/zipball/0020c7563c188bade070cf4bc83be3ee75ceab29",
|
"url": "https://api.github.com/repos/symfony/security-http/zipball/ea0623a02764025268bd928810f012767ea1965a",
|
||||||
"reference": "0020c7563c188bade070cf4bc83be3ee75ceab29",
|
"reference": "ea0623a02764025268bd928810f012767ea1965a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3742,7 +3742,7 @@
|
|||||||
"description": "Symfony Security Component - HTTP Integration",
|
"description": "Symfony Security Component - HTTP Integration",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/security-http/tree/v7.4.22"
|
"source": "https://github.com/symfony/security-http/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3762,20 +3762,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-28T10:54:34+00:00"
|
"time": "2026-11-04T08:27:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/service-contracts",
|
"name": "symfony/service-contracts",
|
||||||
"version": "v3.7.3",
|
"version": "v3.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/service-contracts.git",
|
"url": "https://github.com/symfony/service-contracts.git",
|
||||||
"reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257"
|
"reference": "052852a96fd5e5ebdb617dba22031e41a3300fb5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/15e6a07ec2a2c75ceb1b21dd98105ee8456d2257",
|
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/052852a96fd5e5ebdb617dba22031e41a3300fb5",
|
||||||
"reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257",
|
"reference": "052852a96fd5e5ebdb617dba22031e41a3300fb5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3793,7 +3793,7 @@
|
|||||||
"name": "symfony/contracts"
|
"name": "symfony/contracts"
|
||||||
},
|
},
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "3.7-dev"
|
"dev-main": "3.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -3829,7 +3829,7 @@
|
|||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/service-contracts/tree/v3.7.3"
|
"source": "https://github.com/symfony/service-contracts/tree/v3.8.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3849,7 +3849,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-07-27T15:39:01+00:00"
|
"time": "2026-10-20T17:38:25+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/stopwatch",
|
"name": "symfony/stopwatch",
|
||||||
@@ -4010,16 +4010,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/translation-contracts",
|
"name": "symfony/translation-contracts",
|
||||||
"version": "v3.7.1",
|
"version": "v3.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/translation-contracts.git",
|
"url": "https://github.com/symfony/translation-contracts.git",
|
||||||
"reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621"
|
"reference": "0a3ae917402632fcba2aeddae9c98332f3d7dd05"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/ccb206b98faccc511ebae8e5fad50f2dc0b30621",
|
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0a3ae917402632fcba2aeddae9c98332f3d7dd05",
|
||||||
"reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621",
|
"reference": "0a3ae917402632fcba2aeddae9c98332f3d7dd05",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -4032,7 +4032,7 @@
|
|||||||
"name": "symfony/contracts"
|
"name": "symfony/contracts"
|
||||||
},
|
},
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "3.7-dev"
|
"dev-main": "3.8-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -4068,7 +4068,7 @@
|
|||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/translation-contracts/tree/v3.7.1"
|
"source": "https://github.com/symfony/translation-contracts/tree/v3.8.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4088,7 +4088,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-05T06:23:12+00:00"
|
"time": "2026-10-03T08:17:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/twig-bridge",
|
"name": "symfony/twig-bridge",
|
||||||
@@ -4297,16 +4297,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/type-info",
|
"name": "symfony/type-info",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/type-info.git",
|
"url": "https://github.com/symfony/type-info.git",
|
||||||
"reference": "f69ab198af73e1aac485c0ff5aa066d20c14adf0"
|
"reference": "eca5fdb294539268ad3245b2214f32f24b337e09"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/type-info/zipball/f69ab198af73e1aac485c0ff5aa066d20c14adf0",
|
"url": "https://api.github.com/repos/symfony/type-info/zipball/eca5fdb294539268ad3245b2214f32f24b337e09",
|
||||||
"reference": "f69ab198af73e1aac485c0ff5aa066d20c14adf0",
|
"reference": "eca5fdb294539268ad3245b2214f32f24b337e09",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -4356,7 +4356,7 @@
|
|||||||
"type"
|
"type"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/type-info/tree/v7.4.22"
|
"source": "https://github.com/symfony/type-info/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4376,7 +4376,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-24T08:22:23+00:00"
|
"time": "2026-11-02T09:31:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
@@ -4548,16 +4548,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
"reference": "1ed6afa13d48c579c51cbf32e38f50686313497b"
|
"reference": "1e601207ffe627a2e621faa9d661f1d32dcf1cec"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/1ed6afa13d48c579c51cbf32e38f50686313497b",
|
"url": "https://api.github.com/repos/symfony/yaml/zipball/1e601207ffe627a2e621faa9d661f1d32dcf1cec",
|
||||||
"reference": "1ed6afa13d48c579c51cbf32e38f50686313497b",
|
"reference": "1e601207ffe627a2e621faa9d661f1d32dcf1cec",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -4600,7 +4600,7 @@
|
|||||||
"description": "Loads and dumps YAML files",
|
"description": "Loads and dumps YAML files",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/yaml/tree/v7.4.22"
|
"source": "https://github.com/symfony/yaml/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4620,7 +4620,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-18T14:39:27+00:00"
|
"time": "2026-11-04T08:27:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
@@ -7578,16 +7578,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/browser-kit",
|
"name": "symfony/browser-kit",
|
||||||
"version": "v7.4.22",
|
"version": "v7.4.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/browser-kit.git",
|
"url": "https://github.com/symfony/browser-kit.git",
|
||||||
"reference": "018a7c9b63d9ed402762a2d9f59238207928a2ed"
|
"reference": "a0d19ca90c1fcce29d3337decb761b5adb808965"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/018a7c9b63d9ed402762a2d9f59238207928a2ed",
|
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/a0d19ca90c1fcce29d3337decb761b5adb808965",
|
||||||
"reference": "018a7c9b63d9ed402762a2d9f59238207928a2ed",
|
"reference": "a0d19ca90c1fcce29d3337decb761b5adb808965",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -7628,7 +7628,7 @@
|
|||||||
"description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
|
"description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/browser-kit/tree/v7.4.22"
|
"source": "https://github.com/symfony/browser-kit/tree/v7.4.23"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -7648,7 +7648,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-10-20T19:25:08+00:00"
|
"time": "2026-11-01T07:00:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/css-selector",
|
"name": "symfony/css-selector",
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ function renderContent(block, panel) {
|
|||||||
};
|
};
|
||||||
// Eine Eigenschaft setzen, die kein Textfeld ist (Symbol, Stellung, Bewegung). Danach wird das
|
// Eine Eigenschaft setzen, die kein Textfeld ist (Symbol, Stellung, Bewegung). Danach wird das
|
||||||
// Panel neu gezeichnet, und der Fokus kehrt zu dem Bedienelement zurück, das sie gesetzt hat.
|
// Panel neu gezeichnet, und der Fokus kehrt zu dem Bedienelement zurück, das sie gesetzt hat.
|
||||||
const choose = (key, next, version, focus) => {
|
const setProp = (key, next, version, focus) => {
|
||||||
history.change(doc => {
|
history.change(doc => {
|
||||||
const current = locate(doc.blocks, selected)?.block;
|
const current = locate(doc.blocks, selected)?.block;
|
||||||
if (!current) return;
|
if (!current) return;
|
||||||
@@ -370,7 +370,7 @@ function renderContent(block, panel) {
|
|||||||
document.querySelector(focus)?.focus({ preventScroll: true });
|
document.querySelector(focus)?.focus({ preventScroll: true });
|
||||||
};
|
};
|
||||||
const iconField = (label, value, options = {}) => panel.append(renderIconField({
|
const iconField = (label, value, options = {}) => panel.append(renderIconField({
|
||||||
label, value, none: options.none, onChoose: name => choose('icon', name, options.version, '.icon-field-change'),
|
label, value, none: options.none, onChoose: name => setProp('icon', name, options.version, '.icon-field-change'),
|
||||||
}));
|
}));
|
||||||
// Zwei bis drei Möglichkeiten nebeneinander statt einer Auswahlliste.
|
// Zwei bis drei Möglichkeiten nebeneinander statt einer Auswahlliste.
|
||||||
const segmented = (label, key, current, options, version) => {
|
const segmented = (label, key, current, options, version) => {
|
||||||
@@ -381,7 +381,7 @@ function renderContent(block, panel) {
|
|||||||
for (const [value, text] of options) {
|
for (const [value, text] of options) {
|
||||||
const option = document.createElement('button'); option.type = 'button'; option.dataset[key] = value; option.textContent = text;
|
const option = document.createElement('button'); option.type = 'button'; option.dataset[key] = value; option.textContent = text;
|
||||||
option.setAttribute('aria-pressed', String(value === current));
|
option.setAttribute('aria-pressed', String(value === current));
|
||||||
option.addEventListener('click', () => { if (value !== current) choose(key, value, version, `[data-${key.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`)}="${value}"]`); });
|
option.addEventListener('click', () => { if (value !== current) setProp(key, value, version, `[data-${key.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`)}="${value}"]`); });
|
||||||
group.append(option);
|
group.append(option);
|
||||||
}
|
}
|
||||||
wrap.append(caption, group); panel.append(wrap);
|
wrap.append(caption, group); panel.append(wrap);
|
||||||
|
|||||||
@@ -159,8 +159,14 @@
|
|||||||
if (group.closest('[data-inactive]')) continue;
|
if (group.closest('[data-inactive]')) continue;
|
||||||
const note = group.querySelector('.field-error[data-live]');
|
const note = group.querySelector('.field-error[data-live]');
|
||||||
if (!group.querySelector('input:checked')) {
|
if (!group.querySelector('input:checked')) {
|
||||||
if (!note) group.append(Object.assign(el('p', 'field-error', t('chooseOne', 'Bitte wähle mindestens eine Option.')), { dataset: { live: '' } }));
|
if (!note) {
|
||||||
else note.hidden = false;
|
// dataset lässt sich nicht als Ganzes zuweisen: Object.assign warf hier, und „Weiter“
|
||||||
|
// tat ohne Meldung nichts.
|
||||||
|
const hint = el('p', 'field-error', t('chooseOne', 'Bitte wähle mindestens eine Option.'));
|
||||||
|
hint.dataset.live = '';
|
||||||
|
hint.setAttribute('role', 'alert');
|
||||||
|
group.append(hint);
|
||||||
|
} else note.hidden = false;
|
||||||
group.classList.add('has-error');
|
group.classList.add('has-error');
|
||||||
group.querySelector('input')?.focus();
|
group.querySelector('input')?.focus();
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -707,7 +707,10 @@ final class FormRepository
|
|||||||
'id' => $id, 'form_id' => $formId,
|
'id' => $id, 'form_id' => $formId,
|
||||||
'data' => json_encode($values, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE),
|
'data' => json_encode($values, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE),
|
||||||
'sender_hash' => $senderHash, 'created_at' => $now,
|
'sender_hash' => $senderHash, 'created_at' => $now,
|
||||||
'consent_at' => $consent ? $now : null, 'delivered' => false,
|
'consent_at' => $consent ? $now : null,
|
||||||
|
// Als Zahl: ohne Typangabe wird false als leere Zeichenkette gebunden, und MySQL im
|
||||||
|
// Strict-Modus lehnt die für eine Zahlenspalte ab. SQLite nimmt beides.
|
||||||
|
'delivered' => 0,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $id;
|
return $id;
|
||||||
@@ -715,7 +718,7 @@ final class FormRepository
|
|||||||
|
|
||||||
public function markDelivered(string $submissionId): void
|
public function markDelivered(string $submissionId): void
|
||||||
{
|
{
|
||||||
$this->db->executeStatement('UPDATE form_submission SET delivered = ? WHERE id = ?', [true, $submissionId]);
|
$this->db->executeStatement('UPDATE form_submission SET delivered = ? WHERE id = ?', [1, $submissionId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -190,6 +190,12 @@ final class PageRepository
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Ob eine Seite eine veröffentlichte Fassung trägt - auch wenn sie im Papierkorb liegt. */
|
||||||
|
public function hasPublication(string $pageId): bool
|
||||||
|
{
|
||||||
|
return false !== $this->db->fetchOne('SELECT id FROM page WHERE id = ? AND website_id = ? AND published_revision_id IS NOT NULL', [$pageId, 'default']);
|
||||||
|
}
|
||||||
|
|
||||||
public function trashPage(string $pageId, int $expectedVersion): int
|
public function trashPage(string $pageId, int $expectedVersion): int
|
||||||
{
|
{
|
||||||
return $this->db->transactional(function () use ($pageId, $expectedVersion): int {
|
return $this->db->transactional(function () use ($pageId, $expectedVersion): int {
|
||||||
|
|||||||
@@ -332,13 +332,20 @@ final class EditorController extends AbstractController
|
|||||||
if (!$this->isCsrfTokenValid('pages', $request->request->getString('_csrf_token'))) {
|
if (!$this->isCsrfTokenValid('pages', $request->request->getString('_csrf_token'))) {
|
||||||
return $this->back('Deine Sitzung ist abgelaufen. Bitte melde dich erneut an.');
|
return $this->back('Deine Sitzung ist abgelaufen. Bitte melde dich erneut an.');
|
||||||
}
|
}
|
||||||
|
// Der Papierkorb lässt die veröffentlichte Fassung stehen: eine Seite, die online war, ist
|
||||||
|
// nach dem Wiederherstellen sofort wieder online. Das entscheidet, wer veröffentlichen
|
||||||
|
// darf (ADR 116) - wie beim Weg in den Papierkorb.
|
||||||
|
$live = $this->pages->hasPublication($id);
|
||||||
|
if ($live && !$this->isGranted('ROLE_PUBLISHER')) {
|
||||||
|
return $this->back('Diese Seite war veröffentlicht und wäre nach dem Wiederherstellen sofort wieder öffentlich. Das macht, wer veröffentlichen darf.');
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
$this->pages->restorePage($id);
|
$this->pages->restorePage($id);
|
||||||
} catch (InvalidPage $e) {
|
} catch (InvalidPage $e) {
|
||||||
return $this->back($e->getMessage());
|
return $this->back($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->back('Die Seite ist zurück. Sie ist erst nach dem Veröffentlichen wieder öffentlich.', 'success');
|
return $this->back($live ? 'Die Seite ist zurück und wieder öffentlich.' : 'Die Seite ist zurück. Sie ist ein Entwurf, bis sie veröffentlicht wird.', 'success');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/pages/{id}/revisions/{revision}', name: 'admin_restore_revision', requirements: ['revision' => '[a-f0-9]{32}'], methods: ['POST'])]
|
#[Route('/pages/{id}/revisions/{revision}', name: 'admin_restore_revision', requirements: ['revision' => '[a-f0-9]{32}'], methods: ['POST'])]
|
||||||
|
|||||||
@@ -43,8 +43,12 @@ final class FormController extends AbstractController
|
|||||||
{
|
{
|
||||||
$form = $this->forms->findBySlug($slug);
|
$form = $this->forms->findBySlug($slug);
|
||||||
$path = trim($request->request->getString('page'), '/') ?: $this->settings->homePath();
|
$path = trim($request->request->getString('page'), '/') ?: $this->settings->homePath();
|
||||||
|
// Ein Archiv (Beiträge, Kategorie, Schlagwort) ist keine gespeicherte Seite, trägt aber Kopf
|
||||||
|
// und Fuß wie jede andere - und damit oft das Kontaktformular. Ohne diese Ausnahme endete
|
||||||
|
// das Absenden dort in einer 404, und die Anfrage war weg.
|
||||||
|
$archive = 1 === preg_match(PageController::ARCHIVE_PATH, $path);
|
||||||
// Ein Formular kann auch auf der Seite eines Plugins stehen (ADR 127).
|
// Ein Formular kann auch auf der Seite eines Plugins stehen (ADR 127).
|
||||||
$page = $this->pages->findPublished($path) ?? $this->plugins->page('/'.$path);
|
$page = $archive ? ['id' => null, 'path' => $path] : ($this->pages->findPublished($path) ?? $this->plugins->page('/'.$path));
|
||||||
if (null === $form || null === $page) {
|
if (null === $form || null === $page) {
|
||||||
throw $this->createNotFoundException('Formular oder Seite nicht gefunden.');
|
throw $this->createNotFoundException('Formular oder Seite nicht gefunden.');
|
||||||
}
|
}
|
||||||
@@ -65,7 +69,8 @@ final class FormController extends AbstractController
|
|||||||
$language = $request->request->getString('language');
|
$language = $request->request->getString('language');
|
||||||
$translatedPath = null;
|
$translatedPath = null;
|
||||||
if ($this->languages->isExtra($language)) {
|
if ($this->languages->isExtra($language)) {
|
||||||
$translatedPath = $this->pages->translatedPaths($page['id'])[$language] ?? null;
|
// Archive heißen in jeder Sprache gleich und stehen nur hinter der Sprache.
|
||||||
|
$translatedPath = $archive ? $path : ($this->pages->translatedPaths($page['id'])[$language] ?? null);
|
||||||
}
|
}
|
||||||
$language = null === $translatedPath ? null : $language;
|
$language = null === $translatedPath ? null : $language;
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ final class PageController extends AbstractController
|
|||||||
// the CMS routes (/admin, /media, /assets) out of the catch-all, which matches before them.
|
// the CMS routes (/admin, /media, /assets) out of the catch-all, which matches before them.
|
||||||
private const PATH = '(?!admin(?:/|$)|media/|assets/|kategorie/|schlagwort/|beitraege(?:/|$)|einwilligung$|feed\.xml$|sitemap\.xml$|robots\.txt$|llms\.txt$)[a-z0-9]+(?:-[a-z0-9]+)*(?:/[a-z0-9]+(?:-[a-z0-9]+)*){0,4}';
|
private const PATH = '(?!admin(?:/|$)|media/|assets/|kategorie/|schlagwort/|beitraege(?:/|$)|einwilligung$|feed\.xml$|sitemap\.xml$|robots\.txt$|llms\.txt$)[a-z0-9]+(?:-[a-z0-9]+)*(?:/[a-z0-9]+(?:-[a-z0-9]+)*){0,4}';
|
||||||
|
|
||||||
|
/** Die Adressen der Archive, ohne Sprache davor: Beiträge, eine Kategorie, ein Schlagwort. */
|
||||||
|
public const ARCHIVE_PATH = '#^(beitraege|kategorie/([a-z0-9-]{1,80})|schlagwort/([a-z0-9-]{1,80}))$#D';
|
||||||
|
|
||||||
#[Route('/', name: 'home', methods: ['GET'])]
|
#[Route('/', name: 'home', methods: ['GET'])]
|
||||||
#[Route('/{path}', name: 'page', requirements: ['path' => self::PATH], methods: ['GET'])]
|
#[Route('/{path}', name: 'page', requirements: ['path' => self::PATH], methods: ['GET'])]
|
||||||
public function page(Request $request, string $path = ''): Response
|
public function page(Request $request, string $path = ''): Response
|
||||||
@@ -60,6 +63,11 @@ final class PageController extends AbstractController
|
|||||||
if ('' !== $path && $this->languages->isExtra($segments[0])) {
|
if ('' !== $path && $this->languages->isExtra($segments[0])) {
|
||||||
return $this->translatedPage($request, $segments[0], $segments[1] ?? '');
|
return $this->translatedPage($request, $segments[0], $segments[1] ?? '');
|
||||||
}
|
}
|
||||||
|
// Nur der Formularversand kommt mit einer Archivadresse hier an (die Route selbst schließt
|
||||||
|
// sie aus): er zeigt das Archiv mit den Meldungen des Formulars noch einmal.
|
||||||
|
if (1 === preg_match(self::ARCHIVE_PATH, $path, $archiv)) {
|
||||||
|
return $this->renderArchive($request, str_starts_with($path, 'kategorie/') ? 'category' : 'tag', '' !== ($archiv[2] ?? '') ? $archiv[2] : (($archiv[3] ?? '') ?: null));
|
||||||
|
}
|
||||||
// Mehr als vier Ebenen gibt es nur mit einer Sprache davor.
|
// Mehr als vier Ebenen gibt es nur mit einer Sprache davor.
|
||||||
if (substr_count($path, '/') >= PageRepository::MAX_DEPTH) {
|
if (substr_count($path, '/') >= PageRepository::MAX_DEPTH) {
|
||||||
return $this->notFound($request);
|
return $this->notFound($request);
|
||||||
@@ -111,7 +119,7 @@ final class PageController extends AbstractController
|
|||||||
return $this->shell($this->redirect('/'.$locale, 301));
|
return $this->shell($this->redirect('/'.$locale, 301));
|
||||||
}
|
}
|
||||||
// Die Archive gibt es in jeder Sprache unter derselben Adresse mit vorangestellter Sprache.
|
// Die Archive gibt es in jeder Sprache unter derselben Adresse mit vorangestellter Sprache.
|
||||||
if (1 === preg_match('#^(beitraege|kategorie/([a-z0-9-]{1,80})|schlagwort/([a-z0-9-]{1,80}))$#D', $rest, $archiv)) {
|
if (1 === preg_match(self::ARCHIVE_PATH, $rest, $archiv)) {
|
||||||
$this->translation = ['locale' => $locale, 'map' => $map];
|
$this->translation = ['locale' => $locale, 'map' => $map];
|
||||||
|
|
||||||
return $this->renderArchive($request, str_starts_with($rest, 'kategorie/') ? 'category' : 'tag', '' !== ($archiv[2] ?? '') ? $archiv[2] : (($archiv[3] ?? '') ?: null));
|
return $this->renderArchive($request, str_starts_with($rest, 'kategorie/') ? 'category' : 'tag', '' !== ($archiv[2] ?? '') ? $archiv[2] : (($archiv[3] ?? '') ?: null));
|
||||||
@@ -933,7 +941,9 @@ final class PageController extends AbstractController
|
|||||||
// Stylesheet-Bündel, Nach-oben-Knopf, Einwilligung, Blätterverweise. Vorher hatte es eine
|
// Stylesheet-Bündel, Nach-oben-Knopf, Einwilligung, Blätterverweise. Vorher hatte es eine
|
||||||
// eigene Vorlage, die von alledem nur die Palette kannte.
|
// eigene Vorlage, die von alledem nur die Palette kannte.
|
||||||
$kopf = [
|
$kopf = [
|
||||||
['id' => 'archiv-titel', 'type' => 'heading', 'props' => ['text' => $heading, 'level' => 1]],
|
// Ab Schemaversion 12 wird der Text einer Überschrift als Markup gedruckt. Der Name
|
||||||
|
// einer Kategorie ist aber freier Text, den niemand gefiltert hat - also maskieren.
|
||||||
|
['id' => 'archiv-titel', 'type' => 'heading', 'props' => ['text' => htmlspecialchars($heading, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), 'level' => 1]],
|
||||||
['id' => 'archiv-zahl', 'type' => 'text', 'props' => ['text' => sprintf('%d %s', $result['total'], 1 === $result['total'] ? $t('Beitrag') : $t('Beiträge'))]],
|
['id' => 'archiv-zahl', 'type' => 'text', 'props' => ['text' => sprintf('%d %s', $result['total'], 1 === $result['total'] ? $t('Beitrag') : $t('Beiträge'))]],
|
||||||
];
|
];
|
||||||
if (null !== $term) {
|
if (null !== $term) {
|
||||||
|
|||||||
@@ -177,6 +177,9 @@ final class SystemController extends AbstractController
|
|||||||
@set_time_limit(0);
|
@set_time_limit(0);
|
||||||
if ($request->request->getBoolean('finish')) {
|
if ($request->request->getBoolean('finish')) {
|
||||||
$ergebnis = $this->archive->finish($this->installation);
|
$ergebnis = $this->archive->finish($this->installation);
|
||||||
|
if ($ergebnis['laeuft'] ?? false) {
|
||||||
|
return $this->back(ArchiveUpdate::LAEUFT_BEREITS);
|
||||||
|
}
|
||||||
$request->getSession()->set('update_steps', $ergebnis['steps']);
|
$request->getSession()->set('update_steps', $ergebnis['steps']);
|
||||||
$this->addFlash($ergebnis['ok'] ? 'success' : 'error', $ergebnis['ok']
|
$this->addFlash($ergebnis['ok'] ? 'success' : 'error', $ergebnis['ok']
|
||||||
? 'Das Update ist fertig. Die Website ist wieder erreichbar.'
|
? 'Das Update ist fertig. Die Website ist wieder erreichbar.'
|
||||||
@@ -271,6 +274,10 @@ final class SystemController extends AbstractController
|
|||||||
}
|
}
|
||||||
@set_time_limit(0);
|
@set_time_limit(0);
|
||||||
$ergebnis = $this->archive->finish($this->installation, $this->pruefung);
|
$ergebnis = $this->archive->finish($this->installation, $this->pruefung);
|
||||||
|
if ($ergebnis['laeuft'] ?? false) {
|
||||||
|
// Der andere Abschluss schreibt den Stand fort; die Systemseite fragt ihn weiter ab.
|
||||||
|
return new JsonResponse(['ok' => true, 'meldung' => ArchiveUpdate::LAEUFT_BEREITS, 'status' => $this->archive->status()]);
|
||||||
|
}
|
||||||
$this->sendJsonAndStop(['ok' => $ergebnis['ok'], 'status' => $this->archive->status()]);
|
$this->sendJsonAndStop(['ok' => $ergebnis['ok'], 'status' => $this->archive->status()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,6 +318,9 @@ final class SystemController extends AbstractController
|
|||||||
}
|
}
|
||||||
@set_time_limit(0);
|
@set_time_limit(0);
|
||||||
$ergebnis = $this->archive->finish($this->installation);
|
$ergebnis = $this->archive->finish($this->installation);
|
||||||
|
if ($ergebnis['laeuft'] ?? false) {
|
||||||
|
return $this->back(ArchiveUpdate::LAEUFT_BEREITS);
|
||||||
|
}
|
||||||
$request->getSession()->set('update_steps', $ergebnis['steps']);
|
$request->getSession()->set('update_steps', $ergebnis['steps']);
|
||||||
$this->addFlash($ergebnis['ok'] ? 'success' : 'error', $ergebnis['ok']
|
$this->addFlash($ergebnis['ok'] ? 'success' : 'error', $ergebnis['ok']
|
||||||
? sprintf('Update auf %s abgeschlossen. Die Website ist wieder erreichbar.', $offen['fassung'])
|
? sprintf('Update auf %s abgeschlossen. Die Website ist wieder erreichbar.', $offen['fassung'])
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ final class RemoteUpdateFinishSubscriber implements EventSubscriberInterface
|
|||||||
}
|
}
|
||||||
@ignore_user_abort(true);
|
@ignore_user_abort(true);
|
||||||
@set_time_limit(0);
|
@set_time_limit(0);
|
||||||
$this->archive->finish($this->installation, $this->pruefung);
|
$this->archive->finish($this->installation, $this->pruefung, true);
|
||||||
} catch (\Throwable) {
|
} catch (\Throwable) {
|
||||||
// Was schiefging, steht im Updateprotokoll; die Wartungsseite bleibt dann an.
|
// Was schiefging, steht im Updateprotokoll; die Wartungsseite bleibt dann an.
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ namespace App\Ops;
|
|||||||
*/
|
*/
|
||||||
final class ArchiveUpdate
|
final class ArchiveUpdate
|
||||||
{
|
{
|
||||||
|
public const LAEUFT_BEREITS = 'Der Abschluss läuft bereits in einer anderen Anfrage. Diese Seite in einem Moment neu laden.';
|
||||||
|
|
||||||
/** Was aus dem Archiv übernommen wird. Alles andere im Projektstamm bleibt unberührt. */
|
/** Was aus dem Archiv übernommen wird. Alles andere im Projektstamm bleibt unberührt. */
|
||||||
private const ERSETZEN = ['bin', 'config', 'migrations', 'src', 'templates', 'vendor', 'composer.json', 'composer.lock', 'migrations.php', 'cli-config.php', 'VERSION'];
|
private const ERSETZEN = ['bin', 'config', 'migrations', 'src', 'templates', 'vendor', 'composer.json', 'composer.lock', 'migrations.php', 'cli-config.php', 'VERSION'];
|
||||||
|
|
||||||
@@ -363,7 +365,28 @@ final class ArchiveUpdate
|
|||||||
* gibt null zurück oder den Grund, warum sie nicht
|
* gibt null zurück oder den Grund, warum sie nicht
|
||||||
* läuft - dann wird zurückgeschaltet
|
* läuft - dann wird zurückgeschaltet
|
||||||
*/
|
*/
|
||||||
public function finish(Installation $installation, ?callable $pruefen = null): array
|
public function finish(Installation $installation, ?callable $pruefen = null, bool $gesperrt = false): array
|
||||||
|
{
|
||||||
|
// Nur ein Abschluss zur selben Zeit. Die Zwischenseite ruft ihn von selbst auf und bietet
|
||||||
|
// daneben einen Link an: Zwei Abschlüsse nebeneinander ließen den zweiten an der bereits
|
||||||
|
// laufenden Migration scheitern - und der schaltete dann zurück, Code und Datenbank,
|
||||||
|
// obwohl der erste gelungen war. $gesperrt: der Aufrufer hält die Sperre schon.
|
||||||
|
$sperre = $gesperrt ? null : $this->updater->lock();
|
||||||
|
if (!$gesperrt && null === $sperre) {
|
||||||
|
return ['ok' => false, 'laeuft' => true, 'steps' => [['step' => 'Abschluss', 'ok' => true, 'detail' => self::LAEUFT_BEREITS]]];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return $this->abschliessen($installation, $pruefen);
|
||||||
|
} finally {
|
||||||
|
if (null !== $sperre) {
|
||||||
|
flock($sperre, LOCK_UN);
|
||||||
|
fclose($sperre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param (callable(): ?string)|null $pruefen */
|
||||||
|
private function abschliessen(Installation $installation, ?callable $pruefen): array
|
||||||
{
|
{
|
||||||
$schritte = [];
|
$schritte = [];
|
||||||
$offen = $this->pending();
|
$offen = $this->pending();
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ final class Scheduler
|
|||||||
$this->db->insert('scheduled_task', [
|
$this->db->insert('scheduled_task', [
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'interval_seconds' => $task->interval(),
|
'interval_seconds' => $task->interval(),
|
||||||
'enabled' => true,
|
'enabled' => 1,
|
||||||
'next_run_at' => $now->modify('+120 seconds')->format('Y-m-d H:i:s'),
|
'next_run_at' => $now->modify('+120 seconds')->format('Y-m-d H:i:s'),
|
||||||
'last_message' => '',
|
'last_message' => '',
|
||||||
'last_duration_ms' => 0,
|
'last_duration_ms' => 0,
|
||||||
@@ -357,7 +357,7 @@ final class Scheduler
|
|||||||
|
|
||||||
public function enable(string $name, bool $on): void
|
public function enable(string $name, bool $on): void
|
||||||
{
|
{
|
||||||
$this->db->executeStatement('UPDATE scheduled_task SET enabled = ? WHERE name = ?', [$on, $name]);
|
$this->db->executeStatement('UPDATE scheduled_task SET enabled = ? WHERE name = ?', [(int) $on, $name]);
|
||||||
$this->refreshState();
|
$this->refreshState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,8 +160,10 @@ final class PluginRegistry
|
|||||||
private function write(string $name, array $fields): void
|
private function write(string $name, array $fields): void
|
||||||
{
|
{
|
||||||
$existing = $this->rows()[$name] ?? null;
|
$existing = $this->rows()[$name] ?? null;
|
||||||
|
// Wahrheitswerte als Zahl: false ginge sonst als leere Zeichenkette an die Datenbank.
|
||||||
|
$fields = array_map(static fn (mixed $value): mixed => \is_bool($value) ? (int) $value : $value, $fields);
|
||||||
if (null === $existing) {
|
if (null === $existing) {
|
||||||
$this->db->insert('plugin', ['name' => $name, 'active' => false, 'version' => '', 'activated_at' => null, 'settings' => '{}', ...$fields]);
|
$this->db->insert('plugin', ['name' => $name, 'active' => 0, 'version' => '', 'activated_at' => null, 'settings' => '{}', ...$fields]);
|
||||||
} else {
|
} else {
|
||||||
$this->db->update('plugin', $fields, ['name' => $name]);
|
$this->db->update('plugin', $fields, ['name' => $name]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -311,6 +311,31 @@ final class ArchiveUpdateTest extends TestCase
|
|||||||
self::assertFileDoesNotExist($this->root.'/'.Updater::MAINTENANCE_FILE);
|
self::assertFileDoesNotExist($this->root.'/'.Updater::MAINTENANCE_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testASecondFinishWhileOneRunsDoesNotSwitchBack(): void
|
||||||
|
{
|
||||||
|
// Meta-Refresh und der Link „Weiter, falls nichts passiert“ können den Abschluss zweimal
|
||||||
|
// anstoßen. Der zweite darf nichts tun - vorher scheiterte er an der laufenden Migration
|
||||||
|
// und schaltete ein gelungenes Update zurück.
|
||||||
|
$this->releases->release(self::BASE, self::API, '1.1.0', $this->archive('1.1.0'));
|
||||||
|
self::assertTrue($this->updater()->run()['ok']);
|
||||||
|
$sperre = (new Updater($this->root, 'sqlite:///'.$this->root.'/var/cms.db', new CommandRunner(), $this->db))->lock();
|
||||||
|
self::assertNotNull($sperre);
|
||||||
|
|
||||||
|
$zweiter = $this->updater()->finish($this->installation(), static fn (): string => 'würde zurückschalten');
|
||||||
|
|
||||||
|
self::assertTrue($zweiter['laeuft'] ?? false);
|
||||||
|
self::assertSame('1.1.0', trim((string) file_get_contents($this->root.'/VERSION')), 'Der Code der neuen Fassung bleibt.');
|
||||||
|
self::assertNotNull($this->updater()->pending(), 'Der offene Abschluss gehört weiter dem ersten Lauf.');
|
||||||
|
self::assertSame('migrieren', $this->updater()->status()['phase']);
|
||||||
|
|
||||||
|
flock($sperre, LOCK_UN);
|
||||||
|
fclose($sperre);
|
||||||
|
// Wer die Sperre schon hält (der Abschluss aus der Ferne), läuft durch.
|
||||||
|
$fertig = $this->updater()->finish($this->installation());
|
||||||
|
self::assertTrue($fertig['ok'], $this->explain($fertig));
|
||||||
|
self::assertNull($this->updater()->pending());
|
||||||
|
}
|
||||||
|
|
||||||
public function testANewVersionThatDoesNotRunIsSwitchedBackCompletely(): void
|
public function testANewVersionThatDoesNotRunIsSwitchedBackCompletely(): void
|
||||||
{
|
{
|
||||||
// Wie bei reiseSoft: Läuft die neue Fassung nach den Migrationen nicht, kommt die alte
|
// Wie bei reiseSoft: Läuft die neue Fassung nach den Migrationen nicht, kommt die alte
|
||||||
|
|||||||
@@ -163,6 +163,39 @@ final class BacklogTest extends TestCase
|
|||||||
self::assertStringContainsString('Dieses Feld wird benötigt.', $antwort->getContent());
|
self::assertStringContainsString('Dieses Feld wird benötigt.', $antwort->getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAFormInTheFooterCanBeSentFromAnArchive(): void
|
||||||
|
{
|
||||||
|
(new FormRepository($this->db))->save('kontakt', 'Kontakt', [
|
||||||
|
['name' => 'email', 'type' => 'email', 'label' => 'E-Mail', 'required' => true],
|
||||||
|
['name' => 'datenschutz', 'type' => 'consent', 'label' => 'Einverstanden'],
|
||||||
|
], ['recipient' => 'info@example.org'], 0);
|
||||||
|
$footer = $this->partials->findByKind('footer');
|
||||||
|
$doc = $footer['document'];
|
||||||
|
$doc['schemaVersion'] = 23;
|
||||||
|
$doc['blocks'][] = ['id' => 'fuss-formular', 'type' => 'form', 'props' => ['form' => 'kontakt']];
|
||||||
|
$this->partials->save($footer['id'], $doc, $footer['version']);
|
||||||
|
$this->publishHome(DemoContent::starter('Start'));
|
||||||
|
$this->post('erster', 'Erster Beitrag', '2026-01-01 10:00', ['Neues']);
|
||||||
|
self::assertStringContainsString('name="page" value="beitraege"', $this->request('/beitraege')->getContent());
|
||||||
|
|
||||||
|
// Ein Archiv ist keine gespeicherte Seite. Vorher endete das Absenden hier in einer 404,
|
||||||
|
// bevor irgendetwas gespeichert oder verschickt war.
|
||||||
|
$body = fn (string $page, string $email): array => ['page' => $page, 'block' => 'fuss-formular', 'issued' => (string) (time() - 10), 'issuedSignature' => FormRepository::stamp('kontakt', time() - 10, 'test-only'), 'email' => $email, 'datenschutz' => 'ja'];
|
||||||
|
$fehler = $this->request('/formular/kontakt', 'POST', $body('beitraege', ''));
|
||||||
|
self::assertSame(422, $fehler->getStatusCode());
|
||||||
|
self::assertStringContainsString('Dieses Feld wird benötigt.', $fehler->getContent());
|
||||||
|
self::assertStringContainsString('Erster Beitrag', $fehler->getContent(), 'Die Meldung steht im Archiv, nicht auf einer Fehlerseite.');
|
||||||
|
|
||||||
|
foreach (['beitraege', 'kategorie/neues'] as $n => $archiv) {
|
||||||
|
$antwort = $this->request('/formular/kontakt', 'POST', $body($archiv, 'kunde'.$n.'@example.org'));
|
||||||
|
self::assertSame(303, $antwort->getStatusCode());
|
||||||
|
self::assertSame('/'.$archiv.'?gesendet=kontakt#fuss-formular', $antwort->headers->get('Location'));
|
||||||
|
self::assertSame($n + 1, (int) $this->db->fetchOne('SELECT COUNT(*) FROM form_submission'), 'Die Anfrage ist gespeichert.');
|
||||||
|
}
|
||||||
|
self::assertSame(200, $this->request('/beitraege?gesendet=kontakt')->getStatusCode());
|
||||||
|
self::assertSame(404, $this->request('/formular/kontakt', 'POST', $body('gibt-es-nicht', 'x@example.org'))->getStatusCode(), 'Eine unbekannte Seite bleibt eine unbekannte Seite.');
|
||||||
|
}
|
||||||
|
|
||||||
public function testASectionLinkedTwiceRendersWithoutDuplicateIds(): void
|
public function testASectionLinkedTwiceRendersWithoutDuplicateIds(): void
|
||||||
{
|
{
|
||||||
$sektion = DemoContent::starter('Band');
|
$sektion = DemoContent::starter('Band');
|
||||||
|
|||||||
@@ -931,6 +931,18 @@ final class CmsTest extends TestCase
|
|||||||
self::assertStringContainsString('href="https://cms.test/beitraege"', $html);
|
self::assertStringContainsString('href="https://cms.test/beitraege"', $html);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testACategoryNameIsPrintedAsTextInItsArchiveHeading(): void
|
||||||
|
{
|
||||||
|
// Die Überschrift des Archivs läuft durch den Baustein „Überschrift“, der seinen Text als
|
||||||
|
// Markup druckt. Ein Kategoriename ist aber ungefilterter Text eines Redakteurs.
|
||||||
|
$beitrag = $this->publishedPost('markup', 'Markup', '2026-02-01', ['Bau & <img src="https://example.org/x.png"> Technik']);
|
||||||
|
$href = $this->posts->termsFor($beitrag)['category'][0]['href'];
|
||||||
|
|
||||||
|
$html = $this->request($href)->getContent();
|
||||||
|
self::assertStringNotContainsString('<img src="https://example.org/x.png">', $html);
|
||||||
|
self::assertStringContainsString('Bau & <img src="https://example.org/x.png"> Technik</h1>', $html);
|
||||||
|
}
|
||||||
|
|
||||||
public function testCategoriesAndTagsGroupPostsAndGetTheirOwnArchives(): void
|
public function testCategoriesAndTagsGroupPostsAndGetTheirOwnArchives(): void
|
||||||
{
|
{
|
||||||
$projekt = $this->publishedPost('kanttresor', 'KantTresor', '2026-02-01', ['Projekte'], ['WordPress', 'DSGVO']);
|
$projekt = $this->publishedPost('kanttresor', 'KantTresor', '2026-02-01', ['Projekte'], ['WordPress', 'DSGVO']);
|
||||||
|
|||||||
@@ -382,9 +382,23 @@ final class EditorSecurityTest extends WebTestCase
|
|||||||
$client->request('POST', '/admin/pages/'.$entwurf.'/move', ['_csrf_token' => $token, 'expectedVersion' => $version($entwurf), 'slug' => 'neuer-name']);
|
$client->request('POST', '/admin/pages/'.$entwurf.'/move', ['_csrf_token' => $token, 'expectedVersion' => $version($entwurf), 'slug' => 'neuer-name']);
|
||||||
self::assertSame('neuer-name', $this->db->fetchOne('SELECT path FROM page WHERE id = ?', [$entwurf]));
|
self::assertSame('neuer-name', $this->db->fetchOne('SELECT path FROM page WHERE id = ?', [$entwurf]));
|
||||||
|
|
||||||
|
// Liegt die veröffentlichte Seite im Papierkorb, holt er sie nicht zurück: sie wäre sofort
|
||||||
|
// wieder online. Seinen Entwurf dagegen schon.
|
||||||
|
$pages->trashPage($live, $version($live));
|
||||||
|
$pages->trashPage($entwurf, $version($entwurf));
|
||||||
|
foreach ([$live, $entwurf] as $id) {
|
||||||
|
$client->request('POST', '/admin/pages/'.$id.'/restore', ['_csrf_token' => $token]);
|
||||||
|
self::assertResponseRedirects();
|
||||||
|
}
|
||||||
|
self::assertNotNull($this->db->fetchOne('SELECT deleted_at FROM page WHERE id = ?', [$live]), 'Ein Redakteur stellt keine veröffentlichte Seite wieder online.');
|
||||||
|
self::assertNull($this->db->fetchOne('SELECT deleted_at FROM page WHERE id = ?', [$entwurf]));
|
||||||
|
|
||||||
// Wer veröffentlichen darf, darf auch das.
|
// Wer veröffentlichen darf, darf auch das.
|
||||||
$client = $this->login('publisher', $client);
|
$client = $this->login('publisher', $client);
|
||||||
$token = $client->request('GET', '/admin')->filter('input[name="_csrf_token"]')->last()->attr('value');
|
$token = $client->request('GET', '/admin')->filter('input[name="_csrf_token"]')->last()->attr('value');
|
||||||
|
$client->request('POST', '/admin/pages/'.$live.'/restore', ['_csrf_token' => $token]);
|
||||||
|
self::assertNull($this->db->fetchOne('SELECT deleted_at FROM page WHERE id = ?', [$live]));
|
||||||
|
self::assertStringContainsString('wieder öffentlich', $client->followRedirect()->text());
|
||||||
$client->request('POST', '/admin/pages/'.$live.'/move', ['_csrf_token' => $token, 'expectedVersion' => $version($live), 'slug' => 'umbenannt']);
|
$client->request('POST', '/admin/pages/'.$live.'/move', ['_csrf_token' => $token, 'expectedVersion' => $version($live), 'slug' => 'umbenannt']);
|
||||||
self::assertSame('umbenannt', $this->db->fetchOne('SELECT path FROM page WHERE id = ?', [$live]));
|
self::assertSame('umbenannt', $this->db->fetchOne('SELECT path FROM page WHERE id = ?', [$live]));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user