diff --git a/composer.lock b/composer.lock
index 3a0904f82a9e21b78f7de86ff90df6e9e7a816ca..9b995db663cf4ade817660a46e01755fbdbb02c8 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1342,16 +1342,16 @@
         },
         {
             "name": "doctrine/annotations",
-            "version": "1.13.2",
+            "version": "1.13.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/annotations.git",
-                "reference": "5b668aef16090008790395c02c893b1ba13f7e08"
+                "reference": "648b0343343565c4a056bfc8392201385e8d89f0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08",
-                "reference": "5b668aef16090008790395c02c893b1ba13f7e08",
+                "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0",
+                "reference": "648b0343343565c4a056bfc8392201385e8d89f0",
                 "shasum": ""
             },
             "require": {
@@ -1363,9 +1363,10 @@
             "require-dev": {
                 "doctrine/cache": "^1.11 || ^2.0",
                 "doctrine/coding-standard": "^6.0 || ^8.1",
-                "phpstan/phpstan": "^0.12.20",
+                "phpstan/phpstan": "^1.4.10 || ^1.8.0",
                 "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
-                "symfony/cache": "^4.4 || ^5.2"
+                "symfony/cache": "^4.4 || ^5.2",
+                "vimeo/psalm": "^4.10"
             },
             "type": "library",
             "autoload": {
@@ -1408,9 +1409,9 @@
             ],
             "support": {
                 "issues": "https://github.com/doctrine/annotations/issues",
-                "source": "https://github.com/doctrine/annotations/tree/1.13.2"
+                "source": "https://github.com/doctrine/annotations/tree/1.13.3"
             },
-            "time": "2021-08-05T19:00:23+00:00"
+            "time": "2022-07-02T10:48:51+00:00"
         },
         {
             "name": "doctrine/collections",
@@ -2958,16 +2959,16 @@
         },
         {
             "name": "drupal/core",
-            "version": "9.4.1",
+            "version": "9.4.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/drupal/core.git",
-                "reference": "81489e8f0d5fdcd5d502b561f0f8cdf5ccdda614"
+                "reference": "7b1a403c093c7abc89ef3df1a6b05bdb19b3ffad"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/drupal/core/zipball/81489e8f0d5fdcd5d502b561f0f8cdf5ccdda614",
-                "reference": "81489e8f0d5fdcd5d502b561f0f8cdf5ccdda614",
+                "url": "https://api.github.com/repos/drupal/core/zipball/7b1a403c093c7abc89ef3df1a6b05bdb19b3ffad",
+                "reference": "7b1a403c093c7abc89ef3df1a6b05bdb19b3ffad",
                 "shasum": ""
             },
             "require": {
@@ -3210,9 +3211,9 @@
             ],
             "description": "Drupal is an open source content management platform powering millions of websites and applications.",
             "support": {
-                "source": "https://github.com/drupal/core/tree/9.4.1"
+                "source": "https://github.com/drupal/core/tree/9.4.3"
             },
-            "time": "2022-06-21T20:53:48+00:00"
+            "time": "2022-07-20T15:11:38+00:00"
         },
         {
             "name": "drupal/core-composer-scaffold",
@@ -3266,16 +3267,16 @@
         },
         {
             "name": "drupal/core-recommended",
-            "version": "9.4.1",
+            "version": "9.4.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/drupal/core-recommended.git",
-                "reference": "a3ae54715ba7792fe596c2f6a73dfcef217b0577"
+                "reference": "ff8662af0a5963a88ea856e9786e17a51f8e640c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/drupal/core-recommended/zipball/a3ae54715ba7792fe596c2f6a73dfcef217b0577",
-                "reference": "a3ae54715ba7792fe596c2f6a73dfcef217b0577",
+                "url": "https://api.github.com/repos/drupal/core-recommended/zipball/ff8662af0a5963a88ea856e9786e17a51f8e640c",
+                "reference": "ff8662af0a5963a88ea856e9786e17a51f8e640c",
                 "shasum": ""
             },
             "require": {
@@ -3284,7 +3285,7 @@
                 "doctrine/annotations": "~1.13.2",
                 "doctrine/lexer": "~1.2.3",
                 "doctrine/reflection": "~1.2.3",
-                "drupal/core": "9.4.1",
+                "drupal/core": "9.4.3",
                 "egulias/email-validator": "~3.2",
                 "guzzlehttp/guzzle": "~6.5.8",
                 "guzzlehttp/promises": "~1.5.1",
@@ -3346,9 +3347,9 @@
             ],
             "description": "Core and its dependencies with known-compatible minor versions. Require this project INSTEAD OF drupal/core.",
             "support": {
-                "source": "https://github.com/drupal/core-recommended/tree/9.4.1"
+                "source": "https://github.com/drupal/core-recommended/tree/9.4.3"
             },
-            "time": "2022-06-21T20:53:48+00:00"
+            "time": "2022-07-20T15:11:38+00:00"
         },
         {
             "name": "drupal/crop",
@@ -9154,16 +9155,16 @@
         },
         {
             "name": "laminas/laminas-diactoros",
-            "version": "2.11.0",
+            "version": "2.11.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laminas/laminas-diactoros.git",
-                "reference": "d1bc565b23c2040fafde398a8a5db083c47928c0"
+                "reference": "1f97b0c52eafd108e09c76d6b29d83ef4a855f76"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/d1bc565b23c2040fafde398a8a5db083c47928c0",
-                "reference": "d1bc565b23c2040fafde398a8a5db083c47928c0",
+                "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/1f97b0c52eafd108e09c76d6b29d83ef4a855f76",
+                "reference": "1f97b0c52eafd108e09c76d6b29d83ef4a855f76",
                 "shasum": ""
             },
             "require": {
@@ -9249,7 +9250,7 @@
                     "type": "community_bridge"
                 }
             ],
