1

I got thrown into taking over a project that has gone through a few different developers.

I have a problem with two spaces being output before the doctype declaration. I have confirmed it's not the template and I have isolated both of the whitespaces to be from a custom module (one I found, the other is obvious as it went away when I turned off all modules.) I already went through and verified no whitespace was caused by closing the php tag, and before it. I am confident it's caused by a module. I have error reporting turned to all and displayed but I have no PHP errors that are generated.

I used pcregrep -rMl '\?>[\s\n]+\z' * to find all files that had trailing whitespaces and fixed them.

When I copy and paste the whitespace into my IDE it looks like two really small dots (almost like a backtick but a dot.) When looking at it in view source of the page, it looks like two spaces.

This is an example: (Inside the single quotes, it works for copying the whitespace to see how it looks in an IDE)

' <!DOCTYPE html PUBLIC "-//W3C//DTD HTML+RDFa 1.1//EN">'

Below is a module that I can turn off to remove one of the whitespaces. Turning it back on shows the whitespace. I am not able to see what would be causing this issue. I removed the closing php tag and ensured no whitespace before the opening php tag. Flushed all cache and cleared browser cache too.

My guess is it has to be doing something that I am unaware of, perhaps a Drupal issue with the module?

os_registration.info

name = os_registration
core = 7.x
package = Features
features[features_api][] = api:1

os_registration.module

<?php

/**
 *  Implementation of hook_block_info()
 */
function os_registration_block_info() {
    $blocks['user_registration'] = array(
        'info' => t( 'User registration' )
    );
    return $blocks;
}

function os_registration_block_view( $delta = '' ) {
    $blocks = array();
    switch($delta) {
        case 'user_registration':
            global $user;
            // Don't display the form to logged in users or if registration is disabled
            if ( !$user->uid ) {
                //if (!$user->uid && variable_get('user_register', 1)) {
                return array(
                    //'subject' => t('We\'re busy working on the site right now, but Parables TV will be launching soon! <br/><br/> Submit your email address to receive information on how to get Parables.'),
                    'subject' => t( 'Not a Subscriber?<br><br>Sign Up Now for a Free 30 Day Trial!' ),
                    'content' => drupal_get_form( 'user_register_form' )
                    //'content' => theme('os_blocks_mailchimp'),
                );
            }
            break;
    }
    return $blocks;
}

/**
 *  A helper module for the Safe Streets Miami project
 */
function os_registration_menu() {
    $items = array();
    $items['login'] = array(
        'title' => t( 'Sign in' ),
        'description' => t( 'Sign in' ),
        'access callback' => 'os_registration_login_access',
        'page callback' => 'drupal_get_form',
        'page arguments' => array( 'user_login' ),
        //'type' => MENU_NORMAL_ITEM, This needs to be set when the sign in goes live
        'type' => MENU_CALLBACK,
        'weight' => 10,
        'menu_name' => 'user-menu'
    );

    return $items;
}

function os_registration_menu_alter( &$items ) {
    $items['user/login']['title'] = 'Sign In';
    $items['user/login']['weight'] = 1;
    $items['user/password']['weight'] = 2;


    // Kill the tabs on the login pages.
    //$items['user/login']['type'] = MENU_NORMAL_ITEM;
    //$items['user/register']['type'] = MENU_NORMAL_ITEM;
    //$items['user/password']['type'] = MENU_NORMAL_ITEM;

    // All these items need to be reset so that users can log in
    $items['user/login']['type'] = MENU_CALLBACK;
    $items['user/register']['type'] = MENU_CALLBACK;
    $items['user/password']['type'] = MENU_CALLBACK;
    unset( $items['user/login']['title'], $items['user/register']['title'] );
}

// handles menu item access
function os_registration_login_access() {
    return ( !isset($GLOBALS['user']) || !$GLOBALS['user']->uid ) ? true : false;
//    return ( !( $GLOBALS['user']->uid ) );
}

/**
 * IMPLENTATION OF hook_form_form_id_alter() to hook into the user
 * login form.
 */
