Manual:SessionManager and AuthManager/Adding fields to the registration form

This is a simple (and somewhat silly) example showing how to use AuthManager to add extra fields to the registration form.

Step 1: define the fields with an authentication request object.

<?php

use MediaWiki\Auth\AuthenticationRequest;

class MyExtraFieldsAuthenticationRequest extends AuthenticationRequest {
    // Mark this AuthenticationRequest as optional.
    public $required = self::OPTIONAL;

    /** @var string */
    public $eyeColor;

    /** @var string */
    public $favoriteFood;

    public function getFieldInfo() {
        return [
            'eyeColor' => [
                'type' => 'string',
                'label' => wfMessage( 'eyecolor-label' ),
            ],
            'favoriteFood' => [
                'type' => 'string',
                'label' => wfMessage( 'favoritefood-label' ),
                'help' => wfMessage( 'favoritefood-help' ),
                // Marking the field as optional means the AuthenticationRequest can
                // be created if it's not present. Marking the AuthenticationRequest
                // as optional means authentication can proceed if it was not created.
                'optional' => true,
            ],
        ];
    }
}

Step 2: add a secondary authentication provider (a handler that is called when the User object representing the user becomes available) that signals the need for the request, and processes it:

<?php
use MediaWiki\Auth\AuthManager;
use MediaWiki\Auth\AbstractSecondaryAuthenticationProvider;
use MediaWiki\Auth\AuthenticationRequest;
use MediaWiki\Auth\AuthenticationResponse;

class MyExtraFieldsSecondaryAuthenticationProvider
    extends AbstractSecondaryAuthenticationProvider
{
    public function getAuthenticationRequests( $action, array $options ) {
        if ( $action === AuthManager::ACTION_CREATE ) {
            return [ new MyExtraFieldsAuthenticationRequest() ];
        }
        return [];
    }

    public function beginSecondaryAuthentication( $user, array $reqs ) {
        return AuthenticationResponse::newAbstain();
    }

    public function beginSecondaryAccountCreation( $user, $creator, array $reqs ) {
        $req = AuthenticationRequest::getRequestByClass( $reqs,
            MyExtraFieldsAuthenticationRequest::class );
        if ( !$req ) {
            // fields were left empty
            return AuthenticationResponse::newPass();
        }

        if ( $req->eyeColor === 'pink' ) {
            return AuthenticationResponse::newFail(
                wfMessage( 'error-wrong-eyecolor', $req->eyeColor ) );
        }

        // At this point, the user has been written into the database; $user->getId() is safe to use.
        MyExtraFieldsHandler::saveExtraFields( $user, $req->eyeColor, $req->favoriteFood );

        return AuthenticationResponse::newPass();
    }
}

Step 3 (optional): add a hook for customizing the presentation of the fields (see HTMLForm for the syntax of $formDescriptor):

<?php

class MyExtraFieldsHooks {
    public static function onAuthChangeFormFields(
        array $requests, array $fieldInfo, array &$formDescriptor, $action
    ) {
        if ( isset( $formDescriptor['eyeColor'] ) ) {
            $formDescriptor['eyeColor']['cssclass'] = 'eye-color';
        }
    }
}

Step 4: register the provider (and the hook if it was added):

    ...
    "AuthManagerAutoConfig": {
        "secondaryauth": {
            "MyExtraFieldsSecondaryAuthenticationProvider": {
                "class": "MyExtraFieldsSecondaryAuthenticationProvider",
                "sort": 0
             }
        }
    },
    "Hooks": {
        ...
        "AuthChangeFormFields": "MyExtraFieldsHooks::onAuthChangeFormFields"
    },
    ...