wse-1.0.x-dev/modules/wse_menu/src/EventSubscriber/WseMenuSubscriber.php

modules/wse_menu/src/EventSubscriber/WseMenuSubscriber.php
<?php

namespace Drupal\wse_menu\EventSubscriber;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Menu\MenuLinkManagerInterface;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Drupal\Core\State\StateInterface;
use Drupal\views\Entity\View;
use Drupal\workspaces\Event\WorkspacePostPublishEvent;
use Drupal\workspaces\Event\WorkspacePrePublishEvent;
use Drupal\workspaces\WorkspaceAssociationInterface;
use Drupal\workspaces\WorkspaceManagerInterface;
use Drupal\wse\Event\WorkspaceEvents;
use Drupal\wse\Event\WorkspaceRevertEvent;
use Drupal\wse_menu\Entity\WseMenuTree;
use Drupal\wse_menu\WseMenuTreeStorageInterface;
use Drupal\wse_menu\WseViewsMenuLink;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Handles menu tree changes on workspace operations.
 */
class WseMenuSubscriber implements EventSubscriberInterface {

  public function __construct(
    protected WorkspaceManagerInterface $workspaceManager,
    protected WorkspaceAssociationInterface $workspaceAssociation,
    protected EntityTypeManagerInterface $entityTypeManager,
    protected StaticMenuLinkOverridesInterface $staticMenuLinkOverrides,
    protected MenuLinkManagerInterface $menuLinkManager,
    protected StateInterface $state,
    protected WseMenuTreeStorageInterface $treeStorage,
  ) {}

  /**
   * Publishes workspace-specific menu link overrides.
   *
   * @param \Drupal\workspaces\Event\WorkspacePrePublishEvent $event
   *   The workspace pre-publish event.
   */
  public function onWorkspacePrePublish(WorkspacePrePublishEvent $event): void {
    $overrides = $this->workspaceManager->executeInWorkspace($event->getWorkspace()->id(), function () {
      /** @var \Drupal\Core\Menu\StaticMenuLinkOverridesInterface $static_menu_link_overrides */
      $static_menu_link_overrides = \Drupal::service('menu_link.static.overrides');

      $definitions = WseMenuTree::load(1)->getDefinitions();
      return $static_menu_link_overrides->loadMultipleOverrides(array_keys($definitions));
    });

    $this->workspaceManager->executeOutsideWorkspace(function () use ($overrides) {
      /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
      $menu_link_manager = \Drupal::service('plugin.manager.menu.link');

      foreach ($overrides as $id => $override) {
        $menu_link_manager->updateDefinition($id, $override);
      }
    });
  }

  /**
   * Publishes workspace-specific menu link overrides.
   *
   * @param \Drupal\workspaces\Event\WorkspacePostPublishEvent $event
   *   The workspace post-publish event.
   */
  public function onWorkspacePostPublish(WorkspacePostPublishEvent $event): void {
    // Clean up the workspace-specific menu tree table.
    $this->treeStorage->cleanupWorkspaceMenuTree($event->getWorkspace());

    // Resave the menu link definitions in Live in order to ensure that they're
    // parented correctly.
    $this->workspaceManager->executeOutsideWorkspace(function () use ($event) {
      $menu_link_ids = $event->getPublishedRevisionIds()['menu_link_content'] ?? [];
      if ($menu_link_ids) {
        $menu_links = $this->entityTypeManager
          ->getStorage('menu_link_content')
          ->loadMultiple($menu_link_ids);

        /** @var \Drupal\menu_link_content\MenuLinkContentInterface[] $menu_links */
        foreach ($menu_links as $menu_link) {
          $this->menuLinkManager->updateDefinition($menu_link->getPluginId(), $menu_link->getPluginDefinition(), FALSE);
        }

        // Set the wse_menu_tree_needs_rebuild flag.
        wse_menu_set_menu_rebuild_flag();
      }
    });

    // Handle menu items provided by Views.
    // @todo Think about reverts. We're currently deleting the workspace
    //   overrides at the end.
    $workspace_id = $event->getWorkspace()->id();
    $all_overrides = $this->state->get(WseViewsMenuLink::STATE_KEY, []);

    if (isset($all_overrides[$workspace_id])) {
      $overrides = $all_overrides[$workspace_id];
      $this->workspaceManager->executeOutsideWorkspace(function () use ($overrides) {
        foreach ($overrides as $view_id => $displays) {
          if (!$view_entity = View::load($view_id)) {
            continue;
          }

          $view = $view_entity->getExecutable();
          foreach ($displays as $display_id => $display_overrides) {
            $view->setDisplay($display_id);
            $view->initDisplay();

            $display = &$view->storage->getDisplay($view->current_display);
            foreach ($display_overrides as $key => $new_definition_value) {
              $display['display_options']['menu'][$key] = $new_definition_value;
            }
          }

          $view->storage->save();
        }
      });

      // Remove the override info for the published workspace.
      unset($all_overrides[$workspace_id]);
      $this->state->set(WseViewsMenuLink::STATE_KEY, $all_overrides);
    }
  }

  /**
   * Rebuilds the workspace-specific menu tree.
   *
   * @param \Drupal\wse\Event\WorkspaceRevertEvent $event
   *   The event object.
   */
  public function onWorkspacePostRevert(WorkspaceRevertEvent $event): void {
    // When reverting a workspace that contains menu link changes, we need to
    // get the Live menu tree to the same state it was in before the workspace
    // was published.
    $this->workspaceManager->executeOutsideWorkspace(function () use ($event) {
      $menu_link_ids = $this->workspaceAssociation->getTrackedEntities($event->getWorkspace()->id())['menu_link_content'] ?? [];
      $initial_revisions = $this->workspaceAssociation
        ->getAssociatedInitialRevisions($event->getWorkspace()->id(), 'menu_link_content');

      if ($menu_link_ids) {
        $menu_links = $this->entityTypeManager
          ->getStorage('menu_link_content')
          ->loadMultiple($menu_link_ids);

        /** @var \Drupal\menu_link_content\MenuLinkContentInterface[] $menu_links */
        foreach ($menu_links as $menu_link) {
          if (!in_array($menu_link->id(), $initial_revisions)) {
            // Menu link definitions that were only changed in the reverted
            // workspace have to be updated, so they're re-parented correctly.
            $this->menuLinkManager->updateDefinition($menu_link->getPluginId(), $menu_link->getPluginDefinition(), FALSE);
          }
          else {
            // Menu link definitions that were initially created in that
            // workspace have to be deleted from the Live menu tree.
            $this->menuLinkManager->removeDefinition($menu_link->getPluginId(), FALSE);
          }
        }
      }
    });

    $this->workspaceManager->executeInWorkspace($event->getWorkspace()->id(), function () use ($event) {
      $this->treeStorage->rebuildWorkspaceMenuTree($event->getWorkspace());
    });
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    // @todo Bring back support for static and views menu link overrides.
    // $events[WorkspacePrePublishEvent::class][] = 'onWorkspacePrePublish';
    $events[WorkspacePostPublishEvent::class][] = 'onWorkspacePostPublish';
    $events[WorkspaceEvents::WORKSPACE_POST_REVERT][] = 'onWorkspacePostRevert';
    return $events;
  }

}

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

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