Issue #3437566 by mondrake, smustgrave: Replace trigger_error in TypedConfigManager with a logger

(cherry picked from commit a9668fd0fe4c6ccadceb898a3c1e385ada6fe1ca)
merge-requests/7353/head
catch 2024-04-03 11:43:15 +01:00
parent 1e955e9eef
commit 39d29ea630
4 changed files with 58 additions and 48 deletions

View File

@ -409,7 +409,7 @@ services:
arguments: ['@config.storage', 'config/schema', '', true, '%install_profile%'] arguments: ['@config.storage', 'config/schema', '', true, '%install_profile%']
config.typed: config.typed:
class: Drupal\Core\Config\TypedConfigManager class: Drupal\Core\Config\TypedConfigManager
arguments: ['@config.storage', '@config.storage.schema', '@cache.discovery', '@module_handler', '@class_resolver'] autowire: true
tags: tags:
- { name: plugin_manager_cache_clear } - { name: plugin_manager_cache_clear }
calls: calls:

View File

@ -2,7 +2,6 @@
namespace Drupal\Core\Config; namespace Drupal\Core\Config;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\Schema\ConfigSchemaAlterException; use Drupal\Core\Config\Schema\ConfigSchemaAlterException;
@ -16,26 +15,14 @@ use Drupal\Core\TypedData\MapDataDefinition;
use Drupal\Core\TypedData\TraversableTypedDataInterface; use Drupal\Core\TypedData\TraversableTypedDataInterface;
use Drupal\Core\TypedData\TypedDataManager; use Drupal\Core\TypedData\TypedDataManager;
use Drupal\Core\Validation\Plugin\Validation\Constraint\FullyValidatableConstraint; use Drupal\Core\Validation\Plugin\Validation\Constraint\FullyValidatableConstraint;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\Attribute\AutowireServiceClosure;
/** /**
* Manages config schema type plugins. * Manages config schema type plugins.
*/ */
class TypedConfigManager extends TypedDataManager implements TypedConfigManagerInterface { class TypedConfigManager extends TypedDataManager implements TypedConfigManagerInterface {
/**
* A storage instance for reading configuration data.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $configStorage;
/**
* A storage instance for reading configuration schema data.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $schemaStorage;
/** /**
* The array of plugin definitions, keyed by plugin id. * The array of plugin definitions, keyed by plugin id.
* *
@ -43,27 +30,22 @@ class TypedConfigManager extends TypedDataManager implements TypedConfigManagerI
*/ */
protected $definitions; protected $definitions;
/** public function __construct(
* Creates a new typed configuration manager. #[Autowire(service: 'config.storage')]
* protected StorageInterface $configStorage,
* @param \Drupal\Core\Config\StorageInterface $configStorage #[Autowire(service: 'config.storage.schema')]
* The storage object to use for reading schema data protected StorageInterface $schemaStorage,
* @param \Drupal\Core\Config\StorageInterface $schemaStorage #[Autowire(service: 'cache.discovery')]
* The storage object to use for reading schema data CacheBackendInterface $cache,
* @param \Drupal\Core\Cache\CacheBackendInterface $cache ModuleHandlerInterface $module_handler,
* The cache backend to use for caching the definitions. ClassResolverInterface $class_resolver,
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler #[AutowireServiceClosure('logger.channel.php')]
* The module handler. protected \Closure $loggerClosure,
* @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver ) {
* (optional) The class resolver.
*/
public function __construct(StorageInterface $configStorage, StorageInterface $schemaStorage, CacheBackendInterface $cache, ModuleHandlerInterface $module_handler, ClassResolverInterface $class_resolver = NULL) {
$this->configStorage = $configStorage;
$this->schemaStorage = $schemaStorage;
$this->setCacheBackend($cache, 'typed_config_definitions'); $this->setCacheBackend($cache, 'typed_config_definitions');
$this->alterInfo('config_schema_info'); $this->alterInfo('config_schema_info');
$this->moduleHandler = $module_handler; $this->moduleHandler = $module_handler;
$this->classResolver = $class_resolver ?: \Drupal::service('class_resolver'); $this->classResolver = $class_resolver;
} }
/** /**
@ -84,9 +66,11 @@ class TypedConfigManager extends TypedDataManager implements TypedConfigManagerI
if ($data === FALSE) { if ($data === FALSE) {
// For a typed config the data MUST exist. // For a typed config the data MUST exist.
$data = []; $data = [];
trigger_error(new FormattableMarkup('Missing required data for typed configuration: @config', [ /** @var \Psr\Log\LoggerInterface $logger */
'@config' => $name, $logger = ($this->loggerClosure)();
]), E_USER_ERROR); $logger->error('Missing required data for typed configuration: %config', [
'%config' => $name,
]);
} }
return $this->createFromNameAndData($name, $data); return $this->createFromNameAndData($name, $data);
} }

View File

