WordPress wp-signup headaches, and refactoring.

I've been modifying the wp-signup script a lot, and figured out a better pattern for doing these screens. This technique works more like "views and controllers", so it's one step closer to MVC.

WP doesn't have routes, but the wp-signup script has a paramter named "stage" that specifies the next state. It's effectively a route.

There are two types of stages: showing a form, or validating a form.

When you validate a form, you see if there are errors. If there are, you show the form, with error messages. If there are no errors, you commit the changes, and then show the next form.

If this were a traditional controller in a web app, you would show a form if the request was an HTTP GET, and validate if it was an HTTP POST.

So, here's some pseudocode. It shows a form, and if it validates, then we show the next form.

switch $stage {
  case 'show-form':
  case 'validate-form':
    $context = $_POST;
    list($results, $error) = validate_form( $context );
    if ($error) {
      show_form($results, $error);
    } else {

The only "magic" in here is the validate_form(), which validates the input. If validation fails, the function returns an error value along with the original context, possibly tweaked to fix problems.

Current Practice

The existing wp-signup.php validate_form-style validation functions return values. Instead, they will call the form-showing functions themselves. They also register users and send mail.

The problem with that is unit testing - you can't do it if the functions are either returning false, or displaying some HTML code to the page.

The fix

So my fix is to alter the validation functions so they mainly prepare input into the built-in validation functions (like wpmu_validate_user_signup()), and then use the return values to make a new context that works for our forms.

Another fix is to use a single array to hold all parameters. This allows for creating larger lists of values, so data can be moved between more forms (or in sessions).

Now, in theory, the validation states are testable.

Moreover, the sequence of screens is more visible and modifiable within wp-signup.php file.

I'm thinking there are some more bits of info that should be moved out of the forms and validators - nonces, for one. Another is the form data itself - if parts are going to be held in sessions, the session variables should be defined at this control layer, not within the functions.


The nice thing about the above logic is that it's simple. You don't really need to test it.

The validation classes are a little more complex, but the real complexity is in the built-in validation functions. By separating control logic from the validation logic, you can now test the validations separate from their sequence in the process.