Commit 08c00c6b authored by catch's avatar catch
Browse files

feat: #3536470 TypeError if #[ReOrderHook] targets hook that has no...

feat: #3536470 TypeError if #[ReOrderHook] targets hook that has no implementations anywhere in enabled modules.

By: @donquixote
By: @nicxvan
By: @xjm
By: @catch
By: @phenaproxima
(cherry picked from commit ed3bb26b)
parent 03fe654e
Loading
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -317,10 +317,18 @@ protected function calculateImplementations(): array {
   *   Order operations by hook name.
   */
  protected function getOrderOperations(): array {
    $implementationsByHook = $this->getFilteredImplementations();
    $operations_by_hook = [];
    foreach ($this->orderOperations as $hook => $order_operations_by_weight) {
      ksort($order_operations_by_weight);
      $operations_by_hook[$hook] = array_merge(...$order_operations_by_weight);
      $order_operations = array_merge(...$order_operations_by_weight);
      foreach ($order_operations as $key => $operation) {
        if (!isset($implementationsByHook[$hook][$operation->identify()])) {
          unset($order_operations[$key]);
        }
      }
      $operations_by_hook[$hook] = array_values($order_operations);

    }
    return $operations_by_hook;
  }
+7 −0
Original line number Diff line number Diff line
@@ -34,6 +34,13 @@ public function __construct(
    protected readonly bool $isAfter,
  ) {}

  /**
   * {@inheritdoc}
   */
  public function identify(): string {
    return $this->identifier;
  }

  /**
   * {@inheritdoc}
   */
+7 −0
Original line number Diff line number Diff line
@@ -26,6 +26,13 @@ public function __construct(
    protected readonly bool $isLast,
  ) {}

  /**
   * {@inheritdoc}
   */
  public function identify(): string {
    return $this->identifier;
  }

  /**
   * {@inheritdoc}
   */
+10 −0
Original line number Diff line number Diff line
@@ -23,6 +23,16 @@ abstract class OrderOperation {
   */
  abstract public function apply(array &$identifiers, array $module_finder): void;

  /**
   * Returns the identifier for filtering.
   *
   * The hook implementation identifier, as "$class::$method", to be changed by.
   *
   * @return string
   *   The identifier for the OrderOperation.
   */
  abstract public function identify(): string;

  /**
   * Converts the operation to a structure that can be stored in the container.
   *
+75 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\aaa_hook_order_test\Hook;

use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Hook\Attribute\ReorderHook;
use Drupal\Core\Hook\Order\Order;

/**
 * Contains alter hook implementations.
 *
 * @see \Drupal\KernelTests\Core\Hook\HookAlterOrderTest::testReorderCrossHookAlter()
 */
class ACrossHookReorderAlter {

  #[Hook('test_cross_hook_reorder_base_alter', order: Order::Last)]
  public function baseAlterLast(array &$calls): void {
    $calls[] = __METHOD__;
  }

  /**
   * Implements the base alter hook.
   *
   * This method implements the base alter hook, and has an Order::Last rule.
   * In addition, it is targeted by a #[ReorderHook] for the subtype alter hook.
   *
   * @see self::subtypeAlterLast()
   */
  #[ReorderHook('test_cross_hook_reorder_subtype_alter', self::class, 'baseAlterLastAlsoIfSubtype', Order::Last)]
  #[Hook('test_cross_hook_reorder_base_alter', order: Order::Last)]
  public function baseAlterLastAlsoIfSubtype(array &$calls): void {
    $calls[] = __METHOD__;
  }

  #[ReorderHook('test_cross_hook_reorder_subtype_alter', self::class, 'baseAlterLastIfSubtype', Order::Last)]
  #[Hook('test_cross_hook_reorder_base_alter')]
  public function baseAlterLastIfSubtype(array &$calls): void {
    $calls[] = __METHOD__;
  }

  /**
   * Implements the subtype alter hook.
   *
   * In a call to ->alter(['..base', '..subtype'], ..), this method wants to be
   * called after most other implementations, but not after
   * ::baseAlterLastAlsoIfSubtype().
   *
   * To achieve this, it has a #[ReorderHook] that targets
   * ::baseAlterLastAlsoIfSubtype() in context of the subtype hook, meant to
   * reinforce the Order::Last from that base hook implementation.
   */
  #[Hook('test_cross_hook_reorder_subtype_alter', order: Order::Last)]
  public function subtypeAlterLast(array &$calls): void {
    $calls[] = __METHOD__;
  }

  #[ReorderHook('test_cross_hook_reorder_base_alter', self::class, 'subtypeAlterLastIfBaseHook', Order::Last)]
  #[Hook('test_cross_hook_reorder_subtype_alter')]
  public function subtypeAlterLastIfBaseHook(array &$calls): void {
    $calls[] = __METHOD__;
  }

  #[Hook('test_cross_hook_reorder_base_alter')]
  public function baseAlter(array &$calls): void {
    $calls[] = __METHOD__;
  }

  #[Hook('test_cross_hook_reorder_subtype_alter')]
  public function subtypeAlter(array &$calls): void {
    $calls[] = __METHOD__;
  }

}
Loading