Problem/Motivation
When forward navigation is enabled, the final submit calls WebformNavigationHelper::validateAllPages() (WebformNavigationHandler::validateForm(), line 188 in 2.0.5). For each accessible wizard page it calls validateSubmission(), which creates a new webform_submission form object and runs FormBuilder::submitForm() (src/WebformNavigationHelper.php:398-428 and :443-477).
Each iteration is therefore a full form build: retrieve, every hook_form_alter() / hook_webform_submission_form_alter(), every handler alterForm(), element processing, then validation. On a webform with N pages, the final submit builds the complete form N + 1 times.
Cost grows with pages × elements × site alters. On a 12-page webform with ~840 elements (~340 #states, many composites), final submits took 100–200 s in production, while ordinary page steps on the same form took ~20 s.
The loop also calls logPageVisit() for every page (:410). That is a SELECT plus a possible INSERT per page, and it records pages as visited that the user never opened.
Steps to reproduce
- Create a webform with many wizard pages and elements. Add the Webform Navigation handler with forward navigation enabled.
- Add a
hook_form_alter()that logs each call. - Fill in the form and click Submit on the last page.
- Observe the alter running once per page, plus the normal build and rebuild.
Proposed resolution
Validate the whole submission with a single form build instead of one build per page. Options:
- A. Build once with an operation that renders every page together (e.g.
edit_all), collect the errors, and map each error to its page with the existinggetElementPage(). Needs evaluation:edit_allmust respect the same element access and#statesas the regular wizard, and must not expose admin-only elements. - B. Keep per-page validation but skip pages that have been visited and have no logged errors since the last save, so only unknown or failing pages are rebuilt.
In either case, stop logging page visits during validation. A page should only count as visited when the user actually views it.
Remaining tasks
- Choose an approach, then write an MR.
- Add a test that the per-page errors are the same as before for a multi-page form with conditional pages.
- Add a test that alters run a bounded number of times on final submit.
User interface changes
None intended. Error messages and per-page error lists should stay the same.
API changes
validateAllPages() keeps its signature. validateSubmission() is private and may change.
Data model changes
None. Fewer "page visited" rows get written, because visits are no longer logged during validation.
Issue fork webformnavigation-3632737
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
Comment #3
rymcveighThe MR is ready for testing.
Comment #4
rymcveighComment #5
shubhamgoel commentedHi @rymcveigh,
The MR looks fine to me. Thanks.
Comment #6
rymcveighComment #8
rymcveigh