Verified Commit 45da9862 authored by Dave Long's avatar Dave Long
Browse files

fix: #3592946 ComponentNegotiator::negotiate() re-runs on every call when no replacement is found

By: herved
By: amitgoyal
(cherry picked from commit 46e88176)
parent 94e2b1a5
Loading
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -49,9 +49,8 @@ public function __construct(
   */
  public function negotiate(string $component_id, array $all_definitions): ?string {
    $cache_key = $this->generateCacheKey($component_id);
    $cached_data = $this->cache[$cache_key] ?? NULL;
    if (isset($cached_data)) {
      return $cached_data;
    if (array_key_exists($cache_key, $this->cache)) {
      return $this->cache[$cache_key];
    }
    $negotiated = $this->doNegotiate($component_id, $all_definitions);
    $this->cache[$cache_key] = $negotiated;
+22 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
namespace Drupal\KernelTests\Components;

use Drupal\Core\Theme\ComponentNegotiator;
use Drupal\Core\Theme\ExtensionType;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
@@ -59,6 +60,27 @@ public function testNegotiate(): void {
    });
  }

  /**
   * Tests that negotiate() caches null results.
   */
  public function testNegotiateCachesNullResults(): void {
    $definitions = $this->manager->getDefinitions();

    // sdc_test:my-banner has no replacement: negotiate() returns null.
    $this->assertNull($this->negotiator->negotiate('sdc_test:my-banner', $definitions));

    // Add a fake replacement and call again. The null result must be served
    // from cache. Definitions are immutable within a request, so this fake
    // entry only serves to detect if doNegotiate() re-ran unexpectedly.
    $definitions['fake:replacement'] = [
      'id' => 'fake:replacement',
      'replaces' => 'sdc_test:my-banner',
      'extension_type' => ExtensionType::Module,
      'provider' => 'sdc_test',
    ];
    $this->assertNull($this->negotiator->negotiate('sdc_test:my-banner', $definitions));
  }

  /**
   * Tests rendering components with component replacement.
   */