function os_registration_form_user_register_form_alter( &$form, &$form_state ) {
    $form['account']['name']['#type'] = 'hidden';
    $form['account']['name']['#value'] = user_password();
    $form['account']['mail']['#title'] = t( 'E-mail' );

    if ( $form['#form_id'] == 'user_register_form' ) {
        // no description as it should be self evident how to use
        unset( $form['account']['mail']['#description'] );
        unset( $form['account']['pass']['#description'] );
        $form['account']['mail']['#size'] = 28;
        $form['account']['mail']['#weight'] = -10;
        // create a form field to confirm email
        $form['account']['conf_mail'] = array(
            '#type' => 'textfield',
            '#title' => t( 'Confirm e-mail' ),
            '#weight' => -9,
            '#maxlength' => 64,
            '#required' => true
        );
        $form['legal'] = array(
            '#type' => 'markup',
            '#markup' => '<div class="registration-legal"><div class="registration-legal-secure">Secure server</div><div class="registration-legal-privacy">We will not sell or rent your email address. We may contact you about the Parables service. See our <a href="/privacy-policy" target="_blank">Privacy Policy</a>.</div></div>',
            '#weight' => 200
        );
        // validate the confirm email field
        array_unshift( $form['#validate'], 'os_registration_user_form_validate' );
        os_registration_disablepwstrength_add_js();
    }

    // if the user is going to the register page then the form needs some added attention
    if ( $_GET['q'] == 'user/register' ) {
        // Have gotz to get to the front of the array
        $form['#prefix'] = '<div id="login-wrapper"><div id="login-header">' . t( '<h2>Sign Up<span> or !sign_in</span></h2>', array( '!sign_in' => l( t( 'Sign In' ), "login" ) ) ) . '</div>';
        $form['#suffix'] = '</div>';
    }
}

/**
 * Implementation of hook_form_form_id_alter() to change the submit button of the user login
 */
function os_registration_form_user_login_alter( &$form, &$form_state ) {
    drupal_set_title( '' );
    unset( $form['name']['#description'] );
    unset( $form['pass']['#description'] );
    $form['name']['#title'] = t( 'E-mail' );
    $form['name']['#element_validate'][] = 'os_registration_user_login_validate';
    $form['actions']['submit']['#value'] = "Sign in";
    //Add the forgot password link
    $form['forgot_pass'] = array(
        '#markup' => t( "!link", array( '!link' => l( t( 'Forgot your password?' ), "user/password" ) ) ),
        '#prefix' => '<div id="login-forgot-password">',
        '#suffix' => '</div>'
    );
    $form['actions']['not_registered'] = array(
        '#markup' => t( "!link", array( '!link' => l( t( 'Not a member yet?' ), "user/register" ) ) ),
        '#prefix' => '<span id="login-not-registered">',
        '#suffix' => '</span>'
    );
    // Have gotz to get to the front of the array
    $form['#prefix'] = '<div id="login-wrapper"><div id="login-header">' . t( '<h2>Sign In<span> or !sign_up</span></h2>', array( '!sign_up' => l( t( 'Sign Up' ), "user/register" ) ) ) . '</div>';
    $form['#suffix'] = '</div>';
}

/**
 * Validation function for the user regerster form
 */
function os_registration_user_form_validate( $form, &$form_state ) {
    global $user;
    // Check if email and confirm mail fields are the same
    // If they are, use elseif to check if the email exists in the
    // user database table. We are hooking into the registration process
    // here to log the person in if they have already registered. We will submit
    // this information as the submit for the login form programmatically.
    // Otherwise we will bypass this early login and let the registration
    // process finish through as normal.
    if ( $form_state['values']['mail'] != $form_state['values']['conf_mail'] ) {
        form_set_error( 'conf_mail', t( 'Your e-mail address and confirmed e-mail address must match.' ) );
        // We check to see if this submitted by someone already logged in.
        // The only logged in user submitting this form can the Editor or Administrator
        // $reg_user is just the registered user. Needed a different variable because it might
        // set the GLOBAL $user object to false.
    } elseif ( !$user->uid && $form_state['values']['mail'] && $reg_user = os_registration_user_email_exists( $form, $form_state ) ) {
        if ( user_authenticate( $reg_user->name, $form_state['values']['pass'] ) ) {
            $form_state = array();
            $form_state['uid'] = $reg_user->uid;
            user_login_submit( array(), $form_state );
            drupal_goto( '<front>' );
        }
    }
}

/**
 * Helper function to query to see if new user or not. This process does some
 * of the thinking for people who are curious about the websit but
 * haven't commited yet.
 *
 * @param mixed $form
 * @param mixed $form_state
 * @return mixed
 */
function os_registration_user_email_exists( $form, &$form_state ) {
    $query = new EntityFieldQuery();
    $query
        ->entityCondition( 'entity_type', 'user' )
        ->propertyCondition( 'mail', $form_state['values']['mail'] )
    ;
    $result = $query->execute();

    if ( !empty( $result['user'] ) ) {
        $users = entity_load( 'user', array_keys( $result['user'] ) );
        return array_pop( $users );
    }

    return false;
}

