From 72071e21a4ca685386b8f3e429e7e0d528bb60ed Mon Sep 17 00:00:00 2001
From: Pieter Frenssen <pieter@frenssen.be>
Date: Mon, 10 Feb 2025 15:25:26 +0200
Subject: [PATCH 1/3] Revert "Issue #3472252 by pfrenssen, ralf57, hazn: Remove
 Metadata subfields"

This reverts commit 164e3cc9934ec2600838cd1f507b080cd4926455.
---
 README.md                                     | 14 ++++---
 .../SchemaExtension/WebformExtension.php      | 19 ++++++---
 src/WebformSchemaBuilder.php                  | 22 +++++++----
 tests/queries/actions.gql                     |  9 +++--
 tests/queries/checkboxes.gql                  |  8 ++--
 tests/queries/flexbox.gql                     | 10 +++--
 tests/queries/managed_file.gql                |  3 ++
 tests/queries/markup.gql                      |  3 ++
 tests/queries/multiple.gql                    |  2 +-
 tests/queries/radios.gql                      | 13 ++++---
 tests/queries/select.gql                      |  8 ++--
 tests/queries/term_select.gql                 | 12 +++---
 tests/queries/textarea.gql                    | 13 ++++---
 tests/queries/textfield.gql                   | 13 ++++---
 tests/queries/unexposed.gql                   | 10 +++--
 tests/src/Kernel/Element/ActionsTest.php      |  9 +++--
 tests/src/Kernel/Element/CheckboxesTest.php   |  8 ++--
 tests/src/Kernel/Element/FlexboxTest.php      | 14 +++++--
 tests/src/Kernel/Element/ManagedFileTest.php  | 22 +++++++----
 tests/src/Kernel/Element/MarkupTest.php       |  3 ++
 .../src/Kernel/Element/MultipleValuesTest.php | 18 ++++-----
 tests/src/Kernel/Element/RadiosTest.php       | 13 ++++---
 tests/src/Kernel/Element/SelectTest.php       | 16 +++++---
 tests/src/Kernel/Element/TermSelectTest.php   | 12 +++---
 tests/src/Kernel/Element/TextAreaTest.php     | 13 ++++---
 tests/src/Kernel/Element/TextFieldTest.php    | 39 +++++++++++--------
 .../Kernel/Element/UnexposedElementTest.php   |  9 +++--
 27 files changed, 211 insertions(+), 124 deletions(-)

