Newer
Older
<?php
/**
* @file
* Contains \Drupal\Core\Config\Testing\ConfigSchemaChecker.
*/
namespace Drupal\Core\Config\Testing;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\Config\Schema\SchemaCheckTrait;
use Drupal\Core\Config\Schema\SchemaIncompleteException;
Alex Pott
committed
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Listens to the config save event and validates schema.
*
* If tests have the $strictConfigSchema property set to TRUE this event
* listener will be added to the container and throw exceptions if configuration
* is invalid.
*
* @see \Drupal\simpletest\WebTestBase::setUp()
Alex Pott
committed
* @see \Drupal\KernelTests\KernelTestBase::register()
*/
class ConfigSchemaChecker implements EventSubscriberInterface {
use SchemaCheckTrait;
/**
* The typed config manger.
*
* @var \Drupal\Core\Config\TypedConfigManagerInterface
*/
protected $typedManager;
/**
* An array of config checked already. Keyed by config name and a checksum.
*
* @var array
*/
protected $checked = array();
Alex Bronstein
committed
/**
* An array of config object names that are excluded from schema checking.
*
* @var string[]
*/
protected $exclude = array();
/**
* Constructs the ConfigSchemaChecker object.
*
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_manager
* The typed config manager.
Alex Bronstein
committed
* @param string[] $exclude
* An array of config object names that are excluded from schema checking.
*/
Alex Bronstein
committed
public function __construct(TypedConfigManagerInterface $typed_manager, array $exclude = array()) {
$this->typedManager = $typed_manager;
Alex Bronstein
committed
$this->exclude = $exclude;
}
/**
* Checks that configuration complies with its schema on config save.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The configuration event.
*
* @throws \Drupal\Core\Config\Schema\SchemaIncompleteException
* Exception thrown when configuration does not match its schema.
*/
public function onConfigSave(ConfigCrudEvent $event) {
Alex Pott
committed
// Only validate configuration if in the default collection. Other
// collections may have incomplete configuration (for example language
// overrides only). These are not valid in themselves.
$saved_config = $event->getConfig();
Alex Pott
committed
if ($saved_config->getStorage()->getCollectionName() != StorageInterface::DEFAULT_COLLECTION) {
return;
}
$name = $saved_config->getName();
$data = $saved_config->get();
$checksum = hash('crc32b', serialize($data));
Alex Bronstein
committed
if (!in_array($name, $this->exclude) && !isset($this->checked[$name . ':' . $checksum])) {
$this->checked[$name . ':' . $checksum] = TRUE;
$errors = $this->checkConfigSchema($this->typedManager, $name, $data);
if ($errors === FALSE) {
catch
committed
throw new SchemaIncompleteException("No schema for $name");
}
elseif (is_array($errors)) {
$text_errors = [];
foreach ($errors as $key => $error) {
$text_errors[] = SafeMarkup::format('@key @error', array('@key' => $key, '@error' => $error));
catch
committed
throw new SchemaIncompleteException("Schema errors for $name with the following errors: " . implode(', ', $text_errors));
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[ConfigEvents::SAVE][] = array('onConfigSave', 255);
return $events;
}
}