From bc8a19c8f7a02e72582cee909b80e27cfb2945be Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Tue, 19 Nov 2024 09:30:00 +0000
Subject: [PATCH] Issue #3488179 by phenaproxima, thejimbirch:
 RecipeConfigurator::getIncludedRecipe() should statically cache recipe
 objects to avoid performance problems

---
 core/lib/Drupal/Core/Recipe/InputConfigurator.php  |  8 +++-----
 core/lib/Drupal/Core/Recipe/RecipeConfigurator.php | 12 +++++++++++-
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/core/lib/Drupal/Core/Recipe/InputConfigurator.php b/core/lib/Drupal/Core/Recipe/InputConfigurator.php
index 4e429ef70cf0..77bac34c6f1b 100644
--- a/core/lib/Drupal/Core/Recipe/InputConfigurator.php
+++ b/core/lib/Drupal/Core/Recipe/InputConfigurator.php
@@ -133,15 +133,13 @@ public function describeAll(): array {
    *   constraints.
    */
   public function collectAll(InputCollectorInterface $collector, array &$processed = []): void {
-    if (is_array($this->values)) {
-      throw new \LogicException('Input values cannot be changed once they have been set.');
-    }
-
     // Don't bother collecting values for a recipe we've already seen.
     if (in_array($this->prefix, $processed, TRUE)) {
       return;
     }
-
+    if (is_array($this->values)) {
+      throw new \LogicException('Input values cannot be changed once they have been set.');
+    }
     // First, collect values for the recipe's dependencies.
     /** @var \Drupal\Core\Recipe\Recipe $dependency */
     foreach ($this->dependencies->recipes as $dependency) {
diff --git a/core/lib/Drupal/Core/Recipe/RecipeConfigurator.php b/core/lib/Drupal/Core/Recipe/RecipeConfigurator.php
index 8e1402af2d46..e0d8a0f5826e 100644
--- a/core/lib/Drupal/Core/Recipe/RecipeConfigurator.php
+++ b/core/lib/Drupal/Core/Recipe/RecipeConfigurator.php
@@ -15,6 +15,13 @@ final class RecipeConfigurator {
    */
   public readonly array $recipes;
 
+  /**
+   * A cache of already-loaded recipes, keyed by path.
+   *
+   * @var \Drupal\Core\Recipe\Recipe[]
+   */
+  private static array $cache = [];
+
   /**
    * @param string[] $recipes
    *   A list of recipes for a recipe to apply. The recipes will be applied in
@@ -56,8 +63,11 @@ public static function getIncludedRecipe(string $include_path, string $name): Re
       $path = $include_path . "/$name/recipe.yml";
     }
 
+    if (array_key_exists($path, static::$cache)) {
+      return static::$cache[$path];
+    }
     if (file_exists($path)) {
-      return Recipe::createFromDirectory(dirname($path));
+      return static::$cache[$path] = Recipe::createFromDirectory(dirname($path));
     }
     $search_path = dirname($path, 2);
     throw new UnknownRecipeException($name, $search_path, sprintf("Can not find the %s recipe, search path: %s", $name, $search_path));
-- 
GitLab