simple_grouped_content-2.0.x-dev/modules/sgc_support_module/src/EventSubscriber/MenuFieldFormEventSubscriber.php

modules/sgc_support_module/src/EventSubscriber/MenuFieldFormEventSubscriber.php
<?php

namespace Drupal\sgc_support_module\EventSubscriber;

use Drupal\core_event_dispatcher\Event\Form\FormAlterEvent;
use Drupal\core_event_dispatcher\Event\Form\FormBaseAlterEvent;
use Drupal\core_event_dispatcher\FormHookEvents;
use Drupal\group\Entity\GroupRelationship;
use Drupal\group\Entity\GroupInterface;
use Drupal\value_fetcher\ValueFetcher;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Menu\MenuLinkTree;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Routing\CurrentRouteMatch;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Class ExampleFormEventSubscribers.
 *
 * Don't forget to define your class as a service and tag it as
 * an "event_subscriber":
 *
 * services:
 *  hook_event_dispatcher.example_form_subscribers:
 *   class: Drupal\hook_event_dispatcher\ExampleFormEventSubscribers
 *   tags:
 *     - { name: event_subscriber }
 */
class MenuFieldFormEventSubscriber implements EventSubscriberInterface {

  /**
   * Route matcher.
   */
  protected CurrentRouteMatch $routeMatch;

  /**
   * Menu link tree service.
   */
  protected MenuLinkTree $menuLinkTree;

  /**
   * Form ID's which we should set it to clear group menu cache tags on submit.
   *
   * @var array
   */
  private $formsToClearMenuCacheTagOn = [
    'group_content_menu_default_group_menu_edit_form',
    'menu_link_content_menu_link_content_form',
  ];

