wse-1.0.x-dev/modules/wse_menu/wse_menu.module

modules/wse_menu/wse_menu.module
<?php

/**
 * @file
 * Primary module hooks for Workspaces Menu module.
 */

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\menu_link_content\MenuLinkContentInterface;
use Drupal\workspaces\Entity\Handler\IgnoredWorkspaceHandler;
use Drupal\workspaces\WorkspaceInterface;
use Drupal\wse_menu\EventSubscriber\WseMenuRequestSubscriber;

/**
 * Implements hook_entity_type_build().
 */
function wse_menu_entity_type_build(array &$entity_types) {
  /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
  if (isset($entity_types['menu'])) {
    $entity_types['menu']
      ->set('internal', TRUE)
      ->setHandlerClass('workspace', IgnoredWorkspaceHandler::class)
      ->setFormClass('add', 'Drupal\wse_menu\Form\WseMenuForm')
      ->setFormClass('edit', 'Drupal\wse_menu\Form\WseMenuForm');
  }

  if (isset($entity_types['group_content_menu'])) {
    if ($entity_types['group_content_menu']->hasHandlerClass('workspace')) {
      $entity_types['group_content_menu']->setFormClass('add', 'Drupal\wse_menu\Form\WseGroupContentMenuForm');
      $entity_types['group_content_menu']->setFormClass('edit', 'Drupal\wse_menu\Form\WseGroupContentMenuForm');
    }
    else {
      // The 'group_content_menu' entity type is not revisionable or
      // publishable, so we mark it as 'ignored' in a workspace, which allows
      // its form to be submitted. However, the 'WseUnsupportedEntityType'
      // validation constraint added by wse_entity_type_alter() won't allow any
      // changes to the entity itself.
      // @see wse_menu_form_group_content_menu_form_alter()
      // @see wse_entity_type_alter()
      $entity_types['group_content_menu']->setHandlerClass('workspace', IgnoredWorkspaceHandler::class);
    }
  }
}

/**
 * Implements hook_entity_type_alter().
 */
