Verified Commit 21292df8 authored by godotislate's avatar godotislate
Browse files

refactor: #3571046 Use tagged iterators in PathProcessorManager and RouteProcessorManager

By: longwave
By: smustgrave
By: godotislate
parent a3e15af8
Loading
Loading
Loading
Loading
Loading
+0 −30
Original line number Diff line number Diff line
@@ -8923,24 +8923,6 @@
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/Path/Plugin/Validation/Constraint/ValidPathConstraintValidator.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\PathProcessor\\\\PathProcessorManager\\:\\:addInbound\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/PathProcessor/PathProcessorManager.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\PathProcessor\\\\PathProcessorManager\\:\\:addOutbound\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/PathProcessor/PathProcessorManager.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\PathProcessor\\\\PathProcessorManager\\:\\:sortProcessors\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/PathProcessor/PathProcessorManager.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\Plugin\\\\CachedDiscoveryClearer\\:\\:addCachedDiscovery\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
@@ -9649,24 +9631,12 @@
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/RouteProcessor/RouteProcessorCurrent.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\RouteProcessor\\\\RouteProcessorManager\\:\\:addOutbound\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/RouteProcessor/RouteProcessorManager.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\RouteProcessor\\\\RouteProcessorManager\\:\\:processOutbound\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/RouteProcessor/RouteProcessorManager.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\RouteProcessor\\\\RouteProcessorManager\\:\\:sortProcessors\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/RouteProcessor/RouteProcessorManager.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\Routing\\\\AccessAwareRouter\\:\\:__call\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
+2 −5
Original line number Diff line number Diff line
@@ -1516,14 +1516,11 @@ services:
    class: Drupal\Core\EventSubscriber\EnforcedFormResponseSubscriber
  route_processor_manager:
    class: Drupal\Core\RouteProcessor\RouteProcessorManager
    tags:
      - { name: service_collector, tag: route_processor_outbound, call: addOutbound }
    autowire: true
  Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface: '@route_processor_manager'
  path_processor_manager:
    class: Drupal\Core\PathProcessor\PathProcessorManager
    tags:
      - { name: service_collector, tag: path_processor_inbound, call: addInbound }
      - { name: service_collector, tag: path_processor_outbound, call: addOutbound }
    autowire: true
  Drupal\Core\PathProcessor\InboundPathProcessorInterface: '@path_processor_manager'
  Drupal\Core\PathProcessor\OutboundPathProcessorInterface: '@path_processor_manager'
  path_processor_decode:
+9 −103
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace Drupal\Core\PathProcessor;

use Drupal\Core\Render\BubbleableMetadata;
use Symfony\Component\DependencyInjection\Attribute\AutowireIterator;
use Symfony\Component\HttpFoundation\Request;

/**
@@ -13,126 +14,31 @@
 */
class PathProcessorManager implements InboundPathProcessorInterface, OutboundPathProcessorInterface {

  /**
   * Holds the array of inbound processors to cycle through.
   *
   * @var array
   *   An array whose keys are priorities and whose values are arrays of path
   *   processor objects.
   */
  protected $inboundProcessors = [];

  /**
   * Holds the array of inbound processors, sorted by priority.
   *
   * @var array
   *   An array of path processor objects.
   */
  protected $sortedInbound = [];


  /**
   * Holds the array of outbound processors to cycle through.
   *
   * @var array
   *   An array whose keys are priorities and whose values are arrays of path
   *   processor objects.
   */
  protected $outboundProcessors = [];

  /**
   * Holds the array of outbound processors, sorted by priority.
   *
   * @var array
   *   An array of path processor objects.
   */
  protected $sortedOutbound = [];

  /**
   * Adds an inbound processor object to the $inboundProcessors property.
   *
   * @param \Drupal\Core\PathProcessor\InboundPathProcessorInterface $processor
   *   The processor object to add.
   * @param int $priority
   *   The priority of the processor being added.
   */
  public function addInbound(InboundPathProcessorInterface $processor, $priority = 0) {
    $this->inboundProcessors[$priority][] = $processor;
    $this->sortedInbound = [];
  }
  public function __construct(
    #[AutowireIterator(tag: 'path_processor_inbound')]
    protected readonly iterable $inboundProcessors = [],
    #[AutowireIterator(tag: 'path_processor_outbound')]
    protected readonly iterable $outboundProcessors = [],
  ) {}

  /**
   * {@inheritdoc}
   */
  public function processInbound($path, Request $request) {
    $processors = $this->getInbound();
    foreach ($processors as $processor) {
    foreach ($this->inboundProcessors as $processor) {
      $path = $processor->processInbound($path, $request);
    }
    return $path;
  }

  /**
   * Returns the sorted array of inbound processors.
   *
   * @return array
   *   An array of processor objects.
   */
  protected function getInbound() {
    if (empty($this->sortedInbound)) {
      $this->sortedInbound = $this->sortProcessors('inboundProcessors');
    }

    return $this->sortedInbound;
  }

  /**
   * Adds an outbound processor object to the $outboundProcessors property.
   *
   * @param \Drupal\Core\PathProcessor\OutboundPathProcessorInterface $processor
   *   The processor object to add.
   * @param int $priority
   *   The priority of the processor being added.
   */
  public function addOutbound(OutboundPathProcessorInterface $processor, $priority = 0) {
    $this->outboundProcessors[$priority][] = $processor;
    $this->sortedOutbound = [];
  }

  /**
   * {@inheritdoc}
   */
  public function processOutbound($path, &$options = [], ?Request $request = NULL, ?BubbleableMetadata $bubbleable_metadata = NULL) {
    $processors = $this->getOutbound();
    foreach ($processors as $processor) {
    foreach ($this->outboundProcessors as $processor) {
      $path = $processor->processOutbound($path, $options, $request, $bubbleable_metadata);
    }
    return $path;
  }

  /**
   * Returns the sorted array of outbound processors.
   *
   * @return array
   *   An array of processor objects.
   */
  protected function getOutbound() {
    if (empty($this->sortedOutbound)) {
      $this->sortedOutbound = $this->sortProcessors('outboundProcessors');
    }

    return $this->sortedOutbound;
  }

  /**
   * Sorts the processors according to priority.
   *
   * @param string $type
   *   The processor type to sort, e.g. 'inboundProcessors'.
   */
  protected function sortProcessors($type) {
    krsort($this->{$type});
    return array_merge(...$this->{$type});
  }

}
+6 −53
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace Drupal\Core\RouteProcessor;

use Drupal\Core\Render\BubbleableMetadata;
use Symfony\Component\DependencyInjection\Attribute\AutowireIterator;
use Symfony\Component\Routing\Route;

/**
@@ -13,66 +14,18 @@
 */
class RouteProcessorManager implements OutboundRouteProcessorInterface {

  /**
   * Holds the array of outbound processors to cycle through.
   *
   * @var array
   *   An array whose keys are priorities and whose values are arrays of path
   *   processor objects.
   */
  protected $outboundProcessors = [];

  /**
   * Holds the array of outbound processors, sorted by priority.
   *
   * @var array
   *   An array of path processor objects.
   */
  protected $sortedOutbound = [];

  /**
   * Adds an outbound processor object to the $outboundProcessors property.
   *
   * @param \Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface $processor
   *   The processor object to add.
   * @param int $priority
   *   The priority of the processor being added.
   */
  public function addOutbound(OutboundRouteProcessorInterface $processor, $priority = 0) {
    $this->outboundProcessors[$priority][] = $processor;
    $this->sortedOutbound = [];
  }
  public function __construct(
    #[AutowireIterator(tag: 'route_processor_outbound')]
    protected readonly iterable $outboundProcessors = [],
  ) {}

  /**
   * {@inheritdoc}
   */
  public function processOutbound($route_name, Route $route, array &$parameters, ?BubbleableMetadata $bubbleable_metadata = NULL) {
    $processors = $this->getOutbound();
    foreach ($processors as $processor) {
    foreach ($this->outboundProcessors as $processor) {
      $processor->processOutbound($route_name, $route, $parameters, $bubbleable_metadata);
    }
  }

  /**
   * Returns the sorted array of outbound processors.
   *
   * @return array
   *   An array of processor objects.
   */
  protected function getOutbound() {
    if (empty($this->sortedOutbound)) {
      $this->sortedOutbound = $this->sortProcessors();
    }

    return $this->sortedOutbound;
  }

  /**
   * Sorts the processors according to priority.
   */
  protected function sortProcessors() {
    krsort($this->outboundProcessors);
    return array_merge(...$this->outboundProcessors);
  }

}
+14 −24
Original line number Diff line number Diff line
@@ -142,18 +142,12 @@ public function testProcessInbound(): void {
    // First, test the processor manager with the processors in the incorrect
    // order. The alias processor will run before the language processor,
    // meaning aliases will not be found.
    $priorities = [
      1000 => $alias_processor,
      500 => $decode_processor,
      300 => $front_processor,
      200 => $language_processor,
    ];

    // Create the processor manager and add the processors.
    $processor_manager = new PathProcessorManager();
    foreach ($priorities as $priority => $processor) {
      $processor_manager->addInbound($processor, $priority);
    }
    $processor_manager = new PathProcessorManager([
      $alias_processor,
      $decode_processor,
      $front_processor,
      $language_processor,
    ]);

    // Test resolving the French homepage using the incorrect processor order.
    $test_path = '/fr';
@@ -167,18 +161,14 @@ public function testProcessInbound(): void {
    $processed = $processor_manager->processInbound($test_path, $request);
    $this->assertEquals('/foo', $processed, 'Processing in the incorrect order fails to resolve the system path from an alias');

    // Now create a new processor manager and add the processors, this time in
    // the correct order.
    $processor_manager = new PathProcessorManager();
    $priorities = [
      1000 => $decode_processor,
      500 => $language_processor,
      300 => $front_processor,
      200 => $alias_processor,
    ];
    foreach ($priorities as $priority => $processor) {
      $processor_manager->addInbound($processor, $priority);
    }
    // Now create a new processor manager with the processors in the correct
    // order.
    $processor_manager = new PathProcessorManager([
      $decode_processor,
      $language_processor,
      $front_processor,
      $alias_processor,
    ]);

    // Test resolving the French homepage using the correct processor order.
    $test_path = '/fr';
Loading