  /**
   * {@inheritdoc}
   */
  public function __construct(
    CurrentRouteMatch $routeMatch,
    MenuLinkTree $menuLinkTree
  ) {
    $this->routeMatch = $routeMatch;
    $this->menuLinkTree = $menuLinkTree;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      FormHookEvents::FORM_ALTER => 'alterForm',
    ];
  }

  /**
   * Alter form.
   *
   * PURPOSE: Set group menu as base of menu on menu link field.
   *
   * @param \Drupal\core_event_dispatcher\Event\Form\FormAlterEvent $event
   *   The event.
   */
  public function alterForm(FormAlterEvent $event): void {
    $form = &$event->getForm();
    $form_state =$event->getFormState();
    $build_info = $form_state->getBuildInfo();

    // If we're dealing with a node base form, disable menu form if in group.
    if (
      isset($build_info['base_form_id'])
      && $build_info['base_form_id'] == 'node_form'
    ) {
      $this->disableMenuFieldOnNodesInGroup($form, $form_state);
    }

    // Require menu title on menu links.
    if (isset($form['field_group_content_menu_link'])) {
      // Require title if the menu link is added.
      $form['field_group_content_menu_link']['widget'][0]['title']['#element_validate'][] = [
        $this,
        'validateTitleWhenChecked'
      ];
    }

    // Clear menu cache on any form submit that can change a group's menu.
    if (
      in_array($form['#form_id'], $this->formsToClearMenuCacheTagOn)
      || isset($form['field_group_content_menu_link'])
    ) {
      $form['actions']['submit']['#submit'][] = get_class($this) . '::invalidateGroupMenuBlockTag';
    }

    if (isset($form['field_group_content_menu_link'])) {
      // Change the description field title to "hover text" for easy reference.
      $form['field_group_content_menu_link']['widget'][0]['description']['#title'] = t('Hover text');
      $this->adjustGroupContentMenuLinkparent($form, $form_state);
    }
  }

  /**
   * Adjusts a group content menu link fields parent menu to the groups menu.
   *
   * @param array $form
   *   The form array from the form_alter.
   * @param FormStateInterface $form_state
   *   The form state object as passed from the form_later.
   */
  protected function adjustGroupContentMenuLinkparent(array &$form, FormStateInterface $form_state) : void {
    $element = &$form['field_group_content_menu_link']['widget'][0];
    $group = $this->routeMatch->getParameters()->get('group');
    $group_content = $form_state->getformObject()->getEntity();
    $group_menus = group_content_menu_get_menus_per_group($group);
    $primary_group_menu = $group_menus[0]->getEntity();

    $current_menu_item_uuid = NULL;

    // If we're dealing with group content, establish the group menu to place this in.
    if ($group_content) {
      $current_menu_values = ValueFetcher::getAllValues($group_content, 'field_group_content_menu_link');

      if ($current_menu_values) {
        $parent_key = $this->getGroupMenuName($group). ':' . $current_menu_values['parent'];
        $element['menu_parent']['#default_value'] = $parent_key;
        $current_menu_item_uuid = $group_content->field_group_content_menu_link->first()->getMenuPluginId();
      }
    }

    $element['menu']['#open'] = TRUE;

    // Rebuild menu parent options from scratch!
    $element['menu_parent']['#options'] = [];
    $element['menu_parent']['#options'][$this->getGroupMenuName($group). ':'] = '<base>';
    $element['menu_parent']['#options'] = array_merge(
      $element['menu_parent']['#options'],
      $this->ConvertMenuTreeToOptionsArray(
        $this->getGroupMenuName($group),
        $this->fetchMenuTreeForGroup($group),
        $current_menu_item_uuid
      )
    );
  }

  /**
   * Returns the group menu name string to help DRY that bit up.
   *
   * @param \Drupal\group\Entity\GroupInterface $group
   *
   * @return string
   */
  protected static function getGroupMenuName(GroupInterface $group) {
    $group_menu = group_content_menu_get_menus_per_group($group);

    if (count($group_menu) > 1) {
      \Drupal::logger('sgc_support_module')->error('No Group Menu found for %group (%gid)', [
        '%group' => $group->label(),
        '%gid' => $group->id()
      ]);
      return FALSE;
    }
    $menu_id = ValueFetcher::getFirstValue(reset($group_menu), 'entity_id');
    return 'group_menu_link_content-' . $menu_id;
  }

  /**
   * Get menu tree for menu with group as parent menu item.
   *
   * @param GroupInterface $group
   *   A group entity we can pull the group ID from.
   *
   * @return
   *   Menu tree.
   */
  protected function fetchMenuTreeForGroup(GroupInterface $group) {
    $menu_parameters = new MenuTreeParameters();
    $menu_parameters->onlyEnabledLinks();
    return $this->menuLinkTree->load($this->getGroupMenuName($group), $menu_parameters);
  }

  /**
   * Convert Menu Tree to options array
   *
   * @param string $menu_name
   *   The machine name of the menu to link to.
   * @param array $menu_tree
   *   The menu tree array as returned by the service menu.link_tree.
   * @param string $current_uuid
   *   The current item UUID to skip over.
   * @param int $depth
   *   Do not use. Depth into menu tree. Recursion var for number of dashes.
   *
   * @return array
   *   An array of form options for the #options attribute.
   */
  protected function ConvertMenuTreeToOptionsArray(string $menu_name, array $menu_tree, $current_uuid, $depth = 1, $max_depth = 9) {
    $menu_options = [];
    foreach ($menu_tree as $value => $tree_data) {
      if (is_null($current_uuid) || ($current_uuid && strpos($value, $current_uuid) === FALSE)) {
        $option_key = $menu_name . ':' . $value;
        $menu_options[$option_key] =
          str_repeat('--', $depth - 1) . ' ' . $tree_data->link->getTitle();

        if (!empty($tree_data->subtree) && $depth < $max_depth) {
          $depth = $depth + 1;
          $menu_options = array_merge(
            $menu_options,
            $this->ConvertMenuTreeToOptionsArray(
              $menu_name,
              $tree_data->subtree,
              $current_uuid,
              $depth,
              $max_depth
            )
          );
          $depth = $depth - 1;
        }
      }
    }
    return $menu_options;
  }

  /**
   * Form validation hook checking that a user has at least a contributor role.
   *
   * NOTE: Group may not be set on non-group menu items.
   */
  public static function invalidateGroupMenuBlockTag(&$form, FormStateInterface $form_state) {
    $group = \Drupal::service('current_route_match')->getParameter('group');
    if ($group) {
      $group_menu_name = self::getGroupMenuName($group);

      if (is_string($group_menu_name)) {
        Cache::invalidateTags([
          $group_menu_name
        ]);
      }
    }
  }

  /**
   * Static element validation method for checking menu title has been entered.
   *
   * @param array $element
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   * Form validation hook checking that a user has at least a contributor role.
   */
  public static function validateTitleWhenChecked(array $element, FormStateInterface $form_state) {
    if (
      $form_state->getValue('field_group_content_menu_link')[0]['enabled']
      && strlen($element['#value']) === 0
    ) {
      $form_state->setError($element, t('A menu title is required'));
    }
  }

  /**
   * Disables the menu field on nodes that are in a group
   *
   * @param array $form
   *   The form array to alter.
   */
  protected function disableMenuFieldOnNodesInGroup(&$form, FormStateInterface $form_state) : void{
    $group_from_route = \Drupal::routeMatch()->getParameters()->get('group');
    if (!is_null($group_from_route)) {
      $form['menu']['#access'] = FALSE;
      return;
    }
    $node = $form_state->getformObject()->getEntity();
    if (!$node->isNew()) {
      if(!empty(GroupRelationship::loadByEntity($node))) {
        $form['menu']['#access'] = FALSE;
        return;
      }
    }
  }

}

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

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