class ConfigSorter in Configuration Split 2.0.x
The config sorter service core should have had.
@internal This is not an API, anything here might change without notice. Use config_normalizer 2.x instead.
Hierarchy
- class \Drupal\config_split\Config\ConfigSorter
Expanded class hierarchy of ConfigSorter
2 files declare their use of ConfigSorter
- ConfigPatchTest.php in tests/
src/ Unit/ ConfigPatchTest.php - ConfigSorterTest.php in tests/
src/ Kernel/ ConfigSorterTest.php
1 string reference to 'ConfigSorter'
1 service uses ConfigSorter
File
- src/
Config/ ConfigSorter.php, line 14
Namespace
Drupal\config_split\ConfigView source
class ConfigSorter {
/**
* The typed config manager to get the schema from.
*
* @var \Drupal\Core\Config\TypedConfigManagerInterface
*/
protected $typedConfigManager;
/**
* The active storage to help with the sorting.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $active;
/**
* ConfigCaster constructor.
*
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager
* The typed config manager to look up the schema.
* @param \Drupal\Core\Config\StorageInterface $active
* The active storage to help with the sorting.
*/
public function __construct(TypedConfigManagerInterface $typedConfigManager, StorageInterface $active) {
$this->typedConfigManager = $typedConfigManager;
$this->active = $active;
}
/**
* Cast and sort the config data in a normalised way depending on its schema.
*
* @param string $name
* The config name.
* @param array $data
* The config data.
*
* @return array
* The cast and sorted data.
*/
public function sort(string $name, array $data) : array {
// The sorter is an object extending from the core config class but doing
// the casting and sorting only.
// This is an anonymous class so that we are sure each object gets used only
// once and nobody uses it for anything else. We extend the core class so
// that we can access the methods and inherit the improvements made to it.
$sorter = new class($this->typedConfigManager) extends StorableConfigBase {
/**
* Sort the config.
*
* @param string $name
* The config name.
* @param array $data
* The data.
*
* @return array
* The sorted array.
*/
public function anonymousSort(string $name, array $data) : array {
// Set the object up.
self::validateName($name);
$this
->validateKeys($data);
$this
->setName($name)
->initWithData($data);
// This is essentially what \Drupal\Core\Config\Config::save does when
// there is untrusted data before persisting it and dispatching events.
if ($this->typedConfigManager
->hasConfigSchema($this->name)) {
// Once https://www.drupal.org/project/drupal/issues/2852557 is fixed
// we do just: $this->data = $this->castValue(NULL, $this->data);.
foreach ($this->data as $key => $value) {
$this->data[$key] = $this
->castValue($key, $value);
}
}
else {
foreach ($this->data as $key => $value) {
$this
->validateValue($key, $value);
}
}
// This should now produce the same data as if the config object had
// been saved and loaded. So we can return it.
return $this->data;
}
/**
* The constructor for passing the TypedConfigManager.
*
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager
* The taped config manager.
*/
public function __construct(TypedConfigManagerInterface $typedConfigManager) {
$this->typedConfigManager = $typedConfigManager;
}
/**
* {@inheritdoc}
*/
public function save($has_trusted_data = FALSE) {
throw new \LogicException();
}
/**
* {@inheritdoc}
*/
public function delete() {
throw new \LogicException();
}
};
// Sort the data using the core class we extended.
$data = $sorter
->anonymousSort($name, $data);
// Unfortunately Drupal core does not let one easily sort config.
// Only when entities are saved some order is assured, for config objects
// there is no sorting and both of these things can not easily be addressed.
// @see https://www.drupal.org/project/drupal/issues/3230826
if ($this->active
->exists($name)) {
// Since we are only concerned about sorting to prevent unnecessary diffs
// we don't sort when the config doesn't exist in the active storage.
$data = $this
->sortDeep($data, $this->active
->read($name));
}
return $data;
}
/**
* Sort one array with the sorting order of another.
*
* @param array $config
* The array to sort.
* @param array $model
* The array to get the sorting order from.
*
* @return array
* The sorted array.
*/
protected function sortDeep(array $config, array $model) : array {
if ($config === $model) {
// Shortcut.
return $config;
}
$sorted = [];
$common = array_intersect_key($model, $config);
$unique = array_diff_key($config, $model);
foreach ($common as $key => $modelValue) {
$value = $config[$key];
// We maybe need to differentiate between mappings and sequences, use the
// config schema and all. But as long as core doesn't give us any help we
// just sort in the most crude way to get the job done.
if (is_array($modelValue) && is_array($value) && !empty($value)) {
// Recurse into nested values.
$value = $this
->sortDeep($value, $modelValue);
}
// Fill the $sorted array in the same order as the model.
$sorted[$key] = $value;
}
foreach ($unique as $key => $value) {
// The values that do not exist in the model do not need to be sorted.
$sorted[$key] = $value;
}
return $sorted;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ConfigSorter:: |
protected | property | The active storage to help with the sorting. | |
ConfigSorter:: |
protected | property | The typed config manager to get the schema from. | |
ConfigSorter:: |
public | function | Cast and sort the config data in a normalised way depending on its schema. | |
ConfigSorter:: |
protected | function | Sort one array with the sorting order of another. | |
ConfigSorter:: |
public | function | ConfigCaster constructor. |