-            "time": "2022-05-17T10:57:52+00:00"
+            "time": "2022-07-06T09:24:53+00:00"
         },
         {
             "name": "laminas/laminas-escaper",
@@ -12912,7 +12913,7 @@
         },
         {
             "name": "symfony/deprecation-contracts",
-            "version": "v2.5.1",
+            "version": "v2.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/deprecation-contracts.git",
@@ -12959,7 +12960,7 @@
             "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.1"
+                "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2"
             },
             "funding": [
                 {
@@ -13205,7 +13206,7 @@
         },
         {
             "name": "symfony/event-dispatcher-contracts",
-            "version": "v1.1.12",
+            "version": "v1.1.13",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher-contracts.git",
@@ -13264,7 +13265,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.12"
+                "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.13"
             },
             "funding": [
                 {
@@ -13408,16 +13409,16 @@
         },
         {
             "name": "symfony/http-client-contracts",
-            "version": "v2.5.1",
+            "version": "v2.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-client-contracts.git",
-                "reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5"
+                "reference": "ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1a4f708e4e87f335d1b1be6148060739152f0bd5",
-                "reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5",
+                "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70",
+                "reference": "ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70",
                 "shasum": ""
             },
             "require": {
@@ -13466,7 +13467,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.1"
+                "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.2"
             },
             "funding": [
                 {
@@ -13482,7 +13483,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-03-13T20:07:29+00:00"
+            "time": "2022-04-12T15:48:08+00:00"
         },
         {
             "name": "symfony/http-foundation",
@@ -14810,16 +14811,16 @@
         },
         {
             "name": "symfony/service-contracts",
-            "version": "v2.5.1",
+            "version": "v2.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/service-contracts.git",
-                "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
+                "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
-                "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
+                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
+                "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
                 "shasum": ""
             },
             "require": {
@@ -14873,7 +14874,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/service-contracts/tree/v2.5.1"
+                "source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
             },
             "funding": [
                 {
@@ -14889,7 +14890,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-03-13T20:07:29+00:00"
+            "time": "2022-05-30T19:17:29+00:00"
         },
         {
             "name": "symfony/translation",
@@ -14982,16 +14983,16 @@
         },
         {
             "name": "symfony/translation-contracts",
-            "version": "v2.5.1",
+            "version": "v2.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/translation-contracts.git",
-                "reference": "1211df0afa701e45a04253110e959d4af4ef0f07"
+                "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/1211df0afa701e45a04253110e959d4af4ef0f07",
-                "reference": "1211df0afa701e45a04253110e959d4af4ef0f07",
+                "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe",
+                "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe",
                 "shasum": ""
             },
             "require": {
@@ -15040,7 +15041,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/translation-contracts/tree/v2.5.1"
+                "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2"
             },
             "funding": [
                 {
@@ -15056,7 +15057,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-01-02T09:53:40+00:00"
+            "time": "2022-06-27T16:58:25+00:00"
         },
         {
             "name": "symfony/validator",
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 55becfd2d22430d610c884c377d66c2ce00bc823..e1198c7a003bd58ba652ac7a04ddb564e11c5669 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -3274,6 +3274,8 @@
     'Laminas\\Diactoros\\Exception\\DeserializationException' => $vendorDir . '/laminas/laminas-diactoros/src/Exception/DeserializationException.php',
     'Laminas\\Diactoros\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-diactoros/src/Exception/ExceptionInterface.php',
     'Laminas\\Diactoros\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-diactoros/src/Exception/InvalidArgumentException.php',
+    'Laminas\\Diactoros\\Exception\\InvalidForwardedHeaderNameException' => $vendorDir . '/laminas/laminas-diactoros/src/Exception/InvalidForwardedHeaderNameException.php',
+    'Laminas\\Diactoros\\Exception\\InvalidProxyAddressException' => $vendorDir . '/laminas/laminas-diactoros/src/Exception/InvalidProxyAddressException.php',
     'Laminas\\Diactoros\\Exception\\InvalidStreamPointerPositionException' => $vendorDir . '/laminas/laminas-diactoros/src/Exception/InvalidStreamPointerPositionException.php',
     'Laminas\\Diactoros\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-diactoros/src/Exception/RuntimeException.php',
     'Laminas\\Diactoros\\Exception\\SerializationException' => $vendorDir . '/laminas/laminas-diactoros/src/Exception/SerializationException.php',
@@ -3308,6 +3310,10 @@
     'Laminas\\Diactoros\\Response\\XmlResponse' => $vendorDir . '/laminas/laminas-diactoros/src/Response/XmlResponse.php',
     'Laminas\\Diactoros\\ServerRequest' => $vendorDir . '/laminas/laminas-diactoros/src/ServerRequest.php',
     'Laminas\\Diactoros\\ServerRequestFactory' => $vendorDir . '/laminas/laminas-diactoros/src/ServerRequestFactory.php',
+    'Laminas\\Diactoros\\ServerRequestFilter\\DoNotFilter' => $vendorDir . '/laminas/laminas-diactoros/src/ServerRequestFilter/DoNotFilter.php',
+    'Laminas\\Diactoros\\ServerRequestFilter\\FilterServerRequestInterface' => $vendorDir . '/laminas/laminas-diactoros/src/ServerRequestFilter/FilterServerRequestInterface.php',
+    'Laminas\\Diactoros\\ServerRequestFilter\\FilterUsingXForwardedHeaders' => $vendorDir . '/laminas/laminas-diactoros/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php',
+    'Laminas\\Diactoros\\ServerRequestFilter\\IPRange' => $vendorDir . '/laminas/laminas-diactoros/src/ServerRequestFilter/IPRange.php',
     'Laminas\\Diactoros\\Stream' => $vendorDir . '/laminas/laminas-diactoros/src/Stream.php',
     'Laminas\\Diactoros\\StreamFactory' => $vendorDir . '/laminas/laminas-diactoros/src/StreamFactory.php',
     'Laminas\\Diactoros\\UploadedFile' => $vendorDir . '/laminas/laminas-diactoros/src/UploadedFile.php',
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index bfb31e3b85899a2500a0782e582668cb9cf08638..42fd77cc434f7cfeea9e196f92de959f4ca1029f 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -4060,6 +4060,8 @@ class ComposerStaticInit5c689ffcd54b9e495ed983fdce09b530
         'Laminas\\Diactoros\\Exception\\DeserializationException' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Exception/DeserializationException.php',
         'Laminas\\Diactoros\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Exception/ExceptionInterface.php',
         'Laminas\\Diactoros\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Exception/InvalidArgumentException.php',
+        'Laminas\\Diactoros\\Exception\\InvalidForwardedHeaderNameException' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Exception/InvalidForwardedHeaderNameException.php',
+        'Laminas\\Diactoros\\Exception\\InvalidProxyAddressException' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Exception/InvalidProxyAddressException.php',
         'Laminas\\Diactoros\\Exception\\InvalidStreamPointerPositionException' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Exception/InvalidStreamPointerPositionException.php',
         'Laminas\\Diactoros\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Exception/RuntimeException.php',
         'Laminas\\Diactoros\\Exception\\SerializationException' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Exception/SerializationException.php',
@@ -4094,6 +4096,10 @@ class ComposerStaticInit5c689ffcd54b9e495ed983fdce09b530
         'Laminas\\Diactoros\\Response\\XmlResponse' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Response/XmlResponse.php',
         'Laminas\\Diactoros\\ServerRequest' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/ServerRequest.php',
         'Laminas\\Diactoros\\ServerRequestFactory' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/ServerRequestFactory.php',
+        'Laminas\\Diactoros\\ServerRequestFilter\\DoNotFilter' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/ServerRequestFilter/DoNotFilter.php',
+        'Laminas\\Diactoros\\ServerRequestFilter\\FilterServerRequestInterface' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/ServerRequestFilter/FilterServerRequestInterface.php',
+        'Laminas\\Diactoros\\ServerRequestFilter\\FilterUsingXForwardedHeaders' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php',
+        'Laminas\\Diactoros\\ServerRequestFilter\\IPRange' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/ServerRequestFilter/IPRange.php',
         'Laminas\\Diactoros\\Stream' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/Stream.php',
         'Laminas\\Diactoros\\StreamFactory' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/StreamFactory.php',
         'Laminas\\Diactoros\\UploadedFile' => __DIR__ . '/..' . '/laminas/laminas-diactoros/src/UploadedFile.php',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 8ac11e86cd33024f71d8868e96c504e0d132638b..878dac5a4671d253b87e7ea3a44c00413f7d2bea 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -1365,17 +1365,17 @@
         },
         {
             "name": "doctrine/annotations",
-            "version": "1.13.2",
-            "version_normalized": "1.13.2.0",
+            "version": "1.13.3",
+            "version_normalized": "1.13.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/annotations.git",
-                "reference": "5b668aef16090008790395c02c893b1ba13f7e08"
+                "reference": "648b0343343565c4a056bfc8392201385e8d89f0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08",
-                "reference": "5b668aef16090008790395c02c893b1ba13f7e08",
+                "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0",
+                "reference": "648b0343343565c4a056bfc8392201385e8d89f0",
                 "shasum": ""
             },
             "require": {
@@ -1387,11 +1387,12 @@
             "require-dev": {
                 "doctrine/cache": "^1.11 || ^2.0",
                 "doctrine/coding-standard": "^6.0 || ^8.1",
-                "phpstan/phpstan": "^0.12.20",
+                "phpstan/phpstan": "^1.4.10 || ^1.8.0",
                 "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
-                "symfony/cache": "^4.4 || ^5.2"
+                "symfony/cache": "^4.4 || ^5.2",
+                "vimeo/psalm": "^4.10"
             },
-            "time": "2021-08-05T19:00:23+00:00",
+            "time": "2022-07-02T10:48:51+00:00",
             "type": "library",
             "installation-source": "dist",
             "autoload": {
@@ -1434,7 +1435,7 @@
             ],
             "support": {
                 "issues": "https://github.com/doctrine/annotations/issues",
-                "source": "https://github.com/doctrine/annotations/tree/1.13.2"
+                "source": "https://github.com/doctrine/annotations/tree/1.13.3"
             },
             "install-path": "../doctrine/annotations"
         },
@@ -3044,17 +3045,17 @@
         },
         {
             "name": "drupal/core",
-            "version": "9.4.1",
-            "version_normalized": "9.4.1.0",
+            "version": "9.4.3",
+            "version_normalized": "9.4.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/drupal/core.git",
-                "reference": "81489e8f0d5fdcd5d502b561f0f8cdf5ccdda614"
+                "reference": "7b1a403c093c7abc89ef3df1a6b05bdb19b3ffad"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/drupal/core/zipball/81489e8f0d5fdcd5d502b561f0f8cdf5ccdda614",
-                "reference": "81489e8f0d5fdcd5d502b561f0f8cdf5ccdda614",
+                "url": "https://api.github.com/repos/drupal/core/zipball/7b1a403c093c7abc89ef3df1a6b05bdb19b3ffad",
+                "reference": "7b1a403c093c7abc89ef3df1a6b05bdb19b3ffad",
                 "shasum": ""
             },
             "require": {
@@ -3225,7 +3226,7 @@
                 "drupal/workflows": "self.version",
                 "drupal/workspaces": "self.version"
             },
-            "time": "2022-06-21T20:53:48+00:00",
+            "time": "2022-07-20T15:11:38+00:00",
             "type": "drupal-core",
             "extra": {
                 "drupal-scaffold": {
@@ -3303,7 +3304,7 @@
             ],
             "description": "Drupal is an open source content management platform powering millions of websites and applications.",
             "support": {
-                "source": "https://github.com/drupal/core/tree/9.4.1"
+                "source": "https://github.com/drupal/core/tree/9.4.3"
             },
             "install-path": "../../web/core"
         },
@@ -3359,17 +3360,17 @@
         },
         {
             "name": "drupal/core-recommended",
-            "version": "9.4.1",
-            "version_normalized": "9.4.1.0",
+            "version": "9.4.3",
+            "version_normalized": "9.4.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/drupal/core-recommended.git",
-                "reference": "a3ae54715ba7792fe596c2f6a73dfcef217b0577"
+                "reference": "ff8662af0a5963a88ea856e9786e17a51f8e640c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/drupal/core-recommended/zipball/a3ae54715ba7792fe596c2f6a73dfcef217b0577",
-                "reference": "a3ae54715ba7792fe596c2f6a73dfcef217b0577",
+                "url": "https://api.github.com/repos/drupal/core-recommended/zipball/ff8662af0a5963a88ea856e9786e17a51f8e640c",
+                "reference": "ff8662af0a5963a88ea856e9786e17a51f8e640c",
                 "shasum": ""
             },
             "require": {
@@ -3378,7 +3379,7 @@
                 "doctrine/annotations": "~1.13.2",
                 "doctrine/lexer": "~1.2.3",
                 "doctrine/reflection": "~1.2.3",
-                "drupal/core": "9.4.1",
+                "drupal/core": "9.4.3",
                 "egulias/email-validator": "~3.2",
                 "guzzlehttp/guzzle": "~6.5.8",
                 "guzzlehttp/promises": "~1.5.1",
@@ -3433,7 +3434,7 @@
             "conflict": {
                 "webflo/drupal-core-strict": "*"
             },
-            "time": "2022-06-21T20:53:48+00:00",
+            "time": "2022-07-20T15:11:38+00:00",
             "type": "metapackage",
             "notification-url": "https://packagist.org/downloads/",
             "license": [
@@ -3441,7 +3442,7 @@
             ],
             "description": "Core and its dependencies with known-compatible minor versions. Require this project INSTEAD OF drupal/core.",
             "support": {
-                "source": "https://github.com/drupal/core-recommended/tree/9.4.1"
+                "source": "https://github.com/drupal/core-recommended/tree/9.4.3"
             },
             "install-path": null
         },
@@ -9494,17 +9495,17 @@
         },
         {
             "name": "laminas/laminas-diactoros",
-            "version": "2.11.0",
-            "version_normalized": "2.11.0.0",
+            "version": "2.11.3",
+            "version_normalized": "2.11.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laminas/laminas-diactoros.git",
-                "reference": "d1bc565b23c2040fafde398a8a5db083c47928c0"
+                "reference": "1f97b0c52eafd108e09c76d6b29d83ef4a855f76"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/d1bc565b23c2040fafde398a8a5db083c47928c0",
-                "reference": "d1bc565b23c2040fafde398a8a5db083c47928c0",
+                "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/1f97b0c52eafd108e09c76d6b29d83ef4a855f76",
+                "reference": "1f97b0c52eafd108e09c76d6b29d83ef4a855f76",
                 "shasum": ""
             },
             "require": {
@@ -9533,7 +9534,7 @@
                 "psalm/plugin-phpunit": "^0.14.0",
                 "vimeo/psalm": "^4.3"
             },
-            "time": "2022-05-17T10:57:52+00:00",
+            "time": "2022-07-06T09:24:53+00:00",
             "type": "library",
             "extra": {
                 "laminas": {
@@ -13282,8 +13283,8 @@
         },
         {
             "name": "symfony/deprecation-contracts",
-            "version": "v2.5.1",
-            "version_normalized": "2.5.1.0",
+            "version": "v2.5.2",
+            "version_normalized": "2.5.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/deprecation-contracts.git",
@@ -13332,7 +13333,7 @@
             "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.1"
+                "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2"
             },
             "funding": [
                 {
@@ -13587,8 +13588,8 @@
         },
         {
             "name": "symfony/event-dispatcher-contracts",
-            "version": "v1.1.12",
-            "version_normalized": "1.1.12.0",
+            "version": "v1.1.13",
+            "version_normalized": "1.1.13.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher-contracts.git",
@@ -13649,7 +13650,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.12"
+                "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.13"
             },
             "funding": [
                 {
@@ -13799,17 +13800,17 @@
         },
         {
             "name": "symfony/http-client-contracts",
-            "version": "v2.5.1",
-            "version_normalized": "2.5.1.0",
+            "version": "v2.5.2",
+            "version_normalized": "2.5.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-client-contracts.git",
-                "reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5"
+                "reference": "ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1a4f708e4e87f335d1b1be6148060739152f0bd5",
-                "reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5",
+                "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70",
+                "reference": "ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70",
                 "shasum": ""
             },
             "require": {
@@ -13818,7 +13819,7 @@
             "suggest": {
                 "symfony/http-client-implementation": ""
             },
-            "time": "2022-03-13T20:07:29+00:00",
+            "time": "2022-04-12T15:48:08+00:00",
             "type": "library",
             "extra": {
                 "branch-alias": {
@@ -13860,7 +13861,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.1"
+                "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.2"
             },
             "funding": [
                 {
@@ -15252,17 +15253,17 @@
         },
         {
             "name": "symfony/service-contracts",
-            "version": "v2.5.1",
-            "version_normalized": "2.5.1.0",
+            "version": "v2.5.2",
+            "version_normalized": "2.5.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/service-contracts.git",
-                "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
+                "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
-                "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
+                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
+                "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
                 "shasum": ""
             },
             "require": {
@@ -15276,7 +15277,7 @@
             "suggest": {
                 "symfony/service-implementation": ""
             },
-            "time": "2022-03-13T20:07:29+00:00",
+            "time": "2022-05-30T19:17:29+00:00",
             "type": "library",
             "extra": {
                 "branch-alias": {
@@ -15318,7 +15319,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/service-contracts/tree/v2.5.1"
+                "source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
             },
             "funding": [
                 {
@@ -15430,17 +15431,17 @@
         },
         {
             "name": "symfony/translation-contracts",
-            "version": "v2.5.1",
-            "version_normalized": "2.5.1.0",
+            "version": "v2.5.2",
+            "version_normalized": "2.5.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/translation-contracts.git",
-                "reference": "1211df0afa701e45a04253110e959d4af4ef0f07"
+                "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/1211df0afa701e45a04253110e959d4af4ef0f07",
-                "reference": "1211df0afa701e45a04253110e959d4af4ef0f07",
+                "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe",
+                "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe",
                 "shasum": ""
             },
             "require": {
@@ -15449,7 +15450,7 @@
             "suggest": {
                 "symfony/translation-implementation": ""
             },
-            "time": "2022-01-02T09:53:40+00:00",
+            "time": "2022-06-27T16:58:25+00:00",
             "type": "library",
             "extra": {
                 "branch-alias": {
@@ -15491,7 +15492,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/translation-contracts/tree/v2.5.1"
+                "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2"
             },
             "funding": [
                 {
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 1ba378e309d133258d118539d247993070a441ad..36415218a894e2d370db251c755e6aa053bb5ac4 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -3,7 +3,7 @@
         'name' => 'osu-asc-webservices/d8-upstream',
         'pretty_version' => 'dev-master',
         'version' => 'dev-master',
-        'reference' => '07a7c2435c9d4e8234762b2e1e5bea728ccd9e76',
+        'reference' => 'f3adbe0a3bfef44fba6e4ed128a583c42dc7445f',
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -233,9 +233,9 @@
             'dev_requirement' => false,
         ),
         'doctrine/annotations' => array(
-            'pretty_version' => '1.13.2',
-            'version' => '1.13.2.0',
-            'reference' => '5b668aef16090008790395c02c893b1ba13f7e08',
+            'pretty_version' => '1.13.3',
+            'version' => '1.13.3.0',
+            'reference' => '648b0343343565c4a056bfc8392201385e8d89f0',
             'type' => 'library',
             'install_path' => __DIR__ . '/../doctrine/annotations',
             'aliases' => array(),
@@ -271,7 +271,7 @@
         'drupal/action' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/addtocalendar' => array(
@@ -304,7 +304,7 @@
         'drupal/aggregator' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/allowed_formats' => array(
@@ -328,25 +328,25 @@
         'drupal/automated_cron' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/ban' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/bartik' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/basic_auth' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/better_exposed_filters' => array(
@@ -361,19 +361,19 @@
         'drupal/big_pipe' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/block' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/block_content' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/block_field' => array(
@@ -406,7 +406,7 @@
         'drupal/book' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/bootstrap' => array(
@@ -421,7 +421,7 @@
         'drupal/breakpoint' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/cache_control_override' => array(
@@ -445,13 +445,13 @@
         'drupal/ckeditor' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/ckeditor5' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/ckeditor_indentblock' => array(
@@ -466,31 +466,31 @@
         'drupal/claro' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/classy' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/color' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/comment' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/config' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/config_direct_save' => array(
@@ -523,7 +523,7 @@
         'drupal/config_translation' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/config_update' => array(
@@ -574,7 +574,7 @@
         'drupal/contact' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/content_access' => array(
@@ -589,25 +589,25 @@
         'drupal/content_moderation' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/content_translation' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/contextual' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core' => array(
-            'pretty_version' => '9.4.1',
-            'version' => '9.4.1.0',
-            'reference' => '81489e8f0d5fdcd5d502b561f0f8cdf5ccdda614',
+            'pretty_version' => '9.4.3',
+            'version' => '9.4.3.0',
+            'reference' => '7b1a403c093c7abc89ef3df1a6b05bdb19b3ffad',
             'type' => 'drupal-core',
             'install_path' => __DIR__ . '/../../web/core',
             'aliases' => array(),
@@ -616,25 +616,25 @@
         'drupal/core-annotation' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-assertion' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-bridge' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-class-finder' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-composer-scaffold' => array(
@@ -649,97 +649,97 @@
         'drupal/core-datetime' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-dependency-injection' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-diff' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-discovery' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-event-dispatcher' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-file-cache' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-file-security' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-filesystem' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-front-matter' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-gettext' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-graph' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-http-foundation' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-php-storage' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-plugin' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-proxy-builder' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-recommended' => array(
-            'pretty_version' => '9.4.1',
-            'version' => '9.4.1.0',
-            'reference' => 'a3ae54715ba7792fe596c2f6a73dfcef217b0577',
+            'pretty_version' => '9.4.3',
+            'version' => '9.4.3.0',
+            'reference' => 'ff8662af0a5963a88ea856e9786e17a51f8e640c',
             'type' => 'metapackage',
             'install_path' => NULL,
             'aliases' => array(),
@@ -748,37 +748,37 @@
         'drupal/core-render' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-serialization' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-transliteration' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-utility' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-uuid' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/core-version' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/crop' => array(
@@ -802,19 +802,19 @@
         'drupal/datetime' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/datetime_range' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/dblog' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/dropzonejs' => array(
@@ -838,13 +838,13 @@
         'drupal/dynamic_page_cache' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/editor' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/editor_advanced_link' => array(
@@ -913,7 +913,7 @@
         'drupal/entity_reference' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/entity_reference_revisions' => array(
@@ -946,7 +946,7 @@
         'drupal/field' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/field_group' => array(
@@ -961,7 +961,7 @@
         'drupal/field_layout' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/field_permissions' => array(
@@ -976,13 +976,13 @@
         'drupal/field_ui' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/file' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/file_browser' => array(
@@ -997,7 +997,7 @@
         'drupal/filter' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/focal_point' => array(
@@ -1012,7 +1012,7 @@
         'drupal/forum' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/google_analytics' => array(
@@ -1036,25 +1036,25 @@
         'drupal/hal' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/help' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/help_topics' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/history' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/honeypot' => array(
@@ -1069,7 +1069,7 @@
         'drupal/image' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/inline_entity_form' => array(
@@ -1084,7 +1084,7 @@
         'drupal/inline_form_errors' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/jquery_ui' => array(
@@ -1126,25 +1126,25 @@
         'drupal/jsonapi' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/language' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/layout_builder' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/layout_discovery' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/libraries' => array(
@@ -1159,7 +1159,7 @@
         'drupal/link' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/link_attributes' => array(
@@ -1183,7 +1183,7 @@
         'drupal/locale' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/mathjax' => array(
@@ -1198,7 +1198,7 @@
         'drupal/media' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/media_entity_browser' => array(
@@ -1231,7 +1231,7 @@
         'drupal/media_library' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/menu_block' => array(
@@ -1255,13 +1255,13 @@
         'drupal/menu_link_content' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/menu_ui' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/metatag' => array(
@@ -1276,7 +1276,7 @@
         'drupal/migrate' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/migrate_devel' => array(
@@ -1291,19 +1291,19 @@
         'drupal/migrate_drupal' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/migrate_drupal_multilingual' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/migrate_drupal_ui' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/migrate_plus' => array(
@@ -1327,7 +1327,7 @@
         'drupal/minimal' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/mobile_detect' => array(
@@ -1369,31 +1369,31 @@
         'drupal/mysql' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/node' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/olivero' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/options' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/page_cache' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/pantheon_advanced_page_cache' => array(
@@ -1417,13 +1417,13 @@
         'drupal/path' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/path_alias' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/pathauto' => array(
@@ -1438,7 +1438,7 @@
         'drupal/pgsql' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/queue_mail' => array(
@@ -1453,13 +1453,13 @@
         'drupal/quickedit' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/rdf' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/rebuild_cache_access' => array(
@@ -1501,13 +1501,13 @@
         'drupal/responsive_image' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/rest' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/roleassign' => array(
@@ -1531,7 +1531,7 @@
         'drupal/search' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/search_api' => array(
@@ -1555,25 +1555,25 @@
         'drupal/serialization' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/settings_tray' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/seven' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/shortcut' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/simple_gmap' => array(
@@ -1642,25 +1642,25 @@
         'drupal/sqlite' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/standard' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/stark' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/statistics' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/superfish' => array(
@@ -1684,31 +1684,31 @@
         'drupal/syslog' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/system' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/taxonomy' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/telephone' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/text' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/token' => array(
@@ -1723,19 +1723,19 @@
         'drupal/toolbar' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/tour' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/tracker' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/twig_tweak' => array(
@@ -1768,13 +1768,13 @@
         'drupal/update' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/user' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/userprotect' => array(
@@ -1807,7 +1807,7 @@
         'drupal/views' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/views_ajax_history' => array(
@@ -1867,7 +1867,7 @@
         'drupal/views_ui' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/webform' => array(
@@ -1882,13 +1882,13 @@
         'drupal/workflows' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drupal/workspaces' => array(
             'dev_requirement' => false,
             'replaced' => array(
-                0 => '9.4.1',
+                0 => '9.4.3',
             ),
         ),
         'drush-ops/behat-drush-endpoint' => array(
@@ -2027,9 +2027,9 @@
             'dev_requirement' => false,
         ),
         'laminas/laminas-diactoros' => array(
-            'pretty_version' => '2.11.0',
-            'version' => '2.11.0.0',
-            'reference' => 'd1bc565b23c2040fafde398a8a5db083c47928c0',
+            'pretty_version' => '2.11.3',
+            'version' => '2.11.3.0',
+            'reference' => '1f97b0c52eafd108e09c76d6b29d83ef4a855f76',
             'type' => 'library',
             'install_path' => __DIR__ . '/../laminas/laminas-diactoros',
             'aliases' => array(),
@@ -2125,7 +2125,7 @@
         'osu-asc-webservices/d8-upstream' => array(
             'pretty_version' => 'dev-master',
             'version' => 'dev-master',
-            'reference' => '07a7c2435c9d4e8234762b2e1e5bea728ccd9e76',
+            'reference' => 'f3adbe0a3bfef44fba6e4ed128a583c42dc7445f',
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
@@ -2676,8 +2676,8 @@
             'dev_requirement' => false,
         ),
         'symfony/deprecation-contracts' => array(
-            'pretty_version' => 'v2.5.1',
-            'version' => '2.5.1.0',
+            'pretty_version' => 'v2.5.2',
+            'version' => '2.5.2.0',
             'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
             'type' => 'library',
             'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
@@ -2712,8 +2712,8 @@
             'dev_requirement' => false,
         ),
         'symfony/event-dispatcher-contracts' => array(
-            'pretty_version' => 'v1.1.12',
-            'version' => '1.1.12.0',
+            'pretty_version' => 'v1.1.13',
+            'version' => '1.1.13.0',
             'reference' => '1d5cd762abaa6b2a4169d3e77610193a7157129e',
             'type' => 'library',
             'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts',
@@ -2745,9 +2745,9 @@
             'dev_requirement' => false,
         ),
         'symfony/http-client-contracts' => array(
-            'pretty_version' => 'v2.5.1',
-            'version' => '2.5.1.0',
-            'reference' => '1a4f708e4e87f335d1b1be6148060739152f0bd5',
+            'pretty_version' => 'v2.5.2',
+            'version' => '2.5.2.0',
+            'reference' => 'ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70',
             'type' => 'library',
             'install_path' => __DIR__ . '/../symfony/http-client-contracts',
             'aliases' => array(),
@@ -2898,9 +2898,9 @@
             'dev_requirement' => false,
         ),
         'symfony/service-contracts' => array(
-            'pretty_version' => 'v2.5.1',
-            'version' => '2.5.1.0',
-            'reference' => '24d9dc654b83e91aa59f9d167b131bc3b5bea24c',
+            'pretty_version' => 'v2.5.2',
+            'version' => '2.5.2.0',
+            'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c',
             'type' => 'library',
             'install_path' => __DIR__ . '/../symfony/service-contracts',
             'aliases' => array(),
@@ -2922,9 +2922,9 @@
             'dev_requirement' => false,
         ),
         'symfony/translation-contracts' => array(
-            'pretty_version' => 'v2.5.1',
-            'version' => '2.5.1.0',
-            'reference' => '1211df0afa701e45a04253110e959d4af4ef0f07',
+            'pretty_version' => 'v2.5.2',
+            'version' => '2.5.2.0',
+            'reference' => '136b19dd05cdf0709db6537d058bcab6dd6e2dbe',
             'type' => 'library',
             'install_path' => __DIR__ . '/../symfony/translation-contracts',
             'aliases' => array(),
diff --git a/vendor/doctrine/annotations/composer.json b/vendor/doctrine/annotations/composer.json
index 00d0231075a1116538b27cc437f27e6da28d5bd8..b4dfbd390def5de22f6bd2d7a80ede5c1d6e9c1b 100644
--- a/vendor/doctrine/annotations/composer.json
+++ b/vendor/doctrine/annotations/composer.json
@@ -1,17 +1,36 @@
 {
     "name": "doctrine/annotations",
-    "type": "library",
     "description": "Docblock Annotations Parser",
-    "keywords": ["annotations", "docblock", "parser"],
-    "homepage": "https://www.doctrine-project.org/projects/annotations.html",
     "license": "MIT",
+    "type": "library",
+    "keywords": [
+        "annotations",
+        "docblock",
+        "parser"
+    ],
     "authors": [
-        {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
-        {"name": "Roman Borschel", "email": "roman@code-factory.org"},
-        {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
-        {"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
-        {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
+        {
+            "name": "Guilherme Blanco",
+            "email": "guilhermeblanco@gmail.com"
+        },
+        {
+            "name": "Roman Borschel",
+            "email": "roman@code-factory.org"
+        },
+        {
+            "name": "Benjamin Eberlei",
+            "email": "kontakt@beberlei.de"
+        },
+        {
+            "name": "Jonathan Wage",
+            "email": "jonwage@gmail.com"
+        },
+        {
+            "name": "Johannes Schmitt",
+            "email": "schmittjoh@gmail.com"
+        }
     ],
+    "homepage": "https://www.doctrine-project.org/projects/annotations.html",
     "require": {
         "php": "^7.1 || ^8.0",
         "ext-tokenizer": "*",
@@ -21,15 +40,15 @@
     "require-dev": {
         "doctrine/cache": "^1.11 || ^2.0",
         "doctrine/coding-standard": "^6.0 || ^8.1",
-        "phpstan/phpstan": "^0.12.20",
+        "phpstan/phpstan": "^1.4.10 || ^1.8.0",
         "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
-        "symfony/cache": "^4.4 || ^5.2"
-    },
-    "config": {
-        "sort-packages": true
+        "symfony/cache": "^4.4 || ^5.2",
+        "vimeo/psalm": "^4.10"
     },
     "autoload": {
-        "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" }
+        "psr-4": {
+            "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
+        }
     },
     "autoload-dev": {
         "psr-4": {
@@ -40,5 +59,11 @@
             "tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php",
             "tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php"
         ]
+    },
+    "config": {
+        "allow-plugins": {
+            "dealerdirect/phpcodesniffer-composer-installer": true
+        },
+        "sort-packages": true
     }
 }
diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php
index b1ea64e6f5f959c1484c318f7c55ef1ccb06ac53..4d91825e560481aa33781cc841e41b705fb5fcb4 100644
--- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php
+++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php
@@ -3,6 +3,7 @@
 namespace Doctrine\Common\Annotations;
 
 use Exception;
+use Throwable;
 
 use function get_class;
 use function gettype;
@@ -47,9 +48,9 @@ public static function semanticalError($message)
      *
      * @return AnnotationException
      */
-    public static function creationError($message)
+    public static function creationError($message, ?Throwable $previous = null)
     {
-        return new self('[Creation Error] ' . $message);
+        return new self('[Creation Error] ' . $message, 0, $previous);
     }
 
     /**
diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php
index ae530c50f57cc7530aaa0fd88f3cb07746b862a2..80f307caba39cb39ab2019362d8f2235604bc0cc 100644
--- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php
+++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php
@@ -12,6 +12,7 @@
 use ReflectionProperty;
 use RuntimeException;
 use stdClass;
+use Throwable;
 
 use function array_keys;
 use function array_map;
@@ -941,7 +942,7 @@ private function Annotation()
 
         if (self::$annotationMetadata[$name]['has_named_argument_constructor']) {
             if (PHP_VERSION_ID >= 80000) {
-                return new $name(...$values);
+                return $this->instantiateAnnotiation($originalName, $this->context, $name, $values);
             }
 
             $positionalValues = [];
@@ -968,16 +969,16 @@ private function Annotation()
                 $positionalValues[self::$annotationMetadata[$name]['constructor_args'][$property]['position']] = $value;
             }
 
-            return new $name(...$positionalValues);
+            return $this->instantiateAnnotiation($originalName, $this->context, $name, $positionalValues);
         }
 
         // check if the annotation expects values via the constructor,
         // or directly injected into public properties
         if (self::$annotationMetadata[$name]['has_constructor'] === true) {
-            return new $name($values);
+            return $this->instantiateAnnotiation($originalName, $this->context, $name, [$values]);
         }
 
-        $instance = new $name();
+        $instance = $this->instantiateAnnotiation($originalName, $this->context, $name, []);
 
         foreach ($values as $property => $value) {
             if (! isset(self::$annotationMetadata[$name]['properties'][$property])) {
@@ -1456,4 +1457,31 @@ private function resolvePositionalValues(array $arguments, string $name): array
 
         return $values;
     }
+
+    /**
+     * Try to instantiate the annotation and catch and process any exceptions related to failure
+     *
+     * @param class-string        $name
+     * @param array<string,mixed> $arguments
+     *
+     * @return object
+     *
+     * @throws AnnotationException
+     */
+    private function instantiateAnnotiation(string $originalName, string $context, string $name, array $arguments)
+    {
+        try {
+            return new $name(...$arguments);
+        } catch (Throwable $exception) {
+            throw AnnotationException::creationError(
+                sprintf(
+                    'An error occurred while instantiating the annotation @%s declared on %s: "%s".',
+                    $originalName,
+                    $context,
+                    $exception->getMessage()
+                ),
+                $exception
+            );
+        }
+    }
 }
diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php
index 2efeb1d22165bdf664083481c23dd6d0e3657b8b..ab27f8a5cdc0c9b27b6bac79a42e1bc680dca02b 100644
--- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php
+++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php
@@ -147,6 +147,7 @@ final class ImplicitlyIgnoredAnnotationNames
         // PHPStan, Psalm
         'extends' => true,
         'implements' => true,
+        'readonly' => true,
         'template' => true,
         'use' => true,
 
diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php
index 42e70765db7eb036132fd5effaef4ee73e050daf..62dcf7487b28b322a43765b7d4b1f880d5696222 100644
--- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php
+++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php
@@ -38,9 +38,9 @@ public function getClassAnnotations(ReflectionClass $class)
     /**
      * {@inheritDoc}
      */
-    public function getClassAnnotation(ReflectionClass $class, $annotation)
+    public function getClassAnnotation(ReflectionClass $class, $annotationName)
     {
-        return $this->delegate->getClassAnnotation($class, $annotation);
+        return $this->delegate->getClassAnnotation($class, $annotationName);
     }
 
     /**
@@ -59,9 +59,9 @@ public function getMethodAnnotations(ReflectionMethod $method)
     /**
      * {@inheritDoc}
      */
-    public function getMethodAnnotation(ReflectionMethod $method, $annotation)
+    public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
     {
-        return $this->delegate->getMethodAnnotation($method, $annotation);
+        return $this->delegate->getMethodAnnotation($method, $annotationName);
     }
 
     /**
@@ -80,9 +80,9 @@ public function getPropertyAnnotations(ReflectionProperty $property)
     /**
      * {@inheritDoc}
      */
-    public function getPropertyAnnotation(ReflectionProperty $property, $annotation)
+    public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
     {
-        return $this->delegate->getPropertyAnnotation($property, $annotation);
+        return $this->delegate->getPropertyAnnotation($property, $annotationName);
     }
 
     /**
diff --git a/vendor/doctrine/annotations/psalm.xml b/vendor/doctrine/annotations/psalm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e6af3892387744afa95a49d59498929bde5da218
--- /dev/null
+++ b/vendor/doctrine/annotations/psalm.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<psalm
+    errorLevel="7"
+    resolveFromConfigFile="true"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+>
+    <projectFiles>
+        <directory name="lib/Doctrine/Common/Annotations" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/laminas/laminas-diactoros/composer.lock b/vendor/laminas/laminas-diactoros/composer.lock
index 6f00fc023ea8819d579f60d70447a017c97e22f4..738c3e556ab9eb1d6a32f007c944c0f11fd00d25 100644
--- a/vendor/laminas/laminas-diactoros/composer.lock
+++ b/vendor/laminas/laminas-diactoros/composer.lock
@@ -357,30 +357,30 @@
         },
         {
             "name": "composer/pcre",
-            "version": "1.0.1",
+            "version": "2.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/pcre.git",
-                "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560"
+                "reference": "c8e9d27cfc5ed22643c19c160455b473ffd8aabe"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560",
-                "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560",
+                "url": "https://api.github.com/repos/composer/pcre/zipball/c8e9d27cfc5ed22643c19c160455b473ffd8aabe",
+                "reference": "c8e9d27cfc5ed22643c19c160455b473ffd8aabe",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.3.2 || ^7.0 || ^8.0"
+                "php": "^7.2 || ^8.0"
             },
             "require-dev": {
                 "phpstan/phpstan": "^1.3",
                 "phpstan/phpstan-strict-rules": "^1.1",
-                "symfony/phpunit-bridge": "^4.2 || ^5"
+                "symfony/phpunit-bridge": "^5"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.x-dev"
+                    "dev-main": "2.x-dev"
                 }
             },
             "autoload": {
@@ -408,7 +408,7 @@
             ],
             "support": {
                 "issues": "https://github.com/composer/pcre/issues",
-                "source": "https://github.com/composer/pcre/tree/1.0.1"
+                "source": "https://github.com/composer/pcre/tree/2.0.0"
             },
             "funding": [
                 {
@@ -424,20 +424,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-01-21T20:24:37+00:00"
+            "time": "2022-02-25T20:05:29+00:00"
         },
         {
             "name": "composer/semver",
-            "version": "3.2.9",
+            "version": "3.3.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/semver.git",
-                "reference": "a951f614bd64dcd26137bc9b7b2637ddcfc57649"
+                "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/semver/zipball/a951f614bd64dcd26137bc9b7b2637ddcfc57649",
-                "reference": "a951f614bd64dcd26137bc9b7b2637ddcfc57649",
+                "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
+                "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
                 "shasum": ""
             },
             "require": {
@@ -489,7 +489,7 @@
             "support": {
                 "irc": "irc://irc.freenode.org/composer",
                 "issues": "https://github.com/composer/semver/issues",
-                "source": "https://github.com/composer/semver/tree/3.2.9"
+                "source": "https://github.com/composer/semver/tree/3.3.2"
             },
             "funding": [
                 {
@@ -505,24 +505,24 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-02-04T13:58:43+00:00"
+            "time": "2022-04-01T19:23:25+00:00"
         },
         {
             "name": "composer/xdebug-handler",
-            "version": "3.0.1",
+            "version": "3.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/xdebug-handler.git",
-                "reference": "12f1b79476638a5615ed00ea6adbb269cec96fd8"
+                "reference": "ced299686f41dce890debac69273b47ffe98a40c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/12f1b79476638a5615ed00ea6adbb269cec96fd8",
-                "reference": "12f1b79476638a5615ed00ea6adbb269cec96fd8",
+                "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
+                "reference": "ced299686f41dce890debac69273b47ffe98a40c",
                 "shasum": ""
             },
             "require": {
-                "composer/pcre": "^1",
+                "composer/pcre": "^1 || ^2 || ^3",
                 "php": "^7.2.5 || ^8.0",
                 "psr/log": "^1 || ^2 || ^3"
             },
@@ -555,7 +555,7 @@
             "support": {
                 "irc": "irc://irc.freenode.org/composer",
                 "issues": "https://github.com/composer/xdebug-handler/issues",
-                "source": "https://github.com/composer/xdebug-handler/tree/3.0.1"
+                "source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
             },
             "funding": [
                 {
@@ -571,7 +571,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-01-04T18:29:42+00:00"
+            "time": "2022-02-25T21:32:43+00:00"
         },
         {
             "name": "dnoegel/php-xdg-base-dir",
@@ -612,29 +612,30 @@
         },
         {
             "name": "doctrine/instantiator",
-            "version": "1.4.0",
+            "version": "1.4.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/instantiator.git",
-                "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b"
+                "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b",
-                "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b",
+                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
+                "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
                 "shasum": ""
             },
             "require": {
                 "php": "^7.1 || ^8.0"
             },
             "require-dev": {
-                "doctrine/coding-standard": "^8.0",
+                "doctrine/coding-standard": "^9",
                 "ext-pdo": "*",
                 "ext-phar": "*",
-                "phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
-                "phpstan/phpstan": "^0.12",
-                "phpstan/phpstan-phpunit": "^0.12",
-                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+                "phpbench/phpbench": "^0.16 || ^1",
+                "phpstan/phpstan": "^1.4",
+                "phpstan/phpstan-phpunit": "^1",
+                "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+                "vimeo/psalm": "^4.22"
             },
             "type": "library",
             "autoload": {
@@ -661,7 +662,7 @@
             ],
             "support": {
                 "issues": "https://github.com/doctrine/instantiator/issues",
-                "source": "https://github.com/doctrine/instantiator/tree/1.4.0"
+                "source": "https://github.com/doctrine/instantiator/tree/1.4.1"
             },
             "funding": [
                 {
@@ -677,7 +678,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2020-11-10T18:47:58+00:00"
+            "time": "2022-03-03T08:28:38+00:00"
         },
         {
             "name": "felixfbecker/advanced-json-rpc",
@@ -726,16 +727,16 @@
         },
         {
             "name": "felixfbecker/language-server-protocol",
-            "version": "1.5.1",
+            "version": "v1.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/felixfbecker/php-language-server-protocol.git",
-                "reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730"
+                "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/9d846d1f5cf101deee7a61c8ba7caa0a975cd730",
-                "reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730",
+                "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842",
+                "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842",
                 "shasum": ""
             },
             "require": {
@@ -776,9 +777,9 @@
             ],
             "support": {
                 "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues",
-                "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/1.5.1"
+                "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2"
             },
-            "time": "2021-02-22T14:02:09+00:00"
+            "time": "2022-03-02T22:36:06+00:00"
         },
         {
             "name": "http-interop/http-factory-tests",
@@ -935,25 +936,29 @@
         },
         {
             "name": "myclabs/deep-copy",
-            "version": "1.10.2",
+            "version": "1.11.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/myclabs/DeepCopy.git",
-                "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220"
+                "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220",
-                "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220",
+                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
+                "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
                 "shasum": ""
             },
             "require": {
                 "php": "^7.1 || ^8.0"
             },
+            "conflict": {
+                "doctrine/collections": "<1.6.8",
+                "doctrine/common": "<2.13.3 || >=3,<3.2.2"
+            },
             "require-dev": {
-                "doctrine/collections": "^1.0",
-                "doctrine/common": "^2.6",
-                "phpunit/phpunit": "^7.1"
+                "doctrine/collections": "^1.6.8",
+                "doctrine/common": "^2.13.3 || ^3.2.2",
+                "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
             },
             "type": "library",
             "autoload": {
@@ -978,7 +983,7 @@
             ],
             "support": {
                 "issues": "https://github.com/myclabs/DeepCopy/issues",
-                "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2"
+                "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
             },
             "funding": [
                 {
@@ -986,7 +991,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2020-11-13T09:40:50+00:00"
+            "time": "2022-03-03T13:19:32+00:00"
         },
         {
             "name": "netresearch/jsonmapper",
@@ -1041,16 +1046,16 @@
         },
         {
             "name": "nikic/php-parser",
-            "version": "v4.13.2",
+            "version": "v4.14.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "210577fe3cf7badcc5814d99455df46564f3c077"
+                "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077",
-                "reference": "210577fe3cf7badcc5814d99455df46564f3c077",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1",
+                "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1",
                 "shasum": ""
             },
             "require": {
@@ -1091,9 +1096,9 @@
             ],
             "support": {
                 "issues": "https://github.com/nikic/PHP-Parser/issues",
-                "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2"
+                "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0"
             },
-            "time": "2021-11-30T19:35:32+00:00"
+            "time": "2022-05-31T20:59:12+00:00"
         },
         {
             "name": "openlss/lib-array2xml",
@@ -1430,16 +1435,16 @@
         },
         {
             "name": "phpdocumentor/type-resolver",
-            "version": "1.6.0",
+            "version": "1.6.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpDocumentor/TypeResolver.git",
-                "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706"
+                "reference": "77a32518733312af16a44300404e945338981de3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706",
-                "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706",
+                "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
+                "reference": "77a32518733312af16a44300404e945338981de3",
                 "shasum": ""
             },
             "require": {
@@ -1474,9 +1479,9 @@
             "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
             "support": {
                 "issues": "https://github.com/phpDocumentor/TypeResolver/issues",
-                "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.0"
+                "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
             },
-            "time": "2022-01-04T19:58:01+00:00"
+            "time": "2022-03-15T21:29:03+00:00"
         },
         {
             "name": "phpspec/prophecy",
@@ -1599,16 +1604,16 @@
         },
         {
             "name": "phpunit/php-code-coverage",
-            "version": "9.2.11",
+            "version": "9.2.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "665a1ac0a763c51afc30d6d130dac0813092b17f"
+                "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/665a1ac0a763c51afc30d6d130dac0813092b17f",
-                "reference": "665a1ac0a763c51afc30d6d130dac0813092b17f",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
+                "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
                 "shasum": ""
             },
             "require": {
@@ -1664,7 +1669,7 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
-                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.11"
+                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15"
             },
             "funding": [
                 {
@@ -1672,7 +1677,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2022-02-18T12:46:09+00:00"
+            "time": "2022-03-07T09:28:20+00:00"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -1917,16 +1922,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "9.5.14",
+            "version": "9.5.21",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "1883687169c017d6ae37c58883ca3994cfc34189"
+                "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1883687169c017d6ae37c58883ca3994cfc34189",
-                "reference": "1883687169c017d6ae37c58883ca3994cfc34189",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1",
+                "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1",
                 "shasum": ""
             },
             "require": {
@@ -1942,7 +1947,7 @@
                 "phar-io/version": "^3.0.2",
                 "php": ">=7.3",
                 "phpspec/prophecy": "^1.12.1",
-                "phpunit/php-code-coverage": "^9.2.7",
+                "phpunit/php-code-coverage": "^9.2.13",
                 "phpunit/php-file-iterator": "^3.0.5",
                 "phpunit/php-invoker": "^3.1.1",
                 "phpunit/php-text-template": "^2.0.3",
@@ -1956,11 +1961,10 @@
                 "sebastian/global-state": "^5.0.1",
                 "sebastian/object-enumerator": "^4.0.3",
                 "sebastian/resource-operations": "^3.0.3",
-                "sebastian/type": "^2.3.4",
+                "sebastian/type": "^3.0",
                 "sebastian/version": "^3.0.2"
             },
             "require-dev": {
-                "ext-pdo": "*",
                 "phpspec/prophecy-phpunit": "^2.0.1"
             },
             "suggest": {
@@ -2004,7 +2008,7 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.14"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21"
             },
             "funding": [
                 {
@@ -2016,7 +2020,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2022-02-18T12:54:07+00:00"
+            "time": "2022-06-19T12:14:25+00:00"
         },
         {
             "name": "psalm/plugin-phpunit",
@@ -2542,16 +2546,16 @@
         },
         {
             "name": "sebastian/environment",
-            "version": "5.1.3",
+            "version": "5.1.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/environment.git",
-                "reference": "388b6ced16caa751030f6a69e588299fa09200ac"
+                "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac",
-                "reference": "388b6ced16caa751030f6a69e588299fa09200ac",
+                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
+                "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
                 "shasum": ""
             },
             "require": {
@@ -2593,7 +2597,7 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/environment/issues",
-                "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3"
+                "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
             },
             "funding": [
                 {
@@ -2601,7 +2605,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-09-28T05:52:38+00:00"
+            "time": "2022-04-03T09:37:03+00:00"
         },
         {
             "name": "sebastian/exporter",
@@ -3033,28 +3037,28 @@
         },
         {
             "name": "sebastian/type",
-            "version": "2.3.4",
+            "version": "3.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/type.git",
-                "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914"
+                "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914",
-                "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914",
+                "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
+                "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.3"
+                "phpunit/phpunit": "^9.5"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.3-dev"
+                    "dev-master": "3.0-dev"
                 }
             },
             "autoload": {
@@ -3077,7 +3081,7 @@
             "homepage": "https://github.com/sebastianbergmann/type",
             "support": {
                 "issues": "https://github.com/sebastianbergmann/type/issues",
-                "source": "https://github.com/sebastianbergmann/type/tree/2.3.4"
+                "source": "https://github.com/sebastianbergmann/type/tree/3.0.0"
             },
             "funding": [
                 {
@@ -3085,7 +3089,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-06-15T12:49:02+00:00"
+            "time": "2022-03-15T09:54:48+00:00"
         },
         {
             "name": "sebastian/version",
@@ -3225,16 +3229,16 @@
         },
         {
             "name": "symfony/console",
-            "version": "v5.4.3",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "a2a86ec353d825c75856c6fd14fac416a7bdb6b8"
+                "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/a2a86ec353d825c75856c6fd14fac416a7bdb6b8",
-                "reference": "a2a86ec353d825c75856c6fd14fac416a7bdb6b8",
+                "url": "https://api.github.com/repos/symfony/console/zipball/829d5d1bf60b2efeb0887b7436873becc71a45eb",
+                "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb",
                 "shasum": ""
             },
             "require": {
@@ -3304,7 +3308,7 @@
                 "terminal"
             ],
             "support": {
-                "source": "https://github.com/symfony/console/tree/v5.4.3"
+                "source": "https://github.com/symfony/console/tree/v5.4.9"
             },
             "funding": [
                 {
@@ -3320,20 +3324,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-01-26T16:28:35+00:00"
+            "time": "2022-05-18T06:17:34+00:00"
         },
         {
             "name": "symfony/deprecation-contracts",
-            "version": "v2.5.0",
+            "version": "v2.5.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/deprecation-contracts.git",
-                "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
+                "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
-                "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
+                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
+                "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
                 "shasum": ""
             },
             "require": {
@@ -3371,7 +3375,7 @@
             "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.0"
+                "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1"
             },
             "funding": [
                 {
@@ -3387,20 +3391,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-07-12T14:48:14+00:00"
+            "time": "2022-01-02T09:53:40+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
-            "version": "v1.24.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-ctype.git",
-                "reference": "30885182c981ab175d4d034db0f6f469898070ab"
+                "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
-                "reference": "30885182c981ab175d4d034db0f6f469898070ab",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
+                "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
                 "shasum": ""
             },
             "require": {
@@ -3415,7 +3419,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -3423,12 +3427,12 @@
                 }
             },
             "autoload": {
-                "psr-4": {
-                    "Symfony\\Polyfill\\Ctype\\": ""
-                },
                 "files": [
                     "bootstrap.php"
-                ]
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Ctype\\": ""
+                }
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
@@ -3453,7 +3457,7 @@
                 "portable"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0"
+                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
             },
             "funding": [
                 {
@@ -3469,20 +3473,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-10-20T20:35:02+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-intl-grapheme",
-            "version": "v1.24.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
-                "reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
+                "reference": "433d05519ce6990bf3530fba6957499d327395c2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
-                "reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
+                "reference": "433d05519ce6990bf3530fba6957499d327395c2",
                 "shasum": ""
             },
             "require": {
@@ -3494,7 +3498,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -3534,7 +3538,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.24.0"
+                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
             },
             "funding": [
                 {
@@ -3550,20 +3554,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-11-23T21:10:46+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-intl-normalizer",
-            "version": "v1.24.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
-                "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
+                "reference": "219aa369ceff116e673852dce47c3a41794c14bd"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
-                "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
+                "reference": "219aa369ceff116e673852dce47c3a41794c14bd",
                 "shasum": ""
             },
             "require": {
@@ -3575,7 +3579,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -3618,7 +3622,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.24.0"
+                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
             },
             "funding": [
                 {
@@ -3634,20 +3638,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-02-19T12:13:01+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-mbstring",
-            "version": "v1.24.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
+                "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
-                "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
+                "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
                 "shasum": ""
             },
             "require": {
@@ -3662,7 +3666,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -3701,7 +3705,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0"
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
             },
             "funding": [
                 {
@@ -3717,20 +3721,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-11-30T18:21:41+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-php73",
-            "version": "v1.24.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php73.git",
-                "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5"
+                "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5",
-                "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5",
+                "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
+                "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
                 "shasum": ""
             },
             "require": {
@@ -3739,7 +3743,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -3780,7 +3784,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php73/tree/v1.24.0"
+                "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
             },
             "funding": [
                 {
@@ -3796,20 +3800,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-06-05T21:20:04+00:00"
+            "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-php80",
-            "version": "v1.24.0",
+            "version": "v1.26.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php80.git",
-                "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9"
+                "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9",
-                "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9",
+                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
+                "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
                 "shasum": ""
             },
             "require": {
@@ -3818,7 +3822,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.23-dev"
+                    "dev-main": "1.26-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -3863,7 +3867,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0"
+                "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
             },
             "funding": [
                 {
@@ -3879,26 +3883,26 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-09-13T13:58:33+00:00"
+            "time": "2022-05-10T07:21:04+00:00"
         },
         {
             "name": "symfony/service-contracts",
-            "version": "v2.5.0",
+            "version": "v2.5.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/service-contracts.git",
-                "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc"
+                "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
-                "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
+                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
+                "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.2.5",
                 "psr/container": "^1.1",
-                "symfony/deprecation-contracts": "^2.1"
+                "symfony/deprecation-contracts": "^2.1|^3"
             },
             "conflict": {
                 "ext-psr": "<1.1|>=2"
@@ -3946,7 +3950,7 @@
                 "standards"
             ],
             "support": {
-                "source": "https://github.com/symfony/service-contracts/tree/v2.5.0"
+                "source": "https://github.com/symfony/service-contracts/tree/v2.5.1"
             },
             "funding": [
                 {
@@ -3962,20 +3966,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-11-04T16:48:04+00:00"
+            "time": "2022-03-13T20:07:29+00:00"
         },
         {
             "name": "symfony/string",
-            "version": "v5.4.3",
+            "version": "v5.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/string.git",
-                "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10"
+                "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10",
-                "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10",
+                "url": "https://api.github.com/repos/symfony/string/zipball/985e6a9703ef5ce32ba617c9c7d97873bb7b2a99",
+                "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99",
                 "shasum": ""
             },
             "require": {
@@ -3997,12 +4001,12 @@
             },
             "type": "library",
             "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\String\\": ""
-                },
                 "files": [
                     "Resources/functions.php"
                 ],
+                "psr-4": {
+                    "Symfony\\Component\\String\\": ""
+                },
                 "exclude-from-classmap": [
                     "/Tests/"
                 ]
@@ -4032,7 +4036,7 @@
                 "utf8"
             ],
             "support": {
-                "source": "https://github.com/symfony/string/tree/v5.4.3"
+                "source": "https://github.com/symfony/string/tree/v5.4.9"
             },
             "funding": [
                 {
@@ -4048,7 +4052,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-01-02T09:53:40+00:00"
+            "time": "2022-04-19T10:40:37+00:00"
         },
         {
             "name": "theseer/tokenizer",
@@ -4102,16 +4106,16 @@
         },
         {
             "name": "vimeo/psalm",
-            "version": "4.21.0",
+            "version": "4.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/vimeo/psalm.git",
-                "reference": "d8bec4c7aaee111a532daec32fb09de5687053d1"
+                "reference": "f1fe6ff483bf325c803df9f510d09a03fd796f88"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/vimeo/psalm/zipball/d8bec4c7aaee111a532daec32fb09de5687053d1",
-                "reference": "d8bec4c7aaee111a532daec32fb09de5687053d1",
+                "url": "https://api.github.com/repos/vimeo/psalm/zipball/f1fe6ff483bf325c803df9f510d09a03fd796f88",
+                "reference": "f1fe6ff483bf325c803df9f510d09a03fd796f88",
                 "shasum": ""
             },
             "require": {
@@ -4136,6 +4140,7 @@
                 "php": "^7.1|^8",
                 "sebastian/diff": "^3.0 || ^4.0",
                 "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0",
+                "symfony/polyfill-php80": "^1.25",
                 "webmozart/path-util": "^2.3"
             },
             "provide": {
@@ -4202,27 +4207,27 @@
             ],
             "support": {
                 "issues": "https://github.com/vimeo/psalm/issues",
-                "source": "https://github.com/vimeo/psalm/tree/4.21.0"
+                "source": "https://github.com/vimeo/psalm/tree/4.23.0"
             },
-            "time": "2022-02-18T04:34:15+00:00"
+            "time": "2022-04-28T17:35:49+00:00"
         },
         {
             "name": "webmozart/assert",
-            "version": "1.10.0",
+            "version": "1.11.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/webmozarts/assert.git",
-                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
+                "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
-                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
+                "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
+                "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.2 || ^8.0",
-                "symfony/polyfill-ctype": "^1.8"
+                "ext-ctype": "*",
+                "php": "^7.2 || ^8.0"
             },
             "conflict": {
                 "phpstan/phpstan": "<0.12.20",
@@ -4260,9 +4265,9 @@
             ],
             "support": {
                 "issues": "https://github.com/webmozarts/assert/issues",
-                "source": "https://github.com/webmozarts/assert/tree/1.10.0"
+                "source": "https://github.com/webmozarts/assert/tree/1.11.0"
             },
-            "time": "2021-03-09T10:59:23+00:00"
+            "time": "2022-06-03T18:03:27+00:00"
         },
         {
             "name": "webmozart/path-util",
diff --git a/vendor/laminas/laminas-diactoros/psalm-baseline.xml b/vendor/laminas/laminas-diactoros/psalm-baseline.xml
index fc5a8bafac0436b1921886774b31e837d6c1b5de..47be887f6b855d4716f1af21954c7c3738d583af 100644
--- a/vendor/laminas/laminas-diactoros/psalm-baseline.xml
+++ b/vendor/laminas/laminas-diactoros/psalm-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<files psalm-version="4.21.0@d8bec4c7aaee111a532daec32fb09de5687053d1">
+<files psalm-version="4.23.0@f1fe6ff483bf325c803df9f510d09a03fd796f88">
   <file src="src/CallbackStream.php">
     <ImplementedReturnTypeMismatch occurrences="1">
       <code>null|callable</code>
@@ -242,13 +242,52 @@
     </ParamNameMismatch>
   </file>
   <file src="src/ServerRequestFactory.php">
-    <MixedArgument occurrences="1">
+    <LessSpecificReturnStatement occurrences="1"/>
+    <MixedArgument occurrences="2">
       <code>$headers['cookie']</code>
+      <code>$host</code>
     </MixedArgument>
+    <MixedArgumentTypeCoercion occurrences="1">
+      <code>$headers</code>
+    </MixedArgumentTypeCoercion>
+    <MixedAssignment occurrences="3">
+      <code>$iisUrlRewritten</code>
+      <code>$requestUri</code>
+      <code>$unencodedUrl</code>
+    </MixedAssignment>
+    <MixedInferredReturnType occurrences="1">
+      <code>array{string, int|null}</code>
+    </MixedInferredReturnType>
+    <MixedReturnStatement occurrences="1">
+      <code>$defaults</code>
+    </MixedReturnStatement>
+    <MixedReturnTypeCoercion occurrences="1">
+      <code>self::marshalHostAndPortFromHeader($host)</code>
+    </MixedReturnTypeCoercion>
+    <MoreSpecificReturnType occurrences="1">
+      <code>ServerRequest</code>
+    </MoreSpecificReturnType>
     <RedundantConditionGivenDocblockType occurrences="1">
       <code>is_callable(self::$apacheRequestHeaders)</code>
     </RedundantConditionGivenDocblockType>
   </file>
+  <file src="src/ServerRequestFilter/FilterUsingXForwardedHeaders.php">
+    <ImpureMethodCall occurrences="7">
+      <code>getHeaderLine</code>
+      <code>getServerParams</code>
+      <code>getUri</code>
+      <code>withHost</code>
+      <code>withPort</code>
+      <code>withScheme</code>
+      <code>withUri</code>
+    </ImpureMethodCall>
+    <LessSpecificReturnStatement occurrences="1">
+      <code>$proxyCIDRList</code>
+    </LessSpecificReturnStatement>
+    <MoreSpecificReturnType occurrences="1">
+      <code>list&lt;non-empty-string&gt;</code>
+    </MoreSpecificReturnType>
+  </file>
   <file src="src/Stream.php">
     <InvalidArgument occurrences="1"/>
     <MixedInferredReturnType occurrences="1">
@@ -1125,54 +1164,10 @@
     </MissingReturnType>
   </file>
   <file src="test/UploadedFileTest.php">
-    <MissingParamType occurrences="6">
-      <code>$path</code>
-      <code>$status</code>
-      <code>$status</code>
-      <code>$status</code>
-      <code>$status</code>
-      <code>$streamOrFile</code>
-    </MissingParamType>
-    <MissingPropertyType occurrences="1">
-      <code>$tmpFile</code>
-    </MissingPropertyType>
-    <MissingReturnType occurrences="24">
-      <code>errorConstantsAndMessages</code>
-      <code>invalidErrorStatuses</code>
-      <code>invalidMovePaths</code>
-      <code>invalidStreams</code>
-      <code>nonOkErrorStatus</code>
-      <code>testCannotRetrieveStreamAfterMove</code>
-      <code>testConstructorDoesNotRaiseExceptionForInvalidStreamWhenErrorStatusPresent</code>
-      <code>testGetStreamRaisesExceptionWhenErrorStatusPresent</code>
-      <code>testGetStreamRaisesExceptionWithAppropriateMessageWhenUploadErrorDetected</code>
-      <code>testGetStreamReturnsOriginalStreamObject</code>
-      <code>testGetStreamReturnsStreamForFile</code>
-      <code>testGetStreamReturnsWrappedPhpStream</code>
-      <code>testMoveCannotBeCalledMoreThanOnce</code>
-      <code>testMoveRaisesExceptionForInvalidPath</code>
-      <code>testMoveToCreatesStreamIfOnlyAFilenameWasProvided</code>
-      <code>testMoveToRaisesExceptionWhenErrorStatusPresent</code>
-      <code>testMoveToRaisesExceptionWithAppropriateMessageWhenUploadErrorDetected</code>
-      <code>testMovesFileToDesignatedPath</code>
-      <code>testRaisesExceptionOnInvalidErrorStatus</code>
-      <code>testRaisesExceptionOnInvalidStreamOrFile</code>
-      <code>testValidClientFilename</code>
-      <code>testValidClientMediaType</code>
-      <code>testValidNullClientFilename</code>
-      <code>testValidSize</code>
-    </MissingReturnType>
-    <MixedArgument occurrences="6">
+    <MixedArgument occurrences="2">
       <code>$path</code>
-      <code>$status</code>
-      <code>$status</code>
-      <code>$status</code>
-      <code>$status</code>
       <code>$streamOrFile</code>
     </MixedArgument>
-    <UndefinedThisPropertyAssignment occurrences="1">
-      <code>$this-&gt;tmpfile</code>
-    </UndefinedThisPropertyAssignment>
   </file>
   <file src="test/UriTest.php">
     <InvalidScalarArgument occurrences="2">
diff --git a/vendor/laminas/laminas-diactoros/psalm.xml.dist b/vendor/laminas/laminas-diactoros/psalm.xml.dist
index 9cee6e9efd78015a2a3c7be7c85eb5f08ab603b5..0a854e5436054670a32717b7cd78fd14b50e92b4 100644
--- a/vendor/laminas/laminas-diactoros/psalm.xml.dist
+++ b/vendor/laminas/laminas-diactoros/psalm.xml.dist
@@ -15,11 +15,26 @@
     </projectFiles>
 
     <issueHandlers>
+        <DeprecatedFunction>
+            <errorLevel type="suppress">
+                <referencedFunction name="laminas\diactoros\marshalurifromsapi"/>
+            </errorLevel>
+        </DeprecatedFunction>
+
+        <InternalClass>
+            <errorLevel type="suppress">
+                <referencedClass name="Laminas\Diactoros\ServerRequestFilter\IPRange"/>
+            </errorLevel>
+        </InternalClass>
+
         <InternalMethod>
             <errorLevel type="suppress">
                 <referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::method"/>
                 <referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::willReturn"/>
                 <referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::with"/>
+                <referencedMethod name="Laminas\Diactoros\ServerRequestFilter\IPRange::matches"/>
+                <referencedMethod name="Laminas\Diactoros\ServerRequestFilter\IPRange::matchesIPv4"/>
+                <referencedMethod name="Laminas\Diactoros\ServerRequestFilter\IPRange::matchesIPv6"/>
             </errorLevel>
         </InternalMethod>
 
diff --git a/vendor/laminas/laminas-diactoros/src/ConfigProvider.php b/vendor/laminas/laminas-diactoros/src/ConfigProvider.php
index 32510d1f686126a4a58a9a2fe74d6e1753a18881..78afa0474e8edb3adb437449ac188d62d443bf18 100644
--- a/vendor/laminas/laminas-diactoros/src/ConfigProvider.php
+++ b/vendor/laminas/laminas-diactoros/src/ConfigProvider.php
@@ -13,6 +13,11 @@
 
 class ConfigProvider
 {
+    public const CONFIG_KEY = 'laminas-diactoros';
+    public const X_FORWARDED = 'x-forwarded-request-filter';
+    public const X_FORWARDED_TRUSTED_PROXIES = 'trusted-proxies';
+    public const X_FORWARDED_TRUSTED_HEADERS = 'trusted-headers';
+
     /**
      * Retrieve configuration for laminas-diactoros.
      *
@@ -22,6 +27,7 @@ public function __invoke() : array
     {
         return [
             'dependencies' => $this->getDependencies(),
+            self::CONFIG_KEY => $this->getComponentConfig(),
         ];
     }
 
@@ -31,6 +37,7 @@ public function __invoke() : array
      */
     public function getDependencies() : array
     {
+        // @codingStandardsIgnoreStart
         return [
             'invokables' => [
                 RequestFactoryInterface::class => RequestFactory::class,
@@ -41,5 +48,16 @@ public function getDependencies() : array
                 UriFactoryInterface::class => UriFactory::class
             ],
         ];
+        // @codingStandardsIgnoreEnd
+    }
+
+    public function getComponentConfig(): array
+    {
+        return [
+            self::X_FORWARDED => [
+                self::X_FORWARDED_TRUSTED_PROXIES => '',
+                self::X_FORWARDED_TRUSTED_HEADERS => [],
+            ],
+        ];
     }
 }
diff --git a/vendor/laminas/laminas-diactoros/src/Exception/InvalidForwardedHeaderNameException.php b/vendor/laminas/laminas-diactoros/src/Exception/InvalidForwardedHeaderNameException.php
new file mode 100644
index 0000000000000000000000000000000000000000..1c446439f9fa26033e637b139435993efbdf7a79
--- /dev/null
+++ b/vendor/laminas/laminas-diactoros/src/Exception/InvalidForwardedHeaderNameException.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Laminas\Diactoros\Exception;
+
+use Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders;
+
+class InvalidForwardedHeaderNameException extends RuntimeException implements ExceptionInterface
+{
+    /** @param mixed $name */
+    public static function forHeader($name): self
+    {
+        if (! is_string($name)) {
+            $name = sprintf('(value of type %s)', is_object($name) ? get_class($name) : gettype($name));
+        }
+
+        return new self(sprintf(
+            'Invalid X-Forwarded-* header name "%s" provided to %s',
+            $name,
+            FilterUsingXForwardedHeaders::class
+        ));
+    }
+}
diff --git a/vendor/laminas/laminas-diactoros/src/Exception/InvalidProxyAddressException.php b/vendor/laminas/laminas-diactoros/src/Exception/InvalidProxyAddressException.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c8a68d29c16f801fe2fb594076d299d3972f6ae
--- /dev/null
+++ b/vendor/laminas/laminas-diactoros/src/Exception/InvalidProxyAddressException.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Laminas\Diactoros\Exception;
+
+class InvalidProxyAddressException extends RuntimeException implements ExceptionInterface
+{
+    /** @param mixed $proxy */
+    public static function forInvalidProxyArgument($proxy): self
+    {
+        $type = is_object($proxy) ? get_class($proxy) : gettype($proxy);
+        return new self(sprintf(
+            'Invalid proxy of type "%s" provided;'
+            . ' must be a valid IPv4 or IPv6 address, optionally with a subnet mask provided'
+            . ' or an array of such values',
+            $type,
+        ));
+    }
+
+    public static function forAddress(string $address): self
+    {
+        return new self(sprintf(
+            'Invalid proxy address "%s" provided;'
+            . ' must be a valid IPv4 or IPv6 address, optionally with a subnet mask provided',
+            $address,
+        ));
+    }
+}
diff --git a/vendor/laminas/laminas-diactoros/src/ServerRequestFactory.php b/vendor/laminas/laminas-diactoros/src/ServerRequestFactory.php
index 3cde0e0c020188198c04e19f86275072bef4ef68..30eb71cbe0ef597b827d8beda2154bae2561fade 100644
--- a/vendor/laminas/laminas-diactoros/src/ServerRequestFactory.php
+++ b/vendor/laminas/laminas-diactoros/src/ServerRequestFactory.php
@@ -4,6 +4,8 @@
 
 namespace Laminas\Diactoros;
 
+use Laminas\Diactoros\ServerRequestFilter\FilterServerRequestInterface;
+use Laminas\Diactoros\ServerRequestFilter\FilterUsingXForwardedHeaders;
 use Psr\Http\Message\ServerRequestFactoryInterface;
 use Psr\Http\Message\ServerRequestInterface;
 
@@ -42,6 +44,11 @@ class ServerRequestFactory implements ServerRequestFactoryInterface
      * @param array $body $_POST superglobal
      * @param array $cookies $_COOKIE superglobal
      * @param array $files $_FILES superglobal
+     * @param null|FilterServerRequestInterface $requestFilter If present, the
+     *     generated request will be passed to this instance and the result
+     *     returned by this method. When not present, a default instance of
+     *     FilterUsingXForwardedHeaders is created, using the `trustReservedSubnets()`
+     *     constructor.
      * @return ServerRequest
      */
     public static function fromGlobals(
@@ -49,8 +56,11 @@ public static function fromGlobals(
         array $query = null,
         array $body = null,
         array $cookies = null,
-        array $files = null
+        array $files = null,
+        ?FilterServerRequestInterface $requestFilter = null
     ) : ServerRequest {
+        $requestFilter = $requestFilter ?: FilterUsingXForwardedHeaders::trustReservedSubnets();
+
         $server = normalizeServer(
             $server ?: $_SERVER,
             is_callable(self::$apacheRequestHeaders) ? self::$apacheRequestHeaders : null
@@ -62,10 +72,10 @@ public static function fromGlobals(
             $cookies = parseCookieHeader($headers['cookie']);
         }
 
-        return new ServerRequest(
+        return $requestFilter(new ServerRequest(
             $server,
             $files,
-            marshalUriFromSapi($server, $headers),
+            self::marshalUriFromSapi($server, $headers),
             marshalMethodFromSapi($server),
             'php://input',
             $headers,
@@ -73,7 +83,7 @@ public static function fromGlobals(
             $query ?: $_GET,
             $body ?: $_POST,
             marshalProtocolVersionFromSapi($server)
-        );
+        ));
     }
 
     /**
@@ -91,4 +101,210 @@ public function createServerRequest(string $method, $uri, array $serverParams =
             'php://temp'
         );
     }
+
+    /**
+     * Marshal a Uri instance based on the values present in the $_SERVER array and headers.
+     *
+     * @param array<string, string|list<string>> $headers
+     * @param array $server SAPI parameters
+     */
+    private static function marshalUriFromSapi(array $server, array $headers) : Uri
+    {
+        $uri = new Uri('');
+
+        // URI scheme
+        $https  = false;
+        if (array_key_exists('HTTPS', $server)) {
+            $https = self::marshalHttpsValue($server['HTTPS']);
+        } elseif (array_key_exists('https', $server)) {
+            $https = self::marshalHttpsValue($server['https']);
+        }
+
+        $uri = $uri->withScheme($https ? 'https' : 'http');
+
+        // Set the host
+        [$host, $port] = self::marshalHostAndPort($server, $headers);
+        if (! empty($host)) {
+            $uri = $uri->withHost($host);
+            if (! empty($port)) {
+                $uri = $uri->withPort($port);
+            }
+        }
+
+        // URI path
+        $path = self::marshalRequestPath($server);
+
+        // Strip query string
+        $path = explode('?', $path, 2)[0];
+
+        // URI query
+        $query = '';
+        if (isset($server['QUERY_STRING'])) {
+            $query = ltrim((string) $server['QUERY_STRING'], '?');
+        }
+
+        // URI fragment
+        $fragment = '';
+        if (strpos($path, '#') !== false) {
+            [$path, $fragment] = explode('#', $path, 2);
+        }
+
+        return $uri
+            ->withPath($path)
+            ->withFragment($fragment)
+            ->withQuery($query);
+    }
+
+    /**
+     * Marshal the host and port from the PHP environment.
+     *
+     * @param array<string, string|list<string>> $headers
+     * @return array{string, int|null} Array of two items, host and port,
+     *     in that order (can be passed to a list() operation).
+     */
+    private static function marshalHostAndPort(array $server, array $headers) : array
+    {
+        static $defaults = ['', null];
+
+        $host = self::getHeaderFromArray('host', $headers, false);
+        if ($host !== false) {
+            return self::marshalHostAndPortFromHeader($host);
+        }
+
+        if (! isset($server['SERVER_NAME'])) {
+            return $defaults;
+        }
+
+        $host = (string) $server['SERVER_NAME'];
+        $port = isset($server['SERVER_PORT']) ? (int) $server['SERVER_PORT'] : null;
+
+        if (! isset($server['SERVER_ADDR'])
+            || ! preg_match('/^\[[0-9a-fA-F\:]+\]$/', $host)
+        ) {
+            return [$host, $port];
+        }
+
+        // Misinterpreted IPv6-Address
+        // Reported for Safari on Windows
+        return self::marshalIpv6HostAndPort($server, $port);
+    }
+
+    /**
+     * @return array{string, int|null} Array of two items, host and port,
+     *     in that order (can be passed to a list() operation).
+     */
+    private static function marshalIpv6HostAndPort(array $server, ?int $port) : array
+    {
+        $host             = '[' . (string) $server['SERVER_ADDR'] . ']';
+        $port             = $port ?: 80;
+        $portSeparatorPos = strrpos($host, ':');
+
+        if (false === $portSeparatorPos) {
+            return [$host, $port];
+        }
+
+        if ($port . ']' === substr($host, $portSeparatorPos + 1)) {
+            // The last digit of the IPv6-Address has been taken as port
+            // Unset the port so the default port can be used
+            $port = null;
+        }
+        return [$host, $port];
+    }
+
+    /**
+     * Detect the path for the request
+     *
+     * Looks at a variety of criteria in order to attempt to autodetect the base
+     * request path, including:
+     *
+     * - IIS7 UrlRewrite environment
+     * - REQUEST_URI
+     * - ORIG_PATH_INFO
+     */
+    private static function marshalRequestPath(array $server) : string
+    {
+        // IIS7 with URL Rewrite: make sure we get the unencoded url
+        // (double slash problem).
+        $iisUrlRewritten = $server['IIS_WasUrlRewritten'] ?? null;
+        $unencodedUrl    = $server['UNENCODED_URL'] ?? '';
+        if ('1' === $iisUrlRewritten && is_string($unencodedUrl) && '' !== $unencodedUrl) {
+            return $unencodedUrl;
+        }
+
+        $requestUri = $server['REQUEST_URI'] ?? null;
+
+        if (is_string($requestUri)) {
+            return preg_replace('#^[^/:]+://[^/]+#', '', $requestUri);
+        }
+
+        $origPathInfo = $server['ORIG_PATH_INFO'] ?? '';
+        if (! is_string($origPathInfo) || '' === $origPathInfo) {
+            return '/';
+        }
+
+        return $origPathInfo;
+    }
+
+    /**
+     * @param mixed $https
+     */
+    private static function marshalHttpsValue($https) : bool
+    {
+        if (is_bool($https)) {
+            return $https;
+        }
+
+        if (! is_string($https)) {
+            throw new Exception\InvalidArgumentException(sprintf(
+                'SAPI HTTPS value MUST be a string or boolean; received %s',
+                gettype($https)
+            ));
+        }
+
+        return 'on' === strtolower($https);
+    }
+
+    /**
+     * @param string|list<string> $host
+     * @return array Array of two items, host and port, in that order (can be
+     *     passed to a list() operation).
+     */
+    private static function marshalHostAndPortFromHeader($host): array
+    {
+        if (is_array($host)) {
+            $host = implode(', ', $host);
+        }
+
+        $port = null;
+
+        // works for regname, IPv4 & IPv6
+        if (preg_match('|\:(\d+)$|', $host, $matches)) {
+            $host = substr($host, 0, -1 * (strlen($matches[1]) + 1));
+            $port = (int) $matches[1];
+        }
+
+        return [$host, $port];
+    }
+
+    /**
+     * Retrieve a header value from an array of headers using a case-insensitive lookup.
+     *
+     * @param array<string, string|list<string>> $headers Key/value header pairs
+     * @param mixed $default Default value to return if header not found
+     * @return mixed
+     */
+    private static function getHeaderFromArray(string $name, array $headers, $default = null)
+    {
+        $header  = strtolower($name);
+        $headers = array_change_key_case($headers, CASE_LOWER);
+        if (! array_key_exists($header, $headers)) {
+            return $default;
+        }
+
+        if (is_string($headers[$header])) {
+            return $headers[$header];
+        }
+
+        return implode(', ', $headers[$header]);
+    }
 }
diff --git a/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/DoNotFilter.php b/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/DoNotFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..7a6867a863b6cfedcbe04259e98df8dc42b1f907
--- /dev/null
+++ b/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/DoNotFilter.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Laminas\Diactoros\ServerRequestFilter;
+
+use Psr\Http\Message\ServerRequestInterface;
+
+final class DoNotFilter implements FilterServerRequestInterface
+{
+    public function __invoke(ServerRequestInterface $request): ServerRequestInterface
+    {
+        return $request;
+    }
+}
diff --git a/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/FilterServerRequestInterface.php b/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/FilterServerRequestInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..4de57d6d5fc6db603e2bb9aa51c1a001272cb6ea
--- /dev/null
+++ b/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/FilterServerRequestInterface.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Laminas\Diactoros\ServerRequestFilter;
+
+use Psr\Http\Message\ServerRequestInterface;
+
+/**
+ * Filter/initialize a server request.
+ *
+ * Implementations of this interface will take an incoming request, and
+ * decide if additional modifications are necessary. As examples:
+ *
+ * - Injecting a unique request identifier header.
+ * - Using the X-Forwarded-* headers to rewrite the URI to reflect the original request.
+ * - Using the Forwarded header to rewrite the URI to reflect the original request.
+ *
+ * This functionality is consumed by the ServerRequestFactory using the request
+ * instance it generates, just prior to returning a request.
+ */
+interface FilterServerRequestInterface
+{
+    /**
+     * Determine if a request needs further modification, and if so, return a
+     * new instance reflecting those modifications.
+     */
+    public function __invoke(ServerRequestInterface $request): ServerRequestInterface;
+}
diff --git a/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php b/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php
new file mode 100644
index 0000000000000000000000000000000000000000..00b9707b454b4bfe4008c05db14f4c6d30a5a008
--- /dev/null
+++ b/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php
@@ -0,0 +1,257 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Laminas\Diactoros\ServerRequestFilter;
+
+use Laminas\Diactoros\Exception\InvalidForwardedHeaderNameException;
+use Laminas\Diactoros\Exception\InvalidProxyAddressException;
+use Psr\Http\Message\ServerRequestInterface;
+
+/**
+ * Modify the URI to reflect the X-Forwarded-* headers.
+ *
+ * If the request comes from a trusted proxy, this filter will analyze the
+ * various X-Forwarded-* headers, if any, and if they are marked as trusted,
+ * in order to return a new request that composes a URI instance that reflects
+ * those headers.
+ *
+ * @psalm-immutable
+*/
+final class FilterUsingXForwardedHeaders implements FilterServerRequestInterface
+{
+    public const HEADER_HOST  = 'X-FORWARDED-HOST';
+    public const HEADER_PORT  = 'X-FORWARDED-PORT';
+    public const HEADER_PROTO = 'X-FORWARDED-PROTO';
+
+    private const X_FORWARDED_HEADERS = [
+        self::HEADER_HOST,
+        self::HEADER_PORT,
+        self::HEADER_PROTO,
+    ];
+
+    /**
+     * @var list<FilterUsingXForwardedHeaders::HEADER_*>
+     */
+    private $trustedHeaders;
+
+    /** @var list<non-empty-string> */
+    private $trustedProxies;
+
+    /**
+     * Only allow construction via named constructors
+     *
+     * @param list<non-empty-string> $trustedProxies
+     * @param list<FilterUsingXForwardedHeaders::HEADER_*> $trustedHeaders
+     */
+    private function __construct(
+        array $trustedProxies = [],
+        array $trustedHeaders = []
+    ) {
+        $this->trustedProxies = $trustedProxies;
+        $this->trustedHeaders = $trustedHeaders;
+    }
+
+    public function __invoke(ServerRequestInterface $request): ServerRequestInterface
+    {
+        $remoteAddress = $request->getServerParams()['REMOTE_ADDR'] ?? '';
+
+        if ('' === $remoteAddress || ! is_string($remoteAddress)) {
+            // Should we trigger a warning here?
+            return $request;
+        }
+
+        if (! $this->isFromTrustedProxy($remoteAddress)) {
+            // Do nothing
+            return $request;
+        }
+
+        // Update the URI based on the trusted headers
+        $uri = $originalUri = $request->getUri();
+        foreach ($this->trustedHeaders as $headerName) {
+            $header = $request->getHeaderLine($headerName);
+            if ('' === $header || false !== strpos($header, ',')) {
+                // Reject empty headers and/or headers with multiple values
+                continue;
+            }
+
+            switch ($headerName) {
+                case self::HEADER_HOST:
+                    $uri = $uri->withHost($header);
+                    break;
+                case self::HEADER_PORT:
+                    $uri = $uri->withPort((int) $header);
+                    break;
+                case self::HEADER_PROTO:
+                    $scheme = strtolower($header) === 'https' ? 'https' : 'http';
+                    $uri = $uri->withScheme($scheme);
+                    break;
+            }
+        }
+
+        if ($uri !== $originalUri) {
+            return $request->withUri($uri);
+        }
+
+        return $request;
+    }
+
+    /**
+     * Indicate which proxies and which X-Forwarded headers to trust.
+     *
+     * @param list<non-empty-string> $proxyCIDRList Each element may
+     *     be an IP address or a subnet specified using CIDR notation; both IPv4
+     *     and IPv6 are supported. The special string "*" will be translated to
+     *     two entries, "0.0.0.0/0" and "::/0". An empty list indicates no
+     *     proxies are trusted.
+     * @param list<FilterUsingXForwardedHeaders::HEADER_*> $trustedHeaders If
+     *     the list is empty, all X-Forwarded headers are trusted.
+     * @throws InvalidProxyAddressException
+     * @throws InvalidForwardedHeaderNameException
+     */
+    public static function trustProxies(
+        array $proxyCIDRList,
+        array $trustedHeaders = self::X_FORWARDED_HEADERS
+    ): self {
+        $proxyCIDRList = self::normalizeProxiesList($proxyCIDRList);
+        self::validateTrustedHeaders($trustedHeaders);
+
+        return new self($proxyCIDRList, $trustedHeaders);
+    }
+
+    /**
+     * Trust any X-FORWARDED-* headers from any address.
+     *
+     * This is functionally equivalent to calling `trustProxies(['*'])`.
+     *
+     * WARNING: Only do this if you know for certain that your application
+     * sits behind a trusted proxy that cannot be spoofed. This should only
+     * be the case if your server is not publicly addressable, and all requests
+     * are routed via a reverse proxy (e.g., a load balancer, a server such as
+     * Caddy, when using Traefik, etc.).
+     */
+    public static function trustAny(): self
+    {
+        return self::trustProxies(['*']);
+    }
+
+    /**
+     * Trust X-Forwarded headers from reserved subnetworks.
+     *
+     * This is functionally equivalent to calling `trustProxies()` where the
+     * `$proxcyCIDRList` argument is a list with the following:
+     *
+     * - 10.0.0.0/8
+     * - 127.0.0.0/8
+     * - 172.16.0.0/12
+     * - 192.168.0.0/16
+     * - ::1/128 (IPv6 localhost)
+     * - fc00::/7 (IPv6 private networks)
+     * - fe80::/10 (IPv6 local-link addresses)
+     *
+     * @param list<FilterUsingXForwardedHeaders::HEADER_*> $trustedHeaders If
+     *     the list is empty, all X-Forwarded headers are trusted.
+     * @throws InvalidForwardedHeaderNameException
+     */
+    public static function trustReservedSubnets(array $trustedHeaders = self::X_FORWARDED_HEADERS): self
+    {
+        return self::trustProxies([
+            '10.0.0.0/8',
+            '127.0.0.0/8',
+            '172.16.0.0/12',
+            '192.168.0.0/16',
+            '::1/128', // ipv6 localhost
+            'fc00::/7', // ipv6 private networks
+            'fe80::/10', // ipv6 local-link addresses
+        ], $trustedHeaders);
+    }
+
+    private function isFromTrustedProxy(string $remoteAddress): bool
+    {
+        foreach ($this->trustedProxies as $proxy) {
+            if (IPRange::matches($remoteAddress, $proxy)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /** @throws InvalidForwardedHeaderNameException */
+    private static function validateTrustedHeaders(array $headers): void
+    {
+        foreach ($headers as $header) {
+            if (! in_array($header, self::X_FORWARDED_HEADERS, true)) {
+                throw InvalidForwardedHeaderNameException::forHeader($header);
+            }
+        }
+    }
+
+    /**
+     * @param list<non-empty-string> $proxyCIDRList
+     * @return list<non-empty-string>
+     * @throws InvalidProxyAddressException
+     */
+    private static function normalizeProxiesList(array $proxyCIDRList): array
+    {
+        $foundWildcard = false;
+
+        foreach ($proxyCIDRList as $index => $cidr) {
+            if ($cidr === '*') {
+                unset($proxyCIDRList[$index]);
+                $foundWildcard = true;
+                continue;
+            }
+
+            if (! self::validateProxyCIDR($cidr)) {
+                throw InvalidProxyAddressException::forAddress($cidr);
+            }
+        }
+
+        if ($foundWildcard) {
+            $proxyCIDRList[] = '0.0.0.0/0';
+            $proxyCIDRList[] = '::/0';
+        }
+
+        return $proxyCIDRList;
+    }
+
+    /**
+     * @param mixed $cidr
+     */
+    private static function validateProxyCIDR($cidr): bool
+    {
+        if (! is_string($cidr) || '' === $cidr) {
+            return false;
+        }
+
+        $address = $cidr;
+        $mask    = null;
+        if (false !== strpos($cidr, '/')) {
+            [$address, $mask] = explode('/', $cidr, 2);
+            $mask = (int) $mask;
+        }
+
+        if (false !== strpos($address, ':')) {
+            // is IPV6
+            return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)
+                && (
+                    $mask === null
+                    || (
+                        $mask <= 128
+                        && $mask >= 0
+                    )
+                );
+        }
+
+        // is IPV4
+        return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
+            && (
+                $mask === null
+                || (
+                    $mask <= 32
+                    && $mask >= 0
+                )
+            );
+    }
+}
diff --git a/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/IPRange.php b/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/IPRange.php
new file mode 100644
index 0000000000000000000000000000000000000000..871dde8421fd6334d361b62530ef7674b905a681
--- /dev/null
+++ b/vendor/laminas/laminas-diactoros/src/ServerRequestFilter/IPRange.php
@@ -0,0 +1,106 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Laminas\Diactoros\ServerRequestFilter;
+
+/** @internal */
+final class IPRange
+{
+    /**
+     * Disable instantiation
+     */
+    private function __construct()
+    {
+    }
+
+    /** @psalm-pure */
+    public static function matches(string $ip, string $cidr): bool
+    {
+        if (false !== strpos($ip, ':')) {
+            return self::matchesIPv6($ip, $cidr);
+        }
+
+        return self::matchesIPv4($ip, $cidr);
+    }
+
+    /** @psalm-pure */
+    public static function matchesIPv4(string $ip, string $cidr): bool
+    {
+        $mask   = 32;
+        $subnet = $cidr;
+
+        if (false !== strpos($cidr, '/')) {
+            [$subnet, $mask] = explode('/', $cidr, 2);
+            $mask = (int) $mask;
+        }
+
+        if ($mask < 0 || $mask > 32) {
+            return false;
+        }
+
+        $ip     = ip2long($ip);
+        $subnet = ip2long($subnet);
+        if (false === $ip || false === $subnet) {
+            // Invalid data
+            return false;
+        }
+
+        return 0 === substr_compare(
+            sprintf("%032b", $ip),
+            sprintf("%032b", $subnet),
+            0,
+            $mask
+        );
+    }
+
+    /** @psalm-pure */
+    public static function matchesIPv6(string $ip, string $cidr): bool
+    {
+        $mask   = 128;
+        $subnet = $cidr;
+
+        if (false !== strpos($cidr, '/')) {
+            [$subnet, $mask] = explode('/', $cidr, 2);
+            $mask = (int) $mask;
+        }
+
+        if ($mask < 0 || $mask > 128) {
+            return false;
+        }
+
+        $ip     = inet_pton($ip);
+        $subnet = inet_pton($subnet);
+
+        if (false == $ip || false == $subnet) {
+            // Invalid data
+            return false;
+        }
+
+        // mask 0: if it's a valid IP, it's valid
+        if ($mask === 0) {
+            return (bool) unpack('n*', $ip);
+        }
+
+        // @see http://stackoverflow.com/questions/7951061/matching-ipv6-address-to-a-cidr-subnet, MW answer
+        $binMask = str_repeat("f", intval($mask / 4));
+        switch ($mask % 4) {
+            case 0:
+                break;
+            case 1:
+                $binMask .= "8";
+                break;
+            case 2:
+                $binMask .= "c";
+                break;
+            case 3:
+                $binMask .= "e";
+                break;
+        }
+
+        $binMask = str_pad($binMask, 32, '0');
+        $binMask = pack("H*", $binMask);
+
+        return ($ip & $binMask) === $subnet;
+    }
+}
diff --git a/vendor/laminas/laminas-diactoros/src/UploadedFile.php b/vendor/laminas/laminas-diactoros/src/UploadedFile.php
index 93980f307b76108d7c3c9bc25051b9945b5a7e50..e918697fba5770820f14391aebff4c4d6372a0e6 100644
--- a/vendor/laminas/laminas-diactoros/src/UploadedFile.php
+++ b/vendor/laminas/laminas-diactoros/src/UploadedFile.php
@@ -187,6 +187,13 @@ public function moveTo($targetPath) : void
             case (empty($sapi) || 0 === strpos($sapi, 'cli') || 0 === strpos($sapi, 'phpdbg') || ! $this->file):
                 // Non-SAPI environment, or no filename present
                 $this->writeFile($targetPath);
+
+                if ($this->stream instanceof StreamInterface) {
+                    $this->stream->close();
+                }
+                if (is_string($this->file) && file_exists($this->file)) {
+                    unlink($this->file);
+                }
                 break;
             default:
                 // SAPI environment, with file present
diff --git a/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.php b/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.php
index 778d31bfb670d59b6404ff9ae52ab7c555693def..0092aeff7ac7e8ef9adc9c0e654bc4626c055d31 100644
--- a/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.php
+++ b/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.php
@@ -22,6 +22,8 @@
  *
  * @param array $server SAPI parameters
  * @param array $headers HTTP request headers
+ * @deprecated This function is deprecated as of 2.11.1, and will be removed in
+ *     3.0.0. As of 2.11.1, it is no longer used internally.
  */
 function marshalUriFromSapi(array $server, array $headers) : Uri
 {
diff --git a/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php b/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php
index efb57bc1fe06ad034e7540c19bb083ba6001248d..7acd6b79c1a41f67f3e386cba81c47881bf1adfd 100644
--- a/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php
+++ b/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php
@@ -331,11 +331,16 @@ public function test304()
         $this->assertSame('', $response->getContent(false));
     }
 
-    public function testRedirects()
+    /**
+     * @testWith [[]]
+     *           [["Content-Length: 7"]]
+     */
+    public function testRedirects(array $headers = [])
     {
         $client = $this->getHttpClient(__FUNCTION__);
         $response = $client->request('POST', 'http://localhost:8057/301', [
             'auth_basic' => 'foo:bar',
+            'headers' => $headers,
             'body' => function () {
                 yield 'foo=bar';
             },
diff --git a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php
index f7fc2df6a2fd9c06f96aee41db5c3e7e8d99bec0..16e3eb2c19757dc9593f897bf8ef2198f67a78ab 100644
--- a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php
+++ b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php
@@ -30,12 +30,6 @@ trait ServiceSubscriberTrait
      */
     public static function getSubscribedServices(): array
     {
-        static $services;
-
-        if (null !== $services) {
-            return $services;
-        }
-
         $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : [];
         $attributeOptIn = false;
 
diff --git a/vendor/symfony/translation-contracts/Test/TranslatorTest.php b/vendor/symfony/translation-contracts/Test/TranslatorTest.php
index 890367657843753631c4beecd0fcb8594ee2f04b..a3e9b20af56e5d06c39f3ba481d80d2db9ba6131 100644
--- a/vendor/symfony/translation-contracts/Test/TranslatorTest.php
+++ b/vendor/symfony/translation-contracts/Test/TranslatorTest.php
@@ -362,7 +362,7 @@ protected function validateMatrix($nplural, $matrix, $expectSuccess = true)
         foreach ($matrix as $langCode => $data) {
             $indexes = array_flip($data);
             if ($expectSuccess) {
-                $this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
+                $this->assertCount($nplural, $indexes, "Langcode '$langCode' has '$nplural' plural forms.");
             } else {
                 $this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
             }
diff --git a/web/core/MAINTAINERS.txt b/web/core/MAINTAINERS.txt
index e8ab8076cf982ffc3d2b8eb4e9346bcf15eec6d6..ab0f5769763e79fa9dce21051bef4f4e9e27473c 100644
--- a/web/core/MAINTAINERS.txt
+++ b/web/core/MAINTAINERS.txt
@@ -534,6 +534,10 @@ Decoupled Menus Initiative
 Media Initiative
 - Janez Urevc 'slashrsm' https://www.drupal.org/u/slashrsm
 
+Project Browser Initiative
+- Leslie Glynn 'leslieg' https://www.drupal.org/u/leslieg
+- Chris Wells 'chrisfromredfin' https://www.drupal.org/u/chrisfromredfin
+
 
 Core mentoring coordinators
 ---------------------------
diff --git a/web/core/assets/scaffold/files/default.settings.php b/web/core/assets/scaffold/files/default.settings.php
index 72be7750b93a427526891c4d02068fed3c9a74f6..f3dca008fa380e153e86c2a6bb953b4c030184b5 100644
--- a/web/core/assets/scaffold/files/default.settings.php
+++ b/web/core/assets/scaffold/files/default.settings.php
@@ -490,6 +490,29 @@
  */
 # $settings['file_public_path'] = 'sites/default/files';
 
+/**
+ * Additional public file schemes:
+ *
+ * Public schemes are URI schemes that allow download access to all users for
+ * all files within that scheme.
+ *
+ * The "public" scheme is always public, and the "private" scheme is always
+ * private, but other schemes, such as "https", "s3", "example", or others,
+ * can be either public or private depending on the site. By default, they're
+ * private, and access to individual files is controlled via
+ * hook_file_download().
+ *
+ * Typically, if a scheme should be public, a module makes it public by
+ * implementing hook_file_download(), and granting access to all users for all
+ * files. This could be either the same module that provides the stream wrapper
+ * for the scheme, or a different module that decides to make the scheme
+ * public. However, in cases where a site needs to make a scheme public, but
+ * is unable to add code in a module to do so, the scheme may be added to this
+ * variable, the result of which is that system_file_download() grants public
+ * access to all files within that scheme.
+ */
+# $settings['file_additional_public_schemes'] = ['example'];
+
 /**
  * Private file path:
  *
diff --git a/web/core/assets/vendor/backbone/backbone-min.map b/web/core/assets/vendor/backbone/backbone-min.js.map
similarity index 100%
rename from web/core/assets/vendor/backbone/backbone-min.map
rename to web/core/assets/vendor/backbone/backbone-min.js.map
diff --git a/web/core/includes/common.inc b/web/core/includes/common.inc
index ed359612c33849ad285c8caf26848ce1b2abbb1b..2bee0e5547e39e9255a5b3c7596b71f80c137a71 100644
--- a/web/core/includes/common.inc
+++ b/web/core/includes/common.inc
@@ -558,7 +558,9 @@ function drupal_flush_all_caches($kernel = NULL) {
   // Wipe the Twig PHP Storage cache.
   \Drupal::service('twig')->invalidate();
 
-  // Rebuild theme data that is stored in state.
+  // Rebuild profile, profile, theme_engine and theme data.
+  \Drupal::service('extension.list.profile')->reset();
+  \Drupal::service('extension.list.theme_engine')->reset();
   \Drupal::service('theme_handler')->refreshInfo();
   // In case the active theme gets requested later in the same request we need
   // to reset the theme manager.
diff --git a/web/core/lib/Drupal.php b/web/core/lib/Drupal.php
index 9e903214b2016f3de306154c8f386f9cc2992710..48cb4aa4b7d2705b4f5a27b3f22614901a36fa5f 100644
--- a/web/core/lib/Drupal.php
+++ b/web/core/lib/Drupal.php
@@ -75,7 +75,7 @@ class Drupal {
   /**
    * The current system version.
    */
-  const VERSION = '9.4.1';
+  const VERSION = '9.4.3';
 
   /**
    * Core API compatibility.
diff --git a/web/core/lib/Drupal/Core/Composer/Composer.php b/web/core/lib/Drupal/Core/Composer/Composer.php
index fc7ce25cd4bb6898f252fdaaaa02a1829986f41c..4f7fcda1d3b27e6f65d07892ed85dca5dbc2ec18 100644
--- a/web/core/lib/Drupal/Core/Composer/Composer.php
+++ b/web/core/lib/Drupal/Core/Composer/Composer.php
@@ -130,13 +130,6 @@ public static function preAutoloadDump(Event $event) {
         $vendor_dir . '/symfony/http-kernel/TerminableInterface.php',
       ]);
     }
-    if ($repository->findPackage('symfony/http-kernel', $constraint)) {
-      $autoload['classmap'] = array_merge($autoload['classmap'], [
-        $vendor_dir . '/symfony/http-kernel/HttpKernel.php',
-        $vendor_dir . '/symfony/http-kernel/HttpKernelInterface.php',
-        $vendor_dir . '/symfony/http-kernel/TerminableInterface.php',
-      ]);
-    }
     if ($repository->findPackage('symfony/dependency-injection', $constraint)) {
       $autoload['classmap'] = array_merge($autoload['classmap'], [
         $vendor_dir . '/symfony/dependency-injection/ContainerAwareInterface.php',
diff --git a/web/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php b/web/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php
index 4952283967863dd72b0038d11d54885e33afeb45..a0ba7f0225e37255ea7b0aead8ab6c6a80d0a133 100644
--- a/web/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php
+++ b/web/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php
@@ -16,12 +16,34 @@ class DependencySerializationTraitPass implements CompilerPassInterface {
    * {@inheritdoc}
    */
   public function process(ContainerBuilder $container) {
+    $decorations = new \SplPriorityQueue();
+    $order = PHP_INT_MAX;
+
     foreach ($container->getDefinitions() as $service_id => $definition) {
       // Only add the property to services that are public (as private services
       // can not be reloaded through Container::get()) and are objects.
       if (!$definition->hasTag('parameter_service') && $definition->isPublic()) {
         $definition->setProperty('_serviceId', $service_id);
       }
+
+      if ($decorated = $definition->getDecoratedService()) {
+        $decorations->insert([$service_id, $definition], [$decorated[2], --$order]);
+      }
+    }
+
+    foreach ($decorations as list($service_id, $definition)) {
+      list($inner, $renamedId) = $definition->getDecoratedService();
+      if (!$renamedId) {
+        $renamedId = $service_id . '.inner';
+      }
+
+      $original = $container->getDefinition($inner);
+      if ($original->isPublic()) {
+        // The old service is renamed.
+        $original->setProperty('_serviceId', $renamedId);
+        // The decorating service takes over the old ID.
+        $definition->setProperty('_serviceId', $inner);
+      }
     }
   }
 
diff --git a/web/core/lib/Drupal/Core/File/FileSystemInterface.php b/web/core/lib/Drupal/Core/File/FileSystemInterface.php
index c1781b6944f4943906feefdbd6ae8eefc42edcb5..59d2ee37f0b7477390b815f1ca55380152fad258 100644
--- a/web/core/lib/Drupal/Core/File/FileSystemInterface.php
+++ b/web/core/lib/Drupal/Core/File/FileSystemInterface.php
@@ -37,14 +37,14 @@ interface FileSystemInterface {
    *
    * @see \Drupal\Core\File\FileSystemInterface::INSECURE_EXTENSION_REGEX
    */
-  public const INSECURE_EXTENSIONS = ['phar', 'php', 'pl', 'py', 'cgi', 'asp', 'js'];
+  public const INSECURE_EXTENSIONS = ['phar', 'php', 'pl', 'py', 'cgi', 'asp', 'js', 'htaccess'];
 
   /**
    * The regex pattern used when checking for insecure file types.
    *
    * @see \Drupal\Core\File\FileSystemInterface::INSECURE_EXTENSIONS
    */
-  public const INSECURE_EXTENSION_REGEX = '/\.(phar|php|pl|py|cgi|asp|js)(\.|$)/i';
+  public const INSECURE_EXTENSION_REGEX = '/\.(phar|php|pl|py|cgi|asp|js|htaccess)(\.|$)/i';
 
   /**
    * Moves an uploaded file to a new location.
diff --git a/web/core/lib/Drupal/Core/Form/FormBuilder.php b/web/core/lib/Drupal/Core/Form/FormBuilder.php
index 4ed0faed77bf6273dee48547466b3d0237f81dc1..98eb3263429675d8b0f7f98dc37d0697c7b183ca 100644
--- a/web/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/web/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -1217,7 +1217,12 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$
     // #access=FALSE on an element usually allow access for some users, so forms
     // submitted with self::submitForm() may bypass access restriction and be
     // treated as high-privilege users instead.
-    $process_input = empty($element['#disabled']) && !in_array($element['#type'], ['item', 'value'], TRUE) && (($form_state->isProgrammed() && $form_state->isBypassingProgrammedAccessChecks()) || ($form_state->isProcessingInput() && (!isset($element['#access']) || $element['#access'])));
+    $process_input = empty($element['#disabled']) &&
+      !in_array($element['#type'], ['item', 'value'], TRUE) &&
+      (
+        ($form_state->isProgrammed() && $form_state->isBypassingProgrammedAccessChecks()) ||
+        ($form_state->isProcessingInput() && (!isset($element['#access']) || (($element['#access'] instanceof AccessResultInterface && $element['#access']->isAllowed()) || ($element['#access'] === TRUE))))
+      );
 
     // Set the element's #value property.
     if (!isset($element['#value']) && !array_key_exists('#value', $element)) {
diff --git a/web/core/lib/Drupal/Core/Site/Settings.php b/web/core/lib/Drupal/Core/Site/Settings.php
index 31d494f8b49df889d2651755ff77816ce0091c5c..5509e2be26ca87007d39e484d38d10c81bbcdc25 100644
--- a/web/core/lib/Drupal/Core/Site/Settings.php
+++ b/web/core/lib/Drupal/Core/Site/Settings.php
@@ -207,7 +207,7 @@ public static function initialize($app_root, $site_path, &$class_loader) {
         // the database. Therefore, allow the connection info to specify an
         // autoload directory for the driver.
         if (isset($info['autoload'])) {
-          $class_loader->addPsr4($info['namespace'] . '\\', $info['autoload']);
+          $class_loader->addPsr4($info['namespace'] . '\\', $app_root . '/' . $info['autoload']);
         }
       }
     }
diff --git a/web/core/lib/Drupal/Core/StreamWrapper/PublicStream.php b/web/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
index e89e43219eab46b3fca9ec4310fe50dfc5d86d57..1747bf37c5f58ecb19582ddbe7d9e5926b0ba330 100644
--- a/web/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
+++ b/web/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
@@ -115,4 +115,28 @@ public static function basePath($site_path = NULL) {
     return Settings::get('file_public_path', $site_path . '/files');
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function getLocalPath($uri = NULL) {
+    $path = parent::getLocalPath($uri);
+    if (!$path || (strpos($path, 'vfs://') === 0)) {
+      return $path;
+    }
+
+    if (Settings::get('sa_core_2022_012_override') === TRUE) {
+      return $path;
+    }
+
+    $private_path = Settings::get('file_private_path');
+    if ($private_path) {
+      $private_path = realpath($private_path);
+      if ($private_path && strpos($path, $private_path) === 0) {
+        return FALSE;
+      }
+    }
+
+    return $path;
+  }
+
 }
diff --git a/web/core/modules/ckeditor5/config/schema/ckeditor5.schema.yml b/web/core/modules/ckeditor5/config/schema/ckeditor5.schema.yml
index b7c670a6832ce672f3a171cb8580f7f8f9ba14e9..c58dce3fed5ba9f56b08756678969f0ca529d5ae 100644
--- a/web/core/modules/ckeditor5/config/schema/ckeditor5.schema.yml
+++ b/web/core/modules/ckeditor5/config/schema/ckeditor5.schema.yml
@@ -127,7 +127,7 @@ ckeditor5.plugin.ckeditor5_list:
 # Plugin \Drupal\ckeditor5\Plugin\CKEditor5Plugin\Media
 ckeditor5.plugin.media_media:
   type: mapping
-  label: List
+  label: Media
   mapping:
     allow_view_mode_override:
       type: boolean
diff --git a/web/core/modules/config/src/Form/ConfigSingleExportForm.php b/web/core/modules/config/src/Form/ConfigSingleExportForm.php
index 22e0b4837f680f0e43dd92fb0a04cdbf906a66ce..dc46b45814d3d74be43605b5741b7da954735f10 100644
--- a/web/core/modules/config/src/Form/ConfigSingleExportForm.php
+++ b/web/core/modules/config/src/Form/ConfigSingleExportForm.php
@@ -136,7 +136,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $config_t
    */
   public function updateConfigurationType($form, FormStateInterface $form_state) {
     $form['config_name']['#options'] = $this->findConfiguration($form_state->getValue('config_type'));
-    unset($form['export']['#value']);
+    $form['export']['#value'] = NULL;
     return $form;
   }
 
diff --git a/web/core/modules/config/tests/config_override_test/src/ConfigOverrider.php b/web/core/modules/config/tests/config_override_test/src/ConfigOverrider.php
index c8ffc694b3f23729c518866ebf076b39ca7a763d..8ec572e3aeb55d577c97311eff6eb6fcf194c9bf 100644
--- a/web/core/modules/config/tests/config_override_test/src/ConfigOverrider.php
+++ b/web/core/modules/config/tests/config_override_test/src/ConfigOverrider.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Config\ConfigFactoryOverrideInterface;
+use Drupal\Core\Config\StorageInterface;
 
 /**
  * Tests module overrides for configuration.
diff --git a/web/core/modules/field/src/Plugin/migrate/process/d6/FieldInstanceSettings.php b/web/core/modules/field/src/Plugin/migrate/process/d6/FieldInstanceSettings.php
index be41a4209ca580bca911d6c253842f248f966b3c..ca5741b177090904fea66d4ebe47d2bcfce515cd 100644
--- a/web/core/modules/field/src/Plugin/migrate/process/d6/FieldInstanceSettings.php
+++ b/web/core/modules/field/src/Plugin/migrate/process/d6/FieldInstanceSettings.php
@@ -49,7 +49,7 @@ public function transform($value, MigrateExecutableInterface $migrate_executable
       case 'imagefield_widget':
         $settings['file_extensions'] = $widget_settings['file_extensions'];
         $settings['file_directory'] = $widget_settings['file_path'];
-        $settings['max_filesize'] = $this->convertSizeUnit($widget_settings['max_filesize_per_file']);
+        $settings['max_filesize'] = $this->convertSizeUnit($widget_settings['max_filesize_per_file'] ?? '');
         $settings['alt_field'] = $widget_settings['alt'];
         $settings['alt_field_required'] = $widget_settings['custom_alt'];
         $settings['title_field'] = $widget_settings['title'];
diff --git a/web/core/modules/field/tests/src/Unit/Plugin/migrate/process/d6/FieldInstanceSettingsTest.php b/web/core/modules/field/tests/src/Unit/Plugin/migrate/process/d6/FieldInstanceSettingsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..27f830a611e5c4ee81f4472bf93e2bc1934a79f3
--- /dev/null
+++ b/web/core/modules/field/tests/src/Unit/Plugin/migrate/process/d6/FieldInstanceSettingsTest.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace Drupal\Tests\field\Unit\Plugin\migrate\process\d6;
+
+use Drupal\field\Plugin\migrate\process\d6\FieldInstanceSettings;
+use Drupal\migrate\Plugin\MigrationInterface;
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\Row;
+use Drupal\Tests\UnitTestCase;
+
+// cspell:ignore imagefield
+
+/**
+ * @coversDefaultClass \Drupal\field\Plugin\migrate\process\d6\FieldInstanceSettings
+ * @group field
+ */
+class FieldInstanceSettingsTest extends UnitTestCase {
+
+  /**
+   * @covers ::getSettings
+   *
+   * @dataProvider getSettingsProvider
+   */
+  public function testGetSettings($field_type, $instance_settings, $expected) {
+    $instance_settings = unserialize($instance_settings);
+    $migration = $this->createMock(MigrationInterface::class);
+    $plugin = new FieldInstanceSettings([], 'd6_field_field_settings', [], $migration);
+
+    $executable = $this->createMock(MigrateExecutableInterface::class);
+    $row = $this->getMockBuilder(Row::class)
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $result = $plugin->transform([
+      $field_type,
+      $instance_settings,
+      NULL,
+    ], $executable, $row, 'foo');
+    $this->assertSame($expected, $result);
+  }
+
+  /**
+   * Provides field settings for testGetSettings().
+   */
+  public function getSettingsProvider() {
+    return [
+      'imagefield size set' => [
+        'imagefield_widget',
+        'a:14:{s:15:"file_extensions";s:11:"gif jpg png";s:9:"file_path";N;s:18:"progress_indicator";N;s:21:"max_filesize_per_file";s:3:"10M";s:21:"max_filesize_per_node";N;s:14:"max_resolution";N;s:14:"min_resolution";N;s:3:"alt";N;s:10:"custom_alt";i:1;s:5:"title";N;s:12:"custom_title";i:1;s:10:"title_type";N;s:13:"default_image";N;s:17:"use_default_image";N;}',
+        [
+          'file_extensions' => 'gif jpg png',
+          'file_directory' => NULL,
+          'max_filesize' => '10MB',
+          'alt_field' => NULL,
+          'alt_field_required' => 1,
+          'title_field' => NULL,
+          'title_field_required' => 1,
+          'max_resolution' => '',
+          'min_resolution' => '',
+        ],
+      ],
+      'imagefield size NULL' => [
+        'imagefield_widget',
+        'a:14:{s:15:"file_extensions";s:11:"gif jpg png";s:9:"file_path";N;s:18:"progress_indicator";N;s:21:"max_filesize_per_file";N;s:21:"max_filesize_per_node";N;s:14:"max_resolution";N;s:14:"min_resolution";N;s:3:"alt";N;s:10:"custom_alt";i:1;s:5:"title";N;s:12:"custom_title";i:1;s:10:"title_type";N;s:13:"default_image";N;s:17:"use_default_image";N;}',
+        [
+          'file_extensions' => 'gif jpg png',
+          'file_directory' => NULL,
+          'max_filesize' => '',
+          'alt_field' => NULL,
+          'alt_field_required' => 1,
+          'title_field' => NULL,
+          'title_field_required' => 1,
+          'max_resolution' => '',
+          'min_resolution' => '',
+        ],
+      ],
+
+    ];
+  }
+
+}
diff --git a/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonAnonTest.php b/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonAnonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..128c50ebe0801c8553a2e824e13625422d59b6fb
--- /dev/null
+++ b/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonAnonTest.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Drupal\Tests\hal\Functional\quickedit;
+
+use Drupal\Tests\hal\Functional\layout_builder\LayoutBuilderEntityViewDisplayHalJsonAnonTest;
+
+/**
+ * @group hal
+ * @group legacy
+ */
+class QuickEditLayoutBuilderEntityViewDisplayHalJsonAnonTest extends LayoutBuilderEntityViewDisplayHalJsonAnonTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonBasicAuthTest.php b/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonBasicAuthTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ec69ae947ba9ad841df96c29c1d98877d8dceec
--- /dev/null
+++ b/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonBasicAuthTest.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Drupal\Tests\hal\Functional\quickedit;
+
+use Drupal\Tests\hal\Functional\layout_builder\LayoutBuilderEntityViewDisplayHalJsonBasicAuthTest;
+
+/**
+ * @group hal
+ * @group legacy
+ */
+class QuickEditLayoutBuilderEntityViewDisplayHalJsonBasicAuthTest extends LayoutBuilderEntityViewDisplayHalJsonBasicAuthTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonCookieTest.php b/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonCookieTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e9520663a1c952c189177fa7401d3315978ad28
--- /dev/null
+++ b/web/core/modules/hal/tests/src/Functional/quickedit/QuickEditLayoutBuilderEntityViewDisplayHalJsonCookieTest.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Drupal\Tests\hal\Functional\quickedit;
+
+use Drupal\Tests\hal\Functional\layout_builder\LayoutBuilderEntityViewDisplayHalJsonCookieTest;
+
+/**
+ * @group hal
+ * @group legacy
+ */
+class QuickEditLayoutBuilderEntityViewDisplayHalJsonCookieTest extends LayoutBuilderEntityViewDisplayHalJsonCookieTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/image/src/Controller/ImageStyleDownloadController.php b/web/core/modules/image/src/Controller/ImageStyleDownloadController.php
index 6ded44fab6b47f63cea902288de181bc6fac99b2..c943452b5b8c2b7ff64d8d3e13097cb61ef51c77 100644
--- a/web/core/modules/image/src/Controller/ImageStyleDownloadController.php
+++ b/web/core/modules/image/src/Controller/ImageStyleDownloadController.php
@@ -6,6 +6,7 @@
 use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\Image\ImageFactory;
 use Drupal\Core\Lock\LockBackendInterface;
+use Drupal\Core\Site\Settings;
 use Drupal\Core\StreamWrapper\StreamWrapperManager;
 use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
 use Drupal\image\ImageStyleInterface;
@@ -114,21 +115,25 @@ public function deliver(Request $request, $scheme, ImageStyleInterface $image_st
     $target = $request->query->get('file');
     $image_uri = $scheme . '://' . $target;
 
-    // Check that the style is defined, the scheme is valid, and the image
-    // derivative token is valid. Sites which require image derivatives to be
-    // generated without a token can set the
+    // Check that the style is defined and the scheme is valid.
+    $valid = !empty($image_style) && $this->streamWrapperManager->isValidScheme($scheme);
+
+    // Also validate the derivative token. Sites which require image
+    // derivatives to be generated without a token can set the
     // 'image.settings:allow_insecure_derivatives' configuration to TRUE to
-    // bypass the latter check, but this will increase the site's vulnerability
+    // bypass this check, but this will increase the site's vulnerability
     // to denial-of-service attacks. To prevent this variable from leaving the
     // site vulnerable to the most serious attacks, a token is always required
     // when a derivative of a style is requested.
     // The $target variable for a derivative of a style has
     // styles/<style_name>/... as structure, so we check if the $target variable
     // starts with styles/.
-    $valid = !empty($image_style) && $this->streamWrapperManager->isValidScheme($scheme);
+    $token = $request->query->get(IMAGE_DERIVATIVE_TOKEN, '');
+    $token_is_valid = hash_equals($image_style->getPathToken($image_uri), $token);
     if (!$this->config('image.settings')->get('allow_insecure_derivatives') || strpos(ltrim($target, '\/'), 'styles/') === 0) {
-      $valid &= hash_equals($image_style->getPathToken($image_uri), $request->query->get(IMAGE_DERIVATIVE_TOKEN, ''));
+      $valid = $valid && $token_is_valid;
     }
+
     if (!$valid) {
       // Return a 404 (Page Not Found) rather than a 403 (Access Denied) as the
       // image token is for DDoS protection rather than access checking. 404s
@@ -138,11 +143,23 @@ public function deliver(Request $request, $scheme, ImageStyleInterface $image_st
     }
 
     $derivative_uri = $image_style->buildUri($image_uri);
+    $derivative_scheme = $this->streamWrapperManager->getScheme($derivative_uri);
+
+    if ($token_is_valid) {
+      $is_public = ($scheme !== 'private');
+    }
+    else {
+      $core_schemes = ['public', 'private', 'temporary'];
+      $additional_public_schemes = array_diff(Settings::get('file_additional_public_schemes', []), $core_schemes);
+      $public_schemes = array_merge(['public'], $additional_public_schemes);
+      $is_public = in_array($derivative_scheme, $public_schemes, TRUE);
+    }
+
     $headers = [];
 
-    // If using the private scheme, let other modules provide headers and
+    // If not using a public scheme, let other modules provide headers and
     // control access to the file.
-    if ($scheme == 'private') {
+    if (!$is_public) {
       $headers = $this->moduleHandler()->invokeAll('file_download', [$image_uri]);
       if (in_array(-1, $headers) || empty($headers)) {
         throw new AccessDeniedHttpException();
@@ -150,14 +167,14 @@ public function deliver(Request $request, $scheme, ImageStyleInterface $image_st
     }
 
     // Don't try to generate file if source is missing.
-    if (!file_exists($image_uri)) {
+    if (!$this->sourceImageExists($image_uri, $token_is_valid)) {
       // If the image style converted the extension, it has been added to the
       // original file, resulting in filenames like image.png.jpeg. So to find
       // the actual source image, we remove the extension and check if that
       // image exists.
       $path_info = pathinfo(StreamWrapperManager::getTarget($image_uri));
       $converted_image_uri = sprintf('%s://%s%s%s', $this->streamWrapperManager->getScheme($derivative_uri), $path_info['dirname'], DIRECTORY_SEPARATOR, $path_info['filename']);
-      if (!file_exists($converted_image_uri)) {
+      if (!$this->sourceImageExists($converted_image_uri, $token_is_valid)) {
         $this->logger->notice('Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', ['%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri]);
         return new Response($this->t('Error generating image, missing source file.'), 404);
       }
@@ -196,9 +213,9 @@ public function deliver(Request $request, $scheme, ImageStyleInterface $image_st
       ];
       // \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
       // sets response as not cacheable if the Cache-Control header is not
-      // already modified. We pass in FALSE for non-private schemes for the
-      // $public parameter to make sure we don't change the headers.
-      return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
+      // already modified. When $is_public is TRUE, the following sets the
+      // Cache-Control header to "public".
+      return new BinaryFileResponse($uri, 200, $headers, $is_public);
     }
     else {
       $this->logger->notice('Unable to generate the derived image located at %path.', ['%path' => $derivative_uri]);
@@ -206,4 +223,43 @@ public function deliver(Request $request, $scheme, ImageStyleInterface $image_st
     }
   }
 
+  /**
+   * Checks whether the provided source image exists.
+   *
+   * @param string $image_uri
+   *   The URI for the source image.
+   * @param bool $token_is_valid
+   *   Whether a valid image token was supplied.
+   *
+   * @return bool
+   *   Whether the source image exists.
+   */
+  private function sourceImageExists(string $image_uri, bool $token_is_valid): bool {
+    $exists = file_exists($image_uri);
+
+    // If the file doesn't exist, we can stop here.
+    if (!$exists) {
+      return FALSE;
+    }
+
+    if ($token_is_valid) {
+      return TRUE;
+    }
+
+    if (StreamWrapperManager::getScheme($image_uri) !== 'public') {
+      return TRUE;
+    }
+
+    $image_path = $this->fileSystem->realpath($image_uri);
+    $private_path = Settings::get('file_private_path');
+    if ($private_path) {
+      $private_path = realpath($private_path);
+      if ($private_path && strpos($image_path, $private_path) === 0) {
+        return FALSE;
+      }
+    }
+
+    return TRUE;
+  }
+
 }
diff --git a/web/core/modules/jsonapi/src/Normalizer/ResourceObjectNormalizer.php b/web/core/modules/jsonapi/src/Normalizer/ResourceObjectNormalizer.php
index e4988c9096e98ed40d79f30d0db0ba0be187690e..340fcb21bd92f1663bd8565da249d98324825ca9 100644
--- a/web/core/modules/jsonapi/src/Normalizer/ResourceObjectNormalizer.php
+++ b/web/core/modules/jsonapi/src/Normalizer/ResourceObjectNormalizer.php
@@ -192,7 +192,7 @@ protected function serializeField($field, array $context, $format) {
       // @todo Replace this workaround after https://www.drupal.org/node/3043245
       //   or remove the need for this in https://www.drupal.org/node/2942975.
       //   See \Drupal\layout_builder\Normalizer\LayoutEntityDisplayNormalizer.
-      if ($context['resource_object']->getResourceType()->getDeserializationTargetClass() === 'Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay' && $context['resource_object']->getField('third_party_settings') === $field) {
+      if (is_a($context['resource_object']->getResourceType()->getDeserializationTargetClass(), 'Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay', TRUE) && $context['resource_object']->getField('third_party_settings') === $field) {
         unset($field['layout_builder']['sections']);
       }
 
diff --git a/web/core/modules/layout_builder/layout_builder.module b/web/core/modules/layout_builder/layout_builder.module
index 6e8d0a25f93a20a25303b4cfbb3f6f1f63c55a8f..1646139aa7bf8aed43d3d91c698a6311746a7215 100644
--- a/web/core/modules/layout_builder/layout_builder.module
+++ b/web/core/modules/layout_builder/layout_builder.module
@@ -26,7 +26,6 @@
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Access\AccessResult;
 use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
-use Drupal\layout_builder\QuickEditIntegration;
 
 /**
  * Implements hook_help().
@@ -162,12 +161,6 @@ function layout_builder_entity_view_alter(array &$build, EntityInterface $entity
   if ($display instanceof LayoutBuilderEntityViewDisplay && strpos($route_name, 'layout_builder.') === 0) {
     unset($build['#contextual_links']);
   }
-
-  if (\Drupal::moduleHandler()->moduleExists('quickedit')) {
-    /** @var \Drupal\layout_builder\QuickEditIntegration $quick_edit_integration */
-    $quick_edit_integration = \Drupal::classResolver(QuickEditIntegration::class);
-    $quick_edit_integration->entityViewAlter($build, $entity, $display);
-  }
 }
 
 /**
@@ -351,15 +344,6 @@ function layout_builder_system_breadcrumb_alter(Breadcrumb &$breadcrumb, RouteMa
   }
 }
 
-/**
- * Implements hook_quickedit_render_field().
- */
-function layout_builder_quickedit_render_field(EntityInterface $entity, $field_name, $view_mode_id, $langcode) {
-  /** @var \Drupal\layout_builder\QuickEditIntegration $quick_edit_integration */
-  $quick_edit_integration = \Drupal::classResolver(QuickEditIntegration::class);
-  return $quick_edit_integration->quickEditRenderField($entity, $field_name, $view_mode_id, $langcode);
-}
-
 /**
  * Implements hook_entity_translation_create().
  */
diff --git a/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php b/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
index d543fe1619557edbaf532c41c700706515218e93..c63b96ff01d50d12991ae7f893fbd07436fed4fc 100644
--- a/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
+++ b/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
@@ -18,7 +18,6 @@
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\layout_builder\LayoutEntityHelperTrait;
 use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
-use Drupal\layout_builder\QuickEditIntegration;
 use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionComponent;
 use Drupal\layout_builder\SectionListTrait;
@@ -473,7 +472,7 @@ private function sectionStorageManager() {
    * {@inheritdoc}
    */
   public function getComponent($name) {
-    if ($this->isLayoutBuilderEnabled() && $section_component = $this->getQuickEditSectionComponent() ?: $this->getSectionComponentForFieldName($name)) {
+    if ($this->isLayoutBuilderEnabled() && $section_component = $this->getSectionComponentForFieldName($name)) {
       $plugin = $section_component->getPlugin();
       if ($plugin instanceof ConfigurableInterface) {
         $configuration = $plugin->getConfiguration();
@@ -485,43 +484,6 @@ public function getComponent($name) {
     return parent::getComponent($name);
   }
 
-  /**
-   * Returns the Quick Edit formatter settings.
-   *
-   * @return \Drupal\layout_builder\SectionComponent|null
-   *   The section component if it is available.
-   *
-   * @see \Drupal\layout_builder\QuickEditIntegration::entityViewAlter()
-   * @see \Drupal\quickedit\MetadataGenerator::generateFieldMetadata()
-   */
-  private function getQuickEditSectionComponent() {
-    // To determine the Quick Edit view_mode ID we need an originalMode set.
-    if ($original_mode = $this->getOriginalMode()) {
-      $parts = explode('-', $original_mode);
-      // The Quick Edit view mode ID is created by
-      // \Drupal\layout_builder\QuickEditIntegration::entityViewAlter()
-      // concatenating together the information we need to retrieve the Layout
-      // Builder component. It follows the structure prescribed by the
-      // documentation of hook_quickedit_render_field().
-      if (count($parts) === 6 && $parts[0] === 'layout_builder') {
-        [, $delta, $component_uuid, $entity_id] = QuickEditIntegration::deconstructViewModeId($original_mode);
-        $entity = $this->entityTypeManager()->getStorage($this->getTargetEntityTypeId())->load($entity_id);
-        $sections = $this->getEntitySections($entity);
-        if (isset($sections[$delta])) {
-          $component = $sections[$delta]->getComponent($component_uuid);
-          $plugin = $component->getPlugin();
-          // We only care about FieldBlock because these are only components
-          // that provide Quick Edit integration: Quick Edit enables in-place
-          // editing of fields of entities, not of anything else.
-          if ($plugin instanceof DerivativeInspectionInterface && $plugin->getBaseId() === 'field_block') {
-            return $component;
-          }
-        }
-      }
-    }
-    return NULL;
-  }
-
   /**
    * Gets the component for a given field name if any.
    *
diff --git a/web/core/modules/layout_builder/src/InlineBlockEntityOperations.php b/web/core/modules/layout_builder/src/InlineBlockEntityOperations.php
index ad255cd6fecf9906252463f23f142216215959c7..5b11bbe674833d785c7e5784dfbd18eea73d6a21 100644
--- a/web/core/modules/layout_builder/src/InlineBlockEntityOperations.php
+++ b/web/core/modules/layout_builder/src/InlineBlockEntityOperations.php
@@ -44,18 +44,12 @@ class InlineBlockEntityOperations implements ContainerInjectionInterface {
   /**
    * Constructs a new EntityOperations object.
    *
-   * @todo This constructor has one optional parameter, $section_storage_manager
-   *    and one totally unused $database parameter. Deprecate the current
-   *    constructor signature in https://www.drupal.org/node/3031492 after the
-   *    general policy for constructor backwards compatibility is determined in
-   *    https://www.drupal.org/node/3030640.
-   *
    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
    *   The entity type manager service.
    * @param \Drupal\layout_builder\InlineBlockUsageInterface $usage
    *   Inline block usage tracking service.
    * @param \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface $section_storage_manager
-   *   (optional) The section storage manager.
+   *   The section storage manager.
    */
   public function __construct(EntityTypeManagerInterface $entityTypeManager, InlineBlockUsageInterface $usage, SectionStorageManagerInterface $section_storage_manager) {
     $this->entityTypeManager = $entityTypeManager;
diff --git a/web/core/modules/layout_builder/src/QuickEditIntegration.php b/web/core/modules/layout_builder/src/QuickEditIntegration.php
index c087f90971f5e7759bd0ff91c1a10317685391f3..90c082ae8802a72979f17f0b78d99109f0d01208 100644
--- a/web/core/modules/layout_builder/src/QuickEditIntegration.php
+++ b/web/core/modules/layout_builder/src/QuickEditIntegration.php
@@ -2,21 +2,9 @@
 
 namespace Drupal\layout_builder;
 
-use Drupal\Component\Utility\NestedArray;
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Entity\FieldableEntityInterface;
-use Drupal\Core\Logger\LoggerChannelTrait;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\Plugin\Context\EntityContext;
-use Drupal\Core\Render\Element;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+@trigger_error(__NAMESPACE__ . '\QuickEditIntegration is deprecated in drupal:9.4.2 and is removed from drupal:10.0.0. Instead, use \Drupal\quickedit\LayoutBuilderIntegration. See https://www.drupal.org/node/3265518', E_USER_DEPRECATED);
+
+use Drupal\quickedit\LayoutBuilderIntegration;
 
 /**
  * Helper methods for Quick Edit module integration.
@@ -24,298 +12,4 @@
  * @internal
  *   This is an internal utility class wrapping hook implementations.
  */
-class QuickEditIntegration implements ContainerInjectionInterface {
-
-  use LoggerChannelTrait;
-
-  /**
-   * The section storage manager.
-   *
-   * @var \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface
-   */
-  protected $sectionStorageManager;
-
-  /**
-   * The current user.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $currentUser;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a new QuickEditIntegration object.
-   *
-   * @param \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface $section_storage_manager
-   *   The section storage manager.
-   * @param \Drupal\Core\Session\AccountInterface $current_user
-   *   The current user.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   */
-  public function __construct(SectionStorageManagerInterface $section_storage_manager, AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager) {
-    $this->sectionStorageManager = $section_storage_manager;
-    $this->currentUser = $current_user;
-    $this->entityTypeManager = $entity_type_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('plugin.manager.layout_builder.section_storage'),
-      $container->get('current_user'),
-      $container->get('entity_type.manager')
-    );
-  }
-
-  /**
-   * Alters the entity view build for Quick Edit compatibility.
-   *
-   * When rendering fields outside of normal view modes, Quick Edit requires
-   * that modules identify themselves with a view mode ID in the format
-   * [module_name]-[information the module needs to rerender], as prescribed by
-   * hook_quickedit_render_field().
-   *
-   * @param array $build
-   *   The built entity render array.
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity.
-   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
-   *   The entity view display.
-   *
-   * @see hook_quickedit_render_field()
-   * @see layout_builder_quickedit_render_field()
-   */
-  public function entityViewAlter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
-    if (!$entity instanceof FieldableEntityInterface || !isset($build['_layout_builder'])) {
-      return;
-    }
-
-    $build['#cache']['contexts'][] = 'user.permissions';
-    if (!$this->currentUser->hasPermission('access in-place editing')) {
-      return;
-    }
-
-    $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
-    $section_list = $this->sectionStorageManager->findByContext(
-      [
-        'display' => EntityContext::fromEntity($display),
-        'entity' => EntityContext::fromEntity($entity),
-        'view_mode' => new Context(new ContextDefinition('string'), $display->getMode()),
-      ],
-      $cacheable_metadata
-    );
-    $cacheable_metadata->applyTo($build);
-
-    if (empty($section_list)) {
-      return;
-    }
-
-    // Create a hash of the sections and use it in the unique Quick Edit view
-    // mode ID. Any changes to the sections will result in a different hash,
-    // forcing Quick Edit's JavaScript to recognize any changes and retrieve
-    // up-to-date metadata.
-    $sections_hash = hash('sha256', serialize($section_list->getSections()));
-
-    // Track each component by their plugin ID, delta, region, and UUID.
-    $plugin_ids_to_update = [];
-    foreach (Element::children($build['_layout_builder']) as $delta) {
-      $section = $build['_layout_builder'][$delta];
-
-      if (!Element::isEmpty($section)) {
-        /** @var \Drupal\Core\Layout\LayoutDefinition $layout */
-        $layout = $section['#layout'];
-        $regions = $layout->getRegionNames();
-
-        foreach ($regions as $region) {
-          if (isset($section[$region])) {
-            foreach ($section[$region] as $uuid => $component) {
-              if (isset($component['#plugin_id']) && $this->supportQuickEditOnComponent($component, $entity)) {
-                $plugin_ids_to_update[$component['#plugin_id']][$delta][$region][$uuid] = $uuid;
-              }
-            }
-          }
-        }
-      }
-    }
-
-    // @todo Remove when https://www.drupal.org/node/3041850 is resolved.
-    $plugin_ids_to_update = array_filter($plugin_ids_to_update, function ($info) {
-      // Delta, region, and UUID each count as one.
-      return count($info, COUNT_RECURSIVE) === 3;
-    });
-
-    $plugin_ids_to_update = NestedArray::mergeDeepArray($plugin_ids_to_update, TRUE);
-    foreach ($plugin_ids_to_update as $delta => $regions) {
-      foreach ($regions as $region => $uuids) {
-        foreach ($uuids as $uuid => $component) {
-          $build['_layout_builder'][$delta][$region][$uuid]['content']['#view_mode'] = static::getViewModeId($entity, $display, $delta, $uuid, $sections_hash);
-        }
-      }
-    }
-    // Alter the Quick Edit view mode ID of all fields outside of the Layout
-    // Builder sections to force Quick Edit to request to the field metadata.
-    // @todo Remove this logic in https://www.drupal.org/project/node/2966136.
-    foreach (Element::children($build) as $field_name) {
-      if ($field_name !== '_layout_builder') {
-        $field_build = &$build[$field_name];
-        if (isset($field_build['#view_mode'])) {
-          $field_build['#view_mode'] = "layout_builder-{$display->getMode()}-non_component-$sections_hash";
-        }
-      }
-    }
-  }
-
-  /**
-   * Generates a Quick Edit view mode ID.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity.
-   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
-   *   The entity view display.
-   * @param int $delta
-   *   The delta.
-   * @param string $component_uuid
-   *   The component UUID.
-   * @param string $sections_hash
-   *   The hash of the sections; must change whenever the sections change.
-   *
-   * @return string
-   *   The Quick Edit view mode ID.
-   *
-   * @see \Drupal\layout_builder\QuickEditIntegration::deconstructViewModeId()
-   */
-  private static function getViewModeId(EntityInterface $entity, EntityViewDisplayInterface $display, $delta, $component_uuid, $sections_hash) {
-    return implode('-', [
-      'layout_builder',
-      $display->getMode(),
-      $delta,
-      // Replace the dashes in the component UUID because we need to
-      // use dashes to join the parts.
-      str_replace('-', '_', $component_uuid),
-      $entity->id(),
-      $sections_hash,
-    ]);
-  }
-
-  /**
-   * Deconstructs the Quick Edit view mode ID into its constituent parts.
-   *
-   * @param string $quick_edit_view_mode_id
-   *   The Quick Edit view mode ID.
-   *
-   * @return array
-   *   An array containing the entity view mode ID, the delta, the component
-   *   UUID, and the entity ID.
-   *
-   * @see \Drupal\layout_builder\QuickEditIntegration::getViewModeId()
-   */
-  public static function deconstructViewModeId($quick_edit_view_mode_id) {
-    [, $entity_view_mode_id, $delta, $component_uuid, $entity_id] = explode('-', $quick_edit_view_mode_id, 7);
-    return [
-      $entity_view_mode_id,
-      // @todo Explicitly cast delta to an integer, remove this in
-      //   https://www.drupal.org/project/drupal/issues/2984509.
-      (int) $delta,
-      // Replace the underscores with dash to get back the component UUID.
-      str_replace('_', '-', $component_uuid),
-      $entity_id,
-    ];
-  }
-
-  /**
-   * Re-renders a field rendered by Layout Builder, edited with Quick Edit.
-   *
-   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
-   *   The entity.
-   * @param string $field_name
-   *   The field name.
-   * @param string $quick_edit_view_mode_id
-   *   The Quick Edit view mode ID.
-   * @param string $langcode
-   *   The language code.
-   *
-   * @return array
-   *   The re-rendered field.
-   */
-  public function quickEditRenderField(FieldableEntityInterface $entity, $field_name, $quick_edit_view_mode_id, $langcode) {
-    [$entity_view_mode, $delta, $component_uuid] = static::deconstructViewModeId($quick_edit_view_mode_id);
-
-    $entity_build = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId())->view($entity, $entity_view_mode, $langcode);
-    $this->buildEntityView($entity_build);
-
-    if (isset($entity_build['_layout_builder'][$delta])) {
-      foreach (Element::children($entity_build['_layout_builder'][$delta]) as $region) {
-        if (isset($entity_build['_layout_builder'][$delta][$region][$component_uuid])) {
-          return $entity_build['_layout_builder'][$delta][$region][$component_uuid]['content'];
-        }
-      }
-    }
-
-    $this->getLogger('layout_builder')->warning('The field "%field" failed to render.', ['%field' => $field_name]);
-    return [];
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Replace this hardcoded processing when
-   *   https://www.drupal.org/project/drupal/issues/3041635 is resolved.
-   *
-   * @see \Drupal\Tests\EntityViewTrait::buildEntityView()
-   */
-  private function buildEntityView(array &$elements) {
-    // If the default values for this element have not been loaded yet,
-    // populate them.
-    if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
-      $elements += \Drupal::service('element_info')->getInfo($elements['#type']);
-    }
-
-    // Make any final changes to the element before it is rendered. This means
-    // that the $element or the children can be altered or corrected before
-    // the element is rendered into the final text.
-    if (isset($elements['#pre_render'])) {
-      foreach ($elements['#pre_render'] as $callable) {
-        $elements = call_user_func($callable, $elements);
-      }
-    }
-
-    // And recurse.
-    $children = Element::children($elements, TRUE);
-    foreach ($children as $key) {
-      $this->buildEntityView($elements[$key]);
-    }
-  }
-
-  /**
-   * Determines whether a component has Quick Edit support.
-   *
-   * Only field_block components for display configurable fields should be
-   * supported.
-   *
-   * @param array $component
-   *   The component render array.
-   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
-   *   The entity being displayed.
-   *
-   * @return bool
-   *   Whether Quick Edit is supported on the component.
-   *
-   * @see \Drupal\layout_builder\Plugin\Block\FieldBlock
-   */
-  private function supportQuickEditOnComponent(array $component, FieldableEntityInterface $entity) {
-    if (isset($component['content']['#field_name'], $component['#base_plugin_id']) && $component['#base_plugin_id'] === 'field_block' && $entity->hasField($component['content']['#field_name'])) {
-      return $entity->getFieldDefinition($component['content']['#field_name'])->isDisplayConfigurable('view');
-    }
-    return FALSE;
-  }
-
-}
+class QuickEditIntegration extends LayoutBuilderIntegration {}
diff --git a/web/core/modules/media/src/Controller/OEmbedIframeController.php b/web/core/modules/media/src/Controller/OEmbedIframeController.php
index 5e7b12ff3766092d54e0abe0a19f3e76ef2a4a15..9da8f90502305f4e364d343db9a69d071dcdf554 100644
--- a/web/core/modules/media/src/Controller/OEmbedIframeController.php
+++ b/web/core/modules/media/src/Controller/OEmbedIframeController.php
@@ -116,10 +116,23 @@ public static function create(ContainerInterface $container) {
    *   The response object.
    *
    * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
-   *   Will be thrown if the 'hash' parameter does not match the expected hash
-   *   of the 'url' parameter.
+   *   Will be thrown if either
+   *   - the 'hash' parameter does not match the expected hash of the 'url'
+   *     parameter;
+   *   - the iframe_domain is set in media.settings and does not match the host
+   *     in the request.
    */
   public function render(Request $request) {
+    // @todo Move domain check logic to a separate method.
+    $allowed_domain = \Drupal::config('media.settings')->get('iframe_domain');
+    if ($allowed_domain) {
+      $allowed_host = parse_url($allowed_domain, PHP_URL_HOST);
+      $host = parse_url($request->getSchemeAndHttpHost(), PHP_URL_HOST);
+      if ($allowed_host !== $host) {
+        throw new AccessDeniedHttpException('This resource is not available');
+      }
+    }
+
     $url = $request->query->get('url');
     $max_width = $request->query->getInt('max_width');
     $max_height = $request->query->getInt('max_height');
diff --git a/web/core/modules/migrate/tests/src/Functional/process/DownloadFunctionalTest.php b/web/core/modules/migrate/tests/src/Functional/process/DownloadFunctionalTest.php
index 26f2f3527fcbc5cb4b62fdcf095084ea558b5aba..51371ff69c839614dd647618700e46549e619cb1 100644
--- a/web/core/modules/migrate/tests/src/Functional/process/DownloadFunctionalTest.php
+++ b/web/core/modules/migrate/tests/src/Functional/process/DownloadFunctionalTest.php
@@ -76,8 +76,11 @@ public function testExceptionThrow() {
     $this->assertCount(1, $messages);
     $message = reset($messages);
 
+    // Assert critical parts of the error message, but not the exact message,
+    // since it depends on Guzzle's internal implementation of PSR-7.
     $id = $migration->getPluginId();
-    $this->assertEquals("$id:uri:download: Client error: `GET $invalid_url` resulted in a `404 Not Found` response ($invalid_url)", $message->message);
+    $this->assertStringContainsString("$id:uri:download:", $message->message);
+    $this->assertStringContainsString($invalid_url, $message->message);
     $this->assertEquals(MigrationInterface::MESSAGE_ERROR, $message->level);
 
     // Check that the second row was migrated successfully.
diff --git a/web/core/modules/node/src/Plugin/views/argument/Vid.php b/web/core/modules/node/src/Plugin/views/argument/Vid.php
index 84c31fd1cd3d593aab6e1f53a74d469a0471a5a3..c5a35fc3143f2d0b617df30752edf435bf7bedb9 100644
--- a/web/core/modules/node/src/Plugin/views/argument/Vid.php
+++ b/web/core/modules/node/src/Plugin/views/argument/Vid.php
@@ -75,6 +75,7 @@ public function titleQuery() {
       ->accessCheck(FALSE)
       ->allRevisions()
       ->groupBy('title')
+      ->condition('vid', $this->value, 'IN')
       ->execute();
 
     foreach ($results as $result) {
diff --git a/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_id_argument.yml b/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_id_argument.yml
index e2ac01afd90bbc2d3f463b54bd9942ccea8bf8ba..bf13bdfad00dd50557d8c19be92a166217a6891b 100644
--- a/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_id_argument.yml
+++ b/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_id_argument.yml
@@ -13,45 +13,12 @@ base_table: node_field_data
 base_field: nid
 display:
   default:
-    display_plugin: default
     id: default
     display_title: Default
+    display_plugin: default
     position: 0
     display_options:
-      access:
-        type: perm
-        options:
-          perm: 'access content'
-      cache:
-        type: tag
-        options: {  }
-      query:
-        type: views_query
-        options:
-          disable_sql_rewrite: false
-          distinct: false
-          replica: false
-          query_comment: ''
-          query_tags: {  }
-      exposed_form:
-        type: basic
-        options:
-          submit_button: Apply
-          reset_button: false
-          reset_button_label: Reset
-          exposed_sorts_label: 'Sort by'
-          expose_sort_order: true
-          sort_asc_label: Asc
-          sort_desc_label: Desc
-      pager:
-        type: none
-        options:
-          items_per_page: null
-          offset: 0
-      style:
-        type: default
-      row:
-        type: fields
+      title: test_node_revision_id_argument
       fields:
         title:
           id: title
@@ -60,6 +27,9 @@ display:
           relationship: none
           group_type: group
           admin_label: ''
+          entity_type: node
+          entity_field: title
+          plugin_id: field
           label: ''
           exclude: false
           alter:
@@ -115,16 +85,30 @@ display:
           multi_type: separator
           separator: ', '
           field_api_classes: false
-          entity_type: node
-          entity_field: title
-          plugin_id: field
-      filters: {  }
-      sorts: {  }
-      title: test_node_revision_id_argument
-      header: {  }
-      footer: {  }
+      pager:
+        type: none
+        options:
+          offset: 0
+          items_per_page: null
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: tag
+        options: {  }
       empty: {  }
-      relationships: {  }
+      sorts: {  }
       arguments:
         vid:
           id: vid
@@ -133,13 +117,16 @@ display:
           relationship: none
           group_type: group
           admin_label: ''
+          entity_type: node
+          entity_field: vid
+          plugin_id: node_vid
           default_action: ignore
           exception:
             value: all
             title_enable: false
             title: All
-          title_enable: false
-          title: ''
+          title_enable: true
+          title: '{{ arguments.vid }}'
           default_argument_type: fixed
           default_argument_options:
             argument: ''
@@ -147,8 +134,8 @@ display:
           summary_options:
             base_path: ''
             count: true
-            items_per_page: 25
             override: false
+            items_per_page: 25
           summary:
             sort_order: asc
             number_of_records: 0
@@ -160,38 +147,51 @@ display:
           validate_options: {  }
           break_phrase: false
           not: false
-          entity_type: node
-          entity_field: vid
-          plugin_id: node_vid
-      display_extenders: {  }
+      filters: {  }
       filter_groups:
         operator: AND
         groups: {  }
+      style:
+        type: default
+      row:
+        type: fields
+      query:
+        type: views_query
+        options:
+          query_comment: ''
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_tags: {  }
+      relationships: {  }
+      header: {  }
+      footer: {  }
+      display_extenders: {  }
     cache_metadata:
+      max-age: -1
       contexts:
         - 'languages:language_content'
         - 'languages:language_interface'
         - url
         - 'user.node_grants:view'
         - user.permissions
-      cacheable: false
-      max-age: -1
       tags: {  }
+      cacheable: false
   page_1:
-    display_plugin: page
     id: page_1
     display_title: Page
+    display_plugin: page
     position: 1
     display_options:
       display_extenders: {  }
       path: test-revision-vid-argument
     cache_metadata:
+      max-age: -1
       contexts:
         - 'languages:language_content'
         - 'languages:language_interface'
         - url
         - 'user.node_grants:view'
         - user.permissions
-      cacheable: false
-      max-age: -1
       tags: {  }
+      cacheable: false
diff --git a/web/core/modules/node/tests/src/Kernel/Views/ArgumentNodeRevisionIdTest.php b/web/core/modules/node/tests/src/Kernel/Views/ArgumentNodeRevisionIdTest.php
index 9d3898544e5e9f07d813ecb653512db83ea8e2cc..62dbe92be9b659f2dc36e6b69de3e47b825afb4b 100644
--- a/web/core/modules/node/tests/src/Kernel/Views/ArgumentNodeRevisionIdTest.php
+++ b/web/core/modules/node/tests/src/Kernel/Views/ArgumentNodeRevisionIdTest.php
@@ -46,13 +46,16 @@ public function testNodeRevisionRelationship() {
     NodeType::create(['type' => 'page', 'name' => 'page'])->save();
     $node = Node::create(['type' => 'page', 'title' => 'test1', 'uid' => 1]);
     $node->save();
+    $first_revision_id = $node->getRevisionId();
     $node->setNewRevision();
     $node->setTitle('test2');
     $node->save();
+    $second_revision_id = $node->getRevisionId();
 
     $view_nid = Views::getView('test_node_revision_id_argument');
-    $this->executeView($view_nid, [$node->getRevisionId()]);
+    $this->executeView($view_nid, [$second_revision_id]);
     $this->assertIdenticalResultset($view_nid, [['title' => 'test2']]);
+    $this->assertSame('test2', $view_nid->getTitle());
   }
 
   /**
diff --git a/web/core/modules/quickedit/quickedit.module b/web/core/modules/quickedit/quickedit.module
index 028fe20143516ecaf3741e6e330fa5fe03d42f1d..219b975ebcbf2e8eaa96ed4526e78cfc8b58887c 100644
--- a/web/core/modules/quickedit/quickedit.module
+++ b/web/core/modules/quickedit/quickedit.module
@@ -16,6 +16,8 @@
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 use Drupal\Core\Entity\RevisionableInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\quickedit\Entity\QuickEditLayoutBuilderEntityViewDisplay;
+use Drupal\quickedit\LayoutBuilderIntegration;
 
 /**
  * Implements hook_help().
@@ -174,10 +176,28 @@ function quickedit_preprocess_field(&$variables) {
   }
 }
 
+/**
+ * Implements hook_entity_type_alter().
+ */
+function quickedit_entity_type_alter(array &$entity_types) {
+  if (\Drupal::moduleHandler()->moduleExists('layout_builder')) {
+    /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
+    if ($entity_types['entity_view_display']->getClass() === 'Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay\LayoutBuilderEntityViewDisplay') {
+      $entity_types['entity_view_display']->setClass(QuickEditLayoutBuilderEntityViewDisplay::class);
+    }
+  }
+}
+
 /**
  * Implements hook_entity_view_alter().
  */
 function quickedit_entity_view_alter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
+  if (\Drupal::moduleHandler()->moduleExists('layout_builder')) {
+    /** @var \Drupal\quickedit\LayoutBuilderIntegration $layout_builder_integration */
+    $layout_builder_integration = \Drupal::classResolver(LayoutBuilderIntegration::class);
+    $layout_builder_integration->entityViewAlter($build, $entity, $display);
+  }
+
   if (isset($build['#embed'])) {
     return;
   }
@@ -189,3 +209,12 @@ function quickedit_entity_view_alter(&$build, EntityInterface $entity, EntityVie
 
   $build['#attributes']['data-quickedit-entity-id'] = $entity->getEntityTypeId() . '/' . $entity->id();
 }
+
+/**
+ * Implements hook_quickedit_render_field().
+ */
+function layout_builder_quickedit_render_field(EntityInterface $entity, $field_name, $view_mode_id, $langcode) {
+  /** @var \Drupal\quickedit\LayoutBuilderIntegration $layout_builder_integration */
+  $layout_builder_integration = \Drupal::classResolver(LayoutBuilderIntegration::class);
+  return $layout_builder_integration->quickEditRenderField($entity, $field_name, $view_mode_id, $langcode);
+}
diff --git a/web/core/modules/quickedit/src/Entity/QuickEditLayoutBuilderEntityViewDisplay.php b/web/core/modules/quickedit/src/Entity/QuickEditLayoutBuilderEntityViewDisplay.php
new file mode 100644
index 0000000000000000000000000000000000000000..3dd4eb9b106271d1c3a80b81c20d59bc262b262b
--- /dev/null
+++ b/web/core/modules/quickedit/src/Entity/QuickEditLayoutBuilderEntityViewDisplay.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Drupal\quickedit\Entity;
+
+use Drupal\Component\Plugin\ConfigurableInterface;
+use Drupal\Component\Plugin\DerivativeInspectionInterface;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
+use Drupal\quickedit\LayoutBuilderIntegration;
+
+/**
+ * Provides an entity view display entity that has a layout with quickedit.
+ */
+class QuickEditLayoutBuilderEntityViewDisplay extends LayoutBuilderEntityViewDisplay {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getComponent($name) {
+    if ($this->isLayoutBuilderEnabled() && $section_component = $this->getQuickEditSectionComponent()) {
+      $plugin = $section_component->getPlugin();
+      if ($plugin instanceof ConfigurableInterface) {
+        $configuration = $plugin->getConfiguration();
+        if (isset($configuration['formatter'])) {
+          return $configuration['formatter'];
+        }
+      }
+    }
+    return parent::getComponent($name);
+  }
+
+  /**
+   * Returns the Quick Edit formatter settings.
+   *
+   * @return \Drupal\layout_builder\SectionComponent|null
+   *   The section component if it is available.
+   *
+   * @see \Drupal\quickedit\LayoutBuilderIntegration::entityViewAlter()
+   * @see \Drupal\quickedit\MetadataGenerator::generateFieldMetadata()
+   */
+  private function getQuickEditSectionComponent() {
+    // To determine the Quick Edit view_mode ID we need an originalMode set.
+    if ($original_mode = $this->getOriginalMode()) {
+      $parts = explode('-', $original_mode);
+      // The Quick Edit view mode ID is created by
+      // \Drupal\quickedit\LayoutBuilderIntegration::entityViewAlter()
+      // concatenating together the information we need to retrieve the Layout
+      // Builder component. It follows the structure prescribed by the
+      // documentation of hook_quickedit_render_field().
+      if (count($parts) === 6 && $parts[0] === 'layout_builder') {
+        [, $delta, $component_uuid, $entity_id] = LayoutBuilderIntegration::deconstructViewModeId($original_mode);
+        $entity = $this->entityTypeManager()->getStorage($this->getTargetEntityTypeId())->load($entity_id);
+        $sections = $this->getEntitySections($entity);
+        if (isset($sections[$delta])) {
+          $component = $sections[$delta]->getComponent($component_uuid);
+          $plugin = $component->getPlugin();
+          // We only care about FieldBlock because these are only components
+          // that provide Quick Edit integration: Quick Edit enables in-place
+          // editing of fields of entities, not of anything else.
+          if ($plugin instanceof DerivativeInspectionInterface && $plugin->getBaseId() === 'field_block') {
+            return $component;
+          }
+        }
+      }
+    }
+    return NULL;
+  }
+
+}
diff --git a/web/core/modules/quickedit/src/LayoutBuilderIntegration.php b/web/core/modules/quickedit/src/LayoutBuilderIntegration.php
new file mode 100644
index 0000000000000000000000000000000000000000..49e229b98540c4cd7f4a8bf5ee03cbbeb24e3d83
--- /dev/null
+++ b/web/core/modules/quickedit/src/LayoutBuilderIntegration.php
@@ -0,0 +1,321 @@
+<?php
+
+namespace Drupal\quickedit;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\Core\Logger\LoggerChannelTrait;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\Render\Element;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Helper methods for Layout Builder module integration.
+ *
+ * @internal
+ *   This is an internal utility class wrapping hook implementations.
+ */
+class LayoutBuilderIntegration implements ContainerInjectionInterface {
+
+  use LoggerChannelTrait;
+
+  /**
+   * The section storage manager.
+   *
+   * @var \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface
+   */
+  protected $sectionStorageManager;
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a new LayoutBuilderIntegration object.
+   *
+   * @param \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface $section_storage_manager
+   *   The section storage manager.
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current user.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(SectionStorageManagerInterface $section_storage_manager, AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager) {
+    $this->sectionStorageManager = $section_storage_manager;
+    $this->currentUser = $current_user;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('plugin.manager.layout_builder.section_storage'),
+      $container->get('current_user'),
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * Alters the entity view build for Layout Builder compatibility.
+   *
+   * When rendering fields outside of normal view modes, Quick Edit requires
+   * that modules identify themselves with a view mode ID in the format
+   * [module_name]-[information the module needs to rerender], as prescribed by
+   * hook_quickedit_render_field().
+   *
+   * @param array $build
+   *   The built entity render array.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
+   *   The entity view display.
+   *
+   * @see hook_quickedit_render_field()
+   * @see layout_builder_quickedit_render_field()
+   */
+  public function entityViewAlter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
+    if (!$entity instanceof FieldableEntityInterface || !isset($build['_layout_builder'])) {
+      return;
+    }
+
+    $build['#cache']['contexts'][] = 'user.permissions';
+    if (!$this->currentUser->hasPermission('access in-place editing')) {
+      return;
+    }
+
+    $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
+    $section_list = $this->sectionStorageManager->findByContext(
+      [
+        'display' => EntityContext::fromEntity($display),
+        'entity' => EntityContext::fromEntity($entity),
+        'view_mode' => new Context(new ContextDefinition('string'), $display->getMode()),
+      ],
+      $cacheable_metadata
+    );
+    $cacheable_metadata->applyTo($build);
+
+    if (empty($section_list)) {
+      return;
+    }
+
+    // Create a hash of the sections and use it in the unique Quick Edit view
+    // mode ID. Any changes to the sections will result in a different hash,
+    // forcing Quick Edit's JavaScript to recognize any changes and retrieve
+    // up-to-date metadata.
+    $sections_hash = hash('sha256', serialize($section_list->getSections()));
+
+    // Track each component by their plugin ID, delta, region, and UUID.
+    $plugin_ids_to_update = [];
+    foreach (Element::children($build['_layout_builder']) as $delta) {
+      $section = $build['_layout_builder'][$delta];
+
+      if (!Element::isEmpty($section)) {
+        /** @var \Drupal\Core\Layout\LayoutDefinition $layout */
+        $layout = $section['#layout'];
+        $regions = $layout->getRegionNames();
+
+        foreach ($regions as $region) {
+          if (isset($section[$region])) {
+            foreach ($section[$region] as $uuid => $component) {
+              if (isset($component['#plugin_id']) && $this->supportQuickEditOnComponent($component, $entity)) {
+                $plugin_ids_to_update[$component['#plugin_id']][$delta][$region][$uuid] = $uuid;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    // @todo Remove when https://www.drupal.org/node/3041850 is resolved.
+    $plugin_ids_to_update = array_filter($plugin_ids_to_update, function ($info) {
+      // Delta, region, and UUID each count as one.
+      return count($info, COUNT_RECURSIVE) === 3;
+    });
+
+    $plugin_ids_to_update = NestedArray::mergeDeepArray($plugin_ids_to_update, TRUE);
+    foreach ($plugin_ids_to_update as $delta => $regions) {
+      foreach ($regions as $region => $uuids) {
+        foreach ($uuids as $uuid => $component) {
+          $build['_layout_builder'][$delta][$region][$uuid]['content']['#view_mode'] = static::getViewModeId($entity, $display, $delta, $uuid, $sections_hash);
+        }
+      }
+    }
+    // Alter the Quick Edit view mode ID of all fields outside of the Layout
+    // Builder sections to force Quick Edit to request to the field metadata.
+    // @todo Remove this logic in https://www.drupal.org/project/node/2966136.
+    foreach (Element::children($build) as $field_name) {
+      if ($field_name !== '_layout_builder') {
+        $field_build = &$build[$field_name];
+        if (isset($field_build['#view_mode'])) {
+          $field_build['#view_mode'] = "layout_builder-{$display->getMode()}-non_component-$sections_hash";
+        }
+      }
+    }
+  }
+
+  /**
+   * Generates a Quick Edit view mode ID.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
+   *   The entity view display.
+   * @param int $delta
+   *   The delta.
+   * @param string $component_uuid
+   *   The component UUID.
+   * @param string $sections_hash
+   *   The hash of the sections; must change whenever the sections change.
+   *
+   * @return string
+   *   The Quick Edit view mode ID.
+   *
+   * @see \Drupal\quickedit\LayoutBuilderIntegration::deconstructViewModeId()
+   */
+  private static function getViewModeId(EntityInterface $entity, EntityViewDisplayInterface $display, $delta, $component_uuid, $sections_hash) {
+    return implode('-', [
+      'layout_builder',
+      $display->getMode(),
+      $delta,
+      // Replace the dashes in the component UUID because we need to
+      // use dashes to join the parts.
+      str_replace('-', '_', $component_uuid),
+      $entity->id(),
+      $sections_hash,
+    ]);
+  }
+
+  /**
+   * Deconstructs the Quick Edit view mode ID into its constituent parts.
+   *
+   * @param string $quick_edit_view_mode_id
+   *   The Quick Edit view mode ID.
+   *
+   * @return array
+   *   An array containing the entity view mode ID, the delta, the component
+   *   UUID, and the entity ID.
+   *
+   * @see \Drupal\quickedit\LayoutBuilderIntegration::getViewModeId()
+   */
+  public static function deconstructViewModeId($quick_edit_view_mode_id) {
+    [, $entity_view_mode_id, $delta, $component_uuid, $entity_id] = explode('-', $quick_edit_view_mode_id, 7);
+    return [
+      $entity_view_mode_id,
+      // @todo Explicitly cast delta to an integer, remove this in
+      //   https://www.drupal.org/project/drupal/issues/2984509.
+      (int) $delta,
+      // Replace the underscores with dash to get back the component UUID.
+      str_replace('_', '-', $component_uuid),
+      $entity_id,
+    ];
+  }
+
+  /**
+   * Re-renders a field rendered by Layout Builder, edited with Quick Edit.
+   *
+   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
+   *   The entity.
+   * @param string $field_name
+   *   The field name.
+   * @param string $quick_edit_view_mode_id
+   *   The Quick Edit view mode ID.
+   * @param string $langcode
+   *   The language code.
+   *
+   * @return array
+   *   The re-rendered field.
+   */
+  public function quickEditRenderField(FieldableEntityInterface $entity, $field_name, $quick_edit_view_mode_id, $langcode) {
+    [$entity_view_mode, $delta, $component_uuid] = static::deconstructViewModeId($quick_edit_view_mode_id);
+
+    $entity_build = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId())->view($entity, $entity_view_mode, $langcode);
+    $this->buildEntityView($entity_build);
+
+    if (isset($entity_build['_layout_builder'][$delta])) {
+      foreach (Element::children($entity_build['_layout_builder'][$delta]) as $region) {
+        if (isset($entity_build['_layout_builder'][$delta][$region][$component_uuid])) {
+          return $entity_build['_layout_builder'][$delta][$region][$component_uuid]['content'];
+        }
+      }
+    }
+
+    $this->getLogger('layout_builder')->warning('The field "%field" failed to render.', ['%field' => $field_name]);
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @todo Replace this hardcoded processing when
+   *   https://www.drupal.org/project/drupal/issues/3041635 is resolved.
+   *
+   * @see \Drupal\Tests\EntityViewTrait::buildEntityView()
+   */
+  private function buildEntityView(array &$elements) {
+    // If the default values for this element have not been loaded yet,
+    // populate them.
+    if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
+      $elements += \Drupal::service('element_info')->getInfo($elements['#type']);
+    }
+
+    // Make any final changes to the element before it is rendered. This means
+    // that the $element or the children can be altered or corrected before
+    // the element is rendered into the final text.
+    if (isset($elements['#pre_render'])) {
+      foreach ($elements['#pre_render'] as $callable) {
+        $elements = call_user_func($callable, $elements);
+      }
+    }
+
+    // And recurse.
+    $children = Element::children($elements, TRUE);
+    foreach ($children as $key) {
+      $this->buildEntityView($elements[$key]);
+    }
+  }
+
+  /**
+   * Determines whether a component has Quick Edit support.
+   *
+   * Only field_block components for display configurable fields should be
+   * supported.
+   *
+   * @param array $component
+   *   The component render array.
+   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
+   *   The entity being displayed.
+   *
+   * @return bool
+   *   Whether Quick Edit is supported on the component.
+   *
+   * @see \Drupal\layout_builder\Plugin\Block\FieldBlock
+   */
+  private function supportQuickEditOnComponent(array $component, FieldableEntityInterface $entity) {
+    if (isset($component['content']['#field_name'], $component['#base_plugin_id']) && $component['#base_plugin_id'] === 'field_block' && $entity->hasField($component['content']['#field_name'])) {
+      return $entity->getFieldDefinition($component['content']['#field_name'])->isDisplayConfigurable('view');
+    }
+    return FALSE;
+  }
+
+}
diff --git a/web/core/modules/quickedit/tests/src/Functional/Jsonapi/QuickEditLayoutBuilderEntityViewDisplayTest.php b/web/core/modules/quickedit/tests/src/Functional/Jsonapi/QuickEditLayoutBuilderEntityViewDisplayTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0e1509b2a73b10afbc34c188ad65219de619035e
--- /dev/null
+++ b/web/core/modules/quickedit/tests/src/Functional/Jsonapi/QuickEditLayoutBuilderEntityViewDisplayTest.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Drupal\Tests\quickedit\Functional\Jsonapi;
+
+use Drupal\Tests\layout_builder\Functional\Jsonapi\LayoutBuilderEntityViewDisplayTest;
+
+/**
+ * JSON:API integration test for the "EntityViewDisplay" config entity type.
+ *
+ * @group jsonapi
+ * @group layout_builder
+ * @group quickedit
+ */
+class QuickEditLayoutBuilderEntityViewDisplayTest extends LayoutBuilderEntityViewDisplayTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonAnonTest.php b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonAnonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c138148ae92558b19827dcd9b0160c4a6cf03298
--- /dev/null
+++ b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonAnonTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Tests\quickedit\Functional\Rest;
+
+use Drupal\Tests\layout_builder\Functional\Rest\LayoutBuilderEntityViewDisplayJsonAnonTest;
+
+/**
+ * @group quickedit
+ * @group layout_builder
+ * @group rest
+ */
+class QuickEditLayoutBuilderEntityViewDisplayJsonAnonTest extends LayoutBuilderEntityViewDisplayJsonAnonTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonBasicAuthTest.php b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonBasicAuthTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3acf46eead6f7ea403aa04351585031697f7b7a
--- /dev/null
+++ b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonBasicAuthTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Tests\quickedit\Functional\Rest;
+
+use Drupal\Tests\layout_builder\Functional\Rest\LayoutBuilderEntityViewDisplayJsonBasicAuthTest;
+
+/**
+ * @group quickedit
+ * @group layout_builder
+ * @group rest
+ */
+class QuickEditLayoutBuilderEntityViewDisplayJsonBasicAuthTest extends LayoutBuilderEntityViewDisplayJsonBasicAuthTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonCookieTest.php b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonCookieTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ffd07b021d4061e166cf9c103145fefd322549d4
--- /dev/null
+++ b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayJsonCookieTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Tests\quickedit\Functional\Rest;
+
+use Drupal\Tests\layout_builder\Functional\Rest\LayoutBuilderEntityViewDisplayJsonCookieTest;
+
+/**
+ * @group quickedit
+ * @group layout_builder
+ * @group rest
+ */
+class QuickEditLayoutBuilderEntityViewDisplayJsonCookieTest extends LayoutBuilderEntityViewDisplayJsonCookieTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlAnonTest.php b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlAnonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..87c6a72639f0e5b22a657d7286765056dd37bba2
--- /dev/null
+++ b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlAnonTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Tests\quickedit\Functional\Rest;
+
+use Drupal\Tests\layout_builder\Functional\Rest\LayoutBuilderEntityViewDisplayXmlAnonTest;
+
+/**
+ * @group quickedit
+ * @group layout_builder
+ * @group rest
+ */
+class QuickEditLayoutBuilderEntityViewDisplayXmlAnonTest extends LayoutBuilderEntityViewDisplayXmlAnonTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlBasicAuthTest.php b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlBasicAuthTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8640666302a51e72e9807ac439d4d2217f43d2eb
--- /dev/null
+++ b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlBasicAuthTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Tests\quickedit\Functional\Rest;
+
+use Drupal\Tests\layout_builder\Functional\Rest\LayoutBuilderEntityViewDisplayXmlBasicAuthTest;
+
+/**
+ * @group quickedit
+ * @group layout_builder
+ * @group rest
+ */
+class QuickEditLayoutBuilderEntityViewDisplayXmlBasicAuthTest extends LayoutBuilderEntityViewDisplayXmlBasicAuthTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlCookieTest.php b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlCookieTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..699efe177ecf8f8badc5d0c0c7e7e0e375b7396b
--- /dev/null
+++ b/web/core/modules/quickedit/tests/src/Functional/Rest/QuickEditLayoutBuilderEntityViewDisplayXmlCookieTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Tests\quickedit\Functional\Rest;
+
+use Drupal\Tests\layout_builder\Functional\Rest\LayoutBuilderEntityViewDisplayXmlCookieTest;
+
+/**
+ * @group quickedit
+ * @group layout_builder
+ * @group rest
+ */
+class QuickEditLayoutBuilderEntityViewDisplayXmlCookieTest extends LayoutBuilderEntityViewDisplayXmlCookieTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['quickedit'];
+
+}
diff --git a/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php b/web/core/modules/quickedit/tests/src/FunctionalJavascript/LayoutBuilderIntegrationTest.php
similarity index 99%
rename from web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php
rename to web/core/modules/quickedit/tests/src/FunctionalJavascript/LayoutBuilderIntegrationTest.php
index c78ec364e24976826d1df69dd96f17245b07307d..ab8f1f0a1b20e8a4ba1c9b8e01ad7afb4f26b858 100644
--- a/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php
+++ b/web/core/modules/quickedit/tests/src/FunctionalJavascript/LayoutBuilderIntegrationTest.php
@@ -14,7 +14,7 @@
 /**
  * @group quickedit
  */
-class QuickEditIntegrationTest extends QuickEditJavascriptTestBase {
+class LayoutBuilderIntegrationTest extends QuickEditJavascriptTestBase {
 
   use EntityReferenceTestTrait;
 
diff --git a/web/core/modules/system/src/EventSubscriber/SecurityFileUploadEventSubscriber.php b/web/core/modules/system/src/EventSubscriber/SecurityFileUploadEventSubscriber.php
index 4aeeb574d35e690836bd4705100e61687e50dfce..4bf03463d6d2e66e4a7b8404f300a25d29b77178 100644
--- a/web/core/modules/system/src/EventSubscriber/SecurityFileUploadEventSubscriber.php
+++ b/web/core/modules/system/src/EventSubscriber/SecurityFileUploadEventSubscriber.php
@@ -63,6 +63,15 @@ public function sanitizeName(FileUploadSanitizeNameEvent $event): void {
     $filename = array_shift($filename_parts);
     // Remove final extension.
     $final_extension = (string) array_pop($filename_parts);
+    // Check if we're dealing with a dot file that is also an insecure extension
+    // e.g. .htaccess. In this scenario there is only one 'part' and the
+    // extension becomes the filename. We use the original filename from the
+    // event rather than the trimmed version above.
+    $insecure_uploads = $this->config->get('allow_insecure_uploads');
+    if (!$insecure_uploads && $final_extension === '' && str_contains($event->getFilename(), '.') && in_array(strtolower($filename), FileSystemInterface::INSECURE_EXTENSIONS, TRUE)) {
+      $final_extension = $filename;
+      $filename = '';
+    }
 
     $extensions = $event->getAllowedExtensions();
     if (!empty($extensions) && !in_array(strtolower($final_extension), $extensions, TRUE)) {
@@ -76,7 +85,7 @@ public function sanitizeName(FileUploadSanitizeNameEvent $event): void {
       return;
     }
 
-    if (!$this->config->get('allow_insecure_uploads') && in_array(strtolower($final_extension), FileSystemInterface::INSECURE_EXTENSIONS, TRUE)) {
+    if (!$insecure_uploads && in_array(strtolower($final_extension), FileSystemInterface::INSECURE_EXTENSIONS, TRUE)) {
       if (empty($extensions) || in_array('txt', $extensions, TRUE)) {
         // Add .txt to potentially executable files prior to munging to help prevent
         // exploits. This results in a filenames like filename.php being changed to
diff --git a/web/core/modules/system/system.module b/web/core/modules/system/system.module
index a1b51cc7c0dfb06963a7dd68e8b4a88ac762b58c..deba8f16a016a6ab77d3f8d18261d932119827ed 100644
--- a/web/core/modules/system/system.module
+++ b/web/core/modules/system/system.module
@@ -27,6 +27,8 @@
 use Drupal\Core\Queue\QueueGarbageCollectionInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Routing\StackedRouteMatchInterface;
+use Drupal\Core\Site\Settings;
+use Drupal\Core\StreamWrapper\StreamWrapperManager;
 use Drupal\Core\Url;
 use GuzzleHttp\Exception\TransferException;
 use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -1385,3 +1387,21 @@ function system_page_top() {
     }
   }
 }
+
+/**
+ * Implements hook_file_download().
+ */
+function system_file_download($uri) {
+  $core_schemes = ['public', 'private', 'temporary'];
+  $additional_public_schemes = array_diff(Settings::get('file_additional_public_schemes', []), $core_schemes);
+  if ($additional_public_schemes) {
+    $scheme = StreamWrapperManager::getScheme($uri);
+    if (in_array($scheme, $additional_public_schemes, TRUE)) {
+      return [
+        // Returning any header grants access, and setting the 'Cache-Control'
+        // header is appropriate for public files.
+        'Cache-Control' => 'public',
+      ];
+    }
+  }
+}
diff --git a/web/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.info.yml b/web/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..08d66bdb6904a2b4c419145e5a85250b32dd36ce
--- /dev/null
+++ b/web/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.info.yml
@@ -0,0 +1,5 @@
+name: 'Decorated Service Test'
+type: module
+description: 'Support module for decorated service test.'
+package: Testing
+version: VERSION
diff --git a/web/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.services.yml b/web/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.services.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a00c56c7d0cc06607b6b1258c56479a9328fa162
--- /dev/null
+++ b/web/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.services.yml
@@ -0,0 +1,17 @@
+services:
+  test_service:
+    class: 'Drupal\decorated_service_test\TestService'
+  test_service_decorator:
+    class: 'Drupal\decorated_service_test\TestServiceDecorator'
+    public: false
+    decorates: test_service
+  test_service2:
+    class: 'Drupal\decorated_service_test\TestService'
+  test_service2_decorator:
+    class: 'Drupal\decorated_service_test\TestServiceDecorator'
+    public: false
+    decorates: test_service2
+  test_service2_decorator2:
+    class: 'Drupal\decorated_service_test\TestServiceDecorator'
+    public: false
+    decorates: test_service2
diff --git a/web/core/modules/system/tests/modules/decorated_service_test/src/TestService.php b/web/core/modules/system/tests/modules/decorated_service_test/src/TestService.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e708019ffaedc11d753f5fc37ab98b298e6339e
--- /dev/null
+++ b/web/core/modules/system/tests/modules/decorated_service_test/src/TestService.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Drupal\decorated_service_test;
+
+class TestService {
+
+}
diff --git a/web/core/modules/system/tests/modules/decorated_service_test/src/TestServiceDecorator.php b/web/core/modules/system/tests/modules/decorated_service_test/src/TestServiceDecorator.php
new file mode 100644
index 0000000000000000000000000000000000000000..30dcb023bd95c34e0c9a5aa375aa19f178d2a826
--- /dev/null
+++ b/web/core/modules/system/tests/modules/decorated_service_test/src/TestServiceDecorator.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Drupal\decorated_service_test;
+
+class TestServiceDecorator extends TestService {
+
+}
diff --git a/web/core/modules/system/tests/src/Kernel/DecoratedServiceTest.php b/web/core/modules/system/tests/src/Kernel/DecoratedServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..854662df18bb9804472ec6c5295b422175079b5b
--- /dev/null
+++ b/web/core/modules/system/tests/src/Kernel/DecoratedServiceTest.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Drupal\Tests\system\Kernel;
+
+use Drupal\decorated_service_test\TestServiceDecorator;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Test handling of decorated services in DependencySerializationTraitPass.
+ *
+ * @group system
+ */
+class DecoratedServiceTest extends KernelTestBase {
+
+  protected static $modules = [
+    'decorated_service_test',
+  ];
+
+  /**
+   * Check that decorated services keep their original service ID.
+   */
+  public function testDecoratedServiceId() {
+    // Service decorated once.
+    $test_service = $this->container->get('test_service');
+    $this->assertEquals('test_service', $test_service->_serviceId);
+    $this->assertInstanceOf(TestServiceDecorator::class, $test_service);
+
+    // Service decorated twice.
+    $test_service2 = $this->container->get('test_service2');
+    $this->assertEquals('test_service2', $test_service2->_serviceId);
+    $this->assertInstanceOf(TestServiceDecorator::class, $test_service2);
+  }
+
+}
diff --git a/web/core/modules/system/tests/src/Unit/Event/SecurityFileUploadEventSubscriberTest.php b/web/core/modules/system/tests/src/Unit/Event/SecurityFileUploadEventSubscriberTest.php
index f51f750b42b87f065bddbb43331c4c470b75a62d..ffeaa0de152a5b1ed47fd9937c62865d3c92e4d9 100644
--- a/web/core/modules/system/tests/src/Unit/Event/SecurityFileUploadEventSubscriberTest.php
+++ b/web/core/modules/system/tests/src/Unit/Event/SecurityFileUploadEventSubscriberTest.php
@@ -84,7 +84,8 @@ public function provideFilenames() {
       'filename is munged' => ['foo.phar.png.php.jpg', 'jpg png', 'foo.phar_.png_.php_.jpg'],
       'filename is munged regardless of case' => ['FOO.pHAR.PNG.PhP.jpg', 'jpg png', 'FOO.pHAR_.PNG_.PhP_.jpg'],
       'null bytes are removed' => ['foo' . chr(0) . '.txt' . chr(0), '', 'foo.txt'],
-      'dot files are renamed' => ['.htaccess', '', 'htaccess'],
+      'dot files are renamed' => ['.git', '', 'git'],
+      'htaccess files are renamed even if allowed' => ['.htaccess', 'htaccess txt', '.htaccess_.txt', '.htaccess'],
     ];
   }
 
diff --git a/web/core/modules/views/src/ViewExecutable.php b/web/core/modules/views/src/ViewExecutable.php
index 3da94957027fa190e5aeb5be81af580bc1311011..5a7c6307b455737b71403e1dc2e48a60456c4c7d 100644
--- a/web/core/modules/views/src/ViewExecutable.php
+++ b/web/core/modules/views/src/ViewExecutable.php
@@ -2492,8 +2492,6 @@ public function __sleep() {
     // state during unserialization.
     $this->serializationData = [
       'storage' => $this->storage->id(),
-      'views_data' => $this->viewsData->_serviceId,
-      'route_provider' => $this->routeProvider->_serviceId,
       'current_display' => $this->current_display,
       'args' => $this->args,
       'current_page' => $this->current_page,
@@ -2520,8 +2518,8 @@ public function __wakeup() {
 
       // Attach all necessary services.
       $this->user = \Drupal::currentUser();
-      $this->viewsData = \Drupal::service($this->serializationData['views_data']);
-      $this->routeProvider = \Drupal::service($this->serializationData['route_provider']);
+      $this->viewsData = \Drupal::service('views.views_data');
+      $this->routeProvider = \Drupal::service('router.route_provider');
 
       // Restore the state of this executable.
       if ($request = \Drupal::request()) {
diff --git a/web/core/modules/views/tests/src/Functional/Wizard/BasicTest.php b/web/core/modules/views/tests/src/Functional/Wizard/BasicTest.php
index 0909299bf6cb9f7acf274a11059ace2ecb1ecb39..fbbd320609d4a9ce4411619b4a17522bf989a915 100644
--- a/web/core/modules/views/tests/src/Functional/Wizard/BasicTest.php
+++ b/web/core/modules/views/tests/src/Functional/Wizard/BasicTest.php
@@ -155,9 +155,6 @@ public function testViewsWizardAndListing() {
     $this->assertSession()->pageTextContains($node1->label());
     $this->assertSession()->pageTextNotContains($node2->label());
 
-    // Make sure the listing page doesn't show disabled default views.
-    $this->assertSession()->pageTextNotContains('tracker');
-
     // Create a view with only a REST export.
     $view4 = [];
     $view4['label'] = $this->randomMachineName(16);
diff --git a/web/core/scripts/js/vendor-update.js b/web/core/scripts/js/vendor-update.js
index df014bab69f0291f578e5621a6bdc49a025bd1a0..56f79e0759d699eba7112c4264a37f7a48ceb4b0 100644
--- a/web/core/scripts/js/vendor-update.js
+++ b/web/core/scripts/js/vendor-update.js
@@ -77,7 +77,7 @@ const assetsFolder = `${coreFolder}/assets/vendor`;
     {
       pack: 'backbone',
       library: 'internal.backbone',
-      files: ['backbone.js', 'backbone-min.js', 'backbone-min.map'],
+      files: ['backbone.js', 'backbone-min.js', 'backbone-min.js.map'],
     },
     // Only used to update the version number of the deprecated library.
     {
diff --git a/web/core/tests/Drupal/BuildTests/Composer/Template/ComposerProjectTemplatesTest.php b/web/core/tests/Drupal/BuildTests/Composer/Template/ComposerProjectTemplatesTest.php
index e7e7b2801ffd0db959dc2fe7af94a32f2344b737..7aad3dd7916c87b3452d2792417896b64065e4ed 100644
--- a/web/core/tests/Drupal/BuildTests/Composer/Template/ComposerProjectTemplatesTest.php
+++ b/web/core/tests/Drupal/BuildTests/Composer/Template/ComposerProjectTemplatesTest.php
@@ -244,6 +244,14 @@ public function testTemplateCreateProject($project, $package_dir, $docroot_dir)
 
     $this->executeCommand("COMPOSER_HOME=$composer_home COMPOSER_ROOT_VERSION=$simulated_core_version composer create-project --no-ansi $project testproject $simulated_core_version -vvv --repository $repository_path");
     $this->assertCommandSuccessful();
+    // Check the output of the project creation for the absence of warnings
+    // about any non-allowed composer plugins.
+    // Note: There are different warnings for unallowed composer plugins
+    // depending on running in non-interactive mode or not. It seems the Drupal
+    // CI environment always forces composer commands to run in the
+    // non-interactive mode. The only thing these messages have in common is the
+    // following string.
+    $this->assertErrorOutputNotContains('See https://getcomposer.org/allow-plugins');
 
     // Ensure we used the project from our codebase.
     $this->assertErrorOutputContains("Installing $project ($simulated_core_version): Symlinking from $package_dir");
@@ -386,6 +394,16 @@ protected function makeVendorPackage($repository_path) {
             "version" => $version,
           ],
         ];
+        // Ensure composer plugins are registered correctly.
+        $package_json = json_decode(file_get_contents($full_path . '/composer.json'), TRUE);
+        if (isset($package_json['type']) && $package_json['type'] === 'composer-plugin') {
+          $packages['packages'][$name][$version]['type'] = $package_json['type'];
+          $packages['packages'][$name][$version]['require'] = $package_json['require'];
+          $packages['packages'][$name][$version]['extra'] = $package_json['extra'];
+          if (isset($package_json['autoload'])) {
+            $packages['packages'][$name][$version]['autoload'] = $package_json['autoload'];
+          }
+        }
       }
     }
 
diff --git a/web/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php b/web/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php
index 05cb76783bd27b0885466c9c0724df1c94a2f6fa..a6de48990a18ec1330bf7a8d954feaa849b9eb4f 100644
--- a/web/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php
+++ b/web/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php
@@ -265,6 +265,16 @@ public function assertErrorOutputContains($expected) {
     $this->assertStringContainsString($expected, $this->commandProcess->getErrorOutput());
   }
 
+  /**
+   * Assert text is not present in the error output of the most recent command.
+   *
+   * @param string $expected
+   *   Text we expect not to find in the error output of the command.
+   */
+  public function assertErrorOutputNotContains($expected) {
+    $this->assertStringNotContainsString($expected, $this->commandProcess->getErrorOutput());
+  }
+
   /**
    * Assert that text is present in the output of the most recent command.
    *
diff --git a/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
index a4f2a6500fcceec5fa0774269500ed385efe9d4a..ab224eca47384b8d21ec534b3c386efec5e654fc 100644
--- a/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
+++ b/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
@@ -760,6 +760,9 @@ public function testCronRun() {
   public function testInstall() {
     $htaccess_filename = $this->tempFilesDirectory . '/.htaccess';
     $this->assertFileExists($htaccess_filename);
+
+    // Ensure the update module is not installed.
+    $this->assertFalse(\Drupal::moduleHandler()->moduleExists('update'), 'The Update module is not installed.');
   }
 
   /**
diff --git a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php
index 8a6a9308fcaad1fe3ede391d071a966b9f2b5f61..1e04685e241d778607c49c53224fd5d6158d7c5a 100644
--- a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php
+++ b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigTestBase.php
@@ -105,7 +105,8 @@ protected function installParameters() {
     // existing configuration.
     unset($parameters['forms']['install_configure_form']['site_name']);
     unset($parameters['forms']['install_configure_form']['site_mail']);
-    unset($parameters['forms']['install_configure_form']['update_status_module']);
+    unset($parameters['forms']['install_configure_form']['enable_update_status_module']);
+    unset($parameters['forms']['install_configure_form']['enable_update_status_emails']);
 
     return $parameters;
   }
diff --git a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTest.php b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTest.php
index 118a77124577aede34f9033925258dee1f1560d9..af85b7e7fd221a14684dd71394bf6538e88fe4f4 100644
--- a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTest.php
+++ b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTest.php
@@ -131,6 +131,9 @@ public function testInstalled() {
     $module = $database->getProvider();
     $module_handler = \Drupal::service('module_handler');
 
+    // Ensure the update module is not installed.
+    $this->assertFalse($module_handler->moduleExists('update'), 'The Update module is not installed.');
+
     // Assert that the module that is providing the database driver has been
     // installed.
     $this->assertTrue($module_handler->moduleExists($module));
diff --git a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php
index caf4afab0ff984fca4ab2d891afbf4617373226c..1cc8300aadcb93009a18243eacc21bc422a28e47 100644
--- a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php
+++ b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php
@@ -73,6 +73,19 @@ abstract class InstallerTestBase extends BrowserTestBase {
    */
   protected $isInstalled = FALSE;
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function installParameters() {
+    $params = parent::installParameters();
+    // Set the checkbox values to FALSE so that
+    // \Drupal\Tests\BrowserTestBase::translatePostValues() does not remove
+    // them.
+    $params['forms']['install_configure_form']['enable_update_status_module'] = FALSE;
+    $params['forms']['install_configure_form']['enable_update_status_emails'] = FALSE;
+    return $params;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/web/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php b/web/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
index 3854f3ef8f1d49ec9a95a9a13480d56b2266996c..8db24885962a23e43d62d3dd497139b40d314d69 100644
--- a/web/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
+++ b/web/core/tests/Drupal/KernelTests/Core/Image/ToolkitGdTest.php
@@ -4,54 +4,46 @@
 
 use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\Image\ImageInterface;
-use Drupal\Component\Render\FormattableMarkup;
-use Drupal\Core\Site\Settings;
 use Drupal\KernelTests\KernelTestBase;
 
 /**
- * Tests that core image manipulations work properly: scale, resize, rotate,
- * crop, scale and crop, and desaturate.
+ * Tests for the GD image toolkit.
  *
+ * @coversDefaultClass \Drupal\system\Plugin\ImageToolkit\GDToolkit
  * @group Image
  * @requires extension gd
  */
 class ToolkitGdTest extends KernelTestBase {
 
   /**
-   * The image factory service.
-   *
-   * @var \Drupal\Core\Image\ImageFactory
+   * Colors that are used in testing.
    */
-  protected $imageFactory;
+  protected const BLACK              = [0, 0, 0, 0];
+  protected const RED                = [255, 0, 0, 0];
+  protected const GREEN              = [0, 255, 0, 0];
+  protected const BLUE               = [0, 0, 255, 0];
+  protected const YELLOW             = [255, 255, 0, 0];
+  protected const WHITE              = [255, 255, 255, 0];
+  protected const TRANSPARENT        = [0, 0, 0, 127];
+  protected const FUCHSIA            = [255, 0, 255, 0];
+  protected const ROTATE_TRANSPARENT = [255, 255, 255, 127];
 
   /**
-   * Colors that are used in testing.
+   * The image factory service.
    *
-   * @var array
+   * @var \Drupal\Core\Image\ImageFactory
    */
-  protected $black       = [0, 0, 0, 0];
-  protected $red         = [255, 0, 0, 0];
-  protected $green       = [0, 255, 0, 0];
-  protected $blue        = [0, 0, 255, 0];
-  protected $yellow      = [255, 255, 0, 0];
-  protected $white       = [255, 255, 255, 0];
-  protected $transparent = [0, 0, 0, 127];
+  protected $imageFactory;
 
   /**
-   * Used as rotate background colors.
+   * A directory where test image files can be saved to.
    *
-   * @var array
+   * @var string
    */
-  protected $fuchsia           = [255, 0, 255, 0];
-  protected $rotateTransparent = [255, 255, 255, 127];
-
-  protected $width = 40;
-  protected $height = 20;
+  protected $directory;
 
   /**
-   * Modules to enable.
-   *
-   * @var array
+   * {@inheritdoc}
    */
   protected static $modules = ['system'];
 
@@ -62,32 +54,41 @@ protected function setUp(): void {
     parent::setUp();
 
     $this->installConfig(['system']);
+
     // Set the image factory service.
     $this->imageFactory = $this->container->get('image.factory');
+    $this->assertEquals('gd', $this->imageFactory->getToolkitId(), 'The image factory is set to use the \'gd\' image toolkit.');
+
+    // Prepare a directory for test file results.
+    $this->directory = 'public://imagetest';
+    \Drupal::service('file_system')->prepareDirectory($this->directory, FileSystemInterface::CREATE_DIRECTORY);
   }
 
   /**
-   * Function to compare two colors by RGBa.
+   * Assert two colors are equal by RGBA, net of full transparency.
+   *
+   * @param int[] $expected
+   *   The expected RGBA array.
+   * @param int[] $actual
+   *   The actual RGBA array.
+   * @param int $tolerance
+   *   The acceptable difference between the colors.
+   * @param string $message
+   *   The assertion message.
    */
-  public function colorsAreEqual($color_a, $color_b) {
-    // Fully transparent pixels are equal, regardless of RGB.
-    if ($color_a[3] == 127 && $color_b[3] == 127) {
-      return TRUE;
+  protected function assertColorsAreEqual(array $expected, array $actual, int $tolerance, string $message = ''): void {
+    // Fully transparent colors are equal, regardless of RGB.
+    if ($actual[3] == 127 && $expected[3] == 127) {
+      return;
     }
-
-    foreach ($color_a as $key => $value) {
-      if ($color_b[$key] != $value) {
-        return FALSE;
-      }
-    }
-
-    return TRUE;
+    $distance = pow(($actual[0] - $expected[0]), 2) + pow(($actual[1] - $expected[1]), 2) + pow(($actual[2] - $expected[2]), 2) + pow(($actual[3] - $expected[3]), 2);
+    $this->assertLessThanOrEqual($tolerance, $distance, $message . " - Actual: {" . implode(',', $actual) . "}, Expected: {" . implode(',', $expected) . "}, Distance: " . $distance . ", Tolerance: " . $tolerance);
   }
 
   /**
    * Function for finding a pixel's RGBa values.
    */
-  public function getPixelColor(ImageInterface $image, $x, $y) {
+  public function getPixelColor(ImageInterface $image, int $x, int $y): array {
     $toolkit = $image->getToolkit();
     $color_index = imagecolorat($toolkit->getResource(), $x, $y);
 
@@ -100,123 +101,87 @@ public function getPixelColor(ImageInterface $image, $x, $y) {
   }
 
   /**
-   * Since PHP can't visually check that our images have been manipulated
-   * properly, build a list of expected color values for each of the corners and
-   * the expected height and widths for the final images.
+   * Data provider for ::testManipulations().
    */
-  public function testManipulations() {
-
-    // Test that the image factory is set to use the GD toolkit.
-    $this->assertEquals('gd', $this->imageFactory->getToolkitId(), 'The image factory is set to use the \'gd\' image toolkit.');
-
-    // Test the list of supported extensions.
-    $expected_extensions = ['png', 'gif', 'jpeg', 'jpg', 'jpe', 'webp'];
-    $supported_extensions = $this->imageFactory->getSupportedExtensions();
-    $this->assertEquals($expected_extensions, array_intersect($expected_extensions, $supported_extensions));
-
-    // Test that the supported extensions map to correct internal GD image
-    // types.
-    $expected_image_types = [
-      'png' => IMAGETYPE_PNG,
-      'gif' => IMAGETYPE_GIF,
-      'jpeg' => IMAGETYPE_JPEG,
-      'jpg' => IMAGETYPE_JPEG,
-      'jpe' => IMAGETYPE_JPEG,
-      'webp' => IMAGETYPE_WEBP,
-    ];
-    $image = $this->imageFactory->get();
-    foreach ($expected_image_types as $extension => $expected_image_type) {
-      $image_type = $image->getToolkit()->extensionToImageType($extension);
-      $this->assertSame($expected_image_type, $image_type);
-    }
-
+  public function providerTestImageFiles(): array {
     // Typically the corner colors will be unchanged. These colors are in the
     // order of top-left, top-right, bottom-right, bottom-left.
-    $default_corners = [$this->red, $this->green, $this->blue, $this->transparent];
-
-    // A list of files that will be tested.
-    $files = [
-      'image-test.png',
-      'image-test.gif',
-      'image-test-no-transparency.gif',
-      'image-test.jpg',
-      'img-test.webp',
-    ];
+    $default_corners = [static::RED, static::GREEN, static::BLUE, static::TRANSPARENT];
 
     // Setup a list of tests to perform on each type.
-    $operations = [
+    $test_cases = [
       'resize' => [
-        'function' => 'resize',
+        'operation' => 'resize',
         'arguments' => ['width' => 20, 'height' => 10],
         'width' => 20,
         'height' => 10,
         'corners' => $default_corners,
       ],
       'scale_x' => [
-        'function' => 'scale',
+        'operation' => 'scale',
         'arguments' => ['width' => 20],
         'width' => 20,
         'height' => 10,
         'corners' => $default_corners,
       ],
       'scale_y' => [
-        'function' => 'scale',
+        'operation' => 'scale',
         'arguments' => ['height' => 10],
         'width' => 20,
         'height' => 10,
         'corners' => $default_corners,
       ],
       'upscale_x' => [
-        'function' => 'scale',
+        'operation' => 'scale',
         'arguments' => ['width' => 80, 'upscale' => TRUE],
         'width' => 80,
         'height' => 40,
         'corners' => $default_corners,
       ],
       'upscale_y' => [
-        'function' => 'scale',
+        'operation' => 'scale',
         'arguments' => ['height' => 40, 'upscale' => TRUE],
         'width' => 80,
         'height' => 40,
         'corners' => $default_corners,
       ],
       'crop' => [
-        'function' => 'crop',
+        'operation' => 'crop',
         'arguments' => ['x' => 12, 'y' => 4, 'width' => 16, 'height' => 12],
         'width' => 16,
         'height' => 12,
-        'corners' => array_fill(0, 4, $this->white),
+        'corners' => array_fill(0, 4, static::WHITE),
       ],
       'scale_and_crop' => [
-        'function' => 'scale_and_crop',
+        'operation' => 'scale_and_crop',
         'arguments' => ['width' => 10, 'height' => 8],
         'width' => 10,
         'height' => 8,
-        'corners' => array_fill(0, 4, $this->black),
+        'corners' => array_fill(0, 4, static::BLACK),
       ],
       'convert_jpg' => [
-        'function' => 'convert',
+        'operation' => 'convert',
         'width' => 40,
         'height' => 20,
         'arguments' => ['extension' => 'jpeg'],
         'corners' => $default_corners,
       ],
       'convert_gif' => [
-        'function' => 'convert',
+        'operation' => 'convert',
         'width' => 40,
         'height' => 20,
         'arguments' => ['extension' => 'gif'],
         'corners' => $default_corners,
       ],
       'convert_png' => [
-        'function' => 'convert',
+        'operation' => 'convert',
         'width' => 40,
         'height' => 20,
         'arguments' => ['extension' => 'png'],
         'corners' => $default_corners,
       ],
       'convert_webp' => [
-        'function' => 'convert',
+        'operation' => 'convert',
         'width' => 40,
         'height' => 20,
         'arguments' => ['extension' => 'webp'],
@@ -224,49 +189,51 @@ public function testManipulations() {
       ],
     ];
 
-    // Systems using non-bundled GD2 don't have imagerotate. Test if available.
-    // @todo Remove the version check once
-    //   https://www.drupal.org/project/drupal/issues/2670966 is resolved.
-    if (function_exists('imagerotate') && (version_compare(phpversion(), '7.0.26') < 0)) {
-      $operations += [
+    // Systems using non-bundled GD2 may miss imagerotate(). Test if available.
+    if (function_exists('imagerotate')) {
+      $test_cases += [
         'rotate_5' => [
-          'function' => 'rotate',
+          'operation' => 'rotate',
           // Fuchsia background.
           'arguments' => ['degrees' => 5, 'background' => '#FF00FF'],
-          'width' => 41,
-          'height' => 23,
-          'corners' => array_fill(0, 4, $this->fuchsia),
+          // @todo Re-enable dimensions' check once
+          //   https://www.drupal.org/project/drupal/issues/2921123 is resolved.
+          // 'width' => 41,
+          // 'height' => 23,
+          'corners' => array_fill(0, 4, static::FUCHSIA),
+        ],
+        'rotate_transparent_5' => [
+          'operation' => 'rotate',
+          'arguments' => ['degrees' => 5],
+          // @todo Re-enable dimensions' check once
+          //   https://www.drupal.org/project/drupal/issues/2921123 is resolved.
+          // 'width' => 41,
+          // 'height' => 23,
+          'corners' => array_fill(0, 4, static::ROTATE_TRANSPARENT),
         ],
         'rotate_90' => [
-          'function' => 'rotate',
+          'operation' => 'rotate',
           // Fuchsia background.
           'arguments' => ['degrees' => 90, 'background' => '#FF00FF'],
           'width' => 20,
           'height' => 40,
-          'corners' => [$this->transparent, $this->red, $this->green, $this->blue],
-        ],
-        'rotate_transparent_5' => [
-          'function' => 'rotate',
-          'arguments' => ['degrees' => 5],
-          'width' => 41,
-          'height' => 23,
-          'corners' => array_fill(0, 4, $this->rotateTransparent),
+          'corners' => [static::TRANSPARENT, static::RED, static::GREEN, static::BLUE],
         ],
         'rotate_transparent_90' => [
-          'function' => 'rotate',
+          'operation' => 'rotate',
           'arguments' => ['degrees' => 90],
           'width' => 20,
           'height' => 40,
-          'corners' => [$this->transparent, $this->red, $this->green, $this->blue],
+          'corners' => [static::TRANSPARENT, static::RED, static::GREEN, static::BLUE],
         ],
       ];
     }
 
-    // Systems using non-bundled GD2 don't have imagefilter. Test if available.
+    // Systems using non-bundled GD2 may miss imagefilter(). Test if available.
     if (function_exists('imagefilter')) {
-      $operations += [
+      $test_cases += [
         'desaturate' => [
-          'function' => 'desaturate',
+          'operation' => 'desaturate',
           'arguments' => [],
           'height' => 20,
           'width' => 40,
@@ -283,148 +250,202 @@ public function testManipulations() {
       ];
     }
 
-    // Prepare a directory for test file results.
-    $directory = Settings::get('file_public_path') . '/imagetest';
-    \Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);
-
-    foreach ($files as $file) {
-      foreach ($operations as $op => $values) {
-        // Load up a fresh image.
-        $image = $this->imageFactory->get('core/tests/fixtures/files/' . $file);
-        $toolkit = $image->getToolkit();
-        if (!$image->isValid()) {
-          $this->fail(new FormattableMarkup('Could not load image %file.', ['%file' => $file]));
-          continue 2;
-        }
-        $image_original_type = $image->getToolkit()->getType();
+    $ret = [];
+    foreach ([
+      'image-test.png',
+      'image-test.gif',
+      'image-test-no-transparency.gif',
+      'image-test.jpg',
+      'img-test.webp',
+    ] as $file_name) {
+      foreach ($test_cases as $test_case => $values) {
+        $operation = $values['operation'];
+        $arguments = $values['arguments'];
+        unset($values['operation'], $values['arguments']);
+        $ret[] = [$file_name, $test_case, $operation, $arguments, $values];
+      }
+    }
 
-        // All images should be converted to truecolor when loaded.
-        $image_truecolor = imageistruecolor($toolkit->getResource());
-        $this->assertTrue($image_truecolor, new FormattableMarkup('Image %file after load is a truecolor image.', ['%file' => $file]));
+    return $ret;
+  }
 
-        // Store the original GD resource.
-        $old_res = $toolkit->getResource();
+  /**
+   * Since PHP can't visually check that our images have been manipulated
+   * properly, build a list of expected color values for each of the corners and
+   * the expected height and widths for the final images.
+   *
+   * @dataProvider providerTestImageFiles
+   */
+  public function testManipulations(string $file_name, string $test_case, string $operation, array $arguments, array $expected): void {
+    // Load up a fresh image.
+    $image = $this->imageFactory->get('core/tests/fixtures/files/' . $file_name);
+    $toolkit = $image->getToolkit();
+    $this->assertTrue($image->isValid());
+    $image_original_type = $image->getToolkit()->getType();
 
-        // Perform our operation.
-        $image->apply($values['function'], $values['arguments']);
+    $this->assertTrue(imageistruecolor($toolkit->getResource()), "Image '$file_name' after load should be a truecolor image, but it is not.");
 
-        // If the operation replaced the resource, check that the old one has
-        // been destroyed.
-        $new_res = $toolkit->getResource();
-        if ($new_res !== $old_res) {
-          // @todo In https://www.drupal.org/node/3133236 convert this to
-          //   $this->assertIsNotResource($old_res).
-          $this->assertFalse(is_resource($old_res), new FormattableMarkup("'%operation' destroyed the original resource.", ['%operation' => $values['function']]));
-        }
+    // Perform our operation.
+    $image->apply($operation, $arguments);
 
-        // To keep from flooding the test with assert values, make a general
-        // value for whether each group of values fail.
-        $correct_dimensions_real = TRUE;
-        $correct_dimensions_object = TRUE;
+    // Flush Image object to disk storage.
+    $file_path = $this->directory . '/' . $test_case . image_type_to_extension($image->getToolkit()->getType());
+    $image->save($file_path);
 
-        if (imagesy($toolkit->getResource()) != $values['height'] || imagesx($toolkit->getResource()) != $values['width']) {
-          $correct_dimensions_real = FALSE;
-        }
+    // Check that the both the GD object and the Image object have an accurate
+    // record of the dimensions.
+    if (isset($expected['height']) && isset($expected['width'])) {
+      $this->assertSame($expected['height'], imagesy($toolkit->getResource()), "Image '$file_name' after '$test_case' should have a proper height.");
+      $this->assertSame($expected['width'], imagesx($toolkit->getResource()), "Image '$file_name' after '$test_case' should have a proper width.");
+      $this->assertSame($expected['height'], $image->getHeight(), "Image '$file_name' after '$test_case' should have a proper height.");
+      $this->assertSame($expected['width'], $image->getWidth(), "Image '$file_name' after '$test_case' should have a proper width.");
+    }
 
-        // Check that the image object has an accurate record of the dimensions.
-        if ($image->getWidth() != $values['width'] || $image->getHeight() != $values['height']) {
-          $correct_dimensions_object = FALSE;
+    // Now check each of the corners to ensure color correctness.
+    foreach ($expected['corners'] as $key => $expected_color) {
+      // The test gif that does not have transparency color set is a
+      // special case.
+      if ($file_name === 'image-test-no-transparency.gif') {
+        if ($test_case == 'desaturate') {
+          // For desaturating, keep the expected color from the test
+          // data, but set alpha channel to fully opaque.
+          $expected_color[3] = 0;
         }
-
-        $file_path = $directory . '/' . $op . image_type_to_extension($image->getToolkit()->getType());
-        $image->save($file_path);
-
-        $this->assertTrue($correct_dimensions_real, new FormattableMarkup('Image %file after %action action has proper dimensions.', ['%file' => $file, '%action' => $op]));
-        $this->assertTrue($correct_dimensions_object, new FormattableMarkup('Image %file object after %action action is reporting the proper height and width values.', ['%file' => $file, '%action' => $op]));
-
-        // JPEG colors will always be messed up due to compression. So we skip
-        // these tests if the original or the result is in jpeg format.
-        if ($image->getToolkit()->getType() != IMAGETYPE_JPEG && $image_original_type != IMAGETYPE_JPEG) {
-          // Now check each of the corners to ensure color correctness.
-          foreach ($values['corners'] as $key => $corner) {
-            // The test gif that does not have transparency color set is a
-            // special case.
-            if ($file === 'image-test-no-transparency.gif') {
-              if ($op == 'desaturate') {
-                // For desaturating, keep the expected color from the test
-                // data, but set alpha channel to fully opaque.
-                $corner[3] = 0;
-              }
-              elseif ($corner === $this->transparent) {
-                // Set expected pixel to yellow where the others have
-                // transparent.
-                $corner = $this->yellow;
-              }
-            }
-
-            // Get the location of the corner.
-            switch ($key) {
-              case 0:
-                $x = 0;
-                $y = 0;
-                break;
-
-              case 1:
-                $x = $image->getWidth() - 1;
-                $y = 0;
-                break;
-
-              case 2:
-                $x = $image->getWidth() - 1;
-                $y = $image->getHeight() - 1;
-                break;
-
-              case 3:
-                $x = 0;
-                $y = $image->getHeight() - 1;
-                break;
-            }
-            $color = $this->getPixelColor($image, $x, $y);
-            // We also skip the color test for transparency for gif <-> png
-            // conversion. The convert operation cannot handle that correctly.
-            if ($image->getToolkit()->getType() == $image_original_type || $corner != $this->transparent) {
-              $correct_colors = $this->colorsAreEqual($color, $corner);
-              $this->assertTrue($correct_colors, new FormattableMarkup('Image %file object after %action action has the correct color placement at corner %corner.',
-                ['%file' => $file, '%action' => $op, '%corner' => $key]));
-            }
-          }
+        elseif ($expected_color === static::TRANSPARENT) {
+          // Set expected pixel to yellow where the others have
+          // transparent.
+          $expected_color = static::YELLOW;
         }
+      }
 
-        // Check that saved image reloads without raising PHP errors.
-        $image_reloaded = $this->imageFactory->get($file_path);
-        $resource = $image_reloaded->getToolkit()->getResource();
+      // Get the location of the corner.
+      switch ($key) {
+        case 0:
+          $x = 0;
+          $y = 0;
+          break;
+
+        case 1:
+          $x = $image->getWidth() - 1;
+          $y = 0;
+          break;
+
+        case 2:
+          $x = $image->getWidth() - 1;
+          $y = $image->getHeight() - 1;
+          break;
+
+        case 3:
+          $x = 0;
+          $y = $image->getHeight() - 1;
+          break;
       }
-    }
+      $actual_color = $this->getPixelColor($image, $x, $y);
 
-    // Test creation of image from scratch, and saving to storage.
-    foreach ([IMAGETYPE_PNG, IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_WEBP] as $type) {
-      $image = $this->imageFactory->get();
-      $image->createNew(50, 20, image_type_to_extension($type, FALSE), '#ffff00');
-      $file = 'from_null' . image_type_to_extension($type);
-      $file_path = $directory . '/' . $file;
-      $this->assertEquals(50, $image->getWidth(), new FormattableMarkup('Image file %file has the correct width.', ['%file' => $file]));
-      $this->assertEquals(20, $image->getHeight(), new FormattableMarkup('Image file %file has the correct height.', ['%file' => $file]));
-      $this->assertEquals(image_type_to_mime_type($type), $image->getMimeType(), new FormattableMarkup('Image file %file has the correct MIME type.', ['%file' => $file]));
-      $this->assertTrue($image->save($file_path), new FormattableMarkup('Image %file created anew from a null image was saved.', ['%file' => $file]));
-
-      // Reload saved image.
-      $image_reloaded = $this->imageFactory->get($file_path);
-      if (!$image_reloaded->isValid()) {
-        $this->fail(new FormattableMarkup('Could not load image %file.', ['%file' => $file]));
+      // If image cannot handle transparent colors, skip the pixel color test.
+      if ($actual_color[3] === 0 && $expected_color[3] === 127) {
         continue;
       }
-      $this->assertEquals(50, $image_reloaded->getWidth(), new FormattableMarkup('Image file %file has the correct width.', ['%file' => $file]));
-      $this->assertEquals(20, $image_reloaded->getHeight(), new FormattableMarkup('Image file %file has the correct height.', ['%file' => $file]));
-      $this->assertEquals(image_type_to_mime_type($type), $image_reloaded->getMimeType(), new FormattableMarkup('Image file %file has the correct MIME type.', ['%file' => $file]));
-      if ($image_reloaded->getToolkit()->getType() == IMAGETYPE_GIF) {
-        $this->assertEquals('#ffff00', $image_reloaded->getToolkit()->getTransparentColor(), new FormattableMarkup('Image file %file has the correct transparent color channel set.', ['%file' => $file]));
-      }
-      else {
-        $this->assertNull($image_reloaded->getToolkit()->getTransparentColor(), new FormattableMarkup('Image file %file has no color channel set.', ['%file' => $file]));
-      }
+
+      // JPEG has small differences in color after processing.
+      $tolerance = $image_original_type === IMAGETYPE_JPEG ? 3 : 0;
+
+      $this->assertColorsAreEqual($expected_color, $actual_color, $tolerance, "Image '$file_name' object after '$test_case' action has the correct color placement at corner '$key'");
+    }
+
+    // Check that saved image reloads without raising PHP errors.
+    $image_reloaded = $this->imageFactory->get($file_path);
+    if (PHP_VERSION_ID >= 80000) {
+      $this->assertInstanceOf(\GDImage::class, $image_reloaded->getToolkit()->getResource());
+    }
+    else {
+      $this->assertIsResource($image_reloaded->getToolkit()->getResource());
+      $this->assertSame(get_resource_type($image_reloaded->getToolkit()->getResource()), 'gd');
+    }
+  }
+
+  /**
+   * @covers ::getSupportedExtensions
+   * @covers ::extensionToImageType
+   */
+  public function testSupportedExtensions(): void {
+    // Test the list of supported extensions.
+    $expected_extensions = ['png', 'gif', 'jpeg', 'jpg', 'jpe', 'webp'];
+    $this->assertEqualsCanonicalizing($expected_extensions, $this->imageFactory->getSupportedExtensions());
+
+    // Test that the supported extensions map to correct internal GD image
+    // types.
+    $expected_image_types = [
+      'png' => IMAGETYPE_PNG,
+      'gif' => IMAGETYPE_GIF,
+      'jpeg' => IMAGETYPE_JPEG,
+      'jpg' => IMAGETYPE_JPEG,
+      'jpe' => IMAGETYPE_JPEG,
+      'webp' => IMAGETYPE_WEBP,
+    ];
+    $image = $this->imageFactory->get();
+    foreach ($expected_image_types as $extension => $expected_image_type) {
+      $this->assertSame($expected_image_type, $image->getToolkit()->extensionToImageType($extension));
     }
+  }
+
+  /**
+   * Data provider for ::testCreateImageFromScratch().
+   */
+  public function providerSupportedImageTypes(): array {
+    return [
+      [IMAGETYPE_PNG],
+      [IMAGETYPE_GIF],
+      [IMAGETYPE_JPEG],
+      [IMAGETYPE_WEBP],
+    ];
+  }
 
-    // Test failures of the 'create_new' operation.
+  /**
+   * Tests that GD functions for the image type are available.
+   *
+   * @dataProvider providerSupportedImageTypes
+   */
+  public function testGdFunctionsExist(int $type): void {
+    $extension = image_type_to_extension($type, FALSE);
+    $this->assertTrue(function_exists("imagecreatefrom$extension"), "imagecreatefrom$extension should exist.");
+    $this->assertTrue(function_exists("image$extension"), "image$extension should exist.");
+  }
+
+  /**
+   * Tests creation of image from scratch, and saving to storage.
+   *
+   * @dataProvider providerSupportedImageTypes
+   */
+  public function testCreateImageFromScratch(int $type): void {
+    // Build an image from scratch.
+    $image = $this->imageFactory->get();
+    $image->createNew(50, 20, image_type_to_extension($type, FALSE), '#ffff00');
+    $file = 'from_null' . image_type_to_extension($type);
+    $file_path = $this->directory . '/' . $file;
+    $this->assertSame(50, $image->getWidth());
+    $this->assertSame(20, $image->getHeight());
+    $this->assertSame(image_type_to_mime_type($type), $image->getMimeType());
+    $this->assertTrue($image->save($file_path), "Image '$file' should have been saved successfully, but it has not.");
+
+    // Reload and check saved image.
+    $image_reloaded = $this->imageFactory->get($file_path);
+    $this->assertTrue($image_reloaded->isValid());
+    $this->assertSame(50, $image_reloaded->getWidth());
+    $this->assertSame(20, $image_reloaded->getHeight());
+    $this->assertSame(image_type_to_mime_type($type), $image_reloaded->getMimeType());
+    if ($image_reloaded->getToolkit()->getType() == IMAGETYPE_GIF) {
+      $this->assertSame('#ffff00', $image_reloaded->getToolkit()->getTransparentColor(), "Image '$file' after reload should have color channel set to #ffff00, but it has not.");
+    }
+    else {
+      $this->assertNull($image_reloaded->getToolkit()->getTransparentColor(), "Image '$file' after reload should have no color channel set, but it has.");
+    }
+  }
+
+  /**
+   * Tests failures of the 'create_new' operation.
+   */
+  public function testCreateNewFailures(): void {
     $image = $this->imageFactory->get();
     $image->createNew(-50, 20);
     $this->assertFalse($image->isValid(), 'CreateNew with negative width fails.');
@@ -472,11 +493,7 @@ public function testResourceDestruction() {
   /**
    * Tests for GIF images with transparency.
    */
-  public function testGifTransparentImages() {
-    // Prepare a directory for test file results.
-    $directory = Settings::get('file_public_path') . '/imagetest';
-    \Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);
-
+  public function testGifTransparentImages(): void {
     // Test loading an indexed GIF image with transparent color set.
     // Color at top-right pixel should be fully transparent.
     $file = 'image-test-transparent-indexed.gif';
@@ -484,20 +501,20 @@ public function testGifTransparentImages() {
     $resource = $image->getToolkit()->getResource();
     $color_index = imagecolorat($resource, $image->getWidth() - 1, 0);
     $color = array_values(imagecolorsforindex($resource, $color_index));
-    $this->assertEquals($this->rotateTransparent, $color, "Image {$file} after load has full transparent color at corner 1.");
+    $this->assertEquals(static::ROTATE_TRANSPARENT, $color, "Image {$file} after load has full transparent color at corner 1.");
 
     // Test deliberately creating a GIF image with no transparent color set.
     // Color at top-right pixel should be fully transparent while in memory,
     // fully opaque after flushing image to file.
     $file = 'image-test-no-transparent-color-set.gif';
-    $file_path = $directory . '/' . $file;
+    $file_path = $this->directory . '/' . $file;
     // Create image.
     $image = $this->imageFactory->get();
     $image->createNew(50, 20, 'gif', NULL);
     $resource = $image->getToolkit()->getResource();
     $color_index = imagecolorat($resource, $image->getWidth() - 1, 0);
     $color = array_values(imagecolorsforindex($resource, $color_index));
-    $this->assertEquals($this->rotateTransparent, $color, "New GIF image with no transparent color set after creation has full transparent color at corner 1.");
+    $this->assertEquals(static::ROTATE_TRANSPARENT, $color, "New GIF image with no transparent color set after creation has full transparent color at corner 1.");
     // Save image.
     $this->assertTrue($image->save($file_path), "New GIF image {$file} was saved.");
     // Reload image.
@@ -522,37 +539,20 @@ public function testGifTransparentImages() {
     // can be loaded correctly.
     $file = 'image-test-transparent-out-of-range.gif';
     $image = $this->imageFactory->get('core/tests/fixtures/files/' . $file);
-    $toolkit = $image->getToolkit();
-
-    if (!$image->isValid()) {
-      $this->fail(new FormattableMarkup('Could not load image %file.', ['%file' => $file]));
-    }
-    else {
-      // All images should be converted to truecolor when loaded.
-      $image_truecolor = imageistruecolor($toolkit->getResource());
-      $this->assertTrue($image_truecolor, new FormattableMarkup('Image %file after load is a truecolor image.', ['%file' => $file]));
-    }
+    $this->assertTrue($image->isValid(), "Image '$file' after load should be valid, but it is not.");
+    $this->assertTrue(imageistruecolor($image->getToolkit()->getResource()), "Image '$file' after load should be a truecolor image, but it is not.");
   }
 
   /**
    * Tests calling a missing image operation plugin.
    */
-  public function testMissingOperation() {
-
-    // Test that the image factory is set to use the GD toolkit.
-    $this->assertEquals('gd', $this->imageFactory->getToolkitId(), 'The image factory is set to use the \'gd\' image toolkit.');
-
-    // An image file that will be tested.
-    $file = 'image-test.png';
-
+  public function testMissingOperation(): void {
     // Load up a fresh image.
-    $image = $this->imageFactory->get('core/tests/fixtures/files/' . $file);
-    if (!$image->isValid()) {
-      $this->fail(new FormattableMarkup('Could not load image %file.', ['%file' => $file]));
-    }
+    $image = $this->imageFactory->get('core/tests/fixtures/files/image-test.png');
+    $this->assertTrue($image->isValid(), "Image 'image-test.png' after load should be valid, but it is not.");
 
     // Try perform a missing toolkit operation.
-    $this->assertFalse($image->apply('missing_op', []), 'Calling a missing image toolkit operation plugin fails.');
+    $this->assertFalse($image->apply('missing_op', []), 'Calling a missing image toolkit operation plugin should fail, but it did not.');
   }
 
 }
diff --git a/web/core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php b/web/core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php
index 18deac7e359dd8bc5b30b7a299a8c5221ab44115..fe559499f55c28842a02da69170d3fffea104ca9 100644
--- a/web/core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php
+++ b/web/core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php
@@ -179,11 +179,14 @@ protected function getResponseLogHandler() {
               $html_output = 'Called from ' . $caller['function'] . ' line ' . $caller['line'];
               $html_output .= '<hr />' . $request->getMethod() . ' request to: ' . $request->getUri();
 
-              // Get the response body as a string. Any errors are silenced as
-              // tests should not fail if there is a problem. On PHP 7.4
-              // \Drupal\Tests\migrate\Functional\process\DownloadFunctionalTest
-              // fails without the usage of a silence operator.
-              $body = @(string) $response->getBody();
+              /** @var \Psr\Http\Message\StreamInterface $stream */
+              $stream = $response->getBody();
+
+              // Get the response body as a string.
+              $body = $stream->isReadable()
+                ? (string) $stream
+                : 'Response is not readable.';
+
               // On redirect responses (status code starting with '3') we need
               // to remove the meta tag that would do a browser refresh. We
               // don't want to redirect developers away when they look at the
diff --git a/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ComposerHookTest.php b/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ComposerHookTest.php
index 8ff94785d746efca375e304cf33327574903f7bd..1bc89295b481fe5ef8500af84dbdc9037d22e841 100644
--- a/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ComposerHookTest.php
+++ b/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ComposerHookTest.php
@@ -3,10 +3,10 @@
 namespace Drupal\Tests\Composer\Plugin\Scaffold\Functional;
 
 use Composer\Util\Filesystem;
+use Drupal\BuildTests\Framework\BuildTestBase;
 use Drupal\Tests\Composer\Plugin\Scaffold\AssertUtilsTrait;
 use Drupal\Tests\Composer\Plugin\Scaffold\ExecTrait;
 use Drupal\Tests\Composer\Plugin\Scaffold\Fixtures;
-use PHPUnit\Framework\TestCase;
 
 /**
  * Tests Composer Hooks that run scaffold operations.
@@ -22,7 +22,8 @@
  *
  * @group Scaffold
  */
-class ComposerHookTest extends TestCase {
+class ComposerHookTest extends BuildTestBase {
+
   use ExecTrait;
   use AssertUtilsTrait;
 
@@ -120,9 +121,10 @@ public function testComposerHooks() {
     $this->mustExec("composer install --no-ansi", $sut);
     // Require a project that is not allowed to scaffold and confirm that we
     // get a warning, and it does not scaffold.
-    $stdout = $this->mustExec("composer require --no-ansi --no-interaction fixtures/drupal-assets-fixture:dev-main fixtures/scaffold-override-fixture:dev-main", $sut);
+    $this->executeCommand("composer require --no-ansi --no-interaction fixtures/drupal-assets-fixture:dev-main fixtures/scaffold-override-fixture:dev-main", $sut);
+    $this->assertCommandSuccessful();
     $this->assertFileDoesNotExist($sut . '/sites/default/default.settings.php');
-    $this->assertStringContainsString("Not scaffolding files for fixtures/scaffold-override-fixture, because it is not listed in the element 'extra.drupal-scaffold.allowed-packages' in the root-level composer.json file.", $stdout);
+    $this->assertErrorOutputContains('See https://getcomposer.org/allow-plugins');
   }
 
   /**
diff --git a/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/composer-hooks-fixture/composer.json.tmpl b/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/composer-hooks-fixture/composer.json.tmpl
index f5f5d2a2866c6e9ce6fcba1126318262c9967119..d28a71273df1f915da41a3d2f56d30564c1ffd60 100644
--- a/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/composer-hooks-fixture/composer.json.tmpl
+++ b/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/composer-hooks-fixture/composer.json.tmpl
@@ -64,5 +64,10 @@
       "libraries/{$name}": ["type:drupal-library"],
       "drush/Commands/contrib/{$name}": ["type:drupal-drush"]
     }
+  },
+  "config": {
+     "allow-plugins": {
+       "drupal/core-composer-scaffold": true
+     }
   }
 }
diff --git a/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/drupal-drupal/composer.json.tmpl b/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/drupal-drupal/composer.json.tmpl
index 00a91d79591f2460ab05d8d59d384553192f1255..bf8b11d6c4a02801bf5233c43221309682ad3ee1 100644
--- a/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/drupal-drupal/composer.json.tmpl
+++ b/web/core/tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/drupal-drupal/composer.json.tmpl
@@ -67,5 +67,10 @@
       "libraries/{$name}": ["type:drupal-library"],
       "drush/Commands/contrib/{$name}": ["type:drupal-drush"]
     }
-  }
+  },
+   "config": {
+      "allow-plugins": {
+        "drupal/core-composer-scaffold": true
+      }
+   }
 }
diff --git a/web/core/tests/Drupal/Tests/Core/Site/SettingsTest.php b/web/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
index bcc2eda6c9d1d944e267f0b722fbd201aabd9a28..4e9a3ec6fdf84dc8276e29ce4574b0b9a01973e9 100644
--- a/web/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
+++ b/web/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
@@ -353,7 +353,7 @@ public function testDatabaseInfoInitialization(string $driver, ?string $namespac
     if (!empty($expected_autoload)) {
       $class_loader->expects($this->once())
         ->method('addPsr4')
-        ->with($expected_namespace . '\\', $expected_autoload);
+        ->with($expected_namespace . '\\', vfsStream::url('root') . '/' . $expected_autoload);
     }
     else {
       $class_loader->expects($this->never())
diff --git a/web/core/themes/olivero/templates/includes/get-started.html.twig b/web/core/themes/olivero/templates/includes/get-started.html.twig
index e96327a7fca43da374beea5313a9b090f208ab3b..fd9600cb9eebacbc770d82e90db15310ad149ac6 100644
--- a/web/core/themes/olivero/templates/includes/get-started.html.twig
+++ b/web/core/themes/olivero/templates/includes/get-started.html.twig
@@ -14,7 +14,7 @@
 {% set drupal_community = 'https://www.drupal.org/community' %}
 {% set drupal_values = 'https://www.drupal.org/about/values-and-principles' %}
 {% set drupal_user_guide = 'https://www.drupal.org/docs/user_guide/en/index.html' %}
-{% set create_content = '/node/add' %}
+{% set create_content = path('node.add_page')  %}
 {% set drupal_extend = 'https://www.drupal.org/docs/extending-drupal' %}
 {% set drupal_global_training_days = 'https://groups.drupal.org/global-training-days' %}
 {% set drupal_events = 'https://www.drupal.org/community/events' %}
diff --git a/web/core/themes/olivero/templates/views/views-mini-pager.html.twig b/web/core/themes/olivero/templates/views/views-mini-pager.html.twig
index b64be942db8357f2fc43116841dafb3e8f3b43e5..a9acc73a0026a2cac595fa088a9a5e5a2738945f 100644
--- a/web/core/themes/olivero/templates/views/views-mini-pager.html.twig
+++ b/web/core/themes/olivero/templates/views/views-mini-pager.html.twig
@@ -38,7 +38,7 @@
         {% apply spaceless %}
           <li class="pager__item pager__item--control pager__item--next">
             <a href="{{ items.next.href }}" class="pager__link" title="{{ 'Go to next page'|t }}" rel="next"{{ items.next.attributes|without('href', 'title', 'rel') }}>
-              <span class="visually-hidden">{{ 'Previous page'|t }}</span>
+              <span class="visually-hidden">{{ 'Next page'|t }}</span>
               {% include "@olivero/../images/pager-previous.svg" %}
             </a>
           </li>
diff --git a/web/sites/default/default.settings.php b/web/sites/default/default.settings.php
index 72be7750b93a427526891c4d02068fed3c9a74f6..f3dca008fa380e153e86c2a6bb953b4c030184b5 100644
--- a/web/sites/default/default.settings.php
+++ b/web/sites/default/default.settings.php
@@ -490,6 +490,29 @@
  */
 # $settings['file_public_path'] = 'sites/default/files';
 
+/**
+ * Additional public file schemes:
+ *
+ * Public schemes are URI schemes that allow download access to all users for
+ * all files within that scheme.
+ *
+ * The "public" scheme is always public, and the "private" scheme is always
+ * private, but other schemes, such as "https", "s3", "example", or others,
+ * can be either public or private depending on the site. By default, they're
+ * private, and access to individual files is controlled via
+ * hook_file_download().
+ *
+ * Typically, if a scheme should be public, a module makes it public by
+ * implementing hook_file_download(), and granting access to all users for all
+ * files. This could be either the same module that provides the stream wrapper
+ * for the scheme, or a different module that decides to make the scheme
+ * public. However, in cases where a site needs to make a scheme public, but
+ * is unable to add code in a module to do so, the scheme may be added to this
+ * variable, the result of which is that system_file_download() grants public
+ * access to all files within that scheme.
+ */
+# $settings['file_additional_public_schemes'] = ['example'];
+
 /**
  * Private file path:
  *