From f3b0c8db916677f64e57d046a809634540e1c51a Mon Sep 17 00:00:00 2001 From: catch <6915-catch@users.noreply.drupalcode.org> Date: Tue, 4 Mar 2025 11:32:22 +0000 Subject: [PATCH] Issue #3464388 by vidorado, mogtofu33, smustgrave, wim leers: SDC *.component.yml metadata is cached aggressively, gets in the way of component development --- core/core.services.yml | 1 + .../Core/Theme/ComponentPluginManager.php | 17 +++++++ .../Components/ComponentPluginManagerTest.php | 44 +++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/core/core.services.yml b/core/core.services.yml index bb73e29d505b..f3477c8d8853 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1887,6 +1887,7 @@ services: - '@file_system' - '@Drupal\Core\Theme\Component\SchemaCompatibilityChecker' - '@Drupal\Core\Theme\Component\ComponentValidator' + - '@keyvalue' - '%app.root%' Drupal\Core\Theme\ComponentPluginManager: '@plugin.manager.sdc' Drupal\Core\Template\Loader\ComponentLoader: diff --git a/core/lib/Drupal/Core/Theme/ComponentPluginManager.php b/core/lib/Drupal/Core/Theme/ComponentPluginManager.php index a0c93317699f..3e1b501e2241 100644 --- a/core/lib/Drupal/Core/Theme/ComponentPluginManager.php +++ b/core/lib/Drupal/Core/Theme/ComponentPluginManager.php @@ -12,6 +12,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ThemeHandlerInterface; use Drupal\Core\File\FileSystemInterface; +use Drupal\Core\KeyValueStore\KeyValueFactoryInterface; use Drupal\Core\Plugin\CategorizingPluginManagerTrait; use Drupal\Core\Plugin\DefaultPluginManager; use Drupal\Core\Plugin\Factory\ContainerFactory; @@ -62,6 +63,8 @@ class ComponentPluginManager extends DefaultPluginManager implements Categorizin * The compatibility checker. * @param \Drupal\Core\Theme\Component\ComponentValidator $componentValidator * The component validator. + * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $keyValueFactory + * The key value factory. * @param string $appRoot * The application root. */ @@ -75,6 +78,7 @@ public function __construct( protected FileSystemInterface $fileSystem, protected SchemaCompatibilityChecker $compatibilityChecker, protected ComponentValidator $componentValidator, + protected KeyValueFactoryInterface $keyValueFactory, protected string $appRoot, ) { // We are skipping the call to the parent constructor to avoid initializing @@ -124,6 +128,19 @@ public function createInstance($plugin_id, array $configuration = []): Component } } + /** + * {@inheritdoc} + */ + public function getDefinitions(): array { + $development_settings = $this->keyValueFactory->get('development_settings'); + $twig_debug = $development_settings->get('twig_debug', FALSE); + $twig_cache_disable = $development_settings->get('twig_cache_disable', FALSE); + if ($twig_debug || $twig_cache_disable) { + return $this->findDefinitions(); + } + return parent::getDefinitions(); + } + /** * Gets a component for rendering. * diff --git a/core/tests/Drupal/KernelTests/Components/ComponentPluginManagerTest.php b/core/tests/Drupal/KernelTests/Components/ComponentPluginManagerTest.php index 1f110e36b4b5..59393564944d 100644 --- a/core/tests/Drupal/KernelTests/Components/ComponentPluginManagerTest.php +++ b/core/tests/Drupal/KernelTests/Components/ComponentPluginManagerTest.php @@ -5,6 +5,7 @@ namespace Drupal\KernelTests\Components; use Drupal\Core\Render\Component\Exception\ComponentNotFoundException; +use Drupal\Core\Cache\CacheBackendInterface; /** * Tests the component plugin manager. @@ -49,4 +50,47 @@ public function testMismatchingFolderName(): void { $this->manager->find('sdc_theme_test:mismatching-folder-name'); } + /** + * Test component definitions caching depending on twig debug/cache settings. + * + * @param bool $twigDebug + * Whether twig debug is enabled. + * @param bool $cacheEnabled + * Whether cache is enabled. + * @param bool $expectCacheGet + * Whether we expect the cache to be called. + * + * @dataProvider providerTestComponentCachingDependingOnDevelopmentSettings + */ + public function testComponentCachingDependingOnDevelopmentSettings(bool $twigDebug, bool $cacheEnabled, bool $expectCacheGet): void { + // Set the development settings. + $developmentSettings = $this->keyValue->get('development_settings'); + $developmentSettings->set('twig_debug', $twigDebug); + $developmentSettings->set('twig_cache_disable', !$cacheEnabled); + + // Set the cache backend as a spy mock. + $cacheBackend = $this->createMock(CacheBackendInterface::class); + $cacheBackend->expects($expectCacheGet ? $this->once() : $this->never()) + ->method('get') + ->with('cache_key'); + $this->manager->setCacheBackend($cacheBackend, 'cache_key'); + + // Make two calls to getDefinitions() to ensure the + // cache is/isn't called if it should/shouldn't be. + $this->manager->getDefinitions(); + $this->manager->getDefinitions(); + } + + /** + * Data provider for testComponentCachingDependingOnDevelopmentSettings(). + */ + public static function providerTestComponentCachingDependingOnDevelopmentSettings(): array { + return [ + 'Debug enabled, cache enabled' => [TRUE, TRUE, FALSE], + 'Debug enabled, cache disabled' => [TRUE, FALSE, FALSE], + 'Debug disabled, cache enabled' => [FALSE, TRUE, TRUE], + 'Debug disabled, cache disabled' => [FALSE, FALSE, FALSE], + ]; + } + } -- GitLab