Verified Commit 64bfef04 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #3512835 by nicxvan: [11.1.x] Add BC stubs for Hook ordering

parent d0c9e278
Loading
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@

namespace Drupal\Core\Hook\Attribute;

use Drupal\Core\Hook\Order\OrderInterface;

/**
 * Attribute for defining a class method as a hook implementation.
 *
@@ -88,28 +90,54 @@
 * See \Drupal\Core\Hook\Attribute\LegacyHook for additional information.
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class Hook {
class Hook implements HookAttributeInterface {
  /**
   * The hook prefix such as `form`.
   *
   * @var string
   */
  public const string PREFIX = '';

  /**
   * The hook suffix such as `alter`.
   *
   * @var string
   */
  public const string SUFFIX = '';

  /**
   * Constructs a Hook attribute object.
   *
   * @param string $hook
   *   The short hook name, without the 'hook_' prefix.
   *   $hook is only optional when Hook is extended and a PREFIX or SUFFIX is
   *   defined. When using the [#Hook] attribute directly $hook is required.
   *   See Drupal\Core\Hook\Attribute\Preprocess.
   * @param string $method
   *   (optional) The method name. If this attribute is on a method, this
   *   parameter is not required. If this attribute is on a class and this
   *   parameter is omitted, the class must have an __invoke() method, which is
   *   taken as the hook implementation.
   * @param string|null $module
   *   (optional) The module this implementation is for. This allows one module to
   *   implement a hook on behalf of another module. Defaults to the module the
   *   implementation is in.
   *   (optional) The module this implementation is for. This allows one module
   *   to implement a hook on behalf of another module. Defaults to the module
   *   the implementation is in.
   * @param \Drupal\Core\Hook\Order\OrderInterface|null $order
   *   (optional) Set the order of the implementation. This parameter is
   *   supported in Drupal 11.2 and greater. It will have no affect in Drupal
   *   11.1.
   */
  public function __construct(
    public string $hook,
    public string $hook = '',
    public string $method = '',
    public ?string $module = NULL,
  ) {}
    public OrderInterface|null $order = NULL,
  ) {
    $this->hook = implode('_', array_filter([static::PREFIX, $hook, static::SUFFIX]));
    if ($this->hook === '') {
      throw new \LogicException('The Hook attribute or an attribute extending the Hook attribute must provide the $hook parameter, a PREFIX or a SUFFIX.');
    }
  }

  /**
   * Set the method the hook should apply to.
+15 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Core\Hook\Attribute;

/**
 * Common interface for attributes used for hook discovery.
 *
 * This does not imply any shared behavior, it is only used to collect all
 * hook-related attributes in the same call.
 *
 * @internal
 */
interface HookAttributeInterface {}
+22 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Core\Hook\Attribute;

/**
 * Prevents procedural hook_module_implements_alter from executing.
 *
 * This allows the use of the legacy hook_module_implements_alter alongside
 * attribute-based ordering. Providing support for versions of Drupal older
 * than 11.2.0.
 *
 * Marking hook_module_implements_alter as #LegacyModuleImplementsAlter will
 * prevent hook_module_implements_alter from running when attribute-based
 * ordering is available.
 *
 * On older versions of Drupal which are not aware of attribute-based ordering,
 * only the legacy hook implementation is executed.
 */
#[\Attribute(\Attribute::TARGET_FUNCTION)]
class LegacyModuleImplementsAlter {}
+35 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Core\Hook\Attribute;

/**
 * Removes an already existing implementation.
 *
 * The effect of this attribute is independent from the specific class or method
 * on which it is placed.
 *
 * This attribute is supported in Drupal 11.2 and greater.
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class RemoveHook implements HookAttributeInterface {

  /**
   * Constructs a RemoveHook object.
   *
   * @param string $hook
   *   The hook name from which to remove the target implementation.
   * @param class-string $class
   *   The class name of the target hook implementation.
   * @param string $method
   *   The method name of the target hook implementation.
   *   If the class instance itself is the listener, this should be '__invoke'.
   */
  public function __construct(
    public readonly string $hook,
    public readonly string $class,
    public readonly string $method,
  ) {}

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

declare(strict_types=1);

namespace Drupal\Core\Hook\Attribute;

use Drupal\Core\Hook\Order\OrderInterface;

/**
 * Sets the order of an already existing implementation.
 *
 * The effect of this attribute is independent from the specific class or method
 * on which it is placed.
 *
 * This attribute is supported in Drupal 11.2 and greater.
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class ReorderHook implements HookAttributeInterface {

  /**
   * Constructs a ReorderHook object.
   *
   * @param string $hook
   *   The hook for which to reorder an implementation.
   * @param class-string $class
   *   The class of the targeted hook implementation.
   * @param string $method
   *   The method name of the targeted hook implementation.
   *   If the #[Hook] attribute is on the class itself, this should be
   *   '__invoke'.
   * @param \Drupal\Core\Hook\Order\OrderInterface $order
   *   Specifies a new position for the targeted hook implementation relative to
   *   other implementations.
   */
  public function __construct(
    public string $hook,
    public string $class,
    public string $method,
    public OrderInterface $order,
  ) {}

}
Loading