You are here

class MenuLinkTreeManipulators in Menu Manipulator 3.0.x

Same name and namespace in other branches
  1. 8.2 src/Menu/MenuLinkTreeManipulators.php \Drupal\menu_manipulator\Menu\MenuLinkTreeManipulators
  2. 8 src/Menu/MenuLinkTreeManipulators.php \Drupal\menu_manipulator\Menu\MenuLinkTreeManipulators
  3. 2.0.x src/Menu/MenuLinkTreeManipulators.php \Drupal\menu_manipulator\Menu\MenuLinkTreeManipulators

Provides a menu link tree manipulators.

This class provides a menu link tree manipulators to:

  • filter by current language.

Hierarchy

Expanded class hierarchy of MenuLinkTreeManipulators

See also

menu_manipulator_get_multilingual_menu() to see example of use.

1 string reference to 'MenuLinkTreeManipulators'
menu_manipulator.services.yml in ./menu_manipulator.services.yml
menu_manipulator.services.yml
1 service uses MenuLinkTreeManipulators
menu_manipulator.menu_tree_manipulators in ./menu_manipulator.services.yml
Drupal\menu_manipulator\Menu\MenuLinkTreeManipulators

File

src/Menu/MenuLinkTreeManipulators.php, line 23

Namespace

Drupal\menu_manipulator\Menu
View source
class MenuLinkTreeManipulators {

  /**
   * The entity repository.
   *
   * @var \Drupal\Core\Entity\EntityRepository
   */
  protected $entityRepository;

  /**
   * The current language ID.
   *
   * @var string
   */
  protected $langcode;

  /**
   * Drupal\Core\Entity\EntityStorageInterface.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   *    A storage instance.
   */
  protected $menuLinkContentStorage;

  /**
   * Constructs a \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Language\LanguageManager $language_manager
   *   The language manager.
   * @param \Drupal\Core\Entity\EntityRepository $entity_repository
   *   The entity repository.
   */
  public function __construct(EntityRepository $entity_repository, EntityTypeManagerInterface $entity_type_manager, LanguageManager $language_manager) {
    $this->entityRepository = $entity_repository;
    $this->menuLinkContentStorage = $entity_type_manager
      ->getStorage('menu_link_content');
    $this->langcode = $language_manager
      ->getCurrentLanguage()
      ->getId();
  }

  /**
   * Filter a menu tree by current language MenuLinks.
   *
   * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree
   *   The menu link tree to manipulate.
   *
   * @return \Drupal\Core\Menu\MenuLinkTreeElement[]
   *   The manipulated menu link tree.
   */
  public function filterByCurrentLanguage(array $tree) {
    foreach ($tree as $key => $element) {
      if (!$element->link instanceof MenuLinkBase) {
        continue;
      }
      $access = $this
        ->checkLinkAccess($element->link);
      if (!$access) {

        // Deny access and hide children items.
        $tree[$key]->link = new InaccessibleMenuLink($tree[$key]->link);
        $tree[$key]->access = AccessResult::forbidden();
        $tree[$key]->subtree = [];
      }

      // Filter children items recursively.
      if ($element->hasChildren && !empty($tree[$key]->subtree)) {
        $element->subtree = $this
          ->filterByCurrentLanguage($element->subtree);
      }
    }
    return $tree;
  }

  /**
   *
   */
  public function checkLinkAccess(MenuLinkBase $link) {
    $langcode = $this
      ->getLinkLanguage($link);
    $not_applicable_langcodes = [
      LanguageInterface::LANGCODE_NOT_APPLICABLE,
      LanguageInterface::LANGCODE_NOT_SPECIFIED,
    ];

    // Allow unspecified languages.
    if (in_array($langcode, $not_applicable_langcodes)) {
      return TRUE;
    }

    // Allow if targeted entity is translated, no matter menu item's language.
    $entity = $this
      ->getLinkEntity($link);
    if ($entity instanceof ContentEntityInterface && method_exists($entity, 'hasTranslation')) {
      return $entity
        ->hasTranslation($this->langcode);
    }

    // Allow by the menu item's language itself.
    return $this->langcode == $langcode;
  }

  /**
   * Force the MenuLinkBase to tell us its language code.
   *
   * @param \Drupal\Core\Menu\MenuLinkBase $link
   *   `The Menu Link Content entity.
   *
   * @return string
   *   The menu Link language ID or a default value.
   */
  protected function getLinkLanguage(MenuLinkBase $link) {
    $metadata = $link
      ->getMetaData();
    if (!isset($metadata['entity_id'])) {
      return LanguageInterface::LANGCODE_NOT_APPLICABLE;
    }
    $loaded_link = $this->menuLinkContentStorage
      ->load($metadata['entity_id']);
    $loaded_lang_link = $this->entityRepository
      ->getTranslationFromContext($loaded_link);
    return $loaded_lang_link
      ->language()
      ->getId();
  }

  /**
   * Get targeted entity for a given MenuLinkBase.
   *
   * @param \Drupal\Core\Menu\MenuLinkBase $link
   *   `The Menu Link Content entity.
   *
   * @return \Drupal\Core\Entity\EntityInterface|null|bool
   *   FALSE if Url is unrouted. Otherwise, an entity object variant or NULL.
   */
  protected function getLinkEntity(MenuLinkBase $link) {
    $metadata = $link
      ->getMetaData();
    if (!isset($metadata['entity_id'])) {
      return NULL;
    }
    $loaded_link = $this->menuLinkContentStorage
      ->load($metadata['entity_id']);
    $url = Url::fromUri($loaded_link
      ->get('link')
      ->getString());
    if (!$url instanceof Url || !$url
      ->isRouted()) {
      return FALSE;
    }

    // Get entity info from route.
    $parts = explode('/', $url
      ->getInternalPath());
    if (empty($parts[0] ?? '') || empty($parts[1] ?? '')) {
      return FALSE;
    }
    $entity_type = $parts[0];
    $entity_id = $parts[1];
    return !\is_string($entity_type) || empty($entity_id) ? FALSE : $this->entityRepository
      ->getActive($entity_type, $entity_id);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
MenuLinkTreeManipulators::$entityRepository protected property The entity repository.
MenuLinkTreeManipulators::$langcode protected property The current language ID.
MenuLinkTreeManipulators::$menuLinkContentStorage protected property Drupal\Core\Entity\EntityStorageInterface.
MenuLinkTreeManipulators::checkLinkAccess public function
MenuLinkTreeManipulators::filterByCurrentLanguage public function Filter a menu tree by current language MenuLinks.
MenuLinkTreeManipulators::getLinkEntity protected function Get targeted entity for a given MenuLinkBase.
MenuLinkTreeManipulators::getLinkLanguage protected function Force the MenuLinkBase to tell us its language code.
MenuLinkTreeManipulators::__construct public function Constructs a \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators object.