diff --git a/README.md b/README.md
index 950ea5b..2d7bb06 100644
--- a/README.md
+++ b/README.md
@@ -46,8 +46,10 @@ by granting the `access any webform configuration` permission.
         description
         elements {
           ... on WebformElement {
-            key
-            type
+            metadata {
+              key
+              type
+            }
           }
           ... on WebformElementWebformActions {
             submitLabel
@@ -124,9 +126,11 @@ by granting the `access any webform configuration` permission.
             }
           }
           ... on WebformElementWebformTermSelect {
-            title
-            description
-            multiple
+            metadata {
+              title
+              description
+              multiple
+            }
             options(depth: 1) {
               value
               title
diff --git a/src/Plugin/GraphQL/SchemaExtension/WebformExtension.php b/src/Plugin/GraphQL/SchemaExtension/WebformExtension.php
index 1f7de8f..548af98 100644
--- a/src/Plugin/GraphQL/SchemaExtension/WebformExtension.php
+++ b/src/Plugin/GraphQL/SchemaExtension/WebformExtension.php
@@ -137,15 +137,20 @@ class WebformExtension extends SdlSchemaExtensionPluginBase {
         ->map('id', $builder->fromArgument('id'))
     );
 
-    $registry->addFieldResolver('WebformElement', 'key', $builder->callback(
+    // Expose the metadata of the webform element.
+    $registry->addFieldResolver('WebformElement', 'metadata', $builder->callback(
+      fn (array $value): array => $value
+    ));
+
+    $registry->addFieldResolver('WebformElementMetadata', 'key', $builder->callback(
       fn (array $value): string => $value['#webform_key'] ?? ''
     ));
 
-    $registry->addFieldResolver('WebformElement', 'type', $builder->callback(
+    $registry->addFieldResolver('WebformElementMetadata', 'type', $builder->callback(
       fn (array $value): string => $value['#webform_plugin_id'] ?? ''
     ));
 
-    $registry->addFieldResolver('WebformElement', 'name', $builder->callback(
+    $registry->addFieldResolver('WebformElementMetadata', 'name', $builder->callback(
       function ($value) {
         $name = $value['#name'] ?? '';
         // When an element can be multiple, we remove the nested name of the
@@ -155,15 +160,17 @@ class WebformExtension extends SdlSchemaExtensionPluginBase {
       }
     ));
 
-    $registry->addFieldResolver('WebformElement', 'element', $builder->callback(
+    $registry->addFieldResolver('WebformElementMetadata', 'element', $builder->callback(
       fn (array $value): array => $value
     ));
 
     $typeFields = [
-      'WebformElement' => [
+      'WebformElementMetadata' => [
         'title' => 'string',
         'description' => 'string',
         'multiple' => 'int',
+        'required' => 'boolean',
+        'requiredError' => 'string',
       ],
       'WebformElementMarkupBase' => [
         'markup' => 'string',
@@ -214,7 +221,7 @@ class WebformExtension extends SdlSchemaExtensionPluginBase {
     );
 
     // Expose information about elements that accept multiple values.
-    $registry->addFieldResolver('WebformElementMultipleValuesBase', 'multipleValues', $builder
+    $registry->addFieldResolver('WebformElementMultipleValuesBase', 'multiple', $builder
       ->produce('webform_element_multiple_values')
       ->map('element', $builder->fromParent())
     );
diff --git a/src/WebformSchemaBuilder.php b/src/WebformSchemaBuilder.php
index 6885b07..5499379 100644
--- a/src/WebformSchemaBuilder.php
+++ b/src/WebformSchemaBuilder.php
@@ -46,6 +46,18 @@ class WebformSchemaBuilder {
   public function __construct() {
     $this->types = [];
 
+    $this->types['WebformElementMetadata'] = new ObjectType([
+      'name' => 'WebformElementMetadata',
+      'fields' => [
+        'key' => $this->type(Type::nonNull(Type::string()), 'The key of the element.'),
+        'type' => $this->type(Type::nonNull(Type::string()), 'The element type.'),
+        'title' => $this->type(Type::string(), ''),
+        'description' => $this->type(Type::string(), ''),
+        'multiple' => $this->type(Type::int(), 'The number of values that can be entered into the element. Unlimited if 0.'),
+        'required' => $this->type(Type::boolean(), 'Whether or not input is required on the element. It might be more convenient to use WebformRequiredElement.'),
+        'requiredError' => $this->type(Type::string(), 'The error message to show when required input is missing. It might be more convenient to use WebformRequiredElement.'),
+      ],
+    ]);
     $this->types['WebformRequiredElement'] = new ObjectType([
       'name' => 'WebformRequiredElement',
       'description' => 'Indicates that the Webform element is required.',
@@ -132,7 +144,7 @@ class WebformSchemaBuilder {
     $this->types['WebformElementMultipleValuesBase'] = new InterfaceType([
       'name' => 'WebformElementMultipleValuesBase',
       'fields' => [
-        'multipleValues' => $this->types['WebformElementMultipleValues'],
+        'multiple' => $this->types['WebformElementMultipleValues'],
       ],
     ]);
 
@@ -229,7 +241,7 @@ class WebformSchemaBuilder {
       $interfaces[] = fn () => $this->types['WebformElementMultipleValuesBase'];
       $fields = [
         ...$fields,
-        'multipleValues' => fn () => $this->types['WebformElementMultipleValues'],
+        'multiple' => fn () => $this->types['WebformElementMultipleValues'],
       ];
     }
 
@@ -315,12 +327,8 @@ class WebformSchemaBuilder {
    */
   protected function getElementDefinition(): array {
     return [
+      'metadata' => fn () => $this->types['WebformElementMetadata'],
       'required' => $this->types['WebformRequiredElement'],
-      'key' => $this->type(Type::nonNull(Type::string()), 'The key of the element.'),
-      'type' => $this->type(Type::nonNull(Type::string()), 'The element type.'),
-      'title' => $this->type(Type::string(), ''),
-      'description' => $this->type(Type::string(), ''),
-      'multiple' => $this->type(Type::int(), 'The number of values that can be entered into the element. Unlimited if 0.'),
     ];
   }
 
diff --git a/tests/queries/actions.gql b/tests/queries/actions.gql
index c9dbd0e..9513ddc 100644
--- a/tests/queries/actions.gql
+++ b/tests/queries/actions.gql
@@ -1,9 +1,12 @@
 fragment webformElement on WebformElementWebformActions {
   __typename
   submitLabel
-  key
-  type
-  title
+  metadata {
+    __typename
+    key
+    type
+    title
+  }
 }
 
 fragment webform on Webform {
diff --git a/tests/queries/checkboxes.gql b/tests/queries/checkboxes.gql
index 9994841..886f62a 100644
--- a/tests/queries/checkboxes.gql
+++ b/tests/queries/checkboxes.gql
@@ -6,9 +6,11 @@ fragment webformElementOption on WebformElementOption {
 
 fragment webformElementCheckboxes on WebformElementCheckboxes {
   __typename
-  key
-  title
-  description
+  metadata {
+    key
+    title
+    description
+  }
   options {
     ...webformElementOption
   }
diff --git a/tests/queries/flexbox.gql b/tests/queries/flexbox.gql
index 98aa414..0007113 100644
--- a/tests/queries/flexbox.gql
+++ b/tests/queries/flexbox.gql
@@ -1,10 +1,14 @@
 fragment flexboxes on WebformElementWebformFlexbox {
   __typename
-  key
-  type
+  metadata {
+    key
+    type
+  }
   alignItems
   elements {
-    key
+    metadata {
+      key
+    }
   }
 }
 
diff --git a/tests/queries/managed_file.gql b/tests/queries/managed_file.gql
index f1ff9a3..43f0dc2 100644
--- a/tests/queries/managed_file.gql
+++ b/tests/queries/managed_file.gql
@@ -1,9 +1,12 @@
 fragment webformElement on WebformElement {
   __typename
+  metadata {
+    __typename
   key
   type
   title
   description
+  }
 }
 
 fragment webformElementManagedFileBase on WebformElementManagedFileBase {
diff --git a/tests/queries/markup.gql b/tests/queries/markup.gql
index 27af61e..4055990 100644
--- a/tests/queries/markup.gql
+++ b/tests/queries/markup.gql
@@ -1,5 +1,8 @@
 fragment webformElementMarkup on WebformElementMarkupBase {
   __typename
+  metadata {
+    key
+  }
   markup
   displayOn
 }
diff --git a/tests/queries/multiple.gql b/tests/queries/multiple.gql
index cb3cc4e..407452e 100644
--- a/tests/queries/multiple.gql
+++ b/tests/queries/multiple.gql
@@ -18,7 +18,7 @@ fragment multiple on WebformElementMultipleValues {
 }
 
 fragment element on WebformElementMultipleValuesBase {
-  multipleValues {
+  multiple {
     ...multiple
   }
 }
diff --git a/tests/queries/radios.gql b/tests/queries/radios.gql
index 449df74..8db0f22 100644
--- a/tests/queries/radios.gql
+++ b/tests/queries/radios.gql
@@ -7,12 +7,13 @@ fragment webformElementOption on WebformElementOption {
 
 fragment webformElementRadios on WebformElementRadios {
   __typename
-  key
-  type
-  title
-  description
-  required {
-    message
+  metadata {
+    key
+    type
+    title
+    description
+    required
+    requiredError
   }
   options {
     ...webformElementOption
diff --git a/tests/queries/select.gql b/tests/queries/select.gql
index 718ed43..75cc5ac 100644
--- a/tests/queries/select.gql
+++ b/tests/queries/select.gql
@@ -6,9 +6,11 @@ fragment webformElementOption on WebformElementOption {
 
 fragment webformElementSelect on WebformElementSelect {
   __typename
-  key
-  title
-  description
+  metadata {
+    key
+    title
+    description
+  }
   options {
     ...webformElementOption
   }
diff --git a/tests/queries/term_select.gql b/tests/queries/term_select.gql
index 259bb51..7b85fc1 100644
--- a/tests/queries/term_select.gql
+++ b/tests/queries/term_select.gql
@@ -1,10 +1,12 @@
 fragment webformElementTermSelect on WebformElementWebformTermSelect {
   __typename
-  key
-  type
-  title
-  description
-  multiple
+  metadata {
+    key
+    type
+    title
+    description
+    multiple
+  }
   options(depth: $depth) {
     title
   }
diff --git a/tests/queries/textarea.gql b/tests/queries/textarea.gql
index 895e244..6aa6e62 100644
--- a/tests/queries/textarea.gql
+++ b/tests/queries/textarea.gql
@@ -6,12 +6,13 @@ fragment webformElementValidationPattern on WebformElementValidationPattern {
 
 fragment webformElementTextarea on WebformElementTextarea {
   __typename
-  key
-  type
-  title
-  description
-  required {
-    message
+  metadata {
+    key
+    type
+    title
+    description
+    required
+    requiredError
   }
   readonly
   size
diff --git a/tests/queries/textfield.gql b/tests/queries/textfield.gql
index c74768e..4b7bc02 100644
--- a/tests/queries/textfield.gql
+++ b/tests/queries/textfield.gql
@@ -1,11 +1,12 @@
 fragment webformElementTextField on WebformElementTextfield {
   __typename
-  key
-  type
-  title
-  description
-  required {
-    message
+  metadata {
+    key
+    type
+    title
+    description
+    required
+    requiredError
   }
   readonly
   size
diff --git a/tests/queries/unexposed.gql b/tests/queries/unexposed.gql
index 2cb036c..3905228 100644
--- a/tests/queries/unexposed.gql
+++ b/tests/queries/unexposed.gql
@@ -1,8 +1,11 @@
 fragment webformElement on WebformElementUnexposed {
   __typename
-  key
-  type
-  title
+  metadata {
+    __typename
+    key
+    type
+    title
+  }
 }
 
 fragment webform on Webform {
@@ -17,3 +20,4 @@ query webform($id: String!) {
     ...webform
   }
 }
+
diff --git a/tests/src/Kernel/Element/ActionsTest.php b/tests/src/Kernel/Element/ActionsTest.php
index 9b8f54c..7941bf5 100644
--- a/tests/src/Kernel/Element/ActionsTest.php
+++ b/tests/src/Kernel/Element/ActionsTest.php
@@ -26,9 +26,12 @@ class ActionsTest extends GraphQLWebformKernelTestBase {
           [
             '__typename' => 'WebformElementWebformActions',
             'submitLabel' => 'Set sail for adventure',
-            'key' => 'actions',
-            'type' => 'webform_actions',
-            'title' => 'Submit button(s)',
+            'metadata' => [
+              'key' => 'actions',
+              'type' => 'webform_actions',
+              'title' => 'Submit button(s)',
+              '__typename' => 'WebformElementMetadata',
+            ],
           ],
         ],
       ],
diff --git a/tests/src/Kernel/Element/CheckboxesTest.php b/tests/src/Kernel/Element/CheckboxesTest.php
index 9b5e2f1..c11fa0e 100644
--- a/tests/src/Kernel/Element/CheckboxesTest.php
+++ b/tests/src/Kernel/Element/CheckboxesTest.php
@@ -36,9 +36,11 @@ class CheckboxesTest extends GraphQLWebformKernelTestBase {
                 'description' => 'The outer moon of Mars.',
               ],
             ],
-            'key' => 'checkboxes',
-            'title' => 'Checkboxes',
-            'description' => 'Choose your moons.',
+            'metadata' => [
+              'key' => 'checkboxes',
+              'title' => 'Checkboxes',
+              'description' => 'Choose your moons.',
+            ],
           ],
         ],
       ],
diff --git a/tests/src/Kernel/Element/FlexboxTest.php b/tests/src/Kernel/Element/FlexboxTest.php
index c98cb86..a007ba1 100644
--- a/tests/src/Kernel/Element/FlexboxTest.php
+++ b/tests/src/Kernel/Element/FlexboxTest.php
@@ -27,14 +27,20 @@ class FlexboxTest extends GraphQLWebformKernelTestBase {
             'alignItems' => 'center',
             'elements' => [
               0 => [
-                'key' => 'checkbox',
+                'metadata' => [
+                  'key' => 'checkbox',
+                ],
               ],
               1 => [
-                'key' => 'time',
+                'metadata' => [
+                  'key' => 'time',
+                ],
               ],
             ],
-            'key' => 'flexbox',
-            'type' => 'webform_flexbox',
+            'metadata' => [
+              'key' => 'flexbox',
+              'type' => 'webform_flexbox',
+            ],
           ],
         ],
       ],
diff --git a/tests/src/Kernel/Element/ManagedFileTest.php b/tests/src/Kernel/Element/ManagedFileTest.php
index 3d970b8..791bb68 100644
--- a/tests/src/Kernel/Element/ManagedFileTest.php
+++ b/tests/src/Kernel/Element/ManagedFileTest.php
@@ -36,19 +36,25 @@ class ManagedFileTest extends GraphQLWebformKernelTestBase {
             '__typename' => 'WebformElementManagedFile',
             'maxFilesize' => $expectedFileLimit,
             'fileExtensions' => 'gif jpg png txt',
-            'key' => 'file_upload',
-            'type' => 'managed_file',
-            'title' => 'File upload',
-            'description' => "Description<br />Unlimited number of files can be uploaded to this field.<br />$human_readable_file_limit limit.<br />Allowed types: gif jpg png txt.\n",
+            'metadata' => [
+              '__typename' => 'WebformElementMetadata',
+              'key' => 'file_upload',
+              'type' => 'managed_file',
+              'title' => 'File upload',
+              'description' => "Description<br />Unlimited number of files can be uploaded to this field.<br />$human_readable_file_limit limit.<br />Allowed types: gif jpg png txt.\n",
+            ],
           ],
           11 => [
             '__typename' => 'WebformElementWebformAudioFile',
             'maxFilesize' => $expectedAudioFileLimit,
             'fileExtensions' => 'mp3 ogg wav',
-            'key' => 'audio_files',
-            'type' => 'webform_audio_file',
-            'title' => 'Audio files',
-            'description' => "Unlimited number of files can be uploaded to this field.<br />$human_readable_audio_file_limit limit.<br />Allowed types: mp3 ogg wav.\n",
+            'metadata' => [
+              '__typename' => 'WebformElementMetadata',
+              'key' => 'audio_files',
+              'type' => 'webform_audio_file',
+              'title' => 'Audio files',
+              'description' => "Unlimited number of files can be uploaded to this field.<br />$human_readable_audio_file_limit limit.<br />Allowed types: mp3 ogg wav.\n",
+            ],
           ],
         ],
       ],
diff --git a/tests/src/Kernel/Element/MarkupTest.php b/tests/src/Kernel/Element/MarkupTest.php
index 77ec7ac..f3910fc 100644
--- a/tests/src/Kernel/Element/MarkupTest.php
+++ b/tests/src/Kernel/Element/MarkupTest.php
@@ -56,6 +56,9 @@ class MarkupTest extends GraphQLWebformKernelTestBase {
         'elements' => [
           5 => [
             '__typename' => 'WebformElementWebformMarkup',
+            'metadata' => [
+              'key' => 'markup',
+            ],
             'markup' => '<strong>Markup</strong>',
             'displayOn' => 'DISPLAY_ON_FORM',
           ],
diff --git a/tests/src/Kernel/Element/MultipleValuesTest.php b/tests/src/Kernel/Element/MultipleValuesTest.php
index 1e550b8..64c41a2 100644
--- a/tests/src/Kernel/Element/MultipleValuesTest.php
+++ b/tests/src/Kernel/Element/MultipleValuesTest.php
@@ -22,9 +22,9 @@ class MultipleValuesTest extends GraphQLWebformKernelTestBase {
       'form' => [
         'title' => 'GraphQL Webform test form',
         'elements' => [
-          0 => ['multipleValues' => NULL],
+          0 => ['multiple' => NULL],
           1 => [
-            'multipleValues' => [
+            'multiple' => [
               'limit' => 2,
               'message' => NULL,
               'headerLabel' => '',
@@ -44,7 +44,7 @@ class MultipleValuesTest extends GraphQLWebformKernelTestBase {
             ],
           ],
           2 => [
-            'multipleValues' => [
+            'multiple' => [
               'limit' => -1,
               'message' => "Please don't check more than @count options.",
               'headerLabel' => NULL,
@@ -63,9 +63,9 @@ class MultipleValuesTest extends GraphQLWebformKernelTestBase {
               'remove' => NULL,
             ],
           ],
-          4 => ['multipleValues' => NULL],
+          4 => ['multiple' => NULL],
           6 => [
-            'multipleValues' => [
+            'multiple' => [
               'limit' => -1,
               'message' => NULL,
               'headerLabel' => NULL,
@@ -84,9 +84,9 @@ class MultipleValuesTest extends GraphQLWebformKernelTestBase {
               'remove' => NULL,
             ],
           ],
-          8 => ['multipleValues' => NULL],
+          8 => ['multiple' => NULL],
           11 => [
-            'multipleValues' => [
+            'multiple' => [
               'limit' => -1,
               'message' => NULL,
               'headerLabel' => NULL,
@@ -105,9 +105,9 @@ class MultipleValuesTest extends GraphQLWebformKernelTestBase {
               'remove' => NULL,
             ],
           ],
-          12 => ['multipleValues' => NULL],
+          12 => ['multiple' => NULL],
           13 => [
-            'multipleValues' => [
+            'multiple' => [
               'limit' => 6,
               'message' => NULL,
               'headerLabel' => 'At least two years',
diff --git a/tests/src/Kernel/Element/RadiosTest.php b/tests/src/Kernel/Element/RadiosTest.php
index daeb37b..88f101b 100644
--- a/tests/src/Kernel/Element/RadiosTest.php
+++ b/tests/src/Kernel/Element/RadiosTest.php
@@ -38,11 +38,14 @@ class RadiosTest extends GraphQLWebformKernelTestBase {
                 'description' => 'Broadcasts from Peru since 1964',
               ],
             ],
-            'key' => 'radios',
-            'type' => 'radios',
-            'title' => 'Radios',
-            'description' => 'Choose your favorite station.',
-            'required' => NULL,
+            'metadata' => [
+              'key' => 'radios',
+              'type' => 'radios',
+              'title' => 'Radios',
+              'description' => 'Choose your favorite station.',
+              'required' => FALSE,
+              'requiredError' => NULL,
+            ],
           ],
         ],
       ],
diff --git a/tests/src/Kernel/Element/SelectTest.php b/tests/src/Kernel/Element/SelectTest.php
index 483cd68..6eafa02 100644
--- a/tests/src/Kernel/Element/SelectTest.php
+++ b/tests/src/Kernel/Element/SelectTest.php
@@ -24,9 +24,11 @@ class SelectTest extends GraphQLWebformKernelTestBase {
         'elements' => [
           8 => [
             '__typename' => 'WebformElementSelect',
-            'key' => 'select',
-            'title' => 'Select',
-            'description' => 'Choose wisely.',
+            'metadata' => [
+              'key' => 'select',
+              'title' => 'Select',
+              'description' => 'Choose wisely.',
+            ],
             'options' => [
               0 => [
                 'title' => 'Option 1',
@@ -47,9 +49,11 @@ class SelectTest extends GraphQLWebformKernelTestBase {
           ],
           12 => [
             '__typename' => 'WebformElementSelect',
-            'key' => 'select_with_custom_empty_option',
-            'title' => 'Select with custom empty option',
-            'description' => NULL,
+            'metadata' => [
+              'key' => 'select_with_custom_empty_option',
+              'title' => 'Select with custom empty option',
+              'description' => NULL,
+            ],
             'options' => [
               0 => [
                 'title' => 'Vegetarian',
diff --git a/tests/src/Kernel/Element/TermSelectTest.php b/tests/src/Kernel/Element/TermSelectTest.php
index 6007739..523687e 100644
--- a/tests/src/Kernel/Element/TermSelectTest.php
+++ b/tests/src/Kernel/Element/TermSelectTest.php
@@ -87,11 +87,13 @@ class TermSelectTest extends GraphQLWebformKernelTestBase {
         'elements' => [
           9 => [
             '__typename' => 'WebformElementWebformTermSelect',
-            'key' => 'term_select',
-            'type' => 'webform_term_select',
-            'title' => 'Term select',
-            'description' => 'Select one or two tags.',
-            'multiple' => 2,
+            'metadata' => [
+              'key' => 'term_select',
+              'type' => 'webform_term_select',
+              'title' => 'Term select',
+              'description' => 'Select one or two tags.',
+              'multiple' => 2,
+            ],
             'options' => $expected_term_options,
           ],
         ],
diff --git a/tests/src/Kernel/Element/TextAreaTest.php b/tests/src/Kernel/Element/TextAreaTest.php
index 8ac4803..9a72d54 100644
--- a/tests/src/Kernel/Element/TextAreaTest.php
+++ b/tests/src/Kernel/Element/TextAreaTest.php
@@ -24,11 +24,14 @@ class TextAreaTest extends GraphQLWebformKernelTestBase {
         'elements' => [
           4 => [
             '__typename' => 'WebformElementTextarea',
-            'key' => 'textarea',
-            'type' => 'textarea',
-            'title' => 'Textarea',
-            'description' => 'Tell us a bit more about yourself.',
-            'required' => NULL,
+            'metadata' => [
+              'key' => 'textarea',
+              'type' => 'textarea',
+              'title' => 'Textarea',
+              'description' => 'Tell us a bit more about yourself.',
+              'required' => FALSE,
+              'requiredError' => NULL,
+            ],
             'readonly' => FALSE,
             'size' => 100,
             'minlength' => 20,
diff --git a/tests/src/Kernel/Element/TextFieldTest.php b/tests/src/Kernel/Element/TextFieldTest.php
index c7d6466..f7ed0d8 100644
--- a/tests/src/Kernel/Element/TextFieldTest.php
+++ b/tests/src/Kernel/Element/TextFieldTest.php
@@ -24,12 +24,13 @@ class TextFieldTest extends GraphQLWebformKernelTestBase {
         'elements' => [
           0 => [
             '__typename' => 'WebformElementTextfield',
-            'key' => 'required_text_field',
-            'type' => 'textfield',
-            'title' => 'Required text field',
-            'description' => 'The description of the required text field.',
-            'required' => [
-              'message' => 'This field is required because it is important.',
+            'metadata' => [
+              'key' => 'required_text_field',
+              'type' => 'textfield',
+              'title' => 'Required text field',
+              'description' => 'The description of the required text field.',
+              'required' => TRUE,
+              'requiredError' => 'This field is required because it is important.',
             ],
             'readonly' => FALSE,
             'size' => 10,
@@ -45,11 +46,14 @@ class TextFieldTest extends GraphQLWebformKernelTestBase {
           ],
           1 => [
             '__typename' => 'WebformElementTextfield',
-            'key' => 'optional_text_field',
-            'type' => 'textfield',
-            'title' => 'Optional text field',
-            'description' => NULL,
-            'required' => NULL,
+            'metadata' => [
+              'key' => 'optional_text_field',
+              'type' => 'textfield',
+              'title' => 'Optional text field',
+              'description' => NULL,
+              'required' => FALSE,
+              'requiredError' => NULL,
+            ],
             'readonly' => FALSE,
             'size' => 60,
             'minlength' => NULL,
@@ -64,11 +68,14 @@ class TextFieldTest extends GraphQLWebformKernelTestBase {
           ],
           13 => [
             '__typename' => 'WebformElementTextfield',
-            'key' => '2_years',
-            'type' => 'textfield',
-            'title' => 'Minimum 2 years, maximum 6',
-            'description' => '',
-            'required' => NULL,
+            'metadata' => [
+              'key' => '2_years',
+              'type' => 'textfield',
+              'title' => 'Minimum 2 years, maximum 6',
+              'description' => '',
+              'required' => FALSE,
+              'requiredError' => '',
+            ],
             'readonly' => FALSE,
             'size' => 60,
             'minlength' => NULL,
diff --git a/tests/src/Kernel/Element/UnexposedElementTest.php b/tests/src/Kernel/Element/UnexposedElementTest.php
index a19d153..ea2427c 100644
--- a/tests/src/Kernel/Element/UnexposedElementTest.php
+++ b/tests/src/Kernel/Element/UnexposedElementTest.php
@@ -27,9 +27,12 @@ class UnexposedElementTest extends GraphQLWebformKernelTestBase {
         'elements' => [
           3 => [
             '__typename' => 'WebformElementUnexposed',
-            'key' => 'unsupported_field',
-            'type' => 'webform_element',
-            'title' => 'Unsupported field',
+            'metadata' => [
+              'key' => 'unsupported_field',
+              'type' => 'webform_element',
+              'title' => 'Unsupported field',
+              '__typename' => 'WebformElementMetadata',
+            ],
           ],
         ],
       ],
-- 
GitLab


From 4859d747711082247cba400ea089ffcc84286b9b Mon Sep 17 00:00:00 2001
From: Pieter Frenssen <pieter@frenssen.be>
Date: Mon, 10 Feb 2025 16:13:34 +0200
Subject: [PATCH 2/3] Re-introduce the metadata element.

---
 .../SchemaExtension/WebformExtension.php      |  6 ++---
 src/WebformSchemaBuilder.php                  | 23 +++++++++----------
 tests/queries/fieldset.gql                    | 10 +++++---
 tests/queries/markup.gql                      |  8 ++++---
 tests/queries/multiple.gql                    |  2 +-
 tests/queries/radios.gql                      |  6 +++--
 tests/queries/required.gql                    |  6 +++--
 tests/queries/textarea.gql                    |  5 ++--
 tests/queries/textfield.gql                   |  5 ++--
 tests/queries/unexposed.gql                   |  1 -
 tests/src/Kernel/Element/FieldsetTest.php     | 12 ++++++----
 tests/src/Kernel/Element/MarkupTest.php       |  3 +++
 .../src/Kernel/Element/MultipleValuesTest.php | 21 +----------------
 tests/src/Kernel/Element/RadiosTest.php       |  3 +--
 .../Kernel/Element/RequiredElementTest.php    |  8 ++++---
 tests/src/Kernel/Element/TextAreaTest.php     |  3 +--
 tests/src/Kernel/Element/TextFieldTest.php    | 11 ++++-----
 17 files changed, 64 insertions(+), 69 deletions(-)

diff --git a/src/Plugin/GraphQL/SchemaExtension/WebformExtension.php b/src/Plugin/GraphQL/SchemaExtension/WebformExtension.php
index 484ce58..ce852f3 100644
--- a/src/Plugin/GraphQL/SchemaExtension/WebformExtension.php
+++ b/src/Plugin/GraphQL/SchemaExtension/WebformExtension.php
@@ -169,8 +169,6 @@ class WebformExtension extends SdlSchemaExtensionPluginBase {
         'title' => 'string',
         'description' => 'string',
         'multiple' => 'int',
-        'required' => 'boolean',
-        'requiredError' => 'string',
       ],
       'WebformElementMarkupBase' => [
         'markup' => 'string',
@@ -202,7 +200,7 @@ class WebformExtension extends SdlSchemaExtensionPluginBase {
     }
 
     // Expose information in case the field is required.
-    $registry->addFieldResolver('WebformElement', 'required', $builder->callback(
+    $registry->addFieldResolver('WebformElementMetadata', 'required', $builder->callback(
       fn (array $value): ?array => $value['#required'] ? $value : NULL
     ));
 
@@ -221,7 +219,7 @@ class WebformExtension extends SdlSchemaExtensionPluginBase {
     );
 
     // Expose information about elements that accept multiple values.
-    $registry->addFieldResolver('WebformElementMultipleValuesBase', 'multiple', $builder
+    $registry->addFieldResolver('WebformElementMultipleValuesBase', 'multipleValues', $builder
       ->produce('webform_element_multiple_values')
       ->map('element', $builder->fromParent())
     );
diff --git a/src/WebformSchemaBuilder.php b/src/WebformSchemaBuilder.php
index 5499379..20d278a 100644
--- a/src/WebformSchemaBuilder.php
+++ b/src/WebformSchemaBuilder.php
@@ -46,6 +46,14 @@ class WebformSchemaBuilder {
   public function __construct() {
     $this->types = [];
 
+    $this->types['WebformRequiredElement'] = new ObjectType([
+      'name' => 'WebformRequiredElement',
+      'description' => 'Indicates that the Webform element is required.',
+      'fields' => [
+        'message' => $this->type(Type::string(), 'The error message to display when the element is required but empty.'),
+      ],
+    ]);
+
     $this->types['WebformElementMetadata'] = new ObjectType([
       'name' => 'WebformElementMetadata',
       'fields' => [
@@ -54,15 +62,7 @@ class WebformSchemaBuilder {
         'title' => $this->type(Type::string(), ''),
         'description' => $this->type(Type::string(), ''),
         'multiple' => $this->type(Type::int(), 'The number of values that can be entered into the element. Unlimited if 0.'),
-        'required' => $this->type(Type::boolean(), 'Whether or not input is required on the element. It might be more convenient to use WebformRequiredElement.'),
-        'requiredError' => $this->type(Type::string(), 'The error message to show when required input is missing. It might be more convenient to use WebformRequiredElement.'),
-      ],
-    ]);
-    $this->types['WebformRequiredElement'] = new ObjectType([
-      'name' => 'WebformRequiredElement',
-      'description' => 'Indicates that the Webform element is required.',
-      'fields' => [
-        'message' => $this->type(Type::string(), 'The error message to display when the element is required but empty.'),
+        'required' => $this->types['WebformRequiredElement'],
       ],
     ]);
 
@@ -144,7 +144,7 @@ class WebformSchemaBuilder {
     $this->types['WebformElementMultipleValuesBase'] = new InterfaceType([
       'name' => 'WebformElementMultipleValuesBase',
       'fields' => [
-        'multiple' => $this->types['WebformElementMultipleValues'],
+        'multipleValues' => $this->types['WebformElementMultipleValues'],
       ],
     ]);
 
@@ -241,7 +241,7 @@ class WebformSchemaBuilder {
       $interfaces[] = fn () => $this->types['WebformElementMultipleValuesBase'];
       $fields = [
         ...$fields,
-        'multiple' => fn () => $this->types['WebformElementMultipleValues'],
+        'multipleValues' => fn () => $this->types['WebformElementMultipleValues'],
       ];
     }
 
@@ -328,7 +328,6 @@ class WebformSchemaBuilder {
   protected function getElementDefinition(): array {
     return [
       'metadata' => fn () => $this->types['WebformElementMetadata'],
-      'required' => $this->types['WebformRequiredElement'],
     ];
   }
 
diff --git a/tests/queries/fieldset.gql b/tests/queries/fieldset.gql
index a6b0f5d..e25f9d2 100644
--- a/tests/queries/fieldset.gql
+++ b/tests/queries/fieldset.gql
@@ -1,11 +1,15 @@
 fragment fieldsets on WebformElementFieldset {
   __typename
-  key
-  type
-  elements {
+  metadata {
     key
     type
   }
+  elements {
+    metadata {
+      key
+      type
+    }
+  }
 }
 
 query webform($id: String!) {
diff --git a/tests/queries/markup.gql b/tests/queries/markup.gql
index 4055990..670f472 100644
--- a/tests/queries/markup.gql
+++ b/tests/queries/markup.gql
@@ -1,10 +1,12 @@
 fragment webformElementMarkup on WebformElementMarkupBase {
   __typename
-  metadata {
-    key
-  }
   markup
   displayOn
+  ... on WebformElement {
+    metadata {
+      key
+    }
+  }
 }
 
 fragment webformElement on WebformElement {
diff --git a/tests/queries/multiple.gql b/tests/queries/multiple.gql
index 407452e..cb3cc4e 100644
--- a/tests/queries/multiple.gql
+++ b/tests/queries/multiple.gql
@@ -18,7 +18,7 @@ fragment multiple on WebformElementMultipleValues {
 }
 
 fragment element on WebformElementMultipleValuesBase {
-  multiple {
+  multipleValues {
     ...multiple
   }
 }
diff --git a/tests/queries/radios.gql b/tests/queries/radios.gql
index 8db0f22..cfda96e 100644
--- a/tests/queries/radios.gql
+++ b/tests/queries/radios.gql
@@ -12,8 +12,10 @@ fragment webformElementRadios on WebformElementRadios {
     type
     title
     description
-    required
-    requiredError
+    required {
+      __typename
+      message
+    }
   }
   options {
     ...webformElementOption
diff --git a/tests/queries/required.gql b/tests/queries/required.gql
index eb1ea4e..36b6bec 100644
--- a/tests/queries/required.gql
+++ b/tests/queries/required.gql
@@ -6,8 +6,10 @@ query webform($id: String!) {
   form: webformById(id: $id) {
     title
     elements {
-      required {
-        ...required
+      metadata {
+        required {
+          ...required
+        }
       }
     }
   }
diff --git a/tests/queries/textarea.gql b/tests/queries/textarea.gql
index 6aa6e62..8947980 100644
--- a/tests/queries/textarea.gql
+++ b/tests/queries/textarea.gql
@@ -11,8 +11,9 @@ fragment webformElementTextarea on WebformElementTextarea {
     type
     title
     description
-    required
-    requiredError
+    required {
+      message
+    }
   }
   readonly
   size
diff --git a/tests/queries/textfield.gql b/tests/queries/textfield.gql
index 4b7bc02..ee6174c 100644
--- a/tests/queries/textfield.gql
+++ b/tests/queries/textfield.gql
@@ -5,8 +5,9 @@ fragment webformElementTextField on WebformElementTextfield {
     type
     title
     description
-    required
-    requiredError
+    required {
+      message
+    }
   }
   readonly
   size
diff --git a/tests/queries/unexposed.gql b/tests/queries/unexposed.gql
index 3905228..4ba1080 100644
--- a/tests/queries/unexposed.gql
+++ b/tests/queries/unexposed.gql
@@ -20,4 +20,3 @@ query webform($id: String!) {
     ...webform
   }
 }
-
diff --git a/tests/src/Kernel/Element/FieldsetTest.php b/tests/src/Kernel/Element/FieldsetTest.php
index 49de52c..c0a8ee8 100644
--- a/tests/src/Kernel/Element/FieldsetTest.php
+++ b/tests/src/Kernel/Element/FieldsetTest.php
@@ -26,12 +26,16 @@ class FieldsetTest extends GraphQLWebformKernelTestBase {
             '__typename' => 'WebformElementFieldset',
             'elements' => [
               0 => [
-                'key' => 'checkbox2',
-                'type' => 'checkbox',
+                'metadata' => [
+                  'key' => 'checkbox2',
+                  'type' => 'checkbox',
+                ],
               ],
             ],
-            'key' => 'fieldset',
-            'type' => 'fieldset',
+            'metadata' => [
+              'key' => 'fieldset',
+              'type' => 'fieldset',
+            ],
           ],
         ],
       ],
diff --git a/tests/src/Kernel/Element/MarkupTest.php b/tests/src/Kernel/Element/MarkupTest.php
index 491c9fa..c80fc6c 100644
--- a/tests/src/Kernel/Element/MarkupTest.php
+++ b/tests/src/Kernel/Element/MarkupTest.php
@@ -64,6 +64,9 @@ class MarkupTest extends GraphQLWebformKernelTestBase {
           ],
           14 => [
             '__typename' => 'WebformElementProcessedText',
+            'metadata' => [
+              'key' => 'processed_text',
+            ],
             // The '<em>' tag should be stripped out.
             'markup' => '<p><strong>Processed text</strong></p>',
             'displayOn' => 'DISPLAY_ON_BOTH',
diff --git a/tests/src/Kernel/Element/MultipleValuesTest.php b/tests/src/Kernel/Element/MultipleValuesTest.php
index dd8a8cd..2e55da6 100644
--- a/tests/src/Kernel/Element/MultipleValuesTest.php
+++ b/tests/src/Kernel/Element/MultipleValuesTest.php
@@ -64,26 +64,7 @@ class MultipleValuesTest extends GraphQLWebformKernelTestBase {
             ],
           ],
           4 => ['multipleValues' => NULL],
-          6 => [
-            'multipleValues' => [
-              'limit' => -1,
-              'message' => NULL,
-              'headerLabel' => NULL,
-              'minItems' => NULL,
-              'emptyItems' => NULL,
-              'addMore' => NULL,
-              'addMoreItems' => NULL,
-              'addMoreButtonLabel' => NULL,
-              'addMoreInput' => NULL,
-              'addMoreInputLabel' => NULL,
-              'itemLabel' => NULL,
-              'noItemsMessage' => NULL,
-              'sorting' => NULL,
-              'operations' => NULL,
-              'add' => NULL,
-              'remove' => NULL,
-            ],
-          ],
+          6 => ['multipleValues' => NULL],
           8 => ['multipleValues' => NULL],
           11 => [
             'multipleValues' => [
diff --git a/tests/src/Kernel/Element/RadiosTest.php b/tests/src/Kernel/Element/RadiosTest.php
index 88f101b..4e21231 100644
--- a/tests/src/Kernel/Element/RadiosTest.php
+++ b/tests/src/Kernel/Element/RadiosTest.php
@@ -43,8 +43,7 @@ class RadiosTest extends GraphQLWebformKernelTestBase {
               'type' => 'radios',
               'title' => 'Radios',
               'description' => 'Choose your favorite station.',
-              'required' => FALSE,
-              'requiredError' => NULL,
+              'required' => NULL,
             ],
           ],
         ],
diff --git a/tests/src/Kernel/Element/RequiredElementTest.php b/tests/src/Kernel/Element/RequiredElementTest.php
index 3010ff7..1a7d5fd 100644
--- a/tests/src/Kernel/Element/RequiredElementTest.php
+++ b/tests/src/Kernel/Element/RequiredElementTest.php
@@ -24,8 +24,10 @@ class RequiredElementTest extends GraphQLWebformKernelTestBase {
         'title' => 'GraphQL Webform test form',
         'elements' => [
           0 => [
-            'required' => [
-              'message' => 'This field is required because it is important.',
+            'metadata' => [
+              'required' => [
+                'message' => 'This field is required because it is important.',
+              ],
             ],
           ],
         ],
@@ -43,7 +45,7 @@ class RequiredElementTest extends GraphQLWebformKernelTestBase {
     // fields are added or removed from the form.
     if (!empty($data['data']['form']['elements'])) {
       $elements = &$data['data']['form']['elements'];
-      $elements = array_filter($elements, fn ($value) => !empty($value['required']));
+      $elements = array_filter($elements, fn ($value) => !empty($value['metadata']['required']));
     }
 
     $this->assertArrayHasKey('data', $data, 'No result data.');
diff --git a/tests/src/Kernel/Element/TextAreaTest.php b/tests/src/Kernel/Element/TextAreaTest.php
index 9a72d54..eaca006 100644
--- a/tests/src/Kernel/Element/TextAreaTest.php
+++ b/tests/src/Kernel/Element/TextAreaTest.php
@@ -29,8 +29,7 @@ class TextAreaTest extends GraphQLWebformKernelTestBase {
               'type' => 'textarea',
               'title' => 'Textarea',
               'description' => 'Tell us a bit more about yourself.',
-              'required' => FALSE,
-              'requiredError' => NULL,
+              'required' => NULL,
             ],
             'readonly' => FALSE,
             'size' => 100,
diff --git a/tests/src/Kernel/Element/TextFieldTest.php b/tests/src/Kernel/Element/TextFieldTest.php
index f7ed0d8..413b6d8 100644
--- a/tests/src/Kernel/Element/TextFieldTest.php
+++ b/tests/src/Kernel/Element/TextFieldTest.php
@@ -29,8 +29,9 @@ class TextFieldTest extends GraphQLWebformKernelTestBase {
               'type' => 'textfield',
               'title' => 'Required text field',
               'description' => 'The description of the required text field.',
-              'required' => TRUE,
-              'requiredError' => 'This field is required because it is important.',
+              'required' => [
+                'message' => 'This field is required because it is important.',
+              ]
             ],
             'readonly' => FALSE,
             'size' => 10,
@@ -51,8 +52,7 @@ class TextFieldTest extends GraphQLWebformKernelTestBase {
               'type' => 'textfield',
               'title' => 'Optional text field',
               'description' => NULL,
-              'required' => FALSE,
-              'requiredError' => NULL,
+              'required' => NULL,
             ],
             'readonly' => FALSE,
             'size' => 60,
@@ -73,8 +73,7 @@ class TextFieldTest extends GraphQLWebformKernelTestBase {
               'type' => 'textfield',
               'title' => 'Minimum 2 years, maximum 6',
               'description' => '',
-              'required' => FALSE,
-              'requiredError' => '',
+              'required' => NULL,
             ],
             'readonly' => FALSE,
             'size' => 60,
-- 
GitLab


From d4c8e6f290f80dd2a5a99f3b8b8ac1b5c164705b Mon Sep 17 00:00:00 2001
From: Pieter Frenssen <pieter@frenssen.be>
Date: Mon, 10 Feb 2025 16:36:03 +0200
Subject: [PATCH 3/3] Adhere to coding standards.

---
 tests/src/Kernel/Element/TextFieldTest.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/src/Kernel/Element/TextFieldTest.php b/tests/src/Kernel/Element/TextFieldTest.php
index 413b6d8..8d57317 100644
--- a/tests/src/Kernel/Element/TextFieldTest.php
+++ b/tests/src/Kernel/Element/TextFieldTest.php
@@ -31,7 +31,7 @@ class TextFieldTest extends GraphQLWebformKernelTestBase {
               'description' => 'The description of the required text field.',
               'required' => [
                 'message' => 'This field is required because it is important.',
-              ]
+              ],
             ],
             'readonly' => FALSE,
             'size' => 10,
-- 
GitLab