Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 61 |
SchemaCheckTrait | |
0.00% |
0 / 1 |
|
0.00% |
0 / 2 |
870 | |
0.00% |
0 / 61 |
checkConfigSchema | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 19 |
|||
checkValue | |
0.00% |
0 / 1 |
600 | |
0.00% |
0 / 42 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\Core\Config\Schema\SchemaCheckTrait. | |
*/ | |
namespace Drupal\Core\Config\Schema; | |
use Drupal\Core\Config\TypedConfigManagerInterface; | |
use Drupal\Core\TypedData\PrimitiveInterface; | |
use Drupal\Core\TypedData\TraversableTypedDataInterface; | |
use Drupal\Core\TypedData\Type\BooleanInterface; | |
use Drupal\Core\TypedData\Type\StringInterface; | |
use Drupal\Core\TypedData\Type\FloatInterface; | |
use Drupal\Core\TypedData\Type\IntegerInterface; | |
/** | |
* Provides a trait for checking configuration schema. | |
*/ | |
trait SchemaCheckTrait { | |
/** | |
* The config schema wrapper object for the configuration object under test. | |
* | |
* @var \Drupal\Core\Config\Schema\Element | |
*/ | |
protected $schema; | |
/** | |
* The configuration object name under test. | |
* | |
* @var string | |
*/ | |
protected $configName; | |
/** | |
* Checks the TypedConfigManager has a valid schema for the configuration. | |
* | |
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config | |
* The TypedConfigManager. | |
* @param string $config_name | |
* The configuration name. | |
* @param array $config_data | |
* The configuration data, assumed to be data for a top-level config object. | |
* | |
* @return array|bool | |
* FALSE if no schema found. List of errors if any found. TRUE if fully | |
* valid. | |
*/ | |
public function checkConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data) { | |
// We'd like to verify that the top-level type is either config_base, | |
// config_entity, or a derivative. The only thing we can really test though | |
// is that the schema supports having langcode in it. So add 'langcode' to | |
// the data if it doesn't already exist. | |
if (!isset($config_data['langcode'])) { | |
$config_data['langcode'] = 'en'; | |
} | |
$this->configName = $config_name; | |
if (!$typed_config->hasConfigSchema($config_name)) { | |
return FALSE; | |
} | |
$definition = $typed_config->getDefinition($config_name); | |
$data_definition = $typed_config->buildDataDefinition($definition, $config_data); | |
$this->schema = $typed_config->create($data_definition, $config_data); | |
$errors = array(); | |
foreach ($config_data as $key => $value) { | |
$errors = array_merge($errors, $this->checkValue($key, $value)); | |
} | |
if (empty($errors)) { | |
return TRUE; | |
} | |
return $errors; | |
} | |
/** | |
* Helper method to check data type. | |
* | |
* @param string $key | |
* A string of configuration key. | |
* @param mixed $value | |
* Value of given key. | |
* | |
* @return array | |
* List of errors found while checking with the corresponding schema. | |
*/ | |
protected function checkValue($key, $value) { | |
$error_key = $this->configName . ':' . $key; | |
$element = $this->schema->get($key); | |
if ($element instanceof Undefined) { | |
return array($error_key => 'missing schema'); | |
} | |
// Do not check value if it is defined to be ignored. | |
if ($element && $element instanceof Ignore) { | |
return array(); | |
} | |
if ($element && is_scalar($value) || $value === NULL) { | |
$success = FALSE; | |
$type = gettype($value); | |
if ($element instanceof PrimitiveInterface) { | |
$success = | |
($type == 'integer' && $element instanceof IntegerInterface) || | |
// Allow integer values in a float field. | |
(($type == 'double' || $type == 'integer') && $element instanceof FloatInterface) || | |
($type == 'boolean' && $element instanceof BooleanInterface) || | |
($type == 'string' && $element instanceof StringInterface) || | |
// Null values are allowed for all primitive types. | |
($value === NULL); | |
} | |
// Array elements can also opt-in for allowing a NULL value. | |
elseif ($element instanceof ArrayElement && $element->isNullable() && $value === NULL) { | |
$success = TRUE; | |
} | |
$class = get_class($element); | |
if (!$success) { | |
return array($error_key => "variable type is $type but applied schema class is $class"); | |
} | |
} | |
else { | |
$errors = array(); | |
if (!$element instanceof TraversableTypedDataInterface) { | |
$errors[$error_key] = 'non-scalar value but not defined as an array (such as mapping or sequence)'; | |
} | |
// Go on processing so we can get errors on all levels. Any non-scalar | |
// value must be an array so cast to an array. | |
if (!is_array($value)) { | |
$value = (array) $value; | |
} | |
// Recurse into any nested keys. | |
foreach ($value as $nested_value_key => $nested_value) { | |
$errors = array_merge($errors, $this->checkValue($key . '.' . $nested_value_key, $nested_value)); | |
} | |
return $errors; | |
} | |
// No errors found. | |
return array(); | |
} | |
} |