Commit 3407e5de authored by Luhur Abdi Rizal's avatar Luhur Abdi Rizal
Browse files

Issue #3273042 by el7cosmos: Add event for hook_menu_local_tasks_alter

parent 989b2e73
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ use Drupal\block\BlockInterface;
use Drupal\Core\Access\AccessResultInterface;
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
use Drupal\Core\Config\ConfigImporter;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
@@ -70,6 +71,7 @@ use Drupal\core_event_dispatcher\Event\Form\FormAlterEvent;
use Drupal\core_event_dispatcher\Event\Form\FormBaseAlterEvent;
use Drupal\core_event_dispatcher\Event\Form\FormIdAlterEvent;
use Drupal\core_event_dispatcher\Event\Language\LanguageSwitchLinksAlterEvent;
use Drupal\core_event_dispatcher\Event\Menu\MenuLocalTasksAlterEvent;
use Drupal\core_event_dispatcher\Event\Theme\JsAlterEvent;
use Drupal\core_event_dispatcher\Event\Theme\LibraryInfoAlterEvent;
use Drupal\core_event_dispatcher\Event\Theme\PageAttachmentsEvent;
@@ -673,6 +675,15 @@ function core_event_dispatcher_language_switch_links_alter(array &$links, string
  $manager->register(new LanguageSwitchLinksAlterEvent($links, $type, $path));
}

/**
 * Implements hook_menu_local_tasks_alter().
 */
function core_event_dispatcher_menu_local_tasks_alter(&$data, $routeName, RefinableCacheableDependencyInterface $cacheability) {
  /** @var \Drupal\hook_event_dispatcher\Manager\HookEventDispatcherManagerInterface $manager */
  $manager = Drupal::service('hook_event_dispatcher.manager.legacy');
  $manager->register(new MenuLocalTasksAlterEvent($data, $routeName, $cacheability));
}

/**
 * Implements hook_theme_suggestions_alter().
 *
+106 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\core_event_dispatcher\Event\Menu;

use Drupal\Component\EventDispatcher\Event;
use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
use Drupal\core_event_dispatcher\MenuHookEvents;
use Drupal\hook_event_dispatcher\Event\EventInterface;

/**
 * Class MenuLocalTasksAlterEvent.
 *
 * @HookEvent(
 *   id = "menu_local_tasks_alter",
 *   alter = "menu_local_tasks"
 * )
 */
class MenuLocalTasksAlterEvent extends Event implements EventInterface {

  /**
   * An associative array of menu local tasks data.
   *
   * @var array
   */
  protected $data;

  /**
   * The route name of the page.
   *
   * @var string
   */
  protected $routeName;

  /**
   * The cacheability metadata for the current route's local tasks.
   *
   * @var \Drupal\Core\Cache\RefinableCacheableDependencyInterface
   */
  protected $cacheability;

  /**
   * MenuLocalTaskAlterEvent constructor.
   *
   * @param array $data
   *   An associative array containing list of (up to 2) tab levels that
   *   contain a list of tabs keyed by their href, each one being an
   *   associative array.
   * @param string $routeName
   *   The route name of the page.
   * @param \Drupal\Core\Cache\RefinableCacheableDependencyInterface $cacheability
   *   The cacheability metadata for the current route's local tasks.
   */
  public function __construct(array &$data, string $routeName, RefinableCacheableDependencyInterface $cacheability) {
    $this->cacheability = $cacheability;
    $this->data = &$data;
    $this->routeName = $routeName;
  }

  /**
   * {@inheritdoc}
   */
  public function getDispatcherType(): string {
    return MenuHookEvents::MENU_LOCAL_TASKS_ALTER;
  }

  /**
   * Gets the menu local tasks data.
   *
   * @return array
   *   An associative array containing list of (up to 2) tab levels.
   */
  public function &getData(): array {
    return $this->data;
  }

  /**
   * Sets the menu local tasks data.
   *
   * @param array $data
   *   The menu local tasks data.
   */
  public function setData(array $data): void {
    $this->data = $data;
  }

