Skip to content

fix: preserve multi-step checkout account fields#1611

Merged
superdav42 merged 2 commits into
mainfrom
fix/checkout-step-session
Jul 8, 2026
Merged

fix: preserve multi-step checkout account fields#1611
superdav42 merged 2 commits into
mainfrom
fix/checkout-step-session

Conversation

@superdav42

@superdav42 superdav42 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Persist validated non-final checkout step values during the AJAX validation request.
  • Reuse the same persistence helper for the existing native multi-step POST path.
  • Add focused coverage for preserving email_address, username, password, and password_conf in the signup session.

Reproduction and verification

Created a local 2-step checkout form at http://wordpress.local:8080/aidevops-two-step-repro/:

  • Step 1: products, email, username, password
  • Step 2: site title, site URL, order summary, payment, submit

Before the fix:

  • Step 1 wu_validate_form AJAX returned success: true.
  • Step 2 wu_validate_form AJAX, without reposting step-1 account fields, returned required-field errors for email_address, username, and password.

After the fix:

  • The same two AJAX requests returned success: true on step 2.
  • Checkout created the customer using the email and username submitted on step 1.

Tests

  • php -l inc/checkout/class-checkout.php && php -l tests/WP_Ultimo/Checkout/Checkout_Test.php
  • vendor/bin/phpcs inc/checkout/class-checkout.php tests/WP_Ultimo/Checkout/Checkout_Test.php
  • vendor/bin/phpstan analyse inc/checkout/class-checkout.php tests/WP_Ultimo/Checkout/Checkout_Test.php --no-progress
  • vendor/bin/phpunit --filter test_persist_current_step_to_session_saves_account_fields
  • vendor/bin/phpunit --filter Checkout_Test

Notes:

  • PHPUnit passed with existing vendor/WordPress deprecation notices and 1 skipped test in Checkout_Test.
  • Local dev plugin symlink and CAPTCHA add-on were restored after the manual HTTP verification.

aidevops.sh v3.32.2 plugin for OpenCode v1.17.13

Summary by CodeRabbit

  • Bug Fixes
    • Checkout progress now saves the information you’ve already entered immediately after each validated step, helping prevent data loss when continuing.
    • Saved interim step data is handled consistently, with checkout control fields excluded to keep progress storage clean.
  • Tests
    • Added coverage to verify that only the expected user-entered fields are persisted, and improved checkout-related test setup/teardown to reduce cross-test interference.

@superdav42 superdav42 added the origin:interactive Created by interactive user session label Jul 8, 2026
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f251f2a5-c0d5-47aa-a59b-6d4361b25a90

📥 Commits

Reviewing files that changed from the base of the PR and between 9d2db79 and 60183bd.

📒 Files selected for processing (1)
  • tests/WP_Ultimo/Checkout/Checkout_Test.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/WP_Ultimo/Checkout/Checkout_Test.php

📝 Walkthrough

Walkthrough

This PR adds shared checkout-step session persistence, routes both AJAX and native submission paths through it, and expands checkout test coverage around the new helper and related test-state cleanup.

Changes

Checkout step session persistence

Layer / File(s) Summary
Session persistence helpers
inc/checkout/class-checkout.php
Adds get_current_step_session_values() to filter customer-entered POST fields and persist_current_step_to_session() to store them in the signup session with pre-flight mapped to pre_selected.
Submission flow wiring
inc/checkout/class-checkout.php
maybe_handle_order_submission() now persists validated step fields before the AJAX success response, and maybe_process_checkout() delegates its non-final-step session write to the new helper.
Checkout test updates
tests/WP_Ultimo/Checkout/Checkout_Test.php
Adds reflection-based coverage for session persistence and updates teardown plus a few unrelated assertions and comments in the checkout test file.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

Suggested labels: review-feedback-scanned, status:in-review

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: preserving multi-step checkout account fields.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/checkout-step-session

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
tests/WP_Ultimo/Checkout/Checkout_Test.php (1)

523-579: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Good coverage for the core persistence path.

Test correctly validates that account fields are persisted while control/nonce fields are excluded, matching get_current_step_session_values()'s filtering contract in inc/checkout/class-checkout.php.

One gap: the pre-flight branch of persist_current_step_to_session() (which stores values under pre_selected instead) isn't covered by any test. Given this is a distinct code path in the exact method under test, consider adding a follow-up case.