function wse_menu_entity_type_alter(array &$entity_types) {
  // Remove the MenuTreeHierarchy and MenuSettings constraints, since our tree
  // storage supports changing a link's parent in pending revisions.
  if (isset($entity_types['menu_link_content'])) {
    $constraints = $entity_types['menu_link_content']->getConstraints();
    unset($constraints['MenuTreeHierarchy']);
    $entity_types['menu_link_content']->setConstraints($constraints);
  }
  if (isset($entity_types['node'])) {
    $constraints = $entity_types['node']->getConstraints();
    unset($constraints['MenuSettings']);
    $entity_types['node']->setConstraints($constraints);
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function wse_menu_form_menu_link_edit_alter(&$form, FormStateInterface $form_state) {
  $form_state->set('workspace_safe', TRUE);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function wse_menu_form_menu_link_reset_confirm_alter(&$form, FormStateInterface $form_state) {
  $form_state->set('workspace_safe', TRUE);
}

/**
 * Implements hook_form_FORM_ID_alter() for 'group_content_menu_form'.
 */
function wse_menu_form_group_content_menu_form_alter(&$form, FormStateInterface $form_state) {
  // Allow this form to be submitted in a workspace, in order to allow changes
  // to the menu links of a group menu.
  $form_state->set('workspace_safe', TRUE);
}

/**
 * Implements hook_entity_base_field_info_alter().
 */
function wse_menu_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'menu_link_content') {
    $fields['expanded']->setRevisionable(TRUE);
    $fields['parent']->setRevisionable(TRUE);
    $fields['weight']->setRevisionable(TRUE);
  }
}

/**
 * Implements hook_ENTITY_TYPE_insert().
 */
function wse_menu_menu_link_content_insert() {
  wse_menu_set_menu_rebuild_flag();
}

/**
 * Implements hook_ENTITY_TYPE_update().
 */
function wse_menu_menu_link_content_update(MenuLinkContentInterface $entity) {
  if (!$entity->isSyncing()) {
    wse_menu_set_menu_rebuild_flag();
  }

  if (!\Drupal::service('workspaces.manager')->hasActiveWorkspace()) {
    return;
  }

  // Don't run if the entity is being deleted by the Trash module.
  if (\Drupal::moduleHandler()->moduleExists('trash') && trash_entity_is_deleted($entity)) {
    return;
  }

  // Don't run if the entity is going through a workflow transition.
  if (isset($entity->_entityWorkflowEnforceNoNewRevision)) {
    return;
  }

  // The following code is borrowed from MenuLinkContent::postSave(), the
  // implementation there does not update the tree if the saved revision is not
  // the default revision, which can't ever be the case inside a workspace.
  /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
  $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
  $definition = $entity->getPluginDefinition();
  if ($definition && $menu_link_manager->getDefinition($entity->getPluginId(), FALSE)) {
    if (!$entity->insidePlugin) {
      $menu_link_manager->updateDefinition($entity->getPluginId(), $definition, FALSE);
    }
  }
  else {
    $menu_link_manager->addDefinition($entity->getPluginId(), $definition);
  }
}

/**
 * Implements hook_ENTITY_TYPE_insert() for the 'workspace' entity type.
 */
function wse_menu_workspace_insert(WorkspaceInterface $workspace): void {
  // Create the workspace-specific menu tree for the newly added workspace.
  \Drupal::service('wse_menu.tree_storage')->rebuildWorkspaceMenuTree($workspace, FALSE);
}

/**
 * Implements hook_ENTITY_TYPE_delete() for the 'workspace' entity type.
 */
function wse_menu_workspace_delete(WorkspaceInterface $workspace): void {
  // Delete the workspace-specific menu tree for the deleted workspace.
  \Drupal::service('wse_menu.tree_storage')->cleanupWorkspaceMenuTree($workspace);
}

/**
 * Implements hook_menu_links_discovered_alter().
 */
function wse_menu_menu_links_discovered_alter(&$links) {
  // Swap the plugin class for menu links provided by Views, so they can be
  // updated in a workspace without having to save the view.
  foreach ($links as &$link) {
    if (isset($link['provider']) && $link['provider'] === 'views') {
      $link['class'] = 'Drupal\wse_menu\WseViewsMenuLink';
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_access() for 'group_content_menu'.
 */
function wse_menu_group_content_menu_access(EntityInterface $entity, $operation): AccessResultInterface {
  /** @var \Drupal\workspaces\WorkspaceInformationInterface $workspace_info */
  $workspace_info = \Drupal::service('workspaces.information');
  if ($workspace_info->isEntitySupported($entity)) {
    return AccessResult::neutral();
  }

  // Disallow 'delete' access for 'group_content_menu' entities in a workspace.
  // @see \Drupal\wse_menu\Routing\RouteSubscriber::alterRoutes()
  if ($operation === 'delete') {
    return AccessResult::forbiddenIf(\Drupal::service('workspaces.manager')->hasActiveWorkspace())
      ->addCacheContexts(['workspace']);
  }
  return AccessResult::neutral();
}

/**
 * Sets the wse_menu_tree_needs_rebuild flag.
 */
function wse_menu_set_menu_rebuild_flag(): void {
  /** @var \Drupal\workspaces\WorkspaceManagerInterface $workspaceManager */
  $workspaceManager = \Drupal::service('workspaces.manager');

  // Only set the rebuild flag if changes are made in the "Live" workspace.
  if ($workspaceManager->hasActiveWorkspace()) {
    return;
  }

  while (!\Drupal::lock()->acquire(WseMenuRequestSubscriber::LOCK_REBUILD)) {
    \Drupal::lock()->wait(WseMenuRequestSubscriber::LOCK_REBUILD);
  }

  /** @var \Drupal\workspaces\WorkspaceInterface[] $workspaces */
  $workspaces = \Drupal::service('entity_type.manager')->getStorage('workspace')->loadMultiple();

  $rebuild_menu = [];
  foreach ($workspaces as $workspace) {
    $rebuild_menu[$workspace->id()] = TRUE;
  }

  \Drupal::state()->set(WseMenuRequestSubscriber::STATE_REBUILD_FLAGS, $rebuild_menu);
  \Drupal::lock()->release(WseMenuRequestSubscriber::LOCK_REBUILD);
}

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

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