You are here

public function ConfigSorter::sort in Configuration Split 2.0.x

Cast and sort the config data in a normalised way depending on its schema.

Parameters

string $name: The config name.

array $data: The config data.

Return value

array The cast and sorted data.

File

src/Config/ConfigSorter.php, line 54

Class

ConfigSorter
The config sorter service core should have had.

Namespace

Drupal\config_split\Config

Code

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;
}