Skip to content

Instantly share code, notes, and snippets.

@junaidpv
Created November 12, 2025 14:49
Show Gist options
  • Select an option

  • Save junaidpv/19163c62a6328a2dc82db3718d9a275d to your computer and use it in GitHub Desktop.

Select an option

Save junaidpv/19163c62a6328a2dc82db3718d9a275d to your computer and use it in GitHub Desktop.
diff --git a/domain_config/src/DomainConfigOverrider.php b/domain_config/src/DomainConfigOverrider.php
index 0ff3bcb0f13a7d615e6d6c6b7cb32c9f42c211ad..51cbbd6b94eced2ae8f6058ccae2cf8abda4d693 100644
--- a/domain_config/src/DomainConfigOverrider.php
+++ b/domain_config/src/DomainConfigOverrider.php
@@ -28,6 +28,19 @@ class DomainConfigOverrider implements ConfigFactoryOverrideInterface {
*/
protected const DOMAIN_CONFIG_PREFIX = 'domain.config.';
+ /**
+ * Cache of previously looked up configuration overrides.
+ *
+ * Stores configuration override results keyed by a hash of config names
+ * and language ID to prevent repeating expensive lookup operations.
+ * The array format is:
+ * - key: MD5 hash of imploded config names concatenated with language ID
+ * - value: Array of configuration overrides for those names.
+ *
+ * @var array
+ */
+ protected static $overridesCache = [];
+
/**
* The domain negotiator.
*
@@ -111,6 +124,13 @@ class DomainConfigOverrider implements ConfigFactoryOverrideInterface {
public function __construct(StorageInterface $storage, ModuleHandlerInterface $module_handler) {
$this->storage = $storage;
$this->moduleHandler = $module_handler;
+ $this->initialize();
+ }
+
+ /**
+ * Initializes the domain configuration overrider state.
+ */
+ protected function initialize() {
// Check if domain configs are available and if there are any overrides
// in settings.php. If not, we can skip the overrides.
// See https://www.drupal.org/project/domain/issues/3126532.
@@ -134,6 +154,24 @@ class DomainConfigOverrider implements ConfigFactoryOverrideInterface {
}
}
+ /**
+ * Reset the override cache and context.
+ *
+ * Used mainly for testing.
+ */
+ public function reset() {
+ // Reset the cache.
+ static::$overridesCache = [];
+ // Check for configuration overrides updates.
+ $this->initialize();
+ if ($this->hasOverrides) {
+ // Reset the context.
+ $this->domain = NULL;
+ $this->contextSet = NULL;
+ $this->cacheSuffix = NULL;
+ }
+ }
+
/**
* {@inheritdoc}
*/
@@ -148,12 +186,11 @@ class DomainConfigOverrider implements ConfigFactoryOverrideInterface {
}
else {
// Try to prevent repeating lookups.
- static $lookups;
// Key should be a known length, so hash.
// We add the language as a suffix as it can change after negotiation.
$key = md5(implode(':', $names) . ':' . $this->language->getId());
- if (isset($lookups[$key])) {
- return $lookups[$key];
+ if (isset(static::$overridesCache[$key])) {
+ return static::$overridesCache[$key];
}
// Prepare our overrides.
@@ -163,7 +200,7 @@ class DomainConfigOverrider implements ConfigFactoryOverrideInterface {
// So ensure that we are _not_ looking up a domain.record.*.
// We also skip overriding the domain.settings config.
if ($this->isInternalName(current($names))) {
- $lookups[$key] = $overrides;
+ static::$overridesCache[$key] = $overrides;
return $overrides;
}
@@ -212,12 +249,12 @@ class DomainConfigOverrider implements ConfigFactoryOverrideInterface {
}
}
}
- $lookups[$key] = $overrides;
+ static::$overridesCache[$key] = $overrides;
}
else {
if ($this->domain === FALSE) {
// No domain exists, so we can safely cache the empty overrides.
- $lookups[$key] = $overrides;
+ static::$overridesCache[$key] = $overrides;
}
}
diff --git a/domain_source/src/HttpKernel/DomainSourceRouteMatcher.php b/domain_source/src/HttpKernel/DomainSourceRouteMatcher.php
index 491b4805bb8bec450ddc9c74996987c95f0454e1..dbe15f882eb589d370acab0b9e6bf81f89bb1007 100644
--- a/domain_source/src/HttpKernel/DomainSourceRouteMatcher.php
+++ b/domain_source/src/HttpKernel/DomainSourceRouteMatcher.php
@@ -2,6 +2,7 @@
namespace Drupal\domain_source\HttpKernel;
+use Drupal\Core\Routing\CacheableRouteProviderInterface;
use Drupal\Core\Routing\RequestContext;
use Drupal\Core\Routing\RouteObjectInterface;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
@@ -52,6 +53,10 @@ class DomainSourceRouteMatcher {
protected static function getRouteProvider() {
if (!isset(static::$routeProvider)) {
static::$routeProvider = \Drupal::service('domain_source.route_provider');
+ if (static::$routeProvider instanceof CacheableRouteProviderInterface) {
+ $domain_id = \Drupal::service('domain.negotiator')->getActiveId();
+ static::$routeProvider->addExtraCacheKeyPart('domain', $domain_id);
+ }
}
return static::$routeProvider;
}
diff --git a/domain_source/tests/src/Functional/DomainSourceRouteMatcherTest.php b/domain_source/tests/src/Functional/DomainSourceRouteMatcherTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7d51f81ab589d005e5a9f3413fe3aa6372c1bc13
--- /dev/null
+++ b/domain_source/tests/src/Functional/DomainSourceRouteMatcherTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace Drupal\Tests\domain_source\Functional;
+
+use Drupal\domain_source\HttpKernel\DomainSourceRouteMatcher;
+use Drupal\Tests\domain\Functional\DomainTestBase;
+
+/**
+ * Tests that route match results are correctly cached per domain.
+ *
+ * Verifies that when different domains have different home page
+ * configurations via system.site, the routeMatch() method returns
+ * different cached results for each domain.
+ *
+ * @group domain_source
+ */
+class DomainSourceRouteMatcherTest extends DomainTestBase {
+
+ /**
+ * Disabled config schema checking for domain config.
+ *
+ * @var bool
+ */
+ protected $strictConfigSchema = FALSE;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected static $modules = [
+ 'domain',
+ 'domain_source',
+ 'domain_config',
+ 'domain_config_test',
+ 'node',
+ 'system',
+ 'user',
+ ];
+
+ /**
+ * Test nodes for different home pages.
+ *
+ * @var \Drupal\node\NodeInterface[]
+ */
+ protected $testNodes;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp(): void {
+ parent::setUp();
+
+ // Create test domains. This will create domains with IDs like
+ // example_com, one_example_com, etc.
+ // The domain_config_test module provides pre-configured domain configs.
+ $this->domainCreateTestDomains(5);
+
+ // Create test nodes that match the domain_config_test expectations.
+ $this->testNodes[0] = $this->drupalCreateNode([
+ 'type' => 'page',
+ 'title' => 'Node 1',
+ 'status' => 1,
+ ]);
+ $this->testNodes[1] = $this->drupalCreateNode([
+ 'type' => 'page',
+ 'title' => 'Node 2',
+ 'status' => 1,
+ ]);
+ }
+
+ /**
+ * Tests that routeMatch returns different cached results per domain.
+ */
+ public function testRouteMatchReturnsDifferentResultsPerDomain() {
+ // Load specific domains that have pre-configured home pages.
+ // one_example_com has /node/1 configured as front page.
+ // example_com has the default /node configured.
+ $domain_storage = \Drupal::entityTypeManager()->getStorage('domain');
+ $domain_one = $domain_storage->load('one_example_com');
+ $domain_default = $domain_storage->load('example_com');
+
+ $this->assertNotNull($domain_one, 'Domain one_example_com should exist.');
+ $this->assertNotNull($domain_default, 'Domain example_com should exist.');
+
+ // Set one_example_com as active (has /node/1 as front page).
+ $negotiator = \Drupal::service('domain.negotiator');
+ $negotiator->setActiveDomain($domain_one);
+ // Reset the domain config overrider to ensure a clean state.
+ \Drupal::service('domain_config.overrider')->reset();
+ // Reset the static route provider to ensure a clean state.
+ $this->resetRouteProviderStatic();
+
+ // Call routeMatch for the home page with domain_one.
+ $match1 = DomainSourceRouteMatcher::routeMatch('/');
+
+ // Verify we got a match for domain_one that contains route information.
+ $this->assertIsArray($match1, 'Route match should return an array.');
+ $this->assertArrayHasKey('_route', $match1, 'Route match should contain _route.');
+
+ // Domain_one should route to entity.node.canonical (because /node/1).
+ $route1_name = $match1['_route'];
+ $this->assertEquals('entity.node.canonical', $route1_name,
+ 'Domain one_example_com should route to node page.');
+
+ // Now switch to example_com (has /node as front page).
+ $negotiator->setActiveDomain($domain_default);
+ // Reset the domain config overrider to ensure a clean state.
+ \Drupal::service('domain_config.overrider')->reset();
+ // Reset the static route provider to force re-initialization.
+ $this->resetRouteProviderStatic();
+
+ // Call routeMatch for the home page with domain_default.
+ $match2 = DomainSourceRouteMatcher::routeMatch('/');
+
+ // Verify we got a match for domain_default.
+ $this->assertIsArray($match2, 'Route match should return an array.');
+ $this->assertArrayHasKey('_route', $match2, 'Route match should contain _route.');
+
+ // Domain_default routes are different - it goes to system.404 or
+ // a listing page, not a specific node.
+ $route2_name = $match2['_route'];
+
+ // CRITICAL: Verify the routes are actually different.
+ // This proves that the cache is per-domain.
+ $this->assertNotEquals($route1_name, $route2_name,
+ 'Different domains MUST return different cached routes.');
+ }
+
+ /**
+ * Resets the static routeProvider property in DomainSourceRouteMatcher.
+ */
+ protected function resetRouteProviderStatic(): void {
+ $reflection = new \ReflectionClass(DomainSourceRouteMatcher::class);
+ $property = $reflection->getProperty('routeProvider');
+ $property->setAccessible(TRUE);
+ $property->setValue(NULL, NULL);
+ }
+
+}
diff --git a/domain_source/tests/src/Functional/DomainSourceRouterProviderTest.php b/domain_source/tests/src/Functional/DomainSourceRouterProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a303f08541ee01deb43e6c72e40215a063e956e
--- /dev/null
+++ b/domain_source/tests/src/Functional/DomainSourceRouterProviderTest.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace Drupal\Tests\domain_source\Functional;
+
+use Drupal\domain_source\HttpKernel\DomainSourceRouteMatcher;
+use Drupal\Tests\domain\Functional\DomainTestBase;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Tests that route cache IDs include the domain ID.
+ *
+ * This test verifies the complete integration: when
+ * DomainSourceRouteMatcher::getRouteProvider() injects the domain ID via
+ * addExtraCacheKeyPart(), the cache ID returned by
+ * DomainSourceRouteProvider::getRouteCollectionCacheId() includes it.
+ *
+ * @group domain_source
+ */
+class DomainSourceRouterProviderTest extends DomainTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ protected static $modules = [
+ 'domain',
+ 'domain_source',
+ 'node',
+ ];
+
+ /**
+ * The domain source route provider service.
+ *
+ * @var \Drupal\domain_source\HttpKernel\DomainSourceRouteProvider
+ */
+ protected $routeProvider;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp(): void {
+ parent::setUp();
+
+ // Create two test domains.
+ $this->domainCreateTestDomains(2);
+
+ // Get the route provider service.
+ $this->routeProvider = $this->container->get('domain_source.route_provider');
+ }
+
+ /**
+ * Tests that cache ID includes the domain ID.
+ */
+ public function testCacheIdIncludesDomainId() {
+ // Load the domains.
+ $domains = \Drupal::entityTypeManager()
+ ->getStorage('domain')
+ ->loadMultiple();
+ $domain_values = array_values($domains);
+ $domain1 = $domain_values[0];
+ $domain2 = $domain_values[1];
+
+ // Create a request.
+ $request = Request::create('/node');
+
+ // Set the first domain as active.
+ \Drupal::service('domain.negotiator')->setActiveDomain($domain1);
+
+ // Reset and reinitialize for the first domain.
+ $this->resetRouteProviderStatic();
+
+ // Get the cache ID.
+ $cache_id1 = $this->getRouteCollectionCacheId($request);
+
+ // Verify that the cache ID contains the domain identifier.
+ $this->assertStringContainsString(
+ '[domain]=' . $domain1->id(),
+ $cache_id1,
+ 'Cache ID should contain the first domain ID.'
+ );
+
+ // Now switch to the second domain.
+ \Drupal::service('domain.negotiator')->setActiveDomain($domain2);
+
+ // Reset and reinitialize for the second domain.
+ $this->resetRouteProviderStatic();
+
+ // Get the cache ID for the second domain.
+ $cache_id2 = $this->getRouteCollectionCacheId($request);
+
+ // Verify that the cache ID contains the second domain identifier.
+ $this->assertStringContainsString(
+ '[domain]=' . $domain2->id(),
+ $cache_id2,
+ 'Cache ID should contain the second domain ID.'
+ );
+ }
+
+ /**
+ * Tests the cache ID format.
+ */
+ public function testCacheIdFormat() {
+ // Load a domain.
+ $domains = \Drupal::entityTypeManager()
+ ->getStorage('domain')
+ ->loadMultiple();
+ $domain = reset($domains);
+
+ // Set the domain as active.
+ \Drupal::service('domain.negotiator')->setActiveDomain($domain);
+
+ // Reset and initialize.
+ $this->resetRouteProviderStatic();
+
+ // Create a request.
+ $request = Request::create('/node');
+
+ // Get the cache ID.
+ $cache_id = $this->getRouteCollectionCacheId($request);
+
+ // Verify the format: route:[key1]=val1:[key2]=val2:...:/path.
+ $this->assertMatchesRegularExpression(
+ '/^route:.*\[domain\]=' . preg_quote($domain->id(), '/') . '.*:\/node$/',
+ $cache_id,
+ 'Cache ID should have the correct format with domain information.'
+ );
+ }
+
+ /**
+ * Resets the static routeProvider property in DomainSourceRouteMatcher.
+ *
+ * This method uses reflection to reset the static route provider property
+ * to NULL, forcing re-initialization of the route provider. This is necessary
+ * to ensure that domain-specific cache key parts are properly injected when
+ * switching between different active domains during testing.
+ */
+ protected function resetRouteProviderStatic(): void {
+ // Reset the static route provider to force re-initialization.
+ $reflection = new \ReflectionClass(DomainSourceRouteMatcher::class);
+ $property = $reflection->getProperty('routeProvider');
+ $property->setAccessible(TRUE);
+ $property->setValue(NULL, NULL);
+ // Call getRouteProvider() which injects the domain ID.
+ $method = $reflection->getMethod('getRouteProvider');
+ $method->setAccessible(TRUE);
+ $method->invoke(NULL);
+ }
+
+ /**
+ * Gets the route collection cache ID from the route provider.
+ *
+ * This helper method uses reflection to access the protected
+ * getRouteCollectionCacheId method from the parent RouteProvider class.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * The HTTP request.
+ *
+ * @return string
+ * The cache ID for the route collection.
+ */
+ protected function getRouteCollectionCacheId(Request $request): string {
+ // Get the cache ID for the second domain.
+ $reflection = new \ReflectionClass($this->routeProvider);
+ $get_cache_id_method = $reflection->getMethod('getRouteCollectionCacheId');
+ $get_cache_id_method->setAccessible(TRUE);
+ return $get_cache_id_method->invoke($this->routeProvider, $request);
+ }
+
+}
diff --git a/domain_source/tests/src/Unit/DomainSourceRouterProviderTest.php b/domain_source/tests/src/Unit/DomainSourceRouterProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..944ad2a9ae2c6f1eebe93b72202ade06f2150896
--- /dev/null
+++ b/domain_source/tests/src/Unit/DomainSourceRouterProviderTest.php
@@ -0,0 +1,233 @@
+<?php
+
+namespace Drupal\Tests\domain_source\Unit;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\Core\Path\CurrentPathStack;
+use Drupal\Core\PathProcessor\PathProcessorManager;
+use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\State\StateInterface;
+use Drupal\domain\DomainNegotiatorInterface;
+use Drupal\domain_source\HttpKernel\DomainSourceRouteProvider;
+use Drupal\domain_source\HttpKernel\DomainSourceRouteMatcher;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Tests that cache IDs include the domain ID.
+ *
+ * Verifies that when DomainSourceRouteMatcher::getRouteProvider() injects
+ * the domain ID via addExtraCacheKeyPart(), the cache ID returned by
+ * DomainSourceRouteProvider::getRouteCollectionCacheId() includes it.
+ *
+ * @coversDefaultClass \Drupal\domain_source\HttpKernel\DomainSourceRouteProvider
+ * @group domain_source
+ */
+class DomainSourceRouterProviderTest extends UnitTestCase {
+
+ /**
+ * The domain source route provider.
+ *
+ * @var \Drupal\domain_source\HttpKernel\DomainSourceRouteProvider
+ */
+ protected $routeProvider;
+
+ /**
+ * The mocked domain negotiator.
+ *
+ * @var \Drupal\domain\DomainNegotiatorInterface|\PHPUnit\Framework\MockObject\MockObject
+ */
+ protected $domainNegotiator;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp(): void {
+ parent::setUp();
+
+ // Mock all the dependencies required by RouteProvider.
+ $database = $this->createMock(Connection::class);
+ $state = $this->createMock(StateInterface::class);
+ $current_path = $this->createMock(CurrentPathStack::class);
+ $cache = $this->createMock(CacheBackendInterface::class);
+ $path_processor = $this->createMock(PathProcessorManager::class);
+ $cache_tags_invalidator = $this->createMock(CacheTagsInvalidatorInterface::class);
+
+ // Mock language manager to return a language.
+ $language = $this->createMock(LanguageInterface::class);
+ $language->method('getId')->willReturn('en');
+
+ $language_manager = $this->createMock(LanguageManagerInterface::class);
+ $language_manager->method('getCurrentLanguage')->willReturn($language);
+
+ // Configure path processor to return the path as-is.
+ $path_processor->method('processInbound')
+ ->willReturnCallback(function ($path) {
+ return $path;
+ });
+
+ // Create the actual DomainSourceRouteProvider with all dependencies.
+ $this->routeProvider = new DomainSourceRouteProvider(
+ $database,
+ $state,
+ $current_path,
+ $cache,
+ $path_processor,
+ $cache_tags_invalidator,
+ 'router',
+ $language_manager
+ );
+
+ // Mock domain negotiator.
+ $this->domainNegotiator = $this->createMock(DomainNegotiatorInterface::class);
+
+ // Set up the container.
+ $container = $this->createMock(ContainerInterface::class);
+ $container->method('get')
+ ->willReturnMap([
+ ['domain.negotiator', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->domainNegotiator],
+ ['domain_source.route_provider', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->routeProvider],
+ ]);
+
+ \Drupal::setContainer($container);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function tearDown(): void {
+ parent::tearDown();
+
+ // Reset the static properties.
+ $reflection = new \ReflectionClass(DomainSourceRouteMatcher::class);
+ $property = $reflection->getProperty('routeProvider');
+ $property->setAccessible(TRUE);
+ $property->setValue(NULL, NULL);
+ }
+
+ /**
+ * Tests that cache ID includes the domain ID.
+ *
+ * @covers ::getRouteCollectionCacheId
+ */
+ public function testCacheIdIncludesDomainId() {
+ $domain_id = 'example_com';
+
+ // Configure the domain negotiator to return a specific domain ID.
+ $this->domainNegotiator->method('getActiveId')->willReturn($domain_id);
+
+ // Reset the static route provider.
+ $reflection = new \ReflectionClass(DomainSourceRouteMatcher::class);
+ $property = $reflection->getProperty('routeProvider');
+ $property->setAccessible(TRUE);
+ $property->setValue(NULL, NULL);
+
+ // Call DomainSourceRouteMatcher::getRouteProvider()
+ // which injects the domain.
+ $method = $reflection->getMethod('getRouteProvider');
+ $method->setAccessible(TRUE);
+ $method->invoke(NULL);
+
+ // Create a request.
+ $request = Request::create('/test-path');
+
+ // Get the cache ID using reflection.
+ $reflection = new \ReflectionClass($this->routeProvider);
+ $get_cache_id_method = $reflection->getMethod('getRouteCollectionCacheId');
+ $get_cache_id_method->setAccessible(TRUE);
+ $cache_id = $get_cache_id_method->invoke($this->routeProvider, $request);
+
+ // Verify that the cache ID contains the domain identifier.
+ $this->assertStringContainsString('[domain]=' . $domain_id, $cache_id, 'Cache ID should contain the domain ID.');
+ $this->assertStringContainsString('/test-path', $cache_id, 'Cache ID should contain the path.');
+ }
+
+ /**
+ * Tests that different domains produce different cache IDs.
+ *
+ * @covers ::getRouteCollectionCacheId
+ */
+ public function testDifferentDomainsProduceDifferentCacheIds() {
+ $domain_id1 = 'example_com';
+ $domain_id2 = 'test_com';
+
+ // Configure for first domain.
+ $this->domainNegotiator->method('getActiveId')->willReturn($domain_id1);
+
+ // Reset and call getRouteProvider for first domain.
+ $this->resetRouteProviderStatic();
+ $this->callGetRouteProvider();
+
+ // Get cache ID for first domain.
+ $request = Request::create('/test-path');
+ $cache_id1 = $this->getRouteCollectionCacheId($request);
+
+ // Now configure for second domain.
+ $this->domainNegotiator = $this->createMock(DomainNegotiatorInterface::class);
+ $this->domainNegotiator->method('getActiveId')->willReturn($domain_id2);
+
+ // Update container with new negotiator.
+ $container = $this->createMock(ContainerInterface::class);
+ $container->method('get')
+ ->willReturnMap([
+ ['domain.negotiator', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->domainNegotiator],
+ ['domain_source.route_provider', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->routeProvider],
+ ]);
+ \Drupal::setContainer($container);
+
+ // Reset and call getRouteProvider for second domain.
+ $this->resetRouteProviderStatic();
+ $this->callGetRouteProvider();
+
+ // Get cache ID for second domain.
+ $cache_id2 = $this->getRouteCollectionCacheId($request);
+
+ // Verify both cache IDs contain their respective domain IDs.
+ $this->assertStringContainsString('[domain]=' . $domain_id1, $cache_id1);
+ $this->assertStringContainsString('[domain]=' . $domain_id2, $cache_id2);
+
+ // Verify the cache IDs are different.
+ $this->assertNotEquals($cache_id1, $cache_id2, 'Cache IDs should be different for different domains.');
+ }
+
+ /**
+ * Helper method to reset the static route provider property.
+ */
+ protected function resetRouteProviderStatic(): void {
+ $reflection = new \ReflectionClass(DomainSourceRouteMatcher::class);
+ $property = $reflection->getProperty('routeProvider');
+ $property->setAccessible(TRUE);
+ $property->setValue(NULL, NULL);
+ }
+
+ /**
+ * Helper method to call getRouteProvider.
+ */
+ protected function callGetRouteProvider(): void {
+ $reflection = new \ReflectionClass(DomainSourceRouteMatcher::class);
+ $method = $reflection->getMethod('getRouteProvider');
+ $method->setAccessible(TRUE);
+ $method->invoke(NULL);
+ }
+
+ /**
+ * Helper method to get the route collection cache ID.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * The request.
+ *
+ * @return string
+ * The cache ID.
+ */
+ protected function getRouteCollectionCacheId(Request $request): string {
+ $reflection = new \ReflectionClass($this->routeProvider);
+ $method = $reflection->getMethod('getRouteCollectionCacheId');
+ $method->setAccessible(TRUE);
+ return $method->invoke($this->routeProvider, $request);
+ }
+
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment