class NavigationContentLinks

Same name and namespace in other branches
  1. 11.x core/modules/navigation/src/NavigationContentLinks.php \Drupal\navigation\NavigationContentLinks

Build the menu links for the Content menu.

The content menu contains a "Create" section, along with links to other overview pages for different entity types.

@internal The navigation module is experimental.

Hierarchy

Expanded class hierarchy of NavigationContentLinks

1 file declares its use of NavigationContentLinks
navigation.module in core/modules/navigation/navigation.module
Primary module hooks for navigation module.

File

core/modules/navigation/src/NavigationContentLinks.php, line 22

Namespace

Drupal\navigation
View source
final class NavigationContentLinks implements ContainerInjectionInterface {
  use StringTranslationTrait;
  
  /**
   * Construct a new NavigationContentLinks object.
   *
   * @param \Drupal\Core\Routing\RouteProviderInterface $routeProvider
   *   The route provider.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager.
   */
  public function __construct(private RouteProviderInterface $routeProvider, private EntityTypeManagerInterface $entityTypeManager) {
  }
  
  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container->get('router.route_provider'), $container->get('entity_type.manager'));
  }
  
  /**
   * Add links to the Content menu, based on enabled modules.
   *
   * @param array $links
   *   The array of links being altered.
   */
  public function addMenuLinks(array &$links) : void {
    // First, add the top-level menu items.
    // @todo Consider turning this into a data object so we can avoid typos in
    // array keys.
    $content_links = [
      'navigation.create' => [
        'route_name' => 'node.add_page',
        'title' => $this->t('Create'),
        'weight' => -10,
      ],
      'navigation.content' => [
        'route_name' => 'view.content.page_1',
        'title' => $this->t('Content'),
      ],
      'navigation.files' => [
        'route_name' => 'view.files.page_1',
        'title' => $this->t('Files'),
      ],
      'navigation.media' => [
        'route_name' => 'view.media.media_page_list',
        'title' => $this->t('Media'),
      ],
      'navigation.blocks' => [
        'route_name' => 'view.block_content.page_1',
        'title' => $this->t('Blocks'),
      ],
    ];
    foreach ($content_links as $link_name => $link) {
      $this->addLink($link_name, $link, $links);
    }
    // Add supported add links under the Create button.
    $this->addCreateEntityLinks('node_type', 'node.add', $links);
    $this->addCreateEntityLinks('media_type', 'entity.media.add_form', $links, [
      'document',
      'image',
    ]);
    // Finally, add the bundleless User link and pin it to the bottom.
    $this->addLink('navigation.create.user', [
      'route_name' => 'user.admin_create',
      'title' => $this->t('User'),
      'parent' => 'navigation.create',
      'weight' => 100,
    ], $links);
  }
  
  /**
   * Remove the admin/content link, and any direct children.
   *
   * @param array $links
   *   The array of links being altered.
   */
  public function removeAdminContentLink(array &$links) : void {
    unset($links['system.admin_content']);
    // Also remove any links that have set admin/content as their parent link.
    // They are unsupported by the Navigation module.
    foreach ($links as $link_name => $link) {
      if (isset($link['parent']) && $link['parent'] === 'system.admin_content') {
        // @todo Do we need to make this recursive, and unset children of these
        // links too?
        unset($links[$link_name]);
      }
    }
  }
  
  /**
   * Remove the help link as render it outside any menu.
   *
   * @param array $links
   *   The array of links being altered.
   */
  public function removeHelpLink(array &$links) : void {
    unset($links['help.main']);
  }
  
  /**
   * Add create links for an entity type.
   *
   * This function preserves the order of entity types as it is called.
   *
   * @param string $entity_type
   *   The entity type to add links for, such as node_type.
   * @param string $add_route_id
   *   The ID of the route for the entity type add form.
   * @param array $links
   *   The existing array of links to add to.
   * @param array $bundle_allow_list
   *   A list of allowed bundles to include. Can be used to limit the list of
   *   bundles that are included for noisy entity types like media.
   */
  private function addCreateEntityLinks(string $entity_type, string $add_route_id, array &$links, array $bundle_allow_list = []) : void {
    // Ensure subsequent calls always get added to the bottom, and not in
    // alphabetical order.
    static $weight = 0;
    // The module providing the entity type is either not installed, or in the
    // process of being uninstalled.
    if (!$this->entityTypeManager
      ->hasDefinition($entity_type)) {
      return;
    }
    // Sort all types within an entity type alphabetically.
    $definition = $this->entityTypeManager
      ->getDefinition($entity_type);
    $types = $this->entityTypeManager
      ->getStorage($entity_type)
      ->loadMultiple();
    if (method_exists($definition->getClass(), 'sort')) {
      uasort($types, [
        $definition->getClass(),
        'sort',
      ]);
    }
    $add_content_links = [];
    foreach ($types as $type) {
      // Skip if the bundle is not in the allow list.
      if (!empty($bundle_allow_list) && !in_array($type->id(), $bundle_allow_list)) {
        continue;
      }
      $add_content_links['navigation.content.' . $type->getEntityTypeId() . '.' . $type->id()] = [
        'title' => $type->label(),
        'route_name' => $add_route_id,
        'route_parameters' => [
          $entity_type => $type->id(),
        ],
        'parent' => 'navigation.create',
        'weight' => $weight,
      ];
    }
    foreach ($add_content_links as $link_name => $link) {
      $this->addLink($link_name, $link, $links);
    }
    $weight++;
  }
  
  /**
   * Ensure a route exists and add the link.
   *
   * @param string $link_name
   *   The name of the link being added.
   * @param array $link
   *   The link array, as defined in hook_menu_links_discovered_alter().
   * @param array $links
   *   The existing array of links.
   */
  private function addLink(string $link_name, array $link, array &$links) : void {
    try {
      // Ensure the route exists (there is no separate "exists" method).
      $this->routeProvider
        ->getRouteByName($link['route_name']);
      $links[$link_name] = $link + [
        'menu_name' => 'content',
        'provider' => 'navigation',
      ];
    } catch (RouteNotFoundException $e) {
      // The module isn't installed, or the route (such as provided by a view)
      // has been deleted.
    }
  }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
NavigationContentLinks::addCreateEntityLinks private function Add create links for an entity type.
NavigationContentLinks::addLink private function Ensure a route exists and add the link.
NavigationContentLinks::addMenuLinks public function Add links to the Content menu, based on enabled modules.
NavigationContentLinks::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create
NavigationContentLinks::removeAdminContentLink public function Remove the admin/content link, and any direct children.
NavigationContentLinks::removeHelpLink public function Remove the help link as render it outside any menu.
NavigationContentLinks::__construct public function Construct a new NavigationContentLinks object.
StringTranslationTrait::$stringTranslation protected property The string translation service. 3
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.