Editing user profile, login and registration fields

One of the requirements of the member sign-up plugin I’m currently developing is to present users of type member and subscriber with a modified profile page a little like this
[caption id=“attachment_259” align=“aligncenter” width=“1024”]And there is the fiscal code And there is the fiscal code[/caption] Further more the plugin should also allow the customization, in the first iteration agreed upon as a brute string hardcoding, of not only the location of the login page (easily done via a shortcode) but also of its fields.
Where customization of the login, registration and profile screens are topics already covered both in posts (a quick Google search will return resources aplenty for customizing logins for example) and in plugins doing it the way I needed is not possible, to my knowledge, via the above listed plugins or any other I came across.

A strange need

What makes a user unique in a WordPress site, both multi-site and single site installation, is its username.
Hence the fields username is present in any login form, registration form and profile page a WordPress user is presented with.
In a plugin aimed at allowing people to register as members of an association, or organization for the matter, a username is not that relevant: site administrators might be satisfied with that but anyone taking care of the association paper-work needs to tie “lordOfDeath321” to “John Doe”.
So the requirement emerged to ask members to register using their fiscal code (Italian version of Social Security Number) as their username.

But people will not read

This problem well known to anyone states that the friendly username label “Please enter your fiscal code as username” will be ignored even after several failed attempts to force a validated field to accept it.
So I need to change the label saying “username” in login, registration and profile screen: should be easy.

Easy adding, no change, no remove

All the plugins I tried allowed adding fields, something I have to do via the fantastic Cimy User Extra Field, but none allowed to hide or change the already present fields.
Some JavaScript solutions are scattered across the web and removing contact methods it’s a breeze through the contactmethods hook but while I do not need to do the second the first solution looks to me like using tape to cover unwanted people in pictures.

There must be an hook

Long story short: there are not. You can hook after all the important stuff has happened. So I record the show and edit the movie later.

Using regexes smells like hacking core

I know it’s not the same but parsing output using regexes is not a reliable method to do it. But it’s the only one I found. To get a glimpse (you can have a longer look at the GitHub repository) here is the code to remove some fields from the profile.
First I hook into admin_head and admin_footer some place relevant

$this->functions->add_action('admin_head', array(
    $this,
    'start_profile_buffer'
));
$this->functions->add_action('admin_footer', array(
    $this,
    'end_profile_buffer'
));

then in the above hooked function record the movie using the output buffer

public function start_profile_buffer()
{
    if ($this->should_modify_profile_fields()) {
        // start buffering
        ob_start();
    }
}
public function end_profile_buffer()
{
    if ($this->should_modify_profile_fields()) {
        // get the intercepted output buffer
        $contents = ob_get_contents();
        // clean the output buffer and stop buffering
        ob_end_clean();
        // TODO: all the fields below should be options and not hardcoded strings...
        // TODO: please make stronger regexes
        //remove the personal informations title
        $contents = preg_replace("~(<\\s*form\\s*id\\s*=\\s*['\"]your-profile.*)(<h3>.*)(<h3)~uUs", "$1$3", $contents, 1);
        // change the username label
        $contents = preg_replace("~(<label\\s*for\\s*=\\s*['\"]user_login['\"].*>)([^<]*?)(<.*<span class=\"description\">)([^<]*?)~uUs", "$1Fiscal Code$3Fiscal code can't be modified", $contents);
        // remove the nickname row and the one below
        $contents = preg_replace("~<tr>\\s*<th>\\s*<label\\s*for\\s*=['\"]nickname['\"].*</tr>.*display_name.*/tr>~uUs", "", $contents);
        // remove the website row
        $contents = preg_replace("~<tr>\\s*<th>\\s*<label\\s*for\\s*=[\"']url['\"].*</tr>~uUs", "", $contents);
        echo $contents;
    }
}

I do not usually hardcode strings in the code (it’s bad practice, it’s not easily maintainable and it’s not easily internationalized) and do not like using regexes because it’s not a reliable way to manipulate HTML markup. But here and now it does the trick.