Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Nov 20 2020
Nov 20

Drupal.org has used patches to manage community contribution for many years. But, patches are difficult for new users to learn and require the use of the command line. Recently, Drupal.org code has migrated to Gitlab, and we can now use Gitlab and Drupal.org issues to create Merge Requests to share code and fixes with modules and Drupal Core. Here’s an overview of creating a merge request for folks who want all the details.

Drupal Forks are Special

Drupal Gitlab forks are special because they are accessible to everyone with a Drupal.org account. One fork per issue, and anyone can edit the fork and open a merge request to the main project.

Setup your Drupal Account

Before we begin, you must register for an account on Drupal.org to get access to gitlab forks. Next, add an ssh public key to your Drupal.org user profile so you don’t need a password to work. Lastly, agree to the Drupal.org git terms of service so you can access forks.

Create an issue on Easy Breadcrumb

Before you can create forks on Drupal.org’s gitlab, you need an issue! So, start by creating an issue on Easy Breadcrumb.

Once you have the issue, press “Create issue fork”.

Clone Easy Breadcrumb

Next copy of the module you want to modify. You can get instructions for this by clicking version control near the top of the module.

git clone --branch 8.x-1.x [email protected]:project/easy_breadcrumb.git
cd easy_breadcrumb

Make Your Changes

Now, edit the code on your own computer to fix the issue. This is the hardest part!

Send Your Work to the Issue Fork on Gitlab

The exact git commands vary slightly from issue to issue. So, check the “view commands” link on the issue to see the commands for your issue, but here are the ones I ran. I got the commit message from the commit credit section towards the bottom of the issue.

git remote add easy_breadcrumb-3174165 [email protected]:issue/easy_breadcrumb-3174165.git
git fetch easy_breadcrumb-3174165
git checkout -b '8.x-1.x' --track easy_breadcrumb-3174165/'8.x-1.x'
git add .
git commit -m 'Issue #3174165 by kell.mcnaughton, pattsai: How to support limiting depth' --author="git <[email protected]>"
git push --set-upstream easy_breadcrumb-3174165 HEAD

The commands do the following:

  • Add the new fork as a remote.
  • Fetch the new fork.
  • Checkout a branch on that fork.
  • Add your work to that branch.
  • Commit your work to that branch.
  • Push your work to Gitlab.

Open a Merge Request

Once your work is saved to the issue fork on Gitlab. Go back to the issue on Drupal.org and click Compare near the top of the issue. Then, click open merge request!

Now that your request is open, the maintainer of the module just needs to press merge on Gitlab to make the code part of the project!

Jun 19 2020
Jun 19

With the launch of Drupal 9, the community is rallying to update all of the community contributed modules from Drupal 8 to Drupal 9. This work is often just a single line of code to tell Drupal that the module supports 9. But, for older, out of date modules, the work required to get to Drupal 9 is a bigger effort. Some of these modules haven’t been updated in 4 years.

I’m not to complain about problems without solutions. So, how do we fix it?

The Maintainer’s Initiative!

Together with Damien Mckenna, we’ve started a new Drupal project called Maintainers. Our goal is to support as much of Drupal contrib as we can while focusing on issued marked “reviewed and tested by the community”. Instead of starting a new module, we’re picking up where others left off.

Finishing Drupal 8 Ports

Beyond curating releases for older Drupal 8 modules, I also hope to finish Drupal 7 to 8 ports that aren’t quite finished yet. Most recently, I assisted with releases for of AddtoCal and ShareThis. My next todo is a release for Styleguide and Author Pane.

Join Us

You can read more about the effort on the Drupal Association blog, or join us on Drupal Slack at channel #maintainers.

Sep 25 2016
Sep 25

In many modern frameworks, data modeling is done by building out database tables. In Drupal, we use a web-based interface to build our models. This interface makes building the database accessible for people with no database experience. However, this easy access can lead to overly complex content models because it’s so easy to build out advanced structures with a few hours of clicking. It’s surprising how often Drupal developers are expected to be content modeling experts. Here’s a well-written overview of content modeling for the rest of us who aren’t experts yet.

Data Modeling Goal

Our goal when modeling content in Drupal is build out the structure that will become our editor interface and HTML output. We also need to create a model that supports the functionality needed in the website. While accomplishing this, we want to reduce the complexity of our models as much as possible.

Getting Started

One of the first things to do when building a Drupal site is to build content types. So, before you start a site build, start with either a content model or a detail page wire frame. This spreadsheet from Palantir will help you. The home page design may look amazing, but it’s unhelpful for building out content types. Get the detail pages before you start building.

Why Reduce Complexity?

The more content types you create, the more effort it will take to produce a site. Further, the more types you have, the more time it will take to maintain the site in the future. If you have 15 content types and need to make a site-wide change, you need to edit 15 different pages.

The more pages you need to edit, the more mistakes you will make in choosing labels, settings, and formatters. Lastly, content can’t easily be copied from one type to another which makes moving content around your site harder when there are many content types. So, the first thing you’ll want to do with your content model is to collapse your types into as few types as feasible. How many is that?

5 Content Types is Enough

Drupal has many built in entities like files, taxonomy, users, nodes, comments, and config. So, the vast majority of sites don’t need any more than 5 content types. Instead of adding a new content type for every design, look for ways to reuse existing types by adding fields and applying layouts to those fields.

Break Up the Edit Form

Drupal 8 allows you to have different form displays for a single content type. With either Form Mode Control or Form Mode Manager, you can create different edit experiences for the same content type without overloading the admin interface.

Now that we’ve got the goal in mind and some tools to get us there, we’ll dive into the specifics of configuring field types such as hero images and drop down lists in my next post.

Mar 05 2016
Mar 05

Drupal sites often suffer from a less than ideal editor experience. While Drupal 8 improves on the default experience by providing inline editting, working preview, and moving the ‘advanced’ options to the sidebar, there’s still common mistakes that will lead to poor a experience. As a part of my on-going Drupal 8 Best Practices series, lets look at what we can do to build good admin interfaces.

Here are a few major principles behind the admin experience:

  • Use as few content types as reasonable.
  • Use permissions to hide unneeded options.
  • Content should not be defined in code.
  • Content and layouts should be editable by the editor without modifying code or css.
  • Content should have a contextual edit link.
  • A site should not require admin access to figure out how to edit.
  • Content should be stored in nodes, not entities or taxonomy terms.
  • Taxonomy can be used to apply additional page styles.
  • Taxonomy terms should have limited fields.
  • Vocabularies shouldn’t be too large or too deep.
  • The editor should have easy links and dashboard.
  • Editors should be given the Clear Cache permission.
  • CKeditor should be configured to allow pre-selected CSS styles.
  • Editors should have a simple tool for applying layouts to new pages.
  • Editors should be able to apply custom CSS via a drop down.

Give Permissions Carefully

Clients should be given the admin password for user 1, but every user should log into the site with their own user account that has an ‘editor’ permission set. This editor account should only be given permission to do the things they do frequently.

Content Should be Editable

There’s no reason to hard-code content into your theme or PHP. Every piece of text on the page should be editable through the hover edit link over that content. If you can’t edit something without a git push, then it should be a blocking bug.

Content Should be Stored in Nodes

This is a common mistake. Taxonomy terms are not content. They are meant to organize content. So, if you’re putting fields (especially text fields) on terms, you’re prboably making a pretty big error because taxonomy terms can’t be unpublished, promoted, or revisioned easily. If you’re putting content into custom entities, you’re probably also making a mistake because entities take a lot of extra work to get the basics that you get from nodes for free.

Think of WordPress here, do you see your user profile when you first log in? No, you see a dashboard of content to edit and other useful information. Do the same in Drupal, redirect login to admin/content if nothing else. Give folks short cut links in their menu bar as well.

Did You Clear the Cache?

Lets face it, the cache clear problem from Drupal 7 is a bit worse in Drupal 8. There are many times you need to Cache Rebuild. So, give them the button.

Use a Layout System or Layout Taxonomy

Panels and Display Suite are popular because they are powerful, stable, uesful and easier to use than default Drupal. No matter what tools you use, give your editors easy abilitiy to apply a layout to a new page. Don’t hand code each page. Build layouts, and apply them. Even a simple ‘Layout’ taxonomy field can allow editors to apply layouts to content.

When deciding how to build things in Drupal 8, always spend some thought on how to make sure each piece of content will editted. Not only will your customers thank you, you’ll be making Drupal look good.

Mar 05 2016
Mar 05

The theming guide for Drupal 8 will get you started in the basics for theming a Drupal site. But, once you’ve learned the basics, what best practices should you be applying to Drupal 8 themes? There are lots of popular methods for writing and organizing CSS. The basics of CSS, of course, apply to Drupal.

  • Don’t get too specific
  • Place your CSS in the header and JavaScript in the footer
  • Organize your CSS well
  • Theme by patterns, don’t go top down
  • Preprocess your styles

Use configuration first

When it comes to Drupal, there are some common mistakes that happen when a front end developer doesn’t know Drupal. In general, apply your classes in configuration. Do not fill your Drupal theme with custom templates like you would for WordPress. Template files, especially with Twig, have their place. But, configuration should be your primary tool. My favoriate tool for applying classes is Display Suite and Block class. Panels is also good. And, fences isn’t terrible.

By applying your classes in configuration allows you to easily edit, reuse, and apply classes across every type of thing in Drupal. If you apply your classes with templates, it’s difficult to apply them across different types of content without cutting and pasting your code. However, don’t be afraid to use some presentational logic in your Twig templates.

Be careful what you target

In Drupal, there are many times where the only selector you have that will work is an ID. If you have this problem, Don’t use it! Never, ever, ever, apply your CSS with ids in Drupal. This is true for every framework, but in Drupal it’s a bigger problem because IDs are not reusable, they are hard to set, and they often change. A backend developer will not be able to apply your styles to other items without fixing your CSS for you. Don’t write CSS that you know a PHP programmer will have to rewrite because you don’t want your PHP programmer writing CSS.

Use view modes

Make sure to target your styles to reusable elements. So, avoid node types because those aren’t reusable on other nodes. Instead, use view modes and configuration to apply selectors as you need them.

Avoid machine names

This relates back to avoiding IDs. Machine names in Drupal sometimes need to change, and they are not reusable. So, don’t target them. Instead use view css, block class and configuration to apply classes to your content.

Don’t get too specific

Drupal 8 markup is better, but Drupal is still very verbose. Don’t get sucked in by Drupal’s divs. Only get as specific as you need to be. Don’t replicate Drupal’s HTML in your CSS.

Apply a grid to Drupal

Choose a grid system that allows you to apply the grid to any markup like Singularity or Neat. While you certainly can Bootstrap Drupal. Using Bootstrap on Drupal requires a heavy rewrite of the HTML which will break contributed modules like Drupal Commerce in obscure, hard to fix ways.

Use a breadcrumb module

Do not write advanced business logic into your theme templates. If your theme is programming complex features, move that code to a module. Or, install modules like Current Page Crumb, or Advanced Agg to handle more complex functions. This isn’t WordPress, your theme shouldn’t ship with a custom version of Panels.

Don’t hard code layouts

Use {{ content }} in your templates and let the View Modes, Display Suite, or Panels handle your layouts.

Don’t use template.php

If you need some ‘glue’, write or find a module meant for it. Drupal is built by many, many tiny modules. Learn to love it because well-written modules are reusable, maintained for free and always improving. Custom code dropped into your theme makes for hard to maintain code.

Mar 04 2016
Mar 04

Breadcrumbs are a pain point in Drupal 7. If you don’t know how breadcrumbs are supposed to work, go read this. The crumb should start with home and continue through to an unlinked crumb of the current page. Crumbs were implemented poorly, and breadcrumbs were difficult to modify in a module. Further, they were based on items in the menu. The breadcrumbs didn’t even allow you to edit the home title or include the current page title as an unlinked crumb. So, if you wanted breadcrumbs on a Drupal site, the first step was to choose 1 of 10 different modules to build them for you. Making matters worse, some themes decided to program breadcrumbs for you as well. If you’re stuck with a Drupal 7 breadcrumb problem, use a module I help maintain, Easy Breadcrumb. Trust me. I’ve got this for you.

Drupal 8 vastly improves breadcrumbs, but core still gets them wrong. They are based on the current page path exactly like Easy Breadcrumb in Drupal 7 which is a huge improvement. So, what did they get wrong? The current page title is missing. Bummer. So close. But, not hard to fix. So, lets do it! If someone tells you to program the breadcrumbs into your theme, don’t listen to them. They are doing it wrong. Themes should work with markup and presentation. They shouldn’t implement complex, reusable logic.

Drupal 8 has refactored breadcrumbs making them much easier for developers to extend or replace. This new architecture makes it easy for us to correct Drupal 8’s breadcrumbs. Unfortunately, the code from Larry’s post is a bit out of date and doesn’t work anymore. So, lets look at the code pulled from my module Current Page Crumb module that adds the current page title to the breadcrumb.

This code extends the PathBasedBreadcrumbBuilder core class to add the current page title to the breadcrumb. Since everything else needed for the breadcrumb is handled by the parent, line 31 does almost all the work for us. From there, we just need a few lines to add the current page’s title. If you’re looking for more examples to completely replace the core breadcrumbs with a custom builder, check out the Drupal 8 version of Easy Breadcrumb which does just that.

Feb 18 2016
Feb 18

Don’t store site configuration in the database during development because putting configuration in the database makes configuration difficult to track in version control. Instead, use the file system! Putting configuration in a database also makes it more difficult to restore, compare, sync, deploy, modify, and review the site config. Drupal 8 uses Yml files for configuration which are a perfect format for file-based configuration. In fact, this is the only method for storing configuration in BackdropCMS because BackdropCMS uses JSON files to store site configuration. Drupal uses Yaml to store your configuration the database, but storing Yaml in files was the default method for Drupal 8 when CMI was released. Many posts have been written about the default workflow for configuration. But, the promise of file-based workflow is more efficient.

Configuring in Files Workflow

When Drupal stores configuration files in the file system, all you do to save your work is run a git commit because as soon as you click save in a form, Drupal writes your changes to the configuration folder. Once your work is in code and committed to version control, you can publish those on GitHub and open a pull request to review your work before deploying it to production. This workflow is possible with database configuration, but it requires extra steps with Drush that can lead to errors and differences between environments.

Don’t Modify Production

No matter which storage you use for configuration, you should not edit your configuration in production. Instead, you should install the config readonly module in production and make all of your changes in your local environment. Clients who don’t install Drupal locally can make configuration changes in development. Using a host like Pantheon makes it easy to deploy files from development to production.

So Why Does Drupal Store Config in the DB?

I prefer keeping configuration in the file system, and BackdropCMS agrees with me. But, a few smart core developers don’t see it that way. So, why not? Drupal 8 is slow. And, some poor web hosts might allow the public to read configuration files.

Early in the release cycle the install process was slow. So initially, moving configuration into the database made running the installer a bit faster. However, file-based configuration in the current release of Drupal 8 doesn’t make the installer visibly slower. So, this isn’t a problem for our workflow.

The second concern with file based configuration is the desire for security through obscurity. Since we are storing configuration outside the webroot, and our web server should also be configured not to display configuration files, this isn’t an issue.

Another concern was that file configuration might encourage people to edit their configuration. Since this workflow is for programmers, this is an advantage of our workflow.

Advantages of Database Config Storage

Storing configuration in the database on production has some minor advantages. So, leaving the configuration in the database on production is reasonable. Storing in the file system means you have to sync the file system in multiple web server environments.

Storing config in the database allows you to attach metadata to the configuration so that you can timestamp it, assign an owner to it and create a revision workflow for configuration.

How to Enable Config in Files

The easiest way is to use the Drupal8-base installer which will enable file storage for configuration out of the box. Alternatively, you can export your site configuration from the database and then follow these quick steps to enable file-based configuration storage on an existing Drupal site.

Jan 20 2016
Jan 20

These core concepts apply to Drupal 8 site builds. However, many often apply to the other major web framework from WordPress to Node projects. Many of these ideas are documented on Drupal.org as well. I’m rewriting them here because I disagree with the documentation in several key areas.

Use The Same Development Environment

Everyone on your team should have exactly the same development environment. Using the same development environment ensures that the project runs exactly the same for each team member working on a project. You can do this with Vagrant, Ansible, or a Brew script.

Backups? Put The Database in Code With CMI

Configuration Management in Drupal 8 allows you to quickly store database settings in code. Further, content should come from a single reusable source. We use Google Docs API, others use Profiler. The key is keep your test content in a shared, predictable place.

Drupal.org recommends that you backup your files and database. Since all of your code is on Github, and your database is in your code, Backups only matter in production. After a project launches, your hosting company should be providing backups. If your host isn’t taking care of this automatically for you, then switch to a web host like Pantheon, WP Engine, or Site Ground. All provide automated backups. Site Ground gives you per file recovery while Pantheon focuses on CMS backups for code/files/database in an easy to restore tool.

Never Hack Core (or Contrib)

Don’t change the framework. Instead, write your own code as a module. Pantheon, doesn’t follow this rule, and it creates a lot of extra work for them. But, they have an entire company of developers to maintain their fork of Drupal. The rest of us should stick to the official release. This is true no matter the framework you’re in. If you hack WordPress, your project will fail during automatic updates!

Use Test Sites

Your hosting company should be providing 2-3 sites for each production site automatically. If your hosting company doesn’t give you test sites, switch to Pantheon or WP Engine. You should make all your changes in your local environment first, test them locally, and then deploy them to test in production servers on a test server.

Use Configuration Before Code

Instead of hard coding a class or a snippet of logic into a theme, set these values in configuration and then apply the configuration with code. This allows your code to change in the future without being rewritten. This also leads us to choose high quality, well maintained modules to build our sites out of. Reusing code is one of the most basic steps in writing quality software because reusable code will have fewer bugs and more features.

Instead of writing a massive “glue” module, break up functionality into reusable modules and use configuration to apply advanced functionality so that each module is more powerful and easier to modify without rewriting the code.

Avoid Too Many (Poor) Modules

For those of us who work on large scale Drupal sites, we’ve learned that hundreds of modules can work together to produce an amazing, large-scale software project. When building enterprise Drupal sites, it’s more important to avoid using 1 poor module than it is to avoid 30 well built modules. This too many modules advice leads programmers to favor programming their own modules over reusing modules. However, avoiding contributed modules means you end up rewriting basic Drupal features in every new project.

This includes your custom modules

Drupal.org only talks about contributed modules, but this too many modules advice holds for custom modules as well. The more custom modules you write, the more work it takes to maintain and modify your website. Instead of writing a large collection of custom modules, or a single giant glue module, consider publishing your modules on Github. This will encourage you to create reusable code that has configuration needed to make them reusable and future proof.

Follow Coding Standards

You can automatically check and repair your code for Drupal with Code Sniffer.

Up next, controversial configuration practices for Drupal 8 that will improve your workflow.

Jan 20 2016
Jan 20

I’ve taught an beginners course during Drupal Global Training Days many times in portland, and I give students an introduction to Drupal 8 for site builders. I spend the day simplifying Drupal for new developers. But once you’re beyond the basics of the interface, there are many different ways to accomplish a task in Drupal and Drupal 8 only adds to the choices. So, if you’re a Drupal developer looking to craft easier to maintain Drupal 8 sites, this series is for you.

Over the years I’ve developed many strong opinions about the best way to “drupal”. Some of my decisions aren’t actually better than alternatives, but they are patterns I’ve memorized to make my work more efficient so I can avoid getting stuck building sites. This series will cover the following topics:

And, if you don’t want to wait for me to write and publish all these best practices, feel free to join me in this Gist for a sneak preview without the explanations.

May 28 2015
May 28

WordPress vs Drupal

Dries, the creator of Drupal recently started a conversation about WordPress vs. Drupal. This is the first time I’ve read a great discussion about the pros and cons of each platform. John Eckman, the founder of one of the best WordPress agencies responded well on his blog.

John’s experience with the two communities seems similar to my own because I’ve also been an active participant in both communities. In fact, 3 years ago, I considered myself a WordPress expert. Over the past 3 years, I’ve become a Drupal person because, unlike John, I work for a leading Portland Drupal agency. I know I can build anything in WordPress. But, there are pros to both platform that leads me to choosing one or the other for specific projects. The truth is, both platforms are amazing for making websites.

  • 1 click upgrades. This feature dramatically reduces the cost of ownership and my boredom.
  • Blazing fast performance on uncached pages.
  • Commercial module support. The premium model for WordPress drives a lot of revenue for their ecosystem.
  • Monolithic, Microsoft-like project structure. I can predict your WordPress database without even seeing it.
  • Comment spam protection.
  • The Loop. The WordPress loop makes it very easy to do certain things fast.
  • Out of the box editor experience that’s the same on every site.
  • Easy to use drag and drop widget system for sidebar blocks.
  • Massive contributed module community with many developers per module.
  • Advanced search experiences with Solr.
  • Editorial multistate workflow moderation.
  • Group based permissions on content where users can create, moderate, and join their own groups.
  • Data modeling and list creation is straight forward and expected.
  • Responsive design support including completely adaptive AJAX driven pages.
  • Easy issue queue support with a patch management workflow. If it’s broken, I can snag the fix on D.O.
  • Modular permissions and caching for logged in users in Core.
May 01 2014
May 01

Devsigner is celebrating the cross-overs, the multi-disciplinarians, the coders who paint and the designers who send pull requests — and those who want to develop some new left-right brain skills.

We’re looking for folks to break out of their familiar meetup silos and apply their knowledge across the crafts of development and design.

Join me at Devsigner in Portland, Oregon, May 23-25!

Tickets are now on sale, and session submissions are open until this Friday, May 2!

Sessions will include things like:

  • responsive web development for graphic designers
  • color theory for coders
  • industrial design for web apps
  • why bad user experience is a bug
  • what web technologies can learn from analog design
  • iterative design in open-source communities
  • your great idea — submit a session now!

We’re going to mix it up with a variety of session formats:

  • Traditional presentations (45-60 minutes)
  • Panel and roundtable discussions (45-60 minutes)
  • Hands-on, deep-dive workshops (2 hours Friday, 3 hours Saturday and Sunday)
  • Lightning talks on Saturday night (more information to come)

We’re also kicking off the event with a keynote presentation from a surprise guest!

Who should attend?

  • graphic designers who want to hone their web design chops
  • developers who want to the beauty of their projects to match the beauty of their code
  • artists who are tired of ugly or unusable websites
  • branding experts who want to tell developers a story about the cobbler’s children
  • Sass/Puppet/Angular/Grunt/Node evangelists who want to spread the good word
  • you!

I hope to see you there!

Thanks to RootWork for the post.

Jan 19 2014
Jan 19

Steve Sounder’s is an authority on web performance. He writes about everything from front end performance to browser performance. As a front end developer, it’s easy to get lost in tasks that don’t matter. There’s a saying in software development, “Don’t optimize until you need to.” In frontend development, that doesn’t apply because we don’t write complex algorithims. But, it’s important to make sure we focus our time and attention on the right stuff. So, what is the right stuff.

The best practices to focus on as a front end developer are the ones that have the most impact on site performance and user preception. To that end, here’s 4 topics that you should put special effort into:

  • Prevent jerky, flashy page loads. Restyling content after page loads is annoying and interrupts reading content.
  • Javascript, CSS and images should be minimised and compressed.
  • Images should be responsive and only as large as they need to be.
  • JavaScript and third party content should only load as needed and shouldn’t cause your site to fail or delay.

CSS at the Top

Load CSS at the top of head and JavaScript at the bottom of body. Putting all your CSS in a file at the top of the document prevents any unstyled elements from loading. Avoid inline CSS and printing CSS in JavaScript. Lastly, put your JavaScript in the footer so visitors can read the content of your website while your scripts are loading. If you can’t put your animations in the footer, use a loading graphic.

Prevent Flash of Unstyled Text

Preventing FOUT is a quick and easy win. Firefox and Internet Explorer both do a terrible job loading @font tags. These browsers cause the original unstyled text to flash, sometimes for a couple of seconds before the page is redrawn. This affect can even break your layouts on a page that uses thin custom fonts. All that’s needed is adding a bit of JavaScript when you include custom fonts:

Grunt to Compress, Minify and Optimize

Grunt automates your workflow so that you never forget to put your SASS into production mode again. It allows to string together tools so you can combine, minify, and compress your static files, and optimize your images. You just type Grunt build and Grunt works it’s magic. These tools can easily save you 500KB on a large project.

Responsive Images Done Well

If you’re loading a 1400 pixel hero image on a 320 pixel smart phone, your page load is going to suck. Instead, use tools like Borealis or Picture to load the best size image for the visitor. Converting a slide show to responsive images can easily save 400KB. That’s a huge win.

Prevent Single Point of Failure

Modern websites almost always include JavaScript from Facebook, Twitter, Google, LinkedIn, AddThis, Discuss and other sources. If done incorrectly, these third party scripts can each cause your page to white screen. To avoid this is simple. You should always use asynchronous snippets. If you don’t have an Async snippet, then place the JavaScript just above the footer.

CDN Saves the Day

If you use Cloud Flare as a free content delivery network, Cloud Flare will compress and minify all your code and html. It will combine all your CSS and JavaScript and it will asynchronously load all of your JavaScript. All you have to do is set up Cloud Flare which takes only a few minutes. When you do switch to CF, you’ll want to exclude your web font loader and any other critical javascript from the “Rocket Loader” so it doesn’t get loaded last.

So, load your fonts well, clean up your code, correctly load images, and move all your JavaScript to the footer, or just use Cloud Flare and forget about performance.

Aug 27 2013
Aug 27

Using AJAX to update a Drupal 7 form could be easier. The documentation on this feature is extremely verbose, and I had a difficult time piecing together a working example. So, here’s the code to modify the values of a second field when the value of the first is selected. The code below will use the taxonomy_voc drop down to control the product model drop down values. This code does not work with field widgets that define their own AJAX.

Wrap the field that’s being controlled and add the callback and wrapper to the controller field.

Thanks to Anne Sturdivant for her assistance in writing this code.

 *  Implements of hook_form_alter() to update a field via AJAX.

function hitachi_module_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    case 'contact_us_entityform_edit_form':

    // Wrap the field that being controlled
    // Add the callback and wrapper to the controller field

    // Create a wrapper for the AJAX callback to populate the model
    $form['field_product_model']['#prefix'] = '

'; $form['field_product_model']['#suffix'] = '

'; // If we are editing an existing form, we already have the values if (!empty($form['taxonomy_voc'][LANGUAGE_NONE]['#default_value']) || isset($form_state['values']['taxonomy_voc'][LANGUAGE_NONE][0])) { $form['field_product_model'] = _hitachi_set_model($form, $form_state); } // Create an AJAX callback. This is the magic bit that does all the AJAX. $form['taxonomy_voc'][LANGUAGE_NONE]['#ajax'] = array( 'callback' => '_hitachi_set_model', //Must match the function name below 'wrapper' => 'hitachi_wrapper_type', ); } } /** * AJAX callback to grab all the nodes with a given term. * */ function _hitachi_set_model($form, $form_state) { if (!isset($form['#after_build_done']) && isset($form_state['triggering_element'])) { $product_types = array_keys($form_state['triggering_element']['#value']); // Populate all the product models with all the product titles from that division. foreach($product_types as $product_type) { $entities = _hitachi_module_get_nodes_from_tid($product_type); $nodes = node_load_multiple(array_keys($entities['node'])); foreach($nodes as $node) { $title = entity_metadata_wrapper('node', $node)->title->value(); $key = preg_replace('/[^a-z]/i','', strtolower($title)); $form['field_product_model'][LANGUAGE_NONE]['#options'][$key] = $title; } } } return $form['field_product_model']; }
Jul 11 2013
Jul 11

Have you ever had a client ask for everything to be red? Or perhaps it was auto playing audio on every page load? Well, check these awesome sites out.

Portland is a Drupal epicenter. The Drupal community comes together strongly in many places around the world and Portland’s Drupal User Group is no exception. Once a month we gather for conference quality presentations about all sorts of advanced Drupal topics. Last night our fantastic host, Jason, Yee (JYee) did something different. He had us break into 7 teams with the goal of using 4 specific modules to produce a website that’s awesome in 1 hour. The competition was stiff. Everything from advanced working, feature-complete Drupal builds to sparkles that actually sparkled. I appologize now if any of these screen shots make your eyes water.

Tweet with us at #pdxdug.

We ended up learning a lot about Flags and Rules. I had the luck and privlege of project managing a 1 hour project for an amazing Drupal team:

@illepic – Chris Bloom, Drupalist at Superstar Media
@mpgeek – Eric Paul, Drupal developer at Open Sourcery.
@mikey_p – Michael Prasuhn, 1⁄2 of Shomeya

The Awesome Websites


modules: bad judgement, fivestar, userpoints
alt/bonus module: webform


modules: nodequeue, privatemessage, viewfield (or eva)
alt/bonus module: webform


modules: field collection, flag, userpoints
alt/bonus module: views_field_view


modules: better exposed filters, fivestar, rules
alt/bonus module: webform


modules: bad judgement, flag, message
alt/bonus module: userpoints


modules: field collection, message, privatemessage
alt/bonus module: rules


modules: field collection, message, nodequeue
alt/bonus module: privatemessage

Special thanks to O’Rielly, Drupalize.me, and Lullabot for sponsorship that included beer, pizza, coffee cards and an OScon pass! My group ended up winning, but all the sites are awesome. So, I’ll leave it up to you to guess which one was ours.

Jun 26 2012
Jun 26

So, I’d like to stop using waterfall development for Drupal projects. The first step is to teach myself to be a good advocate for something different… Started way back in the early 90′s was a thing called scrum… It really is very different. Here are some resources that don’t suck.




Not all positive:


It’s funny, when I got a computer information systems degree, we all laughed about waterfall development. But, client’s demand fixed bids! Can you be agile with a fixed scope, budget, and timeline?

Jan 01 2001
Jan 01


grep 'DocumentRoot' /etc/httpd/vhost.d/* | awk {'print $2;'} | xargs -I {} nice find {} -name CHANGELOG.txt > ~/drupal-sites.txt

Produce clean report:

cat ~/drupal-sites.txt | xargs head -n 3 > ~/drupal-sites2.txt


grep 'DocumentRoot' /etc/httpd/vhost.d/* | awk {'print $2;'} | xargs -I {} nice find {} -name readme.html > ~/wp-sites.txt

Todo: Add string to pull WordPress version with pretty formatting.


nice find -L /vol/www/ -name 'PKG-INFO' | xargs grep '^Version:' > ~/django-sites.txt
Jan 01 2001
Jan 01

I’m in the process of migrating an old PHP website for Portland State University from a custom database into Drupal 7. Doing the data entry on hundreds of nodes with multiple custom fields, taxonomies, and images would have taken ages. So, instead I imported the data into Drupal with a PHP script. At first, I attempted to use phpMyAdmin, to export a CSV, and then import the CSV using the Feeds module. However, the feeds module for Drupal 7 doesn’t seem to do field matching well, and I couldn’t get the taxonomies or images to import correctly. So, with the help of my intelligent coworker, I decided to use Drush to execute a PHP script that will import the content. The process wasn’t hard for a PHP programmer, but all the directions I found on other blogs were either confusing me, or missing a few steps. Mainly the examples were missing the code to insert dynamic data from a database in a loop.

This being my first Drupal 7 project, I had a lot to learn about new Drupal features. Don’t worry, I’ve attached the code, so you can cut and paste my hard work.

Import content into Drupal 7

  1. Create the taxonomies and terms that you will need. This can be done with a script, but most websites don’t have that many categories.
  2. Create a content type for the nodes and include all the custom fields you will need. Be sure to include term reference fields for each taxonomy from step 1.
  3. Install Drush and get “Drush help” to work.
  4. Create a PHP script, and execute it with drush php-script (script name)

Drush is nifty because it loads the Drupal environment and allows you to access Drupal’s functions. This saves you from having to figure out where to insert all the node data manually.

Connect to the database and get content

// My source data was not normalized. All data was in 1 table! Lucky me. No joins.

$query = 'SELECT * FROM `tb|record`';
$result = db_query($query);
$i = 20;
foreach ($result as $row) {

Most of what Tim wrote worked perfectly, but here’s what Tim has to say about assigning content to categories…

Add a term to a node

$node-&gt;field_tags[$node-&gt;language][]['tid'] = 1;
‘field_tags’ here is the name of a term reference field attached to your content type, ‘1′ is a term id you wish to assign to a node. Simple!

Now here’s the code I actually used to insert my content into a category. It wasn’t simple:

 if ( $term = taxonomy_get_term_by_name($row-&gt;culture) ) {
$terms_array = array_keys($term);
$node-&gt;field_culture[$node-&gt;language][]['tid'] = $terms_array['0'];

If you review my code, you’ll notice that I failed to get my loop to read and load the taxonomies from the database, so I added them one a time. If anyone can figure out the syntax error in the block of code that’s commented out, that would be awesome. Contact me, and I’ll give you credit. But, I doubt many sites have more than a handful of categories.

The script took me about 10 hours to perfect after I threw away 2-3 different methods. Hopefully, you can copy this script and get your site converted over to Drupal in much less time.

The Full Source Code


function cm_load_rep_data( ) {

// My source data was not normalized. All data was in 1 table! Lucky me. No joins.
$query = ‘SELECT * FROM `tb|record`’;
$result = dbquery($query);
$i = 20;
foreach ($result as $row) {
$node = new stdClass(); // We create a new node object
$node->type = ‘piece’; // Or any other content type you want
$node->title = $row->subject;
$node->language = LANGUAGE_NONE; // Or any language code if Locale module is enabled. More on this below *
$node->uid = $i; // Or any id you wish
$url = str_replace(” “,””,$row->subject);
$node->path = array(‘alias’ => $url) ; // Setting a node path
node_object_prepare($node); // Set some default values.

//grab the file for this node based on the “schema” from the old website…
$file_path = ‘/home/gboggs/Images_data/’
. $row->collection_alias . ‘/’
. $row->collection_alias . $row->accession_no . ‘.jpg’;

if (file_exists($file_path)) {
$file = (object) array(
‘uid’ => $i ,
‘uri’ => $file_path,
‘filemime’ => file_get_mimetype($filepath),
‘status’ => 1,
$file = file_copy($file, “public://”);
$node->field_image[LANGUAGE_NONE][0] = (array)$file;

// Grab the body content. My database had the body content repeated. You don’t need this piece.
if (!isset($row->long_des) || $row->long_des == null) {
$body = $row->short_des;
} else {
$body = $row->long_des;

// Insert the content into the node
$node->body[$node->language][0][‘value’] = $body;
$node->body[$node->language][0][‘format’] = ‘full_html’;

// Let’s add some CCK fields. This is pretty similar to the body example
$node->field_collection_number[$node->language][0][‘value’] = $row->accession_no;
$node->field_dimensions[$node->language][0][‘value’] = $row->dimension;
$node->field_date[$node->language][0][‘value’] = $row->date;
$node->field_artist_author[$node->language][0][‘value’] = $row->artist;
$node->field_provenance[$node->language][0][‘value’] = $row->provenance_prior_pub;
$node->field_details[$node->language][0][‘value’] = $row->object_details;

/* This doesn’t execute, and I couldn’t figure out why in < 10 minutes. so doing it the long way.
$categories = array(‘field_culture’ => ‘culture’,
‘field_medium’ => ‘medium’,
‘field_time_period’ => ‘time_periods’,
‘field_collection’ => ‘collection’,
‘field_theme’ => ‘theme’);
foreach ($categories as $field => $category) {
$term = taxonomy_get_term_by_name($row->$category);
$node->$field[$node->language][][‘tid’] = $term->tid;

// The long way to check taxonmy terms and add them to the node.
if ( $term = taxonomy_get_term_by_name($row->culture) ) {
$terms_array = array_keys($term);
$node->field_culture[$node->language][][‘tid’] = $terms_array[‘0’];

if ( $term = taxonomy_get_term_by_name($row->medium) ) {
$terms_array = array_keys($term);
$node->field_medium[$node->language][][‘tid’] = $terms_array[‘0’];

if ( $term = taxonomy_get_term_by_name($row->time_periods) ) {
$terms_array = array_keys($term);
$node->field_time_period[$node->language][][‘tid’] = $terms_array[‘0’];

if ( $term = taxonomy_get_term_by_name($row->collection) ) {
$terms_array = array_keys($term);
$node->field_collection[$node->language][][‘tid’] = $terms_array[‘0’];

if ( $term = taxonomy_get_term_by_name($row->theme) ){
$terms_array = array_keys($term);
$node->field_theme[$node->language][][‘tid’] = $terms_array[‘0’];

$node = node_submit($node); // Prepare node for a submit
node_save($node); // After this call we’ll get a nid

// printing from Drush is easy
drush_print( $row->subject . ” added.\n” );

Jan 01 2001
Jan 01

Internet Explorer is often the bane of a web designer’s existence. Creating a design in Firefox or Chrome is easy, if something is off, click “inspect element” and you can fix the problem inminutes. However, in Internet Explorer, there’s no such tool. Well, I had an issue with JQuery not displaying correctly on a Drupal site in IE7. It worked perfect in 8, Firefox, and Chrome. The demos for all the plugins I was using worked perfectly in Internet Explorer 7, but when I loaded them on the Drupal site, they were hosed. I checked the code over, and over, and over again. I have my reservations about Drupal. I hate how it creates so many external files, and how many “Gotchas” it has. I knew this had to be one of those weird Drupal quarks.

Optimize CSS Files

After hours of frustration trying to get JavaScript to run, I opened the CSS file for IE in Drupal:

  • CSS targeted specifically for Internet Explorer for Windows.
  • Any CSS in this file will apply to all versions of IE. You can target
  • specific versions of IE by using conditional comments. See your sub-theme’s
  • .info file for an easy way to use them.
  • While building your theme, you should be aware that IE limits Drupal to 31
  • stylesheets total. The work-around for the bug is to enable CSS aggregation
  • under: admin / settings / performance.

I turned CSS caching on and all my JQuery started working perfectly! I had overrun the limit for maximum allowed external files in IE7! How can Drupal possibly include more than 31 external files? Man, Drupal is insane. It’s loading 2 files for every plugin I need. Anyway. Mystery solved. If you can’t get JQuery, or CSS to work in Drupal on IE7, optimize your CSS files and see if that fixes all your problems.

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web