@ -13,6 +13,7 @@ use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\TypedConfigManager; use Drupal\Core\Config\TypedConfigManager;
use Drupal\KernelTests\KernelTestBase; use Drupal\KernelTests\KernelTestBase;
use Drupal\views\Tests\ViewTestData; use Drupal\views\Tests\ViewTestData;
use Psr\Log\LoggerInterface;
/** /**
* Tests that test views provided by all modules match schema. * Tests that test views provided by all modules match schema.
@ -199,6 +200,10 @@ class TestViewsTest extends KernelTestBase {
* Tests default configuration data type. * Tests default configuration data type.
*/ */
public function testDefaultConfig() { public function testDefaultConfig() {
$loggerClosure = function (): LoggerInterface {
return $this->prophesize(LoggerInterface::class)->reveal();
};
// Create a typed config manager with access to configuration schema in // Create a typed config manager with access to configuration schema in
// every module, profile and theme. // every module, profile and theme.
$typed_config = new TypedConfigManager( $typed_config = new TypedConfigManager(
@ -206,7 +211,8 @@ class TestViewsTest extends KernelTestBase {
new TestInstallStorage(InstallStorage::CONFIG_SCHEMA_DIRECTORY), new TestInstallStorage(InstallStorage::CONFIG_SCHEMA_DIRECTORY),
\Drupal::service('cache.discovery'), \Drupal::service('cache.discovery'),
\Drupal::service('module_handler'), \Drupal::service('module_handler'),
\Drupal::service('class_resolver') \Drupal::service('class_resolver'),
$loggerClosure,
); );
$typed_config->setValidationConstraintManager(\Drupal::service('validation.constraint')); $typed_config->setValidationConstraintManager(\Drupal::service('validation.constraint'));
// Avoid restricting to the config schemas discovered. // Avoid restricting to the config schemas discovered.

View File

@ -5,12 +5,14 @@ namespace Drupal\KernelTests\Config;
use Drupal\Core\Config\Schema\Sequence; use Drupal\Core\Config\Schema\Sequence;
use Drupal\Core\Config\Schema\SequenceDataDefinition; use Drupal\Core\Config\Schema\SequenceDataDefinition;
use Drupal\Core\Config\Schema\TypedConfigInterface; use Drupal\Core\Config\Schema\TypedConfigInterface;
use Drupal\Core\Config\Schema\Undefined;
use Drupal\Core\Config\TypedConfigManager;
use Drupal\Core\TypedData\ComplexDataDefinitionInterface; use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
use Drupal\Core\TypedData\ComplexDataInterface; use Drupal\Core\TypedData\ComplexDataInterface;
use Drupal\Core\TypedData\Type\IntegerInterface; use Drupal\Core\TypedData\Type\IntegerInterface;
use Drupal\Core\TypedData\Type\StringInterface; use Drupal\Core\TypedData\Type\StringInterface;
use Drupal\KernelTests\KernelTestBase; use Drupal\KernelTests\KernelTestBase;
use PHPUnit\Framework\Error\Error; use Psr\Log\LoggerInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\ConstraintViolationListInterface;
/** /**
@ -46,15 +48,6 @@ class TypedConfigTest extends KernelTestBase {
/** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */ /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */
$typed_config_manager = \Drupal::service('config.typed'); $typed_config_manager = \Drupal::service('config.typed');
// Test non-existent data.
try {
$typed_config_manager->get('config_test.non_existent');
$this->fail('Expected error when trying to get non-existent typed config.');
}
catch (Error $e) {
$this->assertEquals('Missing required data for typed configuration: config_test.non_existent', $e->getMessage());
}
/** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */ /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */
$typed_config = $typed_config_manager->get('config_test.validation'); $typed_config = $typed_config_manager->get('config_test.validation');
@ -112,6 +105,33 @@ class TypedConfigTest extends KernelTestBase {
$this->assertEquals(['uuid', 'langcode', 'status', 'dependencies', 'id', 'label', 'weight', 'style', 'size', 'size_value', 'protected_property'], array_keys($typed_config->getElements())); $this->assertEquals(['uuid', 'langcode', 'status', 'dependencies', 'id', 'label', 'weight', 'style', 'size', 'size_value', 'protected_property'], array_keys($typed_config->getElements()));
} }
/**
* Tests non-existent data.
*/
public function testNonExistingTypedData(): void {
$loggerClosure = function (): LoggerInterface {
$logger = $this->prophesize(LoggerInterface::class);
$logger->error("Missing required data for typed configuration: %config", [
"%config" => "config_test.non_existent",
])->shouldBeCalledOnce();
return $logger->reveal();
};
// Create a typed config manager with the logger prophecy.
$typedConfigManager = new TypedConfigManager(
\Drupal::service('config.storage'),
\Drupal::service('config.storage.schema'),
\Drupal::service('cache.discovery'),
\Drupal::service('module_handler'),
\Drupal::service('class_resolver'),
$loggerClosure,
);
/** @var \Drupal\Core\Config\Schema\Undefined $typedConfig */
$typedConfig = $typedConfigManager->get('config_test.non_existent');
$this->assertInstanceOf(Undefined::class, $typedConfig);
}
/** /**
* Tests the behavior of `NotBlank` on required data. * Tests the behavior of `NotBlank` on required data.
* *