wse-1.0.x-dev/modules/wse_menu/src/WseStaticMenuLinkOverrides.php

modules/wse_menu/src/WseStaticMenuLinkOverrides.php
<?php

namespace Drupal\wse_menu;

use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Drupal\Core\State\StateInterface;
use Drupal\workspaces\WorkspaceManagerInterface;

/**
 * Defines an implementation of the menu link override using state.
 */
class WseStaticMenuLinkOverrides implements StaticMenuLinkOverridesInterface {

  /**
   * Constructs a new WseStaticMenuLinkOverrides.
   *
   * @param \Drupal\Core\Menu\StaticMenuLinkOverridesInterface $inner
   *   The inner static menu link overrides service.
   * @param \Drupal\workspaces\WorkspaceManagerInterface $workspaceManager
   *   The workspace manager.
   * @param \Drupal\workflows\StateInterface $state
   *   The state service.
   */
  public function __construct(
    protected readonly StaticMenuLinkOverridesInterface $inner,
    protected readonly WorkspaceManagerInterface $workspaceManager,
    protected readonly StateInterface $state,
  ) {}

  /**
   * {@inheritdoc}
   */
  public function reload() {
    $this->inner->reload();
    $this->state->resetCache();
  }

  /**
   * {@inheritdoc}
   */
  public function loadOverride($id) {
    if (!$this->applies()) {
      return $this->inner->loadOverride($id);
    }

    assert(is_string($id), 'Menu link plugin ID should be a string.');
    $all_overrides = $this->state->get($this->getStateKey());
    $id = static::encodeId($id);
    return $all_overrides[$id] ?? [];
  }

  /**
   * {@inheritdoc}
   */
  public function deleteMultipleOverrides(array $ids) {
    if (!$this->applies()) {
      return $this->inner->deleteMultipleOverrides($ids);
    }

    $all_overrides = $this->state->get($this->getStateKey());
    $save = FALSE;
    foreach ($ids as $id) {
      $id = static::encodeId($id);
      if (isset($all_overrides[$id])) {
        unset($all_overrides[$id]);
        $save = TRUE;
      }
    }
    if ($save) {
      if (empty($all_overrides)) {
        $this->state->delete($this->getStateKey());
      }
      else {
        $this->state->set($this->getStateKey(), $all_overrides);
      }
    }
    return $save;
  }

  /**
   * {@inheritdoc}
   */
  public function deleteOverride($id) {
    return $this->deleteMultipleOverrides([$id]);
  }

  /**
   * {@inheritdoc}
   */
  public function loadMultipleOverrides(array $ids) {
    if (!$this->applies()) {
      return $this->inner->loadMultipleOverrides($ids);
    }

    $result = [];
    if ($ids) {
      // When rebuilding the menu tree, ensure that we also return the Live
      // config overrides, otherwise they wouldn't be applied anymore.
      $config_overrides = [];
      $original_config_overrides = $this->inner->loadMultipleOverrides($ids);
      foreach ($original_config_overrides as $key => $value) {
        $config_overrides[static::encodeId($key)] = $value;
      }

      $all_overrides = $this->state->get($this->getStateKey(), []) + $config_overrides;
      foreach ($ids as $id) {
        $encoded_id = static::encodeId($id);
        if (isset($all_overrides[$encoded_id])) {
          $result[$id] = $all_overrides[$encoded_id];
        }
      }
    }
    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function saveOverride($id, array $definition) {
    if (!$this->applies()) {
      return $this->inner->saveOverride($id, $definition);
    }

    // Only allow to override a specific subset of the keys.
    $expected = [
      'menu_name' => '',
      'parent' => '',
      'weight' => 0,
      'expanded' => FALSE,
      'enabled' => FALSE,
    ];
    // Filter the overrides to only those that are expected.
    $definition = array_intersect_key($definition, $expected);
    // Ensure all values are set.
    $definition = $definition + $expected;
    if ($definition) {
      // Cast keys to avoid config schema during save.
      $definition['menu_name'] = (string) $definition['menu_name'];
      $definition['parent'] = (string) $definition['parent'];
      $definition['weight'] = (int) $definition['weight'];
      $definition['expanded'] = (bool) $definition['expanded'];
      $definition['enabled'] = (bool) $definition['enabled'];

      $id = static::encodeId($id);
      $all_overrides = $this->state->get($this->getStateKey());
      // Combine with any existing data.
      $all_overrides[$id] = $definition + $this->loadOverride($id);
      $this->state->set($this->getStateKey(), $all_overrides);
    }
    return array_keys($definition);
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    if (!$this->applies()) {
      return $this->inner->getCacheTags();
    }

    return $this->workspaceManager->getActiveWorkspace()->getCacheTags();
  }

  /**
   * Encodes the ID by replacing dots with double underscores.
   *
   * This is done because config schema uses dots for its internal type
   * hierarchy. Double underscores are converted to triple underscores to
   * avoid accidental conflicts.
   *
   * @param string $id
   *   The menu plugin ID.
   *
   * @return string
   *   The menu plugin ID with double underscore instead of dots.
   */
  protected static function encodeId($id): string {
    return strtr($id, ['.' => '__', '__' => '___']);
  }

  /**
   * Determines whether this static menu link overrides storage should be used.
   *
   * @return bool
   *   TRUE if there is an active workspace, FALSE otherwise.
   */
  protected function applies(): bool {
    return $this->workspaceManager->hasActiveWorkspace();
  }

  /**
   * Gets the ID of the state entry for a workspace.
   *
   * @return string
   *   The ID.
   */
  protected function getStateKey(): string {
    return 'wse_menu.static_menu_link_overrides.' . $this->workspaceManager->getActiveWorkspace()->id();
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc