diff --git a/.gitignore b/.gitignore
index 019564cae8f3441b6703239751dc834841a3005b..01a8abd27b4b0f6a8048499227a5a6d988525a26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,7 +31,6 @@
 /.env
 /.env.pipeline
 /behat.yml
-/grumphp.yml
 /phpcs.xml
 /runner.yml
 /web/sites/default/services.yml
diff --git a/.opts.yml b/.opts.yml
index 602648e7dd21dc200be54e394da00c87aabb2283..687d4a91cf7ae97ca070cb51a4f344c016b90863 100644
--- a/.opts.yml
+++ b/.opts.yml
@@ -24,9 +24,9 @@ upgrade_commands:
       - ./vendor/bin/drush cache:rebuild
       - rm disable-config-readonly
 
-php_version: 7.4
+php_version: 8.1
 extra_pkgs:
-  - php7.4-apcu
+  - php8.1-apcu
 
 mysql_version: "8.0"
 
diff --git a/behat.yml.dist b/behat.yml.dist
index 67e2fab022262d1fe5948f7ee7a3597dcc9dc145..96c274422daaab2cd446fda7294a5398b6cbfe0d 100644
--- a/behat.yml.dist
+++ b/behat.yml.dist
@@ -11,6 +11,7 @@
   # Ref. https://github.com/Behat/Behat/issues/62
   # Ref. https://citnet.tech.ec.europa.eu/CITnet/jira/browse/ISAICP-6060
   - Drupal\joinup\Context\TallinnContext
+  - Drupal\joinup\Context\AccordionContext
   - Drupal\joinup\Context\AdmsValidatorContext
   - Drupal\joinup\Context\AssetDistributionContext
   - Drupal\joinup\Context\AssetReleaseContext
@@ -90,7 +91,7 @@ default:
       base_url: ${env.DRUPAL_BASE_URL}
       ajax_timeout: 10
       files_path: ${joinup.dir}/tests/fixtures/files
-      goutte: ~
+      browserkit_http: ~
       javascript_session: selenium2
       browser_name: ${behat.browser_name}
       selenium2:
diff --git a/composer.json b/composer.json
index ebc569c2bce93ecc56e884b29238d059a7c9a2d4..b346a9abfb3d7b2e3a95be9f0a6ebd96b4c03f7b 100644
--- a/composer.json
+++ b/composer.json
@@ -4,7 +4,7 @@
     "type": "project",
     "license": "EUPL-1.2",
     "require": {
-        "php": ">=7.4",
+        "php": ">=8.1.3",
         "ext-dom": "*",
         "ext-json": "*",
         "ext-pdo": "*",
@@ -34,7 +34,7 @@
         "drupal/embed_block": "^1.0",
         "drupal/entity_legal": "^3.0.0",
         "drupal/entityqueue": "^1.2",
-        "drupal/error_page": "^1.0 || ^2.0",
+        "drupal/error_page": "^2.0",
         "drupal/facets": "2.0.1",
         "drupal/facets_block": "^1.4",
         "drupal/facets_date_range": "^1.0@beta",
@@ -44,7 +44,7 @@
         "drupal/field_permissions": "^1.1",
         "drupal/file_url": "~2.0",
         "drupal/flag": "^4.0",
-        "drupal/geocoder": "^3.0",
+        "drupal/geocoder": "^4.4",
         "drupal/geofield": "~1.6",
         "drupal/honeypot": "~2",
         "drupal/iframe": "2.11.0",
@@ -58,10 +58,10 @@
         "drupal/menu_link_destination": "^1.0",
         "drupal/message": "^1.1",
         "drupal/message_digest": "^1.0.0",
-        "drupal/message_notify": "~1.2",
+        "drupal/message_notify": "~1.3",
         "drupal/meta_entity": "^1.2",
         "drupal/monolog": "^2.0",
-        "drupal/og": "^1.0-alpha7",
+        "drupal/og": "^1.0-alpha8",
         "drupal/og_menu": "^2.0",
         "drupal/page_manager": "^4.0@beta",
         "drupal/paragraphs": "^1.12",
@@ -97,7 +97,7 @@
         "drupal/views_bulk_operations": "^4",
         "drupal/views_data_export": "^1.0",
         "drupal/views_multiple_permissions": "^1.0",
-        "drush/drush": "^11.0",
+        "drush/drush": "^11.3",
         "ec-europa/joinup-tallinn-dashboard": "1.0.0-alpha2",
         "ec-europa/material-design-lite": "1.3.1",
         "ec-europa/spdx": "^1.0",
@@ -106,9 +106,10 @@
         "openeuropa/composer-artifacts": "^1.0",
         "openeuropa/oe_bootstrap_theme": "^1.0",
         "openeuropa/oe_dashboard_agent": "^0.3.0",
-        "openeuropa/oe_webtools": "^1.14",
+        "openeuropa/oe_webtools": "^1.19",
         "openeuropa/webtools-geocoding-provider": "~0.1",
-        "semiceu/adms-ap_validator": "1.0.0-alpha1"
+        "semiceu/adms-ap_validator": "1.0.0-alpha1",
+        "sweetrdf/easyrdf": "^1.7.1"
     },
     "require-dev": {
         "ext-fileinfo": "*",
@@ -119,15 +120,14 @@
         "drupal/coder": "^8.3.11",
         "drupal/composer_deploy": "^1.6",
         "drupal/config_update": "^1.7",
-        "drupal/devel": "^4.0",
-        "drupal/drupal-driver": "^2.1.0",
-        "drupal/drupal-extension": "^4.1",
+        "drupal/devel": "^5.0",
+        "drupal/drupal-extension": "dev-use-guzzle as 4.2.999",
         "drupal/filecache": "^1",
         "drupal/renderviz": "^1.0",
-        "drupal/upgrade_status": "^3.12",
-        "drupaltest/behat-one-time-login": "^1.0",
-        "ec-europa/toolkit": "^8.6.12",
-        "lovers-of-behat/table-extension": "^1.2.0",
+        "drupal/upgrade_status": "^3.14",
+        "drupaltest/behat-one-time-login": "dev-drupal-extension as 1.0.999",
+        "ec-europa/toolkit": "~9.0.0",
+        "lovers-of-behat/table-extension": "dev-drop-behat-mink-extension",
         "mikey179/vfsstream": "~1.6",
         "palantirnet/drupal-rector": "^0.12.2",
         "pear/http_request2": "~2.4",
@@ -142,7 +142,7 @@
         "symfony/dom-crawler": "^4.4",
         "symfony/phpunit-bridge": "^5.4",
         "vlucas/phpdotenv": "~5",
-        "weitzman/drupal-test-traits": "^1.5",
+        "weitzman/drupal-test-traits": "2.x-dev",
         "weitzman/logintrait": "^1.1"
     },
     "replace": {
@@ -157,17 +157,15 @@
     "config": {
         "sort-packages": true,
         "platform": {
-            "php": "7.4.0"
+            "php": "8.1.3"
         },
         "allow-plugins": {
             "dealerdirect/phpcodesniffer-composer-installer": true,
             "cweagans/composer-patches": true,
             "composer/installers": true,
-            "phpro/grumphp": true,
             "drupal/core-composer-scaffold": true,
-            "foxy/foxy": true,
             "openeuropa/composer-artifacts": true,
-            "zaporylie/composer-drupal-optimizations": false
+            "phpstan/extension-installer": true
         }
     },
     "autoload": {
@@ -250,28 +248,29 @@
                 "Use READ COMMITTED by default for MySQL transactions @see https://www.drupal.org/project/drupal/issues/1650930": "https://git.drupalcode.org/project/drupal/-/merge_requests/2394.diff",
                 "Allow image style to be selected in text editor @see https://www.drupal.org/node/2061377": "https://git.drupalcode.org/project/drupal/-/merge_requests/2344.diff",
                 "Allow making the file description a required field @see https://www.drupal.org/node/2320877": "https://git.drupalcode.org/project/drupal/-/merge_requests/975.diff",
-                "Delete should not be the default action on /admin/content @see https://www.drupal.org/project/drupal/issues/2381293": "https://git.drupalcode.org/project/drupal/-/merge_requests/1670.diff",
+                "Delete should not be the default action on /admin/content @see https://www.drupal.org/project/drupal/issues/2381293": "resources/patch/drupal/core/2381293.diff",
                 "Regression: Do not bypass route access with 'link to any page' permissions for menu links @see https://www.drupal.org/project/drupal/issues/2463753": "https://www.drupal.org/files/issues/2021-09-15/2463753-87_0.patch",
                 "Upcast named arguments/named parameters in views @see https://www.drupal.org/project/drupal/issues/2528166": "https://git.drupalcode.org/project/drupal/-/merge_requests/1323.diff",
                 "Confirmation cancel links are incorrect if installed in a subdirectory @see https://www.drupal.org/project/drupal/issues/2582295": "https://www.drupal.org/files/issues/2021-08-23/2582295-52.patch",
                 "Allow plurals on bundle labels @see https://www.drupal.org/node/2765065": "https://git.drupalcode.org/project/drupal/-/merge_requests/1652.diff",
-                "Enlarge file_usage entity ID length. @see https://www.drupal.org/node/2675600": "https://www.drupal.org/files/issues/2675600-30.patch",
+                "Enlarge file_usage entity ID length. @see https://www.drupal.org/node/2675600": "resources/patch/drupal/core/2675600.diff",
                 "Menu link plugins should provide a way for the link to be conditionally hidden @see https://www.drupal.org/project/drupal/issues/2719609": "https://www.drupal.org/files/issues/2719609-2.patch",
-                "New option for Views page displays to use the admin theme @see https://www.drupal.org/node/2719797": "https://www.drupal.org/files/issues/2719797-65.patch",
+                "New option for Views page displays to use the admin theme @see https://www.drupal.org/node/2719797": "https://www.drupal.org/files/issues/2022-09-20/2719797-144.patch",
                 "Make the tab active when the fragment is present in URL @see https://www.drupal.org/project/drupal/issues/2752511": "https://www.drupal.org/files/issues/2022-06-17/2752511-109-9.5.x.patch",
                 "Add thread depth configuration to comments. Includes patch for parent issue #2879087. @see https://www.drupal.org/project/drupal/issues/2786587 @see https://www.drupal.org/project/drupal/issues/2879087": "https://www.drupal.org/files/issues/2022-01-17/2786587-58-9.3.x.patch",
                 "Set fixed depth for comment threads.": "resources/patch/2786587-thread-depth-fixed-limit.patch",
                 "Views with a different query plugin created via the UI do not have the correct query plugin ID in the view config @see https://www.drupal.org/project/drupal/issues/2836237": "https://www.drupal.org/files/issues/2022-01-17/2836237-49-9.3.x.patch",
                 "Disable tableselect element options @see https://www.drupal.org/project/drupal/issues/2895352": "https://www.drupal.org/files/issues/2021-12-04/2895352-53.patch",
-                "Pass current route parameters to the confirmation form route @see https://www.drupal.org/project/drupal/issues/2901412": "https://git.drupalcode.org/project/drupal/-/merge_requests/1666.diff",
+                "Pass current route parameters to the confirmation form route @see https://www.drupal.org/project/drupal/issues/2901412": "resources/patch/2901412-25.diff",
                 "Lazy services: support PHP7 return types in generate-proxy-class @see https://www.drupal.org/node/2919243": "https://www.drupal.org/files/issues/2919243-2.patch",
                 "Cache tags are not invalidated on revision delete @see https://www.drupal.org/project/drupal/issues/2945928": "https://www.drupal.org/files/issues/entity-cache_revision_deletion-2945928-2.patch",
-                "Users w/o access to content should still have configurable access to the content URL @see https://www.drupal.org/project/drupal/issues/3008254": "https://www.drupal.org/files/issues/2022-01-17/3008254-26-9.3.x.patch",
                 "Make it easier to trigger a tour @see https://www.drupal.org/project/drupal/issues/3012027": "https://www.drupal.org/files/issues/2022-01-17/3012027-52-9.3.x.patch",
                 "EntityConstraintValidationList::findByCode is inconsistent @see https://www.drupal.org/project/drupal/issues/3126654": "https://www.drupal.org/files/issues/2020-04-10/find_by_code_override-3126654-D8-4.patch",
                 "Cannot implement a custom user cancellation method @see https://www.drupal.org/project/drupal/issues/3135592": "https://git.drupalcode.org/project/drupal/-/merge_requests/1675.diff",
                 "The old storage handler is still defined for RDF entities.": "resources/patch/core-fix-sparql-storage-hack.patch",
-                "Add option to show only start or end date in the DateTime Range custom formatter @see https://www.drupal.org/project/drupal/issues/2827055": "https://www.drupal.org/files/issues/2022-06-16/2827055-69.patch"
+                "Add option to show only start or end date in the DateTime Range custom formatter @see https://www.drupal.org/project/drupal/issues/2827055": "https://www.drupal.org/files/issues/2022-06-16/2827055-69.patch",
+                "file_requirements() can trigger a PHP 8.1 deprecation notice when called without a SERVER_SOFTWARE server env variable @see https://www.drupal.org/project/drupal/issues/3279289": "https://git.drupalcode.org/project/drupal/-/merge_requests/2247.diff",
+                "If you don't set the \"version\" of a profile, the report/status displays an empty dash @see https://www.drupal.org/project/drupal/issues/3270892": "https://git.drupalcode.org/project/drupal/-/merge_requests/2003.diff"
             },
             "drupal/email_confirmer": {
                 "Support for HTML mails @see https://www.drupal.org/i/3047124": "https://git.drupalcode.org/project/email_confirmer/-/merge_requests/3.diff"
@@ -307,7 +306,7 @@
                 "Ensure backward compatibility with Piwik @see https://www.drupal.org/project/matomo_reporting_api/issues/3080854": "https://www.drupal.org/files/issues/2019-09-18/3080854-7.patch"
             },
             "drupal/message_notify": {
-                "Allow 3rd-party to act before delivery @see https://www.drupal.org/project/message_notify/issues/3314370": "resources/patch/message_notify-diff-8.x-1.2-3314370.diff"
+                "Allow 3rd-party to act before delivery @see https://www.drupal.org/project/message_notify/issues/3314370": "resources/patch/drupal/message_notify/3314370.diff"
             },
             "drupal/meta_entity": {
                 "Make the field configurable in the view @see https://www.drupal.org/project/meta_entity/issues/3279161": "https://git.drupalcode.org/project/meta_entity/-/merge_requests/4.diff",
@@ -373,15 +372,20 @@
                 "Views block area missing schema @see https://www.drupal.org/project/views_block_area/issues/3157188": "https://www.drupal.org/files/issues/2020-07-06/views_block_area-missing_schema-3157188-2.patch"
             },
             "ec-europa/toolkit": {
-                "Add --strict option, it should treat Undefined and Pending steps as failures @see https://github.com/ec-europa/toolkit/pull/559": "https://patch-diff.githubusercontent.com/raw/ec-europa/toolkit/pull/559.diff"
+                "Add --strict option, it should treat Undefined and Pending steps as failures @see https://github.com/ec-europa/toolkit/pull/566": "resources/patch/ec-europa/toolkit/566.diff"
             },
             "openeuropa/oe_webtools": {
                 "Allow to pass an optional referer. @see https://github.com/openeuropa/oe_webtools/pull/96": "https://patch-diff.githubusercontent.com/raw/openeuropa/oe_webtools/pull/96.diff",
                 "Place the webtools loader on the head. @see https://github.com/openeuropa/oe_webtools/pull/102": "https://patch-diff.githubusercontent.com/raw/openeuropa/oe_webtools/pull/102.diff",
-                "Add the possibility to display a marker on the map. @see https://github.com/openeuropa/oe_webtools/pull/111": "https://patch-diff.githubusercontent.com/raw/openeuropa/oe_webtools/pull/111.diff"
-            },
-            "openeuropa/task-runner": {
-                "Command config cannot be overridden @see https://github.com/openeuropa/task-runner/pull/135": "https://patch-diff.githubusercontent.com/raw/openeuropa/task-runner/pull/135.diff"
+                "Add the possibility to display a marker on the map. @see https://github.com/openeuropa/oe_webtools/pull/111": "https://patch-diff.githubusercontent.com/raw/openeuropa/oe_webtools/pull/111.diff",
+                "PHP 8.1 notices @see https://github.com/openeuropa/oe_webtools/pull/182": "https://patch-diff.githubusercontent.com/raw/openeuropa/oe_webtools/pull/182.diff"
+            }
+        },
+        "patches-ignore": {
+            "openeuropa/oe_bootstrap_theme": {
+                "drupal/ui_patterns": {
+                    "Fix unable to detect a pattern from default theme having same id as the pattern in the base theme @see https://github.com/nuvoleweb/ui_patterns/issues/304": "https://patch-diff.githubusercontent.com/raw/nuvoleweb/ui_patterns/pull/318.diff"
+                }
             }
         },
         "artifacts": {
@@ -406,6 +410,10 @@
                 }
             }
         },
+        {
+            "type": "vcs",
+            "url": "https://github.com/claudiu-cristea/drupalextension.git"
+        },
         {
             "type": "vcs",
             "url": "https://github.com/ec-europa/joinup-tallinn-dashboard.git"
diff --git a/composer.lock b/composer.lock
index d167db345a171eaa47cfcf29b523ddb9cdbf4833..d0742284d991c0811a9e5e1b896adf16838bd59a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "560b38cdd25c4db7731fc79bf2fcfd06",
+    "content-hash": "6cc3f47900955f58b287793c00fc46be",
     "packages": [
         {
             "name": "asm89/stack-cors",
@@ -909,24 +909,23 @@
         },
         {
             "name": "consolidation/site-alias",
-            "version": "3.1.7",
+            "version": "4.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/consolidation/site-alias.git",
-                "reference": "3b6519592c7e8557423f935806cd73adf69ed6c7"
+                "reference": "103fbc9bad6bbadb1f7533454a8f070ddce18e13"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/consolidation/site-alias/zipball/3b6519592c7e8557423f935806cd73adf69ed6c7",
-                "reference": "3b6519592c7e8557423f935806cd73adf69ed6c7",
+                "url": "https://api.github.com/repos/consolidation/site-alias/zipball/103fbc9bad6bbadb1f7533454a8f070ddce18e13",
+                "reference": "103fbc9bad6bbadb1f7533454a8f070ddce18e13",
                 "shasum": ""
             },
             "require": {
                 "consolidation/config": "^1.2.1 || ^2",
-                "php": ">=5.5.0",
-                "symfony/filesystem": "^4.4 || ^5.4 || ^6",
-                "symfony/finder": "~2.3 || ^3 || ^4.4 || ^5 || ^6",
-                "webmozart/path-util": "^2.3"
+                "php": ">=7.4",
+                "symfony/filesystem": "^5.4 || ^6",
+                "symfony/finder": "^5 || ^6"
             },
             "require-dev": {
                 "php-coveralls/php-coveralls": "^2.4.2",
@@ -938,7 +937,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "3.x-dev"
+                    "dev-main": "4.x-dev"
                 }
             },
             "autoload": {
@@ -963,9 +962,9 @@
             "description": "Manage alias records for local and remote sites.",
             "support": {
                 "issues": "https://github.com/consolidation/site-alias/issues",
-                "source": "https://github.com/consolidation/site-alias/tree/3.1.7"
+                "source": "https://github.com/consolidation/site-alias/tree/4.0.0"
             },
-            "time": "2022-10-15T01:21:09+00:00"
+            "time": "2022-10-14T03:41:22+00:00"
         },
         {
             "name": "consolidation/site-process",
@@ -1075,31 +1074,28 @@
         },
         {
             "name": "davedevelopment/stiphle",
-            "version": "0.9.3",
+            "version": "0.9.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/davedevelopment/stiphle.git",
-                "reference": "634bd16c6b0a7e8f81a961e9ddc53916fe3ba939"
+                "reference": "76151e6474741adee258c1a4860a0460e319563b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/davedevelopment/stiphle/zipball/634bd16c6b0a7e8f81a961e9ddc53916fe3ba939",
-                "reference": "634bd16c6b0a7e8f81a961e9ddc53916fe3ba939",
+                "url": "https://api.github.com/repos/davedevelopment/stiphle/zipball/76151e6474741adee258c1a4860a0460e319563b",
+                "reference": "76151e6474741adee258c1a4860a0460e319563b",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.6.0|^7.0"
+                "php": ">=5.3.1"
             },
             "require-dev": {
-                "doctrine/cache": "^1.0",
-                "phpunit/phpunit": "^6.5|^7.5|^8.4",
-                "predis/predis": "^1.1",
-                "zendframework/zend-cache": "^2.8"
+                "phpunit/phpunit": "^5.5",
+                "predis/predis": "^1.1"
             },
             "suggest": {
                 "doctrine/cache": "~1.0",
-                "predis/predis": "~1.1",
-                "zendframework/zend-cache": "^2.8"
+                "predis/predis": "~1.1"
             },
             "type": "library",
             "autoload": {
@@ -1128,22 +1124,22 @@
             ],
             "support": {
                 "issues": "https://github.com/davedevelopment/stiphle/issues",
-                "source": "https://github.com/davedevelopment/stiphle/tree/master"
+                "source": "https://github.com/davedevelopment/stiphle/tree/0.9.2"
             },
-            "time": "2019-10-22T20:06:21+00:00"
+            "time": "2017-08-16T07:58:18+00:00"
         },
         {
             "name": "dflydev/dot-access-data",
-            "version": "v3.0.1",
+            "version": "v3.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/dflydev/dflydev-dot-access-data.git",
-                "reference": "0992cc19268b259a39e86f296da5f0677841f42c"
+                "reference": "f41715465d65213d644d3141a6a93081be5d3549"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/0992cc19268b259a39e86f296da5f0677841f42c",
-                "reference": "0992cc19268b259a39e86f296da5f0677841f42c",
+                "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549",
+                "reference": "f41715465d65213d644d3141a6a93081be5d3549",
                 "shasum": ""
             },
             "require": {
@@ -1154,7 +1150,7 @@
                 "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3",
                 "scrutinizer/ocular": "1.6.0",
                 "squizlabs/php_codesniffer": "^3.5",
-                "vimeo/psalm": "^3.14"
+                "vimeo/psalm": "^4.0.0"
             },
             "type": "library",
             "extra": {
@@ -1203,9 +1199,9 @@
             ],
             "support": {
                 "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
-                "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.1"
+                "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2"
             },
-            "time": "2021-08-13T13:06:58+00:00"
+            "time": "2022-10-27T11:44:00+00:00"
         },
         {
             "name": "doctrine/annotations",
@@ -3441,29 +3437,26 @@
         },
         {
             "name": "drupal/field_group",
-            "version": "3.3.0",
+            "version": "3.4.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/field_group.git",
-                "reference": "8.x-3.3"
+                "reference": "8.x-3.4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/field_group-8.x-3.3.zip",
-                "reference": "8.x-3.3",
-                "shasum": "c7a423b1d7643ee40dd1543d72fa04e8ac1756e4"
+                "url": "https://ftp.drupal.org/files/projects/field_group-8.x-3.4.zip",
+                "reference": "8.x-3.4",
+                "shasum": "80b937e1a11f8b29c69d853fc4bf798c057c6f94"
             },
             "require": {
-                "drupal/core": "^8.8 || ^9"
-            },
-            "require-dev": {
-                "drupal/jquery_ui_accordion": "^1.0"
+                "drupal/core": "^9.2 || ^10"
             },
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-3.3",
-                    "datestamp": "1663516404",
+                    "version": "8.x-3.4",
+                    "datestamp": "1667241979",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -3710,23 +3703,23 @@
         },
         {
             "name": "drupal/geocoder",
-            "version": "3.31.0",
+            "version": "4.4.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/geocoder.git",
-                "reference": "8.x-3.31"
+                "reference": "8.x-4.4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/geocoder-8.x-3.31.zip",
-                "reference": "8.x-3.31",
-                "shasum": "f6a24695f1fefa1c52a6119dd02c329410d22ce6"
+                "url": "https://ftp.drupal.org/files/projects/geocoder-8.x-4.4.zip",
+                "reference": "8.x-4.4",
+                "shasum": "916de7e05f2a24fd4260717bfa8825c6736ffbac"
             },
             "require": {
                 "davedevelopment/stiphle": "^0.9.2",
-                "drupal/core": "^8.8 || ^9",
+                "drupal/core": "^9 || ^10",
                 "php": ">=7.3.0",
-                "php-http/guzzle6-adapter": "^1.1 || ^2.0",
+                "php-http/guzzle7-adapter": "^1.0",
                 "php-http/message": "^1.6",
                 "willdurand/geocoder": "^4.0"
             },
@@ -3763,8 +3756,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-3.31",
-                    "datestamp": "1663974561",
+                    "version": "8.x-4.4",
+                    "datestamp": "1664284253",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -3833,17 +3826,17 @@
         },
         {
             "name": "drupal/geofield",
-            "version": "1.45.0",
+            "version": "1.46.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/geofield.git",
-                "reference": "8.x-1.45"
+                "reference": "8.x-1.46"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/geofield-8.x-1.45.zip",
-                "reference": "8.x-1.45",
-                "shasum": "64451e5e8e7d152283e0e588f27ab4f2d6f3af24"
+                "url": "https://ftp.drupal.org/files/projects/geofield-8.x-1.46.zip",
+                "reference": "8.x-1.46",
+                "shasum": "2e3d1e933b42623b9c44660937cee9124c6abfed"
             },
             "require": {
                 "drupal/core": "^8.8 || ^9 || ^10",
@@ -3852,8 +3845,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.45",
-                    "datestamp": "1665693991",
+                    "version": "8.x-1.46",
+                    "datestamp": "1666260947",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -4624,20 +4617,20 @@
         },
         {
             "name": "drupal/message",
-            "version": "1.2.0",
+            "version": "1.4.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/message.git",
-                "reference": "8.x-1.2"
+                "reference": "8.x-1.4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/message-8.x-1.2.zip",
-                "reference": "8.x-1.2",
-                "shasum": "f1494d8c482840b01f8d1dcc4ed572d5844a3873"
+                "url": "https://ftp.drupal.org/files/projects/message-8.x-1.4.zip",
+                "reference": "8.x-1.4",
+                "shasum": "4158df35b5506fc88061358624589c4a04c414a2"
             },
             "require": {
-                "drupal/core": "^8 || ^9"
+                "drupal/core": "^9 || ^10"
             },
             "require-dev": {
                 "drupal/token": "*"
@@ -4645,8 +4638,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.2",
-                    "datestamp": "1607017386",
+                    "version": "8.x-1.4",
+                    "datestamp": "1667584508",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -4655,7 +4648,7 @@
             },
             "notification-url": "https://packages.drupal.org/8/downloads",
             "license": [
-                "GPL-2.0+"
+                "GPL-2.0-or-later"
             ],
             "authors": [
                 {
@@ -4749,21 +4742,21 @@
         },
         {
             "name": "drupal/message_notify",
-            "version": "1.2.0",
+            "version": "1.3.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/message_notify.git",
-                "reference": "8.x-1.2"
+                "reference": "8.x-1.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/message_notify-8.x-1.2.zip",
-                "reference": "8.x-1.2",
-                "shasum": "10e91b84c817ef2c21590d273487c5259d1e7a6c"
+                "url": "https://ftp.drupal.org/files/projects/message_notify-8.x-1.3.zip",
+                "reference": "8.x-1.3",
+                "shasum": "f7ce3a6989a45f4c23173cef7596891d24d2652c"
             },
             "require": {
-                "drupal/core": "^8 || ^9",
-                "drupal/message": "~1.0"
+                "drupal/core": "^9 || ^10",
+                "drupal/message": "^1.0"
             },
             "require-dev": {
                 "drupal/message": "*",
@@ -4772,8 +4765,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.2",
-                    "datestamp": "1603382083",
+                    "version": "8.x-1.3",
+                    "datestamp": "1667430680",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -6034,20 +6027,20 @@
         },
         {
             "name": "drupal/redis",
-            "version": "1.5.0",
+            "version": "1.6.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/redis.git",
-                "reference": "8.x-1.5"
+                "reference": "8.x-1.6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/redis-8.x-1.5.zip",
-                "reference": "8.x-1.5",
-                "shasum": "4283333dc2bf405045765b83ca662acc409a6543"
+                "url": "https://ftp.drupal.org/files/projects/redis-8.x-1.6.zip",
+                "reference": "8.x-1.6",
+                "shasum": "9e21a03743030e09a8b98da49c4549bd4b83251a"
             },
             "require": {
-                "drupal/core": "^8.8 || ^9"
+                "drupal/core": "^9.3 || ^10"
             },
             "suggest": {
                 "predis/predis": "^1.1.1"
@@ -6055,8 +6048,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.5",
-                    "datestamp": "1609972488",
+                    "version": "8.x-1.6",
+                    "datestamp": "1667512839",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -6311,17 +6304,17 @@
         },
         {
             "name": "drupal/search_api",
-            "version": "1.27.0",
+            "version": "1.28.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/search_api.git",
-                "reference": "8.x-1.27"
+                "reference": "8.x-1.28"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/search_api-8.x-1.27.zip",
-                "reference": "8.x-1.27",
-                "shasum": "b8c9a055fe43435c09231fd93d3e07c5d2863a46"
+                "url": "https://ftp.drupal.org/files/projects/search_api-8.x-1.28.zip",
+                "reference": "8.x-1.28",
+                "shasum": "d3ae0bb3cf17c986d5e0c6edb87aee6580b6fc1e"
             },
             "require": {
                 "drupal/core": "^9.3 || ^10.0"
@@ -6342,8 +6335,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.27",
-                    "datestamp": "1666211720",
+                    "version": "8.x-1.28",
+                    "datestamp": "1667814116",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -7658,20 +7651,21 @@
         },
         {
             "name": "drupal/views_bulk_operations",
-            "version": "4.2.0",
+            "version": "4.2.1",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/views_bulk_operations.git",
-                "reference": "4.2.0"
+                "reference": "4.2.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/views_bulk_operations-4.2.0.zip",
-                "reference": "4.2.0",
-                "shasum": "b18fd9a43c47ffaf20f5f888871ff801b6f9f99f"
+                "url": "https://ftp.drupal.org/files/projects/views_bulk_operations-4.2.1.zip",
+                "reference": "4.2.1",
+                "shasum": "3bce967e24c0ce19fc7e0de031594729e22c38ef"
             },
             "require": {
-                "drupal/core": "^9.4 || ^10"
+                "drupal/core": "^9.4 || ^10",
+                "php": ">=7.4.0"
             },
             "require-dev": {
                 "drush/drush": "^11"
@@ -7682,8 +7676,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "4.2.0",
-                    "datestamp": "1664360435",
+                    "version": "4.2.1",
+                    "datestamp": "1666185226",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -7843,16 +7837,16 @@
         },
         {
             "name": "drush/drush",
-            "version": "11.2.1",
+            "version": "11.3.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/drush-ops/drush.git",
-                "reference": "95123e003c96f4c57299fa277ef60457041cae1a"
+                "reference": "57cd12235f0a8b3aaabc841fd6c82b64f3dffc02"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/drush-ops/drush/zipball/95123e003c96f4c57299fa277ef60457041cae1a",
-                "reference": "95123e003c96f4c57299fa277ef60457041cae1a",
+                "url": "https://api.github.com/repos/drush-ops/drush/zipball/57cd12235f0a8b3aaabc841fd6c82b64f3dffc02",
+                "reference": "57cd12235f0a8b3aaabc841fd6c82b64f3dffc02",
                 "shasum": ""
             },
             "require": {
@@ -7862,7 +7856,7 @@
                 "consolidation/config": "^2",
                 "consolidation/filter-via-dot-access-data": "^2",
                 "consolidation/robo": "^3.0.9 || ^4.0.1",
-                "consolidation/site-alias": "^3.1.3",
+                "consolidation/site-alias": "^3.1.6 || ^4",
                 "consolidation/site-process": "^4.1.3 || ^5",
                 "enlightn/security-checker": "^1",
                 "ext-dom": "*",
@@ -7871,12 +7865,12 @@
                 "php": ">=7.4",
                 "psy/psysh": "~0.11",
                 "symfony/event-dispatcher": "^4.0 || ^5.0 || ^6.0",
+                "symfony/filesystem": "^4.4 || ^5.4 || ^6.1",
                 "symfony/finder": "^4.0 || ^5 || ^6",
                 "symfony/polyfill-php80": "^1.23",
                 "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0",
                 "symfony/yaml": "^4.0 || ^5.0 || ^6.0",
-                "webflo/drupal-finder": "^1.2",
-                "webmozart/path-util": "^2.1.0"
+                "webflo/drupal-finder": "^1.2"
             },
             "conflict": {
                 "drupal/core": "< 9.2",
@@ -7974,10 +7968,9 @@
             "homepage": "http://www.drush.org",
             "support": {
                 "forum": "http://drupal.stackexchange.com/questions/tagged/drush",
-                "irc": "irc://irc.freenode.org/drush",
                 "issues": "https://github.com/drush-ops/drush/issues",
                 "slack": "https://drupal.slack.com/messages/C62H9CWQM",
-                "source": "https://github.com/drush-ops/drush/tree/11.2.1"
+                "source": "https://github.com/drush-ops/drush/tree/11.3.2"
             },
             "funding": [
                 {
@@ -7985,82 +7978,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2022-09-23T17:35:58+00:00"
-        },
-        {
-            "name": "easyrdf/easyrdf",
-            "version": "1.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/easyrdf/easyrdf.git",
-                "reference": "c7b0a9dbcb211eb7de03ee99ff5b52d17f2a8e64"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/easyrdf/easyrdf/zipball/c7b0a9dbcb211eb7de03ee99ff5b52d17f2a8e64",
-                "reference": "c7b0a9dbcb211eb7de03ee99ff5b52d17f2a8e64",
-                "shasum": ""
-            },
-            "require": {
-                "ext-dom": "*",
-                "ext-mbstring": "*",
-                "ext-pcre": "*",
-                "ext-xmlreader": "*",
-                "lib-libxml": "*",
-                "php": ">=7.1.0"
-            },
-            "require-dev": {
-                "code-lts/doctum": "^5",
-                "ml/json-ld": "~1.0",
-                "phpunit/phpunit": "^7",
-                "semsol/arc2": "^2.4",
-                "squizlabs/php_codesniffer": "3.*",
-                "zendframework/zend-http": "~2.3"
-            },
-            "suggest": {
-                "ml/json-ld": "~1.0",
-                "semsol/arc2": "~2.2"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "EasyRdf\\": "lib"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Nicholas Humfrey",
-                    "email": "njh@aelius.com",
-                    "homepage": "http://www.aelius.com/njh/",
-                    "role": "Developer"
-                },
-                {
-                    "name": "Alexey Zakhlestin",
-                    "email": "indeyets@gmail.com",
-                    "homepage": "http://indeyets.ru/",
-                    "role": "Developer"
-                }
-            ],
-            "description": "EasyRdf is a PHP library designed to make it easy to consume and produce RDF.",
-            "homepage": "http://www.easyrdf.org/",
-            "keywords": [
-                "Linked Data",
-                "RDF",
-                "Semantic Web",
-                "Turtle",
-                "rdfa",
-                "sparql"
-            ],
-            "support": {
-                "forum": "http://groups.google.com/group/easyrdf/",
-                "issues": "http://github.com/easyrdf/easyrdf/issues",
-                "source": "https://github.com/easyrdf/easyrdf/tree/1.1.1"
-            },
-            "time": "2020-12-02T08:47:31+00:00"
+            "time": "2022-10-24T14:01:14+00:00"
         },
         {
             "name": "ec-europa/joinup-tallinn-dashboard",
@@ -8477,37 +8395,49 @@
         },
         {
             "name": "guzzlehttp/guzzle",
-            "version": "6.5.8",
+            "version": "7.5.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/guzzle.git",
-                "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981"
+                "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981",
-                "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981",
+                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba",
+                "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba",
                 "shasum": ""
             },
             "require": {
                 "ext-json": "*",
-                "guzzlehttp/promises": "^1.0",
-                "guzzlehttp/psr7": "^1.9",
-                "php": ">=5.5",
-                "symfony/polyfill-intl-idn": "^1.17"
+                "guzzlehttp/promises": "^1.5",
+                "guzzlehttp/psr7": "^1.9 || ^2.4",
+                "php": "^7.2.5 || ^8.0",
+                "psr/http-client": "^1.0",
+                "symfony/deprecation-contracts": "^2.2 || ^3.0"
+            },
+            "provide": {
+                "psr/http-client-implementation": "1.0"
             },
             "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.1",
                 "ext-curl": "*",
-                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
-                "psr/log": "^1.1"
+                "php-http/client-integration-tests": "^3.0",
+                "phpunit/phpunit": "^8.5.29 || ^9.5.23",
+                "psr/log": "^1.1 || ^2.0 || ^3.0"
             },
             "suggest": {
+                "ext-curl": "Required for CURL handler support",
+                "ext-intl": "Required for Internationalized Domain Name (IDN) support",
                 "psr/log": "Required for using the Log middleware"
             },
             "type": "library",
             "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                },
                 "branch-alias": {
-                    "dev-master": "6.5-dev"
+                    "dev-master": "7.5-dev"
                 }
             },
             "autoload": {
@@ -8560,19 +8490,20 @@
                 }
             ],
             "description": "Guzzle is a PHP HTTP client library",
-            "homepage": "http://guzzlephp.org/",
             "keywords": [
                 "client",
                 "curl",
                 "framework",
                 "http",
                 "http client",
+                "psr-18",
+                "psr-7",
                 "rest",
                 "web service"
             ],
             "support": {
                 "issues": "https://github.com/guzzle/guzzle/issues",
-                "source": "https://github.com/guzzle/guzzle/tree/6.5.8"
+                "source": "https://github.com/guzzle/guzzle/tree/7.5.0"
             },
             "funding": [
                 {
@@ -8588,7 +8519,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-06-20T22:16:07+00:00"
+            "time": "2022-08-28T15:39:27+00:00"
         },
         {
             "name": "guzzlehttp/promises",
@@ -8676,43 +8607,47 @@
         },
         {
             "name": "guzzlehttp/psr7",
-            "version": "1.9.0",
+            "version": "2.4.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/psr7.git",
-                "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318"
+                "reference": "67c26b443f348a51926030c83481b85718457d3d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/psr7/zipball/e98e3e6d4f86621a9b75f623996e6bbdeb4b9318",
-                "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318",
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d",
+                "reference": "67c26b443f348a51926030c83481b85718457d3d",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.4.0",
-                "psr/http-message": "~1.0",
-                "ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
+                "php": "^7.2.5 || ^8.0",
+                "psr/http-factory": "^1.0",
+                "psr/http-message": "^1.0",
+                "ralouphie/getallheaders": "^3.0"
             },
             "provide": {
+                "psr/http-factory-implementation": "1.0",
                 "psr/http-message-implementation": "1.0"
             },
             "require-dev": {
-                "ext-zlib": "*",
-                "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
+                "bamarni/composer-bin-plugin": "^1.8.1",
+                "http-interop/http-factory-tests": "^0.9",
+                "phpunit/phpunit": "^8.5.29 || ^9.5.23"
             },
             "suggest": {
                 "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
             },
             "type": "library",
             "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                },
                 "branch-alias": {
-                    "dev-master": "1.9-dev"
+                    "dev-master": "2.4-dev"
                 }
             },
             "autoload": {
-                "files": [
-                    "src/functions_include.php"
-                ],
                 "psr-4": {
                     "GuzzleHttp\\Psr7\\": "src/"
                 }
@@ -8751,6 +8686,11 @@
                     "name": "Tobias Schultze",
                     "email": "webmaster@tubo-world.de",
                     "homepage": "https://github.com/Tobion"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://sagikazarmark.hu"
                 }
             ],
             "description": "PSR-7 message implementation that also provides common utility methods",
@@ -8766,7 +8706,7 @@
             ],
             "support": {
                 "issues": "https://github.com/guzzle/psr7/issues",
-                "source": "https://github.com/guzzle/psr7/tree/1.9.0"
+                "source": "https://github.com/guzzle/psr7/tree/2.4.3"
             },
             "funding": [
                 {
@@ -8782,7 +8722,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-06-20T21:43:03+00:00"
+            "time": "2022-10-26T14:07:24+00:00"
         },
         {
             "name": "html2text/html2text",
@@ -8883,20 +8823,20 @@
         },
         {
             "name": "laminas/laminas-diactoros",
-            "version": "2.17.0",
+            "version": "2.20.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laminas/laminas-diactoros.git",
-                "reference": "5b32597aa46b83c8b85bb1cf9a6ed4fe7dd980c5"
+                "reference": "10696c809866bebd9d71dca14de6c0d6c1cac2f8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/5b32597aa46b83c8b85bb1cf9a6ed4fe7dd980c5",
-                "reference": "5b32597aa46b83c8b85bb1cf9a6ed4fe7dd980c5",
+                "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/10696c809866bebd9d71dca14de6c0d6c1cac2f8",
+                "reference": "10696c809866bebd9d71dca14de6c0d6c1cac2f8",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.4 || ~8.0.0 || ~8.1.0",
+                "php": "~8.0.0 || ~8.1.0 || ~8.2.0",
                 "psr/http-factory": "^1.0",
                 "psr/http-message": "^1.0"
             },
@@ -8915,9 +8855,9 @@
                 "http-interop/http-factory-tests": "^0.9.0",
                 "laminas/laminas-coding-standard": "^2.4.0",
                 "php-http/psr7-integration-tests": "^1.1.1",
-                "phpunit/phpunit": "^9.5.23",
+                "phpunit/phpunit": "^9.5.25",
                 "psalm/plugin-phpunit": "^0.17.0",
-                "vimeo/psalm": "^4.24.0"
+                "vimeo/psalm": "^4.28"
             },
             "type": "library",
             "extra": {
@@ -8976,7 +8916,7 @@
                     "type": "community_bridge"
                 }
             ],
-            "time": "2022-08-30T17:01:46+00:00"
+            "time": "2022-10-25T13:35:54+00:00"
         },
         {
             "name": "laminas/laminas-escaper",
@@ -9042,16 +8982,16 @@
         },
         {
             "name": "laminas/laminas-feed",
-            "version": "2.18.2",
+            "version": "2.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laminas/laminas-feed.git",
-                "reference": "a57fdb9df42950d5b7f052509fbdab0d081c6b6d"
+                "reference": "4d0a7a536b48f698914156ca6633104b3aef2f3b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laminas/laminas-feed/zipball/a57fdb9df42950d5b7f052509fbdab0d081c6b6d",
-                "reference": "a57fdb9df42950d5b7f052509fbdab0d081c6b6d",
+                "url": "https://api.github.com/repos/laminas/laminas-feed/zipball/4d0a7a536b48f698914156ca6633104b3aef2f3b",
+                "reference": "4d0a7a536b48f698914156ca6633104b3aef2f3b",
                 "shasum": ""
             },
             "require": {
@@ -9060,23 +9000,23 @@
                 "laminas/laminas-escaper": "^2.9",
                 "laminas/laminas-servicemanager": "^3.14.0",
                 "laminas/laminas-stdlib": "^3.6",
-                "php": "^7.4 || ~8.0.0 || ~8.1.0"
+                "php": "~8.0.0 || ~8.1.0 || ~8.2.0"
             },
             "conflict": {
                 "laminas/laminas-servicemanager": "<3.3",
                 "zendframework/zend-feed": "*"
             },
             "require-dev": {
-                "laminas/laminas-cache": "^2.13.2 || ^3.1.3",
-                "laminas/laminas-cache-storage-adapter-memory": "^1.1.0 || ^2.0.0",
-                "laminas/laminas-coding-standard": "~2.3.0",
-                "laminas/laminas-db": "^2.13.3",
-                "laminas/laminas-http": "^2.15",
-                "laminas/laminas-validator": "^2.15",
-                "phpunit/phpunit": "^9.5.5",
+                "laminas/laminas-cache": "^2.13.2 || ^3.6",
+                "laminas/laminas-cache-storage-adapter-memory": "^1.1.0 || ^2.1",
+                "laminas/laminas-coding-standard": "~2.4.0",
+                "laminas/laminas-db": "^2.15",
+                "laminas/laminas-http": "^2.16",
+                "laminas/laminas-validator": "^2.26",
+                "phpunit/phpunit": "^9.5.25",
                 "psalm/plugin-phpunit": "^0.17.0",
                 "psr/http-message": "^1.0.1",
-                "vimeo/psalm": "^4.24.0"
+                "vimeo/psalm": "^4.29"
             },
             "suggest": {
                 "laminas/laminas-cache": "Laminas\\Cache component, for optionally caching feeds between requests",
@@ -9118,25 +9058,25 @@
                     "type": "community_bridge"
                 }
             ],
-            "time": "2022-08-08T17:02:35+00:00"
+            "time": "2022-10-14T13:40:45+00:00"
         },
         {
             "name": "laminas/laminas-servicemanager",
-            "version": "3.17.0",
+            "version": "3.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laminas/laminas-servicemanager.git",
-                "reference": "360be5f16955dd1edbcce1cfaa98ed82a17f02ec"
+                "reference": "ed160729bb8721127efdaac799f9a298963345b1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/360be5f16955dd1edbcce1cfaa98ed82a17f02ec",
-                "reference": "360be5f16955dd1edbcce1cfaa98ed82a17f02ec",
+                "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/ed160729bb8721127efdaac799f9a298963345b1",
+                "reference": "ed160729bb8721127efdaac799f9a298963345b1",
                 "shasum": ""
             },
             "require": {
                 "laminas/laminas-stdlib": "^3.2.1",
-                "php": "~7.4.0 || ~8.0.0 || ~8.1.0",
+                "php": "~8.0.0 || ~8.1.0 || ~8.2.0",
                 "psr/container": "^1.0"
             },
             "conflict": {
@@ -9152,17 +9092,16 @@
                 "container-interop/container-interop": "^1.2.0"
             },
             "require-dev": {
-                "composer/package-versions-deprecated": "^1.0",
+                "composer/package-versions-deprecated": "^1.11.99.5",
                 "laminas/laminas-coding-standard": "~2.4.0",
                 "laminas/laminas-container-config-test": "^0.7",
-                "laminas/laminas-dependency-plugin": "^2.1.2",
-                "mikey179/vfsstream": "^1.6.10@alpha",
-                "ocramius/proxy-manager": "^2.11",
-                "phpbench/phpbench": "^1.1",
-                "phpspec/prophecy-phpunit": "^2.0",
-                "phpunit/phpunit": "^9.5.5",
+                "laminas/laminas-dependency-plugin": "^2.2",
+                "mikey179/vfsstream": "^1.6.11@alpha",
+                "ocramius/proxy-manager": "^2.14.1",
+                "phpbench/phpbench": "^1.2.6",
+                "phpunit/phpunit": "^9.5.25",
                 "psalm/plugin-phpunit": "^0.17.0",
-                "vimeo/psalm": "^4.8"
+                "vimeo/psalm": "^4.28"
             },
             "suggest": {
                 "ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services"
@@ -9209,35 +9148,34 @@
                     "type": "community_bridge"
                 }
             ],
-            "time": "2022-09-22T11:33:46+00:00"
+            "time": "2022-10-10T20:59:22+00:00"
         },
         {
             "name": "laminas/laminas-stdlib",
-            "version": "3.13.0",
+            "version": "3.15.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laminas/laminas-stdlib.git",
-                "reference": "66a6d03c381f6c9f1dd988bf8244f9afb9380d76"
+                "reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/66a6d03c381f6c9f1dd988bf8244f9afb9380d76",
-                "reference": "66a6d03c381f6c9f1dd988bf8244f9afb9380d76",
+                "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/63b66bd4b696f024f42616b9d95cdb10e5109c27",
+                "reference": "63b66bd4b696f024f42616b9d95cdb10e5109c27",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.4 || ~8.0.0 || ~8.1.0"
+                "php": "~8.0.0 || ~8.1.0 || ~8.2.0"
             },
             "conflict": {
                 "zendframework/zend-stdlib": "*"
             },
             "require-dev": {
-                "laminas/laminas-coding-standard": "~2.3.0",
+                "laminas/laminas-coding-standard": "^2.4.0",
                 "phpbench/phpbench": "^1.2.6",
-                "phpstan/phpdoc-parser": "^0.5.4",
-                "phpunit/phpunit": "^9.5.23",
+                "phpunit/phpunit": "^9.5.25",
                 "psalm/plugin-phpunit": "^0.17.0",
-                "vimeo/psalm": "^4.26"
+                "vimeo/psalm": "^4.28"
             },
             "type": "library",
             "autoload": {
@@ -9269,7 +9207,7 @@
                     "type": "community_bridge"
                 }
             ],
-            "time": "2022-08-24T13:56:50+00:00"
+            "time": "2022-10-10T19:10:24+00:00"
         },
         {
             "name": "league/container",
@@ -10115,16 +10053,16 @@
         },
         {
             "name": "openeuropa/oe_bootstrap_theme",
-            "version": "1.0.0-beta6",
+            "version": "1.0.0-beta7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/openeuropa/oe_bootstrap_theme.git",
-                "reference": "6e808add8962b59e6b54b9c6a6a266d90049d95b"
+                "reference": "29f864ea80333c312ba99e2ca7340e27429e3a70"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/openeuropa/oe_bootstrap_theme/zipball/6e808add8962b59e6b54b9c6a6a266d90049d95b",
-                "reference": "6e808add8962b59e6b54b9c6a6a266d90049d95b",
+                "url": "https://api.github.com/repos/openeuropa/oe_bootstrap_theme/zipball/29f864ea80333c312ba99e2ca7340e27429e3a70",
+                "reference": "29f864ea80333c312ba99e2ca7340e27429e3a70",
                 "shasum": ""
             },
             "require": {
@@ -10191,9 +10129,9 @@
             "description": "OpenEuropa Bootstrap base theme.",
             "support": {
                 "issues": "https://github.com/openeuropa/oe_bootstrap_theme/issues",
-                "source": "https://github.com/openeuropa/oe_bootstrap_theme/tree/1.0.0-beta6"
+                "source": "https://github.com/openeuropa/oe_bootstrap_theme/tree/1.0.0-beta7"
             },
-            "time": "2022-09-29T14:44:59+00:00"
+            "time": "2022-11-03T12:37:41+00:00"
         },
         {
             "name": "openeuropa/oe_dashboard_agent",
@@ -10722,22 +10660,22 @@
             "time": "2022-07-11T14:04:40+00:00"
         },
         {
-            "name": "php-http/guzzle6-adapter",
-            "version": "v2.0.2",
+            "name": "php-http/guzzle7-adapter",
+            "version": "1.0.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/php-http/guzzle6-adapter.git",
-                "reference": "9d1a45eb1c59f12574552e81fb295e9e53430a56"
+                "url": "https://github.com/php-http/guzzle7-adapter.git",
+                "reference": "fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/9d1a45eb1c59f12574552e81fb295e9e53430a56",
-                "reference": "9d1a45eb1c59f12574552e81fb295e9e53430a56",
+                "url": "https://api.github.com/repos/php-http/guzzle7-adapter/zipball/fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01",
+                "reference": "fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01",
                 "shasum": ""
             },
             "require": {
-                "guzzlehttp/guzzle": "^6.0",
-                "php": "^7.1 || ^8.0",
+                "guzzlehttp/guzzle": "^7.0",
+                "php": "^7.2 | ^8.0",
                 "php-http/httplug": "^2.0",
                 "psr/http-client": "^1.0"
             },
@@ -10747,19 +10685,18 @@
                 "psr/http-client-implementation": "1.0"
             },
             "require-dev": {
-                "ext-curl": "*",
-                "php-http/client-integration-tests": "^2.0 || ^3.0",
-                "phpunit/phpunit": "^7.4 || ^8.4"
+                "php-http/client-integration-tests": "^3.0",
+                "phpunit/phpunit": "^8.0|^9.3"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.x-dev"
+                    "dev-master": "0.2.x-dev"
                 }
             },
             "autoload": {
                 "psr-4": {
-                    "Http\\Adapter\\Guzzle6\\": "src/"
+                    "Http\\Adapter\\Guzzle7\\": "src/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -10768,25 +10705,21 @@
             ],
             "authors": [
                 {
-                    "name": "David de Boer",
-                    "email": "david@ddeboer.nl"
-                },
-                {
-                    "name": "Márk Sági-Kazár",
-                    "email": "mark.sagikazar@gmail.com"
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com"
                 }
             ],
-            "description": "Guzzle 6 HTTP Adapter",
+            "description": "Guzzle 7 HTTP Adapter",
             "homepage": "http://httplug.io",
             "keywords": [
                 "Guzzle",
                 "http"
             ],
             "support": {
-                "issues": "https://github.com/php-http/guzzle6-adapter/issues",
-                "source": "https://github.com/php-http/guzzle6-adapter/tree/v2.0.2"
+                "issues": "https://github.com/php-http/guzzle7-adapter/issues",
+                "source": "https://github.com/php-http/guzzle7-adapter/tree/1.0.0"
             },
-            "time": "2021-03-02T10:52:33+00:00"
+            "time": "2021-03-09T07:35:15+00:00"
         },
         {
             "name": "php-http/httplug",
@@ -11037,20 +10970,20 @@
         },
         {
             "name": "psr/cache",
-            "version": "1.0.1",
+            "version": "3.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/php-fig/cache.git",
-                "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
+                "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
-                "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
+                "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+                "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.0"
+                "php": ">=8.0.0"
             },
             "type": "library",
             "extra": {
@@ -11070,7 +11003,7 @@
             "authors": [
                 {
                     "name": "PHP-FIG",
-                    "homepage": "http://www.php-fig.org/"
+                    "homepage": "https://www.php-fig.org/"
                 }
             ],
             "description": "Common interface for caching libraries",
@@ -11080,9 +11013,9 @@
                 "psr-6"
             ],
             "support": {
-                "source": "https://github.com/php-fig/cache/tree/master"
+                "source": "https://github.com/php-fig/cache/tree/3.0.0"
             },
-            "time": "2016-08-06T20:24:11+00:00"
+            "time": "2021-02-03T23:26:27+00:00"
         },
         {
             "name": "psr/container",
@@ -11394,16 +11327,16 @@
         },
         {
             "name": "psy/psysh",
-            "version": "v0.11.8",
+            "version": "v0.11.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/bobthecow/psysh.git",
-                "reference": "f455acf3645262ae389b10e9beba0c358aa6994e"
+                "reference": "1acec99d6684a54ff92f8b548a4e41b566963778"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/bobthecow/psysh/zipball/f455acf3645262ae389b10e9beba0c358aa6994e",
-                "reference": "f455acf3645262ae389b10e9beba0c358aa6994e",
+                "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1acec99d6684a54ff92f8b548a4e41b566963778",
+                "reference": "1acec99d6684a54ff92f8b548a4e41b566963778",
                 "shasum": ""
             },
             "require": {
@@ -11464,9 +11397,9 @@
             ],
             "support": {
                 "issues": "https://github.com/bobthecow/psysh/issues",
-                "source": "https://github.com/bobthecow/psysh/tree/v0.11.8"
+                "source": "https://github.com/bobthecow/psysh/tree/v0.11.9"
             },
-            "time": "2022-07-28T14:25:11+00:00"
+            "time": "2022-11-06T15:29:46+00:00"
         },
         {
             "name": "ralouphie/getallheaders",
@@ -11650,6 +11583,85 @@
             },
             "time": "2020-01-30T12:17:27+00:00"
         },
+        {
+            "name": "sweetrdf/easyrdf",
+            "version": "1.7.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sweetrdf/easyrdf.git",
+                "reference": "19ba21288e0aa344227267cab7f8f9c565eee426"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sweetrdf/easyrdf/zipball/19ba21288e0aa344227267cab7f8f9c565eee426",
+                "reference": "19ba21288e0aa344227267cab7f8f9c565eee426",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-mbstring": "*",
+                "ext-pcre": "*",
+                "ext-xmlreader": "*",
+                "lib-libxml": "*",
+                "php": "^7.1|^8.0"
+            },
+            "replace": {
+                "easyrdf/easyrdf": "1.0.*|1.1.*"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^3.0",
+                "ml/json-ld": "^1.0",
+                "phpstan/phpstan": "^1.0",
+                "phpstan/phpstan-phpunit": "^1.0",
+                "phpunit/phpunit": "^7.5|^8.5|^9.5",
+                "semsol/arc2": "^2.4",
+                "zendframework/zend-http": "^2.3"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "EasyRdf\\": "lib"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Nicholas Humfrey",
+                    "email": "njh@aelius.com",
+                    "homepage": "http://www.aelius.com/njh/",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Alexey Zakhlestin",
+                    "email": "indeyets@gmail.com",
+                    "homepage": "http://indeyets.ru/",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Konrad Abicht",
+                    "email": "hi@inspirito.de",
+                    "homepage": "http://inspirito.de/",
+                    "role": "Maintainer, Developer"
+                }
+            ],
+            "description": "EasyRdf is a PHP library designed to make it easy to consume and produce RDF.",
+            "keywords": [
+                "Linked Data",
+                "RDF",
+                "Semantic Web",
+                "Turtle",
+                "rdfa",
+                "sparql"
+            ],
+            "support": {
+                "issues": "https://github.com/sweetrdf/easyrdf/issues",
+                "source": "https://github.com/sweetrdf/easyrdf/tree/1.7.1"
+            },
+            "time": "2022-11-08T08:13:50+00:00"
+        },
         {
             "name": "swiftmailer/swiftmailer",
             "version": "v6.3.0",
@@ -11791,16 +11803,16 @@
         },
         {
             "name": "symfony/console",
-            "version": "v4.4.47",
+            "version": "v4.4.48",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "4f40012db8d55c956406890b5720f686fee7f7b7"
+                "reference": "8e70c1cab07ac641b885ce80385b9824a293c623"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/4f40012db8d55c956406890b5720f686fee7f7b7",
-                "reference": "4f40012db8d55c956406890b5720f686fee7f7b7",
+                "url": "https://api.github.com/repos/symfony/console/zipball/8e70c1cab07ac641b885ce80385b9824a293c623",
+                "reference": "8e70c1cab07ac641b885ce80385b9824a293c623",
                 "shasum": ""
             },
             "require": {
@@ -11861,7 +11873,7 @@
             "description": "Eases the creation of beautiful and testable command line interfaces",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/console/tree/v4.4.47"
+                "source": "https://github.com/symfony/console/tree/v4.4.48"
             },
             "funding": [
                 {
@@ -11877,7 +11889,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-10-04T05:58:30+00:00"
+            "time": "2022-10-26T16:02:45+00:00"
         },
         {
             "name": "symfony/css-selector",
@@ -12102,25 +12114,25 @@
         },
         {
             "name": "symfony/deprecation-contracts",
-            "version": "v2.5.2",
+            "version": "v3.1.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/deprecation-contracts.git",
-                "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
+                "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
-                "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
+                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918",
+                "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1"
+                "php": ">=8.1"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "2.5-dev"
+                    "dev-main": "3.1-dev"
                 },
                 "thanks": {
                     "name": "symfony/contracts",
@@ -12149,7 +12161,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.2"
+                "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1"
             },
             "funding": [
                 {
@@ -12165,7 +12177,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-01-02T09:53:40+00:00"
+            "time": "2022-02-25T11:15:52+00:00"
         },
         {
             "name": "symfony/error-handler",
@@ -12464,22 +12476,23 @@
         },
         {
             "name": "symfony/finder",
-            "version": "v5.4.11",
+            "version": "v6.1.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c"
+                "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/7872a66f57caffa2916a584db1aa7f12adc76f8c",
-                "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709",
+                "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.2.5",
-                "symfony/deprecation-contracts": "^2.1|^3",
-                "symfony/polyfill-php80": "^1.16"
+                "php": ">=8.1"
+            },
+            "require-dev": {
+                "symfony/filesystem": "^6.0"
             },
             "type": "library",
             "autoload": {
@@ -12507,7 +12520,7 @@
             "description": "Finds files and directories via an intuitive fluent interface",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/finder/tree/v5.4.11"
+                "source": "https://github.com/symfony/finder/tree/v6.1.3"
             },
             "funding": [
                 {
@@ -12523,7 +12536,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-07-29T07:37:50+00:00"
+            "time": "2022-07-29T07:42:06+00:00"
         },
         {
             "name": "symfony/http-client-contracts",
@@ -12605,16 +12618,16 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v4.4.47",
+            "version": "v4.4.48",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-foundation.git",
-                "reference": "7eea76ae186c68466e7676e62812ce2769f96811"
+                "reference": "cd4f478e67f7c8776a13b17e7d44241fd66261ad"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7eea76ae186c68466e7676e62812ce2769f96811",
-                "reference": "7eea76ae186c68466e7676e62812ce2769f96811",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cd4f478e67f7c8776a13b17e7d44241fd66261ad",
+                "reference": "cd4f478e67f7c8776a13b17e7d44241fd66261ad",
                 "shasum": ""
             },
             "require": {
@@ -12653,7 +12666,7 @@
             "description": "Defines an object-oriented layer for the HTTP specification",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-foundation/tree/v4.4.47"
+                "source": "https://github.com/symfony/http-foundation/tree/v4.4.48"
             },
             "funding": [
                 {
@@ -12669,20 +12682,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-10-01T21:39:02+00:00"
+            "time": "2022-10-12T09:40:54+00:00"
         },
         {
             "name": "symfony/http-kernel",
-            "version": "v4.4.47",
+            "version": "v4.4.48",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-kernel.git",
-                "reference": "91cf5dbc9ea4d902470e596246a736179acfb79d"
+                "reference": "a6d5229dd9466e046674baad8449ad92ee24eddd"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/91cf5dbc9ea4d902470e596246a736179acfb79d",
-                "reference": "91cf5dbc9ea4d902470e596246a736179acfb79d",
+                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/a6d5229dd9466e046674baad8449ad92ee24eddd",
+                "reference": "a6d5229dd9466e046674baad8449ad92ee24eddd",
                 "shasum": ""
             },
             "require": {
@@ -12757,7 +12770,7 @@
             "description": "Provides a structured process for converting a Request into a Response",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-kernel/tree/v4.4.47"
+                "source": "https://github.com/symfony/http-kernel/tree/v4.4.48"
             },
             "funding": [
                 {
@@ -12773,7 +12786,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-10-12T07:05:45+00:00"
+            "time": "2022-10-28T16:49:22+00:00"
         },
         {
             "name": "symfony/mime",
@@ -14014,34 +14027,33 @@
         },
         {
             "name": "symfony/string",
-            "version": "v5.4.14",
+            "version": "v6.1.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/string.git",
-                "reference": "089e7237497fae7a9c404d0c3aeb8db3254733e4"
+                "reference": "823f143370880efcbdfa2dbca946b3358c4707e5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/string/zipball/089e7237497fae7a9c404d0c3aeb8db3254733e4",
-                "reference": "089e7237497fae7a9c404d0c3aeb8db3254733e4",
+                "url": "https://api.github.com/repos/symfony/string/zipball/823f143370880efcbdfa2dbca946b3358c4707e5",
+                "reference": "823f143370880efcbdfa2dbca946b3358c4707e5",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.2.5",
+                "php": ">=8.1",
                 "symfony/polyfill-ctype": "~1.8",
                 "symfony/polyfill-intl-grapheme": "~1.0",
                 "symfony/polyfill-intl-normalizer": "~1.0",
-                "symfony/polyfill-mbstring": "~1.0",
-                "symfony/polyfill-php80": "~1.15"
+                "symfony/polyfill-mbstring": "~1.0"
             },
             "conflict": {
-                "symfony/translation-contracts": ">=3.0"
+                "symfony/translation-contracts": "<2.0"
             },
             "require-dev": {
-                "symfony/error-handler": "^4.4|^5.0|^6.0",
-                "symfony/http-client": "^4.4|^5.0|^6.0",
-                "symfony/translation-contracts": "^1.1|^2",
-                "symfony/var-exporter": "^4.4|^5.0|^6.0"
+                "symfony/error-handler": "^5.4|^6.0",
+                "symfony/http-client": "^5.4|^6.0",
+                "symfony/translation-contracts": "^2.0|^3.0",
+                "symfony/var-exporter": "^5.4|^6.0"
             },
             "type": "library",
             "autoload": {
@@ -14080,7 +14092,7 @@
                 "utf8"
             ],
             "support": {
-                "source": "https://github.com/symfony/string/tree/v5.4.14"
+                "source": "https://github.com/symfony/string/tree/v6.1.7"
             },
             "funding": [
                 {
@@ -14096,7 +14108,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-10-05T15:16:54+00:00"
+            "time": "2022-10-10T09:34:31+00:00"
         },
         {
             "name": "symfony/translation",
@@ -14267,16 +14279,16 @@
         },
         {
             "name": "symfony/validator",
-            "version": "v4.4.47",
+            "version": "v4.4.48",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/validator.git",
-                "reference": "37456082bb034cb5f2d8602471a0de6c448535b8"
+                "reference": "54781a4c41efbd283b779110bf8ae7f263737775"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/validator/zipball/37456082bb034cb5f2d8602471a0de6c448535b8",
-                "reference": "37456082bb034cb5f2d8602471a0de6c448535b8",
+                "url": "https://api.github.com/repos/symfony/validator/zipball/54781a4c41efbd283b779110bf8ae7f263737775",
+                "reference": "54781a4c41efbd283b779110bf8ae7f263737775",
                 "shasum": ""
             },
             "require": {
@@ -14353,7 +14365,7 @@
             "description": "Provides tools to validate values",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/validator/tree/v4.4.47"
+                "source": "https://github.com/symfony/validator/tree/v4.4.48"
             },
             "funding": [
                 {
@@ -14369,7 +14381,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-10-01T17:13:09+00:00"
+            "time": "2022-10-25T13:54:11+00:00"
         },
         {
             "name": "symfony/var-dumper",
@@ -14764,685 +14776,43 @@
             "time": "2020-10-27T09:42:17+00:00"
         },
         {
-            "name": "webmozart/assert",
-            "version": "1.11.0",
+            "name": "willdurand/geocoder",
+            "version": "4.6.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/webmozarts/assert.git",
-                "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
+                "url": "https://github.com/geocoder-php/php-common.git",
+                "reference": "be3d9ed0fddf8c698ee079d8a07ae9520b4a49a1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
-                "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
-                "shasum": ""
-            },
-            "require": {
-                "ext-ctype": "*",
-                "php": "^7.2 || ^8.0"
-            },
-            "conflict": {
-                "phpstan/phpstan": "<0.12.20",
-                "vimeo/psalm": "<4.6.1 || 4.6.2"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^8.5.13"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.10-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Webmozart\\Assert\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@gmail.com"
-                }
-            ],
-            "description": "Assertions to validate method input/output with nice error messages.",
-            "keywords": [
-                "assert",
-                "check",
-                "validate"
-            ],
-            "support": {
-                "issues": "https://github.com/webmozarts/assert/issues",
-                "source": "https://github.com/webmozarts/assert/tree/1.11.0"
-            },
-            "time": "2022-06-03T18:03:27+00:00"
-        },
-        {
-            "name": "webmozart/path-util",
-            "version": "2.3.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/webmozart/path-util.git",
-                "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
-                "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "webmozart/assert": "~1.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.6",
-                "sebastian/version": "^1.0.1"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Webmozart\\PathUtil\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@gmail.com"
-                }
-            ],
-            "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
-            "support": {
-                "issues": "https://github.com/webmozart/path-util/issues",
-                "source": "https://github.com/webmozart/path-util/tree/2.3.0"
-            },
-            "abandoned": "symfony/filesystem",
-            "time": "2015-12-17T08:42:14+00:00"
-        },
-        {
-            "name": "willdurand/geocoder",
-            "version": "4.6.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/geocoder-php/php-common.git",
-                "reference": "be3d9ed0fddf8c698ee079d8a07ae9520b4a49a1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/geocoder-php/php-common/zipball/be3d9ed0fddf8c698ee079d8a07ae9520b4a49a1",
-                "reference": "be3d9ed0fddf8c698ee079d8a07ae9520b4a49a1",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^7.4 || ^8.0"
-            },
-            "require-dev": {
-                "nyholm/nsa": "^1.1",
-                "phpunit/phpunit": "^9.5",
-                "symfony/stopwatch": "~2.5"
-            },
-            "suggest": {
-                "symfony/stopwatch": "If you want to use the TimedGeocoder"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "4.1-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Geocoder\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "William Durand",
-                    "email": "william.durand1@gmail.com"
-                }
-            ],
-            "description": "Common files for PHP Geocoder",
-            "homepage": "http://geocoder-php.org",
-            "keywords": [
-                "abstraction",
-                "geocoder",
-                "geocoding",
-                "geoip"
-            ],
-            "support": {
-                "source": "https://github.com/geocoder-php/php-common/tree/4.6.0"
-            },
-            "time": "2022-07-30T11:09:43+00:00"
-        }
-    ],
-    "packages-dev": [
-        {
-            "name": "amphp/amp",
-            "version": "v2.6.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/amphp/amp.git",
-                "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
-                "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7.1"
-            },
-            "require-dev": {
-                "amphp/php-cs-fixer-config": "dev-master",
-                "amphp/phpunit-util": "^1",
-                "ext-json": "*",
-                "jetbrains/phpstorm-stubs": "^2019.3",
-                "phpunit/phpunit": "^7 | ^8 | ^9",
-                "psalm/phar": "^3.11@dev",
-                "react/promise": "^2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.x-dev"
-                }
-            },
-            "autoload": {
-                "files": [
-                    "lib/functions.php",
-                    "lib/Internal/functions.php"
-                ],
-                "psr-4": {
-                    "Amp\\": "lib"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Daniel Lowrey",
-                    "email": "rdlowrey@php.net"
-                },
-                {
-                    "name": "Aaron Piotrowski",
-                    "email": "aaron@trowski.com"
-                },
-                {
-                    "name": "Bob Weinand",
-                    "email": "bobwei9@hotmail.com"
-                },
-                {
-                    "name": "Niklas Keller",
-                    "email": "me@kelunik.com"
-                }
-            ],
-            "description": "A non-blocking concurrency framework for PHP applications.",
-            "homepage": "https://amphp.org/amp",
-            "keywords": [
-                "async",
-                "asynchronous",
-                "awaitable",
-                "concurrency",
-                "event",
-                "event-loop",
-                "future",
-                "non-blocking",
-                "promise"
-            ],
-            "support": {
-                "irc": "irc://irc.freenode.org/amphp",
-                "issues": "https://github.com/amphp/amp/issues",
-                "source": "https://github.com/amphp/amp/tree/v2.6.2"
-            },
-            "funding": [
-                {
-                    "url": "https://github.com/amphp",
-                    "type": "github"
-                }
-            ],
-            "time": "2022-02-20T17:52:18+00:00"
-        },
-        {
-            "name": "amphp/byte-stream",
-            "version": "v1.8.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/amphp/byte-stream.git",
-                "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd",
-                "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd",
-                "shasum": ""
-            },
-            "require": {
-                "amphp/amp": "^2",
-                "php": ">=7.1"
-            },
-            "require-dev": {
-                "amphp/php-cs-fixer-config": "dev-master",
-                "amphp/phpunit-util": "^1.4",
-                "friendsofphp/php-cs-fixer": "^2.3",
-                "jetbrains/phpstorm-stubs": "^2019.3",
-                "phpunit/phpunit": "^6 || ^7 || ^8",
-                "psalm/phar": "^3.11.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.x-dev"
-                }
-            },
-            "autoload": {
-                "files": [
-                    "lib/functions.php"
-                ],
-                "psr-4": {
-                    "Amp\\ByteStream\\": "lib"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Aaron Piotrowski",
-                    "email": "aaron@trowski.com"
-                },
-                {
-                    "name": "Niklas Keller",
-                    "email": "me@kelunik.com"
-                }
-            ],
-            "description": "A stream abstraction to make working with non-blocking I/O simple.",
-            "homepage": "http://amphp.org/byte-stream",
-            "keywords": [
-                "amp",
-                "amphp",
-                "async",
-                "io",
-                "non-blocking",
-                "stream"
-            ],
-            "support": {
-                "irc": "irc://irc.freenode.org/amphp",
-                "issues": "https://github.com/amphp/byte-stream/issues",
-                "source": "https://github.com/amphp/byte-stream/tree/v1.8.1"
-            },
-            "funding": [
-                {
-                    "url": "https://github.com/amphp",
-                    "type": "github"
-                }
-            ],
-            "time": "2021-03-30T17:13:30+00:00"
-        },
-        {
-            "name": "amphp/parallel",
-            "version": "v1.4.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/amphp/parallel.git",
-                "reference": "fbc128383c1ffb3823866f71b88d8c4722a25ce9"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/amphp/parallel/zipball/fbc128383c1ffb3823866f71b88d8c4722a25ce9",
-                "reference": "fbc128383c1ffb3823866f71b88d8c4722a25ce9",
-                "shasum": ""
-            },
-            "require": {
-                "amphp/amp": "^2",
-                "amphp/byte-stream": "^1.6.1",
-                "amphp/parser": "^1",
-                "amphp/process": "^1",
-                "amphp/serialization": "^1",
-                "amphp/sync": "^1.0.1",
-                "php": ">=7.1"
-            },
-            "require-dev": {
-                "amphp/php-cs-fixer-config": "dev-master",
-                "amphp/phpunit-util": "^1.1",
-                "phpunit/phpunit": "^8 || ^7"
-            },
-            "type": "library",
-            "autoload": {
-                "files": [
-                    "lib/Context/functions.php",
-                    "lib/Sync/functions.php",
-                    "lib/Worker/functions.php"
-                ],
-                "psr-4": {
-                    "Amp\\Parallel\\": "lib"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Aaron Piotrowski",
-                    "email": "aaron@trowski.com"
-                },
-                {
-                    "name": "Stephen Coakley",
-                    "email": "me@stephencoakley.com"
-                }
-            ],
-            "description": "Parallel processing component for Amp.",
-            "homepage": "https://github.com/amphp/parallel",
-            "keywords": [
-                "async",
-                "asynchronous",
-                "concurrent",
-                "multi-processing",
-                "multi-threading"
-            ],
-            "support": {
-                "issues": "https://github.com/amphp/parallel/issues",
-                "source": "https://github.com/amphp/parallel/tree/v1.4.1"
-            },
-            "funding": [
-                {
-                    "url": "https://github.com/amphp",
-                    "type": "github"
-                }
-            ],
-            "time": "2021-10-25T19:16:02+00:00"
-        },
-        {
-            "name": "amphp/parallel-functions",
-            "version": "v1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/amphp/parallel-functions.git",
-                "reference": "af9795d51abfafc3676cbe7e17965479491abaad"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/amphp/parallel-functions/zipball/af9795d51abfafc3676cbe7e17965479491abaad",
-                "reference": "af9795d51abfafc3676cbe7e17965479491abaad",
-                "shasum": ""
-            },
-            "require": {
-                "amphp/amp": "^2.0.3",
-                "amphp/parallel": "^1.1",
-                "opis/closure": "^3.0.7",
-                "php": ">=7"
-            },
-            "require-dev": {
-                "amphp/phpunit-util": "^1.0",
-                "friendsofphp/php-cs-fixer": "^2.9",
-                "phpunit/phpunit": "^6.5"
-            },
-            "type": "library",
-            "autoload": {
-                "files": [
-                    "src/functions.php"
-                ],
-                "psr-4": {
-                    "Amp\\ParallelFunctions\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Niklas Keller",
-                    "email": "me@kelunik.com"
-                }
-            ],
-            "description": "Parallel processing made simple.",
-            "support": {
-                "issues": "https://github.com/amphp/parallel-functions/issues",
-                "source": "https://github.com/amphp/parallel-functions/tree/master"
-            },
-            "funding": [
-                {
-                    "url": "https://github.com/amphp",
-                    "type": "github"
-                }
-            ],
-            "time": "2020-07-10T17:05:35+00:00"
-        },
-        {
-            "name": "amphp/parser",
-            "version": "v1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/amphp/parser.git",
-                "reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/amphp/parser/zipball/f83e68f03d5b8e8e0365b8792985a7f341c57ae1",
-                "reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7"
-            },
-            "require-dev": {
-                "friendsofphp/php-cs-fixer": "^2.3",
-                "phpunit/phpunit": "^6"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "Amp\\Parser\\": "lib"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Niklas Keller",
-                    "email": "me@kelunik.com"
-                },
-                {
-                    "name": "Aaron Piotrowski",
-                    "email": "aaron@trowski.com"
-                }
-            ],
-            "description": "A generator parser to make streaming parsers simple.",
-            "homepage": "https://github.com/amphp/parser",
-            "keywords": [
-                "async",
-                "non-blocking",
-                "parser",
-                "stream"
-            ],
-            "support": {
-                "issues": "https://github.com/amphp/parser/issues",
-                "source": "https://github.com/amphp/parser/tree/is-valid"
-            },
-            "time": "2017-06-06T05:29:10+00:00"
-        },
-        {
-            "name": "amphp/process",
-            "version": "v1.1.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/amphp/process.git",
-                "reference": "76e9495fd6818b43a20167cb11d8a67f7744ee0f"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/amphp/process/zipball/76e9495fd6818b43a20167cb11d8a67f7744ee0f",
-                "reference": "76e9495fd6818b43a20167cb11d8a67f7744ee0f",
+                "url": "https://api.github.com/repos/geocoder-php/php-common/zipball/be3d9ed0fddf8c698ee079d8a07ae9520b4a49a1",
+                "reference": "be3d9ed0fddf8c698ee079d8a07ae9520b4a49a1",
                 "shasum": ""
             },
             "require": {
-                "amphp/amp": "^2",
-                "amphp/byte-stream": "^1.4",
-                "php": ">=7"
+                "php": "^7.4 || ^8.0"
             },
             "require-dev": {
-                "amphp/php-cs-fixer-config": "dev-master",
-                "amphp/phpunit-util": "^1",
-                "phpunit/phpunit": "^6"
-            },
-            "type": "library",
-            "autoload": {
-                "files": [
-                    "lib/functions.php"
-                ],
-                "psr-4": {
-                    "Amp\\Process\\": "lib"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Bob Weinand",
-                    "email": "bobwei9@hotmail.com"
-                },
-                {
-                    "name": "Aaron Piotrowski",
-                    "email": "aaron@trowski.com"
-                },
-                {
-                    "name": "Niklas Keller",
-                    "email": "me@kelunik.com"
-                }
-            ],
-            "description": "Asynchronous process manager.",
-            "homepage": "https://github.com/amphp/process",
-            "support": {
-                "issues": "https://github.com/amphp/process/issues",
-                "source": "https://github.com/amphp/process/tree/v1.1.4"
-            },
-            "funding": [
-                {
-                    "url": "https://github.com/amphp",
-                    "type": "github"
-                }
-            ],
-            "time": "2022-07-06T23:50:12+00:00"
-        },
-        {
-            "name": "amphp/serialization",
-            "version": "v1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/amphp/serialization.git",
-                "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1",
-                "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7.1"
+                "nyholm/nsa": "^1.1",
+                "phpunit/phpunit": "^9.5",
+                "symfony/stopwatch": "~2.5"
             },
-            "require-dev": {
-                "amphp/php-cs-fixer-config": "dev-master",
-                "phpunit/phpunit": "^9 || ^8 || ^7"
+            "suggest": {
+                "symfony/stopwatch": "If you want to use the TimedGeocoder"
             },
             "type": "library",
-            "autoload": {
-                "files": [
-                    "src/functions.php"
-                ],
-                "psr-4": {
-                    "Amp\\Serialization\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Aaron Piotrowski",
-                    "email": "aaron@trowski.com"
-                },
-                {
-                    "name": "Niklas Keller",
-                    "email": "me@kelunik.com"
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.1-dev"
                 }
-            ],
-            "description": "Serialization tools for IPC and data storage in PHP.",
-            "homepage": "https://github.com/amphp/serialization",
-            "keywords": [
-                "async",
-                "asynchronous",
-                "serialization",
-                "serialize"
-            ],
-            "support": {
-                "issues": "https://github.com/amphp/serialization/issues",
-                "source": "https://github.com/amphp/serialization/tree/master"
-            },
-            "time": "2020-03-25T21:39:07+00:00"
-        },
-        {
-            "name": "amphp/sync",
-            "version": "v1.4.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/amphp/sync.git",
-                "reference": "85ab06764f4f36d63b1356b466df6111cf4b89cf"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/amphp/sync/zipball/85ab06764f4f36d63b1356b466df6111cf4b89cf",
-                "reference": "85ab06764f4f36d63b1356b466df6111cf4b89cf",
-                "shasum": ""
-            },
-            "require": {
-                "amphp/amp": "^2.2",
-                "php": ">=7.1"
             },
-            "require-dev": {
-                "amphp/php-cs-fixer-config": "dev-master",
-                "amphp/phpunit-util": "^1.1",
-                "phpunit/phpunit": "^9 || ^8 || ^7"
-            },
-            "type": "library",
             "autoload": {
-                "files": [
-                    "src/functions.php",
-                    "src/ConcurrentIterator/functions.php"
-                ],
                 "psr-4": {
-                    "Amp\\Sync\\": "src"
-                }
+                    "Geocoder\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
@@ -15450,35 +14820,25 @@
             ],
             "authors": [
                 {
-                    "name": "Aaron Piotrowski",
-                    "email": "aaron@trowski.com"
-                },
-                {
-                    "name": "Stephen Coakley",
-                    "email": "me@stephencoakley.com"
+                    "name": "William Durand",
+                    "email": "william.durand1@gmail.com"
                 }
             ],
-            "description": "Mutex, Semaphore, and other synchronization tools for Amp.",
-            "homepage": "https://github.com/amphp/sync",
+            "description": "Common files for PHP Geocoder",
+            "homepage": "http://geocoder-php.org",
             "keywords": [
-                "async",
-                "asynchronous",
-                "mutex",
-                "semaphore",
-                "synchronization"
+                "abstraction",
+                "geocoder",
+                "geocoding",
+                "geoip"
             ],
             "support": {
-                "issues": "https://github.com/amphp/sync/issues",
-                "source": "https://github.com/amphp/sync/tree/v1.4.2"
+                "source": "https://github.com/geocoder-php/php-common/tree/4.6.0"
             },
-            "funding": [
-                {
-                    "url": "https://github.com/amphp",
-                    "type": "github"
-                }
-            ],
-            "time": "2021-10-25T18:29:10+00:00"
-        },
+            "time": "2022-07-30T11:09:43+00:00"
+        }
+    ],
+    "packages-dev": [
         {
             "name": "behat/behat",
             "version": "v3.11.0",
@@ -15576,158 +14936,29 @@
             "dist": {
                 "type": "zip",
                 "url": "https://api.github.com/repos/Behat/Gherkin/zipball/0bc8d1e30e96183e4f36db9dc79caead300beff4",
-                "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4",
-                "shasum": ""
-            },
-            "require": {
-                "php": "~7.2|~8.0"
-            },
-            "require-dev": {
-                "cucumber/cucumber": "dev-gherkin-22.0.0",
-                "phpunit/phpunit": "~8|~9",
-                "symfony/yaml": "~3|~4|~5"
-            },
-            "suggest": {
-                "symfony/yaml": "If you want to parse features, represented in YAML files"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "4.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Behat\\Gherkin": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Konstantin Kudryashov",
-                    "email": "ever.zet@gmail.com",
-                    "homepage": "http://everzet.com"
-                }
-            ],
-            "description": "Gherkin DSL parser for PHP",
-            "homepage": "http://behat.org/",
-            "keywords": [
-                "BDD",
-                "Behat",
-                "Cucumber",
-                "DSL",
-                "gherkin",
-                "parser"
-            ],
-            "support": {
-                "issues": "https://github.com/Behat/Gherkin/issues",
-                "source": "https://github.com/Behat/Gherkin/tree/v4.9.0"
-            },
-            "time": "2021-10-12T13:05:09+00:00"
-        },
-        {
-            "name": "behat/mink",
-            "version": "v1.10.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/minkphp/Mink.git",
-                "reference": "19e58905632e7cfdc5b2bafb9b950a3521af32c5"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/minkphp/Mink/zipball/19e58905632e7cfdc5b2bafb9b950a3521af32c5",
-                "reference": "19e58905632e7cfdc5b2bafb9b950a3521af32c5",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7.2",
-                "symfony/css-selector": "^4.4 || ^5.0 || ^6.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^8.5.22 || ^9.5.11",
-                "symfony/error-handler": "^4.4 || ^5.0 || ^6.0",
-                "symfony/phpunit-bridge": "^5.4 || ^6.0"
-            },
-            "suggest": {
-                "behat/mink-browserkit-driver": "fast headless driver for any app without JS emulation",
-                "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)",
-                "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)",
-                "dmore/chrome-mink-driver": "fast and JS-enabled driver for any app (requires chromium or google chrome)"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Behat\\Mink\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Konstantin Kudryashov",
-                    "email": "ever.zet@gmail.com",
-                    "homepage": "http://everzet.com"
-                }
-            ],
-            "description": "Browser controller/emulator abstraction for PHP",
-            "homepage": "https://mink.behat.org/",
-            "keywords": [
-                "browser",
-                "testing",
-                "web"
-            ],
-            "support": {
-                "issues": "https://github.com/minkphp/Mink/issues",
-                "source": "https://github.com/minkphp/Mink/tree/v1.10.0"
-            },
-            "time": "2022-03-28T14:22:43+00:00"
-        },
-        {
-            "name": "behat/mink-browserkit-driver",
-            "version": "v1.4.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/minkphp/MinkBrowserKitDriver.git",
-                "reference": "057926c9da452bac5bfcffb92eb4f3e1ce74dae9"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/057926c9da452bac5bfcffb92eb4f3e1ce74dae9",
-                "reference": "057926c9da452bac5bfcffb92eb4f3e1ce74dae9",
+                "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4",
                 "shasum": ""
             },
             "require": {
-                "behat/mink": "^1.7.1@dev",
-                "php": ">=5.4",
-                "symfony/browser-kit": "~2.3|~3.0|~4.0",
-                "symfony/dom-crawler": "~2.3|~3.0|~4.0"
+                "php": "~7.2|~8.0"
             },
             "require-dev": {
-                "mink/driver-testsuite": "dev-master",
-                "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.18 || ^8.5 || ^9.5",
-                "symfony/debug": "^2.7|^3.0|^4.0",
-                "symfony/http-kernel": "~2.3|~3.0|~4.0",
-                "yoast/phpunit-polyfills": "^1.0"
+                "cucumber/cucumber": "dev-gherkin-22.0.0",
+                "phpunit/phpunit": "~8|~9",
+                "symfony/yaml": "~3|~4|~5"
             },
-            "type": "mink-driver",
+            "suggest": {
+                "symfony/yaml": "If you want to parse features, represented in YAML files"
+            },
+            "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.x-dev"
+                    "dev-master": "4.x-dev"
                 }
             },
             "autoload": {
-                "psr-4": {
-                    "Behat\\Mink\\Driver\\": "src/"
+                "psr-0": {
+                    "Behat\\Gherkin": "src/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -15741,53 +14972,60 @@
                     "homepage": "http://everzet.com"
                 }
             ],
-            "description": "Symfony2 BrowserKit driver for Mink framework",
-            "homepage": "https://mink.behat.org/",
+            "description": "Gherkin DSL parser for PHP",
+            "homepage": "http://behat.org/",
             "keywords": [
-                "Mink",
-                "Symfony2",
-                "browser",
-                "testing"
+                "BDD",
+                "Behat",
+                "Cucumber",
+                "DSL",
+                "gherkin",
+                "parser"
             ],
             "support": {
-                "issues": "https://github.com/minkphp/MinkBrowserKitDriver/issues",
-                "source": "https://github.com/minkphp/MinkBrowserKitDriver/tree/v1.4.1"
+                "issues": "https://github.com/Behat/Gherkin/issues",
+                "source": "https://github.com/Behat/Gherkin/tree/v4.9.0"
             },
-            "time": "2021-12-10T14:17:06+00:00"
+            "time": "2021-10-12T13:05:09+00:00"
         },
         {
-            "name": "behat/mink-extension",
-            "version": "2.3.1",
+            "name": "behat/mink",
+            "version": "v1.10.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/Behat/MinkExtension.git",
-                "reference": "80f7849ba53867181b7e412df9210e12fba50177"
+                "url": "https://github.com/minkphp/Mink.git",
+                "reference": "19e58905632e7cfdc5b2bafb9b950a3521af32c5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/80f7849ba53867181b7e412df9210e12fba50177",
-                "reference": "80f7849ba53867181b7e412df9210e12fba50177",
+                "url": "https://api.github.com/repos/minkphp/Mink/zipball/19e58905632e7cfdc5b2bafb9b950a3521af32c5",
+                "reference": "19e58905632e7cfdc5b2bafb9b950a3521af32c5",
                 "shasum": ""
             },
             "require": {
-                "behat/behat": "^3.0.5",
-                "behat/mink": "^1.5",
-                "php": ">=5.3.2",
-                "symfony/config": "^2.7|^3.0|^4.0"
+                "php": ">=7.2",
+                "symfony/css-selector": "^4.4 || ^5.0 || ^6.0"
             },
             "require-dev": {
-                "behat/mink-goutte-driver": "^1.1",
-                "phpspec/phpspec": "^2.0"
+                "phpunit/phpunit": "^8.5.22 || ^9.5.11",
+                "symfony/error-handler": "^4.4 || ^5.0 || ^6.0",
+                "symfony/phpunit-bridge": "^5.4 || ^6.0"
             },
-            "type": "behat-extension",
+            "suggest": {
+                "behat/mink-browserkit-driver": "fast headless driver for any app without JS emulation",
+                "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)",
+                "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)",
+                "dmore/chrome-mink-driver": "fast and JS-enabled driver for any app (requires chromium or google chrome)"
+            },
+            "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.1.x-dev"
+                    "dev-master": "1.x-dev"
                 }
             },
             "autoload": {
-                "psr-0": {
-                    "Behat\\MinkExtension": "src/"
+                "psr-4": {
+                    "Behat\\Mink\\": "src/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -15795,55 +15033,58 @@
                 "MIT"
             ],
             "authors": [
-                {
-                    "name": "Christophe Coevoet",
-                    "email": "stof@notk.org"
-                },
                 {
                     "name": "Konstantin Kudryashov",
-                    "email": "ever.zet@gmail.com"
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
                 }
             ],
-            "description": "Mink extension for Behat",
-            "homepage": "http://extensions.behat.org/mink",
+            "description": "Browser controller/emulator abstraction for PHP",
+            "homepage": "https://mink.behat.org/",
             "keywords": [
                 "browser",
-                "gui",
-                "test",
+                "testing",
                 "web"
             ],
             "support": {
-                "issues": "https://github.com/Behat/MinkExtension/issues",
-                "source": "https://github.com/Behat/MinkExtension/tree/master"
+                "issues": "https://github.com/minkphp/Mink/issues",
+                "source": "https://github.com/minkphp/Mink/tree/v1.10.0"
             },
-            "time": "2018-02-06T15:36:30+00:00"
+            "time": "2022-03-28T14:22:43+00:00"
         },
         {
-            "name": "behat/mink-goutte-driver",
-            "version": "v1.3.0",
+            "name": "behat/mink-browserkit-driver",
+            "version": "v2.1.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/minkphp/MinkGoutteDriver.git",
-                "reference": "8139f520f417c81bf9d2f9a171fff400f6adc9ea"
+                "url": "https://github.com/minkphp/MinkBrowserKitDriver.git",
+                "reference": "d2768e6c17b293d86d8fcff54cbb9e6ad938fee1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8139f520f417c81bf9d2f9a171fff400f6adc9ea",
-                "reference": "8139f520f417c81bf9d2f9a171fff400f6adc9ea",
+                "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/d2768e6c17b293d86d8fcff54cbb9e6ad938fee1",
+                "reference": "d2768e6c17b293d86d8fcff54cbb9e6ad938fee1",
                 "shasum": ""
             },
             "require": {
-                "behat/mink-browserkit-driver": "~1.2@dev",
-                "fabpot/goutte": "~1.0.4|~2.0|~3.1",
-                "php": ">=5.4"
+                "behat/mink": "^1.9.0@dev",
+                "php": ">=7.2",
+                "symfony/browser-kit": "^4.4 || ^5.0 || ^6.0",
+                "symfony/dom-crawler": "^4.4 || ^5.0 || ^6.0"
             },
             "require-dev": {
-                "mink/driver-testsuite": "dev-master"
+                "mink/driver-testsuite": "dev-master",
+                "phpunit/phpunit": "^8.5 || ^9.5",
+                "symfony/error-handler": "^4.4 || ^5.0 || ^6.0",
+                "symfony/http-client": "^4.4 || ^5.0 || ^6.0",
+                "symfony/http-kernel": "^4.4 || ^5.0 || ^6.0",
+                "symfony/mime": "^4.4 || ^5.0 || ^6.0",
+                "yoast/phpunit-polyfills": "^1.0"
             },
             "type": "mink-driver",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.x-dev"
+                    "dev-master": "2.x-dev"
                 }
             },
             "autoload": {
@@ -15862,19 +15103,19 @@
                     "homepage": "http://everzet.com"
                 }
             ],
-            "description": "Goutte driver for Mink framework",
+            "description": "Symfony2 BrowserKit driver for Mink framework",
             "homepage": "https://mink.behat.org/",
             "keywords": [
+                "Mink",
+                "Symfony2",
                 "browser",
-                "goutte",
-                "headless",
                 "testing"
             ],
             "support": {
-                "issues": "https://github.com/minkphp/MinkGoutteDriver/issues",
-                "source": "https://github.com/minkphp/MinkGoutteDriver/tree/v1.3.0"
+                "issues": "https://github.com/minkphp/MinkBrowserKitDriver/issues",
+                "source": "https://github.com/minkphp/MinkBrowserKitDriver/tree/v2.1.0"
             },
-            "time": "2021-10-12T11:35:46+00:00"
+            "time": "2022-03-28T14:33:51+00:00"
         },
         {
             "name": "behat/mink-selenium2-driver",
@@ -15995,16 +15236,16 @@
         },
         {
             "name": "composer/pcre",
-            "version": "3.0.0",
+            "version": "3.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/pcre.git",
-                "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd"
+                "reference": "4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd",
-                "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd",
+                "url": "https://api.github.com/repos/composer/pcre/zipball/4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb",
+                "reference": "4482b6409ca6bfc2af043a5711cd21ac3e7a8dfb",
                 "shasum": ""
             },
             "require": {
@@ -16046,7 +15287,7 @@
             ],
             "support": {
                 "issues": "https://github.com/composer/pcre/issues",
-                "source": "https://github.com/composer/pcre/tree/3.0.0"
+                "source": "https://github.com/composer/pcre/tree/3.0.2"
             },
             "funding": [
                 {
@@ -16062,7 +15303,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-02-25T20:21:48+00:00"
+            "time": "2022-11-03T20:24:16+00:00"
         },
         {
             "name": "composer/xdebug-handler",
@@ -17211,28 +16452,28 @@
         },
         {
             "name": "drupal/devel",
-            "version": "4.2.1",
+            "version": "5.0.2",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/devel.git",
-                "reference": "4.2.1"
+                "reference": "5.0.2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/devel-4.2.1.zip",
-                "reference": "4.2.1",
-                "shasum": "aa08379bad81cb2e604ee9a0b9e2aabd86fae13f"
+                "url": "https://ftp.drupal.org/files/projects/devel-5.0.2.zip",
+                "reference": "5.0.2",
+                "shasum": "9299d52d806897240fb5a57e66f12e09c4f00960"
             },
             "require": {
                 "doctrine/common": "^2.7",
-                "drupal/core": "^8.8 || ^9",
-                "symfony/var-dumper": "^4 || ^5"
+                "drupal/core": "^9 || ^10",
+                "symfony/var-dumper": "^4 || ^5 || ^6"
             },
             "conflict": {
                 "kint-php/kint": "<3"
             },
             "require-dev": {
-                "drush/drush": "^10"
+                "drush/drush": "^11"
             },
             "suggest": {
                 "kint-php/kint": "Kint provides an informative display of arrays/objects. Useful for debugging and developing."
@@ -17240,8 +16481,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "4.2.1",
-                    "datestamp": "1664317444",
+                    "version": "5.0.2",
+                    "datestamp": "1664317512",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -17249,7 +16490,7 @@
                 },
                 "drush": {
                     "services": {
-                        "drush.services.yml": "^9 || ^10"
+                        "drush.services.yml": "^9 || ^10 || ^11"
                     }
                 }
             },
@@ -17277,16 +16518,16 @@
         },
         {
             "name": "drupal/drupal-driver",
-            "version": "v2.2.0",
+            "version": "dev-master",
             "source": {
                 "type": "git",
                 "url": "https://github.com/jhedstrom/DrupalDriver.git",
-                "reference": "000ce86a345bb8decaefdd7f0509825179641221"
+                "reference": "d60daee40c26ff7473c7fea4f9734722da033489"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/jhedstrom/DrupalDriver/zipball/000ce86a345bb8decaefdd7f0509825179641221",
-                "reference": "000ce86a345bb8decaefdd7f0509825179641221",
+                "url": "https://api.github.com/repos/jhedstrom/DrupalDriver/zipball/d60daee40c26ff7473c7fea4f9734722da033489",
+                "reference": "d60daee40c26ff7473c7fea4f9734722da033489",
                 "shasum": ""
             },
             "require": {
@@ -17304,7 +16545,13 @@
                 "phpspec/phpspec": "~2.0 || ~4.0 || ~6.1 || dev-main",
                 "phpunit/phpunit": "~6.0 || ~7.0 || ^9"
             },
+            "default-branch": true,
             "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.3.x-dev"
+                }
+            },
             "autoload": {
                 "psr-0": {
                     "Drupal\\Driver": "src/",
@@ -17330,7 +16577,7 @@
             ],
             "support": {
                 "issues": "https://github.com/jhedstrom/DrupalDriver/issues",
-                "source": "https://github.com/jhedstrom/DrupalDriver/tree/v2.2.0"
+                "source": "https://github.com/jhedstrom/DrupalDriver/tree/master"
             },
             "funding": [
                 {
@@ -17338,44 +16585,45 @@
                     "type": "github"
                 }
             ],
-            "time": "2022-05-16T18:47:08+00:00"
+            "time": "2022-11-07T18:23:51+00:00"
         },
         {
             "name": "drupal/drupal-extension",
-            "version": "v4.2.1",
+            "version": "dev-use-guzzle",
             "source": {
                 "type": "git",
-                "url": "https://github.com/jhedstrom/drupalextension.git",
-                "reference": "03c06860db91a2e456e3e7ca170414c2a4a40107"
+                "url": "https://github.com/claudiu-cristea/drupalextension.git",
+                "reference": "2763d4d5afa90073cde93cb23cf1c6175bbe7b74"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/jhedstrom/drupalextension/zipball/03c06860db91a2e456e3e7ca170414c2a4a40107",
-                "reference": "03c06860db91a2e456e3e7ca170414c2a4a40107",
+                "url": "https://api.github.com/repos/claudiu-cristea/drupalextension/zipball/2763d4d5afa90073cde93cb23cf1c6175bbe7b74",
+                "reference": "2763d4d5afa90073cde93cb23cf1c6175bbe7b74",
                 "shasum": ""
             },
             "require": {
                 "behat/behat": "~3.2",
-                "behat/mink": "~1.5",
-                "behat/mink-goutte-driver": "~1.0",
+                "behat/mink-browserkit-driver": "^2.1.0",
                 "behat/mink-selenium2-driver": "~1.1",
-                "drupal/drupal-driver": "^2.1.0",
-                "friends-of-behat/mink-extension": "^2",
-                "symfony/browser-kit": "^3.4|~4.4",
-                "symfony/dependency-injection": "~3.0|~4.4",
-                "symfony/translation": "^3.4|~4.4"
+                "drupal/drupal-driver": "dev-master",
+                "friends-of-behat/mink-extension": "^2.7.1",
+                "symfony/http-client": "~4.4 || ^5 || ^6",
+                "webflo/drupal-finder": "^1.2"
             },
             "require-dev": {
-                "composer/installers": "^1.2",
+                "composer/installers": "^2",
                 "drupal/coder": "^8.3",
-                "drupal/core-composer-scaffold": "^9.1",
-                "drupal/core-recommended": "^9.1",
-                "drush/drush": "^10.5",
+                "drupal/core": "^9.4 || ^10.0",
+                "drupal/core-composer-scaffold": "^9.4 || ^10.0",
+                "drush/drush": "^11.0",
                 "php-parallel-lint/php-parallel-lint": "^1.3",
                 "phpspec/phpspec": "^4.0 || ^6.0 || ^7.0"
             },
             "type": "behat-extension",
             "extra": {
+                "branch-alias": {
+                    "dev-master": "5.0.x-dev"
+                },
                 "installer-paths": {
                     "drupal/core": [
                         "type:drupal-core"
@@ -17391,11 +16639,19 @@
                 "psr-0": {
                     "Drupal\\Drupal": "src/",
                     "Drupal\\Exception": "src/",
-                    "Drupal\\MinkExtension": "src/",
-                    "Drupal\\DrupalExtension": "src/"
+                    "Drupal\\DrupalExtension": "src/",
+                    "Drupal\\MinkExtension": "src/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
+            "scripts": {
+                "test": [
+                    "composer validate --no-interaction",
+                    "parallel-lint src spec features fixtures",
+                    "phpcs --standard=./phpcs-ruleset.xml -p",
+                    "phpcs --standard=./phpcs-drupal-ruleset.xml -p",
+                    "phpspec run -f pretty --no-interaction"
+                ]
+            },
             "license": [
                 "GPL-2.0-or-later"
             ],
@@ -17421,16 +16677,15 @@
                 "web"
             ],
             "support": {
-                "issues": "https://github.com/jhedstrom/drupalextension/issues",
-                "source": "https://github.com/jhedstrom/drupalextension/tree/v4.2.1"
+                "source": "https://github.com/claudiu-cristea/drupalextension/tree/use-guzzle"
             },
             "funding": [
                 {
-                    "url": "https://github.com/jhedstrom",
-                    "type": "github"
+                    "type": "github",
+                    "url": "https://github.com/jhedstrom"
                 }
             ],
-            "time": "2022-04-26T19:55:44+00:00"
+            "time": "2022-11-07T21:54:13+00:00"
         },
         {
             "name": "drupal/filecache",
@@ -17633,20 +16888,20 @@
         },
         {
             "name": "drupaltest/behat-one-time-login",
-            "version": "1.0.1",
+            "version": "dev-drupal-extension",
             "source": {
                 "type": "git",
                 "url": "https://github.com/drupaltest/behat-one-time-login.git",
-                "reference": "a7c754de36e3fcc563e496f65a7e6800c523f415"
+                "reference": "d4a190cba1a7e2ad7ca813c86aea7f5fd4727d0e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/drupaltest/behat-one-time-login/zipball/a7c754de36e3fcc563e496f65a7e6800c523f415",
-                "reference": "a7c754de36e3fcc563e496f65a7e6800c523f415",
+                "url": "https://api.github.com/repos/drupaltest/behat-one-time-login/zipball/d4a190cba1a7e2ad7ca813c86aea7f5fd4727d0e",
+                "reference": "d4a190cba1a7e2ad7ca813c86aea7f5fd4727d0e",
                 "shasum": ""
             },
             "require": {
-                "drupal/drupal-extension": "~4.1",
+                "drupal/drupal-extension": "^4.1",
                 "friends-of-behat/service-container-extension": "~1.0"
             },
             "require-dev": {
@@ -17690,37 +16945,36 @@
             "homepage": "https://github.com/drupaltest/behat-one-time-login",
             "support": {
                 "issues": "https://github.com/drupaltest/behat-one-time-login/issues",
-                "source": "https://github.com/drupaltest/behat-one-time-login/tree/1.0.1"
+                "source": "https://github.com/drupaltest/behat-one-time-login/tree/drupal-extension"
             },
-            "time": "2021-08-12T06:48:58+00:00"
+            "time": "2022-10-15T15:52:31+00:00"
         },
         {
             "name": "ec-europa/qa-automation",
-            "version": "8.1.8",
+            "version": "9.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/ec-europa/qa-automation.git",
-                "reference": "531a135fda0312cddc2964c85a0b7242ac89909c"
+                "reference": "07891b0aa017e905be7b0d9e0b31ef4471e9544b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/ec-europa/qa-automation/zipball/531a135fda0312cddc2964c85a0b7242ac89909c",
-                "reference": "531a135fda0312cddc2964c85a0b7242ac89909c",
+                "url": "https://api.github.com/repos/ec-europa/qa-automation/zipball/07891b0aa017e905be7b0d9e0b31ef4471e9544b",
+                "reference": "07891b0aa017e905be7b0d9e0b31ef4471e9544b",
                 "shasum": ""
             },
             "require": {
                 "composer/xdebug-handler": "^3.0",
                 "cweagans/composer-patches": "^1.7",
                 "drupal/coder": "^8.3",
-                "php": ">=7.3",
+                "php": ">=8.1",
                 "phpcompatibility/php-compatibility": "^9.1",
                 "phpmd/phpmd": "^2.10",
-                "phpro/grumphp": "^1.5",
-                "squizlabs/php_codesniffer": "^3.6"
+                "squizlabs/php_codesniffer": "^3.6",
+                "symfony/yaml": "^4.4 | ^5.0 | ^6.0"
             },
             "require-dev": {
-                "openeuropa/task-runner": "^1.0.0-beta6",
-                "phpunit/phpunit": "^5.0"
+                "phpunit/phpunit": "^9.0"
             },
             "type": "phpcodesniffer-standard",
             "extra": {
@@ -17730,9 +16984,6 @@
             "autoload": {
                 "psr-0": {
                     "QualityAssurance\\": "phpcs/QualityAssurance/"
-                },
-                "psr-4": {
-                    "EcEuropa\\QaAutomation\\": "./src/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -17747,20 +16998,20 @@
                 "issues": "https://github.com/ec-europa/qa-automation/issues",
                 "source": "https://github.com/ec-europa/qa-automation"
             },
-            "time": "2022-08-03T12:32:01+00:00"
+            "time": "2022-09-28T07:08:18+00:00"
         },
         {
             "name": "ec-europa/toolkit",
-            "version": "8.6.23",
+            "version": "9.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/ec-europa/toolkit.git",
-                "reference": "2343e9d91e230ae8a81671d9d757f3d78f41c3b7"
+                "reference": "c7979d9c4194ded798f62eed02c08150998e7432"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/ec-europa/toolkit/zipball/2343e9d91e230ae8a81671d9d757f3d78f41c3b7",
-                "reference": "2343e9d91e230ae8a81671d9d757f3d78f41c3b7",
+                "url": "https://api.github.com/repos/ec-europa/toolkit/zipball/c7979d9c4194ded798f62eed02c08150998e7432",
+                "reference": "c7979d9c4194ded798f62eed02c08150998e7432",
                 "shasum": ""
             },
             "require": {
@@ -17768,7 +17019,7 @@
                 "consolidation/annotated-command": "^4.5 <4.5.7",
                 "cweagans/composer-patches": "^1.4 || ^1.7",
                 "drush/drush": "^9.7.1 || ^10.0.0 || ^11.0.4",
-                "ec-europa/qa-automation": "^8.1.5",
+                "ec-europa/qa-automation": "^9.0",
                 "ext-curl": "*",
                 "ext-dom": "*",
                 "ext-json": "*",
@@ -17776,7 +17027,7 @@
                 "guzzlehttp/guzzle": "^6.3 || ^7.0",
                 "j13k/yaml-lint": "^1.1",
                 "openeuropa/task-runner": "^2.0@alpha",
-                "php": ">=7.4",
+                "php": ">=8.1",
                 "php-parallel-lint/php-parallel-lint": "^1.3",
                 "phpmd/phpmd": "^2.12",
                 "phpunit/phpunit": "^7.5 || ^9.5"
@@ -17804,90 +17055,34 @@
                 "email": "DIGIT-NEXTEUROPA-QA@ec.europa.eu",
                 "source": "https://github.com/ec-europa/toolkit"
             },
-            "time": "2022-11-04T13:01:25+00:00"
-        },
-        {
-            "name": "fabpot/goutte",
-            "version": "v3.3.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/FriendsOfPHP/Goutte.git",
-                "reference": "80a23b64f44d54dd571d114c473d9d7e9ed84ca5"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/80a23b64f44d54dd571d114c473d9d7e9ed84ca5",
-                "reference": "80a23b64f44d54dd571d114c473d9d7e9ed84ca5",
-                "shasum": ""
-            },
-            "require": {
-                "guzzlehttp/guzzle": "^6.0",
-                "php": ">=7.1.3",
-                "symfony/browser-kit": "^4.4|^5.0",
-                "symfony/css-selector": "^4.4|^5.0",
-                "symfony/dom-crawler": "^4.4|^5.0"
-            },
-            "require-dev": {
-                "symfony/phpunit-bridge": "^5.0"
-            },
-            "type": "application",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Goutte\\": "Goutte"
-                },
-                "exclude-from-classmap": [
-                    "Goutte/Tests"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                }
-            ],
-            "description": "A simple PHP Web Scraper",
-            "homepage": "https://github.com/FriendsOfPHP/Goutte",
-            "keywords": [
-                "scraper"
-            ],
-            "support": {
-                "issues": "https://github.com/FriendsOfPHP/Goutte/issues",
-                "source": "https://github.com/FriendsOfPHP/Goutte/tree/v3.3.1"
-            },
-            "time": "2020-11-01T09:30:18+00:00"
+            "time": "2022-09-28T06:50:45+00:00"
         },
         {
             "name": "friends-of-behat/mink-extension",
-            "version": "2.3.1",
+            "version": "v2.7.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/FriendsOfBehat/MinkExtension.git",
-                "reference": "80f7849ba53867181b7e412df9210e12fba50177"
+                "reference": "ffc5ee88aa8e5b430f0c417adb3f0c943ffeafed"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/FriendsOfBehat/MinkExtension/zipball/80f7849ba53867181b7e412df9210e12fba50177",
-                "reference": "80f7849ba53867181b7e412df9210e12fba50177",
+                "url": "https://api.github.com/repos/FriendsOfBehat/MinkExtension/zipball/ffc5ee88aa8e5b430f0c417adb3f0c943ffeafed",
+                "reference": "ffc5ee88aa8e5b430f0c417adb3f0c943ffeafed",
                 "shasum": ""
             },
             "require": {
                 "behat/behat": "^3.0.5",
                 "behat/mink": "^1.5",
-                "php": ">=5.3.2",
-                "symfony/config": "^2.7|^3.0|^4.0"
+                "php": ">=7.4",
+                "symfony/config": "^4.4 || ^5.0 || ^6.0"
+            },
+            "replace": {
+                "behat/mink-extension": "self.version"
             },
             "require-dev": {
-                "behat/mink-goutte-driver": "^1.1",
-                "phpspec/phpspec": "^2.0"
+                "behat/mink-goutte-driver": "^1.1 || ^2.0",
+                "phpspec/phpspec": "^6.0 || ^7.0 || 7.1.x-dev"
             },
             "type": "behat-extension",
             "extra": {
@@ -17923,9 +17118,9 @@
                 "web"
             ],
             "support": {
-                "source": "https://github.com/FriendsOfBehat/MinkExtension/tree/2.3.1"
+                "source": "https://github.com/FriendsOfBehat/MinkExtension/tree/v2.7.2"
             },
-            "time": "2018-02-06T15:36:30+00:00"
+            "time": "2022-10-17T07:23:22+00:00"
         },
         {
             "name": "friends-of-behat/service-container-extension",
@@ -18112,16 +17307,16 @@
         },
         {
             "name": "instaclick/php-webdriver",
-            "version": "1.4.15",
+            "version": "1.4.16",
             "source": {
                 "type": "git",
                 "url": "https://github.com/instaclick/php-webdriver.git",
-                "reference": "ed8f7741a0952db42686aae0780a0935138a7cf8"
+                "reference": "a39a1f6dc0f4ddd8b2438fa5eb1f67755730d606"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/ed8f7741a0952db42686aae0780a0935138a7cf8",
-                "reference": "ed8f7741a0952db42686aae0780a0935138a7cf8",
+                "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/a39a1f6dc0f4ddd8b2438fa5eb1f67755730d606",
+                "reference": "a39a1f6dc0f4ddd8b2438fa5eb1f67755730d606",
                 "shasum": ""
             },
             "require": {
@@ -18169,9 +17364,9 @@
             ],
             "support": {
                 "issues": "https://github.com/instaclick/php-webdriver/issues",
-                "source": "https://github.com/instaclick/php-webdriver/tree/1.4.15"
+                "source": "https://github.com/instaclick/php-webdriver/tree/1.4.16"
             },
-            "time": "2022-08-09T14:26:29+00:00"
+            "time": "2022-10-28T13:30:35+00:00"
         },
         {
             "name": "j13k/yaml-lint",
@@ -18328,28 +17523,28 @@
         },
         {
             "name": "lovers-of-behat/table-extension",
-            "version": "1.3.0",
+            "version": "dev-drop-behat-mink-extension",
             "source": {
                 "type": "git",
                 "url": "https://github.com/LoversOfBehat/TableExtension.git",
-                "reference": "895c5c5cec095ce67e5f82d9064e3e1d3787950d"
+                "reference": "4e84e899fdae03cc43269043cd49ad7a0a3f779c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/LoversOfBehat/TableExtension/zipball/895c5c5cec095ce67e5f82d9064e3e1d3787950d",
-                "reference": "895c5c5cec095ce67e5f82d9064e3e1d3787950d",
+                "url": "https://api.github.com/repos/LoversOfBehat/TableExtension/zipball/4e84e899fdae03cc43269043cd49ad7a0a3f779c",
+                "reference": "4e84e899fdae03cc43269043cd49ad7a0a3f779c",
                 "shasum": ""
             },
             "require": {
                 "behat/behat": "^3.4",
-                "behat/mink-extension": "^2.3",
+                "friends-of-behat/mink-extension": "^2.7",
                 "php": ">=7.1",
                 "symfony/dependency-injection": "^2.1|^3.0|^4.0",
                 "symfony/dom-crawler": "^2.8|^3.0|^4.0",
                 "symfony/event-dispatcher": "^2.0|^3.0|^4.0"
             },
             "require-dev": {
-                "behat/mink-goutte-driver": "^1.2",
+                "behat/mink-goutte-driver": "^1.2 || ^2",
                 "squizlabs/php_codesniffer": "^3.2",
                 "symfony/css-selector": "^2.0|^3.0|^4.0"
             },
@@ -18372,9 +17567,9 @@
             "description": "Behat extension to inspect HTML tables",
             "support": {
                 "issues": "https://github.com/LoversOfBehat/TableExtension/issues",
-                "source": "https://github.com/LoversOfBehat/TableExtension/tree/1.3.0"
+                "source": "https://github.com/LoversOfBehat/TableExtension/tree/drop-behat-mink-extension"
             },
-            "time": "2022-02-15T16:00:27+00:00"
+            "time": "2022-09-06T14:12:30+00:00"
         },
         {
             "name": "mathieuviossat/arraytotexttable",
@@ -18687,99 +17882,22 @@
             },
             "time": "2022-01-12T09:43:01+00:00"
         },
-        {
-            "name": "ondram/ci-detector",
-            "version": "4.1.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/OndraM/ci-detector.git",
-                "reference": "8a4b664e916df82ff26a44709942dfd593fa6f30"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/OndraM/ci-detector/zipball/8a4b664e916df82ff26a44709942dfd593fa6f30",
-                "reference": "8a4b664e916df82ff26a44709942dfd593fa6f30",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^7.1 || ^8.0"
-            },
-            "require-dev": {
-                "ergebnis/composer-normalize": "^2.2",
-                "lmc/coding-standard": "^1.3 || ^2.1",
-                "php-parallel-lint/php-parallel-lint": "^1.2",
-                "phpstan/extension-installer": "^1.0.5",
-                "phpstan/phpstan": "^0.12.58",
-                "phpstan/phpstan-phpunit": "^0.12.16",
-                "phpunit/phpunit": "^7.1 || ^8.0 || ^9.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "OndraM\\CiDetector\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Ondřej Machulda",
-                    "email": "ondrej.machulda@gmail.com"
-                }
-            ],
-            "description": "Detect continuous integration environment and provide unified access to properties of current build",
-            "keywords": [
-                "CircleCI",
-                "Codeship",
-                "Wercker",
-                "adapter",
-                "appveyor",
-                "aws",
-                "aws codebuild",
-                "azure",
-                "azure devops",
-                "azure pipelines",
-                "bamboo",
-                "bitbucket",
-                "buddy",
-                "ci-info",
-                "codebuild",
-                "continuous integration",
-                "continuousphp",
-                "devops",
-                "drone",
-                "github",
-                "gitlab",
-                "interface",
-                "jenkins",
-                "pipelines",
-                "sourcehut",
-                "teamcity",
-                "travis"
-            ],
-            "support": {
-                "issues": "https://github.com/OndraM/ci-detector/issues",
-                "source": "https://github.com/OndraM/ci-detector/tree/4.1.0"
-            },
-            "time": "2021-04-14T09:16:52+00:00"
-        },
         {
             "name": "openeuropa/task-runner",
-            "version": "2.0.0-alpha2",
+            "version": "2.0.0-alpha3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/openeuropa/task-runner.git",
-                "reference": "72074b80b03f731a798f587473bd59d0ee079590"
+                "reference": "35a9b31cfce185289f42a072a0ed67d8c655ffd2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/openeuropa/task-runner/zipball/72074b80b03f731a798f587473bd59d0ee079590",
-                "reference": "72074b80b03f731a798f587473bd59d0ee079590",
+                "url": "https://api.github.com/repos/openeuropa/task-runner/zipball/35a9b31cfce185289f42a072a0ed67d8c655ffd2",
+                "reference": "35a9b31cfce185289f42a072a0ed67d8c655ffd2",
                 "shasum": ""
             },
             "require": {
+                "consolidation/annotated-command": "^4.3 <4.5.7",
                 "consolidation/robo": "^3.0",
                 "gitonomy/gitlib": "^1.0",
                 "jakeasmith/http_build_url": "^1.0.1",
@@ -18805,86 +17923,21 @@
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "EUPL-1.2"
-            ],
-            "description": "PHP task runner based on Robo, focused on extensibility.",
-            "keywords": [
-                "automation",
-                "robo",
-                "task-runner",
-                "yaml"
-            ],
-            "support": {
-                "issues": "https://github.com/openeuropa/task-runner/issues",
-                "source": "https://github.com/openeuropa/task-runner/tree/2.0.0-alpha2"
-            },
-            "time": "2022-02-21T14:50:27+00:00"
-        },
-        {
-            "name": "opis/closure",
-            "version": "3.6.3",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/opis/closure.git",
-                "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad",
-                "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.4 || ^7.0 || ^8.0"
-            },
-            "require-dev": {
-                "jeremeamia/superclosure": "^2.0",
-                "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.6.x-dev"
-                }
-            },
-            "autoload": {
-                "files": [
-                    "functions.php"
-                ],
-                "psr-4": {
-                    "Opis\\Closure\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Marius Sarca",
-                    "email": "marius.sarca@gmail.com"
-                },
-                {
-                    "name": "Sorin Sarca",
-                    "email": "sarca_sorin@hotmail.com"
-                }
+            "license": [
+                "EUPL-1.2"
             ],
-            "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.",
-            "homepage": "https://opis.io/closure",
+            "description": "PHP task runner based on Robo, focused on extensibility.",
             "keywords": [
-                "anonymous functions",
-                "closure",
-                "function",
-                "serializable",
-                "serialization",
-                "serialize"
+                "automation",
+                "robo",
+                "task-runner",
+                "yaml"
             ],
             "support": {
-                "issues": "https://github.com/opis/closure/issues",
-                "source": "https://github.com/opis/closure/tree/3.6.3"
+                "issues": "https://github.com/openeuropa/task-runner/issues",
+                "source": "https://github.com/openeuropa/task-runner/tree/2.0.0-alpha3"
             },
-            "time": "2022-01-27T09:35:39+00:00"
+            "time": "2022-10-21T14:06:43+00:00"
         },
         {
             "name": "palantirnet/drupal-rector",
@@ -19966,121 +19019,6 @@
             ],
             "time": "2022-07-30T15:51:26+00:00"
         },
-        {
-            "name": "phpro/grumphp",
-            "version": "v1.5.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpro/grumphp.git",
-                "reference": "ef3d019f25f6852e61c3af7c8c234b1bf451a34c"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpro/grumphp/zipball/ef3d019f25f6852e61c3af7c8c234b1bf451a34c",
-                "reference": "ef3d019f25f6852e61c3af7c8c234b1bf451a34c",
-                "shasum": ""
-            },
-            "require": {
-                "amphp/amp": "^2.4",
-                "amphp/parallel": "^1.4",
-                "amphp/parallel-functions": "1.0",
-                "composer-plugin-api": "~1.0 || ~2.0",
-                "doctrine/collections": "^1.6.7",
-                "ext-json": "*",
-                "gitonomy/gitlib": "^1.0.3",
-                "monolog/monolog": "~1.16 || ^2.0",
-                "ondram/ci-detector": "^3.5 || ^4.0",
-                "opis/closure": "^3.5",
-                "php": "^7.3 || ^8.0",
-                "psr/container": "^1.0",
-                "seld/jsonlint": "~1.1",
-                "symfony/config": "~4.4 || ~5.0",
-                "symfony/console": "~4.4 || ~5.0",
-                "symfony/dependency-injection": "~4.4 || ~5.0",
-                "symfony/dotenv": "~4.4 || ~5.0",
-                "symfony/event-dispatcher": "~4.4 || ~5.0",
-                "symfony/filesystem": "~4.4 || ~5.0",
-                "symfony/finder": "~4.4 || ~5.0",
-                "symfony/options-resolver": "~4.4 || ~5.0",
-                "symfony/process": "~4.4 || ~5.0",
-                "symfony/yaml": "~4.4 || ~5.0"
-            },
-            "require-dev": {
-                "brianium/paratest": "^6.3",
-                "composer/composer": "^1.10.22 || ^2.0.13",
-                "nikic/php-parser": "~4.0",
-                "php-parallel-lint/php-parallel-lint": "^1.3",
-                "phpspec/phpspec": "^7.1",
-                "phpspec/prophecy-phpunit": "^2.0",
-                "phpunit/phpunit": "^9.5"
-            },
-            "suggest": {
-                "atoum/atoum": "Lets GrumPHP run your unit tests.",
-                "behat/behat": "Lets GrumPHP validate your project features.",
-                "brianium/paratest": "Lets GrumPHP run PHPUnit in parallel.",
-                "codeception/codeception": "Lets GrumPHP run your project's full stack tests",
-                "consolidation/robo": "Lets GrumPHP run your automated PHP tasks.",
-                "designsecurity/progpilot": "Lets GrumPHP be sure that there are no vulnerabilities in your code.",
-                "doctrine/orm": "Lets GrumPHP validate your Doctrine mapping files.",
-                "enlightn/security-checker": "Lets GrumPHP be sure that there are no known security issues.",
-                "ergebnis/composer-normalize": "Lets GrumPHP tidy and normalize your composer.json file.",
-                "friendsofphp/php-cs-fixer": "Lets GrumPHP automatically fix your codestyle.",
-                "friendsoftwig/twigcs": "Lets GrumPHP check Twig coding standard.",
-                "infection/infection": "Lets GrumPHP evaluate the quality your unit tests",
-                "maglnet/composer-require-checker": "Lets GrumPHP analyze composer dependencies.",
-                "malukenho/kawaii-gherkin": "Lets GrumPHP lint your Gherkin files.",
-                "nette/tester": "Lets GrumPHP run your unit tests with nette tester.",
-                "nikic/php-parser": "Lets GrumPHP run static analyses through your PHP files.",
-                "pestphp/pest": "Lets GrumPHP run your unit test with Pest PHP",
-                "phan/phan": "Lets GrumPHP unleash a static analyzer on your code",
-                "phing/phing": "Lets GrumPHP run your automated PHP tasks.",
-                "php-parallel-lint/php-parallel-lint": "Lets GrumPHP quickly lint your entire code base.",
-                "phpmd/phpmd": "Lets GrumPHP sort out the mess in your code",
-                "phpspec/phpspec": "Lets GrumPHP spec your code.",
-                "phpstan/phpstan": "Lets GrumPHP discover bugs in your code without running it.",
-                "phpunit/phpunit": "Lets GrumPHP run your unit tests.",
-                "povils/phpmnd": "Lets GrumPHP help you detect magic numbers in PHP code.",
-                "roave/security-advisories": "Lets GrumPHP be sure that there are no known security issues.",
-                "sebastian/phpcpd": "Lets GrumPHP find duplicated code.",
-                "squizlabs/php_codesniffer": "Lets GrumPHP sniff on your code.",
-                "sstalle/php7cc": "Lets GrumPHP check PHP 5.3 - 5.6 code compatibility with PHP 7.",
-                "symfony/phpunit-bridge": "Lets GrumPHP run your unit tests with the phpunit-bridge of Symfony.",
-                "symplify/easy-coding-standard": "Lets GrumPHP check coding standard.",
-                "vimeo/psalm": "Lets GrumPHP discover errors in your code without running it."
-            },
-            "bin": [
-                "bin/grumphp"
-            ],
-            "type": "composer-plugin",
-            "extra": {
-                "class": "GrumPHP\\Composer\\GrumPHPPlugin"
-            },
-            "autoload": {
-                "psr-4": {
-                    "GrumPHP\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Toon Verwerft",
-                    "email": "toon.verwerft@phpro.be"
-                },
-                {
-                    "name": "Community",
-                    "homepage": "https://github.com/phpro/grumphp/graphs/contributors"
-                }
-            ],
-            "description": "A composer plugin that enables source code quality checks.",
-            "support": {
-                "issues": "https://github.com/phpro/grumphp/issues",
-                "source": "https://github.com/phpro/grumphp/tree/v1.5.1"
-            },
-            "time": "2022-02-07T13:28:33+00:00"
-        },
         {
             "name": "phpspec/prophecy",
             "version": "v1.15.0",
@@ -20202,16 +19140,16 @@
         },
         {
             "name": "phpstan/phpdoc-parser",
-            "version": "1.11.0",
+            "version": "1.13.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpdoc-parser.git",
-                "reference": "7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65"
+                "reference": "33aefcdab42900e36366d0feab6206e2dd68f947"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65",
-                "reference": "7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65",
+                "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/33aefcdab42900e36366d0feab6206e2dd68f947",
+                "reference": "33aefcdab42900e36366d0feab6206e2dd68f947",
                 "shasum": ""
             },
             "require": {
@@ -20241,22 +19179,22 @@
             "description": "PHPDoc parser with support for nullable, intersection and generic types",
             "support": {
                 "issues": "https://github.com/phpstan/phpdoc-parser/issues",
-                "source": "https://github.com/phpstan/phpdoc-parser/tree/1.11.0"
+                "source": "https://github.com/phpstan/phpdoc-parser/tree/1.13.0"
             },
-            "time": "2022-10-14T13:32:28+00:00"
+            "time": "2022-10-21T09:57:39+00:00"
         },
         {
             "name": "phpstan/phpstan",
-            "version": "1.8.10",
+            "version": "1.9.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpstan.git",
-                "reference": "0c4459dc42c568b818b3f25186589f3acddc1823"
+                "reference": "a59c8b5bfd4a236f27efc8b5ce72c313c2b54b5f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0c4459dc42c568b818b3f25186589f3acddc1823",
-                "reference": "0c4459dc42c568b818b3f25186589f3acddc1823",
+                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a59c8b5bfd4a236f27efc8b5ce72c313c2b54b5f",
+                "reference": "a59c8b5bfd4a236f27efc8b5ce72c313c2b54b5f",
                 "shasum": ""
             },
             "require": {
@@ -20286,7 +19224,7 @@
             ],
             "support": {
                 "issues": "https://github.com/phpstan/phpstan/issues",
-                "source": "https://github.com/phpstan/phpstan/tree/1.8.10"
+                "source": "https://github.com/phpstan/phpstan/tree/1.9.1"
             },
             "funding": [
                 {
@@ -20302,7 +19240,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-10-17T14:23:35+00:00"
+            "time": "2022-11-04T13:35:59+00:00"
         },
         {
             "name": "phpstan/phpstan-deprecation-rules",
@@ -20356,16 +19294,16 @@
         },
         {
             "name": "phpunit/php-code-coverage",
-            "version": "9.2.17",
+            "version": "9.2.18",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
+                "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
-                "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
+                "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
                 "shasum": ""
             },
             "require": {
@@ -20421,7 +19359,7 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
-                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
+                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.18"
             },
             "funding": [
                 {
@@ -20429,7 +19367,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2022-08-30T12:24:04+00:00"
+            "time": "2022-10-27T13:35:33+00:00"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -20674,16 +19612,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "9.5.25",
+            "version": "9.5.26",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d"
+                "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
-                "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2",
+                "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2",
                 "shasum": ""
             },
             "require": {
@@ -20756,7 +19694,7 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26"
             },
             "funding": [
                 {
@@ -20772,7 +19710,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-09-25T03:44:45+00:00"
+            "time": "2022-10-28T06:00:21+00:00"
         },
         {
             "name": "rector/rector",
@@ -21878,70 +20816,6 @@
             ],
             "time": "2020-09-28T06:39:44+00:00"
         },
-        {
-            "name": "seld/jsonlint",
-            "version": "1.9.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/Seldaek/jsonlint.git",
-                "reference": "4211420d25eba80712bff236a98960ef68b866b7"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7",
-                "reference": "4211420d25eba80712bff236a98960ef68b866b7",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3 || ^7.0 || ^8.0"
-            },
-            "require-dev": {
-                "phpstan/phpstan": "^1.5",
-                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
-            },
-            "bin": [
-                "bin/jsonlint"
-            ],
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "Seld\\JsonLint\\": "src/Seld/JsonLint/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be",
-                    "homepage": "http://seld.be"
-                }
-            ],
-            "description": "JSON Linter",
-            "keywords": [
-                "json",
-                "linter",
-                "parser",
-                "validator"
-            ],
-            "support": {
-                "issues": "https://github.com/Seldaek/jsonlint/issues",
-                "source": "https://github.com/Seldaek/jsonlint/tree/1.9.0"
-            },
-            "funding": [
-                {
-                    "url": "https://github.com/Seldaek",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2022-04-01T13:37:23+00:00"
-        },
         {
             "name": "sirbrillig/phpcs-variable-analysis",
             "version": "v2.11.9",
@@ -22119,28 +20993,28 @@
         },
         {
             "name": "symfony/browser-kit",
-            "version": "v4.4.44",
+            "version": "v5.4.11",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/browser-kit.git",
-                "reference": "2a1ff40723ef6b29c8229a860a9c8f815ad7dbbb"
+                "reference": "081fe28a26b6bd671dea85ef3a4b5003f3c88027"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/browser-kit/zipball/2a1ff40723ef6b29c8229a860a9c8f815ad7dbbb",
-                "reference": "2a1ff40723ef6b29c8229a860a9c8f815ad7dbbb",
+                "url": "https://api.github.com/repos/symfony/browser-kit/zipball/081fe28a26b6bd671dea85ef3a4b5003f3c88027",
+                "reference": "081fe28a26b6bd671dea85ef3a4b5003f3c88027",
                 "shasum": ""
             },
             "require": {
-                "php": ">=7.1.3",
-                "symfony/dom-crawler": "^3.4|^4.0|^5.0",
+                "php": ">=7.2.5",
+                "symfony/dom-crawler": "^4.4|^5.0|^6.0",
                 "symfony/polyfill-php80": "^1.16"
             },
             "require-dev": {
-                "symfony/css-selector": "^3.4|^4.0|^5.0",
-                "symfony/http-client": "^4.3|^5.0",
-                "symfony/mime": "^4.3|^5.0",
-                "symfony/process": "^3.4|^4.0|^5.0"
+                "symfony/css-selector": "^4.4|^5.0|^6.0",
+                "symfony/http-client": "^4.4|^5.0|^6.0",
+                "symfony/mime": "^4.4|^5.0|^6.0",
+                "symfony/process": "^4.4|^5.0|^6.0"
             },
             "suggest": {
                 "symfony/process": ""
@@ -22171,7 +21045,7 @@
             "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/browser-kit/tree/v4.4.44"
+                "source": "https://github.com/symfony/browser-kit/tree/v5.4.11"
             },
             "funding": [
                 {
@@ -22187,7 +21061,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-07-25T12:56:14+00:00"
+            "time": "2022-07-27T15:50:05+00:00"
         },
         {
             "name": "symfony/config",
@@ -22342,100 +21216,52 @@
             "time": "2022-08-03T12:57:57+00:00"
         },
         {
-            "name": "symfony/dotenv",
-            "version": "v5.4.5",
+            "name": "symfony/http-client",
+            "version": "v5.4.15",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/dotenv.git",
-                "reference": "83a2310904a4f5d4f42526227b5a578ac82232a9"
+                "url": "https://github.com/symfony/http-client.git",
+                "reference": "8f29b0f06c9ff48c8431e78eb90c8bd6f82cb12b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dotenv/zipball/83a2310904a4f5d4f42526227b5a578ac82232a9",
-                "reference": "83a2310904a4f5d4f42526227b5a578ac82232a9",
+                "url": "https://api.github.com/repos/symfony/http-client/zipball/8f29b0f06c9ff48c8431e78eb90c8bd6f82cb12b",
+                "reference": "8f29b0f06c9ff48c8431e78eb90c8bd6f82cb12b",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.2.5",
-                "symfony/deprecation-contracts": "^2.1|^3"
-            },
-            "require-dev": {
-                "symfony/console": "^4.4|^5.0|^6.0",
-                "symfony/process": "^4.4|^5.0|^6.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Dotenv\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Registers environment variables from a .env file",
-            "homepage": "https://symfony.com",
-            "keywords": [
-                "dotenv",
-                "env",
-                "environment"
-            ],
-            "support": {
-                "source": "https://github.com/symfony/dotenv/tree/v5.4.5"
-            },
-            "funding": [
-                {
-                    "url": "https://symfony.com/sponsor",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/fabpot",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2022-02-15T17:04:12+00:00"
-        },
-        {
-            "name": "symfony/options-resolver",
-            "version": "v5.4.11",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/options-resolver.git",
-                "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690"
+                "psr/log": "^1|^2|^3",
+                "symfony/deprecation-contracts": "^2.1|^3",
+                "symfony/http-client-contracts": "^2.4",
+                "symfony/polyfill-php73": "^1.11",
+                "symfony/polyfill-php80": "^1.16",
+                "symfony/service-contracts": "^1.0|^2|^3"
             },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/options-resolver/zipball/54f14e36aa73cb8f7261d7686691fd4d75ea2690",
-                "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690",
-                "shasum": ""
+            "provide": {
+                "php-http/async-client-implementation": "*",
+                "php-http/client-implementation": "*",
+                "psr/http-client-implementation": "1.0",
+                "symfony/http-client-implementation": "2.4"
             },
-            "require": {
-                "php": ">=7.2.5",
-                "symfony/deprecation-contracts": "^2.1|^3",
-                "symfony/polyfill-php73": "~1.0",
-                "symfony/polyfill-php80": "^1.16"
+            "require-dev": {
+                "amphp/amp": "^2.5",
+                "amphp/http-client": "^4.2.1",
+                "amphp/http-tunnel": "^1.0",
+                "amphp/socket": "^1.1",
+                "guzzlehttp/promises": "^1.4",
+                "nyholm/psr7": "^1.0",
+                "php-http/httplug": "^1.0|^2.0",
+                "psr/http-client": "^1.0",
+                "symfony/dependency-injection": "^4.4|^5.0|^6.0",
+                "symfony/http-kernel": "^4.4.13|^5.1.5|^6.0",
+                "symfony/process": "^4.4|^5.0|^6.0",
+                "symfony/stopwatch": "^4.4|^5.0|^6.0"
             },
             "type": "library",
             "autoload": {
                 "psr-4": {
-                    "Symfony\\Component\\OptionsResolver\\": ""
+                    "Symfony\\Component\\HttpClient\\": ""
                 },
                 "exclude-from-classmap": [
                     "/Tests/"
@@ -22447,23 +21273,18 @@
             ],
             "authors": [
                 {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
                 },
                 {
                     "name": "Symfony Community",
                     "homepage": "https://symfony.com/contributors"
                 }
             ],
-            "description": "Provides an improved replacement for the array_replace PHP function",
+            "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
             "homepage": "https://symfony.com",
-            "keywords": [
-                "config",
-                "configuration",
-                "options"
-            ],
             "support": {
-                "source": "https://github.com/symfony/options-resolver/tree/v5.4.11"
+                "source": "https://github.com/symfony/http-client/tree/v5.4.15"
             },
             "funding": [
                 {
@@ -22479,7 +21300,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-07-20T13:00:38+00:00"
+            "time": "2022-10-25T16:22:13+00:00"
         },
         {
             "name": "symfony/phpunit-bridge",
@@ -22778,38 +21599,78 @@
             "time": "2022-10-16T01:01:54+00:00"
         },
         {
-            "name": "weitzman/drupal-test-traits",
-            "version": "1.6.0",
+            "name": "webmozart/assert",
+            "version": "1.11.0",
             "source": {
                 "type": "git",
-                "url": "git@gitlab.com:weitzman/drupal-test-traits.git",
-                "reference": "e7076173db0daa256ec7daab92ad6685ccffdca4"
+                "url": "https://github.com/webmozarts/assert.git",
+                "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://gitlab.com/api/v4/projects/weitzman%2Fdrupal-test-traits/repository/archive.zip?sha=e7076173db0daa256ec7daab92ad6685ccffdca4",
-                "reference": "e7076173db0daa256ec7daab92ad6685ccffdca4",
+                "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
+                "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
                 "shasum": ""
             },
             "require": {
-                "behat/mink": "^1.8 | 1.7.1 | 1.7.x-dev",
-                "behat/mink-goutte-driver": "^1.2",
-                "php": ">=7.0.8",
-                "phpunit/phpunit": ">=6.5",
-                "webflo/drupal-finder": "^1.1"
+                "ext-ctype": "*",
+                "php": "^7.2 || ^8.0"
+            },
+            "conflict": {
+                "phpstan/phpstan": "<0.12.20",
+                "vimeo/psalm": "<4.6.1 || 4.6.2"
             },
             "require-dev": {
-                "behat/mink-selenium2-driver": "1.4.0 | 1.3.1 | 1.3.x-dev",
-                "composer/installers": "^1.2",
-                "dmore/chrome-mink-driver": "^2.6",
-                "drupal/core-composer-scaffold": "^9",
-                "drupal/core-dev": "^9",
-                "drupal/core-recommended": "^9",
-                "drush/drush": "^10",
-                "jakub-onderka/php-parallel-lint": "^1.0",
-                "squizlabs/php_codesniffer": "^3.2",
-                "zaporylie/composer-drupal-optimizations": "^1.0"
+                "phpunit/phpunit": "^8.5.13"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.10-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Webmozart\\Assert\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@gmail.com"
+                }
+            ],
+            "description": "Assertions to validate method input/output with nice error messages.",
+            "keywords": [
+                "assert",
+                "check",
+                "validate"
+            ],
+            "support": {
+                "issues": "https://github.com/webmozarts/assert/issues",
+                "source": "https://github.com/webmozarts/assert/tree/1.11.0"
+            },
+            "time": "2022-06-03T18:03:27+00:00"
+        },
+        {
+            "name": "weitzman/drupal-test-traits",
+            "version": "2.x-dev",
+            "source": {
+                "type": "git",
+                "url": "git@gitlab.com:weitzman/drupal-test-traits.git",
+                "reference": "f73971bae49ed85a3e1f6f1f07eff3afdb69acb3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://gitlab.com/api/v4/projects/weitzman%2Fdrupal-test-traits/repository/archive.zip?sha=f73971bae49ed85a3e1f6f1f07eff3afdb69acb3",
+                "reference": "f73971bae49ed85a3e1f6f1f07eff3afdb69acb3",
+                "shasum": ""
             },
+            "default-branch": true,
             "type": "library",
             "extra": {
                 "installer-paths": {
@@ -22844,7 +21705,7 @@
                 }
             ],
             "description": "Traits for testing Drupal sites that have user content (versus unpopulated sites).",
-            "time": "2022-05-31T12:57:35+00:00"
+            "time": "2022-10-11T02:16:53+00:00"
         },
         {
             "name": "weitzman/logintrait",
@@ -22887,22 +21748,39 @@
             "time": "2021-07-07T17:59:50+00:00"
         }
     ],
-    "aliases": [],
+    "aliases": [
+        {
+            "package": "drupal/drupal-extension",
+            "version": "dev-use-guzzle",
+            "alias": "4.2.999",
+            "alias_normalized": "4.2.999.0"
+        },
+        {
+            "package": "drupaltest/behat-one-time-login",
+            "version": "dev-drupal-extension",
+            "alias": "1.0.999",
+            "alias_normalized": "1.0.999.0"
+        }
+    ],
     "minimum-stability": "dev",
     "stability-flags": {
         "drupal/dropsolid_purge": 10,
         "drupal/facets_date_range": 10,
         "drupal/page_manager": 10,
         "drupal/views_block_area": 10,
+        "drupal/drupal-extension": 20,
+        "drupaltest/behat-one-time-login": 20,
+        "lovers-of-behat/table-extension": 20,
         "php-task-runner/composer": 20,
         "php-task-runner/redis": 20,
         "php-task-runner/scss": 20,
-        "php-task-runner/sparql": 20
+        "php-task-runner/sparql": 20,
+        "weitzman/drupal-test-traits": 20
     },
     "prefer-stable": true,
     "prefer-lowest": false,
     "platform": {
-        "php": ">=7.4",
+        "php": ">=8.1.3",
         "ext-dom": "*",
         "ext-json": "*",
         "ext-pdo": "*",
@@ -22915,7 +21793,7 @@
         "ext-libxml": "*"
     },
     "platform-overrides": {
-        "php": "7.4.0"
+        "php": "8.1.3"
     },
     "plugin-api-version": "2.3.0"
 }
diff --git a/config/sync/views.view.announcements.yml b/config/sync/views.view.announcements.yml
index a2718c615e580b6a274f8994f80fb74d1a492692..92c256131e4818fa4704f714f20cbb375273a6c8 100644
--- a/config/sync/views.view.announcements.yml
+++ b/config/sync/views.view.announcements.yml
@@ -400,7 +400,6 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: edit
-          bypass_access_check: false
           output_url_as_text: false
           absolute: false
       pager:
@@ -1133,7 +1132,6 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: edit
-          bypass_access_check: false
           output_url_as_text: false
           absolute: false
       arguments: {  }
@@ -1265,7 +1263,7 @@ display:
         menu_name: admin
         parent: system.admin
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
@@ -1318,7 +1316,7 @@ display:
         menu_name: main
         parent: ''
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
diff --git a/config/sync/views.view.asset_distribution_downloads.yml b/config/sync/views.view.asset_distribution_downloads.yml
index 37954c21a775292bf29e8bd5681f6e9a95c81ea7..b82f079d6130fe75b81bf812150b7161e667f593 100644
--- a/config/sync/views.view.asset_distribution_downloads.yml
+++ b/config/sync/views.view.asset_distribution_downloads.yml
@@ -754,7 +754,7 @@ display:
         title: Statistics
         description: Stuff
         weight: 0
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
diff --git a/config/sync/views.view.comment.yml b/config/sync/views.view.comment.yml
index c2e0d2da52f2aa188cf69005658d0464e9127683..7dc36051ad1f8ab2b06d89d10661869f0b6972ff 100644
--- a/config/sync/views.view.comment.yml
+++ b/config/sync/views.view.comment.yml
@@ -889,7 +889,7 @@ display:
         menu_name: admin
         parent: ''
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: 0
       contexts:
@@ -1597,7 +1597,7 @@ display:
         menu_name: admin
         parent: ''
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: 0
       contexts:
diff --git a/config/sync/views.view.content.yml b/config/sync/views.view.content.yml
index f9dd759f32e4fd387371025f7246b9869fa0d9be..598ec2c764a7515355892b138c791c3ef59676e6 100644
--- a/config/sync/views.view.content.yml
+++ b/config/sync/views.view.content.yml
@@ -608,7 +608,7 @@ display:
         description: 'Find and manage content'
         weight: -10
         menu_name: admin
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: 0
       contexts:
diff --git a/config/sync/views.view.curated_content_listings.yml b/config/sync/views.view.curated_content_listings.yml
index e5760b7b1c85f82eefd655767dcd976725691ca4..27b08fb15c638ecede992a3a2738718c1e19193a 100644
--- a/config/sync/views.view.curated_content_listings.yml
+++ b/config/sync/views.view.curated_content_listings.yml
@@ -72,7 +72,6 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: edit
-          bypass_access_check: false
           output_url_as_text: true
           absolute: false
         title:
@@ -260,7 +259,7 @@ display:
     display_options:
       display_extenders: {  }
       path: admin/curated-content-listings
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
diff --git a/config/sync/views.view.eif_recommendation.yml b/config/sync/views.view.eif_recommendation.yml
index 4195a4bd6567985d7a7e2495cd1149e884306ab3..ef21e24534049570a9aa6680fb79c90aff514799 100644
--- a/config/sync/views.view.eif_recommendation.yml
+++ b/config/sync/views.view.eif_recommendation.yml
@@ -598,7 +598,7 @@ display:
         title: All
         description: ''
         weight: 0
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
@@ -724,7 +724,7 @@ display:
         menu_name: main
         parent: ''
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
@@ -850,7 +850,7 @@ display:
         menu_name: main
         parent: ''
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
@@ -979,7 +979,7 @@ display:
         menu_name: main
         parent: ''
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
diff --git a/config/sync/views.view.files.yml b/config/sync/views.view.files.yml
index a2a05fee8b11ba013577973cfb2f43f628457800..b0a853926f83d4dc9c3cbb332a94a36892ef333f 100644
--- a/config/sync/views.view.files.yml
+++ b/config/sync/views.view.files.yml
@@ -763,7 +763,7 @@ display:
         weight: 0
         menu_name: admin
         context: ''
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
@@ -1122,7 +1122,7 @@ display:
       display_description: ''
       display_extenders: {  }
       path: admin/content/files/usage/%
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
diff --git a/config/sync/views.view.group_content_management.yml b/config/sync/views.view.group_content_management.yml
index 03ffd0590fde2c79e94360fa0bbde0ac501ca19a..27b912910eadbc30b8597b1bfe5a5c376ad1b40b 100644
--- a/config/sync/views.view.group_content_management.yml
+++ b/config/sync/views.view.group_content_management.yml
@@ -17,6 +17,7 @@ dependencies:
   module:
     - csv_serialization
     - joinup_group
+    - joinup_group_content_management
     - node
     - rest
     - serialization
@@ -1142,7 +1143,7 @@ display:
           group_type: group
           admin_label: ''
           entity_type: node
-          plugin_id: entity_link
+          plugin_id: accessible_entity_link
           label: URL
           exclude: false
           alter:
@@ -1185,7 +1186,6 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: view
-          bypass_access_check: true
           output_url_as_text: true
           absolute: true
       pager:
@@ -1692,7 +1692,7 @@ display:
         menu_name: main
         parent: ''
         context: '0'
-      always_use_admin_theme: true
+      use_admin_theme: true
     cache_metadata:
       max-age: 0
       contexts:
diff --git a/config/sync/views.view.group_feed.yml b/config/sync/views.view.group_feed.yml
index 624f930f76545e5a97654e4e072152d8a615aa05..b5f2854e77ed8c723b3a84e4105a46c4de281f21 100644
--- a/config/sync/views.view.group_feed.yml
+++ b/config/sync/views.view.group_feed.yml
@@ -1010,7 +1010,6 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: view
-          bypass_access_check: false
           output_url_as_text: true
           absolute: false
           use_highlighting: false
@@ -1066,7 +1065,6 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: view
-          bypass_access_check: false
           output_url_as_text: true
           absolute: false
           use_highlighting: false
diff --git a/config/sync/views.view.legal_notice_report.yml b/config/sync/views.view.legal_notice_report.yml
index 038d82f302c0593f9153d57fd6179566fa7fb6aa..a22c9dda217d100e0ae1821b17c9f5c8819cfa78 100644
--- a/config/sync/views.view.legal_notice_report.yml
+++ b/config/sync/views.view.legal_notice_report.yml
@@ -594,7 +594,7 @@ display:
         menu_name: admin
         parent: joinup.admin_reporting
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
diff --git a/config/sync/views.view.manage_collection_solutions.yml b/config/sync/views.view.manage_collection_solutions.yml
index e53aba7fd5b900bfa0f62b6b3f3119ad3498f881..8190279c83635ca2ecacec49d9443c1435cfb9e0 100644
--- a/config/sync/views.view.manage_collection_solutions.yml
+++ b/config/sync/views.view.manage_collection_solutions.yml
@@ -536,7 +536,7 @@ display:
         menu_name: main
         parent: ''
         context: '0'
-      always_use_admin_theme: true
+      use_admin_theme: true
     cache_metadata:
       max-age: 0
       contexts:
diff --git a/config/sync/views.view.message.yml b/config/sync/views.view.message.yml
index af757afaf0f9c2340ad4bdbdc16ae1c608cf33aa..421587133830af4093d371d60ca55077efc8850b 100644
--- a/config/sync/views.view.message.yml
+++ b/config/sync/views.view.message.yml
@@ -586,7 +586,7 @@ display:
         title: ''
         description: ''
         weight: 0
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: 0
       contexts:
diff --git a/config/sync/views.view.moderator_solutions_by_type.yml b/config/sync/views.view.moderator_solutions_by_type.yml
index f9fbb9e9e84c2459743820e65f710359acf0730f..700eb483d069b082cbe29f6b2cd9a57dcc90f769 100644
--- a/config/sync/views.view.moderator_solutions_by_type.yml
+++ b/config/sync/views.view.moderator_solutions_by_type.yml
@@ -556,7 +556,7 @@ display:
         menu_name: admin
         parent: joinup.admin_reporting
         context: '0'
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
diff --git a/config/sync/views.view.topic_parent_list.yml b/config/sync/views.view.topic_parent_list.yml
index f569ab400ad1f6a5d48c2e5b878addf0721bddc1..ff7dd35079c8bf2489d27855ea5c92ce0c16b909 100644
--- a/config/sync/views.view.topic_parent_list.yml
+++ b/config/sync/views.view.topic_parent_list.yml
@@ -240,7 +240,7 @@ display:
     display_options:
       display_extenders: {  }
       path: topic-list-only-parents
-      always_use_admin_theme: false
+      use_admin_theme: false
     cache_metadata:
       max-age: -1
       contexts:
diff --git a/docker-compose.yml b/docker-compose.yml
index 8826665855d390b8a1837036c6f63ba7a84019c5..138f7fb7eccf5069539ed36d552b7bf51de8fffa 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -16,6 +16,7 @@
 version: '3.8'
 services:
   web:
+    image: fpfis/httpd-php-dev:8.1
     build:
       context: './resources/docker/web'
     working_dir: /var/www/html
diff --git a/grumphp.yml.dist b/grumphp.yml.dist
deleted file mode 100644
index 6835192add8519f640e3620c68e4b904e7b58027..0000000000000000000000000000000000000000
--- a/grumphp.yml.dist
+++ /dev/null
@@ -1,6 +0,0 @@
-imports:
-  - { resource: vendor/ec-europa/qa-automation/dist/qa-conventions.yml }
-
-grumphp:
-    ascii: ~
-    tasks: {  }
diff --git a/resources/patch/2901412-25.diff b/resources/patch/2901412-25.diff
new file mode 100644
index 0000000000000000000000000000000000000000..ca182e025828dd38020be861ea4a08f587bb4aae
--- /dev/null
+++ b/resources/patch/2901412-25.diff
@@ -0,0 +1,449 @@
+diff --git a/core/modules/comment/tests/src/Unit/Plugin/views/field/CommentBulkFormTest.php b/core/modules/comment/tests/src/Unit/Plugin/views/field/CommentBulkFormTest.php
+index d342bda45e8d7c5931a172868280153ca21d5e08..6806b84fda884212a6b0f873b466ee959c5b402f 100644
+--- a/core/modules/comment/tests/src/Unit/Plugin/views/field/CommentBulkFormTest.php
++++ b/core/modules/comment/tests/src/Unit/Plugin/views/field/CommentBulkFormTest.php
+@@ -6,6 +6,7 @@
+ use Drupal\comment\Plugin\views\field\CommentBulkForm;
+ use Drupal\Core\Entity\EntityRepositoryInterface;
+ use Drupal\Core\Entity\EntityTypeManagerInterface;
++use Drupal\Core\Routing\ResettableStackedRouteMatchInterface;
+ use Drupal\Tests\UnitTestCase;
+ 
+ /**
+@@ -60,6 +61,8 @@ public function testConstructor() {
+ 
+     $messenger = $this->createMock('Drupal\Core\Messenger\MessengerInterface');
+ 
++    $route_match = $this->createMock(ResettableStackedRouteMatchInterface::class);
++
+     $views_data = $this->getMockBuilder('Drupal\views\ViewsData')
+       ->disableOriginalConstructor()
+       ->getMock();
+@@ -90,7 +93,7 @@ public function testConstructor() {
+     $definition['title'] = '';
+     $options = [];
+ 
+-    $comment_bulk_form = new CommentBulkForm([], 'comment_bulk_form', $definition, $entity_type_manager, $language_manager, $messenger, $entity_repository);
++    $comment_bulk_form = new CommentBulkForm([], 'comment_bulk_form', $definition, $entity_type_manager, $language_manager, $messenger, $entity_repository, $route_match);
+     $comment_bulk_form->init($executable, $display, $options);
+ 
+     $reflected_actions = (new \ReflectionObject($comment_bulk_form))->getProperty('actions');
+diff --git a/core/modules/node/tests/src/Unit/Plugin/views/field/NodeBulkFormTest.php b/core/modules/node/tests/src/Unit/Plugin/views/field/NodeBulkFormTest.php
+index cd421f167e26011de588032a19c01b5bb7d42fbc..07574ff6b1be68619589752826470f7e7e71e3e1 100644
+--- a/core/modules/node/tests/src/Unit/Plugin/views/field/NodeBulkFormTest.php
++++ b/core/modules/node/tests/src/Unit/Plugin/views/field/NodeBulkFormTest.php
+@@ -5,6 +5,7 @@
+ use Drupal\Core\DependencyInjection\ContainerBuilder;
+ use Drupal\Core\Entity\EntityRepositoryInterface;
+ use Drupal\Core\Entity\EntityTypeManagerInterface;
++use Drupal\Core\Routing\ResettableStackedRouteMatchInterface;
+ use Drupal\node\Plugin\views\field\NodeBulkForm;
+ use Drupal\Tests\UnitTestCase;
+ 
+@@ -60,6 +61,8 @@ public function testConstructor() {
+ 
+     $messenger = $this->createMock('Drupal\Core\Messenger\MessengerInterface');
+ 
++    $route_match = $this->createMock(ResettableStackedRouteMatchInterface::class);
++
+     $views_data = $this->getMockBuilder('Drupal\views\ViewsData')
+       ->disableOriginalConstructor()
+       ->getMock();
+@@ -91,6 +94,7 @@ public function testConstructor() {
+     $options = [];
+ 
+     $node_bulk_form = new NodeBulkForm([], 'node_bulk_form', $definition, $entity_type_manager, $language_manager, $messenger, $entity_repository);
++    $node_bulk_form = new NodeBulkForm([], 'node_bulk_form', $definition, $entity_type_manager, $language_manager, $messenger, $entity_repository, $route_match);
+     $node_bulk_form->init($executable, $display, $options);
+ 
+     $reflected_actions = (new \ReflectionObject($node_bulk_form))->getProperty('actions');
+diff --git a/core/modules/user/tests/src/Unit/Plugin/views/field/UserBulkFormTest.php b/core/modules/user/tests/src/Unit/Plugin/views/field/UserBulkFormTest.php
+index cdd6ec685b684e143f00d50df486b8c9310445c4..5040102c0dc806f76c8bdd94ede6af462a88106e 100644
+--- a/core/modules/user/tests/src/Unit/Plugin/views/field/UserBulkFormTest.php
++++ b/core/modules/user/tests/src/Unit/Plugin/views/field/UserBulkFormTest.php
+@@ -5,6 +5,7 @@
+ use Drupal\Core\DependencyInjection\ContainerBuilder;
+ use Drupal\Core\Entity\EntityRepositoryInterface;
+ use Drupal\Core\Entity\EntityTypeManagerInterface;
++use Drupal\Core\Routing\ResettableStackedRouteMatchInterface;
+ use Drupal\Tests\UnitTestCase;
+ use Drupal\user\Plugin\views\field\UserBulkForm;
+ 
+@@ -60,6 +61,8 @@ public function testConstructor() {
+ 
+     $messenger = $this->createMock('Drupal\Core\Messenger\MessengerInterface');
+ 
++    $route_match = $this->createMock(ResettableStackedRouteMatchInterface::class);
++
+     $views_data = $this->getMockBuilder('Drupal\views\ViewsData')
+       ->disableOriginalConstructor()
+       ->getMock();
+@@ -90,7 +93,7 @@ public function testConstructor() {
+     $definition['title'] = '';
+     $options = [];
+ 
+-    $user_bulk_form = new UserBulkForm([], 'user_bulk_form', $definition, $entity_type_manager, $language_manager, $messenger, $entity_repository);
++    $user_bulk_form = new UserBulkForm([], 'user_bulk_form', $definition, $entity_type_manager, $language_manager, $messenger, $entity_repository, $route_match);
+     $user_bulk_form->init($executable, $display, $options);
+ 
+     $reflected_actions = (new \ReflectionObject($user_bulk_form))->getProperty('actions');
+diff --git a/core/modules/views/src/Plugin/views/field/BulkForm.php b/core/modules/views/src/Plugin/views/field/BulkForm.php
+index 04c58e46acf04c36fbb4734f1d20541ba1145ee3..19fefce7b9afaf96def1ff9b9a86b34b9a46efeb 100644
+--- a/core/modules/views/src/Plugin/views/field/BulkForm.php
++++ b/core/modules/views/src/Plugin/views/field/BulkForm.php
+@@ -11,6 +11,7 @@
+ use Drupal\Core\Language\LanguageManagerInterface;
+ use Drupal\Core\Messenger\MessengerInterface;
+ use Drupal\Core\Routing\RedirectDestinationTrait;
++use Drupal\Core\Routing\ResettableStackedRouteMatchInterface;
+ use Drupal\Core\TypedData\TranslatableInterface;
+ use Drupal\views\Entity\Render\EntityTranslationRenderTrait;
+ use Drupal\views\Plugin\views\display\DisplayPluginBase;
+@@ -72,6 +73,13 @@ class BulkForm extends FieldPluginBase implements CacheableDependencyInterface {
+    */
+   protected $messenger;
+ 
++  /**
++   * The current route match service.
++   *
++   * @var \Drupal\Core\Routing\ResettableStackedRouteMatchInterface
++   */
++  protected $routeMatch;
++
+   /**
+    * Constructs a new BulkForm object.
+    *
+@@ -89,10 +97,13 @@ class BulkForm extends FieldPluginBase implements CacheableDependencyInterface {
+    *   The messenger.
+    * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
+    *   The entity repository.
++   * @param \Drupal\Core\Routing\ResettableStackedRouteMatchInterface $route_match
++   *   The current route match service.
+    *
+    * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
++   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
+    */
+-  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager, MessengerInterface $messenger, EntityRepositoryInterface $entity_repository) {
++  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager, MessengerInterface $messenger, EntityRepositoryInterface $entity_repository, ResettableStackedRouteMatchInterface $route_match = NULL) {
+     parent::__construct($configuration, $plugin_id, $plugin_definition);
+ 
+     $this->entityTypeManager = $entity_type_manager;
+@@ -100,6 +111,11 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
+     $this->languageManager = $language_manager;
+     $this->messenger = $messenger;
+     $this->entityRepository = $entity_repository;
++    if (!$route_match) {
++      @trigger_error('Calling BulkForm::__construct() without the $route_match argument is deprecated in drupal:8.9.0 and the $route_match argument will be required in drupal:10.0.0. See https://www.drupal.org/node/3115868', E_USER_DEPRECATED);
++      $route_match = \Drupal::routeMatch();
++    }
++    $this->routeMatch = $route_match;
+   }
+ 
+   /**
+@@ -113,7 +129,8 @@ public static function create(ContainerInterface $container, array $configuratio
+       $container->get('entity_type.manager'),
+       $container->get('language_manager'),
+       $container->get('messenger'),
+-      $container->get('entity.repository')
++      $container->get('entity.repository'),
++      $container->get('current_route_match')
+     );
+   }
+ 
+@@ -419,7 +436,8 @@ public function viewsFormSubmit(&$form, FormStateInterface $form_state) {
+         $options = [
+           'query' => $this->getDestinationArray(),
+         ];
+-        $form_state->setRedirect($operation_definition['confirm_form_route_name'], [], $options);
++        $route_parameters = $this->routeMatch->getRawParameters()->all();
++        $form_state->setRedirect($operation_definition['confirm_form_route_name'], $route_parameters, $options);
+       }
+       else {
+         // Don't display the message unless there are some elements affected and
+diff --git a/core/modules/views/tests/modules/action_bulk_test/action_bulk_test.routing.yml b/core/modules/views/tests/modules/action_bulk_test/action_bulk_test.routing.yml
+new file mode 100644
+index 0000000000000000000000000000000000000000..43cab18ec54c8c17c261d18bd7eba058c5384a27
+--- /dev/null
++++ b/core/modules/views/tests/modules/action_bulk_test/action_bulk_test.routing.yml
+@@ -0,0 +1,10 @@
++action_bulk_test.action.confirm:
++  path: '/node/{node}/confirm'
++  defaults:
++    _form: Drupal\action_bulk_test\Form\TestActionConfirmForm
++  requirements:
++    _access: 'TRUE'
++  options:
++    parameters:
++      node:
++        type: entity:node
+diff --git a/core/modules/views/tests/modules/action_bulk_test/config/install/system.action.test_action.yml b/core/modules/views/tests/modules/action_bulk_test/config/install/system.action.test_action.yml
+new file mode 100644
+index 0000000000000000000000000000000000000000..555531cc8e2c818329dda0732cfe39a284679e63
+--- /dev/null
++++ b/core/modules/views/tests/modules/action_bulk_test/config/install/system.action.test_action.yml
+@@ -0,0 +1,10 @@
++langcode: en
++status: true
++dependencies:
++  module:
++    - action_bulk_test
++id: test_action
++label: 'Test action'
++type: node
++plugin: test_action
++configuration: {  }
+diff --git a/core/modules/views/tests/modules/action_bulk_test/config/install/views.view.test_bulk_form.yml b/core/modules/views/tests/modules/action_bulk_test/config/install/views.view.test_bulk_form.yml
+index 292863128427709da93f60103b8467bf0171dd21..6446dc86c8c1b1f477179c9a4b7ca60980e1fbd4 100644
+--- a/core/modules/views/tests/modules/action_bulk_test/config/install/views.view.test_bulk_form.yml
++++ b/core/modules/views/tests/modules/action_bulk_test/config/install/views.view.test_bulk_form.yml
+@@ -120,6 +120,8 @@ display:
+           group: 1
+           expose:
+             operator: ''
++            operator_limit_selection: false
++            operator_list: {  }
+       style:
+         type: table
+         options:
+@@ -151,6 +153,17 @@ display:
+         type: fields
+       query:
+         type: views_query
++      display_extenders: {  }
++      arguments: {  }
++    cache_metadata:
++      max-age: 0
++      contexts:
++        - 'languages:language_content'
++        - 'languages:language_interface'
++        - url.query_args
++        - 'user.node_grants:view'
++        - user.permissions
++      tags: {  }
+   page_1:
+     id: page_1
+     display_title: Page
+@@ -158,6 +171,16 @@ display:
+     position: null
+     display_options:
+       path: test_bulk_form
++      display_extenders: {  }
++    cache_metadata:
++      max-age: 0
++      contexts:
++        - 'languages:language_content'
++        - 'languages:language_interface'
++        - url.query_args
++        - 'user.node_grants:view'
++        - user.permissions
++      tags: {  }
+   page_2:
+     id: page_2
+     display_title: Page
+@@ -205,3 +228,66 @@ display:
+         row: false
+       display_extenders: { }
+       path: display-without-fields
++  page_4:
++    id: page_4
++    display_title: 'Page 4'
++    display_plugin: page
++    position: 4
++    display_options:
++      arguments:
++        nid:
++          id: nid
++          table: node_field_data
++          field: nid
++          relationship: none
++          group_type: group
++          admin_label: ''
++          default_action: ignore
++          exception:
++            value: all
++            title_enable: false
++            title: All
++          title_enable: false
++          title: ''
++          default_argument_type: fixed
++          default_argument_options:
++            argument: ''
++          default_argument_skip_url: false
++          summary_options:
++            base_path: ''
++            count: true
++            items_per_page: 25
++            override: false
++          summary:
++            sort_order: asc
++            number_of_records: 0
++            format: default_summary
++          specify_validation: true
++          validate:
++            type: 'entity:node'
++            fail: 'not found'
++          validate_options:
++            operation: view
++            multiple: 0
++            bundles: {  }
++            access: false
++          break_phrase: false
++          not: false
++          entity_type: node
++          entity_field: nid
++          plugin_id: node_nid
++      defaults:
++        arguments: false
++      display_description: ''
++      display_extenders: {  }
++      path: node/%node/test_bulk_form
++    cache_metadata:
++      max-age: 0
++      contexts:
++        - 'languages:language_content'
++        - 'languages:language_interface'
++        - url
++        - url.query_args
++        - 'user.node_grants:view'
++        - user.permissions
++      tags: {  }
+diff --git a/core/modules/views/tests/modules/action_bulk_test/config/schema/action_bulk_test.schema.yml b/core/modules/views/tests/modules/action_bulk_test/config/schema/action_bulk_test.schema.yml
+new file mode 100644
+index 0000000000000000000000000000000000000000..8627f6abef07856f5e95d54b5df88f7b63ce5334
+--- /dev/null
++++ b/core/modules/views/tests/modules/action_bulk_test/config/schema/action_bulk_test.schema.yml
+@@ -0,0 +1,2 @@
++action.configuration.test_action:
++  type: mapping
+diff --git a/core/modules/views/tests/modules/action_bulk_test/src/Form/TestActionConfirmForm.php b/core/modules/views/tests/modules/action_bulk_test/src/Form/TestActionConfirmForm.php
+new file mode 100644
+index 0000000000000000000000000000000000000000..18f3c8667fb75e9cf6eb8fdba2a9d9d3ed23b296
+--- /dev/null
++++ b/core/modules/views/tests/modules/action_bulk_test/src/Form/TestActionConfirmForm.php
+@@ -0,0 +1,40 @@
++<?php
++
++namespace Drupal\action_bulk_test\Form;
++
++use Drupal\Core\Form\ConfirmFormBase;
++use Drupal\Core\Form\FormStateInterface;
++use Drupal\Core\Url;
++
++/**
++ * Confirmation form for 'test_action' action.
++ */
++class TestActionConfirmForm extends ConfirmFormBase {
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getFormId() {
++    return 'test_action_confirm_form';
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getCancelUrl() {
++    return Url::fromRoute('<front>');
++  }
++
++  /**
++   * @inheritdoc
++   */
++  public function getQuestion() {
++    return $this->t('Do you agree?');
++  }
++
++  /**
++   * @inheritdoc
++   */
++  public function submitForm(array &$form, FormStateInterface $form_state) {}
++
++}
+diff --git a/core/modules/views/tests/modules/action_bulk_test/src/Plugin/Action/TestAction.php b/core/modules/views/tests/modules/action_bulk_test/src/Plugin/Action/TestAction.php
+new file mode 100644
+index 0000000000000000000000000000000000000000..9056ecdbae725d75241bb5e20afc83c4070d7029
+--- /dev/null
++++ b/core/modules/views/tests/modules/action_bulk_test/src/Plugin/Action/TestAction.php
+@@ -0,0 +1,31 @@
++<?php
++
++namespace Drupal\action_bulk_test\Plugin\Action;
++
++use Drupal\Core\Access\AccessResult;
++use Drupal\Core\Action\ActionBase;
++use Drupal\Core\Session\AccountInterface;
++
++/**
++ * @Action(
++ *   id = "test_action",
++ *   label = @Translation("Test action"),
++ *   type = "node",
++ *   confirm_form_route_name = "action_bulk_test.action.confirm",
++ * )
++ */
++class TestAction extends ActionBase {
++
++  /**
++   * @inheritdoc
++   */
++  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
++    return $return_as_object ? AccessResult::allowed() : TRUE;
++  }
++
++  /**
++   * @inheritdoc
++   */
++  public function execute() {}
++
++}
+diff --git a/core/modules/views/tests/src/Functional/BulkFormTest.php b/core/modules/views/tests/src/Functional/BulkFormTest.php
+index 4e515c6aa6022cf2ce26845dbb0cd22a990e8816..29aac7ca61fdfed4a65e02b4dca700d92e50db90 100644
+--- a/core/modules/views/tests/src/Functional/BulkFormTest.php
++++ b/core/modules/views/tests/src/Functional/BulkFormTest.php
+@@ -4,6 +4,7 @@
+ 
+ use Drupal\Component\Render\FormattableMarkup;
+ use Drupal\Tests\BrowserTestBase;
++use Drupal\Tests\node\Traits\NodeCreationTrait;
+ use Drupal\views\Views;
+ 
+ /**
+@@ -14,6 +15,8 @@
+  */
+ class BulkFormTest extends BrowserTestBase {
+ 
++  use NodeCreationTrait;
++
+   /**
+    * Modules to install.
+    *
+@@ -209,4 +212,27 @@ public function testBulkForm() {
+     $this->assertSession()->pageTextContains('No content selected.');
+   }
+ 
++  /**
++   * Tests that route parameters are passed to the confirmation form route.
++   */
++  public function testConfirmRouteWithParameters() {
++    $session = $this->getSession();
++    $page = $session->getPage();
++    $assert = $this->assertSession();
++
++    $node = $this->createNode();
++    // Access the view page.
++    $this->drupalGet('/node/' . $node->id() . '/test_bulk_form');
++
++    // Select a node and perform the 'Test action'.
++    $page->checkField('node_bulk_form[0]');
++    $page->selectFieldOption('Action', 'Test action');
++    $page->pressButton('Apply to selected items');
++
++    // Check that we've been landed on the confirmation form.
++    $assert->pageTextContains('Do you agree?');
++    // Check that route parameters were passed to the confirmation from route.
++    $assert->addressEquals('/node/' . $node->id() . '/confirm');
++  }
++
+ }
diff --git a/resources/patch/drupal/core/2381293.diff b/resources/patch/drupal/core/2381293.diff
new file mode 100644
index 0000000000000000000000000000000000000000..c37606728a3a8f3b16c16537f8b9c2d5d20852df
--- /dev/null
+++ b/resources/patch/drupal/core/2381293.diff
@@ -0,0 +1,844 @@
+diff --git a/core/modules/comment/config/optional/views.view.comment.yml b/core/modules/comment/config/optional/views.view.comment.yml
+index a7003253e3..2bb5054af0 100644
+--- a/core/modules/comment/config/optional/views.view.comment.yml
++++ b/core/modules/comment/config/optional/views.view.comment.yml
+@@ -75,6 +75,9 @@ display:
+           selected_actions:
+             - comment_delete_action
+             - comment_unpublish_action
++          actions_order:
++            - comment_unpublish_action
++            - comment_delete_action
+         subject:
+           id: subject
+           table: comment_field_data
+@@ -953,6 +956,9 @@ display:
+           selected_actions:
+             - comment_delete_action
+             - comment_publish_action
++          actions_order:
++            - comment_publish_action
++            - comment_delete_action
+         subject:
+           id: subject
+           table: comment_field_data
+diff --git a/core/modules/comment/tests/src/Kernel/Views/CommentAdminViewTest.php b/core/modules/comment/tests/src/Kernel/Views/CommentAdminViewTest.php
+index d52e16b584..5ef2b0776d 100644
+--- a/core/modules/comment/tests/src/Kernel/Views/CommentAdminViewTest.php
++++ b/core/modules/comment/tests/src/Kernel/Views/CommentAdminViewTest.php
+@@ -35,11 +35,13 @@ class CommentAdminViewTest extends ViewsKernelTestBase {
+    * {@inheritdoc}
+    */
+   protected static $modules = [
+-    'user',
+     'comment',
+     'entity_test',
++    'field',
+     'language',
+     'locale',
++    'text',
++    'user',
+   ];
+ 
+   /**
+@@ -52,7 +54,7 @@ protected function setUp($import_test_views = TRUE): void {
+     $this->installEntitySchema('comment');
+     $this->installEntitySchema('entity_test');
+     // Create the anonymous role.
+-    $this->installConfig(['user']);
++    $this->installConfig(['comment', 'user']);
+ 
+     // Create user 1 so that the user created later in the test has a different
+     // user ID.
+diff --git a/core/modules/media/config/optional/views.view.media.yml b/core/modules/media/config/optional/views.view.media.yml
+index cbcb293bb5..a7a0a16872 100644
+--- a/core/modules/media/config/optional/views.view.media.yml
++++ b/core/modules/media/config/optional/views.view.media.yml
+@@ -76,6 +76,11 @@ display:
+           action_title: Action
+           include_exclude: exclude
+           selected_actions: {  }
++          actions_order:
++            - media_publish_action
++            - media_unpublish_action
++            - media_save_action
++            - media_delete_action
+         thumbnail__target_id:
+           id: thumbnail__target_id
+           table: media_field_data
+diff --git a/core/modules/media/tests/modules/media_test_views/config/install/views.view.test_media_bulk_form.yml b/core/modules/media/tests/modules/media_test_views/config/install/views.view.test_media_bulk_form.yml
+index 7fb69207ac..2a0c2d8366 100644
+--- a/core/modules/media/tests/modules/media_test_views/config/install/views.view.test_media_bulk_form.yml
++++ b/core/modules/media/tests/modules/media_test_views/config/install/views.view.test_media_bulk_form.yml
+@@ -41,6 +41,11 @@ display:
+           action_title: 'With selection'
+           include_exclude: exclude
+           selected_actions: {  }
++          actions_order:
++            - media_publish_action
++            - media_unpublish_action
++            - media_save_action
++            - media_delete_action
+         name:
+           id: name
+           table: media_field_data
+diff --git a/core/modules/media/tests/src/Functional/MediaBulkFormTest.php b/core/modules/media/tests/src/Functional/MediaBulkFormTest.php
+index d65f34e2b0..8e0e192a13 100644
+--- a/core/modules/media/tests/src/Functional/MediaBulkFormTest.php
++++ b/core/modules/media/tests/src/Functional/MediaBulkFormTest.php
+@@ -2,6 +2,7 @@
+ 
+ namespace Drupal\Tests\media\Functional;
+ 
++use Behat\Mink\Element\NodeElement;
+ use Drupal\media\Entity\Media;
+ use Drupal\views\Views;
+ 
+@@ -72,16 +73,18 @@ public function testBulkForm() {
+ 
+     // Check the operations are accessible to the logged in user.
+     $this->drupalGet('test-media-bulk-form');
+-    // Current available actions: Delete, Save, Publish, Unpublish.
+-    $available_actions = [
+-      'media_delete_action',
++
++    // Tests that actions are sorted according to the view configured order.
++    $actual_actions = $this->xpath('//select[@id="edit-action"]//option');
++    $expected_actions = [
+       'media_publish_action',
+-      'media_save_action',
+       'media_unpublish_action',
++      'media_save_action',
++      'media_delete_action',
+     ];
+-    foreach ($available_actions as $action_name) {
+-      $assert_session->optionExists('action', $action_name);
+-    }
++    $this->assertSame($expected_actions, array_values(array_filter(array_map(function (NodeElement $action): string {
++      return $action->getValue();
++    }, $actual_actions))));
+ 
+     // Test unpublishing in bulk.
+     $page->checkField('media_bulk_form[0]');
+diff --git a/core/modules/media_library/config/install/views.view.media_library.yml b/core/modules/media_library/config/install/views.view.media_library.yml
+index 6f4aae256d..75ca5fda99 100644
+--- a/core/modules/media_library/config/install/views.view.media_library.yml
++++ b/core/modules/media_library/config/install/views.view.media_library.yml
+@@ -81,6 +81,11 @@ display:
+           action_title: Action
+           include_exclude: exclude
+           selected_actions: {  }
++          actions_order:
++            - media_publish_action
++            - media_unpublish_action
++            - media_save_action
++            - media_delete_action
+         rendered_entity:
+           id: rendered_entity
+           table: media
+@@ -542,6 +547,11 @@ display:
+           action_title: Action
+           include_exclude: exclude
+           selected_actions: {  }
++          actions_order:
++            - media_publish_action
++            - media_save_action
++            - media_unpublish_action
++            - media_delete_action
+         name:
+           id: name
+           table: media_field_data
+diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/MediaOverviewTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/MediaOverviewTest.php
+index e3eaab22e1..e38582732f 100644
+--- a/core/modules/media_library/tests/src/FunctionalJavascript/MediaOverviewTest.php
++++ b/core/modules/media_library/tests/src/FunctionalJavascript/MediaOverviewTest.php
+@@ -2,6 +2,8 @@
+ 
+ namespace Drupal\Tests\media_library\FunctionalJavascript;
+ 
++use Behat\Mink\Element\NodeElement;
++
+ /**
+  * Tests the grid-style media overview page.
+  *
+@@ -59,6 +61,18 @@ public function testAdministrationPage() {
+     // Visit the administration page.
+     $this->drupalGet('admin/content/media');
+ 
++    // Tests that actions are sorted according to the view configured order.
++    $actual_actions = $this->xpath('//select[@id="edit-action"]//option');
++    $expected_actions = [
++      'media_publish_action',
++      'media_unpublish_action',
++      'media_save_action',
++      'media_delete_action',
++    ];
++    $this->assertSame($expected_actions, array_values(array_filter(array_map(function (NodeElement $action): string {
++      return $action->getValue();
++    }, $actual_actions))));
++
+     // There should be links to both the grid and table displays.
+     $assert_session->linkExists('Grid');
+     $assert_session->linkExists('Table');
+@@ -101,6 +115,7 @@ public function testAdministrationPage() {
+ 
+     // This tests that anchor tags clicked inside the preview are suppressed.
+     $this->getSession()->executeScript('jQuery(".js-click-to-select-trigger a")[4].click()');
++    $this->getSession()->getPage()->selectFieldOption('Action', 'Delete media');
+     $this->submitForm([], 'Apply to selected items');
+     $assert_session->pageTextContains('Dog');
+     $assert_session->pageTextNotContains('Cat');
+diff --git a/core/modules/node/config/optional/views.view.content.yml b/core/modules/node/config/optional/views.view.content.yml
+index a784f217b3..087848e7c2 100644
+--- a/core/modules/node/config/optional/views.view.content.yml
++++ b/core/modules/node/config/optional/views.view.content.yml
+@@ -36,6 +36,18 @@ display:
+           hide_empty: false
+           empty_zero: false
+           hide_alter_empty: true
++          action_title: Action
++          include_exclude: exclude
++          selected_actions: {  }
++          actions_order:
++            - node_publish_action
++            - node_unpublish_action
++            - node_promote_action
++            - node_unpromote_action
++            - node_make_sticky_action
++            - node_make_unsticky_action
++            - node_save_action
++            - node_delete_action
+         title:
+           id: title
+           table: node_field_data
+diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
+index 78536b8314..f7dc0dc037 100644
+--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
++++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_bulk_form.yml
+@@ -28,6 +28,18 @@ display:
+           field: node_bulk_form
+           plugin_id: node_bulk_form
+           entity_type: node
++          action_title: Action
++          include_exclude: exclude
++          selected_actions: {  }
++          actions_order:
++            - node_publish_action
++            - node_unpublish_action
++            - node_promote_action
++            - node_unpromote_action
++            - node_make_sticky_action
++            - node_make_unsticky_action
++            - node_save_action
++            - node_delete_action
+         title:
+           id: title
+           table: node_field_data
+diff --git a/core/modules/node/tests/src/Functional/Views/BulkFormTest.php b/core/modules/node/tests/src/Functional/Views/BulkFormTest.php
+index cdbd7b63c7..9568bb0797 100644
+--- a/core/modules/node/tests/src/Functional/Views/BulkFormTest.php
++++ b/core/modules/node/tests/src/Functional/Views/BulkFormTest.php
+@@ -2,6 +2,7 @@
+ 
+ namespace Drupal\Tests\node\Functional\Views;
+ 
++use Behat\Mink\Element\NodeElement;
+ use Drupal\language\Entity\ConfigurableLanguage;
+ use Drupal\views\Views;
+ 
+@@ -94,13 +95,29 @@ protected function setUp($import_test_views = TRUE, $modules = ['node_test_views
+     ]));
+     $this->drupalGet('test-node-bulk-form');
+     $elements = $this->assertSession()->selectExists('edit-action')->findAll('css', 'option');
+-    $this->assertCount(8, $elements, 'All node operations are found.');
++    $this->assertCount(9, $elements, 'All node operations are found.');
+   }
+ 
+   /**
+    * Tests the node bulk form.
+    */
+   public function testBulkForm() {
++    // Tests that actions are sorted according to the view configured order.
++    $actual_actions = $this->xpath('//select[@id="edit-action"]//option');
++    $expected_actions = [
++      'node_publish_action',
++      'node_unpublish_action',
++      'node_promote_action',
++      'node_unpromote_action',
++      'node_make_sticky_action',
++      'node_make_unsticky_action',
++      'node_save_action',
++      'node_delete_action',
++    ];
++    $this->assertSame($expected_actions, array_values(array_filter(array_map(function (NodeElement $action): string {
++      return $action->getValue();
++    }, $actual_actions))));
++
+     // Unpublish a node using the bulk form.
+     $node = reset($this->nodes);
+     $this->assertTrue($node->isPublished(), 'Node is initially published');
+diff --git a/core/modules/user/config/optional/views.view.user_admin_people.yml b/core/modules/user/config/optional/views.view.user_admin_people.yml
+index d49503f814..5f779987c9 100644
+--- a/core/modules/user/config/optional/views.view.user_admin_people.yml
++++ b/core/modules/user/config/optional/views.view.user_admin_people.yml
+@@ -69,6 +69,10 @@ display:
+           hide_empty: false
+           empty_zero: false
+           hide_alter_empty: true
++          action_title: Action
++          include_exclude: exclude
++          selected_actions: {  }
++          actions_order: []
+         name:
+           id: name
+           table: users_field_data
+diff --git a/core/modules/user/tests/src/Functional/Views/BulkFormTest.php b/core/modules/user/tests/src/Functional/Views/BulkFormTest.php
+index 74650146e2..bb8db716c6 100644
+--- a/core/modules/user/tests/src/Functional/Views/BulkFormTest.php
++++ b/core/modules/user/tests/src/Functional/Views/BulkFormTest.php
+@@ -122,7 +122,7 @@ public function testBulkForm() {
+     $action_id = 'user_add_role_action.' . $role;
+     $edit = [
+       'options[include_exclude]' => 'exclude',
+-      "options[selected_actions][$action_id]" => $action_id,
++      "options[selected_actions][$action_id][selected]" => TRUE,
+     ];
+     $this->drupalGet('admin/structure/views/nojs/handler/test_user_bulk_form/default/field/user_bulk_form');
+     $this->submitForm($edit, 'Apply');
+diff --git a/core/modules/views/config/schema/views.data_types.schema.yml b/core/modules/views/config/schema/views.data_types.schema.yml
+index 4c88562ce7..363f214b8d 100644
+--- a/core/modules/views/config/schema/views.data_types.schema.yml
++++ b/core/modules/views/config/schema/views.data_types.schema.yml
+@@ -849,3 +849,9 @@ views_field_bulk_form:
+       sequence:
+         type: string
+         label: 'Action'
++    actions_order:
++      type: sequence
++      label: 'Actions order'
++      sequence:
++        type: string
++        label: 'Action'
+diff --git a/core/modules/views/css/views.bulk_form.css b/core/modules/views/css/views.bulk_form.css
+new file mode 100644
+index 0000000000..1b193ef423
+--- /dev/null
++++ b/core/modules/views/css/views.bulk_form.css
+@@ -0,0 +1,12 @@
++tr.draggable td {
++  width: 100%;
++}
++tr.draggable td:first-child {
++  display: flex;
++  align-items: center;
++  width: 2.5rem;
++}
++/* Ensure a space between checkbox and the 'Changed' asterisk */
++tr.draggable td:first-child input[type=checkbox] {
++  margin-right: 3px;
++}
+diff --git a/core/modules/views/src/Plugin/views/field/BulkForm.php b/core/modules/views/src/Plugin/views/field/BulkForm.php
+index 04c58e46ac..a23e38b057 100644
+--- a/core/modules/views/src/Plugin/views/field/BulkForm.php
++++ b/core/modules/views/src/Plugin/views/field/BulkForm.php
+@@ -200,6 +200,9 @@ protected function defineOptions() {
+     $options['selected_actions'] = [
+       'default' => [],
+     ];
++    $options['actions_order'] = [
++      'default' => [],
++    ];
+     return $options;
+   }
+ 
+@@ -223,13 +226,52 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+       ],
+       '#default_value' => $this->options['include_exclude'],
+     ];
++
+     $form['selected_actions'] = [
+-      '#type' => 'checkboxes',
++      '#type' => 'table',
+       '#title' => $this->t('Selected actions'),
+-      '#options' => $this->getBulkOptions(FALSE),
+-      '#default_value' => $this->options['selected_actions'],
++      '#tabledrag' => [
++        [
++          'action' => 'order',
++          'relationship' => 'sibling',
++          'group' => 'action-order-weight',
++        ],
++      ],
++      '#tree' => FALSE,
++      '#input' => FALSE,
++      '#theme_wrappers' => ['form_element'],
++      '#attached' => ['library' => ['views/views.bulk_form']],
+     ];
+ 
++    $weight = 0;
++    foreach ($this->getBulkOptions(FALSE) as $action_id => $action_label) {
++      $form['selected_actions'][$action_id]['#attributes']['class'][] = 'draggable';
++      $form['selected_actions'][$action_id]['#weight'] = $weight++;
++
++      $arguments = ['@title' => $action_label];
++      $form['selected_actions'][$action_id]['selected'] = [
++        '#type' => 'checkbox',
++        '#title' => $this->t('Select @title', $arguments),
++        '#title_display' => 'attribute',
++        '#default_value' => in_array($action_id, $this->options['selected_actions'], TRUE),
++        '#parents' => ['options', 'selected_actions', $action_id, 'selected'],
++      ];
++
++      $form['selected_actions'][$action_id]['action'] = [
++        '#markup' => $action_label,
++      ];
++
++      $form['selected_actions'][$action_id]['weight'] = [
++        '#type' => 'weight',
++        '#title' => $this->t('Weight for @title', $arguments),
++        '#title_display' => 'invisible',
++        '#delta' => 50,
++        '#default_value' => $weight,
++        '#parents' => ['options', 'selected_actions', $action_id, 'weight'],
++        '#attributes' => ['class' => ['action-order-weight']],
++      ];
++
++    }
+     parent::buildOptionsForm($form, $form_state);
+   }
+ 
+@@ -239,8 +281,16 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+   public function validateOptionsForm(&$form, FormStateInterface $form_state) {
+     parent::validateOptionsForm($form, $form_state);
+ 
+-    $selected_actions = $form_state->getValue(['options', 'selected_actions']);
+-    $form_state->setValue(['options', 'selected_actions'], array_values(array_filter($selected_actions)));
++    $selected_actions = $actions_order = [];
++    foreach ($form_state->getValue(['options', 'selected_actions']) as $action_id => $action_data) {
++      if ($action_data['selected']) {
++        $selected_actions[] = $action_id;
++      }
++      $actions_order[$action_id] = (int) $action_data['weight'];
++    }
++    $form_state->setValue(['options', 'selected_actions'], $selected_actions);
++    asort($actions_order);
++    $form_state->setValue(['options', 'actions_order'], array_keys($actions_order));
+   }
+ 
+   /**
+@@ -303,6 +353,11 @@ public function viewsForm(&$form, FormStateInterface $form_state) {
+ 
+       // Replace the form submit button label.
+       $form['actions']['submit']['#value'] = $this->t('Apply to selected items');
++      $form['actions']['submit']['#states'] = [
++        'disabled' => [
++          'select[name="action"]' => ['value' => ''],
++        ],
++      ];
+ 
+       // Ensure a consistent container for filters/operations in the view header.
+       $form['header'] = [
+@@ -319,6 +374,7 @@ public function viewsForm(&$form, FormStateInterface $form_state) {
+         '#type' => 'select',
+         '#title' => $this->options['action_title'],
+         '#options' => $this->getBulkOptions(),
++        '#required' => TRUE,
+       ];
+ 
+       // Duplicate the form actions into the action container in the header.
+@@ -341,8 +397,18 @@ public function viewsForm(&$form, FormStateInterface $form_state) {
+    */
+   protected function getBulkOptions($filtered = TRUE) {
+     $options = [];
++
++    $actions = $this->actions;
++
++    // Only order if there is a user specified order.
++    if ($actions && $this->options['actions_order']) {
++      // Some actions might have been removed. Keep only existing actions.
++      $actions_order = array_intersect($this->options['actions_order'], array_keys($actions));
++      $actions = array_merge(array_flip($actions_order), $actions);
++    }
++
+     // Filter the action list.
+-    foreach ($this->actions as $id => $action) {
++    foreach ($actions as $id => $action) {
+       if ($filtered) {
+         $in_selected = in_array($id, $this->options['selected_actions']);
+         // If the field is configured to include only the selected actions,
+diff --git a/core/modules/views/src/ViewsConfigUpdater.php b/core/modules/views/src/ViewsConfigUpdater.php
+index 2ddb741c0a..b2830c1c50 100644
+--- a/core/modules/views/src/ViewsConfigUpdater.php
++++ b/core/modules/views/src/ViewsConfigUpdater.php
+@@ -10,6 +10,7 @@
+ use Drupal\Core\Entity\EntityTypeManagerInterface;
+ use Drupal\Core\Entity\FieldableEntityInterface;
+ use Drupal\Core\Entity\Sql\DefaultTableMapping;
++use Drupal\views\Plugin\views\field\BulkForm;
+ use Symfony\Component\DependencyInjection\ContainerInterface;
+ 
+ /**
+@@ -561,4 +562,45 @@ protected function processSortFieldIdentifierUpdateHandler(array &$handler, stri
+     return FALSE;
+   }
+ 
++  /**
++   * Updates the bulk form fields by adding the actions order configuration.
++   *
++   * @param \Drupal\views\ViewEntityInterface $view
++   *   The View to update.
++   *
++   * @return bool
++   *   Whether the view was updated.
++   */
++  public function needsBulkFormActionsOrderUpdate(ViewEntityInterface $view): bool {
++    return $this->processDisplayHandlers($view, FALSE, function (array &$handler, string $handler_type): bool {
++      return $this->processBulkFormActionsOrderUpdate($handler, $handler_type);
++    });
++  }
++
++  /**
++   * Processes the bulk form fields by adding the actions order configuration.
++   *
++   * @param array $handler
++   *   A display handler.
++   * @param string $handler_type
++   *   The handler type.
++   *
++   * @return bool
++   *   Whether the handler was updated.
++   */
++  protected function processBulkFormActionsOrderUpdate(array &$handler, string $handler_type): bool {
++    if ($handler_type === 'field' && !isset($handler['actions_order']) && isset($handler['plugin_id'])) {
++      /** @var \Drupal\views\Plugin\ViewsPluginManager $plugin_manager */
++      $plugin_manager = \Drupal::service('plugin.manager.views.field');
++      if ($plugin_manager->hasDefinition($handler['plugin_id'])) {
++        $definition = $plugin_manager->getDefinition($handler['plugin_id']);
++        if (is_subclass_of($definition['class'], BulkForm::class)) {
++          $handler['actions_order'] = [];
++          return TRUE;
++        }
++      }
++    }
++    return FALSE;
++  }
++
+ }
+diff --git a/core/modules/views/tests/modules/action_bulk_test/config/install/views.view.test_bulk_form.yml b/core/modules/views/tests/modules/action_bulk_test/config/install/views.view.test_bulk_form.yml
+index 2928631284..c654443977 100644
+--- a/core/modules/views/tests/modules/action_bulk_test/config/install/views.view.test_bulk_form.yml
++++ b/core/modules/views/tests/modules/action_bulk_test/config/install/views.view.test_bulk_form.yml
+@@ -89,6 +89,18 @@ display:
+           hide_empty: false
+           empty_zero: false
+           hide_alter_empty: true
++          action_title: Action
++          include_exclude: exclude
++          selected_actions: {  }
++          actions_order:
++            - node_publish_action
++            - node_unpublish_action
++            - node_promote_action
++            - node_unpromote_action
++            - node_make_sticky_action
++            - node_make_unsticky_action
++            - node_save_action
++            - node_delete_action
+       pager:
+         type: full
+         options:
+diff --git a/core/modules/views/tests/src/Functional/BulkFormTest.php b/core/modules/views/tests/src/Functional/BulkFormTest.php
+index 4e515c6aa6..c343561073 100644
+--- a/core/modules/views/tests/src/Functional/BulkFormTest.php
++++ b/core/modules/views/tests/src/Functional/BulkFormTest.php
+@@ -2,6 +2,7 @@
+ 
+ namespace Drupal\Tests\views\Functional;
+ 
++use Behat\Mink\Element\NodeElement;
+ use Drupal\Component\Render\FormattableMarkup;
+ use Drupal\Tests\BrowserTestBase;
+ use Drupal\views\Views;
+@@ -52,6 +53,52 @@ public function testBulkForm() {
+ 
+     $this->drupalGet('test_bulk_form');
+ 
++    // Tests that actions are sorted according to the view configured order.
++    $actual_actions = $this->xpath('//select[@id="edit-action"]//option');
++    $expected_actions = [
++      'node_publish_action',
++      'node_unpublish_action',
++      'node_promote_action',
++      'node_unpromote_action',
++      'node_make_sticky_action',
++      'node_make_unsticky_action',
++      'node_save_action',
++      'node_delete_action',
++    ];
++    $this->assertSame($expected_actions, array_values(array_filter(array_map(function (NodeElement $action): string {
++      return $action->getValue();
++    }, $actual_actions))));
++
++    // Test changing the order of the actions.
++    $view = Views::getView('test_bulk_form');
++    $display = &$view->storage->getDisplay('default');
++    $display['display_options']['fields']['node_bulk_form']['actions_order'] = [
++      'node_make_unsticky_action',
++      'node_publish_action',
++      'node_make_sticky_action',
++      'node_save_action',
++      'node_unpromote_action',
++      'node_delete_action',
++      'node_unpublish_action',
++      'node_promote_action',
++    ];
++    $view->save();
++    $this->getSession()->reload();
++    $actual_actions = $this->xpath('//select[@id="edit-action"]//option');
++    $expected_actions = [
++      'node_make_unsticky_action',
++      'node_publish_action',
++      'node_make_sticky_action',
++      'node_save_action',
++      'node_unpromote_action',
++      'node_delete_action',
++      'node_unpublish_action',
++      'node_promote_action',
++    ];
++    $this->assertSame($expected_actions, array_values(array_filter(array_map(function (NodeElement $action): string {
++      return $action->getValue();
++    }, $actual_actions))));
++
+     // Test that the views edit header appears first.
+     $this->assertSession()->elementExists('xpath', '//form/div[1][@id = "edit-header"]');
+ 
+@@ -116,7 +163,7 @@ public function testBulkForm() {
+ 
+     $this->drupalGet('test_bulk_form');
+     $options = $this->assertSession()->selectExists('edit-action')->findAll('css', 'option');
+-    $this->assertCount(2, $options);
++    $this->assertCount(3, $options);
+     $this->assertSession()->optionExists('edit-action', 'node_make_sticky_action');
+     $this->assertSession()->optionExists('edit-action', 'node_make_unsticky_action');
+ 
+diff --git a/core/modules/views/tests/src/Functional/Plugin/ViewsBulkTest.php b/core/modules/views/tests/src/Functional/Plugin/ViewsBulkTest.php
+index f9b92e1d23..171ff9469a 100644
+--- a/core/modules/views/tests/src/Functional/Plugin/ViewsBulkTest.php
++++ b/core/modules/views/tests/src/Functional/Plugin/ViewsBulkTest.php
+@@ -63,7 +63,8 @@ public function testBulkSelection() {
+ 
+     // Now click 'Apply to selected items' and assert the first node is selected
+     // on the confirm form.
+-    $this->submitForm(['node_bulk_form[0]' => TRUE], 'Apply to selected items');
++    $edit = ['node_bulk_form[0]' => TRUE, 'action' => 'node_delete_action'];
++    $this->submitForm($edit, 'Apply to selected items');
+     $this->assertSession()->pageTextContains($node_1->getTitle());
+     $this->assertSession()->pageTextNotContains($node_2->getTitle());
+ 
+@@ -81,7 +82,8 @@ public function testBulkSelection() {
+ 
+     // Now click 'Apply to selected items' and assert the second node is
+     // selected on the confirm form.
+-    $this->submitForm(['node_bulk_form[1]' => TRUE], 'Apply to selected items');
++    $edit = ['node_bulk_form[1]' => TRUE, 'action' => 'node_delete_action'];
++    $this->submitForm($edit, 'Apply to selected items');
+     $this->assertSession()->pageTextContains($node_1->getTitle());
+     $this->assertSession()->pageTextNotContains($node_3->getTitle());
+   }
+diff --git a/core/modules/views/tests/src/Functional/Update/ViewsBulkFormActionsOrderUpdate.php b/core/modules/views/tests/src/Functional/Update/ViewsBulkFormActionsOrderUpdate.php
+new file mode 100644
+index 0000000000..a634c817f6
+--- /dev/null
++++ b/core/modules/views/tests/src/Functional/Update/ViewsBulkFormActionsOrderUpdate.php
+@@ -0,0 +1,40 @@
++<?php
++
++namespace Drupal\Tests\views\Functional\Update;
++
++use Drupal\FunctionalTests\Update\UpdatePathTestBase;
++
++/**
++ * Tests views_post_update_bulk_form_action_order().
++ *
++ * @group views
++ * @group legacy
++ */
++class ViewsBulkFormActionsOrderUpdate extends UpdatePathTestBase {
++
++  /**
++   * {@inheritdoc}
++   */
++  protected function setDatabaseDumpFiles(): void {
++    $this->databaseDumpFiles = [
++      __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-9.0.0.bare.standard.php.gz',
++    ];
++  }
++
++  /**
++   * Tests views_post_update_bulk_form_action_order().
++   *
++   * @see views_post_update_bulk_form_action_order()
++   */
++  public function testBulkFormActionsOrderPostUpdate(): void {
++    $config_factory = \Drupal::configFactory();
++    $path = 'display.default.display_options.fields.user_bulk_form';
++    $config = $config_factory->get('views.view.user_admin_people');
++    $this->assertArrayNotHasKey('actions_order', $config->get($path));
++    $this->runUpdates();
++    $config = $config_factory->get('views.view.user_admin_people');
++    $this->assertArrayHasKey('actions_order', $config->get($path));
++    $this->assertSame([], $config->get("$path.actions_order"));
++  }
++
++}
+diff --git a/core/modules/views/views.libraries.yml b/core/modules/views/views.libraries.yml
+index a191767b0b..f7a557f2e1 100644
+--- a/core/modules/views/views.libraries.yml
++++ b/core/modules/views/views.libraries.yml
+@@ -17,3 +17,9 @@ views.ajax:
+     - core/jquery.once.bc
+     - core/internal.jquery.form
+     - core/drupal.ajax
++
++views.bulk_form:
++  version: VERSION
++  css:
++    component:
++      css/views.bulk_form.css: {}
+diff --git a/core/modules/views/views.post_update.php b/core/modules/views/views.post_update.php
+index 4cca352d89..adf91de47f 100644
+--- a/core/modules/views/views.post_update.php
++++ b/core/modules/views/views.post_update.php
+@@ -105,3 +105,14 @@ function views_post_update_image_lazy_load(?array &$sandbox = NULL): void {
+     return $view_config_updater->needsImageLazyLoadFieldUpdate($view);
+   });
+ }
++
++/**
++ * Add the actions order option to all bulk form field configurations.
++ */
++function views_post_update_bulk_form_action_order(?array &$sandbox = NULL): void {
++  /** @var \Drupal\views\ViewsConfigUpdater $view_config_updater */
++  $view_config_updater = \Drupal::classResolver(ViewsConfigUpdater::class);
++  \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'view', function (ViewEntityInterface $view) use ($view_config_updater): bool {
++    return $view_config_updater->needsBulkFormActionsOrderUpdate($view);
++  });
++}
+diff --git a/core/profiles/demo_umami/config/optional/views.view.media.yml b/core/profiles/demo_umami/config/optional/views.view.media.yml
+index dc3b7e813f..f1db673285 100644
+--- a/core/profiles/demo_umami/config/optional/views.view.media.yml
++++ b/core/profiles/demo_umami/config/optional/views.view.media.yml
+@@ -76,6 +76,11 @@ display:
+           action_title: Action
+           include_exclude: exclude
+           selected_actions: {  }
++          actions_order:
++            - media_publish_action
++            - media_unpublish_action
++            - media_save_action
++            - media_delete_action
+         thumbnail__target_id:
+           id: thumbnail__target_id
+           table: media_field_data
+diff --git a/core/themes/claro/claro.info.yml b/core/themes/claro/claro.info.yml
+index 6032f10bc5..53082cda09 100644
+--- a/core/themes/claro/claro.info.yml
++++ b/core/themes/claro/claro.info.yml
+@@ -102,6 +102,11 @@ libraries-override:
+       state:
+         css/toolbar.menu.css: css/state/toolbar.menu.css
+ 
++  views/views.bulk_form:
++    css:
++      component:
++        css/views.bulk_form.css: css/components/views.bulk_form.css
++
+   views_ui/admin.styling:
+     css:
+       component:
+diff --git a/core/themes/claro/css/components/views.bulk_form.css b/core/themes/claro/css/components/views.bulk_form.css
+new file mode 100644
+index 0000000000..17ac9fa0ee
+--- /dev/null
++++ b/core/themes/claro/css/components/views.bulk_form.css
+@@ -0,0 +1,12 @@
++tr.draggable td {
++  width: 100%;
++}
++tr.draggable td:first-child {
++  display: flex;
++  align-items: center;
++  width: 5rem;
++}
++/* Ensure a space between checkbox and the 'Changed' asterisk */
++tr.draggable td:first-child input[type=checkbox] {
++  margin-right: 3px;
++}
+diff --git a/core/themes/stable/css/views/views.bulk_form.css b/core/themes/stable/css/views/views.bulk_form.css
+new file mode 100644
+index 0000000000..1b193ef423
+--- /dev/null
++++ b/core/themes/stable/css/views/views.bulk_form.css
+@@ -0,0 +1,12 @@
++tr.draggable td {
++  width: 100%;
++}
++tr.draggable td:first-child {
++  display: flex;
++  align-items: center;
++  width: 2.5rem;
++}
++/* Ensure a space between checkbox and the 'Changed' asterisk */
++tr.draggable td:first-child input[type=checkbox] {
++  margin-right: 3px;
++}
+diff --git a/core/themes/stable/stable.info.yml b/core/themes/stable/stable.info.yml
+index 13f28498ce..aaf939de04 100644
+--- a/core/themes/stable/stable.info.yml
++++ b/core/themes/stable/stable.info.yml
+@@ -293,6 +293,11 @@ libraries-override:
+       component:
+         css/views.module.css: css/views/views.module.css
+ 
++  views/views.bulk_form:
++    css:
++      component:
++        css/views.bulk_form.css: css/views/views.bulk_form.css
++
+   views_ui/admin.styling:
+     css:
+       component:
+diff --git a/core/themes/stable9/css/views/views.bulk_form.css b/core/themes/stable9/css/views/views.bulk_form.css
+new file mode 100644
+index 0000000000..1b193ef423
+--- /dev/null
++++ b/core/themes/stable9/css/views/views.bulk_form.css
+@@ -0,0 +1,12 @@
++tr.draggable td {
++  width: 100%;
++}
++tr.draggable td:first-child {
++  display: flex;
++  align-items: center;
++  width: 2.5rem;
++}
++/* Ensure a space between checkbox and the 'Changed' asterisk */
++tr.draggable td:first-child input[type=checkbox] {
++  margin-right: 3px;
++}
+diff --git a/core/themes/stable9/stable9.info.yml b/core/themes/stable9/stable9.info.yml
+index 32595170a1..90b182da66 100644
+--- a/core/themes/stable9/stable9.info.yml
++++ b/core/themes/stable9/stable9.info.yml
+@@ -313,6 +313,11 @@ libraries-override:
+       component:
+         css/views.module.css: css/views/views.module.css
+ 
++  views/views.bulk_form:
++    css:
++      component:
++        css/views.bulk_form.css: css/views/views.bulk_form.css
++
+   views_ui/admin.styling:
+     css:
+       component:
diff --git a/resources/patch/drupal/core/2675600.diff b/resources/patch/drupal/core/2675600.diff
new file mode 100644
index 0000000000000000000000000000000000000000..3b8acae6f843d7c732a401e977c1a8dfec65b120
--- /dev/null
+++ b/resources/patch/drupal/core/2675600.diff
@@ -0,0 +1,208 @@
+diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+index 46e96c9a88..c50efde4bf 100644
+--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
++++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+@@ -2250,7 +2250,8 @@ protected function getDedicatedTableSchema(FieldStorageDefinitionInterface $stor
+     else {
+       $id_schema = [
+         'type' => 'varchar_ascii',
+-        'length' => 128,
++        // @todo Changing this is out of scope for issue #2675600.
++        'length' => 255,
+         'not null' => TRUE,
+         'description' => 'The entity id this data is attached to',
+       ];
+diff --git a/core/modules/file/file.install b/core/modules/file/file.install
+index a975eed34b..6838d165f7 100644
+--- a/core/modules/file/file.install
++++ b/core/modules/file/file.install
+@@ -35,7 +35,7 @@ function file_schema() {
+       'id' => [
+         'description' => 'The primary key of the object using the file.',
+         'type' => 'varchar_ascii',
+-        'length' => 64,
++        'length' => 255,
+         'not null' => TRUE,
+         'default' => 0,
+       ],
+@@ -119,3 +119,22 @@ function file_requirements($phase) {
+ function file_update_last_removed() {
+   return 8700;
+ }
++
++/**
++ * Update file_usage table to support longer entity IDs.
++ */
++function file_update_8301() {
++  $database = \Drupal::database();
++  $database->schema()->changeField(
++    'file_usage',
++    'id',
++    'id',
++    [
++      'type' => 'varchar_ascii',
++      'not null' => TRUE,
++      'default' => 0,
++      'length' => 255,
++      'description' => 'The primary key of the object using the file.',
++    ]
++  );
++}
+diff --git a/core/modules/file/tests/src/Kernel/EntityStringIdTest.php b/core/modules/file/tests/src/Kernel/EntityStringIdTest.php
+new file mode 100644
+index 0000000000..ab1789011a
+--- /dev/null
++++ b/core/modules/file/tests/src/Kernel/EntityStringIdTest.php
+@@ -0,0 +1,130 @@
++<?php
++
++namespace Drupal\Tests\file\Kernel;
++
++use Drupal\Core\Entity\EntityInterface;
++use Drupal\KernelTests\KernelTestBase;
++use Drupal\entity_test\Entity\EntityTestStringId;
++use Drupal\field\Entity\FieldConfig;
++use Drupal\field\Entity\FieldStorageConfig;
++use Drupal\file\Entity\File;
++use Drupal\file\FileInterface;
++use Drupal\user\Entity\User;
++use org\bovigo\vfs\vfsStream;
++
++/**
++ * Tests that entities using string IDs can use file fields.
++ *
++ * @group file
++ */
++class EntityStringIdTest extends KernelTestBase {
++
++  /**
++   * {@inheritdoc}
++   */
++  public static $modules = [
++    'entity_test',
++    'field',
++    'file',
++    'image',
++    'system',
++    'user',
++  ];
++
++  /**
++   * A test user.
++   *
++   * @var \Drupal\user\UserInterface
++   */
++  protected $user;
++
++  /**
++   * {@inheritdoc}
++   */
++  protected function setUp() {
++    parent::setUp();
++
++    $this->installEntitySchema('entity_test_string_id');
++    $this->installEntitySchema('user');
++    $this->installEntitySchema('file');
++    $this->installSchema('file', 'file_usage');
++    $this->installSchema('system', 'sequences');
++
++    $this->user = User::create([
++      'name' => 'username',
++      'status' => 1,
++    ]);
++    $this->user->save();
++    $this->container->get('current_user')->setAccount($this->user);
++  }
++
++  /**
++   * Tests that entities with string IDs can reference files.
++   *
++   * @dataProvider getFileTypes
++   */
++  public function testEntityStringId($file_type) {
++    $field_storage = FieldStorageConfig::create([
++      'field_name' => 'field_test_file',
++      'entity_type' => 'entity_test_string_id',
++      'type' => $file_type,
++    ]);
++    $field_storage->save();
++
++    $field = FieldConfig::create([
++      'field_name' => 'field_test_file',
++      'entity_type' => 'entity_test_string_id',
++      'bundle' => 'entity_test_string_id',
++        'settings' => [
++          //'max_filesize' => '2k',
++          'file_extensions' => 'txt',
++        ],
++    ]);
++    $field->save();
++
++    vfsStream::setup('drupal_root');
++    vfsStream::create([
++      'sites' => [
++        'default' => [
++          'files' => [
++            'test.txt' => 'test',
++          ]
++        ]
++      ]
++    ]);
++
++    /** @var FileInterface $file */
++    $file = File::create([
++      'uri' => 'vfs://drupal_root/sites/default/files/test.txt',
++      'uid' => $this->user->id(),
++    ]);
++    $file->setPermanent();
++    $file->save();
++
++    /** @var EntityInterface $entity_test */
++    $entity_test = EntityTestStringId::create([
++      'uid' => $this->user->id(),
++      'id' => $this->randomMachineName(255),
++      'field_test_file' => [
++        'target_id' => $file->id(),
++      ]
++    ]);
++
++    // Check that there are no validation errors.
++    $result = $entity_test->validate();
++    $this->assertCount(0, $result);
++
++    // Check that the file can correctly be saved on the entity.
++    $entity_test->save();
++    $referenced_file = $entity_test->get('field_test_file')->referencedEntities()[0];
++    $this->assertEquals($file->id(), $referenced_file->id());
++  }
++
++  /**
++   * Provides a list of file types to test.
++   */
++  public function getFileTypes() {
++    return [['file'], ['image']];
++  }
++
++}
+diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
+index 7ae6eeba57..85ba0388df 100644
+--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
++++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
+@@ -1084,13 +1084,15 @@ public function testDedicatedTableSchemaForEntityWithStringIdentifier() {
+           ],
+           'entity_id' => [
+             'type' => 'varchar_ascii',
+-            'length' => 128,
++            // @todo This change is out of scope for issue #2675600.
++            'length' => 255,
+             'not null' => TRUE,
+             'description' => 'The entity id this data is attached to',
+           ],
+           'revision_id' => [
+             'type' => 'varchar_ascii',
+-            'length' => 128,
++            // @todo This change is out of scope for issue #2675600.
++            'length' => 255,
+             'not null' => TRUE,
+             'description' => 'The entity revision id this data is attached to, which for an unversioned entity type is the same as the entity id',
+           ],
diff --git a/resources/patch/message_notify-diff-8.x-1.2-3314370.diff b/resources/patch/drupal/message_notify/3314370.diff
similarity index 61%
rename from resources/patch/message_notify-diff-8.x-1.2-3314370.diff
rename to resources/patch/drupal/message_notify/3314370.diff
index 45c62a8482800a9aee530e1182f9432f33055352..b14221b58bfe864eb2c488dff7ef34743908bcc9 100644
--- a/resources/patch/message_notify-diff-8.x-1.2-3314370.diff
+++ b/resources/patch/drupal/message_notify/3314370.diff
@@ -1,29 +1,3 @@
-diff --git a/composer.json b/composer.json
-index 8b56a61..515721c 100644
---- a/composer.json
-+++ b/composer.json
-@@ -10,7 +10,7 @@
-         "source": "https://cgit.drupalcode.org/message_notify"
-     },
-     "require": {
--      "drupal/message": "~8.1.0"
-+      "drupal/message": "^1.0"
-     },
-     "minimum-stability": "dev"
- }
-diff --git a/message_notify.info.yml b/message_notify.info.yml
-index 9c75b79..6d54b08 100644
---- a/message_notify.info.yml
-+++ b/message_notify.info.yml
-@@ -1,7 +1,6 @@
- name: 'Message Notify'
- description: 'Message notify.'
--core: 8.x
--core_version_requirement: ^8 || ^9
-+core_version_requirement: ^9 || ^10
- package: Message
- dependencies:
-   - message:message
 diff --git a/src/Event/MessageNotifyDeliveryEvent.php b/src/Event/MessageNotifyDeliveryEvent.php
 new file mode 100644
 index 0000000..2e25e4e
@@ -96,7 +70,7 @@ index 0000000..2e25e4e
 +
 +}
 diff --git a/src/Plugin/Notifier/Email.php b/src/Plugin/Notifier/Email.php
-index 9568ef9..45dfc21 100644
+index 97949cf..45dfc21 100644
 --- a/src/Plugin/Notifier/Email.php
 +++ b/src/Plugin/Notifier/Email.php
 @@ -9,6 +9,7 @@ use Drupal\Core\Render\RendererInterface;
@@ -165,7 +139,7 @@ index 9568ef9..45dfc21 100644
      // The subject in an email can't be with HTML, so strip it.
      $output['mail_subject'] = trim(strip_tags($output['mail_subject']));
  
-@@ -115,13 +121,13 @@ class Email extends MessageNotifierBase {
+@@ -115,10 +121,10 @@ class Email extends MessageNotifierBase {
      $result = $this->mailManager->mail(
        'message_notify',
        $this->message->getTemplate()->id(),
@@ -178,13 +152,9 @@ index 9568ef9..45dfc21 100644
 +      $this->configuration['from']
      );
  
--    return $result['result'];
-+    return isset($result['result']);
-   }
- 
- }
+     return isset($result['result']);
 diff --git a/src/Plugin/Notifier/MessageNotifierBase.php b/src/Plugin/Notifier/MessageNotifierBase.php
-index a1b500c..7244a6d 100644
+index 77a93cb..7244a6d 100644
 --- a/src/Plugin/Notifier/MessageNotifierBase.php
 +++ b/src/Plugin/Notifier/MessageNotifierBase.php
 @@ -7,8 +7,10 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
@@ -266,30 +236,7 @@ index a1b500c..7244a6d 100644
      $output = [];
  
      $view_builder = $this->entityTypeManager->getViewBuilder('message');
-@@ -121,13 +144,20 @@ abstract class MessageNotifierBase extends PluginBase implements MessageNotifier
-    */
-   public function postSend($result, array $output = []) {
-     $save = FALSE;
--    if (!$result) {
-+    // NULL means skip delivery. False signifies failure. Strict check.
-+    if ($result === FALSE) {
-       $this->logger->error('Could not send message using {title} to user ID {uid}.', ['{title}' => $this->pluginDefinition['title'], '{uid}' => $this->message->getOwnerId()]);
-       if ($this->configuration['save on fail']) {
-         $save = TRUE;
-       }
-     }
--    elseif ($result && $this->configuration['save on success']) {
-+    // MailManager::doMail may set $message['result'] = NULL in case sending was
-+    // canceled by one or more hook_mail_alter() implementations. This can
-+    // happen for example with Mail queue module. In that case the Message was
-+    // not really sent, on the other hand it didn't fail. As we won't know later
-+    // if it indeed was sent successfully, we take an optimistic approach, and
-+    // assume it will - thus saving the Message.
-+    elseif ($result !== FALSE && $this->configuration['save on success']) {
-       $save = TRUE;
-     }
- 
-@@ -175,4 +205,28 @@ abstract class MessageNotifierBase extends PluginBase implements MessageNotifier
+@@ -182,4 +205,28 @@ abstract class MessageNotifierBase extends PluginBase implements MessageNotifier
      $this->message = $message;
    }
  
@@ -340,15 +287,13 @@ index c45bc02..0cafc00 100644
    /**
     * Entry point to send and process a message.
 diff --git a/tests/modules/message_notify_test/message_notify_test.info.yml b/tests/modules/message_notify_test/message_notify_test.info.yml
-index d05ad96..a0e7786 100644
+index 2c32bab..a0e7786 100644
 --- a/tests/modules/message_notify_test/message_notify_test.info.yml
 +++ b/tests/modules/message_notify_test/message_notify_test.info.yml
-@@ -1,8 +1,7 @@
+@@ -1,6 +1,7 @@
  name: 'Message Notify Test Module'
  description: 'Functionality to assist Message notify testing.'
  type: module
--core: 8.x
--core_version_requirement: ^8 || ^9
 +core_version_requirement: ^9 || ^10
  dependencies:
    - drupal:field
@@ -453,35 +398,8 @@ index 0000000..ebc1b5a
 +  }
 +
 +}
-diff --git a/tests/src/Functional/EmailNotifierTest.php b/tests/src/Functional/EmailNotifierTest.php
-index 1916d39..14b0435 100644
---- a/tests/src/Functional/EmailNotifierTest.php
-+++ b/tests/src/Functional/EmailNotifierTest.php
-@@ -21,7 +21,12 @@ class EmailNotifierTest extends BrowserTestBase {
-   /**
-    * {@inheritdoc}
-    */
--  public static $modules = ['text', 'message_notify_test', 'filter_test'];
-+  protected static $modules = ['text', 'message_notify_test', 'filter_test'];
-+
-+  /**
-+   * {@inheritdoc}
-+   */
-+  protected $defaultTheme = 'stark';
- 
-   /**
-    * Testing message template.
-@@ -40,7 +45,7 @@ class EmailNotifierTest extends BrowserTestBase {
-   /**
-    * {@inheritdoc}
-    */
--  public function setUp() {
-+  public function setUp(): void {
-     parent::setUp();
- 
-     $this->messageTemplate = MessageTemplate::load('message_notify_test');
 diff --git a/tests/src/Kernel/MessageNotifyTest.php b/tests/src/Kernel/MessageNotifyTest.php
-index 415bbc9..1ec96b9 100644
+index 6d8c72e..1ec96b9 100644
 --- a/tests/src/Kernel/MessageNotifyTest.php
 +++ b/tests/src/Kernel/MessageNotifyTest.php
 @@ -2,12 +2,14 @@
@@ -509,179 +427,7 @@ index 415bbc9..1ec96b9 100644
    /**
     * Testing message template.
     *
-@@ -34,7 +39,7 @@ class MessageNotifyTest extends KernelTestBase {
-   /**
-    * {@inheritdoc}
-    */
--  public static $modules = [
-+  protected static $modules = [
-     'message_notify_test',
-     'message_notify',
-     'message',
-@@ -49,7 +54,7 @@ class MessageNotifyTest extends KernelTestBase {
-   /**
-    * {@inheritdoc}
-    */
--  public function setUp() {
-+  public function setUp(): void {
-     parent::setUp();
- 
-     $this->installEntitySchema('user');
-@@ -80,10 +85,10 @@ class MessageNotifyTest extends KernelTestBase {
-     // The test notifier added the output to the message.
-     $output = $message->output;
-     $text = $message->getText();
--    $this->assertContains((string) $text[1], (string) $output['foo']);
--    $this->assertContains('another field', (string) $output['foo']);
--    $this->assertContains((string) $text[0], (string) $output['bar']);
--    $this->assertNotContains('another field', (string) $output['bar']);
-+    $this->assertStringContainsString((string) $text[1], (string) $output['foo']);
-+    $this->assertStringContainsString('another field', (string) $output['foo']);
-+    $this->assertStringContainsString((string) $text[0], (string) $output['bar']);
-+    $this->assertStringNotContainsString('another field', (string) $output['bar']);
-   }
- 
-   /**
-@@ -95,12 +100,12 @@ class MessageNotifyTest extends KernelTestBase {
-     $message = Message::create(['template' => $this->messageTemplate->id(), 'uid' => $account->id()]);
-     $message->fail = FALSE;
-     $this->messageNotifier->send($message, [], 'test');
--    $this->assertTrue($message->id(), 'Message saved after successful delivery.');
-+    $this->assertNotNull($message->id(), 'Message saved after successful delivery.');
- 
-     $message = Message::create(['template' => $this->messageTemplate->id(), 'uid' => $account->id()]);
-     $message->fail = TRUE;
-     $this->messageNotifier->send($message, [], 'test');
--    $this->assertFalse($message->id(), 'Message not saved after unsuccessful delivery.');
-+    $this->assertNull($message->id(), 'Message not saved after unsuccessful delivery.');
- 
-     // Disable saving Message on delivery.
-     $options = [
-@@ -122,65 +127,79 @@ class MessageNotifyTest extends KernelTestBase {
- 
-   /**
-    * Test populating the rednered output to fields.
-+   *
-+   * @dataProvider providerPostSendRenderedField
-    */
--  public function testPostSendRenderedField() {
-+  public function testPostSendRenderedField(array $options, bool $exception) {
-     $this->attachRenderedFields();
- 
--    // Test plain fields.
--    $options = [
--      'rendered fields' => [
--        'foo' => 'rendered_foo',
--        'bar' => 'rendered_bar',
--      ],
--    ];
--
-     $message = Message::create(['template' => $this->messageTemplate->id()]);
-+
-+    if ($exception) {
-+      $this->expectException(MessageNotifyException::class);
-+    }
-+
-     $this->messageNotifier->send($message, $options, 'test');
--    $this->assertTrue($message->rendered_foo->value && $message->rendered_bar->value, 'Message is rendered to fields.');
- 
--    // Test field with text-processing.
--    $options = [
--      'rendered fields' => [
--        'foo' => 'rendered_baz',
--        'bar' => 'rendered_bar',
-+    if (!$exception) {
-+      $this->assertArrayHasKey('rendered fields', $options);
-+      $fields = array_values($options['rendered fields']);
-+      $this->assertNotEmpty($fields);
-+      foreach ($fields as $field) {
-+        $this->assertNotEmpty($message->{$field}->value, 'The message field ' . $field . ' was not rendered.');
-+      }
-+    }
-+  }
-+
-+  /**
-+   * Data provider for ::testPostSendRenderedField.
-+   *
-+   * @return array
-+   */
-+  public function providerPostSendRenderedField():array {
-+    $cases = [];
-+
-+    $cases['plain fields'] = [
-+      [
-+        'rendered fields' => [
-+          'foo' => 'rendered_foo',
-+          'bar' => 'rendered_bar',
-+        ],
-       ],
-+      FALSE,
-     ];
- 
--    $message = Message::create(['template' => $this->messageTemplate->id()]);
--    $this->messageNotifier->send($message, $options, 'test');
--    $this->assertTrue($message->rendered_baz->value && $message->rendered_bar->value, 'Message is rendered to fields with text-processing.');
-+    $cases['field with text-processing'] = [
-+      [
-+        'rendered fields' => [
-+          'foo' => 'rendered_baz',
-+          'bar' => 'rendered_bar',
-+        ],
-+      ],
-+      FALSE,
-+    ];
- 
--    // Test missing view mode key in the rendered fields.
--    $options = [
--      'rendered fields' => [
--        'foo' => 'rendered_foo',
--        // No "bar" field.
-+    $cases['missing view mode key in rendered fields'] = [
-+      [
-+        'rendered fields' => [
-+          'foo' => 'rendered_foo',
-+          // No "bar" field.
-+        ],
-       ],
-+      TRUE,
-     ];
--    $message = Message::create(['template' => $this->messageTemplate->id()]);
--    try {
--      $this->messageNotifier->send($message, $options, 'test');
--      $this->fail('Can save rendered message with missing view mode.');
--    }
--    catch (MessageNotifyException $e) {
--      $this->pass('Cannot save rendered message with missing view mode.');
--    }
- 
--    // Test invalid field name.
--    $options = [
--      'rendered fields' => [
--        'foo' => 'wrong_field',
--        'bar' => 'rendered_bar',
-+    $cases['invalid field name'] = [
-+      [
-+        'rendered fields' => [
-+          'foo' => 'wrong_field',
-+          'bar' => 'rendered_bar',
-+        ],
-       ],
-+      TRUE,
-     ];
--    $message = Message::create(['template' => $this->messageTemplate->id()]);
--    try {
--      $this->messageNotifier->send($message, $options, 'test');
--      $this->fail('Can save rendered message to non-existing field.');
--    }
--    catch (MessageNotifyException $e) {
--      $this->pass('Cannot save rendered message to non-existing field.');
--    }
-+
-+    return $cases;
-   }
- 
-   /**
-@@ -213,4 +232,28 @@ class MessageNotifyTest extends KernelTestBase {
+@@ -227,4 +232,28 @@ class MessageNotifyTest extends KernelTestBase {
      }
    }
  
@@ -711,19 +457,18 @@ index 415bbc9..1ec96b9 100644
 +
  }
 diff --git a/tests/src/Unit/Plugin/Notifier/EmailTest.php b/tests/src/Unit/Plugin/Notifier/EmailTest.php
-index 054fca3..4821236 100644
+index f40bc9e..4821236 100644
 --- a/tests/src/Unit/Plugin/Notifier/EmailTest.php
 +++ b/tests/src/Unit/Plugin/Notifier/EmailTest.php
-@@ -14,6 +14,8 @@ use Drupal\message_notify\Exception\MessageNotifyException;
- use Drupal\message_notify\Plugin\Notifier\Email;
+@@ -15,6 +15,7 @@ use Drupal\message_notify\Plugin\Notifier\Email;
  use Drupal\Tests\UnitTestCase;
  use Drupal\user\UserInterface;
-+use Prophecy\Argument;
+ use Prophecy\Argument;
 +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  
  /**
   * Unit tests for the Email notifier.
-@@ -52,6 +54,13 @@ class EmailTest extends UnitTestCase {
+@@ -53,6 +54,13 @@ class EmailTest extends UnitTestCase {
     */
    protected $renderer;
  
@@ -737,47 +482,15 @@ index 054fca3..4821236 100644
    /**
     * Plugin definition.
     *
-@@ -74,12 +83,15 @@ class EmailTest extends UnitTestCase {
-   /**
-    * {@inheritdoc}
-    */
--  public function setUp() {
-+  public function setUp(): void {
-     parent::setUp();
+@@ -80,6 +88,7 @@ class EmailTest extends UnitTestCase {
  
      $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class)->reveal();
      $this->mailManager = $this->prophesize(MailManagerInterface::class)->reveal();
--    $this->renderer = $this->prophesize(RendererInterface::class)->reveal();
 +    $this->eventDispatcher = $this->prophesize(EventDispatcherInterface::class)->reveal();
-+    $renderer = $this->prophesize(RendererInterface::class);
-+    $renderer->renderPlain(Argument::any())->willReturn('foo bar');
-+    $this->renderer = $renderer->reveal();
-     $this->pluginId = $this->randomMachineName();
-     $this->pluginDefinition['title'] = $this->randomMachineName();
-   }
-@@ -101,16 +113,18 @@ class EmailTest extends UnitTestCase {
-     $message->getOwnerId()->willReturn(42);
-     $template = $this->prophesize(MessageTemplateInterface::class)->reveal();
-     $message->getTemplate()->willReturn($template);
-+    $message->save()->willReturn(1);
- 
-     // Mock view builder.
--    $view_builder = $this->prophesize(EntityViewBuilderInterface::class)->reveal();
-+    $view_builder = $this->prophesize(EntityViewBuilderInterface::class);
-+    $view_builder->view(Argument::cetera())->willReturn([]);
-     $entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
--    $entity_type_manager->getViewBuilder('message')->willReturn($view_builder);
-+    $entity_type_manager->getViewBuilder('message')->willReturn($view_builder->reveal());
-     $this->entityTypeManager = $entity_type_manager->reveal();
- 
-     $notifier = $this->getNotifier();
-     $notifier->setMessage($message->reveal());
--    $this->assertNull($notifier->send());
-+    $this->assertFalse($notifier->send());
-   }
- 
-   /**
-@@ -137,6 +151,12 @@ class EmailTest extends UnitTestCase {
+     $renderer = $this->prophesize(RendererInterface::class);
+     $renderer->renderPlain(Argument::any())->willReturn('foo bar');
+     $this->renderer = $renderer->reveal();
+@@ -142,6 +151,12 @@ class EmailTest extends UnitTestCase {
      $account = $this->prophesize(UserInterface::class)->reveal();
      $message->getOwner()->willReturn($account);
      $notifier = $this->getNotifier($message->reveal());
@@ -790,7 +503,7 @@ index 054fca3..4821236 100644
      $notifier->deliver([]);
    }
  
-@@ -160,7 +180,8 @@ class EmailTest extends UnitTestCase {
+@@ -165,7 +180,8 @@ class EmailTest extends UnitTestCase {
        $this->entityTypeManager,
        $this->renderer,
        $message,
diff --git a/resources/patch/ec-europa/toolkit/566.diff b/resources/patch/ec-europa/toolkit/566.diff
new file mode 100644
index 0000000000000000000000000000000000000000..df38cb7985d81e04f7799ae79256abceb34c1b69
--- /dev/null
+++ b/resources/patch/ec-europa/toolkit/566.diff
@@ -0,0 +1,87 @@
+diff --git a/config/commands/test.yml b/config/commands/test.yml
+index 038faa19..9b028e64 100644
+--- a/config/commands/test.yml
++++ b/config/commands/test.yml
+@@ -4,6 +4,8 @@ command:
+       options:
+         from: ${toolkit.test.behat.from}
+         to: ${toolkit.test.behat.to}
++        profile: ${toolkit.test.behat.profile}
++        options: ${toolkit.test.behat.options}
+     test-phpunit:
+       options:
+         execution: ${toolkit.test.phpunit.execution}
+diff --git a/config/default.yml b/config/default.yml
+index 14a5b29c..819d9fc4 100644
+--- a/config/default.yml
++++ b/config/default.yml
+@@ -56,6 +56,7 @@ toolkit:
+       from: behat.yml.dist
+       to: behat.yml
+       profile: default
++      options: 'strict'
+     phpunit:
+       options: ''
+       execution: default
+diff --git a/src/TaskRunner/Commands/TestsCommands.php b/src/TaskRunner/Commands/TestsCommands.php
+index 6acbf433..b451b47b 100644
+--- a/src/TaskRunner/Commands/TestsCommands.php
++++ b/src/TaskRunner/Commands/TestsCommands.php
+@@ -351,12 +351,16 @@ class TestsCommands extends AbstractCommands implements FilesystemAwareInterface
+      * @option to       To behat.yml config file.
+      * @option profile  The profile to execute.
+      * @option suite    The suite to execute, default runs all suites of profile.
++     * @option options  Extra options for the command without -- (only options with no value).
++     *
++     * @usage --profile='prod' --options='strict stop-on-failure'
+      */
+     public function toolkitBehat(array $options = [
+         'from' => InputOption::VALUE_OPTIONAL,
+         'to' => InputOption::VALUE_OPTIONAL,
+         'profile' => InputOption::VALUE_OPTIONAL,
+         'suite' => InputOption::VALUE_OPTIONAL,
++        'options' => InputOption::VALUE_OPTIONAL,
+     ])
+     {
+         $tasks = [];
+@@ -369,10 +373,17 @@ class TestsCommands extends AbstractCommands implements FilesystemAwareInterface
+ 
+         $behatBin = $this->getBin('behat');
+         $defaultProfile = $this->getConfig()->get('toolkit.test.behat.profile');
++        $execOpts = [
++            'profile' => !empty($options['profile']) ? $options['profile'] : $defaultProfile,
++        ];
+ 
+-        $profile = (!empty($options['profile'])) ? $options['profile'] : $defaultProfile;
+-        $suite = (!empty($options['suite'])) ? $options['suite'] : '';
+-        $suiteParameter = ($suite) ? ' --suite=' . $suite : '';
++        if (!empty($options['suite'])) {
++            $execOpts['suite'] = $options['suite'];
++        }
++        if (!empty($options['options'])) {
++            $extraOptions = array_fill_keys(explode(' ', $options['options']), null);
++            $execOpts = array_merge($execOpts, $extraOptions);
++        }
+ 
+         // Execute a list of commands to run before tests.
+         if ($commands = $this->getConfig()->get('toolkit.test.behat.commands.before')) {
+@@ -381,15 +392,15 @@ class TestsCommands extends AbstractCommands implements FilesystemAwareInterface
+ 
+         $this->taskProcessConfigFile($options['from'], $options['to'])->run();
+ 
+-        $result = $this->taskExec("$behatBin --dry-run --profile=$profile $suiteParameter")
++        $result = $this->taskExec($behatBin)->options($execOpts + ['dry-run' => null], '=')
+             ->silent(true)->run()->getMessage();
+ 
+-        if (strpos(trim($result), 'No scenarios') !== false) {
+-            $this->say("No Scenarios found for profile $profile $suiteParameter, please create at least one Scenario.");
++        if (str_contains(trim($result), 'No scenarios')) {
++            $this->say("No Scenarios found for profile {$execOpts['profile']}, please create at least one Scenario.");
+             return new ResultData(1);
+         }
+ 
+-        $tasks[] = $this->taskExec("$behatBin --profile=$profile $suiteParameter");
++        $tasks[] = $this->taskExec($behatBin)->options($execOpts, '=');
+ 
+         // Execute a list of commands to run after tests.
+         if ($commands = $this->getConfig()->get('toolkit.test.behat.commands.after')) {
diff --git a/resources/patch/facet_accessibility-3208580.patch b/resources/patch/facet_accessibility-3208580.patch
deleted file mode 100644
index 2a62fea679bb24cd7f390f4cac62efbe8fba0d04..0000000000000000000000000000000000000000
--- a/resources/patch/facet_accessibility-3208580.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-Index: js/soft-limit.js
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
-<+>UTF-8
-===================================================================
-diff --git a/js/soft-limit.js b/js/soft-limit.js
---- a/js/soft-limit.js	
-+++ b/js/soft-limit.js	(date 1643037840570)
-@@ -56,13 +56,13 @@
-       $('<a href="#" class="facets-soft-limit-link"></a>')
-         .text(showMoreLabel).attr("aria-expanded", "false")
-         .on('click', function () {
--          if (facet.find('li:hidden').length > 0) {
--            facet.find('li:gt(' + zero_based_limit + ')').slideDown();
--            facet.find('li:lt(' + (zero_based_limit + 2) + ') input').focus();
-+          if (facet.find('> li:hidden').length > 0) {
-+            facet.find('> li:gt(' + zero_based_limit + ')').slideDown();
-+            facet.find('> li:lt(' + (zero_based_limit + 2) + ') input').focus();
-             $(this).addClass('open').text(showLessLabel).attr("aria-expanded", "true");
-           }
-           else {
--            facet.find('li:gt(' + zero_based_limit + ')').slideUp();
-+            facet.find('> li:gt(' + zero_based_limit + ')').slideUp();
-             $(this).removeClass('open').text(showMoreLabel).attr("aria-expanded", "false");
-           }
-           return false;
diff --git a/resources/patch/search_api_solr-3236773.diff b/resources/patch/search_api_solr-3236773.diff
deleted file mode 100644
index f2c92c64afddc6e28c96e1d88a07fff723ef4e6b..0000000000000000000000000000000000000000
--- a/resources/patch/search_api_solr-3236773.diff
+++ /dev/null
@@ -1,956 +0,0 @@
-diff --git a/.github/workflows/jump-start-config-sets.yml b/.github/workflows/jump-start-config-sets.yml
-index bdbc075d..ef1668b3 100644
---- a/.github/workflows/jump-start-config-sets.yml
-+++ b/.github/workflows/jump-start-config-sets.yml
-@@ -269,7 +269,7 @@ jobs:
-                 php -S localhost:8888 >& /dev/null &
-                 vendor/bin/drush si minimal --db-url=sqlite://sites/default/files/db.sqlite --yes
-                 vendor/bin/drush en search_api_solr_admin,search_api_solr_defaults,search_api_solr_devel,search_api_solr_legacy --yes
--                vendor/bin/drush en search_api_spellcheck,search_api_autocomplete,facets,search_api_location --yes
-+                vendor/bin/drush en search_api_spellcheck,search_api_solr_autocomplete,facets,search_api_location --yes
-                 vendor/bin/phpunit -v -c core --group search_api_solr --exclude-group not_drupal${{ matrix.drupal }},not_solr${{ matrix.solr }} modules/contrib/search_api_solr
- 
-     run-legacy-tests:
-diff --git a/README.md b/README.md
-index 977fd863..44cadce0 100644
---- a/README.md
-+++ b/README.md
-@@ -194,7 +194,7 @@ a Solr Query Debugger and shows how content gets indexed.
- Regarding third-party features, the following are supported:
- 
- - autocomplete
--  - Introduced by module: search_api_autocomplete
-+  - Introduced by module: search_api_solr_autocomplete
-   - Lets you add autocompletion capabilities to search forms on the site.
- - facets
-   - Introduced by module: facet
-diff --git a/composer.json b/composer.json
-index 3599ad67..592568fd 100644
---- a/composer.json
-+++ b/composer.json
-@@ -37,7 +37,6 @@
-         "drupal/devel": "^4.0",
-         "drupal/facets": "1.x-dev",
-         "drupal/geofield": "1.x-dev",
--        "drupal/search_api_autocomplete": "1.x-dev",
-         "drupal/search_api_location": "1.x-dev",
-         "drupal/search_api_spellcheck": "3.x-dev"
-     },
-diff --git a/modules/search_api_solr_autocomplete/config/schema/search_api_solr_autocomplete.suggester.schema.yml b/modules/search_api_solr_autocomplete/config/schema/search_api_solr_autocomplete.suggester.schema.yml
-new file mode 100644
-index 00000000..c87603c7
---- /dev/null
-+++ b/modules/search_api_solr_autocomplete/config/schema/search_api_solr_autocomplete.suggester.schema.yml
-@@ -0,0 +1,21 @@
-+plugin.plugin_configuration.search_api_autocomplete_suggester.search_api_solr_suggester:
-+  type: mapping
-+  label: 'Search API Solr Suggester'
-+  mapping:
-+    search_api_solr/site_hash:
-+      type: integer
-+      label: 'Site hash'
-+    search_api/index:
-+      type: string
-+      label: 'Index ID'
-+    drupal/langcode:
-+      type: string
-+      label: 'Language'
-+
-+plugin.plugin_configuration.search_api_autocomplete_suggester.search_api_solr_spellcheck:
-+  type: mapping
-+  label: 'Search API Solr Spellcheck'
-+
-+plugin.plugin_configuration.search_api_autocomplete_suggester.search_api_solr_terms:
-+  type: plugin.plugin_configuration.search_api_autocomplete_suggester.server
-+  label: 'Search API Solr Terms'
-diff --git a/modules/search_api_solr_autocomplete/search_api_solr_autocomplete.info.yml b/modules/search_api_solr_autocomplete/search_api_solr_autocomplete.info.yml
-new file mode 100644
-index 00000000..bca33dd5
---- /dev/null
-+++ b/modules/search_api_solr_autocomplete/search_api_solr_autocomplete.info.yml
-@@ -0,0 +1,8 @@
-+type: module
-+name: 'Search API Solr Autocomplete'
-+description: 'Adds autocomplete functionality to Apache Solr searches.'
-+core_version_requirement: ^8.9 || ^9.2 || ^10.0
-+package: Search
-+dependencies:
-+  - search_api_autocomplete:search_api_autocomplete
-+  - search_api_solr:search_api_solr
-diff --git a/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php b/modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php
-similarity index 92%
-copy from src/Plugin/search_api_autocomplete/suggester/BackendTrait.php
-copy to modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php
-index 00233704..703124c9 100644
---- a/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php
-+++ b/modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php
-@@ -1,6 +1,6 @@
- <?php
- 
--namespace Drupal\search_api_solr\Plugin\search_api_autocomplete\suggester;
-+namespace Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester;
- 
- use Drupal\search_api\IndexInterface;
- use Drupal\search_api\LoggerTrait;
-diff --git a/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php b/modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php
-similarity index 96%
-copy from src/Plugin/search_api_autocomplete/suggester/Spellcheck.php
-copy to modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php
-index 31018815..02dda658 100644
---- a/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php
-+++ b/modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php
-@@ -1,6 +1,6 @@
- <?php
- 
--namespace Drupal\search_api_solr\Plugin\search_api_autocomplete\suggester;
-+namespace Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester;
- 
- use Drupal\Core\Form\FormStateInterface;
- use Drupal\Core\Plugin\PluginFormInterface;
-diff --git a/src/Plugin/search_api_autocomplete/suggester/Suggester.php b/modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Suggester.php
-similarity index 98%
-copy from src/Plugin/search_api_autocomplete/suggester/Suggester.php
-copy to modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Suggester.php
-index 46df04e8..c3d755fd 100644
---- a/src/Plugin/search_api_autocomplete/suggester/Suggester.php
-+++ b/modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Suggester.php
-@@ -1,6 +1,6 @@
- <?php
- 
--namespace Drupal\search_api_solr\Plugin\search_api_autocomplete\suggester;
-+namespace Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester;
- 
- use Drupal\Core\Form\FormStateInterface;
- use Drupal\Core\Language\LanguageInterface;
-diff --git a/src/Plugin/search_api_autocomplete/suggester/Terms.php b/modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Terms.php
-similarity index 94%
-copy from src/Plugin/search_api_autocomplete/suggester/Terms.php
-copy to modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Terms.php
-index 315a9c92..ab362bc0 100644
---- a/src/Plugin/search_api_autocomplete/suggester/Terms.php
-+++ b/modules/search_api_solr_autocomplete/src/Plugin/search_api_autocomplete/suggester/Terms.php
-@@ -1,6 +1,6 @@
- <?php
- 
--namespace Drupal\search_api_solr\Plugin\search_api_autocomplete\suggester;
-+namespace Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester;
- 
- use Drupal\search_api\Query\QueryInterface;
- use Drupal\search_api_autocomplete\Plugin\search_api_autocomplete\suggester\Server;
-diff --git a/modules/search_api_solr_autocomplete/tests/src/Kernel/SearchApiSolrAutocompleteAndNgramTest.php b/modules/search_api_solr_autocomplete/tests/src/Kernel/SearchApiSolrAutocompleteAndNgramTest.php
-new file mode 100644
-index 00000000..539f7777
---- /dev/null
-+++ b/modules/search_api_solr_autocomplete/tests/src/Kernel/SearchApiSolrAutocompleteAndNgramTest.php
-@@ -0,0 +1,171 @@
-+<?php
-+
-+namespace Drupal\Tests\search_api_solr_autocomplete\Kernel;
-+
-+use Drupal\search_api\Entity\Server;
-+use Drupal\search_api_autocomplete\Entity\Search;
-+use Drupal\Tests\search_api_solr\Kernel\SolrBackendTestBase;
-+
-+/**
-+ * Tests search autocomplete support and ngram results using the Solr search backend.
-+ *
-+ * @group search_api_solr
-+ */
-+class SearchApiSolrAutocompleteAndNgramTest extends SolrBackendTestBase {
-+
-+  /**
-+   * {@inheritdoc}
-+   */
-+  public static $modules = [
-+    'search_api_solr_autocomplete',
-+    'search_api_solr_legacy',
-+  ];
-+
-+  /**
-+   * Tests the autocomplete support and ngram results.
-+   */
-+  protected function testAutocompleteAndNgram(): void {
-+    $this->addTestEntity(1, [
-+      'name' => 'Test Article 1',
-+      'body' => 'The test article number 1 about cats, dogs and trees.',
-+      'type' => 'article',
-+      'category' => 'dogs and trees',
-+    ]);
-+
-+    // Add another node with body length equal to the limit.
-+    $this->addTestEntity(2, [
-+      'name' => 'Test Article 1',
-+      'body' => 'The test article number 2 about a tree.',
-+      'type' => 'article',
-+      'category' => 'trees',
-+    ]);
-+
-+    $this->indexItems($this->indexId);
-+
-+    /** @var \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend $backend */
-+    $backend = Server::load($this->serverId)->getBackend();
-+    $solr_major_version = $backend->getSolrConnector()->getSolrMajorVersion();
-+    $autocompleteSearch = new Search([], 'search_api_autocomplete_search');
-+
-+    $query = $this->buildSearch(['artic'], [], ['body_unstemmed'], FALSE);
-+    $query->setLanguages(['en']);
-+    $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'artic', 'artic');
-+    $this->assertEquals(1, count($suggestions));
-+    $this->assertEquals('le', $suggestions[0]->getSuggestionSuffix());
-+    $this->assertEquals(2, $suggestions[0]->getResultsCount());
-+
-+    $query = $this->buildSearch(['artic'], [], ['body'], FALSE);
-+    $query->setLanguages(['en']);
-+    $suggestions = $backend->getTermsSuggestions($query, $autocompleteSearch, 'artic', 'artic');
-+    $this->assertEquals(1, count($suggestions));
-+    // This time we test the stemmed token.
-+    $this->assertEquals('l', $suggestions[0]->getSuggestionSuffix());
-+    $this->assertEquals(2, $suggestions[0]->getResultsCount());
-+
-+    $targeted_branch = $backend->getSolrConnector()->getSchemaTargetedSolrBranch();
-+    if ('4.x' !== $targeted_branch && '3.x' !== $targeted_branch) {
-+      $query = $this->buildSearch(['articel'], [], ['body'], FALSE);
-+      $query->setLanguages(['en']);
-+      $suggestions = $backend->getSpellcheckSuggestions($query, $autocompleteSearch, 'articel', 'articel');
-+      $this->assertEquals(1, count($suggestions));
-+      $this->assertEquals('article', $suggestions[0]->getSuggestedKeys());
-+      $this->assertEquals(0, $suggestions[0]->getResultsCount());
-+    }
-+
-+    $query = $this->buildSearch(['article tre'], [], ['body_unstemmed'], FALSE);
-+    $query->setLanguages(['en']);
-+    $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'tre', 'article tre');
-+    $this->assertEquals('article tree', $suggestions[0]->getSuggestedKeys());
-+    $this->assertEquals(1, $suggestions[0]->getResultsCount());
-+    // Having set preserveOriginal in WordDelimiter let punction remain.
-+    $this->assertEquals('article tree.', $suggestions[1]->getSuggestedKeys());
-+    $this->assertEquals(1, $suggestions[1]->getResultsCount());
-+    $this->assertEquals('article trees', $suggestions[2]->getSuggestedKeys());
-+    $this->assertEquals(1, $suggestions[2]->getResultsCount());
-+    $this->assertEquals('article trees.', $suggestions[3]->getSuggestedKeys());
-+    $this->assertEquals(1, $suggestions[3]->getResultsCount());
-+
-+    // @todo spellcheck tests
-+    // @codingStandardsIgnoreStart
-+    // $query = $this->buildSearch(['articel cats doks'], [], ['body'], FALSE);
-+    // $query->setLanguages(['en']);
-+    // $suggestions = $backend->getSpellcheckSuggestions($query, $autocompleteSearch, 'doks', 'articel doks');
-+    // $this->assertEquals(1, count($suggestions));
-+    // $this->assertEquals('article dogs', $suggestions[0]->getSuggestedKeys());
-+
-+    // $query = $this->buildSearch(['articel tre'], [], ['body'], FALSE);
-+    // $query->setLanguages(['en']);
-+    // $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'tre', 'articel tre');
-+    // $this->assertEquals(5, count($suggestions));
-+    // $this->assertEquals('e', $suggestions[0]->getSuggestionSuffix());
-+    // $this->assertEquals(1, $suggestions[0]->getResultsCount());
-+    // $this->assertEquals('es', $suggestions[1]->getSuggestionSuffix());
-+    // @codingStandardsIgnoreEnd
-+
-+    if (version_compare($solr_major_version, '6', '>=')) {
-+      // @todo Add more suggester tests.
-+      $query = $this->buildSearch(['artic'], [], ['body'], FALSE);
-+      $query->setLanguages(['en']);
-+      $suggestions = $backend->getSuggesterSuggestions($query, $autocompleteSearch, 'artic', 'artic');
-+      $this->assertEquals(2, count($suggestions));
-+
-+      // Since we don't specify the result weights explicitly for this suggester
-+      // we need to deal with a random order and need predictable array keys.
-+      foreach ($suggestions as $suggestion) {
-+        $suggestions[$suggestion->getSuggestedKeys()] = $suggestion;
-+      }
-+      $this->assertEquals('artic', $suggestions['The test <b>artic</b>le number 1 about cats, dogs and trees.']->getUserInput());
-+      $this->assertEquals('The test <b>', $suggestions['The test <b>artic</b>le number 1 about cats, dogs and trees.']->getSuggestionPrefix());
-+      $this->assertEquals('</b>le number 1 about cats, dogs and trees.', $suggestions['The test <b>artic</b>le number 1 about cats, dogs and trees.']->getSuggestionSuffix());
-+      $this->assertEquals('The test <b>artic</b>le number 1 about cats, dogs and trees.', $suggestions['The test <b>artic</b>le number 1 about cats, dogs and trees.']->getSuggestedKeys());
-+
-+      $this->assertEquals('artic', $suggestions['The test <b>artic</b>le number 2 about a tree.']->getUserInput());
-+      $this->assertEquals('The test <b>', $suggestions['The test <b>artic</b>le number 2 about a tree.']->getSuggestionPrefix());
-+      $this->assertEquals('</b>le number 2 about a tree.', $suggestions['The test <b>artic</b>le number 2 about a tree.']->getSuggestionSuffix());
-+      $this->assertEquals('The test <b>artic</b>le number 2 about a tree.', $suggestions['The test <b>artic</b>le number 2 about a tree.']->getSuggestedKeys());
-+    }
-+
-+    // Tests NGram and Edge NGram search result.
-+    foreach (['category_ngram', 'category_edge'] as $field) {
-+      $results = $this->buildSearch(['tre'], [], [$field])
-+        ->execute();
-+      $this->assertResults([1, 2], $results, $field . ': tre');
-+
-+      $results = $this->buildSearch(['Dog'], [], [$field])
-+        ->execute();
-+      $this->assertResults([1], $results, $field . ': Dog');
-+
-+      $results = $this->buildSearch([], [], [])
-+        ->addCondition($field, 'Dog')
-+        ->execute();
-+      $this->assertResults([1], $results, $field . ': Dog as condition');
-+    }
-+
-+    // Tests NGram search result.
-+    $result_set = [
-+      'category_ngram' => [1, 2],
-+      'category_ngram_string' => [1, 2],
-+      'category_edge' => [],
-+      'category_edge_string' => [],
-+    ];
-+    foreach ($result_set as $field => $expected_results) {
-+      $results = $this->buildSearch(['re'], [], [$field])
-+        ->execute();
-+      $this->assertResults($expected_results, $results, $field . ': re');
-+    }
-+
-+    foreach (['category_ngram_string' => [1, 2], 'category_edge_string' => [2]] as $field => $expected_results) {
-+      $results = $this->buildSearch(['tre'], [], [$field])
-+        ->execute();
-+      $this->assertResults($expected_results, $results, $field . ': tre');
-+    }
-+  }
-+
-+  /**
-+   * {@inheritdoc}
-+   */
-+  public function testBackend() {
-+    $this->testAutocompleteAndNgram();
-+  }
-+
-+}
-diff --git a/modules/search_api_solr_autocomplete/tests/src/Kernel/SearchApiSolrAutocompleteTest.php b/modules/search_api_solr_autocomplete/tests/src/Kernel/SearchApiSolrAutocompleteTest.php
-new file mode 100644
-index 00000000..ffbe550e
---- /dev/null
-+++ b/modules/search_api_solr_autocomplete/tests/src/Kernel/SearchApiSolrAutocompleteTest.php
-@@ -0,0 +1,108 @@
-+<?php
-+
-+namespace Drupal\Tests\search_api_solr_autocomplete\Kernel;
-+
-+use Drupal\search_api\Entity\Server;
-+use Drupal\search_api_autocomplete\Entity\Search;
-+use Drupal\Tests\search_api_solr\Kernel\SolrBackendTestBase;
-+
-+/**
-+ * Tests search autocomplete results using the Solr search backend.
-+ *
-+ * @group search_api_solr
-+ */
-+class SearchApiSolrAutocompleteTest extends SolrBackendTestBase {
-+
-+  /**
-+   * {@inheritdoc}
-+   */
-+  public static $modules = [
-+    'search_api_solr_autocomplete',
-+  ];
-+
-+  /**
-+   * Tests the autocomplete support and ngram results.
-+   */
-+  protected function testAutocomplete(): void {
-+    $this->addTestEntity(1, [
-+      'name' => 'This is sparta',
-+      'body' => 'The scene originates from the 2006 film 300 directed by Zack Snyder.',
-+      'type' => 'article',
-+      'category' => 'movies',
-+    ]);
-+
-+    $this->addTestEntity(2, [
-+      'name' => 'Queen',
-+      'body' => 'Queen are a British rock band formed in London in 1970.',
-+      'type' => 'article',
-+      'category' => 'music',
-+    ]);
-+
-+    $this->addTestEntity(3, [
-+      'name' => 'William Shakespeare',
-+      'body' => 'Shakespeare produced most of his known works between 1589 and 1613.',
-+      'type' => 'article',
-+      'category' => 'actor',
-+    ]);
-+
-+    $this->addTestEntity(4, [
-+      'name' => 'Fast and Furious',
-+      'body' => 'This article is about the Fast & Furious 1 media franchise.',
-+      'type' => 'article',
-+      'category' => 'movies',
-+    ]);
-+
-+    $this->addTestEntity(5, [
-+      'name' => 'Fast and Furious 2',
-+      'body' => 'This article is about the Fast and Furious 2 media francia.',
-+      'type' => 'article',
-+      'category' => 'movies',
-+    ]);
-+
-+    $this->indexItems($this->indexId);
-+
-+    /** @var \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend $backend */
-+    $backend = Server::load($this->serverId)->getBackend();
-+    $autocompleteSearch = new Search([], 'search_api_solr_autocomplete_search');
-+
-+    $query = $this->buildSearch(['produc'], [], ['body_unstemmed'], FALSE);
-+    $query->setLanguages(['en']);
-+    $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'produc', 'produc');
-+    $this->assertEquals(1, count($suggestions));
-+    $this->assertEquals('ed', $suggestions[0]->getSuggestionSuffix());
-+    $this->assertEquals(1, $suggestions[0]->getResultsCount());
-+
-+    $query = $this->buildSearch(['furi'], [], ['body'], FALSE);
-+    $query->setLanguages(['en']);
-+    $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'furi', 'furi');
-+    $this->assertEquals(1, count($suggestions));
-+    $this->assertEquals('ous', $suggestions[0]->getSuggestionSuffix());
-+    $this->assertEquals(2, $suggestions[0]->getResultsCount());
-+
-+    $query = $this->buildSearch(['fast and fur'], [], ['body'], FALSE);
-+    $query->setLanguages(['en']);
-+    $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'fur', 'fast and fur');
-+    $this->assertEquals('fast and furious', $suggestions[0]->getSuggestedKeys());
-+    $this->assertEquals(2, $suggestions[0]->getResultsCount());
-+
-+    $query = $this->buildSearch(['media fran'], [], ['body'], FALSE);
-+    $query->setLanguages(['en']);
-+    $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'fran', 'media fran');
-+    $this->assertEquals('media franchis', $suggestions[0]->getSuggestedKeys());
-+    $this->assertEquals(1, $suggestions[0]->getResultsCount());
-+    $this->assertEquals('media franchise.', $suggestions[1]->getSuggestedKeys());
-+    $this->assertEquals(1, $suggestions[1]->getResultsCount());
-+    $this->assertEquals('media francia', $suggestions[2]->getSuggestedKeys());
-+    $this->assertEquals(1, $suggestions[2]->getResultsCount());
-+    $this->assertEquals('media francia.', $suggestions[3]->getSuggestedKeys());
-+    $this->assertEquals(1, $suggestions[3]->getResultsCount());
-+  }
-+
-+  /**
-+   * {@inheritdoc}
-+   */
-+  public function testBackend() {
-+    $this->testAutocomplete();
-+  }
-+
-+}
-diff --git a/search_api_solr.post_update.php b/search_api_solr.post_update.php
-index 6fc5906e..565726fe 100644
---- a/search_api_solr.post_update.php
-+++ b/search_api_solr.post_update.php
-@@ -51,3 +51,14 @@ function search_api_solr_post_update_8319() {
-   module_load_include('install', 'search_api_solr');
-   search_api_solr_update_helper_install_configs();
- }
-+
-+/**
-+ * Install new Search API Solr Autocomplete.
-+ */
-+function search_api_solr_post_update_8320(): void {
-+  if (\Drupal::moduleHandler()->moduleExists('search_api_autocomplete')) {
-+    /** @var \Drupal\Core\Extension\ModuleInstallerInterface $module_installer */
-+    $module_installer = \Drupal::service('module_installer');
-+    $module_installer->install(['search_api_solr_autocomplete']);
-+  }
-+}
-diff --git a/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php b/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php
-index 00233704..cbb48bf9 100644
---- a/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php
-+++ b/src/Plugin/search_api_autocomplete/suggester/BackendTrait.php
-@@ -2,43 +2,18 @@
- 
- namespace Drupal\search_api_solr\Plugin\search_api_autocomplete\suggester;
- 
--use Drupal\search_api\IndexInterface;
--use Drupal\search_api\LoggerTrait;
--use Drupal\search_api_solr\SolrAutocompleteInterface;
-+use Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\BackendTrait as BackendTraitOriginal;
-+
-+@trigger_error('The ' . __NAMESPACE__ . '\BackendTrait is deprecated in search_api_solr:4.3.0 and is removed from search_api_solr:5.0.0. Instead use \Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\BackendTrait. See https://www.drupal.org/node/3254186.', E_USER_DEPRECATED);
- 
- /**
-  * Provides a helper method for loading the search backend.
-+ *
-+ * @deprecated in search_api_solr:4.3.0 and is removed from search_api_solr:5.0.0. Use the
-+ *   \Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\BackendTrait instead
-+ *
-+ * @see https://www.drupal.org/node/3254186
-  */
- trait BackendTrait {
--
--  use LoggerTrait;
--
--  /**
--   * Retrieves the backend for the given index, if it supports autocomplete.
--   *
--   * @param \Drupal\search_api\IndexInterface $index
--   *   The search index.
--   *
--   * @return \Drupal\search_api_solr\SolrAutocompleteInterface|null
--   *   The backend plugin of the index's server, if it exists and supports
--   *   autocomplete; NULL otherwise.
--   */
--  protected static function getBackend(IndexInterface $index) {
--    try {
--      if (
--        $index->hasValidServer() &&
--        ($server = $index->getServerInstance()) &&
--        ($backend = $server->getBackend()) &&
--        $backend instanceof SolrAutocompleteInterface &&
--        $server->supportsFeature('search_api_autocomplete')
--      ) {
--        return $backend;
--      }
--    }
--    catch (\Exception $e) {
--      watchdog_exception('search_api', $e);
--    }
--    return NULL;
--  }
--
-+  use BackendTraitOriginal;
- }
-diff --git a/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php b/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php
-index 31018815..e01524ac 100644
---- a/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php
-+++ b/src/Plugin/search_api_autocomplete/suggester/Spellcheck.php
-@@ -2,12 +2,9 @@
- 
- namespace Drupal\search_api_solr\Plugin\search_api_autocomplete\suggester;
- 
--use Drupal\Core\Form\FormStateInterface;
--use Drupal\Core\Plugin\PluginFormInterface;
--use Drupal\search_api\Plugin\PluginFormTrait;
--use Drupal\search_api\Query\QueryInterface;
--use Drupal\search_api_autocomplete\SearchInterface;
--use Drupal\search_api_autocomplete\Suggester\SuggesterPluginBase;
-+use Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Spellcheck as SpellcheckOriginal;
-+
-+@trigger_error('The ' . __NAMESPACE__ . '\Spellcheck is deprecated in search_api_solr:4.3.0 and is removed from search_api_solr:5.0.0. Instead use \Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Spellcheck. See https://www.drupal.org/node/3254186.', E_USER_DEPRECATED);
- 
- /**
-  * Provides a suggester plugin that retrieves suggestions from the server.
-@@ -15,55 +12,9 @@ use Drupal\search_api_autocomplete\Suggester\SuggesterPluginBase;
-  * The server needs to support the "search_api_autocomplete" feature for this to
-  * work.
-  *
-- * @SearchApiAutocompleteSuggester(
-- *   id = "search_api_solr_spellcheck",
-- *   label = @Translation("Solr Spellcheck"),
-- *   description = @Translation("Suggest corrections for the entered words based on Solr's spellcheck component. Note: Be careful when activating this feature if you run multiple indexes in one Solr core! The spellcheck component is not able to distinguish between the different indexes and returns suggestions for the complete core. If you run multiple indexes in one core you might get suggestions that lead to zero results on a specific index!"),
-- * )
-+ * @deprecated in search_api_solr:4.3.0 and is removed from search_api_solr:5.0.0. Use the
-+ *   \Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Spellcheck instead
-+ *
-+ * @see https://www.drupal.org/node/3254186
-  */
--class Spellcheck extends SuggesterPluginBase implements PluginFormInterface {
--
--  use PluginFormTrait;
--  use BackendTrait;
--
--  /**
--   * {@inheritdoc}
--   *
--   * @throws \Drupal\search_api\SearchApiException
--   * @throws \Drupal\search_api_autocomplete\SearchApiAutocompleteException
--   */
--  public static function supportsSearch(SearchInterface $search) {
--    /** @var \Drupal\search_api_solr\SolrBackendInterface $backend */
--    $backend = static::getBackend($search->getIndex());
--    return ($backend && version_compare($backend->getSolrConnector()->getSolrMajorVersion(), '4', '>='));
--  }
--
--  /**
--   * {@inheritdoc}
--   */
--  public function defaultConfiguration() {
--    return [];
--  }
--
--  /**
--   * {@inheritdoc}
--   */
--  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
--    return [];
--  }
--
--  /**
--   * {@inheritdoc}
--   *
--   * @throws \Drupal\search_api\SearchApiException
--   * @throws \Drupal\search_api_autocomplete\SearchApiAutocompleteException
--   */
--  public function getAutocompleteSuggestions(QueryInterface $query, $incomplete_key, $user_input) {
--    if (!($backend = static::getBackend($this->getSearch()->getIndex()))) {
--      return [];
--    }
--
--    return $backend->getSpellcheckSuggestions($query, $this->getSearch(), $incomplete_key, $user_input);
--  }
--
--}
-+class Spellcheck extends SpellcheckOriginal {}
-diff --git a/src/Plugin/search_api_autocomplete/suggester/Suggester.php b/src/Plugin/search_api_autocomplete/suggester/Suggester.php
-index 46df04e8..a0ed8deb 100644
---- a/src/Plugin/search_api_autocomplete/suggester/Suggester.php
-+++ b/src/Plugin/search_api_autocomplete/suggester/Suggester.php
-@@ -2,14 +2,9 @@
- 
- namespace Drupal\search_api_solr\Plugin\search_api_autocomplete\suggester;
- 
--use Drupal\Core\Form\FormStateInterface;
--use Drupal\Core\Language\LanguageInterface;
--use Drupal\Core\Plugin\PluginFormInterface;
--use Drupal\search_api\Plugin\PluginFormTrait;
--use Drupal\search_api\Query\QueryInterface;
--use Drupal\search_api_autocomplete\SearchInterface;
--use Drupal\search_api_autocomplete\Suggester\SuggesterPluginBase;
--use Drupal\search_api_solr\Utility\Utility;
-+use Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Suggester as SuggesterOriginal;
-+
-+@trigger_error('The ' . __NAMESPACE__ . '\Suggester is deprecated in search_api_solr:4.3.0 and is removed from search_api_solr:5.0.0. Instead use \Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Suggester. See https://www.drupal.org/node/3254186.', E_USER_DEPRECATED);
- 
- /**
-  * Provides a suggester plugin that retrieves suggestions from the server.
-@@ -17,120 +12,9 @@ use Drupal\search_api_solr\Utility\Utility;
-  * The server needs to support the "search_api_autocomplete" feature for this to
-  * work.
-  *
-- * @SearchApiAutocompleteSuggester(
-- *   id = "search_api_solr_suggester",
-- *   label = @Translation("Solr Suggester"),
-- *   description = @Translation("Suggest complete phrases for the entered string based on Solr's suggest component."),
-- * )
-+ * @deprecated in search_api_solr:4.3.0 and is removed from search_api_solr:5.0.0. Use the
-+ *    \Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Suggester instead
-+ *
-+ * @see https://www.drupal.org/node/3254186
-  */
--class Suggester extends SuggesterPluginBase implements PluginFormInterface {
--
--  use PluginFormTrait;
--  use BackendTrait;
--
--  /**
--   * {@inheritdoc}
--   *
--   * @throws \Drupal\search_api\SearchApiException
--   * @throws \Drupal\search_api_autocomplete\SearchApiAutocompleteException
--   */
--  public static function supportsSearch(SearchInterface $search) {
--    /** @var \Drupal\search_api_solr\SolrBackendInterface $backend */
--    $backend = static::getBackend($search->getIndex());
--    return ($backend && version_compare($backend->getSolrConnector()->getSolrMajorVersion(), '6', '>='));
--  }
--
--  /**
--   * {@inheritdoc}
--   */
--  public function defaultConfiguration() {
--    return [
--      'search_api_solr/site_hash' => TRUE,
--      'search_api/index' => '',
--      'drupal/langcode' => 'any',
--    ];
--  }
--
--  /**
--   * {@inheritdoc}
--   *
--   * @throws \Drupal\search_api\SearchApiException
--   * @throws \Drupal\search_api_autocomplete\SearchApiAutocompleteException
--   */
--  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
--    $search = $this->getSearch();
--    $server = $search->getIndex()->getServerInstance();
--
--    $form['search_api_solr/site_hash'] = [
--      '#type' => 'checkbox',
--      '#title' => $this->t('From this site only'),
--      '#description' => $this->t('Limit the suggestion dictionary to entries created by this site in case of a multisite setup.'),
--      '#default_value' => $this->getConfiguration()['search_api_solr/site_hash'],
--    ];
--
--    $index_options['any'] = $this->t('Any index');
--    foreach ($server->getIndexes() as $index) {
--      $index_options[$index->id()] = $this->t('Index @index', ['@index' => $index->label()]);
--    }
--
--    $form['search_api/index'] = [
--      '#type' => 'radios',
--      '#title' => $this->t('Index'),
--      '#description' => $this->t('Limit the suggestion dictionary to entries to those created by a specific index.'),
--      '#options' => $index_options,
--      '#default_value' => $this->getConfiguration()['search_api/index'] ?: $search->getIndex()->id(),
--    ];
--
--    $langcode_options['any'] = $this->t('Any language');
--    $langcode_options['multilingual'] = $this->t('Let the Solr server handle it dynamically.');
--    foreach (\Drupal::languageManager()->getLanguages() as $language) {
--      $langcode_options[$language->getId()] = $language->getName();
--    }
--    $langcode_options[LanguageInterface::LANGCODE_NOT_SPECIFIED] = $this->t('Undefined');
--
--    $form['drupal/langcode'] = [
--      '#type' => 'radios',
--      '#title' => $this->t('Language'),
--      '#description' => $this->t('Limit the suggestion dictionary to entries that belong to a specific language.'),
--      '#options' => $langcode_options,
--      '#default_value' => $this->getConfiguration()['drupal/langcode'],
--    ];
--
--    return $form;
--  }
--
--  /**
--   * {@inheritdoc}
--   */
--  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
--    $values = $form_state->getValues();
--    $this->setConfiguration($values);
--  }
--
--  /**
--   * {@inheritdoc}
--   *
--   * @throws \Drupal\search_api\SearchApiException
--   * @throws \Drupal\search_api_autocomplete\SearchApiAutocompleteException
--   */
--  public function getAutocompleteSuggestions(QueryInterface $query, $incomplete_key, $user_input) {
--    if (!($backend = static::getBackend($this->getSearch()->getIndex()))) {
--      return [];
--    }
--
--    $config = $this->getConfiguration();
--    $options['context_filter_tags'] = [];
--    if ($config['search_api_solr/site_hash']) {
--      $options['context_filter_tags'][] = 'search_api_solr/site_hash:' . Utility::getSiteHash();
--    }
--    if (!empty($config['search_api/index']) && 'any' !== $config['search_api/index']) {
--      $options['context_filter_tags'][] = 'search_api/index:' . $config['search_api/index'];
--    }
--    if ('any' !== $config['drupal/langcode']) {
--      $options['context_filter_tags'][] = 'drupal/langcode:' . $config['drupal/langcode'];
--    }
--
--    return $backend->getSuggesterSuggestions($query, $this->getSearch(), $incomplete_key, $user_input, $options);
--  }
--
--}
-+class Suggester extends SuggesterOriginal {}
-diff --git a/src/Plugin/search_api_autocomplete/suggester/Terms.php b/src/Plugin/search_api_autocomplete/suggester/Terms.php
-index 315a9c92..c0cc07bc 100644
---- a/src/Plugin/search_api_autocomplete/suggester/Terms.php
-+++ b/src/Plugin/search_api_autocomplete/suggester/Terms.php
-@@ -2,41 +2,16 @@
- 
- namespace Drupal\search_api_solr\Plugin\search_api_autocomplete\suggester;
- 
--use Drupal\search_api\Query\QueryInterface;
--use Drupal\search_api_autocomplete\Plugin\search_api_autocomplete\suggester\Server;
-+use Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Terms as TermsOriginal;
-+
-+@trigger_error('The ' . __NAMESPACE__ . '\Terms is deprecated in search_api_solr:4.3.0 and is removed from search_api_solr:5.0.0. Instead use \Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Terms. See https://www.drupal.org/node/3254186.', E_USER_DEPRECATED);
- 
- /**
-  * Provides a suggester that retrieves suggestions from Solr's Terms component.
-  *
-- * @SearchApiAutocompleteSuggester(
-- *   id = "search_api_solr_terms",
-- *   label = @Translation("Solr Terms"),
-- *   description = @Translation("Autocomplete the entered string based on Solr's Terms component. Note: Be careful when activating this feature if you run multiple indexes in one Solr core! The Terms component is not able to distinguish between the different indexes and returns matching terms for the complete core. If you run multiple indexes in one core the term counts are not correct and you might get suggestions that lead to zero results on a specific index! You can mitigate that effect if you ensure that the fulltext field names are completely different in the indexes.")
-- * )
-+ * @deprecated in search_api_solr:4.3.0 and is removed from search_api_solr:5.0.0. Use the
-+ *    \Drupal\search_api_solr_autocomplete\Plugin\search_api_autocomplete\suggester\Terms instead
-+ *
-+ * @see https://www.drupal.org/node/3254186
-  */
--class Terms extends Server {
--
--  use BackendTrait;
--
--  /**
--   * {@inheritdoc}
--   *
--   * @throws \Drupal\search_api\SearchApiException
--   * @throws \Drupal\search_api_autocomplete\SearchApiAutocompleteException
--   */
--  public function getAutocompleteSuggestions(QueryInterface $query, $incomplete_key, $user_input) {
--    if (!($backend = static::getBackend($this->getSearch()->getIndex()))) {
--      return [];
--    }
--
--    if ($this->configuration['fields']) {
--      $query->setFulltextFields($this->configuration['fields']);
--    }
--    else {
--      $query->setFulltextFields($query->getIndex()->getFulltextFields());
--    }
--
--    return $backend->getAutocompleteSuggestions($query, $this->getSearch(), $incomplete_key, $user_input);
--  }
--
--}
-+class Terms extends TermsOriginal {}
-diff --git a/tests/src/Kernel/SearchApiSolrTest.php b/tests/src/Kernel/SearchApiSolrTest.php
-index d2ed4b2c..747d086d 100644
---- a/tests/src/Kernel/SearchApiSolrTest.php
-+++ b/tests/src/Kernel/SearchApiSolrTest.php
-@@ -9,7 +9,6 @@ use Drupal\search_api\Entity\Server;
- use Drupal\search_api\Query\QueryInterface;
- use Drupal\search_api\Query\ResultSetInterface;
- use Drupal\search_api\Utility\Utility;
--use Drupal\search_api_autocomplete\Entity\Search;
- use Drupal\search_api_solr\Controller\SolrConfigSetController;
- use Drupal\search_api_solr\SearchApiSolrException;
- use Drupal\search_api_solr\SolrBackendInterface;
-@@ -77,7 +76,6 @@ class SearchApiSolrTest extends SolrBackendTestBase {
-    */
-   public static $modules = [
-     'language',
--    'search_api_autocomplete',
-     'search_api_solr_legacy',
-     'user',
-   ];
-@@ -1085,146 +1083,6 @@ class SearchApiSolrTest extends SolrBackendTestBase {
-     $this->removeTestEntity(7);
-   }
- 
--  /**
--   * Tests the autocomplete support and ngram results.
--   */
--  public function testAutocompleteAndNgram() {
--    $this->addTestEntity(1, [
--      'name' => 'Test Article 1',
--      'body' => 'The test article number 1 about cats, dogs and trees.',
--      'type' => 'article',
--      'category' => 'dogs and trees',
--    ]);
--
--    // Add another node with body length equal to the limit.
--    $this->addTestEntity(2, [
--      'name' => 'Test Article 1',
--      'body' => 'The test article number 2 about a tree.',
--      'type' => 'article',
--      'category' => 'trees',
--    ]);
--
--    $this->indexItems($this->indexId);
--
--    /** @var \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend $backend */
--    $backend = Server::load($this->serverId)->getBackend();
--    $solr_major_version = $backend->getSolrConnector()->getSolrMajorVersion();
--    $autocompleteSearch = new Search([], 'search_api_autocomplete_search');
--
--    $query = $this->buildSearch(['artic'], [], ['body_unstemmed'], FALSE);
--    $query->setLanguages(['en']);
--    $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'artic', 'artic');
--    $this->assertEquals(1, count($suggestions));
--    $this->assertEquals('le', $suggestions[0]->getSuggestionSuffix());
--    $this->assertEquals(2, $suggestions[0]->getResultsCount());
--
--    $query = $this->buildSearch(['artic'], [], ['body'], FALSE);
--    $query->setLanguages(['en']);
--    $suggestions = $backend->getTermsSuggestions($query, $autocompleteSearch, 'artic', 'artic');
--    $this->assertEquals(1, count($suggestions));
--    // This time we test the stemmed token.
--    $this->assertEquals('l', $suggestions[0]->getSuggestionSuffix());
--    $this->assertEquals(2, $suggestions[0]->getResultsCount());
--
--    $targeted_branch = $backend->getSolrConnector()->getSchemaTargetedSolrBranch();
--    if ('4.x' !== $targeted_branch && '3.x' !== $targeted_branch) {
--      $query = $this->buildSearch(['articel'], [], ['body'], FALSE);
--      $query->setLanguages(['en']);
--      $suggestions = $backend->getSpellcheckSuggestions($query, $autocompleteSearch, 'articel', 'articel');
--      $this->assertEquals(1, count($suggestions));
--      $this->assertEquals('article', $suggestions[0]->getSuggestedKeys());
--      $this->assertEquals(0, $suggestions[0]->getResultsCount());
--    }
--
--    $query = $this->buildSearch(['article tre'], [], ['body_unstemmed'], FALSE);
--    $query->setLanguages(['en']);
--    $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'tre', 'article tre');
--    $this->assertEquals('article tree', $suggestions[0]->getSuggestedKeys());
--    $this->assertEquals(1, $suggestions[0]->getResultsCount());
--    // Having set preserveOriginal in WordDelimiter let punction remain.
--    $this->assertEquals('article tree.', $suggestions[1]->getSuggestedKeys());
--    $this->assertEquals(1, $suggestions[1]->getResultsCount());
--    $this->assertEquals('article trees', $suggestions[2]->getSuggestedKeys());
--    $this->assertEquals(1, $suggestions[2]->getResultsCount());
--    $this->assertEquals('article trees.', $suggestions[3]->getSuggestedKeys());
--    $this->assertEquals(1, $suggestions[3]->getResultsCount());
--
--    // @todo spellcheck tests
--    // @codingStandardsIgnoreStart
--    // $query = $this->buildSearch(['articel cats doks'], [], ['body'], FALSE);
--    // $query->setLanguages(['en']);
--    // $suggestions = $backend->getSpellcheckSuggestions($query, $autocompleteSearch, 'doks', 'articel doks');
--    // $this->assertEquals(1, count($suggestions));
--    // $this->assertEquals('article dogs', $suggestions[0]->getSuggestedKeys());
--
--    // $query = $this->buildSearch(['articel tre'], [], ['body'], FALSE);
--    // $query->setLanguages(['en']);
--    // $suggestions = $backend->getAutocompleteSuggestions($query, $autocompleteSearch, 'tre', 'articel tre');
--    // $this->assertEquals(5, count($suggestions));
--    // $this->assertEquals('e', $suggestions[0]->getSuggestionSuffix());
--    // $this->assertEquals(1, $suggestions[0]->getResultsCount());
--    // $this->assertEquals('es', $suggestions[1]->getSuggestionSuffix());
--    // @codingStandardsIgnoreEnd
--
--    if (version_compare($solr_major_version, '6', '>=')) {
--      // @todo Add more suggester tests.
--      $query = $this->buildSearch(['artic'], [], ['body'], FALSE);
--      $query->setLanguages(['en']);
--      $suggestions = $backend->getSuggesterSuggestions($query, $autocompleteSearch, 'artic', 'artic');
--      $this->assertEquals(2, count($suggestions));
--
--      // Since we don't specify the result weights explicitly for this suggester
--      // we need to deal with a random order and need predictable array keys.
--      foreach ($suggestions as $suggestion) {
--        $suggestions[$suggestion->getSuggestedKeys()] = $suggestion;
--      }
--      $this->assertEquals('artic', $suggestions['The test <b>artic</b>le number 1 about cats, dogs and trees.']->getUserInput());
--      $this->assertEquals('The test <b>', $suggestions['The test <b>artic</b>le number 1 about cats, dogs and trees.']->getSuggestionPrefix());
--      $this->assertEquals('</b>le number 1 about cats, dogs and trees.', $suggestions['The test <b>artic</b>le number 1 about cats, dogs and trees.']->getSuggestionSuffix());
--      $this->assertEquals('The test <b>artic</b>le number 1 about cats, dogs and trees.', $suggestions['The test <b>artic</b>le number 1 about cats, dogs and trees.']->getSuggestedKeys());
--
--      $this->assertEquals('artic', $suggestions['The test <b>artic</b>le number 2 about a tree.']->getUserInput());
--      $this->assertEquals('The test <b>', $suggestions['The test <b>artic</b>le number 2 about a tree.']->getSuggestionPrefix());
--      $this->assertEquals('</b>le number 2 about a tree.', $suggestions['The test <b>artic</b>le number 2 about a tree.']->getSuggestionSuffix());
--      $this->assertEquals('The test <b>artic</b>le number 2 about a tree.', $suggestions['The test <b>artic</b>le number 2 about a tree.']->getSuggestedKeys());
--    }
--
--    // Tests NGram and Edge NGram search result.
--    foreach (['category_ngram', 'category_edge'] as $field) {
--      $results = $this->buildSearch(['tre'], [], [$field])
--        ->execute();
--      $this->assertResults([1, 2], $results, $field . ': tre');
--
--      $results = $this->buildSearch(['Dog'], [], [$field])
--        ->execute();
--      $this->assertResults([1], $results, $field . ': Dog');
--
--      $results = $this->buildSearch([], [], [])
--        ->addCondition($field, 'Dog')
--        ->execute();
--      $this->assertResults([1], $results, $field . ': Dog as condition');
--    }
--
--    // Tests NGram search result.
--    $result_set = [
--      'category_ngram' => [1, 2],
--      'category_ngram_string' => [1, 2],
--      'category_edge' => [],
--      'category_edge_string' => [],
--    ];
--    foreach ($result_set as $field => $expected_results) {
--      $results = $this->buildSearch(['re'], [], [$field])
--        ->execute();
--      $this->assertResults($expected_results, $results, $field . ': re');
--    }
--
--    foreach (['category_ngram_string' => [1, 2], 'category_edge_string' => [2]] as $field => $expected_results) {
--      $results = $this->buildSearch(['tre'], [], [$field])
--        ->execute();
--      $this->assertResults($expected_results, $results, $field . ': tre');
--    }
--  }
--
-   /**
-    * Tests language fallback and language limiting via options.
-    */
diff --git a/scripts/composer/composer.php b/scripts/composer/composer.php
index 9b3308a4a86916f6fc366e0a6db907f23c5e6e4e..d6cb2a3506156f6f7f6b7d46588c39b59b55a5c7 100755
--- a/scripts/composer/composer.php
+++ b/scripts/composer/composer.php
@@ -15,11 +15,6 @@
   exit($exitCode++);
 }
 
-// Mute GrumPHP.
-if (file_exists("$projectRoot/vendor/bin/grumphp")) {
-  print execCmd("$projectRoot/vendor/bin/grumphp git:deinit") . "\n";
-}
-
 // Store the Joinup version.
 print "Detecting the Joinup version... ";
 if (execCmd('git rev-parse --is-shallow-repository') !== 'false') {
@@ -46,13 +41,12 @@
   print 'NPM ' . execCmd("npm --version") . "\n";
 
   // Theme dependencies.
-  $command = "cd $projectRoot/web/themes/ventuno && npm ci";
+  $command = "npm ci --prefix web/themes/ventuno";
   print "Running: $command\n";
   execCmd($command);
 
   // Project dependencies.
   $command = $argv[1] === 'install' ? 'npm ci' : 'npm install';
-  $command = "cd $projectRoot && $command";
   print "Running: $command\n";
   execCmd($command);
 }
diff --git a/tests/features/collection/collection.moderation.feature b/tests/features/collection/collection.moderation.feature
index 031e3a0eb2d444adf32065999a32b7b2825b3838..06a0af50a88fff0fea451459dbababe6c3228ec5 100644
--- a/tests/features/collection/collection.moderation.feature
+++ b/tests/features/collection/collection.moderation.feature
@@ -213,11 +213,7 @@ Feature: Collection moderation
     Given I am logged in as a user with the "authenticated" role
     # Propose a collection, filling in the required fields.
     When I go to the propose collection form
-    Then the "Main fields" accordion item should be active
-    # @todo The summaries are no longer visible since we migrated to Drupal 9.
-    #   Restore these when ISAICP-6963 is fixed.
-    # And the "Main fields" tab summary should be "Contains all the fields to be mandatorily filled to create a collection"
-    # And the "Additional fields" tab summary should be "Contains all optional fields providing additional information on the collection"
+    Then the "Main fields" accordion section should be active
     And I fill in the following:
       | Title  | Spectres in fog        |
       # Contact information data.
@@ -229,8 +225,8 @@ Feature: Collection moderation
     And I wait for AJAX to finish
     And I fill in "Name" with "Katsumoto"
     And I check the box "Academia/Scientific organisation"
-    And I press "Additional fields"
-    Then the "Additional fields" accordion item should be active
+    And I expand the "Additional fields" accordion section
+    Then the "Additional fields" accordion section should be active
     And I attach the file "logo.png" to "Logo"
     And I wait for AJAX to finish
     And I attach the file "banner.jpg" to "Banner"
@@ -254,15 +250,14 @@ Feature: Collection moderation
     And I go to the homepage of the "Spectres in fog" collection
     And I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     Then the radio button "Any user can create content." from field "Content creation" should be selected
     # Also when saving and reopening the edit form the content creation option
     # should remain unchanged.
     When I press "Publish"
     And I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Main fields"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     Then the radio button "Any user can create content." from field "Content creation" should be selected
 
     # Clean up the entities that were created.
@@ -291,7 +286,7 @@ Feature: Collection moderation
     And I wait for AJAX to finish
     And I fill in "Name" with "Garnett Clifton"
     And I check the box "Supra-national authority"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I attach the file "logo.png" to "Logo"
     And I wait for AJAX to finish
     And I attach the file "banner.jpg" to "Banner"
@@ -304,8 +299,7 @@ Feature: Collection moderation
     # Edit again.
     When I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Main fields"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     Then the radio button "Any user can create content." from field "Content creation" should be selected
 
     # Clean up the entities that were created.
@@ -334,7 +328,7 @@ Feature: Collection moderation
     And I wait for AJAX to finish
     And I fill in "Name" with "Coretta Simonson"
     And I check the box "Private Individual(s)"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I attach the file "logo.png" to "Logo"
     And I wait for AJAX to finish
     And I attach the file "banner.jpg" to "Banner"
@@ -347,8 +341,7 @@ Feature: Collection moderation
     # Edit again.
     When I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Main fields"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     Then the radio button "Only facilitators and authors can create content." from field "Content creation" should be selected
 
     # Clean up the entities that were created.
@@ -378,7 +371,7 @@ Feature: Collection moderation
     And I wait for AJAX to finish
     And I fill in "Name" with "Terrance Nash"
     And I check the box "Regional authority"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I attach the file "logo.png" to "Logo"
     And I wait for AJAX to finish
     And I attach the file "banner.jpg" to "Banner"
@@ -393,8 +386,7 @@ Feature: Collection moderation
     # Edit again.
     When I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Main fields"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     Then the radio button "Only facilitators and authors can create content." from field "Content creation" should be selected
 
     # Clean up the entities that were created.
@@ -423,7 +415,7 @@ Feature: Collection moderation
     And I wait for AJAX to finish
     And I fill in "Name" with "Mable Pelley"
     And I check the box "National authority"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I attach the file "logo.png" to "Logo"
     And I wait for AJAX to finish
     And I attach the file "banner.jpg" to "Banner"
@@ -439,8 +431,7 @@ Feature: Collection moderation
     # Edit again.
     When I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Main fields"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     Then the radio button "Only facilitators and authors can create content." from field "Content creation" should be selected
 
     # Clean up the entities that were created.
diff --git a/tests/features/collection/newsletter_subscription.feature b/tests/features/collection/newsletter_subscription.feature
index c03500cd5c9ce1bfdd5ebeba54f931af8f458222..2034dcad19bf2ec090301a75d991174e9c39c5c6 100644
--- a/tests/features/collection/newsletter_subscription.feature
+++ b/tests/features/collection/newsletter_subscription.feature
@@ -92,7 +92,7 @@ Feature: Subscribing to collection newsletters
     When I go to the "Volkor X" collection
     And I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    Then I press "Additional fields"
+    Then I expand the "Additional fields" accordion section
     And I check "Enable newsletter subscriptions"
     And I fill in "Universe acronym" with "volkor-x"
     And I fill in "Newsletter service ID" with "123"
diff --git a/tests/features/collection/propose.feature b/tests/features/collection/propose.feature
index d0674d19d8f5d706c6a5d203bd37233c246e29dd..03786f2d68e3c2cc0ac637d59352c4caa0389156 100644
--- a/tests/features/collection/propose.feature
+++ b/tests/features/collection/propose.feature
@@ -125,7 +125,7 @@ Feature: Proposing a collection
   Scenario: Content creation options should not vanish after AJAX request.
     Given I am logged in as a user with the "authenticated" role
     When I go to the propose collection form
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I attach the file "banner.jpg" to "Banner"
     And I wait for AJAX to finish
     Then I should see the link "banner.jpg"
@@ -159,8 +159,8 @@ Feature: Proposing a collection
     And I press "Create contact information"
 
     # Close "Main fields" to check its fields visibility.
-    When I press "Main fields"
-    And I press "Additional fields"
+    When I expand the "Additional fields" accordion section
+    And I collapse the "Main fields" accordion section
     Then the following fields should not be visible "Title, Description, Topic"
     And the following field widgets should not be visible "Owner"
     And the following fields should be visible "Content creation, Moderated, Abstract, Geographical coverage"
@@ -180,7 +180,7 @@ Feature: Proposing a collection
     And the "Just a proposal" collection banner is image #8
 
     Given I go to the edit form of the "Just a proposal" collection
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I remove the file from the "Logo" field
     But I wait for AJAX to finish
 
@@ -190,7 +190,7 @@ Feature: Proposing a collection
     And I press "Propose"
 
     When I go to the edit form of the "Just a proposal" collection
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     Then I should see the link "logo.png"
 
     # As some entities were created via UI, we should explicitly delete them.
@@ -206,15 +206,14 @@ Feature: Proposing a collection
   Scenario: Browser validation errors should focus the correct field group.
     Given I am logged in as an "authenticated user"
     When I go to the propose collection form
-    Then the "Main fields" accordion item should be active
+    Then the "Main fields" accordion section should be active
     # This form has two elements only that have browser-side validation.
     When I fill in "Title" with "Constraint validation API"
-    And I press "Main fields"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I press "Propose"
     # Our code should have changed the active accordion item now. A browser message will
     # be shown to the user.
-    Then the "Main fields" accordion item should be active
+    Then the "Main fields" accordion section should be active
     # Fill the required fields.
     When I select "HR" from "Topic"
     And I fill in the following:
diff --git a/tests/features/error.feature b/tests/features/error.feature
index f5cb762af14b13321c2091672195e2b11fbd69a7..e05ebcdb1d4539f16f08c9ce0d06c404f168b8cf 100644
--- a/tests/features/error.feature
+++ b/tests/features/error.feature
@@ -115,7 +115,7 @@ Feature: On errors I want to see a friendly page and be able to report an
       | There was an unexpected problem serving your request.            |
       | Please try again and contact us if the problem persist including |
       | in your message.                                                 |
-    And I should see "Notice: Undefined variable: not_initialised_variable in Drupal\error_page_test\Controller\ErrorPageTestController->notice()"
+    And I should see "Warning: Undefined variable $not_initialised_variable in Drupal\error_page_test\Controller\ErrorPageTestController->notice()"
     And the response should not contain "<pre class=\"backtrace\">"
 
     # Error level: verbose.
@@ -152,5 +152,5 @@ Feature: On errors I want to see a friendly page and be able to report an
       | There was an unexpected problem serving your request.            |
       | Please try again and contact us if the problem persist including |
       | in your message.                                                 |
-    And I should see "Notice: Undefined variable: not_initialised_variable in Drupal\error_page_test\Controller\ErrorPageTestController->notice()"
+    And I should see "Warning: Undefined variable $not_initialised_variable in Drupal\error_page_test\Controller\ErrorPageTestController->notice()"
     And the response should contain "<pre class=\"backtrace\">"
diff --git a/tests/features/file_url/widget-ui.feature b/tests/features/file_url/widget-ui.feature
index d3598853af43f838c98ab01c2b8a798da0fa7122..3ddfaffc3cba8c202d325226597b6f5f5464c44a 100644
--- a/tests/features/file_url/widget-ui.feature
+++ b/tests/features/file_url/widget-ui.feature
@@ -23,7 +23,7 @@ Feature: User interface for the File URL field
     But the following fields should not be visible "Choose a file,Remote URL"
     And I should not see the text "Allowed types: txt doc docx pdf."
     And I should not see the description "This must be an external URL such as http://example.com." for "Upload a new file or enter a URL"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     # Try to upload a file.
     Given I select the radio button "Upload file"
     Then the following field should be visible "Choose a file"
diff --git a/tests/features/joinup_document/document.moderation.feature b/tests/features/joinup_document/document.moderation.feature
index 7764b9da341a6fcbc3e8b1b751847a868202eb91..3dce276912ac304d824f6b3155d907a28584c579 100644
--- a/tests/features/joinup_document/document.moderation.feature
+++ b/tests/features/joinup_document/document.moderation.feature
@@ -47,8 +47,8 @@ Feature: Document moderation
     And I go to the homepage of the "The Naked Ashes" collection
     And I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Additional fields"
-    And I check the box "Moderated"
+    And I expand the "Additional fields" accordion section
+    And I check "Moderated"
     Then I press "Publish"
     And I should see the heading "The Naked Ashes"
 
@@ -67,8 +67,7 @@ Feature: Document moderation
     And I go to the homepage of the "The Naked Ashes" collection
     And I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Main fields"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I select the radio button "Only members can create content."
     And I press "Publish"
     # I should now have the possibility to add documents.
diff --git a/tests/features/joinup_event/event.moderation.feature b/tests/features/joinup_event/event.moderation.feature
index 55471d822df426221c6841c1729e8b9407e6bf89..bed28b8f98dde66b1be7f13584f683427ce06bf7 100644
--- a/tests/features/joinup_event/event.moderation.feature
+++ b/tests/features/joinup_event/event.moderation.feature
@@ -48,8 +48,8 @@ Feature: Event moderation
     And I go to the homepage of the "Wet Lords" collection
     And I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Additional fields"
-    And I check the box "Moderated"
+    And I expand the "Additional fields" accordion section
+    And I check "Moderated"
     Then I press "Publish"
     And I should see the heading "Wet Lords"
 
@@ -68,7 +68,7 @@ Feature: Event moderation
     And I go to the homepage of the "Wet Lords" collection
     And I open the header local tasks menu
     And I click "Edit" in the "Entity actions" region
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I check "Closed collection"
     And I wait for AJAX to finish
     And I select the radio button "Only members can create content."
diff --git a/tests/features/solution/add_solution.feature b/tests/features/solution/add_solution.feature
index b41bc3bea6117373af980f9964d1fd57088cccda..a5d43337c3a9aaafa0b5e0ec5f53159ab550a6a6 100644
--- a/tests/features/solution/add_solution.feature
+++ b/tests/features/solution/add_solution.feature
@@ -298,8 +298,7 @@ Feature: "Add solution" visibility options.
 
     Given I am logged in as a moderator
     When I go to the edit form of the "Cleaning solution" solution
-    And I press "Main fields"
-    When I press "Additional fields"
+    When I expand the "Additional fields" accordion section
     And  I remove the first file from "Logo"
     And I wait for AJAX to finish
     Then  I remove the first file from "Banner"
diff --git a/tests/features/solution/related_solution.feature b/tests/features/solution/related_solution.feature
index ba7abf20271a3c2ec3702bb898195a21dd6f3c23..1bae56a4c60984fc49db935eb0860b2a6ec303cc 100644
--- a/tests/features/solution/related_solution.feature
+++ b/tests/features/solution/related_solution.feature
@@ -69,8 +69,7 @@ Feature: Related solution
       | PHP  |
 
     When I go to the edit form of the "Javascript" solution
-    And I press "Main fields"
-    And I press "Additional fields"
+    And I expand the "Additional fields" accordion section
     And I drag the table row in the "Related solutions" region at position 2 up
     And I press "Publish"
     Then I should see the heading "Javascript"
diff --git a/tests/features/solution/solution.edit.feature b/tests/features/solution/solution.edit.feature
index 557f8f5976f64e08f648e56c4b1004a7ea46addf..5f6bd289c53fa9c5afb4acece6d76fa98d14001d 100644
--- a/tests/features/solution/solution.edit.feature
+++ b/tests/features/solution/solution.edit.feature
@@ -107,20 +107,3 @@ Feature: Solution editing.
     Then I should not see the link "Edit"
     When I go to the edit form of the "Another solution" solution
     Then I should get an access denied error
-
-  @javascript
-  Scenario: Test solution edit form vertical tabs.
-    When I am logged in as "Yancy Burton"
-    And I go to the homepage of the "Collection example" collection
-    And I click "Add solution" in the plus button menu
-    And I check the "I have read and accept the legal notice and I commit to manage my solution on a regular basis." material checkbox
-    And I press "Yes"
-    Then I should see the heading "Add Solution"
-    And the "Main fields" accordion item should be active
-    # @todo The summaries are no longer visible since we migrated to Drupal 9.
-    #   Restore these when ISAICP-6963 is fixed.
-    # And the "Main fields" tab summary should be "Contains all the fields to be mandatorily filled to create a solution"
-    # And the "Additional fields" tab summary should be "Contains all optional fields providing additional information on the solution"
-    And I press "Main fields"
-    And I press "Additional fields"
-    Then the "Additional fields" accordion item should be active
diff --git a/tests/src/Context/AccordionContext.php b/tests/src/Context/AccordionContext.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e738bf00cdc3d77d6876d6bfb6bb6616e4a3b6b
--- /dev/null
+++ b/tests/src/Context/AccordionContext.php
@@ -0,0 +1,132 @@
+<?php
+
+declare(strict_types = 1);
+
+namespace Drupal\joinup\Context;
+
+use Behat\Mink\Element\NodeElement;
+use Behat\Mink\Exception\ElementNotFoundException;
+use Drupal\DrupalExtension\Context\RawDrupalContext;
+use Drupal\joinup\Traits\JavascriptTrait;
+use Drupal\joinup\Traits\UtilityTrait;
+
+/**
+ * Behat step definitions for testing the accordion widget.
+ */
+class AccordionContext extends RawDrupalContext {
+
+  use JavascriptTrait;
+  use UtilityTrait;
+
+  /**
+   * Expands an accordion section.
+   *
+   * @param string $section
+   *   The accordion sections label.
+   *
+   * @throws \Behat\Mink\Exception\ElementNotFoundException
+   *   When there's no accordion section with the given label.
+   *
+   * @When I expand the :section accordion section
+   */
+  public function iExpandAccordionSection(string $section): void {
+    $this->toggleAccordionSection($section, TRUE);
+  }
+
+  /**
+   * Collapses an accordion section.
+   *
+   * @param string $section
+   *   The accordion sections label.
+   *
+   * @throws \Behat\Mink\Exception\ElementNotFoundException
+   *   When there's no accordion section with the given label.
+   *
+   * @When I collapse the :section accordion section
+   */
+  public function iCollapseAccordionSection(string $section): void {
+    $this->toggleAccordionSection($section, FALSE);
+  }
+
+  /**
+   * Toggles an accordion section by clicking its title.
+   *
+   * @param string $section
+   *   The accordion section title.
+   * @param bool $expand
+   *   The action: TRUE when expanding, FALS when collapsing.
+   *
+   * @throws \Behat\Mink\Exception\ElementNotFoundException
+   *   When the accordion section with the given label was not found.
+   */
+  protected function toggleAccordionSection(string $section, bool $expand): void {
+    if (!$this->hasJavascriptSupport()) {
+      return;
+    }
+
+    $session = $this->getSession();
+    $page = $session->getPage();
+    if (!$button = $page->findButton($section)) {
+      throw new ElementNotFoundException($session->getDriver(), 'button', 'label', $section);
+    }
+
+    if ($expand xor $button->hasClass('collapsed')) {
+      $state = $expand ? 'expanded' : 'collapsed';
+      throw new \Exception("The '$section' accordion section is already $state");
+    }
+
+    $this->scrollElementIntoView($button);
+    $button->press();
+    // @todo Disable animations and perform an instant expand/collapse.
+    $this->waitUntil(function () use ($button, $expand): bool {
+      return $expand xor $button->hasClass('collapsed');
+    });
+    sleep(1);
+  }
+
+  /**
+   * Asserts that an accordion section is active.
+   *
+   * @param string $section
+   *   The accordion section title.
+   *
+   * @throws \Exception
+   *   When the accordion section is not found on the page or it's not active.
+   *
+   * @Then the :section accordion section should be active
+   */
+  public function assertAccordionSectionActive(string $section): void {
+    if ($this->findAccordionSection($section)->hasClass('collapsed')) {
+      throw new \Exception("The accordion section '$section' is not active.");
+    }
+  }
+
+  /**
+   * Finds an accordion section by its title.
+   *
+   * @param string $section
+   *   The title of the accordion secion.
+   *
+   * @return \Behat\Mink\Element\NodeElement
+   *   The accordion section element.
+   *
+   * @throws \Exception
+   *   Thrown when no section element is found.
+   */
+  protected function findAccordionSection(string $section): NodeElement {
+    // Xpath to find the accordion item.
+    $xpath = "//div[@class and contains(concat(' ', normalize-space(@class), ' '), ' accordion-item ')]";
+    // Filter down to the accordion section containing a button with the
+    // provided text.
+    $xpath .= "[.//h2[@class and contains(concat(' ', normalize-space(@class), ' '), ' accordion-header ')]/button[@class and contains(concat(' ', normalize-space(@class), ' '), ' accordion-button ')]"
+      . "[normalize-space(string(.)) = '$section']]";
+    $element = $this->getSession()->getPage()->find('xpath', $xpath);
+
+    if ($element === NULL) {
+      throw new \Exception('Accordion item not found: ' . $section);
+    }
+
+    return $element;
+  }
+
+}
diff --git a/tests/src/Context/BootstrapContext.php b/tests/src/Context/BootstrapContext.php
index a045ed56beaaec4e7216f6dea0d42202b1c37a27..1befd07545317f58e04e307630e1dced7267ef2b 100644
--- a/tests/src/Context/BootstrapContext.php
+++ b/tests/src/Context/BootstrapContext.php
@@ -5,14 +5,14 @@
 namespace Drupal\joinup\Context;
 
 use Drupal\DrupalExtension\Context\RawDrupalContext;
-use Drupal\joinup\Traits\BrowserCapabilityDetectionTrait;
+use Drupal\joinup\Traits\JavascriptTrait;
 
 /**
  * Step definitions for interacting with pages using the Bootstrap framework.
  */
 class BootstrapContext extends RawDrupalContext {
 
-  use BrowserCapabilityDetectionTrait;
+  use JavascriptTrait;
 
   /**
    * Some common screen resolutions, mapped on Bootstrap breakpoints.
diff --git a/tests/src/Context/EuplContext.php b/tests/src/Context/EuplContext.php
index 55c4594087d3ab98615252c759a19459bd0155a7..77c45686c36e96b38f8077bd9d72960f43906a24 100644
--- a/tests/src/Context/EuplContext.php
+++ b/tests/src/Context/EuplContext.php
@@ -263,7 +263,7 @@ public function selectRadioButtonForLicenceCompatibilityCheck(string $spdx_id, s
   public function clickLicenceTileLink(string $link, string $spdx_id): void {
     $licence = $this->findLicenceTile($spdx_id);
 
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       // On JS enabled browsers, scroll to the top before clicking the link
       // since it might be obscured by the floating header.
       $this->scrollToTop();
diff --git a/tests/src/Context/FeatureContext.php b/tests/src/Context/FeatureContext.php
index b045701046b8c76fba4ec4af5774c48566e0a505..018616107b3c0db10a79c73f332cfb07c7e4fa1e 100644
--- a/tests/src/Context/FeatureContext.php
+++ b/tests/src/Context/FeatureContext.php
@@ -22,8 +22,6 @@
 use Drupal\image\Plugin\Field\FieldType\ImageItem;
 use Drupal\joinup\HtmlManipulator;
 use Drupal\joinup\Traits\AntibotTrait;
-use Drupal\joinup\Traits\BrowserCapabilityDetectionTrait;
-use Drupal\joinup\Traits\BrowserWindowTrait;
 use Drupal\joinup\Traits\ContextualLinksTrait;
 use Drupal\joinup\Traits\EntityTrait;
 use Drupal\joinup\Traits\JavascriptTrait;
@@ -49,8 +47,6 @@
 class FeatureContext extends RawDrupalContext implements SnippetAcceptingContext {
 
   use AntibotTrait;
-  use BrowserCapabilityDetectionTrait;
-  use BrowserWindowTrait;
   use ContextualLinksTrait;
   use EntityTrait;
   use JavascriptTrait;
@@ -902,8 +898,8 @@ public function assertElementVisibleInRegion(string $locator, string $element, s
    */
   public function clickVerticalTabLink(string $tab): void {
     // When this is running in a browser without JavaScript the vertical tabs
-    // are rendered as a details element.
-    if (!$this->browserSupportsJavaScript()) {
+    // are rendered as detail elements.
+    if (!$this->hasJavascriptSupport()) {
       return;
     }
 
@@ -911,25 +907,6 @@ public function clickVerticalTabLink(string $tab): void {
     $this->findVerticalTab($tab)->clickLink($tab);
   }
 
-  /**
-   * Asserts that an accordion item is active.
-   *
-   * @param string $item
-   *   The accordion item title.
-   *
-   * @throws \Exception
-   *   When the accordion item is not found on the page or it's not active.
-   *
-   * @Then the :item accordion item should be active
-   */
-  public function assertAccordionItemActive(string $item): void {
-    $element = $this->findAccordionItem($item);
-
-    if ($element->hasClass('collapsed')) {
-      throw new \Exception("The accordion item '$item' is not active.");
-    }
-  }
-
   /**
    * Creates testing terms for scenarios tagged with @terms tag.
    *
diff --git a/tests/src/Context/JoinupContext.php b/tests/src/Context/JoinupContext.php
index 0add6f8a9a700237a0cb113052b970bf52add8b0..1cd0031ee98af48b7a8bef5b6e9e180d67d7e6e4 100644
--- a/tests/src/Context/JoinupContext.php
+++ b/tests/src/Context/JoinupContext.php
@@ -27,6 +27,7 @@
 use Drupal\joinup\Traits\MaterialDesignTrait;
 use Drupal\joinup\Traits\OgTrait;
 use Drupal\joinup\Traits\TabledragTrait;
+use Drupal\joinup\Traits\TestingEntitiesTrait;
 use Drupal\joinup\Traits\TraversingTrait;
 use Drupal\joinup\Traits\UserTrait;
 use Drupal\joinup\Traits\UtilityTrait;
@@ -63,6 +64,7 @@ class JoinupContext extends RawDrupalContext {
   use OgTrait;
   use StringTranslationTrait;
   use TabledragTrait;
+  use TestingEntitiesTrait;
   use TraversingTrait;
   use UserTrait;
   use UtilityTrait;
@@ -1570,7 +1572,7 @@ public function iOpenTheMdlDropdown() {
   public function iOpenTheAccountMenu() {
     // Non-JS browsers are directly interacting with the HTML, so we consider
     // the account menu to be already open.
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       return;
     }
 
@@ -1613,7 +1615,7 @@ public function relativeUrlMatches($url) {
    * @When the plus button menu should be empty
    */
   public function assertEmptyPlusButtonMenu() {
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       if ($this->getSession()->getPage()->findAll('xpath', '//div[contains(concat(" ", normalize-space(@class), " "), " add-content-menu ")]//li[last()]')) {
         throw new \Exception("The plus button menu is not empty.");
       }
@@ -1690,6 +1692,7 @@ public function createComments(TableNode $table) {
         'field_name' => $field_name,
         'entity_type' => 'node',
         'entity_id' => $id,
+        'subject' => $this->getRandom()->string(),
       ];
       $comment_values += $values;
       $comment = Comment::create($comment_values);
@@ -1703,7 +1706,9 @@ public function createComments(TableNode $table) {
         $comment->setCreatedTime($comment_values['created']);
       }
 
+      $comment->skip_notification = TRUE;
       $comment->save();
+      $this->entities['comment'][$comment->id()] = $comment;
     }
   }
 
@@ -2201,7 +2206,7 @@ public function assertLinkHref(string $link, string $expected_href): void {
    * @When I pick :value from the autocomplete suggestions
    */
   public function fillFieldWithNormalisedEntityReference(string $value, ?string $field = NULL): void {
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $session = $this->getSession();
       $xpath = '//ul[contains(concat(" ", normalize-space(@class), " "), " ui-autocomplete ")]//a[text() = "' . $value . '"]';
       $element = $session->getPage()->find('xpath', $xpath);
@@ -2511,7 +2516,7 @@ public function assertTourNotAvailable() {
    * @When I hit|press the :key key in the :field field
    */
   public function pressKeyInField(string $key, string $field): void {
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       throw new \Exception('This step requires JavaScript to run.');
     }
 
diff --git a/tests/src/Context/JoinupCoreContext.php b/tests/src/Context/JoinupCoreContext.php
index 7cf4d917e9e74c628ac525e4eb869c8b37ea11ea..ddab206840b9d723ecbe723774a559151028f80b 100644
--- a/tests/src/Context/JoinupCoreContext.php
+++ b/tests/src/Context/JoinupCoreContext.php
@@ -8,8 +8,8 @@
 use Behat\Testwork\Hook\Scope\BeforeSuiteScope;
 use Drupal\DrupalExtension\Context\RawDrupalContext;
 use Drupal\joinup\Chip;
-use Drupal\joinup\Traits\BrowserCapabilityDetectionTrait;
 use Drupal\joinup\Traits\EntityTrait;
+use Drupal\joinup\Traits\JavascriptTrait;
 use Drupal\joinup\Traits\TraversingTrait;
 use Drupal\joinup\Traits\UtilityTrait;
 use PHPUnit\Framework\Assert;
@@ -19,7 +19,7 @@
  */
 class JoinupCoreContext extends RawDrupalContext {
 
-  use BrowserCapabilityDetectionTrait;
+  use JavascriptTrait;
   use EntityTrait;
   use TraversingTrait;
   use UtilityTrait;
@@ -126,7 +126,7 @@ protected function getChips(?string $region = NULL): array {
     $locator_visibility_mapping = [
       '.mdl-chip__text, .navbar-search .badge' => TRUE,
     ];
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       $locator_visibility_mapping['.mdl-chipfield__input'] = FALSE;
     }
     foreach ($locator_visibility_mapping as $locator => $is_visible) {
diff --git a/tests/src/Context/JoinupParagraphsContext.php b/tests/src/Context/JoinupParagraphsContext.php
index 2c8cda0bcc791946bdd01b53e41a1be8b2c92161..e6321ff438fdfea2329956c630e0ca8e52047071 100644
--- a/tests/src/Context/JoinupParagraphsContext.php
+++ b/tests/src/Context/JoinupParagraphsContext.php
@@ -68,7 +68,7 @@ public function enterTextInWysiwyg(string $text, string $label, string $field, i
     // If we are running in a JavaScript enabled browser, first click the
     // 'Source' button so we can enter the text as HTML and get the same result
     // as in a non-JS browser.
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $this->pressWysiwygButton($label, 'Source', $field);
       $this->setWysiwygText($label, $text, $field);
     }
@@ -141,7 +141,7 @@ public function enterWysywigInRawOrder(string $text, string $position, string $l
     // Ascend twice so that the label of the field is also included and can be
     // found by xpath search properly.
     $region = $wysiwygs[$position]->getParent()->getParent();
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $this->pressWysiwygButton($label, 'Source', $region);
       $this->setWysiwygText($label, $text, $region);
     }
diff --git a/tests/src/Context/JoinupSearchContext.php b/tests/src/Context/JoinupSearchContext.php
index 26c5cd7bcf4c37fe2014cb2bc6e212fbb59c5b7e..2e270db45469cd5e7e0dcc1f894c250575758967 100644
--- a/tests/src/Context/JoinupSearchContext.php
+++ b/tests/src/Context/JoinupSearchContext.php
@@ -127,7 +127,7 @@ public function assertContentTypeFacetSelected(string $type): void {
    * @Then the :bundle content checkbox item should be selected
    */
   public function assertContentFacetCheckboxSelected(string $bundle): void {
-    if ($this->browserSupportsJavascript()) {
+    if ($this->hasJavascriptSupport()) {
       // The following xpath searches for
       // * Any div
       // ** that has a class named facets-widget-checkbox
@@ -275,12 +275,12 @@ public function assertSelectFacetOptionSelected(string $option, string $select):
     // list of links by the Facets module which is ultimately converted into a
     // select list using JavaScript.
     // @see https://www.drupal.org/project/facets/issues/2937191
-    $html_tag = $this->browserSupportsJavaScript() ? 'select' : 'ul';
+    $html_tag = $this->hasJavascriptSupport() ? 'select' : 'ul';
     $element = $this->findFacetByAlias($select, NULL, $html_tag);
     if (!$element) {
       throw new \Exception(sprintf('The select "%s" was not found in the page %s', $select, $this->getSession()->getCurrentUrl()));
     }
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $this->assertSelectedOption($element, $option);
     }
     else {
@@ -314,7 +314,7 @@ public function assertSelectFacetFormOptionSelected(string $option, string $sele
     if (!$element) {
       throw new \Exception(sprintf('The select "%s" was not found in the page %s', $select, $this->getSession()->getCurrentUrl()));
     }
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $this->assertSelectedOption($element, $option);
     }
     else {
@@ -538,7 +538,7 @@ public function assertNumberOfTopicsInCards(int $number, string $heading): void
    */
   protected function openFacetDropdown(NodeElement $facet): void {
     // Only needed when running in a JS enabled browser.
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       // Only open the dropdown if it is not already open.
       if (!$this->isFacetDropdownVisible($facet)) {
         // Click the arrow down button and wait for the animation to finish.
@@ -638,7 +638,7 @@ public function assertInlineFacetInactiveItems(string $facet, TableNode $values)
   public function assertCheckboxFacetItems(string $facet, string $values): void {
     $element = $this->findFacetByAlias($facet);
 
-    $css = $this->browserSupportsJavaScript() ? 'li.facet-item label' : 'li.facet-item';
+    $css = $this->hasJavascriptSupport() ? 'li.facet-item label' : 'li.facet-item';
     $found = array_map(function (NodeElement $item) {
       $text = $item->getText();
       // If a value is selected, it is prefixed with a '(-) ' in the text. Clean
@@ -680,7 +680,7 @@ public function enterSearchKeywords(string $keywords): void {
    * @When I enter :keywords in the search bar and press enter
    */
   public function launchSearchFromHeader(string $keywords): void {
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $element = $this->getSearchBarElement();
       $element->setValue($keywords);
       $this->submitSearch();
@@ -974,7 +974,7 @@ public function assertSearchBarHeader(): void {
   public function assertSearchToggleIconNavbar(): void {
     // Non-JS browsers are directly interacting with the HTML, so we consider
     // the account menu to be already open.
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       return;
     }
 
diff --git a/tests/src/Context/MinkContext.php b/tests/src/Context/MinkContext.php
index cd81ec07998badfcbdc649001161fc3aaa81f905..8a089a89122bc11833f0e636031e3c5a146eba70 100644
--- a/tests/src/Context/MinkContext.php
+++ b/tests/src/Context/MinkContext.php
@@ -66,7 +66,7 @@ public function assertCheckboxChecked($radio) {
   public function assertPageNotContainsText($text) {
     // When running in a JS enabled browser, check that the text is not visually
     // visible.
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $xpath = '//*[text()[contains(.,"' . $text . '")]]';
       foreach ($this->getSession()->getPage()->findAll('xpath', $xpath) as $element) {
         if ($element->isVisible()) {
diff --git a/tests/src/Context/WysiwygContext.php b/tests/src/Context/WysiwygContext.php
index 5386250a5732945971e9a8726424d27978a943aa..7a6a8f95aa8a5affdacb3319e538e0b2a0ca5726 100644
--- a/tests/src/Context/WysiwygContext.php
+++ b/tests/src/Context/WysiwygContext.php
@@ -5,8 +5,7 @@
 namespace Drupal\joinup\Context;
 
 use Drupal\DrupalExtension\Context\RawDrupalContext;
-use Drupal\joinup\Traits\BrowserCapabilityDetectionTrait;
-use Drupal\joinup\Traits\BrowserWindowTrait;
+use Drupal\joinup\Traits\JavascriptTrait;
 use Drupal\joinup\Traits\UtilityTrait;
 use Drupal\joinup\Traits\WysiwygTrait;
 use PHPUnit\Framework\Assert;
@@ -16,8 +15,7 @@
  */
 class WysiwygContext extends RawDrupalContext {
 
-  use BrowserCapabilityDetectionTrait;
-  use BrowserWindowTrait;
+  use JavascriptTrait;
   use UtilityTrait;
   use WysiwygTrait;
 
@@ -28,7 +26,7 @@ class WysiwygContext extends RawDrupalContext {
    * 'Source' button so the text can be entered as normal HTML.
    *
    * @param string $text
-   *   The text to enter in the WYSIWYG editor.
+   *   The text to be entered in the WYSIWYG editor.
    * @param string $label
    *   The label of the field containing the WYSIWYG editor.
    *
@@ -38,7 +36,7 @@ public function enterTextInWysiwyg(string $text, string $label): void {
     // If we are running in a JavaScript enabled browser, first click the
     // 'Source' button so we can enter the text as HTML and get the same result
     // as in a non-JS browser.
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       // Scroll to the top because the button might be obscured by the floating
       // header.
       $page = $this->getSession()->getPage();
@@ -81,7 +79,6 @@ function(){
    */
   public function pressButtonInWysiwyg(string $button, string $label): void {
     self::assertJavaScriptEnabledBrowser();
-
     $this->pressWysiwygButton($label, $button);
   }
 
@@ -127,7 +124,7 @@ public function assertNoWysiwyg(string $label): void {
    * @Then the paragraph formats in the :field field should not contain the :format_tags format(s)
    */
   public function assertNotFormatInCkeditorExists(string $label, string $format_tags): void {
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       throw new \Exception('This step requires javascript to run.');
     }
     $element = $this->getSession()->getPage()->findField($label);
diff --git a/tests/src/ContextualLinksHelper.php b/tests/src/ContextualLinksHelper.php
index 5181437f05491606a07d5d850595d02cbf011dda..83e8f9fde2a103f8f73155f7a1c4959be466d35a 100644
--- a/tests/src/ContextualLinksHelper.php
+++ b/tests/src/ContextualLinksHelper.php
@@ -7,7 +7,6 @@
 use Behat\Mink\Element\NodeElement;
 use Behat\Mink\Element\TraversableElement;
 use Drupal\DrupalExtension\Context\RawDrupalContext;
-use Drupal\joinup\Traits\BrowserCapabilityDetectionTrait;
 use Drupal\joinup\Traits\JavascriptTrait;
 use Drupal\joinup\Traits\TraversingTrait;
 use Drupal\joinup\Traits\UtilityTrait;
@@ -25,7 +24,6 @@
  */
 class ContextualLinksHelper {
 
-  use BrowserCapabilityDetectionTrait;
   use JavascriptTrait;
   use TraversingTrait;
   use UtilityTrait;
@@ -75,7 +73,7 @@ public function __call($name, $arguments) {
    *   An array of link paths found keyed by title.
    */
   public function findContextualLinkPaths(TraversableElement $element): array {
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       return $this->generateContextualLinks($element);
     }
 
@@ -211,7 +209,7 @@ protected function findContextualLinkElement(TraversableElement $element, string
    *   The element that contains the contextual links to open.
    */
   protected function openContextualLinksMenu(TraversableElement $element): void {
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       throw new \LogicException('Cannot open the contextual link menu on a browser that doesn\'t support JavaScript.');
     }
 
@@ -256,7 +254,7 @@ public function clickContextualLink(TraversableElement $element, string $link_ti
 
     // If we are not in a real browser, visit the link path instead of actually
     // opening the contextual menu and clicking the link.
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $this->openContextualLinksMenu($element);
       $link_element = $this->findContextualLinkElement($element, $link_title);
       $link_element->click();
diff --git a/tests/src/Traits/BootstrapTrait.php b/tests/src/Traits/BootstrapTrait.php
index 3de02300ec5542ab30e704597f9cefb2b000293e..9accc9319025af3126275e28a74a27e368273109 100644
--- a/tests/src/Traits/BootstrapTrait.php
+++ b/tests/src/Traits/BootstrapTrait.php
@@ -23,11 +23,11 @@ trait BootstrapTrait {
    *   when the accordion doesn't become visible within a reasonable time frame.
    */
   protected function openBootstrapAccordion(NodeElement $wrapper) {
-    \assert(method_exists($this, 'browserSupportsJavaScript'), __METHOD__ . ' depends on BrowserCapabilityDetectionTrait. Please include it in your class.');
+    \assert(method_exists($this, 'hasJavascriptSupport'), __METHOD__ . ' depends on JavascriptTrait. Please include it in your class.');
 
     // Non-JS browsers are directly interacting with the HTML, so we can
     // consider the content inside the accordion to be visible.
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       return;
     }
 
@@ -76,11 +76,11 @@ protected function openBootstrapAccordion(NodeElement $wrapper) {
    *   frame.
    */
   protected function openBootstrapDropdown(NodeElement $wrapper) {
-    \assert(method_exists($this, 'browserSupportsJavaScript'), __METHOD__ . ' depends on BrowserCapabilityDetectionTrait. Please include it in your class.');
+    \assert(method_exists($this, 'hasJavascriptSupport'), __METHOD__ . ' depends on JavascriptTrait. Please include it in your class.');
 
     // Non-JS browsers are directly interacting with the HTML, so we can
     // consider the content inside the dropdown to be visible.
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       return;
     }
 
diff --git a/tests/src/Traits/BrowserCapabilityDetectionTrait.php b/tests/src/Traits/BrowserCapabilityDetectionTrait.php
deleted file mode 100644
index 654fcea23164f0c0c7433a753e1ce978bf1a734e..0000000000000000000000000000000000000000
--- a/tests/src/Traits/BrowserCapabilityDetectionTrait.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-declare(strict_types = 1);
-
-namespace Drupal\joinup\Traits;
-
-use Behat\Mink\Exception\UnsupportedDriverActionException;
-
-/**
- * Helper methods for detecting browser capabilities.
- */
-trait BrowserCapabilityDetectionTrait {
-
-  /**
-   * Checks whether the browser supports JavaScript.
-   *
-   * @return bool
-   *   Returns TRUE when the browser environment supports executing JavaScript
-   *   code, for example because the test is running in Selenium or PhantomJS.
-   */
-  protected function browserSupportsJavaScript(): bool {
-    $driver = $this->getSession()->getDriver();
-    try {
-      $driver->executeScript('return;');
-      return TRUE;
-    }
-    catch (UnsupportedDriverActionException $e) {
-      return FALSE;
-    }
-  }
-
-  /**
-   * Checks that we are running on a JavaScript-enabled browser.
-   *
-   * @throws \LogicException
-   *   Thrown when not running on a JS-enabled browser.
-   */
-  protected function assertJavaScriptEnabledBrowser(): void {
-    if (!$this->browserSupportsJavaScript()) {
-      // Show a helpful error message.
-      throw new \LogicException('This test needs to run on a real browser using Selenium or similar. Please add the "@javascript" tag to the scenario.');
-    }
-  }
-
-}
diff --git a/tests/src/Traits/BrowserWindowTrait.php b/tests/src/Traits/BrowserWindowTrait.php
deleted file mode 100644
index bd33923a6cfe65d123b96773e486bd823691c364..0000000000000000000000000000000000000000
--- a/tests/src/Traits/BrowserWindowTrait.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-
-declare(strict_types = 1);
-
-namespace Drupal\joinup\Traits;
-
-/**
- * Helper methods to interact with the browser window.
- */
-trait BrowserWindowTrait {
-
-  use BrowserCapabilityDetectionTrait;
-
-  /**
-   * Scrolls to the top of the browser window.
-   */
-  protected function scrollToTop(): void {
-    if ($this->browserSupportsJavaScript()) {
-      $this->getSession()->getDriver()->executeScript('window.scroll(0, 0);');
-    }
-  }
-
-}
diff --git a/tests/src/Traits/JavascriptTrait.php b/tests/src/Traits/JavascriptTrait.php
index b9864d42c5fede257640455af5fc4b69f8ede59d..c7529eaaee8809d711ee17e05e0cc6cc3dfccbf5 100644
--- a/tests/src/Traits/JavascriptTrait.php
+++ b/tests/src/Traits/JavascriptTrait.php
@@ -4,6 +4,7 @@
 
 namespace Drupal\joinup\Traits;
 
+use Behat\Mink\Driver\Selenium2Driver;
 use Behat\Mink\Element\TraversableElement;
 
 /**
@@ -11,8 +12,6 @@
  */
 trait JavascriptTrait {
 
-  use BrowserCapabilityDetectionTrait;
-
   /**
    * Moves a named element in the middle of the screen for Javascript tests.
    *
@@ -25,6 +24,9 @@ trait JavascriptTrait {
    *   A traversable element to restrict the search to. Defaults to page.
    */
   protected function scrollNamedElementIntoView(string $type, string $label, ?TraversableElement $container = NULL): void {
+    if (!$this->hasJavascriptSupport()) {
+      return;
+    }
     assert(in_array($type, [
       'fieldset',
       'field',
@@ -43,17 +45,15 @@ protected function scrollNamedElementIntoView(string $type, string $label, ?Trav
       'id_or_name',
     ], TRUE));
 
-    if ($this->browserSupportsJavaScript()) {
-      if ($container) {
-        $this->scrollElementIntoView($container);
-      }
-      $container ??= $this->getSession()->getPage();
-      $element = $container->find('named', [
-        $type, str_replace('\\"', '"', $label),
-      ]);
-      if ($element) {
-        $this->scrollElementIntoView($element);
-      }
+    if ($container) {
+      $this->scrollElementIntoView($container);
+    }
+    $container ??= $this->getSession()->getPage();
+    $element = $container->find('named', [
+      $type, str_replace('\\"', '"', $label),
+    ]);
+    if ($element) {
+      $this->scrollElementIntoView($element);
     }
   }
 
@@ -66,11 +66,12 @@ protected function scrollNamedElementIntoView(string $type, string $label, ?Trav
    *   A traversable element to restrict the search to. Defaults to page.
    */
   protected function scrollCssSelectedElementIntoView(string $css_selector, ?TraversableElement $container = NULL): void {
-    if ($this->browserSupportsJavaScript()) {
-      $container ??= $this->getSession()->getPage();
-      if ($element = $container->find('css', $css_selector)) {
-        $this->scrollElementIntoView($element);
-      }
+    if (!$this->hasJavascriptSupport()) {
+      return;
+    }
+    $container ??= $this->getSession()->getPage();
+    if ($element = $container->find('css', $css_selector)) {
+      $this->scrollElementIntoView($element);
     }
   }
 
@@ -78,8 +79,8 @@ protected function scrollCssSelectedElementIntoView(string $css_selector, ?Trave
    * Moves an element in the middle of the screen for Javascript tests.
    *
    * In the latest versions of Selenium in Docker, moving to a button element
-   * might throw this exception while the button is visible. This might be due
-   * to attempting to find the button too fast.
+   * might throw this exception when the button is not visible in the browser
+   * viewport.
    *
    * Note that the method is using the Javascript `document.evaluate()` function
    * which is not available in Internet Explorer, but we're using this method
@@ -89,10 +90,9 @@ protected function scrollCssSelectedElementIntoView(string $css_selector, ?Trave
    *   The node element.
    */
   protected function scrollElementIntoView(TraversableElement $element): void {
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       return;
     }
-
     // Strings (labels) containing simple quotes (') are enclosed with double
     // quotes ("), thus we need to escape them. Also, xpath might contain new
     // lines which we replace with spaces.
@@ -109,4 +109,36 @@ function() {
     sleep(1);
   }
 
+  /**
+   * Detects whether this test has Javascript support.
+   *
+   * @return bool
+   *   Whether this test has Javascript support.
+   */
+  public function hasJavascriptSupport(): bool {
+    return $this->getSession()->getDriver() instanceof Selenium2Driver;
+  }
+
+  /**
+   * Checks that we are running on a JavaScript-enabled browser.
+   *
+   * @throws \LogicException
+   *   Thrown when not running on a JS-enabled browser.
+   */
+  protected function assertJavaScriptEnabledBrowser(): void {
+    if (!$this->hasJavascriptSupport()) {
+      // Show a helpful error message.
+      throw new \LogicException('This test needs to run on a real browser using Selenium or similar. Please add the "@javascript" tag to the scenario.');
+    }
+  }
+
+  /**
+   * Scrolls to the top of the browser's window.
+   */
+  protected function scrollToTop(): void {
+    if ($this->hasJavascriptSupport()) {
+      $this->getSession()->getDriver()->executeScript('window.scroll(0, 0);');
+    }
+  }
+
 }
diff --git a/tests/src/Traits/MaterialDesignTrait.php b/tests/src/Traits/MaterialDesignTrait.php
index 73241791277c17270fb542e0848b4e05a1d9458f..f3f5fc76d366391ed65c0d554c8725cfbde8d1f4 100644
--- a/tests/src/Traits/MaterialDesignTrait.php
+++ b/tests/src/Traits/MaterialDesignTrait.php
@@ -12,8 +12,7 @@
  */
 trait MaterialDesignTrait {
 
-  use BrowserCapabilityDetectionTrait;
-  use BrowserWindowTrait;
+  use JavascriptTrait;
 
   /**
    * Checks whether the current page is based on Material Design Lite library.
@@ -44,7 +43,7 @@ protected function usesMaterialDesignLite(): bool {
    *   given label is not found.
    */
   protected function checkMaterialDesignField($label, TraversableElement $element) {
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       // Check if the checkbox has already been checked.
       if (!$this->findMaterialDesignCheckbox($label, $element)->isChecked()) {
         // First scroll to the top of the page before attempting to check the
@@ -77,7 +76,7 @@ protected function checkMaterialDesignField($label, TraversableElement $element)
    *   given label is not found.
    */
   protected function uncheckMaterialDesignField($label, TraversableElement $element) {
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       // Only check if the checkbox is unchecked.
       if ($this->findMaterialDesignCheckbox($label, $element)->isChecked()) {
         // First scroll to the top of the page before attempting to uncheck the
@@ -108,7 +107,7 @@ protected function uncheckMaterialDesignField($label, TraversableElement $elemen
    *   checkbox with the given label is not found.
    */
   protected function toggleMaterialDesignCheckbox(TraversableElement $element, ?string $label = NULL): void {
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       throw new \Exception("The animated checkbox with label $label cannot be toggled in a browser that doesn't support JavaScript.");
     }
 
@@ -145,7 +144,7 @@ protected function toggleMaterialDesignCheckbox(TraversableElement $element, ?st
    *   checkbox with the given label is not found.
    */
   protected function findMaterialDesignCheckbox($label, TraversableElement $element): NodeElement {
-    if (!$this->browserSupportsJavaScript()) {
+    if (!$this->hasJavascriptSupport()) {
       throw new \Exception("The hidden input field for the $label checkbox cannot be found in a browser that doesn't support JavaScript.");
     }
 
@@ -169,7 +168,7 @@ protected function findMaterialDesignCheckbox($label, TraversableElement $elemen
    *   and when the menu doesn't become visible within the allowed time frame.
    */
   protected function openMaterialDesignMenu($wrapper) {
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       if (!$wrapper) {
         throw new \Exception('The MDL menu wrapper was not found in the page.');
       }
@@ -226,7 +225,7 @@ protected function openMaterialDesignMenu($wrapper) {
    *   Thrown when the radio button is not found.
    */
   protected function selectMaterialDesignRadioButton(string $label, TraversableElement $parent_element): void {
-    \assert($this->browserSupportsJavaScript(), 'A fallback method to select a material design radio button has not yet been implemented for non-JS browsers.');
+    \assert($this->hasJavascriptSupport(), 'A fallback method to select a material design radio button has not yet been implemented for non-JS browsers.');
 
     $xpath = '//label[text()="' . $label . '"]/../../span[contains(concat(" ", normalize-space(@class), " "), " mdl-radio__ripple-container ")]';
 
diff --git a/tests/src/Traits/TraversingTrait.php b/tests/src/Traits/TraversingTrait.php
index 9bc53384fb20023184affd3161bba2353b185d7b..6bfa77d925fd8a3384793b5d80466342b2dc2f6f 100644
--- a/tests/src/Traits/TraversingTrait.php
+++ b/tests/src/Traits/TraversingTrait.php
@@ -205,34 +205,6 @@ protected function findVerticalTab(string $tab): NodeElement {
     return $element;
   }
 
-  /**
-   * Finds an accordion item by its title.
-   *
-   * @param string $item
-   *   The title of the accordion item.
-   *
-   * @return \Behat\Mink\Element\NodeElement
-   *   The accordion item element.
-   *
-   * @throws \Exception
-   *   Thrown when no item element is found.
-   */
-  protected function findAccordionItem(string $item): NodeElement {
-    // Xpath to find the accordion item.
-    $xpath = "//div[@class and contains(concat(' ', normalize-space(@class), ' '), ' accordion-item ')]";
-    // Filter down to the accordion item containing a button with the
-    // provided text.
-    $xpath .= "[.//h2[@class and contains(concat(' ', normalize-space(@class), ' '), ' accordion-header ')]/button[@class and contains(concat(' ', normalize-space(@class), ' '), ' accordion-button ')]"
-      . "[normalize-space(string(.)) = '$item']]";
-    $element = $this->getSession()->getPage()->find('xpath', $xpath);
-
-    if ($element === NULL) {
-      throw new \Exception('Accordion item not found: ' . $item);
-    }
-
-    return $element;
-  }
-
   /**
    * Retrieves a region container from the page.
    *
diff --git a/tests/src/Traits/WysiwygTrait.php b/tests/src/Traits/WysiwygTrait.php
index 749340c6caa37a0dbe29b5b7e5039fa0f4c37054..dc4cd6405fd1d893bd93b5ff92341ff78aeeba30 100644
--- a/tests/src/Traits/WysiwygTrait.php
+++ b/tests/src/Traits/WysiwygTrait.php
@@ -210,9 +210,9 @@ protected function getWysiwygEditorEntity(string $label, ?TraversableElement $re
    *   page.
    */
   protected function getWysiwygButtons(string $label, ?TraversableElement $region = NULL): array {
-    assert(method_exists($this, 'browserSupportsJavaScript'), __METHOD__ . ' depends on BrowserCapabilityDetectionTrait. Please include it in your class.');
+    assert(method_exists($this, 'hasJavascriptSupport'), __METHOD__ . ' depends on JavascriptTrait. Please include it in your class.');
 
-    if ($this->browserSupportsJavaScript()) {
+    if ($this->hasJavascriptSupport()) {
       $editor = $this->getWysiwyg($label, $region);
       $button_elements = $editor->findAll('xpath', '//a[contains(concat(" ", normalize-space(@class), " "), " cke_button ")]/span[contains(@id, "_label")]');
 
diff --git a/web/modules/custom/asset_release/tests/src/ExistingSite/AssetReleaseWorkflowTest.php b/web/modules/custom/asset_release/tests/src/ExistingSite/AssetReleaseWorkflowTest.php
index 8677e1f7c2da1b172955cf608c109a2828a88079..e3b82ddfc178bf0f6cb375a2d6959f4d1d218fe3 100644
--- a/web/modules/custom/asset_release/tests/src/ExistingSite/AssetReleaseWorkflowTest.php
+++ b/web/modules/custom/asset_release/tests/src/ExistingSite/AssetReleaseWorkflowTest.php
@@ -225,7 +225,7 @@ protected function createDefaultParent(string $state): RdfInterface {
    *    ['user1', 'expected_result'],
    *    ['user2', 'expected_result'],
    * ];
-   * @code
+   * @endcode
    * The user variable represents the variable defined in the test.
    * Only two parent states need to be tested as the expected result might
    * differ depending on whether the parent is published or not.
@@ -267,7 +267,7 @@ public function createAccessProvider(): array {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    * Only two parent states need to be tested as the expected result might
    * differ depending on whether the parent is published or not.
    *
@@ -404,7 +404,7 @@ public function readUpdateDeleteAccessProvider(): array {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    * There can be multiple transitions that can lead to a specific state, so
    * the check is being done on allowed transitions.
    *
diff --git a/web/modules/custom/asset_release/tests/src/ExistingSite/SyncFieldsFromParentSolutionTest.php b/web/modules/custom/asset_release/tests/src/ExistingSite/SyncFieldsFromParentSolutionTest.php
index 08c46df1da5f759279ea401223ad9c48ba02a42a..98097d1b37817e68958a1b2ec4a30b423376635a 100644
--- a/web/modules/custom/asset_release/tests/src/ExistingSite/SyncFieldsFromParentSolutionTest.php
+++ b/web/modules/custom/asset_release/tests/src/ExistingSite/SyncFieldsFromParentSolutionTest.php
@@ -5,7 +5,6 @@
 namespace Drupal\Tests\asset_release\ExistingSite;
 
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use Drupal\rdf_entity\Entity\Rdf;
 use Drupal\taxonomy\Entity\Vocabulary;
 
@@ -16,8 +15,6 @@
  */
 class SyncFieldsFromParentSolutionTest extends JoinupExistingSiteTestBase {
 
-  use RdfEntityCreationTrait;
-
   /**
    * {@inheritdoc}
    */
diff --git a/web/modules/custom/contact_information/tests/src/ExistingSite/ContactInformationWorkflowTest.php b/web/modules/custom/contact_information/tests/src/ExistingSite/ContactInformationWorkflowTest.php
index a2b0fdcd6f89e8d384c2c289475c0a6123fdbb48..d499e45c1cd10390ed90ffb677c8b1962fc8d5d6 100644
--- a/web/modules/custom/contact_information/tests/src/ExistingSite/ContactInformationWorkflowTest.php
+++ b/web/modules/custom/contact_information/tests/src/ExistingSite/ContactInformationWorkflowTest.php
@@ -109,7 +109,7 @@ public function testWorkflow(): void {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    * There can be multiple transitions that can lead to a specific state, so
    * the check is being done on allowed transitions.
    *
diff --git a/web/modules/custom/dashboard/dashboard.module b/web/modules/custom/dashboard/dashboard.module
index b3c2156dd5ee571fc3d663ebcd86023a1a88ddd5..a63eba0c17b19e7a268298e71f336329d32fdcc0 100644
--- a/web/modules/custom/dashboard/dashboard.module
+++ b/web/modules/custom/dashboard/dashboard.module
@@ -30,7 +30,7 @@ function dashboard_form_alter(array &$form, FormStateInterface $form_state, stri
 }
 
 /**
- * Redirect users to the Curated content listings after saving a content list.
+ * Redirects users to the Curated content listings after saving a content list.
  *
  * @param array $form
  *   The form array.
diff --git a/web/modules/custom/joinup_community_content/tests/src/ExistingSite/CommunityContentWorkflowTestBase.php b/web/modules/custom/joinup_community_content/tests/src/ExistingSite/CommunityContentWorkflowTestBase.php
index b11df5fa1d2194d7089b8fd50343170e62e9a2dd..7bc354c95e23f8f9fa269108c9e9336f435fc02a 100644
--- a/web/modules/custom/joinup_community_content/tests/src/ExistingSite/CommunityContentWorkflowTestBase.php
+++ b/web/modules/custom/joinup_community_content/tests/src/ExistingSite/CommunityContentWorkflowTestBase.php
@@ -5,6 +5,7 @@
 namespace Drupal\Tests\joinup_community_content\ExistingSite;
 
 use Drupal\Core\Session\AnonymousUserSession;
+use Drupal\Tests\joinup_test\Traits\NodeCreationTrait;
 use Drupal\Tests\joinup_workflow\ExistingSite\JoinupWorkflowExistingSiteTestBase;
 use Drupal\joinup_group\ContentCreationOptions;
 use Drupal\joinup_group\Entity\GroupInterface;
@@ -13,7 +14,6 @@
 use Drupal\og\OgGroupAudienceHelper;
 use Drupal\og\OgMembershipInterface;
 use Drupal\rdf_entity\RdfInterface;
-use weitzman\DrupalTestTraits\Entity\NodeCreationTrait;
 
 /**
  * Base setup for a Joinup workflow test for community content.
@@ -322,7 +322,7 @@ protected function deleteOperationTest(): void {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    * The user variable represents the variable defined in the test.
    * No parent state needs to be checked as it does not affect the possibility
    * to create document.
@@ -539,7 +539,7 @@ protected function createAccessProvider(): array {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    * The user variable represents the variable defined in the test.
    * No parent state needs to be checked as it does not affect the possibility
    * to create document.
@@ -659,7 +659,7 @@ protected function viewAccessProvider(): array {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    * The user variable represents the variable defined in the test.
    * No parent state needs to be checked as it does not affect the possibility
    * to create document.
@@ -845,7 +845,7 @@ protected function updateAccessProvider(): array {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    * The user variable represents the variable defined in the test.
    * No parent state needs to be checked as it does not affect the possibility
    * to create document.
diff --git a/web/modules/custom/joinup_core/tests/src/ExistingSite/ConfigTest.php b/web/modules/custom/joinup_core/tests/src/ExistingSite/ConfigTest.php
index abf5cdc50838ac5988b444f03f622b3b1bd23777..9847328c6e08245490d38644a5a536d6a55e7149 100644
--- a/web/modules/custom/joinup_core/tests/src/ExistingSite/ConfigTest.php
+++ b/web/modules/custom/joinup_core/tests/src/ExistingSite/ConfigTest.php
@@ -19,7 +19,7 @@ class ConfigTest extends JoinupExistingSiteTestBase {
   /**
    * {@inheritdoc}
    */
-  protected $disableSpamProtection = FALSE;
+  protected bool $disableSpamProtection = FALSE;
 
   /**
    * Tests that the active and sync stores are the same.
diff --git a/web/modules/custom/joinup_core/tests/src/ExistingSite/FileUrlFieldTest.php b/web/modules/custom/joinup_core/tests/src/ExistingSite/FileUrlFieldTest.php
index c372db22be3e68a231657a0019b2531997cb12f0..a0a1c888e9533ddf0f4e0d867a6c083d526acc06 100644
--- a/web/modules/custom/joinup_core/tests/src/ExistingSite/FileUrlFieldTest.php
+++ b/web/modules/custom/joinup_core/tests/src/ExistingSite/FileUrlFieldTest.php
@@ -8,7 +8,6 @@
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Tests\joinup_core\Traits\TestFileTrait;
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use Drupal\Tests\rdf_entity\Traits\EntityUtilityTrait;
 use Drupal\Tests\sparql_entity_storage\Traits\SparqlConnectionTrait;
 use Drupal\file\FileInterface;
@@ -27,7 +26,6 @@ class FileUrlFieldTest extends JoinupExistingSiteTestBase {
   use EntityUtilityTrait;
   use TestFileTrait;
   use LoginTrait;
-  use RdfEntityCreationTrait;
   use SparqlConnectionTrait;
   use StringTranslationTrait;
 
diff --git a/web/modules/custom/joinup_core/tests/src/ExistingSite/OutdatedContentTest.php b/web/modules/custom/joinup_core/tests/src/ExistingSite/OutdatedContentTest.php
index 98b1be53d0a674fa4f00a4f42bd40cffb897a190..afd353bafa95f00b8fcaf58230ad8ca7dd58fe29 100644
--- a/web/modules/custom/joinup_core/tests/src/ExistingSite/OutdatedContentTest.php
+++ b/web/modules/custom/joinup_core/tests/src/ExistingSite/OutdatedContentTest.php
@@ -5,7 +5,6 @@
 namespace Drupal\Tests\joinup_core\ExistingSite;
 
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use Drupal\joinup_core\Entity\OutdatedContentInterface;
 
 /**
@@ -15,8 +14,6 @@
  */
 class OutdatedContentTest extends JoinupExistingSiteTestBase {
 
-  use RdfEntityCreationTrait;
-
   /**
    * The current time.
    *
diff --git a/web/modules/custom/joinup_core/tests/src/ExistingSite/TokenTest.php b/web/modules/custom/joinup_core/tests/src/ExistingSite/TokenTest.php
index a2b43930796a0dd688dc9757eac85b4f00c88dcc..599f088171a7f1ce2a9ac54aa6d13c78751b3c31 100644
--- a/web/modules/custom/joinup_core/tests/src/ExistingSite/TokenTest.php
+++ b/web/modules/custom/joinup_core/tests/src/ExistingSite/TokenTest.php
@@ -6,7 +6,6 @@
 
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
 use Drupal\Tests\node\Traits\NodeCreationTrait;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use Drupal\Tests\token\Functional\TokenTestTrait;
 use Drupal\rdf_entity\Entity\Rdf;
 
@@ -16,7 +15,6 @@
 class TokenTest extends JoinupExistingSiteTestBase {
 
   use NodeCreationTrait;
-  use RdfEntityCreationTrait;
   use TokenTestTrait;
 
   /**
diff --git a/web/modules/custom/joinup_core/tests/src/ExistingSite/TopicHierarchyIndexingTest.php b/web/modules/custom/joinup_core/tests/src/ExistingSite/TopicHierarchyIndexingTest.php
index 8a11f72205ef8cf9adc0a55e2f63472835ee2de9..62e551d062fb16f222a365d7b6be6fc78850ed5b 100644
--- a/web/modules/custom/joinup_core/tests/src/ExistingSite/TopicHierarchyIndexingTest.php
+++ b/web/modules/custom/joinup_core/tests/src/ExistingSite/TopicHierarchyIndexingTest.php
@@ -5,7 +5,6 @@
 namespace Drupal\Tests\joinup_core\ExistingSite;
 
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use Drupal\search_api\Entity\Index;
 use Drupal\taxonomy\Entity\Vocabulary;
 use weitzman\DrupalTestTraits\Entity\TaxonomyCreationTrait;
@@ -17,7 +16,6 @@
  */
 class TopicHierarchyIndexingTest extends JoinupExistingSiteTestBase {
 
-  use RdfEntityCreationTrait;
   use TaxonomyCreationTrait;
 
   /**
diff --git a/web/modules/custom/joinup_document/tests/src/ExistingSite/DocumentThemeTest.php b/web/modules/custom/joinup_document/tests/src/ExistingSite/DocumentThemeTest.php
index 9f574a4a025841f5b0c71e0cc5d8f2bcc9cf9ec1..fe88d44ee7c6e680fda98f6feb380eb855afd9f3 100644
--- a/web/modules/custom/joinup_document/tests/src/ExistingSite/DocumentThemeTest.php
+++ b/web/modules/custom/joinup_document/tests/src/ExistingSite/DocumentThemeTest.php
@@ -5,28 +5,15 @@
 namespace Drupal\Tests\joinup_document\ExistingSite;
 
 use Drupal\Tests\joinup_core\Traits\TestFileTrait;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
-use Drupal\Tests\sparql_entity_storage\Traits\SparqlConnectionTrait;
-use Drupal\file\FileInterface;
-use Drupal\joinup_document\Entity\DocumentInterface;
-use weitzman\DrupalTestTraits\ExistingSiteBase;
+use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
 
 /**
  * Various tests related to document theming.
  */
-class DocumentThemeTest extends ExistingSiteBase {
+class DocumentThemeTest extends JoinupExistingSiteTestBase {
 
-  use RdfEntityCreationTrait;
-  use SparqlConnectionTrait;
   use TestFileTrait;
 
-  /**
-   * A test file.
-   *
-   * @var \Drupal\file\FileInterface
-   */
-  protected $file;
-
   /**
    * Tests that the logo affects relative fields in the listing tile.
    */
@@ -44,35 +31,30 @@ public function testDocumentLogoListing(): void {
       'body' => 'Hello document body',
       'field_keywords' => ['keyword_sample'],
       'field_short_title' => 'DocTitle',
+      'field_state' => 'validated',
     ]);
 
-    $this->assertTrue($document instanceof DocumentInterface);
-    $this->assertNotEmpty($document->id());
-
-    $view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
-    $renderer = \Drupal::getContainer()->get('renderer');
-    $view_array = $view_builder->view($document, 'view_mode_tile');
-    $html = (string) $renderer->renderPlain($view_array);
+    /** @var \Drupal\Core\DestructableInterface $post_request_indexing */
+    $post_request_indexing = \Drupal::service('search_api.post_request_indexing');
+    $assert = $this->assertSession();
 
-    $this->assertNotEmpty($html);
-    $this->assertStringContainsString('Document title', $html);
-    $this->assertStringContainsString('<p>Hello document body</p>', $html);
-    $this->assertStringContainsString('keyword_sample', $html);
+    $post_request_indexing->destruct();
+    $this->drupalGet($collection->toUrl());
+    $assert->pageTextContains('Document title');
+    $assert->pageTextContains('Hello document body');
+    $assert->pageTextContains('keyword_sample');
 
-    $this->file = $this->getTestFile('text');
-    $this->file->save();
-    $this->assertTrue($this->file instanceof FileInterface);
-    $document->set('field_document_logo', $this->file);
-    $document->save();
+    $file = $this->getTestFile('text');
+    $file->save();
+    $document->set('field_document_logo', $file)->save();
 
-    $view_array = $view_builder->view($document, 'view_mode_tile');
-    $html = (string) $renderer->renderPlain($view_array);
+    $post_request_indexing->destruct();
+    $this->getSession()->reload();
 
-    $this->assertNotEmpty($html);
-    $this->assertStringContainsString('<div class="listing__image">', $html);
-    $this->assertStringContainsString('Document title', $html);
-    $this->assertStringNotContainsString('<p>Hello document body</p>', $html);
-    $this->assertStringNotContainsString('keyword_sample', $html);
+    $assert->responseContains('<div class="listing__image">');
+    $assert->pageTextContains('Document title');
+    $assert->pageTextNotContains('Hello document body');
+    $assert->pageTextNotContains('keyword_sample');
   }
 
 }
diff --git a/web/modules/custom/joinup_eulogin/src/Routing/JoinupEuLoginRouteSubscriber.php b/web/modules/custom/joinup_eulogin/src/Routing/JoinupEuLoginRouteSubscriber.php
index 312d66b9f51d8cfe5eaf3510b174479b795f2faf..2d90b0d83f6bfd6b292e445f19cde34ed73c9ec0 100644
--- a/web/modules/custom/joinup_eulogin/src/Routing/JoinupEuLoginRouteSubscriber.php
+++ b/web/modules/custom/joinup_eulogin/src/Routing/JoinupEuLoginRouteSubscriber.php
@@ -31,10 +31,10 @@ protected function alterRoutes(RouteCollection $collection): void {
     }
 
     // Password reset should not be available anymore. Note that we cannot just
-    // remove the routes as 'user.pass' is used in AccountForm::form().
+    // remove the 'user.pass' route as is used in AccountForm::form().
     // @see \Drupal\user\AccountForm::form()
     $collection->add('user.pass', $collection->get('system.404'));
-    $collection->add('user.pass.http', $collection->get('system.404'));
+    $collection->remove('user.pass.http');
 
     if ($route = $collection->get('user.login')) {
       $route->setRequirements(['_access' => 'FALSE']);
diff --git a/web/modules/custom/joinup_eulogin/tests/src/ExistingSite/Anonymous403RedirectCacheTest.php b/web/modules/custom/joinup_eulogin/tests/src/ExistingSite/Anonymous403RedirectCacheTest.php
index cac47e20df386098b879d2e06a5aedb0cc28762c..2cbe932dd9c897bd0a227707addfa1e0149860a1 100644
--- a/web/modules/custom/joinup_eulogin/tests/src/ExistingSite/Anonymous403RedirectCacheTest.php
+++ b/web/modules/custom/joinup_eulogin/tests/src/ExistingSite/Anonymous403RedirectCacheTest.php
@@ -5,7 +5,7 @@
 namespace Drupal\Tests\joinup_eulogin\ExistingSite;
 
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
+use Drupal\Tests\joinup_test\Traits\NodeCreationTrait;
 
 /**
  * Tests the 403 redirection cache.
@@ -23,7 +23,7 @@
  */
 class Anonymous403RedirectCacheTest extends JoinupExistingSiteTestBase {
 
-  use RdfEntityCreationTrait;
+  use NodeCreationTrait;
 
   /**
    * Tests the 403 redirection cache.
diff --git a/web/modules/custom/joinup_group/tests/src/ExistingSite/GroupContentUpdateUrlAliasTest.php b/web/modules/custom/joinup_group/tests/src/ExistingSite/GroupContentUpdateUrlAliasTest.php
index 4fbb5ee7efa3f0ce529aa62d417d92197cea2d1f..da762dad6a6517b96c4c1dc5f008f05db6a18d77 100644
--- a/web/modules/custom/joinup_group/tests/src/ExistingSite/GroupContentUpdateUrlAliasTest.php
+++ b/web/modules/custom/joinup_group/tests/src/ExistingSite/GroupContentUpdateUrlAliasTest.php
@@ -6,7 +6,6 @@
 
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use Drupal\rdf_taxonomy\Entity\RdfTerm;
 use Drush\TestTraits\DrushTestTrait;
 use weitzman\LoginTrait\LoginTrait;
@@ -20,7 +19,6 @@ class GroupContentUpdateUrlAliasTest extends JoinupExistingSiteTestBase {
 
   use DrushTestTrait;
   use LoginTrait;
-  use RdfEntityCreationTrait;
 
   /**
    * Testing entities.
diff --git a/web/modules/custom/joinup_group/tests/src/ExistingSite/GroupTokensTest.php b/web/modules/custom/joinup_group/tests/src/ExistingSite/GroupTokensTest.php
index 1a5a6a62d143fd505e16ff607471b91c061ca72a..088343828eec43df1076b3e599dff6f34d5a6a12 100644
--- a/web/modules/custom/joinup_group/tests/src/ExistingSite/GroupTokensTest.php
+++ b/web/modules/custom/joinup_group/tests/src/ExistingSite/GroupTokensTest.php
@@ -5,7 +5,6 @@
 namespace Drupal\Tests\joinup_group\ExistingSite;
 
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use Drupal\Tests\token\Functional\TokenTestTrait;
 
 /**
@@ -13,7 +12,6 @@
  */
 class GroupTokensTest extends JoinupExistingSiteTestBase {
 
-  use RdfEntityCreationTrait;
   use TokenTestTrait;
 
   /**
diff --git a/web/modules/custom/joinup_group_content_management/config/schema/joinup_group_content_management.schema.yml b/web/modules/custom/joinup_group_content_management/config/schema/joinup_group_content_management.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3dad581a688095a3598c0e0024b384c6d39bae47
--- /dev/null
+++ b/web/modules/custom/joinup_group_content_management/config/schema/joinup_group_content_management.schema.yml
@@ -0,0 +1,3 @@
+views.field.accessible_entity_link:
+  type: views.field.entity_link
+  label: 'Accessible entity link'
diff --git a/web/modules/custom/joinup_group_content_management/joinup_group_content_management.info.yml b/web/modules/custom/joinup_group_content_management/joinup_group_content_management.info.yml
index 7e3f3d7d588fbee7487267223ee40398c2185ad4..69474c750c73ede90f922853d8486b46b5ec4019 100644
--- a/web/modules/custom/joinup_group_content_management/joinup_group_content_management.info.yml
+++ b/web/modules/custom/joinup_group_content_management/joinup_group_content_management.info.yml
@@ -12,6 +12,7 @@ dependencies:
   - 'drupal:rest'
   - 'drupal:serialization'
   - 'drupal:user'
+  - 'drupal:views'
   - 'joinup:custom_page'
   - 'joinup:joinup_group'
   - 'og_menu:og_menu'
diff --git a/web/modules/custom/joinup_group_content_management/src/Plugin/Action/ChangeGroupAction.php b/web/modules/custom/joinup_group_content_management/src/Plugin/Action/ChangeGroupAction.php
index 16e404b75af7f0a057cd2896057ffca52a9ff0bd..094ccfc9c22e50735ae438e2a7f5201cf32c1ea4 100644
--- a/web/modules/custom/joinup_group_content_management/src/Plugin/Action/ChangeGroupAction.php
+++ b/web/modules/custom/joinup_group_content_management/src/Plugin/Action/ChangeGroupAction.php
@@ -283,7 +283,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
   /**
    * {@inheritdoc}
    */
-  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
+  public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void {
     /** @var \Drupal\Core\Url $url */
     $url = $form_state->get('views_bulk_operations')['redirect_url'];
     if ($url->isRouted() && ($parameters = $url->getRouteParameters()) && !empty($parameters['rdf_entity'])) {
diff --git a/web/modules/custom/joinup_group_content_management/src/Plugin/views/field/AccessibleEntityLink.php b/web/modules/custom/joinup_group_content_management/src/Plugin/views/field/AccessibleEntityLink.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7c27857ed900451535e49ac4273a397bb13569b
--- /dev/null
+++ b/web/modules/custom/joinup_group_content_management/src/Plugin/views/field/AccessibleEntityLink.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types = 1);
+
+namespace Drupal\joinup_group_content_management\Plugin\views\field;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Access\AccessResultInterface;
+use Drupal\views\Plugin\views\field\EntityLink;
+use Drupal\views\ResultRow;
+
+/**
+ * Present a link to an entity even the entity cannot be accessed.
+ *
+ * @ingroup views_field_handlers
+ *
+ * @ViewsField("accessible_entity_link")
+ */
+class AccessibleEntityLink extends EntityLink {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkUrlAccess(ResultRow $row): AccessResultInterface {
+    return AccessResult::allowed();
+  }
+
+}
diff --git a/web/modules/custom/joinup_html_stripper/src/Plugin/Field/FieldFormatter/StrippedHTMLFormatter.php b/web/modules/custom/joinup_html_stripper/src/Plugin/Field/FieldFormatter/StrippedHTMLFormatter.php
index 9f3f15744b422d2e3ac02eb9b6143c03863e3973..9e90d093cb2576a1835070caa02d32623aa3a32f 100644
--- a/web/modules/custom/joinup_html_stripper/src/Plugin/Field/FieldFormatter/StrippedHTMLFormatter.php
+++ b/web/modules/custom/joinup_html_stripper/src/Plugin/Field/FieldFormatter/StrippedHTMLFormatter.php
@@ -89,7 +89,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
       $output = !empty($item->summary) ? $item->summary : $item->value;
 
       // Strip HTML, after applying all embedded media filters.
-      $output = check_markup($output, 'stripped_html');
+      $output = (string) check_markup($output, 'stripped_html');
 
       // Replace funny whitespace.
       $output = preg_replace('/\n|\r|\t/m', ' ', $output);
diff --git a/web/modules/custom/joinup_notification/joinup_notification.module b/web/modules/custom/joinup_notification/joinup_notification.module
index 2ee3ed026ad5a1a2447ce35d6112bb2f48498407..5286e2c2a2e37bbf2c47193ab50202c9cf37b358 100644
--- a/web/modules/custom/joinup_notification/joinup_notification.module
+++ b/web/modules/custom/joinup_notification/joinup_notification.module
@@ -174,7 +174,7 @@ function joinup_notification_dispatch_notification(string $operation, string $ev
   // @todo Replace this direct access of a custom entity property with the
   //   temporary entity data API once it lands in core.
   // @see https://www.drupal.org/node/2896474
-  if (isset($entity->skip_notification) && $entity->skip_notification === TRUE) {
+  if (!empty($entity->skip_notification)) {
     return;
   }
   $event = new NotificationEvent($operation, $entity);
diff --git a/web/modules/custom/joinup_test/tests/src/ExistingSite/JoinupExistingSiteTestBase.php b/web/modules/custom/joinup_test/tests/src/ExistingSite/JoinupExistingSiteTestBase.php
index f00953c07ab6f7a4aec8d4edbd8aa19659a0f8bf..13763a03c157c0b39b1cfd41a8bf9a331aa94383 100644
--- a/web/modules/custom/joinup_test/tests/src/ExistingSite/JoinupExistingSiteTestBase.php
+++ b/web/modules/custom/joinup_test/tests/src/ExistingSite/JoinupExistingSiteTestBase.php
@@ -4,6 +4,9 @@
 
 namespace Drupal\Tests\joinup_test\ExistingSite;
 
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\State\StateInterface;
+use Drupal\Tests\joinup_test\Traits\RdfEntityCreationTrait;
 use Drupal\joinup\Traits\AntibotTrait;
 use weitzman\DrupalTestTraits\ExistingSiteBase;
 
@@ -13,27 +16,28 @@
 abstract class JoinupExistingSiteTestBase extends ExistingSiteBase {
 
   use AntibotTrait;
+  use RdfEntityCreationTrait;
 
   /**
    * The list of Honeypot forms.
    *
    * @var bool[]
    */
-  protected $honeypotForms;
+  protected array $honeypotForms;
 
   /**
    * Whether the current test should run without Antibot & Honeypot features.
    *
    * @var bool
    */
-  protected $disableSpamProtection = TRUE;
+  protected bool $disableSpamProtection = TRUE;
 
   /**
    * The state service.
    *
    * @var \Drupal\Core\State\StateInterface
    */
-  protected $state;
+  protected StateInterface $state;
 
   /**
    * {@inheritdoc}
@@ -71,7 +75,20 @@ public function tearDown(): void {
       $this->restoreHoneypot();
     }
 
-    // Make sure we don't send any notifications during test entities cleanup.
+    // Avoid sending notifications during test entities cleanup. First, sort the
+    // entities by moving the 'user' entities at the end, as deleting a user
+    // might trigger deletion of entities authored by that user. Such entities
+    // are subsequently reloaded, losing the 'skip_notification' flag.
+    // @see node_user_predelete()
+    usort($this->cleanupEntities, function (EntityInterface $left, EntityInterface $right): int {
+      if ($left->getEntityTypeId() !== 'user' && $right->getEntityTypeId() === 'user') {
+        return -1;
+      }
+      elseif ($left->getEntityTypeId() === 'user' && $right->getEntityTypeId() !== 'user') {
+        return 1;
+      }
+      return 0;
+    });
     foreach ($this->cleanupEntities as $entity) {
       $entity->skip_notification = TRUE;
     }
diff --git a/web/modules/custom/joinup_test/tests/src/Traits/NodeCreationTrait.php b/web/modules/custom/joinup_test/tests/src/Traits/NodeCreationTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..576a0ca1e711ad9a53990b440a3e3273014b8020
--- /dev/null
+++ b/web/modules/custom/joinup_test/tests/src/Traits/NodeCreationTrait.php
@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types = 1);
+
+namespace Drupal\Tests\joinup_test\Traits;
+
+use Drupal\node\NodeInterface;
+use weitzman\DrupalTestTraits\Entity\NodeCreationTrait as ContribNodeCreationTrait;
+
+/**
+ * Wraps the `weitzman/drupal-test-traits` library node creation trait.
+ */
+trait NodeCreationTrait {
+
+  use ContribNodeCreationTrait {
+    createNode as contribCreateNode;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function createNode(array $values = []): NodeInterface {
+    $values += [
+      // Prevent notifications for test entities creation.
+      'skip_notification' => TRUE,
+    ];
+    return $this->contribCreateNode($values);
+  }
+
+}
diff --git a/web/modules/custom/joinup_test/tests/src/Traits/RdfEntityCreationTrait.php b/web/modules/custom/joinup_test/tests/src/Traits/RdfEntityCreationTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..104e75905e7dcd28374e09d897606354633d4d94
--- /dev/null
+++ b/web/modules/custom/joinup_test/tests/src/Traits/RdfEntityCreationTrait.php
@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types = 1);
+
+namespace Drupal\Tests\joinup_test\Traits;
+
+use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait as ContribRdfEntityCreationTrait;
+use Drupal\rdf_entity\RdfInterface;
+
+/**
+ * Wraps the `rdf_entity` module RDF entity creation trait.
+ */
+trait RdfEntityCreationTrait {
+
+  use ContribRdfEntityCreationTrait {
+    createRdfEntity as contribCreateRdfEntity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function createRdfEntity(array $values = []): RdfInterface {
+    $values += [
+      // Prevent notifications for test entities creation.
+      'skip_notification' => TRUE,
+    ];
+    return $this->contribCreateRdfEntity($values);
+  }
+
+}
diff --git a/web/modules/custom/joinup_user/joinup_user.module b/web/modules/custom/joinup_user/joinup_user.module
index 87fb0dcd7fa707cab84e427b4f690bfc148a0ae6..2b27e811a524e19051fe1043d6ac085edf75f7cb 100644
--- a/web/modules/custom/joinup_user/joinup_user.module
+++ b/web/modules/custom/joinup_user/joinup_user.module
@@ -147,7 +147,7 @@ function joinup_user_mail_alter(&$message) {
   }
 
   $message['body'] = array_map(function ($text) use ($moderation_text) {
-    $text = str_replace('@joinup_user:moderation_text', $moderation_text, $text);
+    $text = str_replace('@joinup_user:moderation_text', $moderation_text, (string) $text);
     return Markup::create($text);
   }, $message['body']);
 }
diff --git a/web/modules/custom/joinup_user/tests/src/ExistingSite/ProfileOverviewTest.php b/web/modules/custom/joinup_user/tests/src/ExistingSite/ProfileOverviewTest.php
index 7cafc49902e64ae6d5e83463ee6ec07d99de6b5e..bf1fe436734ec5b1db7f5e40e364ca8b64ee1f5c 100644
--- a/web/modules/custom/joinup_user/tests/src/ExistingSite/ProfileOverviewTest.php
+++ b/web/modules/custom/joinup_user/tests/src/ExistingSite/ProfileOverviewTest.php
@@ -5,7 +5,6 @@
 namespace Drupal\Tests\joinup_user\ExistingSite;
 
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use weitzman\LoginTrait\LoginTrait;
 
 /**
@@ -16,7 +15,6 @@
 class ProfileOverviewTest extends JoinupExistingSiteTestBase {
 
   use LoginTrait;
-  use RdfEntityCreationTrait;
 
   /**
    * The owner of the groups.
diff --git a/web/modules/custom/joinup_user/tests/src/ExistingSite/UserCancelTest.php b/web/modules/custom/joinup_user/tests/src/ExistingSite/UserCancelTest.php
index 9fecd833cf5a7ba4e891d580edb63cebb6075a1a..bccf85b0918642ad3475857cdb1b7b1d37efab17 100644
--- a/web/modules/custom/joinup_user/tests/src/ExistingSite/UserCancelTest.php
+++ b/web/modules/custom/joinup_user/tests/src/ExistingSite/UserCancelTest.php
@@ -6,7 +6,6 @@
 
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use Drupal\file\Entity\File;
 use Drupal\image\Plugin\Field\FieldType\ImageItem;
 use Drupal\og\OgMembershipInterface;
@@ -21,7 +20,6 @@
 class UserCancelTest extends JoinupExistingSiteTestBase {
 
   use LoginTrait;
-  use RdfEntityCreationTrait;
 
   /**
    * Tests user cancellation.
diff --git a/web/modules/custom/joinup_video/src/Plugin/Filter/JoinupVideo.php b/web/modules/custom/joinup_video/src/Plugin/Filter/JoinupVideo.php
index 17874dc3916de7835d364e406904bc123bacf98f..8adfb13aa27267a14f716c7bc2d62a928e6d45a7 100644
--- a/web/modules/custom/joinup_video/src/Plugin/Filter/JoinupVideo.php
+++ b/web/modules/custom/joinup_video/src/Plugin/Filter/JoinupVideo.php
@@ -153,7 +153,7 @@ public function process($text, $langcode) {
       }
 
       // Replace the JSON settings with a video.
-      $text = str_replace($source_text, $this->renderer->render($embed_code), $text);
+      $text = str_replace($source_text, (string) $this->renderer->render($embed_code), $text);
 
       // Add the required responsive video library only when at least one match
       // is present.
diff --git a/web/modules/custom/joinup_workflow/tests/src/ExistingSite/JoinupWorkflowExistingSiteTestBase.php b/web/modules/custom/joinup_workflow/tests/src/ExistingSite/JoinupWorkflowExistingSiteTestBase.php
index 94ab5ca58b6fcd2786ba0a99ff4a93c15aab85ef..8eb0b8e1c50c367d6de077219e9ac71c5539fb27 100644
--- a/web/modules/custom/joinup_workflow/tests/src/ExistingSite/JoinupWorkflowExistingSiteTestBase.php
+++ b/web/modules/custom/joinup_workflow/tests/src/ExistingSite/JoinupWorkflowExistingSiteTestBase.php
@@ -8,7 +8,6 @@
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Tests\joinup_test\ExistingSite\JoinupExistingSiteTestBase;
-use Drupal\Tests\rdf_entity\Traits\DrupalTestTraits\RdfEntityCreationTrait;
 use weitzman\DrupalTestTraits\Entity\UserCreationTrait;
 
 /**
@@ -18,7 +17,6 @@ abstract class JoinupWorkflowExistingSiteTestBase extends JoinupExistingSiteTest
 
   use StringTranslationTrait;
   use UserCreationTrait;
-  use RdfEntityCreationTrait;
 
   /**
    * The OG membership access manager service.
diff --git a/web/modules/custom/owner/tests/src/ExistingSite/OwnerWorkflowTest.php b/web/modules/custom/owner/tests/src/ExistingSite/OwnerWorkflowTest.php
index 808b97b4b2aee91d289ac8e535ab737d9e2f3964..bcab93fde63fd8c1f12505eb2602485a8dd20e55 100644
--- a/web/modules/custom/owner/tests/src/ExistingSite/OwnerWorkflowTest.php
+++ b/web/modules/custom/owner/tests/src/ExistingSite/OwnerWorkflowTest.php
@@ -187,7 +187,7 @@ public function createAccessProvider(): array {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    *
    * @return array
    *   Test cases.
@@ -254,7 +254,7 @@ public function readUpdateDeleteAccessProvider(): array {
    *     ],
    *   ],
    * ];
-   * @code
+   * @endcode
    * There can be multiple transitions that can lead to a specific state, so
    * the check is being done on allowed transitions.
    *
diff --git a/web/profiles/joinup/src/Form/SolutionsByLicenceForm.php b/web/profiles/joinup/src/Form/SolutionsByLicenceForm.php
index 9e0f1183e6418ef2ed6722dbe900569d8d822a3d..c8c5c0108ea09198a6e7904df9f01007ab0f29d4 100644
--- a/web/profiles/joinup/src/Form/SolutionsByLicenceForm.php
+++ b/web/profiles/joinup/src/Form/SolutionsByLicenceForm.php
@@ -212,7 +212,7 @@ protected function getCountQuery(?string $licence_id = NULL): string {
 }
 QUERY;
 
-    $extra_condition = $licence_id ? 'VALUES ?licence { ' . SparqlArg::uri($licence_id) . ' } ' : NULL;
+    $extra_condition = $licence_id ? 'VALUES ?licence { ' . SparqlArg::uri($licence_id) . ' } ' : '';
     $query = str_replace('@extra_condition', $extra_condition, $query);
     return $query;
   }
diff --git a/web/profiles/joinup/tests/src/ExistingSite/PinnableEntitiesTest.php b/web/profiles/joinup/tests/src/ExistingSite/PinnableEntitiesTest.php
index 584bad8293cc94ff661036a8de835215f0bc1377..67e30dfec0e736f4b53ca6f20ec1219bc52a52db 100644
--- a/web/profiles/joinup/tests/src/ExistingSite/PinnableEntitiesTest.php
+++ b/web/profiles/joinup/tests/src/ExistingSite/PinnableEntitiesTest.php
@@ -44,7 +44,9 @@ protected function setUp(): void {
    */
   public function testGetGroupsWherePinnedWithDeletedGroup() {
     // Create a test collection.
-    $collection = Collection::create();
+    $collection = Collection::create([
+      'label' => $this->getRandomGenerator()->string(),
+    ]);
     $collection->setWorkflowState('validated')->save();
 
     // Create a test news article inside the collection.