function os_registration_form_user_profile_form_alter( &$form, &$form_state, $form_id ) {
    os_registration_disablepwstrength_add_js();
}

/**
 * Add the JavaScript to disable Drupal's password strength checker.
 */
function os_registration_disablepwstrength_add_js() {
    drupal_add_js( 'Drupal.behaviors.password = function () {};', array( 'type' => 'inline', 'scope' => 'footer' ) );
}

/**
 * When the password is being reset redirct to password edit page
 *
 * Subscribers on login get sent to the live stream
 * Previous subscribers get sent to renew their subscription
 * Admins get sent to front until a dashboard is made
 * Everyone else gets sent to pricing.
 * If the $edit form
 */
function os_registration_user_login( &$edit, $account ) {
    $reset = !empty( $_POST['form_id'] ) && $_POST['form_id'] == 'user_pass_reset';
    if ( !$reset && arg( 0 ) != 'os-apps' ) {
        if ( in_array( 'previous_subscriber', $account->roles ) ) {
            drupal_goto( 'renew-pricing' );
        } elseif ( in_array( 'editor', $account->roles ) || in_array( 'administrator', $account->roles ) ) {
            drupal_goto( 'dashboard' );
        } elseif ( in_array( 'subscriber', $account->roles ) || in_array( 'promo', $account->roles ) ) {
            drupal_goto( 'live-stream' );
        } elseif ( in_array( 'family-christian', $account->roles ) ) {
            drupal_goto( 'basic-page' );
        } else {
            drupal_goto( 'pricing' );
        }
    }
}

function os_registration_user_presave( &$edit, &$account, $category ) {
    if ( !empty( $account->mail ) && !isset( $edit['name'] ) || !empty( $account->mail ) && $edit['name'] != 'admin' ) {
        $account->name = $edit['name'] = os_registration_get_new_name( $account );
    }
}

function os_registration_get_new_name( $account ) {

    // Default implementation of name generation.
    $new_name = preg_replace( '/@.*$/', '', $account->mail );
    // Remove unwanted characters.
    $new_name = preg_replace( '/[^a-zA-Z0-9.-]/', '', $new_name );

    // if username generated from email record already exists, append underscore and number eg:(chris_123)
    if ( (bool) db_query( "SELECT 1 FROM {users} WHERE uid <> :uid AND LOWER(name) = LOWER(:new_name)", array( ':uid' => $account->uid, ':new_name' => $new_name ) )->fetchField() ) {
        $name_idx = db_query_range( "SELECT SUBSTRING_INDEX(name,'_',-1) FROM {users} WHERE name REGEXP :search ORDER BY CAST(SUBSTRING_INDEX(name,'_',-1) AS UNSIGNED) DESC", 0, 1, array( ':search' => '^' . $new_name . '_[0-9]+$' ) )->fetchField();

        $new_name .= '_' . ( $name_idx + 1 );
    }
    return $new_name;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function os_registration_form_user_pass_alter( &$form, &$form_state, $form_id ) {
    $form['name']['#title'] = t( 'E-mail' );
    $form['name']['#description'] = t( 'A password reset message will be sent to your e-mail address.' );
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function os_registration_form_user_login_block_alter( &$form, &$form_state, $form_id ) {
    $form['name']['#title'] = t( 'E-mail' );
    $form['name']['#element_validate'][] = 'os_registration_user_login_validate';
}

/**
 * Form element validation handler for the user login form.
 * Allows users to authenticate by email, which is our preferred method.
 */
function os_registration_user_login_validate( $form, &$form_state ) {
    if ( isset( $form_state['values']['name'] ) ) {
        $name = db_query( 'SELECT name FROM {users} WHERE LOWER(mail) = LOWER(:name)', array( ':name' => $form_state['values']['name'] ) )->fetchField();
        if ( $name ) {
            $form_state['values']['name'] = $name;
        }
    }
}

If you need any other information let me know. I am still trying to isolated this but thought more expert advice would be beneficial.

Thanks

  • 1
    I´ve seen similar behaviour before and I´ve always resolved it by forcing the file to have UTF-8 (Without BOM) encoding. If you use Sublime Text 2/3 or Notepad++ (I´m a Windows guy, sorry :|) you can go to File -> Save with Encoding -> UTF-8. Try it and let us know. – hachesilva Aug 25 '14 at 20:27
  • 1
    You are a life saver! I've been trying to fix this for days... I had to remove BOM on the file. Thanks! Post this as an answer and I'll accept it. Thanks! – Jeremy Aug 25 '14 at 21:09
2

So the solution was to save the file with a forced UTF-8 encoding and remove BOM ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.