Debugging on Platform.sh

We are in the process of deploying a lot of sites on to the excellent Platform.sh infrastructure at the moment.  As with all these things, we hit a few snags along the way.  The way that we worked around this was to install the Xdebug extension and use it to step through the code.

Firstly you need to enable the extension. Edit your .platform.app.yaml file to add the extension.

runtime:
    extensions:
      - xdebug

You will need to check that code in and deploy it to one of your containers.

Now that you have XDebug installed, you need to get it to talk to your local IDE.  The easiest way is via an ssh tunnel.  Open a terminal and run the following command, changing the user to that of your project hash.

ssh -R 9000:localhost:9000 bvzmhsdbu6g3g-master@ssh.eu.platform.sh

If you don’t know where to find your ssh details, it is in the web interface under Access Info.  Click the clipboard to the right to copy the ssh connection.

ssh access settings

Assuming that you have your IDE set up to accept Xdebug settings, you can now start it listening on port 9000 and tell the website to start debugging.

Xdebug helper in the address barIf you’re using Google Chrome, then Xdebug helper is a great little icon that sits in your address bar.  Rather than you having to add an attribute to the address, you can simply click this friendly little bug to add a cookie to the request.

Drupal and DNS Prefetch

In a bid to help you gain performance from your web apps, a new feature introduced with HTML5 is the ability to prefetch DNS resources.  Currently widely supported (Firefox 3.5+, Chrome, Safari 5+ and IE 9+), prefetching is where your browser will in the background to a DNS lookup for the addresses that you give. This means when it comes to access a resource at a host, it can skip the DNS lookup, thus saving precious milliseconds on your load time.

This is one way you can implement prefetching with Drupal, inside a THEME_prerpocess_page() hook.

function MYTHEME_preprocess_page(&$variables, $hook) {
    drupal_add_html_head(array(
    '#tag' => 'link',
    '#attributes' => array(
      'rel' => 'dns-prefetch',
      'href' => '//www.googletagmanager.com',
    ),
  ), 'googletagmanager_dns_prefetch');
}

This will produce the following html in the head of your site

<link rel="dns-prefetch" href="//www.googletagmanager.com" />

How we dealt with Heartbleed and Drupal

I just wanted to share how we have dealt with the Heartbleed bug at work in case there is anyone else out there that runs a Drupal site that needs some help.

Obviously we have patched the servers and got new certificates issued, but the job of resetting passwords is the tricky one.  Now we could use the approach of asking our users to change their passwords, but if more than 5% of users actually did that I would be shocked.

Below is a hook_update snippet of code similar to that we have used to force every user to reset their password.

The code works by forcefully ending every users session (by truncating the sessions table).  We then update every users password with a randomly generated password (that we do not know) to prevent them from being able to log in with their insecure password. Finally, we send every user the reset your password email with the one time login link to make it easy for them to get back in.

function HOOK_update_7???() {
  require_once DRUPAL_ROOT . '/includes/password.inc';

  // Log users out.
  db_truncate('sessions')->execute();

  // Generate a password.
  $password = user_password();

  // Hash password.
  $password = user_hash_password($password);

  // Update all the passwords to hashed generated password, not user 0 or 1.
  $updatepass = db_update('users')
    ->fields(array(
      'pass' => $password,
    ))
    ->condition('uid', '0', '!=')
    ->condition('uid', '1', '!=')
    ->execute();

  // Get users to send email.
  $users = db_select('users', 'u')
    ->condition('uid', '0', '!=')
    ->condition('uid', '1', '!=')
    ->fields('u', array(
      'uid',
      'name',
      'mail',
      'login',
      'pass',
      'language',
    ))
    ->execute()
    ->fetchAllAssoc('uid');

  // Send emails to the users
  foreach ($users as $user) {
    $mail = _user_mail_notify('password_reset', $user);
  }
}

Why not use a module like Mass Password Reset? Simple, we run 100+ sites on our installation and it would be a pain to run that on all sites.  This is in our profile so all we have to do is deploy the code and run updates.

Kudos goes out to pbz1912 who actually wrote the code.

Edit

As mentioned in the comment from Luca, it’s not best practice to just send your users the reset password email, but to let them know whats going on.  We also used a similar snippet of code to the one below to add some help text to the login form.

function HOOK_form_user_login_alter(&$form, $form_state) {
  $form['heartbleed'] = array(
    '#type' => 'markup',
    '#markup' => t("

Put your friendly help text in here, it will appear above the login form

"), '#weight' => -50, ); }

Adding classes to the Drupal image_formatter link

So you are using Drupal, and you are outputting an image field from a node to the screen.  You have it set up so that the display is using an image_style to generate a thumbnail, and you are linking to the full size image.  All great, except you want an additional class on the link….

You could override the field template so that it has the field hard coded.  Seems like a bit of hard work, and massively redundant since all you want is a single (or couple of) class(es) on the link (as you’re using a Bootstrap based theme and want to add the thumbnail class)

Preprocess this

Enter theme_preprocess_field(), which is called before any field is rendered, and is your friend.

First thing to do is target the field that you are looking to modify, which is done like this

function THEME-NAME_preprocess_field(&$variables, $hook) {
  if ($variables['element']['#field_name'] == 'field_FIELD-NAME') {
    ...
  }
}

Next thing is to add the class to the link.  The image formatter uses items from the #path array to construct and link, and makes use of the l() function, so we need to bare that in mind when we are adding classes.  The option array with the #path array gets passed into the l function as the options parameter.

The final code looks like this.

function THEME-NAME_preprocess_field(&$variables, $hook) {
  if ($variables['element']['#field_name'] == 'field_FIELD-NAME') {
    foreach ($variables['item'] as &$item) {
      $item['#path']['options']['attributes']['class'] = array(
        'my-class',
      );
    }
  }
}

So there we have it, our class is added to the link, in just a few lines of code, without overriding a template that could easily get stale or hard to maintain.

Using Drupal’s hook_views_default_views_alter

I came across an issue recently with a Drupal installation that I am working on that required me to use hook_views_default_views_alter, and found that the help out there was minimal.  I finally got what I was after working, but with much debugging using the Devel module and dpm.  I thought that I would put down what I found out to help others in a similar position. Continue reading Using Drupal’s hook_views_default_views_alter