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%']
config.typed:
class: Drupal\Core\Config\TypedConfigManager
arguments: ['@config.storage', '@config.storage.schema', '@cache.discovery', '@module_handler', '@class_resolver']
autowire: true
tags:
- { name: plugin_manager_cache_clear }
calls:

View File

@ -2,7 +2,6 @@
namespace Drupal\Core\Config;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\Schema\ConfigSchemaAlterException;
@ -16,26 +15,14 @@ use Drupal\Core\TypedData\MapDataDefinition;
use Drupal\Core\TypedData\TraversableTypedDataInterface;
use Drupal\Core\TypedData\TypedDataManager;
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.
*/
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.
*
@ -43,27 +30,22 @@ class TypedConfigManager extends TypedDataManager implements TypedConfigManagerI
*/
protected $definitions;
/**
* Creates a new typed configuration manager.
*
* @param \Drupal\Core\Config\StorageInterface $configStorage
* The storage object to use for reading schema data
* @param \Drupal\Core\Config\StorageInterface $schemaStorage
* The storage object to use for reading schema data
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache backend to use for caching the definitions.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @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;
public function __construct(
#[Autowire(service: 'config.storage')]
protected StorageInterface $configStorage,
#[Autowire(service: 'config.storage.schema')]
protected StorageInterface $schemaStorage,
#[Autowire(service: 'cache.discovery')]
CacheBackendInterface $cache,
ModuleHandlerInterface $module_handler,
ClassResolverInterface $class_resolver,
#[AutowireServiceClosure('logger.channel.php')]
protected \Closure $loggerClosure,
) {
$this->setCacheBackend($cache, 'typed_config_definitions');
$this->alterInfo('config_schema_info');
$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) {
// For a typed config the data MUST exist.
$data = [];
trigger_error(new FormattableMarkup('Missing required data for typed configuration: @config', [
'@config' => $name,
]), E_USER_ERROR);
/** @var \Psr\Log\LoggerInterface $logger */
$logger = ($this->loggerClosure)();
$logger->error('Missing required data for typed configuration: %config', [
'%config' => $name,
]);
}
return $this->createFromNameAndData($name, $data);
}

View File

@ -13,6 +13,7 @@ use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\TypedConfigManager;
use Drupal\KernelTests\KernelTestBase;
use Drupal\views\Tests\ViewTestData;
use Psr\Log\LoggerInterface;
/**
* Tests that test views provided by all modules match schema.
@ -199,6 +200,10 @@ class TestViewsTest extends KernelTestBase {
* Tests default configuration data type.
*/
public function testDefaultConfig() {
$loggerClosure = function (): LoggerInterface {
return $this->prophesize(LoggerInterface::class)->reveal();
};
// Create a typed config manager with access to configuration schema in
// every module, profile and theme.
$typed_config = new TypedConfigManager(
@ -206,7 +211,8 @@ class TestViewsTest extends KernelTestBase {
new TestInstallStorage(InstallStorage::CONFIG_SCHEMA_DIRECTORY),
\Drupal::service('cache.discovery'),
\Drupal::service('module_handler'),
\Drupal::service('class_resolver')
\Drupal::service('class_resolver'),
$loggerClosure,
);
$typed_config->setValidationConstraintManager(\Drupal::service('validation.constraint'));
// 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\SequenceDataDefinition;
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\ComplexDataInterface;
use Drupal\Core\TypedData\Type\IntegerInterface;
use Drupal\Core\TypedData\Type\StringInterface;
use Drupal\KernelTests\KernelTestBase;
use PHPUnit\Framework\Error\Error;
use Psr\Log\LoggerInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;
/**
@ -46,15 +48,6 @@ class TypedConfigTest extends KernelTestBase {
/** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */
$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 */
$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()));
}
/**
* 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.
*