From ac347da742f8e32f57480f05b72fceb8cee4323b Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Fri, 20 Dec 2024 18:41:12 +0000
Subject: [PATCH] Issue #3495305 by phenaproxima: Recipes that depend on other
 recipes break RecipeInputFormTrait

---
 core/lib/Drupal/Core/Recipe/InputConfigurator.php   | 13 +++++++------
 .../src/Functional/Form/RecipeFormInputTest.php     |  1 +
 core/tests/fixtures/recipes/input_test/recipe.yml   |  4 ++++
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/core/lib/Drupal/Core/Recipe/InputConfigurator.php b/core/lib/Drupal/Core/Recipe/InputConfigurator.php
index f6ace4b489b4..cec8e588611c 100644
--- a/core/lib/Drupal/Core/Recipe/InputConfigurator.php
+++ b/core/lib/Drupal/Core/Recipe/InputConfigurator.php
@@ -25,11 +25,11 @@ final class InputConfigurator {
   private array $data = [];
 
   /**
-   * The collected input values, or NULL if none have been collected yet.
+   * The collected input values.
    *
-   * @var mixed[]|null
+   * @var mixed[]
    */
-  private ?array $values = NULL;
+  private array $values = [];
 
   /**
    * @param array<string, array<string, mixed>> $definitions
@@ -96,7 +96,7 @@ public function getDataDefinitions(): array {
    *   The collected input values, keyed by name.
    */
   public function getValues(): array {
-    return $this->values ?? [];
+    return $this->values;
   }
 
   /**
@@ -131,13 +131,15 @@ public function describeAll(): array {
    * @throws \Symfony\Component\Validator\Exception\ValidationFailedException
    *   Thrown if any of the collected values violate their validation
    *   constraints.
+   * @throws \LogicException
+   *   Thrown if input values have already been collected for this recipe.
    */
   public function collectAll(InputCollectorInterface $collector, array &$processed = []): void {
     // 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)) {
+    if ($this->values) {
       throw new \LogicException('Input values cannot be changed once they have been set.');
     }
     // First, collect values for the recipe's dependencies.
@@ -146,7 +148,6 @@ public function collectAll(InputCollectorInterface $collector, array &$processed
       $dependency->input->collectAll($collector, $processed);
     }
 
-    $this->values = [];
     foreach ($this->data as $key => $data) {
       $definition = $data->getDataDefinition();
 
diff --git a/core/modules/system/tests/src/Functional/Form/RecipeFormInputTest.php b/core/modules/system/tests/src/Functional/Form/RecipeFormInputTest.php
index 90c1ef699c09..270212a5f62a 100644
--- a/core/modules/system/tests/src/Functional/Form/RecipeFormInputTest.php
+++ b/core/modules/system/tests/src/Functional/Form/RecipeFormInputTest.php
@@ -39,6 +39,7 @@ public function testRecipeInputViaForm(): void {
     // All recipe inputs are required, except for checkboxes, for which that
     // behavior makes no sense.
     $this->submitForm(['input_test[owner]' => ''], 'Apply recipe');
+    $assert_session->statusCodeEquals(200);
     $assert_session->statusMessageContains("Site owner's name field is required.", 'error');
     $assert_session->statusMessageNotContains('Allow mischief field is required.', 'error');
     // All inputs should be validated with their own constraints.
diff --git a/core/tests/fixtures/recipes/input_test/recipe.yml b/core/tests/fixtures/recipes/input_test/recipe.yml
index 629d40d02913..279bc7fee452 100644
--- a/core/tests/fixtures/recipes/input_test/recipe.yml
+++ b/core/tests/fixtures/recipes/input_test/recipe.yml
@@ -1,4 +1,8 @@
 name: Input Test
+recipes:
+  # Depend on another recipe in order to prove that we can collect input
+  # from recipes that depend on other recipes.
+  - no_extensions
 input:
   owner:
     data_type: string
-- 
GitLab