block_editor-1.0.x-dev/src/Hook/MenuHooks.php

src/Hook/MenuHooks.php
<?php

namespace Drupal\block_editor\Hook;

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\block_editor\Service\EntityManager;

/**
 * Menu-related hooks for Block Editor.
 */
class MenuHooks {

  /**
   * The current route match.
   */
  protected RouteMatchInterface $routeMatch;

  /**
   * The entity type manager.
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * The Block Editor entity manager.
   */
  protected EntityManager $entityManager;

  /**
   * Constructs a new MenuHooks instance.
   */
  public function __construct(RouteMatchInterface $route_match, EntityTypeManagerInterface $entity_type_manager, EntityManager $entity_manager) {
    $this->routeMatch = $route_match;
    $this->entityTypeManager = $entity_type_manager;
    $this->entityManager = $entity_manager;
  }

  /**
   * Implements hook_menu_local_tasks_alter().
   */
  #[Hook('menu_local_tasks_alter')]
  public function menuLocalTasksAlter(array &$data, string $route_name): void {
    if (!$this->isCanonicalRoute($route_name)) {
      return;
    }

    $entity = $this->extractContentEntity();
    if (!$entity) {
      return;
    }

    $bundle_entity = $this->loadBundleEntity($entity);
    if (!$bundle_entity || !$this->entityManager->isBlockEditorEnabledForEntity($bundle_entity)) {
      return;
    }

    $tab_collection = $data['tabs'][0] ?? [];
    if (!$tab_collection) {
      return;
    }

    $entity_type_id = $entity->getEntityTypeId();
    $entity_type = $entity->getEntityType();
    $default_tab_key = 'entity.' . $entity_type_id . '.edit_form';
    $default_tab_key_with_suffix = 'entity.' . $entity_type_id . '.edit_form_tab';
    $canonical_tab_key = 'entity.' . $entity_type_id . '.canonical';
    $block_editor_tab_key = 'block_editor.entity.' . $entity_type_id . '.edit_form';

    // Check if canonical and edit-form are the same for this entity type.
    $canonical_link = $entity_type->getLinkTemplate('canonical');
    $edit_form_link = $entity_type->getLinkTemplate('edit-form');
    $is_canonical_same_as_edit = ($canonical_link === $edit_form_link);

    // Always remove the default Edit tab when Block Editor is enabled.
    // Some entity types use 'edit_form' and others use 'edit_form_tab'.
    if (isset($data['tabs'][0][$default_tab_key])) {
      unset($data['tabs'][0][$default_tab_key]);
    }
    if (isset($data['tabs'][0][$default_tab_key_with_suffix])) {
      unset($data['tabs'][0][$default_tab_key_with_suffix]);
    }

    // For entity types where canonical IS the edit form (like block_content),
    // also remove the canonical tab (which is essentially the edit tab).
    if ($is_canonical_same_as_edit && isset($data['tabs'][0][$canonical_tab_key])) {
      unset($data['tabs'][0][$canonical_tab_key]);
    }

    // Only move Block Editor tab to the beginning for entity types where
    // canonical IS the edit form (like block_content).
    if ($is_canonical_same_as_edit && isset($data['tabs'][0][$block_editor_tab_key])) {
      $block_editor_tab = $data['tabs'][0][$block_editor_tab_key];
      unset($data['tabs'][0][$block_editor_tab_key]);

      // Set weight to -100 to ensure it appears first.
      $block_editor_tab['#weight'] = -100;

      // Mark as the active/default tab.
      $block_editor_tab['#active'] = TRUE;

      // Re-add at the beginning by prepending.
      $data['tabs'][0] = [$block_editor_tab_key => $block_editor_tab] + $data['tabs'][0];
    }
  }

  /**
   * Determines if the current route should invoke tab adjustments.
   */
  protected function isCanonicalRoute(string $route_name): bool {
    // Handle entity types with separate canonical routes.
    if ($route_name === 'entity.node.canonical') {
      return TRUE;
    }

    // Handle entity types where canonical IS the edit form
    // (like block_content).
    if (preg_match('/^entity\.([a-z_]+)\.canonical$/', $route_name, $matches)) {
      return TRUE;
    }

    // Handle edit form routes (like entity.comment.edit_form).
    // Some entity types have edit forms as separate routes that are tabs
    // on the canonical route.
    if (preg_match('/^entity\.([a-z_]+)\.edit_form$/', $route_name, $matches)) {
      return TRUE;
    }

    // Handle Block Editor routes.
    if (\str_starts_with($route_name, 'block_editor.entity.')) {
      return TRUE;
    }

    // Handle related entity routes (revisions, delete, etc.) that use
    // canonical as their base route. These routes follow patterns like:
    // - entity.{entity_type}.version_history
    // - entity.{entity_type}.revision
    // - entity.{entity_type}.delete_form
    // - entity.{entity_type}.revision_revert_form
    // - entity.{entity_type}.revision_delete_form.
    if (preg_match('/^entity\.([a-z_]+)\.(version_history|revision|delete_form|revision_revert_form|revision_delete_form)/', $route_name, $matches)) {
      return TRUE;
    }

    return FALSE;
  }

  /**
   * Extracts the content entity from the current route.
   */
  protected function extractContentEntity(): ?ContentEntityInterface {
    foreach ($this->routeMatch->getParameters() as $parameter) {
      if ($parameter instanceof ContentEntityInterface) {
        return $parameter;
      }
    }

    return NULL;
  }

  /**
   * Loads the bundle entity corresponding to a content entity.
   */
  protected function loadBundleEntity(ContentEntityInterface $entity): ?object {
    $entity_type = $entity->getEntityType();
    $bundle_entity_type_id = $entity_type->getBundleEntityType();
    if (!$bundle_entity_type_id) {
      return NULL;
    }

    $bundle_storage = $this->entityTypeManager->getStorage($bundle_entity_type_id);
    return $bundle_storage->load($entity->bundle());
  }

}

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

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