  /**
   * Gets the route name of the page.
   *
   * @return string
   *   The route name of the page.
   */
  public function getRouteName(): string {
    return $this->routeName;
  }

  /**
   * Gets the cacheability metadata for the current route's local tasks.
   *
   * @return \Drupal\Core\Cache\RefinableCacheableDependencyInterface
   *   The cacheability metadata.
   */
  public function getCacheability(): RefinableCacheableDependencyInterface {
    return $this->cacheability;
  }

}
+25 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\core_event_dispatcher;

use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;

/**
 * Define events for menu hooks.
 */
final class MenuHookEvents {

  /**
   * Alter local tasks displayed on the page before they are rendered.
   *
   * @Event
   *
   * @see \Drupal\core_event_dispatcher\Event\Menu\MenuLocalTasksAlterEvent
   * @see core_event_dispatcher_menu_local_tasks_alter()
   * @see hook_menu_local_tasks_alter()
   *
   * @var string
   */
  public const MENU_LOCAL_TASKS_ALTER = HookEventDispatcherInterface::PREFIX . 'menu_local_tasks.alter';

}
+81 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\core_event_dispatcher\Kernel\Menu;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\core_event_dispatcher\Event\Menu\MenuLocalTasksAlterEvent;
use Drupal\core_event_dispatcher\MenuHookEvents;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\hook_event_dispatcher\Kernel\ListenerTrait;

/**
 * Class MenuLocalTasksAlterEventTest.
 *
 * @group hook_event_dispatcher
 * @group core_event_dispatcher
 *
 * @see core_event_dispatcher_menu_local_tasks_alter()
 */
class MenuLocalTasksAlterEventTest extends KernelTestBase {

  use ListenerTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'hook_event_dispatcher',
    'core_event_dispatcher',
  ];

  /**
   * Test MenuLocalTasksAlterEvent.
   *
   * @throws \Exception
   */
  public function testMenuLocalTasksAlterEvent(): void {
    $this->listen(MenuHookEvents::MENU_LOCAL_TASKS_ALTER, 'onMenuLocalTasksAlter', $this->exactly(2));

    $localTaskManager = $this->container->get('plugin.manager.menu.local_task');
    $noneLocalTasks = $localTaskManager->getLocalTasks('<none>');
    $this->assertArrayHasKey('tabs', $noneLocalTasks);
    $this->assertEmpty($noneLocalTasks['tabs']);

    $frontLocalTasks = $localTaskManager->getLocalTasks('<front>');
    $this->assertArrayHasKey('tabs', $frontLocalTasks);
    $this->assertIsArray($frontLocalTasks['tabs']);
    $this->assertNotEmpty($frontLocalTasks['tabs']);
    $this->assertArrayHasKey('foo', $frontLocalTasks['tabs']);
    $this->assertTrue($frontLocalTasks['tabs']['foo']);
    $this->assertArrayHasKey('bar', $frontLocalTasks['tabs']);
    $this->assertTrue($frontLocalTasks['tabs']['bar']);

    $this->assertArrayHasKey('cacheability', $frontLocalTasks);
    $cacheability = $frontLocalTasks['cacheability'];
    $this->assertInstanceOf(CacheableMetadata::class, $cacheability);
    $this->assertContains('kittens:dwarf-cat', $cacheability->getCacheTags());
  }

  /**
   * Callback for MenuLocalTasksAlterEvent.
   *
   * @param \Drupal\core_event_dispatcher\Event\Menu\MenuLocalTasksAlterEvent $event
   *   The event.
   */
  public function onMenuLocalTasksAlter(MenuLocalTasksAlterEvent $event): void {
    if ($event->getRouteName() === '<front>') {
      $data = $event->getData();
      $this->assertArrayHasKey('tabs', $data);
      $this->assertEmpty($data['tabs']);

      $data['tabs'][0]['foo'] = TRUE;
      $event->setData($data);

      $refData = &$event->getData();
      $refData['tabs'][0]['bar'] = TRUE;
    }
    $this->assertNotContains('kittens:dwarf-cat', $event->getCacheability()->getCacheTags());
    $event->getCacheability()->addCacheTags(['kittens:dwarf-cat']);
  }

}