💡 Suggested additional test case
public function test_persist_current_step_to_session_handles_pre_flight(): void {

	$checkout   = Checkout::get_instance();
	$reflection = new \ReflectionClass($checkout);

	$this->ensure_session($checkout);

	$session_prop = $this->get_session_prop($reflection);
	$session      = $session_prop->getValue($checkout);

	$session->set('signup', []);

	$_POST['pre-flight']      = '1';
	$_POST['email_address']   = 'pre-flight@example.com';

	$method = $reflection->getMethod('persist_current_step_to_session');
	if (PHP_VERSION_ID < 80100) {
		$method->setAccessible(true);
	}

	$saved  = $method->invoke($checkout);
	$signup = $session->get('signup');

	$this->assertArrayNotHasKey('pre-flight', $saved);
	$this->assertSame('pre-flight@example.com', $signup['pre_selected']['email_address']);

	$session->set('signup', []);
	unset($_POST['pre-flight'], $_POST['email_address']);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/WP_Ultimo/Checkout/Checkout_Test.php` around lines 523 - 579, Add a
follow-up test for the pre-flight branch in persist_current_step_to_session(),
since the current test only covers the normal account path. Create a new case
around Checkout::persist_current_step_to_session that sets the pre-flight
request input, invokes the method via reflection like the existing test, and
asserts the returned data omits control fields while the session stores values
under signup['pre_selected'] rather than the regular account keys. Reuse the
same setup helpers and cleanup pattern from
test_persist_current_step_to_session_saves_account_fields().
inc/checkout/class-checkout.php (1)

3639-3655: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Apply input sanitization per coding guidelines.

get_current_step_session_values() returns raw $_POST values without sanitization. Per coding guidelines, input should be sanitized using wu_clean() or WordPress sanitization functions. Password fields (e.g., password, password_conf) should be excluded from sanitization to avoid altering credentials.

🛡️ Proposed sanitization wrapper
 protected function get_current_step_session_values() {

-	return array_filter(
-		$_POST, // phpcs:ignore WordPress.Security.NonceVerification.Missing
-		fn($key) => ! str_starts_with((string) $key, 'checkout_') && ! str_starts_with((string) $key, '_'),
-		ARRAY_FILTER_USE_KEY
-	);
+	$values = array_filter(
+		$_POST, // phpcs:ignore WordPress.Security.NonceVerification.Missing
+		fn($key) => ! str_starts_with((string) $key, 'checkout_') && ! str_starts_with((string) $key, '_'),
+		ARRAY_FILTER_USE_KEY
+	);
+
+	foreach ($values as $key => $value) {
+		if ( ! str_contains((string) $key, 'password')) {
+			$values[ $key ] = wu_clean($value);
+		}
+	}
+
+	return $values;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@inc/checkout/class-checkout.php` around lines 3639 - 3655,
`get_current_step_session_values()` is returning raw `$_POST` data without
sanitization. Update the method to sanitize each retained value before returning
it, using `wu_clean()` or an appropriate WordPress sanitization function, while
preserving the existing exclusion logic for checkout control/private nonce keys.
Make sure password-related fields such as `password` and `password_conf` are
left unsanitized so credentials are not altered, and keep the behavior localized
to `get_current_step_session_values()`.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@inc/checkout/class-checkout.php`:
- Around line 3639-3655: `get_current_step_session_values()` is returning raw
`$_POST` data without sanitization. Update the method to sanitize each retained
value before returning it, using `wu_clean()` or an appropriate WordPress
sanitization function, while preserving the existing exclusion logic for
checkout control/private nonce keys. Make sure password-related fields such as
`password` and `password_conf` are left unsanitized so credentials are not
altered, and keep the behavior localized to `get_current_step_session_values()`.

In `@tests/WP_Ultimo/Checkout/Checkout_Test.php`:
- Around line 523-579: Add a follow-up test for the pre-flight branch in
persist_current_step_to_session(), since the current test only covers the normal
account path. Create a new case around Checkout::persist_current_step_to_session
that sets the pre-flight request input, invokes the method via reflection like
the existing test, and asserts the returned data omits control fields while the
session stores values under signup['pre_selected'] rather than the regular
account keys. Reuse the same setup helpers and cleanup pattern from
test_persist_current_step_to_session_saves_account_fields().

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fc986c58-76b9-4b9c-acfc-93e86b5e4342

📥 Commits

Reviewing files that changed from the base of the PR and between b61f22a and 9d2db79.

📒 Files selected for processing (2)
  • inc/checkout/class-checkout.php
  • tests/WP_Ultimo/Checkout/Checkout_Test.php

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@superdav42 superdav42 merged commit 4cfccfd into main Jul 8, 2026
11 checks passed
@superdav42 superdav42 added the review-feedback-scanned Merged PR already scanned for quality feedback label Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

origin:interactive Created by interactive user session review-feedback-scanned Merged PR already scanned for quality feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant