by David Snopek on March 21, 2017 - 11:24am

This is the second in a series of articles, in which I'd like to share the most common pitfalls we've seen, so that you can avoid making the same mistakes when building your sites!

myDropWizard offers support and maintenance for Drupal sites that we didn't build initially. We've learned the hard way which site building mistakes have the greatest potential for creating issues later.

And we've seen a lot of sites! Besides our clients, we also do a FREE in-depth site audit as the first step when talking to a potential client, so we've seen loads of additional sites that didn't become customers.

In the last article, we looked at security updates, badly installed module code and challenges ith "patching" modules and themes, as well as specific strategies for addressing each of those problems. In this article, we'll look at how to do the most common Drupal customizations without patching!

NOTE: even though they might take a slightly different form depending on the version, most of these same pitfalls apply equally to Drupal 6, 7 and 8! It turns out that bad practices are quite compatible with multiple Drupal versions ;-)

4. Patching when it's not necessary

In the last article, we talked about the potential problems with depending on patches and the extra work required to organize them to avoid those problems.

If you want to avoid doing all that extra work, it's best to avoid "patching" (ie. modifying) contrib modules and themes whenever possible!

However, most of the patched modules we see on the sites we audit, are patched to customize things that could easily be customized WITHOUT patching the module!

Here are the most common patches we see:

  • CSS changes
  • HTML template changes
  • Form alterations

All of those things could be done in custom theme or module - patching is totally unnecessary!

Since 99% of Drupal sites include a custom theme, we highly recommend putting those type of customizations in the theme. You could also put them in a custom module, however, we find that people who don't consider themselves "developers" are more comfortable working in the theme than a custom module.

Here's how...

4a. CSS changes

If you only want to make a minor change, you can just add some new CSS rules to your theme's CSS styles which override the CSS from the module. The theme's CSS will always come after the module's CSS, so it'll override it (assuming it's not "less specific" than the module CSS).

But if you want to totally change the CSS from the module, you can copy the CSS file into your theme, "register" it and your theme's version will totally replace the version from the module.

In order to "register" a CSS file in Drupal 6 or 7, you simply add a line like "stylesheets[all][] = MODULE.css" to your themes .info file and clear caches. See this documentation page for a more detailed explanation.

Replacing a CSS file in Drupal 8

Unfortunately, the process for completely replacing a CSS file in Drupal 8 is ... overly complicated. I sincerely hope that this is simplified in later versions or that tools appear to help make this easier. Going from adding a single line to this complex process is a clear loss for Drupal 8, where usually working in Drupal 8 is all wins. :-/

This documentation page covers it in detail, but I'm going to attempt to briefly explain here in order to get you started!

CSS files are registered in "libraries" in the MODULE.libraries.yml file. So, first we need to find the library entry for the CSS file we want to replace. If we wanted to replace "node.preview.css", we'd look in "node.libraries.yml" in the "node" module and see:

drupal.node.preview: # The library name
  version: VERSION
  css:
    theme: # The type of the CSS file - take note of this!
      css/node.preview.css: {} # Here you can see the CSS file we want!
  js:
    node.preview.js: {}
  dependencies:
    - core/jquery
    - core/jquery.once
    - core/drupal
    - core/drupal.form

So, we need to edit our THEME.info.yml and add the following:

libraries-override:
  node/drupal.node.preview: # MODULE/LIBRARY_NAME
    css:
      theme: # this has to come from the MODULE.libraries.yml
        # The original CSS file name mapped to the file in the theme
        css/node.preview.css: css/node.preview.css

Notice that some information from the MODULE.libraries.yml needs to be transferred into the THEME.info.yml (which is what makes this such a pain):

  • The module and library name
  • The CSS file type - 'theme' in this case
  • The path to the original CSS file in the theme (mapped to the path to the new CSS file in the theme)

Then you just clear the Drupal caches and Drupal will use your CSS file instead of the module CSS file everywhere it was originally used!

4b. HTML template changes

All of the HTML that Drupal generates comes from templates in Drupal 8 (*.html.twig files), and most of it in Drupal 6 and 7 too (*.tpl.php files).

To customize one of these templates, simply copy it from the module into your theme, modify if it, and clear the Drupal cache. The next time you load the page, Drupal will use your version instead!

4c. Form alterations

In Drupal, you create forms in PHP by making special arrays that represent the form elements. While a module will create the original form array, there is a mechanism for other modules and the theme to alter forms before they are shown to the user!

Unfortunately, doing this requires understanding a little PHP and referring to lots of docs on the Form API. However, if you were able to patch a module to alter the form, it's only a little more work to alter one in your theme!

Of all the topics discussed so far this is the most "developer-y" and I don't want to overwhelm you, so we're going to cover the "cheaters" process for making form alterations! ;-)

  1. Find the form ID of the form you want to alter. You can view the form in the web browser and then look at the HTML source for a hidden "form_id" input. For example, the login form's id is "user_login": The user login form and the source code showing the form id
  2. Install the Devel module. Never leave this installed on live sites! It's not a security vulnerability, but an attacker could potentially use it to escalate their access after exploiting another vulnerability.
  3. Edit (or create) template.php (D6 & 7) or THEME.theme (D8). If you're creating a new file, be sure to put '<?php' as the first line!
  4. Add a function named like THEME_form_FORM_ID_alter. So, if your theme is "mytheme" and you're altering "user_login", then it'd be:
    <?php
    function mytheme_form_user_login_alter(&$form, &$form_state) {
      dsm($form);
    }
    ?>
  5. Clear caches and reload the form. You'll see a cool, interactive array explorer which allows you to drill down into the form array and see what's in there. You can use this to find the thing you want to change:Screenshot showing exploring the form array of the login form via the Devel module
  6. Add PHP code to make our alteration. For example, let's say we want to change the "Username" field to "Nick name":
    <?php
    function mytheme_form_user_login_alter(&$form, &$form_state) {
      $form['name']['#title'] = t('Nick name');
    }
    ?>
  7. Reload the page and see your change:Screenshot of an alteration to the user login form without any patches

Note: In the code above, it wraps the "Nick name" in a t() function -- this is to enable translation. If you're site doesn't serve pages in multiple languages, you don't need to use that, but it's considered best practice. Who knows if you'll need to support multiple languages later?

Note 2: The code above WILL work with Drupal 6, 7 & 8, but it technically doesn't follow coding standards for Drupal 8, which should declare the function like this instead:

<?php
use \Drupal\Core\Form\FormStateInterface;
 
function mytheme_form_user_login_alter(&$form, FormStateInterface $form_state) {
  $form['name']['#title'] = t('Nick name');
}
?>

What next?

In this article, we covered the 4th pitfall among the 7 we're going to cover in this 3-part series. If you haven't already, please check out the first article!

Have you encoutered Drupal sites that include unnecessary patching? Are there any other important examples that you've encountered when building a Drupal site or reviewing a site built by someone else? Please write a comment below!

Or, if you'd like us to audit your Drupal site, please contact us about a FREE site audit!

Want to read more articles like this?

myDropWizard.com blog Subscribe to the myDropWizard.com blog and recieve e-mail updates when new articles are published!

Comments

Patches are such a pain! As a D7 Site builder, with very limited experience, I found that the Calendar Module [ https://www.drupal.org/project/calendar ] needs a patch to fix a skip-month issue. I tried the patch on my dev site, it worked, but I'm so unsure of the process for a live site that I won't attempt to fix. Last mod to the module was Oct 2014, both standard and dev release. Patches should be incorporated into the final release within a reasonable time!

Yeah, that's a tough part of Open Source: it's available and you can patch it but you should avoid it -- but since it could be maintained by volunteers in their free time, there's no guarantee on when patches will ever be included in a proper release. The first article of in this series gives some advice on organizing your patches, so, if you follow one of the recommendations there, then deploying to your live site should be fine!

Add comment