Problem/Motivation

This is part 1 of splitting the large contribution in #3595219: 3.0 Exploration into reviewable pieces. It is the foundation the per-element issues build on, and should land first.

When the module resolves a built form's elements, it walks the render array produced by Webform and exposes each element's metadata, default value and options. Two correctness problems exist in 3.x today:

  • Cacheability is dropped. Element render arrays carry cache metadata (cache tags, contexts, and a max-age) — for example a default value computed from a token like [current-user:mail] is per-user and must not be cached across users, and option lists built from entities carry the entities' cache tags. The current resolvers read values out of the render array but never bubble its #cache metadata into the GraphQL response, so the response is over-cached and can leak one user's data to another.
  • Non-renderable and placeholder elements are exposed. Elements that Webform decides not to render on the form (access-denied, #access = FALSE, value/markup-only containers in some cases) are still walked and surface as meaningless entries. Related to this, an unavailable form (see #3595219: 3.0 Exploration's WebformForm work) can still produce stray element entries.

Steps to reproduce

  1. Add a textfield whose #default_value is [current-user:mail].
  2. Query the form's elements { ... defaultValue } as user A, then as user B.
  3. Expected: each user sees their own e-mail; the response is not cached across users (a user cache context is present).

    Actual: the token-derived default value is cached and the second user can be served the first user's value; the per-user cache context is missing from the response.

Proposed resolution

Make the element resolvers cacheability-aware and stop exposing elements Webform would not render:

  • Bubble the #cache metadata (tags, contexts, max-age) of every element render array into the GraphQL field context, so it is merged into the response's cache metadata — the same mechanism GraphQL already uses elsewhere. This includes honouring max-age (e.g. 0 for uncacheable elements) rather than only tags/contexts.
  • Resolve defaultValue through a dedicated webform_element_default_value data producer that renders the default value in a render context and captures the resulting cacheability, instead of reading a bare value. This is what makes token-derived and entity-derived defaults safe to cache. A read-only producer keeps the logic testable and reusable by the per-element issues.
  • Fix the cacheability leak from token resolution: tokens replaced while building element data must contribute their cache metadata (e.g. user context) to the response.
  • Exclude elements that are not meant to render on the form from the exposed element list, and make an unavailable form return no stray elements.

The kernel test base (GraphQLWebformKernelTestBase) gains assertion helpers for asserting the response's cache tags / contexts / max-age, so every per-element issue that follows can assert cacheability honestly.

Remaining tasks

  • Bubble element render-array cacheability (tags, contexts, max-age) in src/Plugin/GraphQL/DataProducer/WebformElements.php.
  • Add src/Plugin/GraphQL/DataProducer/WebformElementDefaultValue.php and route defaultValue through it.
  • Fix the token-resolution cacheability leak.
  • Exclude non-renderable elements in WebformElements.php / WebformElementMetadata.php; return no elements for an unavailable form.
  • Add cacheability assertion helpers to tests/src/Kernel/GraphQLWebformKernelTestBase.php.
  • Tests: DefaultValueTest, DefaultValueTokenCacheabilityTest, TokenPrefillCacheabilityTest, plus updated expectations for existing element/markup/title tests now that cache metadata is reported.

API changes

No schema shape changes. The cache metadata of responses changes: responses that were previously (incorrectly) cacheable now carry the correct cache contexts/tags/max-age — e.g. token-derived default values gain a user cache context. This is a correctness fix, not a field addition.

Release notes snippet

Element data (default values, options) now correctly propagates Drupal cache metadata into the GraphQL response, so per-user and entity-derived values are no longer over-cached, and elements that Webform does not render are no longer exposed as placeholder entries.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

pfrenssen created an issue. See original summary.

pfrenssen’s picture

Status: Active » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.