Upgrade Your Drupal Skills

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

See Advanced Courses NAH, I know Enough
Jan 13 2021
Jan 13
If it is the top level menu, we print a
    and we pass Drupal’s attributes in addition to our custom classes.</li>
  • If menu is not top level (submenus), then we simply print a
      with its corresponding class.</li>

Learn more about Macros in Twig Templates.

Looping Through the Menu Tree

Looping through the items array allows us to intersect each item and apply classes or attributes.

  • First, we loop through the items array (for item in items), and for each item, we print a
  • to which we pass an array of CSS classes using attributes.addClass() method.  However we do this only if we have access to Drupal's attributes ({% if attributes %}).  If not, we manually print the same classes on the list item. 
  • For each item and link, we pass a series of things such as:
    • The link title
    • The link url
    • Is the link in the active trail,
    • ... and others.
  • Inside the list item, we check to see if that particular item has other items or submenus({% if item.below %})
  • When submenus exist, we make use of the macro again to repeat the process of printing the menu. This is where the macro saves us from writing duplicate code.
  • For each level of submenus we are increasing the menu_level by 1 and printing it as part of the submenu class. This is handy if we want to target a specific submenu in the tree.
  • Finally, we close all previously open actions/tags (i.e. for loops, if statements, lists, and macro).

RESOURCE: I recently ran into a blog post by Tamas Hajas where he has a great way to address classes and states on a menu. Check it out: Drupal 8 Twig: add custom CSS classes to menus

Looking at the Rendered Menu after Macro Improvements

Now that we have a better understanding on how the macro works, and after making the improvements discussed above, the markup for the menu would look something like this:
Example of menu with good markup.

These styles are as bare as possible. They are simply to make the menu look presentable and could use a lot of improvements. This is what the multi-level menu looks like:

Example of an expanded menu

Create a Twig Template Suggestion for the Main Menu

Our ultimate goal is to update Drupal’s menu system to render using the navigation component. 

Follow these steps to enable Twig Debugging in your theme. Then, you can inspect your site, which will allow you to see the various template suggestions that Drupal uses to render the page; including your navigation menu. The debug information looks like this:

Example of twig debugging code.

Under File Name Suggestions notice two template names: menu.html.twig & menu--main.html.twig. The X next to menu.html.twig indicates Drupal is using this file to render the Main Menu. The second file, menu--main.html.twig, is what Drupal is suggesting we create if we only want to alter the Main navigation and not other menus.  The word "main" in the file name represents the Drupal machine name for that menu.

Under Begin Output notice the path where menu.html.twig can be found, the example above is pointing to Drupal’s stable theme.

To ensure we only affect the main menu and not other menus on our site, we are going to make a copy of Drupal’s menu.html.twig in our theme and then override it. This is recommended rather than modifying Drupal core’s template. Let’s start:

  1. Copy the menu.html.twig template from core/themes/stable/templates/navigation/ into [site_root]/themes/custom//templates/navigation/menu.html.twig (if these folders do not exist yet in your theme go ahead and create them).
  2. Following the golden rule “Never hack core”, we want to make a copy of Drupal’s menu template in our own theme. Replace the core theme’s name with your core base theme if you are not using stable.
  3. Next, In your theme rename the newly copied template to menu--main.html.twig.
    Copying menu.html.twig into our theme will affect other menus. This is why we are renaming the template so it only affects the main menu (menu--main.html.twig). Replace ‘main’ with whatever your menu’s machine name is if you are not using Drupal’s Main Menu. This can be found in Drupal’s Menus page (admin/structure/menus).,>
  4. After clearing Drupal’s cache, inspect the menu again and you should see the X next to menu--main.html.twig which means Drupal is now using our custom twig template suggestion to render the menu.

Create a Multi-level Menu in Drupal

  • Let’s make sure we have a menu we can see in Drupal. Let’s create a multi-level menu using the Main Navigation menu (Structure | Menus | Main Navigation).
  • Add as many links as you wish. Be sure to add nested items so we end up with a multi-level menu.
  • In addition, ensure each of the submenu’s parent links are set to “show expanded”. You will see the option on the Add/Edit Link page.
  • Finally, go to Structure | Block Layout and click Configure next to Main Navigation
    • Change Number of levels to display to Unlimited. This will ensure dropdowns are rendered and display in your navigation.

Integrate the Main Menu component with Drupal’s Menu

The last part of the process is to integrate all the work we’ve done with Drupal, so our Navigation is rendered with the markup, styles, and behavior we implemented when we built the component.  

  1. In your editor, open [site_root]/themes/custom//templates/navigation/menu--main.html.twig
  2. Delete all the content in the twig template except for the comments, and then paste the code below into it
{% include '@your-namespace-here/navigation/navigation.twig' %}
  1. Clear Drupal’s cache
  2. Reload Drupal’s page

Since we moved the macro to the component’s location, all we need to do in the menu--main.html.twig template is to call our Navigation component by using a Twig include statement. 

If we did our job right, Drupal’s menu should now look and behave the same way as our component. In addition, if you inspect the Drupal page, the menu should reflect the same markup as the main-menu component.

Drupal Libraries

As a best practice, we should create a drupal library to attach any styles and javascript to our component. See this article for adding CSS and JS to a page or component.

If your navigation is displaying unstyled that's because a Drupal library does not exist.  Create one as follows:

navigation:
  css:
    component:
      dist/css/navigation.css: {}

Your compiled css path may be different.

This library has already been attached above inside navigation.twig

By doing this any styles we wrote for the component will apply to the main navigation when it’s rendered in Drupal. Drupal libraries have no effect in Pattern Lab.

After completing the steps above, clear your Drupal’s cache and reload your Drupal site. You should see your Drupal menu being rendered with all the styles and markup we wrote throughout this post,

What about Accessibility?

You should always ensure your menus and navigations are accessible. It is the right thing to do. However, don't yell at me for not following my own advice. In an effort to keeping this tutorial simple, I opted to omit anything related to accessibility. Perhaps part two can focus on that ;-)

Video Tutorials

[embedded content]

[embedded content]

In Closing

I’d like to admit that I went about the long way to get the main menu working on both, Pattern Lab and Drupal. There are other ways to accomplish this by using contrib modules such as Simplify Menu (full disclosure, I am a co-maintainer of the module), and perhaps Twig Tweak among several others, however, the approach I took here gives you the most control and that can make all the difference if you are dealing with a pretty advanced or complicated menu.

Dec 18 2020
Dec 18

Rain logo updated

The Mediacurrent team is proud to introduce the latest version of our open source Rain CMS, now for Drupal 9. The latest version ships (currently in beta) with a brand new theme and admin experience. Make your move to Drupal 9 with speed and confidence. 

The New 'Nimbus' Theme

Homepage design for Mediacurrent's Rain CMS for Drupal 9 Nimbus theme

New Rain CMS theme homepage

The new base theme comes with a full Pattern Lab style guide to make development easier using a component-based theming approach. The new Rain CMS theme also adds color module support for in-browser color configuration. We wanted a great out-of-box experience for content authors and administrators so we pre-load the site with sample content to make it simple to get started.

Rain Admin 2.0

Rain CMS for Drupal authoring experience with jump navigation to manage page components

Rain CMS admin content edit page

With the latest version of Rain Admin, the content editing experience is more intuitive to use. A jump-navigation on the right-hand side helps authors move between different sections of the page. The UX for Paragraphs has also been improved to make it visually easier to manage components on the page.

Let’s Get Started

For developers, you can download and install Rain CMS 9 using our Drupal project template: https://bitbucket.org/mediacurrent/drupal-project/src/9.x/. Setup and installation remain the same as our previous version, with detailed instructions provided in the project README file.

For more information on the benefits of Rain CMS D9 and to schedule a free demo, please visit our contact page or chat with us right now (see bottom right corner of the page). We would be happy to talk more about your project or schedule a demonstration.

Nov 09 2020
Nov 09

[embedded content]

Sarah Durham (00:02):

Hey everybody. Welcome to today’s webinar. I am Sarah Durham, and I am going to briefly introduce my colleagues. They will talk a little bit more in a minute and also we’d love you to introduce yourself as people start to arrive. If you are comfortable doing so, you’ll see a chat panel. And if you could chat in to us your name, the name of your organization, your pronouns, and where you are, where you are geographically, so who you are and where you are, would be great. Theresa, you want to say hi. 

Theresa Gutierrez Jacobs (00:50):

Hi, I’m Theresa Gutierrez Jacobs. I am a project manager at Advomatic. And for today, I’m going to just quickly chat my email. If you have any, I don’t know, tech issues or questions or anything like that, that is more tech related to this webinar. Feel free to reach out to me via my email. Otherwise, you can always chat or ask questions, particularly for this webinar here. And Dave, you want to say a quick hi, before we get rolling.

Dave Hansen-Lange (01:18):

Hello. I’m Dave Hansen-Lange and where I am, I’m about an hour from Toronto. I’m the director of technical strategy at Advomatic. I’ve been with Advomatic for about 13 years. And I’ve been doing work with nonprofits in the web for maybe about 15 or 17 years.

Sarah Durham (01:42):

Okay. So we’ve got a bunch of people who are already with us, a few more people who might join us in the next couple of minutes, but just to keep the ball rolling and use your time thoughtfully, we’re going to dig into our content for today. And as I said a little bit earlier, I will reintroduce myself. I’m Sarah Durham, I’m the CEO of Advomatic and also Advomatic sister agency, Big Duck. Some of you may have noticed that the Zoom we’re using today is a Big Duck/Advomatic shared Zoom. So if you’re wondering what the connection is, there’s some common leadership across both companies. For those of you who might know Big Duck, but don’t know Advomatic, Advomatic builds sturdy sites that support change. We build, and we support websites in Drupal and in WordPress. And Advomatic has been around now for, I think almost 15 years, although it’s partnership and collaboration with Big Duck and my coming into the company is relatively new.

Sarah Durham (02:43):

It’s about, I’ve been in it about two years. And so Dave is going to really take us through our topic today. And Dave, you could advance to your next slide, if you would like, which is this, what should you do with your Drupal 7 website? So Dave’s gonna talk us through why this is an issue and a few other things in a minute. What I am going to do throughout this conversation is I am going to be monitoring both the chat that you can see in the bottom of your screen, a little button that says chat. And if you click on that, you have the ability to either chat privately to the panelists. So if you want to ask a question confidentially, or you don’t want everybody who’s here to see it, just chat to the panelists and only Dave and Theresa and I will see it.

Sarah Durham (03:26):

If you want to chat to everybody and share who you are, like shout out to Rick, who’s already done that. He’s from the National Council of Nonprofits and he’s in the DC area. If you want to share your information with the panelists or to everybody, you can chat to all attendees. Also, you have the ability to specifically ask questions. There’s a Q&A feature in Zoom Webinar. And that will give me the ability to keep an eye on your questions. And some of them I can type back to you and others will be addressed verbally. So throughout the presentation, I’ll be monitoring all of that and we will address your questions perhaps as we go on, certainly at the end if it doesn’t make sense to do so in the webinar. So don’t hesitate to chat, don’t hesitate to ask questions. We are recording today’s session and Theresa will be sending out an email with a link to that recording and the transcript and the resources we’re mentioning later this week or early next week. So you will have all of this and you can share it with any colleagues if that is useful. So with that, we are going to get rolling over to you, Dave, and thanks, Theresa.

Dave Hansen-Lange (04:44):

Okay. Thank you, Sarah. All right. So to kick things off before we get into the details of all the different things that you can do with your website and what might be best for you I thought we should start with some backstory about like, why we’re at this spot and like, what does end of life even mean? Like, it’s software, how can software… and it really all comes down to security. And just to explain a little bit about how security in Drupal works, there is the Drupal security team, and that’s a team of about a dozen people all across the world. And then there’s a group of people even wider than that who contribute things to the team and say, Oh, this could be a problem. We should look into this. And people on the security team, you know, a lot of their time is paid for by their employers or their clients, but a lot of their time they’re just volunteering for free.

Dave Hansen-Lange (05:50):

And you know, there’s a lot of commitment there. Like, they have weeks on call and stuff like that, because security is very important to the Drupal community. And so we don’t want to have those people working forever for free. So the Drupal community at large has decided, okay, thank you for your time of service, people on the Drupal security team, we will let you go after this date. Some of those people work on AAA too. But people are generally committed for like Drupal 7. And so the original date for the end of Drupal 7 was going to be November, 2021. But then COVID happened and the Drupal community decided, okay, there’s this extenuating circumstance. We’ll give everybody one more year to figure out what they’re going to do. So now that the end of life date for Drupal 7 is November 2022, two years from now. 

Dave Hansen-Lange (06:56):

Drupal 8, just as an aside, it’s not really what we’re talking about today. Drupal 8, the end of life is November 2021, a year from now. That’s not what we’re talking about today. And thankfully, if you do have any AAA sites, the situation is a lot simpler. And if you want to get into that a little bit more possibly we could at the end of the presentation. Okay. So today we are going to first cover: these are the options that you have in dealing with your Drupal 7 websites. Then we’re going to look at some example scenarios. And by that, I mean like, okay, here’s an organization, they have a website like this, and because of that, they might consider scenario x. And then I’m going to pass things over to Sarah. And Sarah is going to dive into more of the organizational things, like, how do you plan for this and how do you work with this within your organization? All right. 

Sarah Durham (08:15):

Hang on one second, Dave, before we dig into this, I also just want to remind everybody feel free to chat in questions and comments as you go, and we’re going to take pauses in between each of these sections. So if you have, as Dave goes through the options, if you have a specific question about one of the options, and it seems like it’s universal to some of the other people who are participating today, I’ll probably pop in and ask that otherwise we’ll save Q&A for the end. Alright, sorry for the interruption.

Dave Hansen-Lange (08:41):

No, no, all good. I’m also going to be muting every now and then to take a sip of tea. I’ve got a sore throat. It’s not, COVID, it’s just a cold. And yeah, so I’ll be pausing too, as I go. Okay. So what are your options? So I’ve grouped these into four main options, and these are listed in terms of most expensive, to least expensive, most expensive option being start from scratch and build a new website for most people with a Drupal 7 website your main options are move to Drupal 9 or create something in WordPress. There’s some other options that you might consider, but those are the two that are applicable to most people. Option B is upgrade to Drupal 9 and immediately you’re probably thinking what is upgrading to Drupal 9? How is that different from building a website and Drupal 8? And I’ll explain that when we get there, another option is to switch to something called Backdrop. Many of you have probably never heard of Backdrop. And so I’ll start us out by what exactly that means. Or you could just stay on Drupal 7. And even though it has end of life, that there still are ways to keep going on, on your Drupal 7 website.

Dave Hansen-Lange (10:15):

So moving to a new website like I mentioned the main options for most people are Drupal 9 or WordPress. And so just by saying those two names in the same sentence, we immediately get into the topic of like what’s better Drupal or WordPress and what is right for me? I will touch on this a little bit now, and sort of back up a little bit and say that for starters, it’s really hard to make an unbiased and fair assessment of the two. But in a general sense, Drupal 9 is really great for people that, or on websites and organizations that want to do something a little bit more complicated, a little bit more ambitious, a little bit more technological, with more moving parts. And WordPress is generally more applicable to the organizations whose website, in many ways might be similar to other websites. And yeah, that is a little bit vague. I don’t want to dive too deeply into this topic right now. 

Dave Hansen-Lange (11:54):

If you want, we can come back to this in the Q&A at the end. And we also have another webinar that we did a couple months ago on this topic more generally. And if you’re just, if you can, we can send along a link to that as well. One last thing on this, though, I will say that when most people compare Drupal and WordPress, they’re not really comparing Drupal and WordPress, they’re comparing the website that someone built for them in Drupal or the website that someone built for them in WordPress. And because of that, they’re often comparing the skills of those people who built the website and not necessarily the underlying technology. And that’s part of the reason why this is such a sticky, thorny issue with a lot of people being on one side or the other there about moving to a new website. You don’t have to do the whole entire thing. You can find ways to do this in bits and pieces. I’ll show some examples of that later, but we’re at this point of rethinking what should we generally do with our Drupal website. It’s a great time to think, okay, this section, do we need it anymore? Should it be here? Is there a better way to do this then when we created this website however many years ago?

Dave Hansen-Lange (13:30):

Since many of you may not have seen modern Drupal I’m going to show you, or we’re pressed, I’m going to show you some slides here. So on the left, what we see is I am editing a page on a website and I want to add a new component which is a common term that we use these days, a new component to the page. I can browse through this library of available components and then add one.

Dave Hansen-Lange (14:00):

Or how it’s going to appear on the page. There’s many ways to do this in Drupal. Drupal is kind of known for having many ways to solve a problem. What we see in this screenshot is a tool called paragraphs. That’s a tool that we’ve been using for this problem pretty successfully on several websites. There’s other tools within Drupal 9. You may have heard the term layout builder and there was a couple of smaller ones as well on the right side. We see the administrative listing of all the content on your website for each site, it’s going to be a little bit different, what you decide to list here. But this is just one example of how it looks and comparing this to WordPress on the left. This is also how WordPress looks when you want to add a new component to the page. And so the right column there, we see, the available components that you have, again, on the right, a screenshot that’s WordPress of a list of all the content on the website.

Dave Hansen-Lange (15:20):

Looking at these two sets of screenshots, there’s a couple things that might sort of immediately come to mind. WordPress, the administrative interface generally looks a little bit more polished.

Dave Hansen-Lange (15:39):

In some ways WordPress can be a little bit all over the place in that each plugin or each new thing that you add to your website tends to design things its own way and do its thing its own way and it’s WordPress. Compared to Drupal, each new thing works in a very consistent manner. So it’s easy to move around from section to section on the website. All that to say is really either is probably a big step forward from where you are with your Drupal 7 website.

Dave Hansen-Lange (16:18):

All right, so which Drupal 7 website is this going to be most applicable to, or maybe you shouldn’t at all consider this option? If you are really frustrated with any part of your website, be that like how the content of this is organized, or just the general backend experience the design of the website, if there’s anything about it that you’d just want to just toss and start again fresh, this is a good option to consider. But like I mentioned, when I listed these four main options, creating a new website is going to be the most expensive of the options. And in the age of COVID, many of you are probably dealing with some tight budgets. So one of the other options may be the better choice. Also, this might not be a good choice for you if your existing site is very complex. And one way to think about this is like you built your website so many years ago, let’s say it was five years ago. And you put all this work into doing that initial build, but then over those five years, you’ve also put in some work, to make the website more and more better. And in this new version of the website that you’re gonna create, you want to encompass all of that. 

Dave Hansen-Lange (17:52):

It’s going to be a pretty big project. And so it’s just one way to consider looking at your options.

Okay. Option B, I don’t have a handsome, single flat you can upgrade to Drupal net. So how is this different from just creating a new websiteIn AAA? Drupal 9 has these built-in tools that can take your Drupal 7 website and take all those, all that content, all the content structure all the menus, everything that’s stored in the backend of the website and upgrade it and make it work in a new Drupal 9 website. But what you don’t get is any of the, how that content is presented to visitors, all of that stuff. If you go through this upgrade process, you still need to come up with or you still need to rebuild the way that it’s presented to visitors. Maybe, maybe you’re happy with the design of your Drupal 7 website. And so you can just redo that same design in Drupal 9 or another option since we’re here and we’re creating a new website and Drupal 9, you might want to take advantage of that and do a new design.

Dave Hansen-Lange (19:31):

And so, because of all those things, it’s going to be still a big chunk of work, not as big as just doing a clean slate and starting from scratch. But still a lot of work involved. One thing you do need to look into before you get too far down this road is like, are there any ways in which we solve the problem in Drupal 7, that just there’s no equivalent in Drupal 9. And that has sometimes happened because the Drupal 7 way of solving a problem, one example would be locations. Let’s say you got a content type in Drupal 7 called offices of your organization and they’re storing their address and location. That’s almost certainly done in a very different way in Drupal 9. And there isn’t a way to directly go from one to the other, at least not directly in the same sense of this upgrade process that I talked about before. There may be these situations like that, and you’ll have to do something custom or something else. That’s a little bit more complicated. It’s just important that, you know, these things happen upfront before you get into moving down this road.

Dave Hansen-Lange (21:00):

So who is this good for? I mentioned, you’re going to get the same stuff in the backend as you have now. So it’s, if you’re happy with that, great, consider this option. I mentioned that the visual presentation, you’ve got to redo that. So if you want a fresh design, this might be an option for you. Again, avoid if budget is tight, like I mentioned, it’s still a fairly complicated procedure. All right. A third option is to switch to Backdrop.

Dave Hansen-Lange (21:39):

So Backdrop, I said earlier that your main options are WordPress or Drupal. What’s this, what’s this new Backdrop thing? Backdrop is kind of like a different flavor of Drupal. And in the technical parlance, Backdrop is a fork of Drupal 7. And what does cutlery have to do with software? Absolutely nothing. So by fork, we mean fork in the road. You may know that Drupal and WordPress are open-source software. And that means that anybody, anybody really who has the time available to do it, can jump into the project. You got a problem with the way something works, you want to make it better, you can just do that and you can contribute something and get it rolled into the software. But what that also means is that if you don’t like how something works, you can just take it, copy it, and roll with it.

Dave Hansen-Lange (22:42):

And that’s what’s happened with, with Backdrop so well. Drupal 8 was being developed. There were many people in the community who thought, “Oh, no, like Drupal 8 is looking great and all, but it’s going to be really hard for websites that are on Drupal 7 to get to Drupal 8 and whatever it comes in the future. And they were right. That’s, that’s why we’re here. That’s why we’re having this webinar. And so what they did was they took Drupal 7, copied it, called it Backdrop and started to evolve it and evolve it in some of the same ways that AAA has evolved only keeping with the Drupal 7 way of doing things and the Drupal 7 styles. And so you have an option to take your website and sort of just take that fork in the road and start moving down the Backdrop trail.

Dave Hansen-Lange (23:42):

What this is going to look like for your website is that you’re still gonna have the existing content structure things in the backend of the website, just like that, upgrading to Drupal 9 option. It’s all going to look very similar, if not identical, but different from that upgrade to Drupal 9 option. You can still keep the visitor-facing portion of the website. If it’s going to need a little bit of tweaking to get onto that Backdrop fork in the road. But that is going to be relatively much smaller, a much lighter lift. Not to say that you must keep your existing design, you can make some changes and revisions. You might even consider doing a full redesign. But yeah, you don’t have to, as you’ve heard me describe this, you may be thinking fundamentally that the steps involved, it’s pretty similar to the upgrade to Drupal 9.

Dave Hansen-Lange (25:00):

It is, but still, it is almost certainly cheaper than upgrading to Drupal 9. And mainly the reason is because like I mentioned, it is just Drupal 7 evolved. So the changes that you have to make to your existing website are just immensely smaller, some increased risk. So what I mean by this well, like anybody who works with websites for a nonprofit is probably going to know WordPress, and probably getting to know the word Drupal, probably not going to know the word Backdrop, because it is such a much smaller community. Where there might be that there’s about half a million Drupal websites out there. There may be like a few thousand Backdrop websites out there. And because of that, there’s enough momentum in the community that we know that Backdrop will be here for two years, maybe four years, but it’s harder to sort of see deeper into the future. Whereas Drupal, you know, half a million websites. We know it’s, there’s a lot of people working on this, a lot of organizations, big and small, it’s going to be here for probably at least another 10 years, if not longer. Backdrop, much smaller community. There’s just not as much certainty about the future. 

Dave Hansen-Lange (26:44):

But with that said, Backdrop has committed to like the same sort of upgrade structure that Drupal 8 and Drupal 9 have committed to being. We’re not going to do a huge change again in the future. We’re going to make all these incremental changes that will make it much easier for you to stay up to date and evolve your website over time.

Dave Hansen-Lange (27:12):

Great. I thought it important to show some visuals about what Backdrop looks like and looking at these, you might be thinking, “Oh, this looks pretty similar to my Drupal 7 website, but the colors and fonts are more contemporary”. And you are a hundred percent correct in thinking that like I mentioned, it really is Drupal 7 evolved. But there is more to it. There are some easier things on the technical side of how to work with Backdrop compared to Drupal 7. There’s some different ways of managing page layouts. There’s other new features in Backdrop that Drupal 7 doesn’t have. But the thing is, if you take this sort of upgrade from Drupal 7 to backdrop trajectory, you’re not going to get those things all of a sudden. If you want to take advantage of Backdrop’s fancier ways of laying out content on a page then you’re going to have to have a small project to enable that feature. At first, you’re still going to be working in the same paradigms as you are with Drupal 7. So who is Backdrop great for? Anyone who has a lot of custom code. I was talking earlier about like, why you might want to avoid building a new website and Drupal 9 is if you’ve got a lot of custom stuff. Here in this option, and this would be a good option for you because all that custom stuff probably doesn’t need to change very much, probably needs to change a little. But if it’s not going to be all that significant, this is a good option for you.

Dave Hansen-Lange (29:16):

If you are happy with your existing design that’s going to need a little bit of touch-ups to move to Backdrop. I was trying to be consistent here and come up with a reason why you should avoid Backdrop. I couldn’t really come up with one. I think everyone should at least consider this option. It’s kind of like the middle of the road option. You might not choose this option if you’re wanting to do a full redesign, but if all the rest of the things line up for you, then you could do a full redesign in Backdrop. It would be fine. I guess the only reason that I can think of now is that if you are super concerned about keeping the website that you have the same fundamentally as it is now, four, five years into the future, 7 years into the future—because the future is a little less defined for Backdrop—you may want to avoid it in that case.

Dave Hansen-Lange (30:35):

All right. And the last option stay on Drupal 7. I mentioned even though Drupal 7 has reached end of life, there are ways to continue on with it. If you had any websites that were on Drupal 6 and you were in this sort of situation for Drupal 6’s website, when it reached its end of life, there was a program started called the extended support for Drupal 6. This Drupal 7 version of that program is fundamentally identical. And what this is is that I mentioned that many of the security team are volunteering their time. And so this program gets around by trying to force people to volunteer their time by saying it’s a paid program. The Drupal community has vetted several Drupal agencies to offer this extended support service. And what that means is that as security issues come up, maybe there’s a security issue that comes up in Drupal 8 that might also apply to Drupal 7 this, this team of extended support people work on fixing that problem in Drupal 7.

Dave Hansen-Lange (32:11):

And so there’s kind of two ways to take advantage of this: Number one, you sign up with one of the extended support vendors. You’ll be able to find that list through some links that we’re going to send at the end. One of the mandates of this is that they release all of their fixes publicly. It’s happened for Drupal 6 as well. And so if you are technically savvy or you’ve got someone at your disposal who’s technically savvy and can sort out the details and apply these fixes as they come up, this could be a good option for you, too.

Dave Hansen-Lange (33:08):

I think it’s important though, to like, take a step back at this point and talk about why you might think about security in different ways. And one way to think about security is kind of like two groups of websites on the internet—those who security is really important for, for whatever reason. Maybe they’re doing something that some people find controversial and they have people who are trying to hack into their website. Maybe you are processing credit cards on your website and you, you know, someone might want to try and break in and steal those credit cards. Maybe you are a news outlet and you get hundreds or hundreds of thousands of people viewing your content every day. And if someone could break in and get some sort of message out to those people, that might be an incentive as well. So that’s like one group of websites, people who have some sort of special security concern. And then there’s kind of everybody else—everybody who knows that security is fundamentally important, but it’s not more important than it is for everyone else in this group.

Dave Hansen-Lange (34:33):

It’s just the nature of how I described that most organizations are going to be in this group where security is important, but not more important than anyone else. Some are going to be in this heightened group of security. And for those people, they need to think about things more than just like, am I getting the bare necessity basics? Or am I really doing all that I’m responsible for ensuring the security is as good as it can be. And for those people, this may not be the best option in that you’re not on the most recent and currently secure thing you were on, this thing that’s on extended support. And whether that rationale is purely technical, or if it’s purely optics in that if something were to ever happen to your website and it was discovered, “Oh, they’re running this version of Drupal that was created 10 years ago”. 

Dave Hansen-Lange (35:38):

How can that be responsible? And then there’s all sorts of politics involved. I mean, it’s a situation you want to completely avoid, but for those of us who are in the group of security as important, but not more important than anyone else, this can be a very reasonable option to consider. So stay on Drupal 7, if you have a really tight budget. And I admit that budget is in the eye of the beholder. For some of you a roomy budget would be a tight budget and vice versa. Like I was talking about, if you don’t have any special security requirements avoid, if your site needs a facelift or if you’re frustrated with the backend. So like I mentioned, this is keeping the same website and keeping it the same. And so if you want to rip something out and try again, this is probably not the option for you.

Sarah Durham (36:56):

Okay. So, Dave, I’m just going to jump in here for a second before we continue with your sample scenarios. We’ve got about 20 minutes left in our time together, so we’re going to need to move pretty quickly through our sample scenarios and through the make a plan section. But we did get a really good question that I’d love you to try to answer for us before we continue on. It’s from our friend, Rita, and Rita asks, if you choose to migrate or upgrade to Backdrop, what would that mean for your future options to upgrade to Drupal 9?

Dave Hansen-Lange (37:29):

I don’t think it really changes the landscape for that at all. Whether you’re upgrading from Drupal 7 or from Backdrop, it’s fundamentally the same thing. It is technically almost identical and that’s because well, Backdrop has gone on this new trail at a foundational level. The way the content is stored, it’s fundamentally the same. And so if you want to pull that content out of either version of those websites into a new Drupal 9 website, it’s going to be the same process. That could change though, as it’s a fork in the road. So Backdrop could go further one way, while well, Drupal 7 is not moving anywhere at this point, but it could continue to move on in a way that’s more different from Drupal 7. But in my opinion, it’s unlikely to change all that much for the foreseeable year or two.

Sarah Durham (38:37):

Okay, great. So, so back over to you.

Dave Hansen-Lange (38:40):

Okay. So like I mentioned, those options, they were great in theory, but now let’s try and put some of this to practice. I’m going to show, I think, four, maybe five example websites and what is unique or different about those websites and why they might choose one option over the other. As you’re looking through this, you might think, “Oh, that’s nothing like my website”. But I’m going to try and pull some things out here that hopefully are going to apply or at least show some things that you should consider. And you also might recognize some of these websites. Don’t focus on that. We’re going to focus on what is it about these websites? I’m also not going to tell you anything about these websites that isn’t something… Sorry, everything that I’m going to tell you about these websites is something that you could just go to the website, look at and figure out for yourself.

Dave Hansen-Lange (39:45):

So there’s not going to be any sort of like private information here that I’m gonna show either. So in this first example, we’re going to look at the ACLU. On the left here, we see what their website homepage used to look like. On the right side, we’re going to see what the homepage looks like now. And the prior version of the website, that was Drupal 7. The homepage, and I say that specifically, the homepage, is now WordPress. You may remember back when I talked about the option of creating a new website that you don’t have to do the whole thing. Here’s just the homepage. And they’ve actually done the same thing with the blog section. It used to be Drupal on the left. Now it’s WordPress on the right. You don’t have to do with everything.

Dave Hansen-Lange (40:44):

So this is an example of a case on the ACLU website. And like, this is just one really long page here that is cut up into three pieces. See at the top, this is all just fairly straightforward content. But then in this section, things start to get more complicated. Like there’s all these other bits of content elsewhere on the website that are related to this case. That’s something that you can do in WordPress, but the more complicated those relationships get, the more awkward it gets to do in WordPress. Then down here at the bottom of the page, things get super complicated. Visually it doesn’t look too bad, but that’s because I think the design was done well. There’s hundreds of legal documents that relate to this case, all in these groupings and hierarchy and get super complicated. WordPress is not the best tool for this kind of job. And so this part of the website is still on Drupal. It’s still going to be on Drupal for now. It might evolve in the future, but that’s where it is for now.

Dave Hansen-Lange (42:03):

Another section of the website, there is this sort of intermediary thing where you could show an action within like an article or a blog post or something to say, “Okay, come take this action”. And during the redesign or in moving bits to WordPress, you know, if you’ve stepped back and thought, is this useful? Is this complicated? Is there a way to do this simpler? And this sort of intermediary thing was just checked and now there’s just links to actions and there’s other ways to show actions without this complicated section of the website. Please consider for your website: What should I get rid of? There’s almost always something. 

Dave Hansen-Lange (43:11):

Looking at a different organization, here is one that’s a Drupal 7 website. But you might be thinking, “Oh, this design, it looks fairly current”. And you’d be correct because this organization went through a redesign, I want to say, like, two years ago. And so because of that, looking at those four main options, they can probably throw the create-a-new-website option out because the design still looks great. As long as they’re happy with how the content works on the backend, they could really choose any of the other three options. And, yeah, so consider that.

Dave Hansen-Lange (43:47):

Next, we have a municipality. When I was talking about the option of staying on Drupal 7, that’s maybe not the best option for a municipality in the news all the time. We hear stories of like such-and-such municipality, their website has been hacked, or their computer systems have been taken over by ransomware. And so just the optics of staying on Drupal 7 might not be the best choice for them. The design looks, doesn’t look as fresh as those first two options that we showed. But let me guess a municipality kind of has different requirements in that the number one goal is not a flashy design, it’s getting information out to its residents.

Dave Hansen-Lange (44:32):

And so there may be a way for them to choose one of the non-design related options. And at the same time, maybe consider how it can do any sort of restructuring to better present the information that people need to find. Here’s another organization. In looking at the screenshot, you might be thinking the same things that this organization thinks about this website and that the design is very text-heavy, and it is not quite as engaging as they would really like it to be. And so for this organization, one of the first two options is probably the best choice: creating a new website completely or upgrading this to Drupal 9 with a new design.

Dave Hansen-Lange (45:43):

Lastly, we’re going to look here at, this is not so much a website, but a web platform. AFT has 1,300 websites on this one platform for States and Locals within a state. And the center one up top here, this is for a campaign website. And this is an example of a few things: One, it’s not their primary website, it’s not aft.org. And so if you’ve got more than one website, you don’t have to choose the same option for all of them. You can choose different options. Number two, there’s a lot of custom stuff involved here, as you might imagine. Some stuff around creating a new website, around connecting the information altogether. So because of that, you might lean more to one of the options that works better for custom stuff and doesn’t require recreating all of their custom stuff in a brand new website.

Sarah Durham (47:07):

Thank you, Dave. So a quick question, before we talk about where you go from here. Just want to confirm the ACLU, the sections of the ACLU site that are still in Drupal, or are those WordPress? 

Dave Hansen-Lange (47:22):

That is in Drupal. Yes. 

Sarah Durham (47:26):

Okay, so Dave is going to be advancing some slides for me. So I will ask you, Dave, to go onto the next slide. And basically, before we flip over to your questions and discussion, and in the remaining time we have together, what I want to get you thinking about is how to make a plan. And it’s interesting we’re doing this today because actually I had a call with somebody at a higher ed institution this morning, who’s got an old site and they are debating what their options are. They were describing a lot of feelings of being overwhelmed. I think that, you know, these days with the reality of what’s going on in the world with COVID, with elections, all that kind of stuff, tackling these kinds of big projects is feeling pretty daunting. So I wrote an article about planning and we’ll share links to that article and a bunch of other things.

Sarah Durham (48:20):

Dave has also written a really helpful post about Drupal 7’s end-of-life. At the end of this webinar and also in the follow-up email, we’ll send you one of the things I wrote. The first step is to make a plan and you don’t have to have all the answers. You’ve just got to begin by getting your team on the same page about the implications. I think that’s one of the big barriers that a lot of people are facing is that they’ve got these Drupal sites and there is a real challenge coming up, a real cliff coming up for many of you that you’ve got to begin to get your team aligned around so that you can budget and plan appropriately. Next slide please, Dave. So I recommend that you come up with a plan, which you could do in five slides or in two pages.

Sarah Durham (49:05):

And the intention of this plan is actually to give you an internal document you can use to get your team on the same page and build some buy-in. So you can see first you’d start by outlining the situation. I think we’ve given you some of the ammunition for that conversation and in today’s session or in the articles we’ll share with you, and what the risk is to your organization. You might want to outline some options if it’s clear to you and the people on your team where you should go from Drupal 7. You might go forward with outlining some options or making a recommendation, but honestly, if you’re not sure which way to go, a good partner should help you get there, too. So if you don’t have the answers already in mind, if it’s not clear to you which way to go, it might be that you map out a few options.

Sarah Durham (49:52):

But your recommendation might be more to find a partner to help you navigate that. Of course Advomatic can do that. We would love to help you make a decision about this, and we do regularly do that as part of our work. There are many people you could work with who could do that. I think one of the things that’s also really important in your plan is mapping out a timeline, not so much for the build or the upgrade that you might do, but all the things leading up to it. If you are looking ahead and thinking what you really need to do is rebuild your website or do a significant upgrade, that’s going to take time and a lot of work, and you’re going to want to get your team on the same page about when the budget needs to be approved, and when you’re going to get rolling so that you’re doing it hopefully well in advance of some of the deadlines that are going to be important within your organization and within the Drupal 7 end-of-life timeline.

Sarah Durham (50:49):

You know, in the non-profit sector, one of the key pieces that is in my experience kind of do-or-die for many big projects is building buy-in. So with that plan in mind, I would encourage you to have some conversations, share it, get it into the budgeting process and kind of keep it alive because very often you know, you mentioned these things once or twice, but there’s so many things going on that are taking up so much attention and energy for the leaders of organizations today that I think you’re going to have a little bit of work to do to keep it alive, which is the next step. My next slide. Also, keeping it alive is about not just writing this plan and sending it to people, but keep nudging and keep bringing it up. If you know what your milestones are when people are talking about budgets or budgets are getting approved, you know, those are great opportunities to research, collate your plan and go from there.

Sarah Durham (51:47):

Now, many organizations that we work with and talk to are already doing this, and they’re already talking to us and other people about what they’re doing. And a partner can also help you figure out your timeline. So there are a lot of ways to do this. You don’t have to do the heavy lifting on your own. But what you don’t want to do is you don’t want to wait until you’re, you know, a couple of months away from these deadlines if they pose significant risks or implications for your organization. So we have a few minutes left to go before the top of our hour. And I want to hear a little bit from you. So if you’ve got questions or comments, you can either use the Q&A feature, which you will see at the bottom of your screen, or you can chat them in to Dave and I, as we go. And we’re going to stop sharing our screen. Now we’ll take a few questions and while you chat those in, I also want to just remind everybody that we are going to be sending out a follow-up link to the recording here. And Theresa is also going to chat out a couple of the articles we mentioned. Dave has written a really helpful article about D7 end-of-life. He’s also written an article about D8 and there’s an article I’ve written that’s about how you, how you plan for this change. So Theresa will chat those all out.

Sarah Durham (53:17):

Okay, Dave, first question for you. Somebody is chatting in about administrators and they’re thinking, well, actually, this is sort of a double-barreled question. Let’s take it in two parts. First in option A, you talked about building a new site as option A. You specifically talked about WordPress and Drupal. Both of those are open source technologies. Why are you talking just about WordPress and Drupal and not any other systems?

Dave Hansen-Lange (53:46):

One of the things that I also talked about was like, kind of the momentum of these projects, like Drupal is large. WordPress is ginormous. And there’s lots of movement in those projects. There’s lots of momentum as soon as someone has a new idea or a new technology pops up on the internet, like things move quickly. And there’s a way to do it on your website in short order. And I also talked about the security group, that’s not the official title, but like there’s ways like that in which you’re getting the benefits of someone else volunteering their time for your website, which you just don’t get in in some of the other options that you have.

Sarah Durham (54:37):

Okay, thank you. And the second part of this question was about comparing WordPress and Drupal about administrators and the options there. This person is talking about how there’s lots of different people in their organization, who right now have different layers of access in Drupal 7. And they’re wondering if there are any recommendations you have for new platforms based on that kind of complexity.

Dave Hansen-Lange (55:01):

Yeah, so like the area of editorial permissions and controls, like that’s one of the big differentiators between Drupal and WordPress. WordPress has some basic systems around this role can do this, or this role can do that. In Drupal, we can make things a whole lot more complicated, like people who manage this section of the website, they can upload images. Other people can use those images, but only the original group of people can edit them or ways of more complicated things that you can do in Drupal.

Sarah Durham (55:38):

Okay, so there’s a question here about the difference between a Drupal new build and a Drupal upgrade in terms of cost. And actually, would you mind just bringing it up again, cause somebody chatted to me that they arrived a bit late and they didn’t see your slide. I think it’s your slide number six, which outlines all the options. Let’s just quickly go back to that slide for a second and share that. And I think that the question that just got chatted into me relates to this. So on slide six, you mapped out a bunch of different options ranging from building a new site to staying on Drupal 7. And those were ranked, as you talked about them from most expensive to least expensive. So you said building a new site is the most expensive, staying on Drupal 7 is the least expensive, and then the upgrade or the switching to Backdrop were in between. So the question is about the cost differential between building a new site in Drupal 9 and upgrading in Drupal 9. I assume that there are additional costs for design, for UX, things like that, and building a new website, but how significant is that differential? What other variables inform the cost difference there?

Dave Hansen-Lange (57:06):

Yeah, so I talked about sort of in any of these higher options… well, no, let me rephrase that. In the two middle options, you have the option of how much redesign you want to do, of course. And that’s probably the biggest thing that affects how big or small upgrading to Drupal 9, that project is going to be. But let’s say you wanted to redesign and compare upgrading to Drupal 9 versus creating a new website in Drupal 9. It’s difficult to be put on the spot, but I don’t know, 80%, 90% since you’re doing a full redesign. Upgrading to Drupal 9 and moving to a new website, they start to become more similar. The more you’re redesigning, the similar in cost.

Sarah Durham (58:01):

Okay, thank you. That sounds like what we were expecting. So I am just skimming through your questions and it looks like a couple of other questions that we have here are pretty unique to specific organizations, so I’m going to follow up directly with those organizations since we are just about out of time. I want to thank Theresa and Dave for joining us today. Dave, thank you for imparting your wisdom on this topic. And I want to thank everybody who took the time to log in and watch this. I hope this has been helpful for you. If you have specific questions or concerns or things you want to pick our brain about, you can always email us at [email protected] or [email protected]. We’d be happy to get on the phone with you, talk a little bit about your situation if that is of use to you. And again, Theresa will be sending out a link to these articles and the recording to you in just a few days. So thank you, all. And thank you all for the excellent work you do to make the world a better place. Be well, thanks.

Oct 27 2020
Oct 27

For many years styling websites with CSS has been pretty standard. A CSS stylesheet exists somewhere in your project which provides styles for your pages or components. Even with the introduction of CSS preprocessors like Sass, Less, Stylus, and PostCSS to mention a few, the ultimate result is for stylesheets to serve styles to your pages and website.  

With the introduction of JavaScript frameworks such as React, NextJS, and others, the approaches for writing and serving CSS styles have become more complex and at times controversial. Things like CSS-in-JS (Reactjs.org defines this as “a pattern where CSS is composed using JavaScript instead of defined in external files"), can make some people question whether we are getting ourselves in trouble and whether we will regret going in this direction. It wouldn’t be the first time we find ourselves undoing practices we have followed for years because we realized there was a better way.

In GatsbyJS, a library of React, we can use different methods for styling a website.  Some of these approaches include:

  • Plain CSS
  • Inline styles
  • Styled Components
  • CSS Modules
  • Others

In most cases, people who lack the in-depth knowledge of CSS will opt for the easier way possible to style a website.  This is not always the best way to go about it, but unfortunately, it is the reality.  As someone who has worked with CSS for many years, I could technically pick any of the approaches above and accomplish my goal of styling a website, but I see issues with some of those practices and prefer to use an approach that provides flexibility, control, and best practices.

Choosing a Styling Method 

Working for an agency where we build websites for clients of all sizes, many times the method we choose for doing something depends on the client’s preferences or skill level of their team.  Meaning that we want to build a website that a client could take over and maintain on their own after our engagement with the client has scaled down.  So even if I have a personal preference but the client has no experience or desire to work with that approach, I would need to provide a way for the client to work with a system or approach that may be more comfortable to them.

The one thing to keep in mind when choosing a method for styling your websites, Gatsby or otherwise, is that at the end of the day, we are producing plain CSS and as such, it should be well-written, and easy to maintain and scale. I am a fan of keeping styles simple, flat, and to a minimum. I don’t see the point of using over-engineered methods that complicate the most simple task.

CSS Modules

My approach of choice for styling React or Gatsby websites is CSS Modules because it most closely resembles the traditional way of styling websites I have grown accustomed to. As I alluded to before, my ultimate goal is to write proper CSS, following best practices, while leveraging styles scope, performance, and scalability. CSS Modules allows me to do all these things while providing an environment I am familiar with. I am not against learning new ways of doing things (I welcome them), but if new approaches don’t offer significant benefits, I don’t see the need of complicating my life and that of clients who will interact with my code.

In a typical Gatsby website, CSS Modules works out of the box without any special configuration. You can create any CSS files in your project, import them into the components you are working with and your styles will work. This is great and can get you very far if you are working with a simple website. However, this only works with plain CSS and not Sass. I personally like Sass because it provides features that are currently not available in CSS. Things like Mixins and nesting to mention a few. I will use Sass and SCSS interchangeably in this post to refer to the preprocessing process of compiling SCSS into plain CSS code.

Add Sass to Your Gatsby Website

Adding Sass to a Gatsby website is relatively easy. It’s a two-step process that includes installing a Gatsby plugin and adding a line of code to gatsby-config.js. Let’s do this now:

  1. While In your Gatsby project root directory, run the following command to install the gatsby-plugin-sass and node-sass plugins:

    npm install node-sass gatsby-plugin-sass
    Gatsby-plugin-sass has a dependency of node-sass and therefore we need to install both.

  2. Edit gatsby-config.js (located in the root of you gatsby project), by adding the new plugin to the plugins array:

    plugins: [`gatsby-plugin-sass`]
    If you already have other plugins in place, you can add each new plugin in a new line within the array.

That’s it! Now Sass is available on your site.

Updating CSS Modules to use Sass

Now that we have Sass available, the last thing to do is to update CSS Modules to use Sass versus plain CSS. This is a two-step process:

  1. Rename any existing .css files to use .scss
  2. Update any imports of these files to also use .scss

Now you can take advantage of CSS Modules and Sass for writing great styles. Let’s go over a quick example of how CSS Modules works.

Using CSS Modules and Sass in Gatsby

Consider the following HTML/JS in your Gatsby Component (hero):

import React from 'react';
import PropTypes from 'prop-types';
import Image from 'gatsby-image';

import Heading from '../Heading';
import Link from '../Link';
import {fluidImage} from '../../global/js/customPropTypes';

const Hero = ({ title, image, body, path }) => {
  return (
    
        
          {title}
        

{body}

Learn more ); }; export default Hero; Hero.propTypes = { title: PropTypes.string, body: PropTypes.string, image: fluidImage, path: PropTypes.string };

Styling the Hero component above with CSS Modules will require we create a stylesheet for the Hero. Assuming you have a Hero folder inside components, which has an index.js for the component’s markup and JavaScript, create a file called hero.scss with the following code:

.hero {
  background-color:$color-white;
  position: relative;
}

.media {

  img {
    display: block;
    height: auto;
    max-width: 100%;
  }
}

.content {
  left: 50%;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
}

.title {
  color: $color-secondary;
}

And finally, you would update index.js by first importing the hero’s stylesheet as follows:

import styles from './hero.scss';

Then adding the respective CSS classes to each of the HTML elements in the Hero component. The end result of index.js would look like this:

import React from 'react';
import PropTypes from 'prop-types';
import Image from 'gatsby-image';

import Heading from '../Heading';
import Link from '../Link';
import styles from './hero.scss';
import {fluidImage} from '../../global/js/customPropTypes';

const Hero = ({ title, image, body, path }) => {
  return (
    
        
          {title}
        

{body}

Read the full article ); }; export default Hero; Hero.propTypes = { title: PropTypes.string, body: PropTypes.string, image: fluidImage, path: PropTypes.string };
  • When we imported the Hero styles into the component we used styles as the namespace in the import.
  • To apply each of the CSS classes found in hero.scss to the markup in index.js we are using the className attribute since class is a reserved keyword in React/Gatsby.
  • Then in curly brackets we apply each class by prefixing them with styles. For example: 

If you render this component in the browser, what you will see as a result when you inspect the code is something similar to:

Example of HTML code through dev tools

  • Main things to note from the image above are the CSS classes added after css-modules--. These are the classes we created in hero.scss.
  • The end of the class names (i.e. akrigl, woitn, w95ls9), are dynamic strings created by CSS Modules which ensure they are unique CSS classes.  This prevents issues of regression and styles from leaking into other parts of your website.
  • CSS Modules restricts the scope of its styles to only the component they are written for.

In closing

I like CSS Modules because it provides a familiar approach to working with Sass similar to that of a traditional Sass project. This works well with clients who are not well-versed in React or Gatsby but still want to be able to update styles.

[embedded content]

Sep 23 2020
Sep 23

Working in digital design and development, you grow accustomed to the rapid pace of technology. For example: After much anticipation, the latest version of Drupal was released this summer. Just months later, the next major version is in progress.

At July’s all-virtual DrupalCon Global, the open-source digital experience conference, platform founder Dries Buytaert announced Drupal 10 is aiming for a June 2022 release. Assuming those plans hold, Drupal 9 would have the shortest release lifetime of any recent major version.

For IT managers, platform changes generate stress and uncertainty. Considering the time-intensive migration process from Drupal 7 to 8, updating your organization’s website can be costly and complicated. Consequently, despite a longtime absence of new features, Drupal 7 still powers more websites than Drupal 8 and 9 combined. And, as technology marches on, the end of its life as a supported platform is approaching.

Fortunately, whatever version your website is running, Drupal is not running away from you. Drupal’s users and site builders may be accustomed to expending significant resources to update their website platform, but the plan for more frequent major releases alleviates the stress of the typical upgrade. And, for those whose websites are still on Drupal 7, Drupal 10 will continue offering a way forward.

The news that Drupal 10 is coming sooner rather than later might have been unexpected, but you still have no reason to panic just yet. However, your organization shouldn’t stand still, either.

Image via Dri.es

The End for Drupal 7 Is Still Coming, but Future Upgrades Will Be Easier

Considering upgrading to Drupal 8 involves the investment of building a new site and migrating its content, it’s no wonder so many organizations have been slow to update their platform. Drupal 7 is solid and has existed for nearly 10 years. And, fortunately, it’s not reaching its end of life just yet.

At the time of Drupal 9’s release, Drupal 7’s planned end of life was set to arrive late next year. This meant the community would no longer release security advisories or bug fixes for that version of the platform. Affected organizations would need to contact third-party vendors for their support needs. With the COVID-19 pandemic upending businesses and their budgets, the platform’s lifespan has been extended to November 28, 2022.

Drupal’s development team has retained its internal migration system through versions 8 and 9, and it remains part of the plan for the upcoming Drupal 10 as well. And the community continues to maintain and improve the system in an effort to make the transition easier. If your organization is still on Drupal 7 now, you can use the migration system to jump directly to version 9, or version 10 upon its release. Drupal has no plans to eliminate that system until Drupal 7 usage numbers drop significantly.

Once Drupal 10 is ready for release, Drupal 7 will finally reach its end of life. However, paid vendors will still offer support options that will allow your organization to maintain a secure website until you’re ready for an upgrade. But make a plan for that migration sooner rather than later. The longer you wait for this migration, the more new platform features you’ll have to integrate into your rebuilt website.

Initiatives for Drupal 10 Focus on Faster Updates, Third-Party Software

In delivering his opening keynote for DrupalCon Global, Dries Buytaert outlined five strategic goals for the next iteration of the platform. Like the work for Drupal 9 that began within the Drupal 8 platform, development of Drupal 10 has begun under the hood of version 9.

A Drupal 10 Readiness initiative focuses on upgrading third-party components that count as technological dependencies. One crucial component is Symfony, which is the PHP framework Drupal is based upon. Symfony operates on a major release schedule every two years, which requires that Drupal is also updated to stay current. The transition from Symfony 2 to Symfony 3 created challenges for core developers in creating the 8.4 release, which introduced changes that impacted many parts of Drupal’s software.

To avoid a repeat of those difficulties, it was determined that the breaking changes involved in a new Symfony major release warranted a new Drupal major release as well. While Drupal 9 is on Symfony 4, the Drupal team hopes to launch 10 on Symfony 6, which is a considerable technical challenge for the platform’s team of contributors. However, once complete, this initiative will extend the lifespan of Drupal 10 to as long as three or four years.

Other announced initiatives included greater ease of use through more out-of-the-box features, a new front-end theme, creating a decoupled menu component written in JavaScript, and, in accordance with its most requested feature, automated security updates that will make it as easy as possible to upgrade from 9 to 10 when the time comes. For those already on Drupal 9, these are some of the new features to anticipate in versions 9.1 through 9.4.

Less Time Between Drupal Versions Means an Easier Upgrade Path

The shift from Drupal 8 to this summer’s release of Drupal 9 was close to five years in the making. Fortunately for website managers, that update was a far cry from the full migration required from version 7. While there are challenges such as ensuring your custom code is updated to use the most recent APIs, the transition was doable with a good tech team at your side.

Still, the work that update required could generate a little anxiety given how comparatively fast another upgrade will arrive. But the shorter time frame will make the move to Drupal 10 easier for everybody. Less time between updates also translates to less deprecated code, especially if you’re already using version 9. But if you’re not there yet, the time to make a plan is now.

Mar 12 2020
Mar 12

argument-open-sourceargument-open-source

If you engaged in a word association game, one of the first things people would respond when you say “open source” is that it’s free. If any of those people are in the position of purchasing software licenses for a business or organization, that makes open source (a.k.a., free) definitely a benefit worth exploring. Open source has the potential to save thousands of dollars or more, depending on the software and the size of the organization. 

Even though eliminating a budget line item for licensing costs may be enough to convince some organizations that open source is the way to go, it’s actually only one of several compelling reasons to migrate from proprietary platforms to open-source architecture. 

In a debate on open-source vs. licensed platforms, the affirmative argument will include these four, additional points: 

Development Freedom

When businesses provide workstations for their employees, they choose (often inadvertently) the framework on which their organizations operate. For example, if a business buys Dell computers, it will operate within the Microsoft Windows framework. This isn’t necessarily a bad thing. A business with limited IT and development resources won’t have to worry about how to keep its operating system working or whether business applications or security solutions are available. Microsoft has a line of solutions and partnerships that can provide what they’re looking for. 

With a system built on an open-source platform, on the other hand, it may take more resources and work to keep it running and secure, but it gives developers the freedom to do exactly what the end user needs. You aren’t limited by what a commercial platform enables you to do. 

In some markets, foregoing the status quo for developmental freedom sounds like risk. It’s a major reason that government users lag behind the commercial space in technology. They’re committed to the old systems that they know are robust, secure, and predictable at budget time — even though they’re outdated. When those organizations take a closer look, however, they quickly realize they can negate development costs through greater visibility, efficiency, and productivity that a platform that specifically supports their operations can provide. 

Open-source platforms are also hardware agnostic, giving organizations more latitude when it comes to the computers, mobile devices, and tools they can use, rather than being locked into limited, sometimes expensive, options for hardware. 

Moreover, development freedom delivers more ROI than merely decreasing current costs. Open-source platforms give developers the freedom to customize systems and innovate. If your system enabled you to expand your reach, better control labor costs, and support new revenue streams, what impact could that have on your business?

Interoperability

Enterprises and manufacturers have traditionally guarded their proprietary systems, which gave them an edge in their markets and control over complementary solutions and peripherals end users needed. Those same proprietary systems, however, could now be a business liability. Many markets are moving toward open source to provide greater interoperability, and businesses continuing to use proprietary platforms will increasingly be viewed as less desirable partners. 

Military avionics is a prime example. This industry is migrating to the Future Airborne Capability Environment (FACE) Technical Standard. Administered by the FACE Consortium, this open standard aims to give the U.S. Department of Defense the ability to acquire systems more easily and affordably and to integrate them more quickly and efficiently.  

You’ll also find a preference for open-source architecture in some segments of the tech industry as well, such as robotics. The Robot Operation System (ROS) is a set of open resources of tools, libraries, and conventions that standardizes how robots communicate and share information. ROS simplifies the time-consuming work of creating robotic behaviors, and ROS 2 takes that objective further by giving industrial robot developers support for multirobot systems, safety, and security. 

As Internet of Things (IoT) technology adoption grows, more operations are experiencing roadblocks connecting legacy equipment and enabling the free flow of data — which open-source architecture can overcome. Furthermore, IoT based on open-source components allow networks to expand beyond the four walls of a facility to connect with business partners, the supply chain, and end users. The Linux Foundation’s Zephyr Project, for example, promotes open-source, real-time operating systems (RTOS) that enables developers to build secure, manageable systems more easily and quickly. 

Faster Time to Market

Open source projects can also move more quickly than developing on a proprietary platform. You may be at the mercy of the vendor during the development process if you require assistance, and certifying hardware or applications occur on their timelines. 

That process moves much more quickly in an open source community. Additionally, members of the community share. Some of the best developers in the industry work on these platforms and often make their work available to other developers so they don’t need to start from scratch to include a feature or function their end user requires. A modular system can include components that these developers have created, tested, and proven — and that have fewer bugs than a newly developed prototype. 

Developers, using prebuilt components and leveraging an open source community’s expertise, can help you deploy your next system more quickly than starting from ground zero. 

Business Flexibility

Open-source architecture also gives a business or organization advantages beyond the IT department. With open source, you have more options. The manager of a chain of resorts facing budget cuts, for example, could more easily find ways to decrease operating expenses if her organization’s system runs on an open-source platform. A chain that operates on a commercial platform, however, may have to find other options, such as reducing staff with lay-offs.  

Open source architecture also decreases vendor lock-in. In a world that’s changing at a faster and faster pace, basing your systems open-source architecture gives you options if a vendor’s company is acquired and product quality, customer service, and prices change. It also gives you flexibility if industry standards or regulations require that you add new features or capabilities that your vendor doesn’t provide, decreasing the chances you’ll need to rip and replace your IT system.

The Price of Open Source

To be perfectly honest in the open source vs. commercial platform debate, we have to admit there is a cost associated with using these platforms. They can’t exist without their communities’ contributions of time, talent, and support. 

At Mobomo, for example, we’re an active part of the Drupal open-source content management system (CMS) platform. Our developers are among the more than 1 million members of this community that have contributed more than 30,000 modules. We also take the opportunity to speak at Drupal community events and give back to the community in other ways. 

Regardless of how much we contribute to the community, however, it’s never exceeded the payback. It’s enabled lower total cost of ownership (TCO) for us and our clients, saving millions of dollars in operating expenses. It has ramped up our ability to create and innovate. It’s also allowed us to help build more viable organizations and valuable partnerships. 

The majority of our industry agrees with us. The State of Enterprise Open Source report in 2019 from Red Hat asked nearly 1,000 IT leaders around the world how strategically important open source is to an enterprises’ infrastructure software plans. Among respondents, 69 percent reported that it is extremely important, citing top benefits as lower TCO, access to innovation, security, higher-quality software, support, and the freedom to customize. 

Only 1 percent of survey respondents said it wasn’t important at all. 

Which side of the open-source vs. commercial platforms argument do you come down on?

Contact us to drop us a line and tell us about your project.

Mar 02 2020
Mar 02

As of Drupal 8.7, the Media and Media Library modules can be enabled and used out-of-box. Below, you'll find a quick tutorial on enabling and using these features.

out-of-box before media and media library

In the past there were two different ways to add an image to a page.

  1. An image could be added via a field, with the developer given control over its size and placement:
     

    Image field before media library
  2. An image could be added via the WYSIWYG editor, with the editor given some control over its size and placement:
     

    Image field upload choices screen

A very straightforward process, but these images could not be reused, as they were not part of a reusable media library.

reusing uploaded media Before Drupal 8.7

Overcoming image placement limitations in prior versions of Drupal required the use of several modules, a lot of configuration, and time. Sites could be set up to reference a media library that allowed editors to select and reuse images that had previously been uploaded, which we explained here.

This was a great time to be alive.

What is available with Media Library

Enabling the Media and Media Library modules extends a site's image functionality. First, ensure that the Media and Media Library core modules are enabled. 

Enable media library in drupal

A media entity reference field must be used with the Media Library. It will not work with a regular image field out-of-box.

Image field on manage display page

On the Manage form display page, select "Media library" widget. 

Media library widget on manage display page

On the "Node Add" and "Node Edit" forms, you’ll see the below difference between a regular image field and a field connected to the media library.

Media library field on node edit

Click on “Add media” and you’ll see a popup with the ability to add a new image to the library or to select an image that is already in the library.

Media field grid

With a simple configuration of the field, if multiple media types are allowed in the field, you’ll see vertical tabs for each media type.

Media grid with multiple media types

WYSIWYG configuration

The WYSIWYG editor requires a few steps when configuring the media library for a specific text format. First, a new icon will appear with a musical note overlapping the image icon. This should be added to the active toolbar and the regular image icon should be moved to the available buttons.

wysiwyg toolbar configuration

Under “Enabled filters,” enable “Embed media."  Under the filter settings, vertical tab settings can be chosen for media types and view modes. Once that configuration is saved, you’ll see on a WYSIWYG editor that you have the same popup dialog for adding a new image to the media library, or selecting an already-uploaded image.

wysiwyg media configuration

Once you are on a "Node Add or "Node Edit" page with a WYSIWYG element, you’ll see the media button (image icon plus musical note).

Media button on wysiwyg editor

Clicking on the media button brings up the same, familiar popup that we saw earlier from the image field:

media library grid

This article is an update to a previous explainer from last year. 

Jan 23 2020
Jan 23

In the Drupal support world, working on Drupal 7 sites is a necessity. But switching between Drupal 7 and Drupal 8 development can be jarring, if only for the coding style.

Fortunately, I’ve got a solution that makes working in Drupal 7 more like working in Drupal 8. Use this three-part approach to have fun with Drupal 7 development:

  • Apply Xautoload to keep your PHP skills fresh, modern, and compatible with all frameworks and make your code more reusable and maintainable between projects. 
  • Use the Drupal Libraries API to use third-party libraries. 
  • Use the Composer template to push the boundaries of your programming design patterns. 

Applying Xautoload

Xautoload is simply a module that enables PSR-0/4 autoloading. Using Xautoload is as simple as downloading and enabling it. You can then start using use and namespace statements to write object-oriented programming (OOP) code.

For example:

xautoload.info

name = Xautoload Example
description = Example of using Xautoload to build a page
core = 7.x package = Midcamp Fun

dependencies[] = xautoload:xautoload

xautoload_example.module

<?php use Drupal\xautoload_example\SimpleObject; function xautoload_example_menu() { $items['xautoload_example'] = array( 'page callback' => 'xautoload_example_page_render', 'access callback' => TRUE, ); return $items; } function xautoload_example_page_render() { $obj = new SimpleObject(); return $obj->render(); } use Drupal\xautoload_example\SimpleObject;function xautoload_example_menu() {  $items['xautoload_example'] = array(    'page callback' => 'xautoload_example_page_render',    'access callback' => TRUE,  return $items;function xautoload_example_page_render() {  $obj = new SimpleObject();  return $obj->render();

src/SimpleObject.php

<?php namespace Drupal\xautoload_example; class SimpleObject { public function render() { return array( '#markup' => "<p>Hello World</p>", ); } } namespace Drupal\xautoload_example;class SimpleObject {  public function render() {    return array(      '#markup' => "

Hello World

"
,    );

Enabling and running this code causes the URL /xautoload_example to spit out “Hello World”. 

You’re now ready to add in your own OOP!

Using Third-Party Libraries

Natively, Drupal 7 has a hard time autoloading third-party library files. But there are contributed modules (like Guzzle) out there that wrap third-party libraries. These modules wrap object-oriented libraries to provide a functional interface. Now that you have Xautoload in your repertoire, you can use its functionality to autoload libraries as well.

I’m going to show you how to use the Drupal Libraries API module with Xautoload to load a third-party library. You can find examples of all the different ways you can add a library in xautoload.api.php. I’ll demonstrate an easy example by using the php-loremipsum library:

1. Download your library and store it in sites/all/libraries. I named the folder php-loremipsum. 

2. Add a function implementing hook_libraries_info to your module by pulling in the namespace from Composer. This way, you don’t need to set up all the namespace rules that the library might contain.

function xautoload_example_libraries_info() { return array( 'php-loremipsum' => array( 'name' => 'PHP Lorem Ipsum', 'xautoload' => function ($adapter) { $adapter->composerJson('composer.json'); } ) ); } function xautoload_example_libraries_info() {  return array(    'php-loremipsum' => array(      'name' => 'PHP Lorem Ipsum',      'xautoload' => function ($adapter) {        $adapter->composerJson('composer.json');      }

3. Change the page render function to use the php-loremipsum library to build content.

use joshtronic\LoremIpsum; function xautoload_example_page_render() { $library = libraries_load('php-loremipsum'); if ($library['loaded'] === FALSE) { throw new \Exception("php-loremipsum didn't load!"); } $lipsum = new LoremIpsum(); return array( '#markup' => $lipsum->paragraph('p'), ); } use joshtronic\LoremIpsum;function xautoload_example_page_render() {  $library = libraries_load('php-loremipsum');  if ($library['loaded'] === FALSE) {    throw new \Exception("php-loremipsum didn't load!");  $lipsum = new LoremIpsum();  return array(    '#markup' => $lipsum->paragraph('p'),

Note that I needed  to tell the Libraries API to load the library, but I then have access to all the namespaces within the library. Keep in mind that the dependencies of some libraries are immense. You’ll very likely need to use Composer from within the library and commit it when you first start out. In such cases, you might need to make sure to include the Composer autoload.php file.

Another tip:  Abstract your libraries_load() functionality out in such a way that if the class you want already exists, you don’t call libraries_load() again. Doing so removes libraries as a hard dependency from your module and enables you to use Composer to load the library later on with no more work on your part. For example:

function xautoload_example_load_library() { if (!class_exists('\joshtronic\LoremIpsum', TRUE)) { if (!module_exists('libraries')) { throw new \Exception('Include php-loremipsum via composer or enable libraries.'); } $library = libraries_load('php-loremipsum'); if ($library['loaded'] === FALSE) { throw new \Exception("php-loremipsum didn't load!"); } } } function xautoload_example_load_library() {  if (!class_exists('\joshtronic\LoremIpsum', TRUE)) {    if (!module_exists('libraries')) {      throw new \Exception('Include php-loremipsum via composer or enable libraries.');    $library = libraries_load('php-loremipsum');    if ($library['loaded'] === FALSE) {      throw new \Exception("php-loremipsum didn't load!");

And with that, you’ve conquered the challenge of using third-party libraries!

Setting up a New Site with Composer

Speaking of Composer, you can use it to simplify the setup of a new Drupal 7 site. Just follow the instructions in the Readme for the Composer Template for Drupal Project. From the command line, run the following:

composer create-project drupal-composer/drupal-project:7.x-dev --no-interaction

This code gives you a basic site with a source repository (a repo that doesn’t commit contributed modules and libraries) to push up to your Git provider. (Note that migrating an existing site to Composer involves a few additional considerations and steps, so I won’t get into that now.)

If you’re generating a Pantheon site, check out the Pantheon-specific Drupal 7 Composer project. But wait: The instructions there advise you to use Terminus to create your site, and that approach attempts to do everything for you—including setting up the actual site. Instead, you can simply use composer create-project  to test your site in something like Lando. Make sure to run composer install if you copy down a repo.

From there, you need to enable the Composer Autoload module , which is automatically required in the composer.json you pulled in earlier. Then, add all your modules to the require portion of the file or use composer require drupal/module_name just as you would in Drupal 8.

You now have full access to all the  Packagist libraries and can use them in your modules. To use the previous example, you could remove php-loremipsum from sites/all/libraries, and instead run composer require joshtronic/php-loremipsum. The code would then run the same as before.

Have fun!

From here on out, it’s up to your imagination. Code and implement with ease, using OOP design patterns and reusable code. You just might find that this new world of possibilities for integrating new technologies with your existing Drupal 7 sites increases your productivity as well.

Dec 09 2019
Dec 09

With Drupal 9 set to be released later next year, upgrading to Drupal 8 may seem like a lost cause. However, beyond the fact that Drupal 8 is superior to its predecessors, it will also make the inevitable upgrade to Drupal 9, and future releases, much easier. 

Acquia puts it best in this eBook, where they cover common hangups that may prevent migration to Drupal 8 and the numerous reasons to push past them.

The Benefits of Drupal 8

To put it plainly, Drupal 8 is better. Upon its release, the upgrade shifted the way Drupal operates and has only improved through subsequent patches and iterations, most recently with the release of Drupal 8.8.0

Some new features of Drupal 8 that surpass those of Drupal 7 include improved page building tools and content authoring, multilingual support, and the inclusion of JSON:API as part of Drupal core. We discussed some of these additions in a previous blog post

Remaining on Drupal 7 means hanging on to a less capable CMS. Drupal 8 is simply more secure with better features.

What Does Any of This Have to Do With Drupal 9?

With an anticipated release date of June 3, 2020, Drupal 9 will see the CMS pivot to an iterative release model, moving away from the incremental releases that have made upgrading necessary in the past. That means that migrating to Drupal 8 is the last major migration Drupal sites will have to undertake. As Acquia points out, one might think “Why can’t I just wait to upgrade to Drupal 9?” 

While migration from Drupal 7 or Drupal 8 to Drupal 9 would be essentially the same process, Drupal 7 goes out of support in November 2021. As that deadline approaches, upgrading will only become an increasingly pressing necessity. By migrating to Drupal 8 now, you avoid the complications that come with a hurried migration and can take on the process incrementally. 

So why wait? 

To get started with Drupal migration, be sure to check out our Drupal Development Services, and come back to our blog for more updates and other business insights. 
 

Apr 19 2019
Apr 19

What we learned from our fellow Drupalists

Lisa Mirabile

On April 7th, our team packed up our bags and headed off to Seattle for one of the bigger can’t miss learning events of the year, DrupalCon.

“Whether you’re C-level, a developer, a content strategist, or a marketer — there’s something for you at DrupalCon.” -https://events.drupal.org/

As you may have read in one of our more recent posts, we had a lot of sessions that we couldn’t wait to attend! We were very excited to find new ideas that we could bring back to improve our services for constituents or the agencies we work with to make digital interactions with government fast, easy, and wicked awesome. DrupalCon surpassed our already high expectations.

At the Government Summit, we were excited to speak with other state employees who are interested in sharing knowledge, including collaborating on open-source projects. We wanted to see how other states are working on problems we’ve tried to solve and to learn from their solutions to improve constituents’ digital interactions with government.

One of the best outcomes of the Government Summit was an amazing “birds of a feather” (BOF) talk later in the week. North Carolina’s Digital Services Director Billy Hylton led the charge for digital teams across state governments to choose a concrete next step toward collaboration. At the BOF, more than a dozen Massachusetts, North Carolina, Georgia, Texas, and Arizona digital team members discussed, debated, and chose a content type (“event”) to explore. Even better, we left with a meeting date to discuss specific next steps on what collaborating together could do for our constituents.

The learning experience did not stop at the GovSummit. Together, our team members attended dozens of sessions. For example, I attended a session called “Stanford and FFW — Defaulting to Open” since we are starting to explore what open-sourcing will look like for Mass.gov. The Stanford team’s main takeaway was the tremendous value they’ve found in building with and contributing to Drupal. Quirky fact: their team discovered during user testing among high-school students that “FAQ” is completely mysterious to younger people: they expect the much more straightforward “Questions” or “Help.”

Another session I really enjoyed was called “Pattern Lab: The Definitive How-to.” It was exciting to hear that Pattern Lab, a tool for creating design systems, has officially merged its two separate cores into a single one that supports all existing rendering engines. This means simplifying the technical foundation to allow more focus on extending Pattern Lab in new and useful ways (and less just keeping it up and running). We used Pattern Lab to build Mayflower, the design system created for the Commonwealth of Massachusetts and implemented first on Mass.gov. We are now looking at the best ways to offer the benefits of Mayflower — user-centeredness, accessibility, and consistent look and feel — to more Commonwealth digital properties. Some team members had a chance to talk later to Evan Lovely, the speaker and one of the maintainers of Pattern Lab, and were excited by the possibility of further collaboration to implement Mayflower in more places.

There were a variety of other informative topics. Here are some that my peers and I enjoyed, just to name a few:

Our exhibit hall booth at DrupalCon 2019Talking to fellow Drupalists at our booth

On Thursday we started bright and early to unfurl our Massachusetts Digital Service banner and prepare to greet fellow Drupalists at our booth! We couldn’t have done it without our designer, who put all of our signs together for our first time exhibiting at DrupalCon (Thanks Eva!)

It was remarkable to be able to talk with so many bright minds in one day. Our one-on-one conversations took us on several deep dives into the work other organizations are doing to improve their digital assets. Meeting so many brilliant Drupalists made us all the more excited to share some opportunities we currently have to work with them, such as the ITS74 contract to work with us as a vendor, or our job opening for a technical architect.

We left our table briefly to attend Mass.gov: A Guide to Data-Informed Content Optimization, where team members Julia Gutierrez and Nathan James shared how government agencies in Massachusetts are now making data-driven content decisions. Watch their presentation to learn:

To cap it off, Mass.gov, with partners Last Call Media and Mediacurrent, won Best Theme for our custom admin theme at the first-ever Global Splash awards (established to “recognize the best Drupal projects on the web”)! An admin theme is the look and feel that users see when they log in. The success of Mass.gov rests in the hands of all of its 600+ authors and editors. We’ve known from the start of the project that making it easy and efficient to add or edit content in Mass.gov was key to the ultimate goal: a site that serves constituents as well as possible. To accomplish this, we decided to create a custom admin theme, launched in May 2018.

A before-and-after view of our admin theme

Our goal was not just a nicer looker and feel (though it is that!), but a more usable experience. For example, we wanted authors to see help text before filling out a field, so we brought it up above the input box. And we wanted to help them keep their place when navigating complicated page types with multiple levels of nested information, so we added vertical lines to tie together items at each level.

Last Call Media founder Kelly Albrecht crosses the stage to accept the Splash award for Best Theme on behalf of the Mass.gov Team.All the Splash award winners!

It was a truly enriching experience to attend DrupalCon and learn from the work of other great minds. Our team has already started brainstorming how we can improve our products and services for our partner agencies and constituents. Come back to our blog weekly to check out updates on how we are putting our DrupalCon lessons to use for the Commonwealth of Massachusetts!

Interested in a career in civic tech? Find job openings at Digital Service.
Follow us on Twitter | Collaborate with us on GitHub | Visit our site

Apr 01 2019
Apr 01

Vienna, VA March 19, 2019—Mobomo,

Mobomo, LLC is pleased to announce our award as a prime contractor on the $25M Department of Interior (DOI) Drupal Developer Support Services BPA . Mobomo brings an experienced and extensive Drupal Federal practice team to DOI.  Our team has launched a large number of award winning federal websites in both Drupal 7 and Drupal 8, to include www.nasa.gov, www.usgs.gov, and www.fisheries.noaa.gov.,These sites have won industry recognition and awards including the 2014, 2016, 2017 and 2018 Webby Award; two 2017 Innovate IT awards; and the 2018 MUSE Creative Award and the Acquia 2018 Public Sector Engage award.

DOI has been shifting its websites from an array of Content Management System (CMS) and non-CMS-based solutions to a set of single-architecture, cloud-hosted Drupal solutions. In doing so, DOI requires Drupal support for hundreds of websites that are viewed by hundreds of thousands of visitors each year, including its parent website, www.doi.gov, managed by the Office of the Secretary. Other properties include websites and resources provided by its bureaus  (Bureau of Indian Affairs, Bureau of Land Management, Bureau of Ocean Energy Management, Bureau of Reclamation, Bureau of Safety and Environmental Enforcement, National Park Service, Office of Surface Mining Reclamation and Enforcement, U.S. Fish and Wildlife Service, U.S. Geological Survey) and many field offices.

This BPA provides that support. The period of performance for this BPA is five years and it’s available agency-wide and to all bureaus as a vehicle for obtaining Drupal development, migration, information architecture, digital strategy, and support services. Work under this BPA will be hosted in DOI’s OpenCloud infrastructure, which was designed for supporting the Drupal platform.

Mar 13 2019
Mar 13

Note: This post refers to Drupal 8, but is very applicable to Drupal 7 sites as well

Most Drupal developers are experienced building sitewide search with Search API and Views. But it’s easy to learn and harder to master. These are the most common mistakes I see made when doing this task:

Not reviewing Analytics

Before you start, make sure you have access to analytics if relevant. You want to get an idea of how much sitewide search is being used and what the top searches are. On many sites, sitewide search usage is extremely low and you may need to explain this statistic to stakeholders asking for any time-consuming search features (and yourself before you start going down rabbit holes of refinements).

Take a look for yourself at how the sitewide search is currently performing for the top keywords users are giving it. Do the relevant pages come up first? You’ll take this into account when configuring boosts.

Using Solr for small sites

Drupal 8 Search API comes with database search included. Search API DB has come a long way over the years and is likely to have the features you need for smaller sites. Using a Solr backend is going to add complexity that may not be worth it for the amount of value your sitewide search is giving. Remember, if you use a Solr backend you have to have Solr running on all environments used in the project and you’ll have to reindex when you sync databases.

Not configuring all environments for working Solr

Which takes us to this one. If you do use Solr (or another server-side index) you need to also make sure your team has Solr running on their local environments and has an index for the site. 

Your settings.php needs to be configured to connect to the right index on each environment. We use Probo for review sandboxes so we need to configure our Probo builds to use the right search index and to index it on build.

Missing fields in index or wrong type

Always included the ‘Rendered HTML’ field in your search index rather than trying to capture every text field on all your content types and then having to come back to add more every time you add a field. Include the title field as well, but don’t forget to use ‘Fulltext’ as its field type. Only ‘Fulltext’ text fields are searchable by word.

Not configuring boosts

In your Processor settings, use Type-specific boosting and Tag-boosting via HTML filter. Tag boosting is straightforward: boost headers. For type-specific boosting you’re not necessarily just boosting the most important content types, but also thinking about what’s in the index and what people are likely looking for. Go back to your analytics for this. 

For example, when someone searches for a person’s name, are they likely wanting the top result to be the bio and contact info, a news posting mentioning that person, or a white paper authored by the person? So, even if staff bios are not the most important content on the site, perhaps they will need to be boosted high in search, where they are very relevant.

Not ordering by relevance

Whoops. This is a very common and devastating mistake. All your boost work be damned if you forget this. The View you make for search results needs to order results by Relevance: Descending.

Using AJAX

Don’t use the setting to ‘Use AJAX’ on your search results View. Doing so would mean that search results don’t have unique URLs, which is bad for user experience and analytics. It’s all about the URLs not about the whizzbang.

Not customizing the query string

Any time you configure a View with an exposed filter, take the extra second to customize the query string it is going to use. ‘search’ is a better query string than ‘search_api_fulltext’ for the search filter. URLs are part of your user interface.

No empty text

Similarly, when you add an exposed filter to a search you should also almost always be adding empty text. “No results match your search” is usually appropriate.

Facets that don’t speak to the audience

Facets can be useful for large search indexes and certain types of sites. But too many or too complex facets just create confusion. ‘Content-type’ is a very common facet, but if you use it, make sure you only include in its options the names of content types that are likely to make sense to visitors. For example, I don’t expect my visitors to understand the technical distinction between a ‘page’ and a ‘landing page’ so I don’t include facet links for these.

A screen shot of facets in DrupalYou can exclude confusing facet options 

Making search results page a node

I tell my team to make just about every page a visitor sees a node. This simplifies things for both editors and developers. It also ensures every page is in the search index: If you make key landing pages like ‘Events Calendar’ as Views pages or as custom routes these key pages will not be found in your search results. 

One important exception is the Search Results page itself. You don’t want your search results page in the search index: this can actually make an infinite loop when you search. Let this one be a Views page, not a Views block you embed into a node.

Important page content not in the ‘content’

Speaking of blocks and nodes, the way you architect your site will determine how well your search works. If you build your pages by placing blocks via core Block Layout, these blocks are not part of the page ‘content’ that gets indexed in the ‘Rendered HTML.’ Anything you want to be searchable needs to be part of the content. 

You can embed blocks in node templates with Twig Tweak, or you can reference blocks as part of the content (I use Paragraphs and Block Field.)

Not focusing on accessibility

The most accessible way to handle facets is to use ‘List of Links’ widget. You can also add some visually hidden help text just above your facet links. A common mistake is to hide the ‘Search’ label on the form. Instead of display: none, use the ‘visually-hidden’ class.

Nov 09 2018
Nov 09

Last week, the Children’s Hospital of Philadelphia (CHOP) Vaccine Makers Project (VMP) won a PR News Digital Award in the category “Redesign/Relaunch of Site.” The awards gala honors the year’s best and brightest campaigns across a variety of media. 

PR News Award on a table.

Our CEO, Alex, and our Director of Client Engagement, Aaron, along with members of the Vaccine Makers team attended the event at the Yale Club in New York City.

Screenshot of a Tweet posted by the PR News. Source

The Vaccine Makers Project (VMP) is a subset of CHOP’s Vaccine Education Center (VEC). It’s a public education portal for students and teachers that features resources such as lesson plans, downloadable worksheets, and videos. 

The Vaccine Makers team first approached us in need of a site that aligned with the branding of CHOP’s existing site. They also wanted a better strategy for site organization and resource classification. Our team collaborated with theirs to build a new site that’s easy to navigate for all users. You can learn more about the project here.

Screenshot of a Tweet from Vaccine Makers team. Source

We’d like to thank CHOP and the Vaccine Makers team for giving us the opportunity to work on this project. We’d also like to thank PR News for recognizing our work and hosting such a wonderful event. 

Finally, we’d like to congratulate our incredible team for their endless effort and dedication to this project. 
 

Oct 29 2018
Oct 29

At this year's BADCamp, our Senior Web Architect Nick Lewis led a session on Gatsby and the JAMstack. The JAMStack is a web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup. Gatsby is one of the leading JAMstack based static page generators, and this session primarily covers how to integrate it with Drupal. 

Our team has been developing a "Gatsby Drupal Kit" over the past few months to help jump start Gatsby-Drupal integrations. This kit is designed to work with a minimal Drupal install as a jumping off point, and give a structure that can be extended to much larger, more complicated sites.

This session will leave you with: 

1. A base Drupal 8 site that is connected with Gatsby.  

2. Best practices for making Gatsby work for real sites in production.

3. Sane patterns for translating Drupal's structure into Gatsby components, templates, and pages.

This is not an advanced session for those already familiar with React and Gatsby. Recommended prerequisites are a basic knowledge of npm package management, git, CSS, Drupal, web services, and Javascript. Watch the full session below. 

Oct 23 2018
Oct 23

PHP 5.6 will officially be no longer supported through security fixes on December 31, 2018. This software has not been actively developed for a number of years, but people have been slow to jump on the bandwagon. Beginning in the new year, no bug fixes will be released for this version of PHP. This opens the door for a dramatic increase in security risks if you are not beginning the new year on a version of PHP 7. PHP 7 was released back in December 2015 and PHP 7.2 is the latest version that you can update to. PHP did skip over 6; so don’t even try searching for it.

Drupal 8.6 is the final Drupal version that will support PHP 5.6. Many other CMS’s will be dropping their support for PHP 5.6 in their latest versions as well. Simply because it is supported in that version does not mean that you will be safe from the security bugs; you will still need to upgrade your PHP version before December 31, 2018. In addition to the security risks, you have already been missing out on many improvements that have been made to PHP.

What Should You Do About This?

You are probably thinking “Upgrade, I get it.” It may actually be more complicated than that and you will need to refactor. 90-95% of your code should be fine. The version your CMS is may affect the complexity of your conversion. Most major CMS’s will handle PHP 7 right out of the box in their most recent versions.

By upgrading to a version of PHP 7, you will see a variety of performance improvements; the most dramatic being speed. The engine behind PHP, Zend Technologies, ran performance tests on a variety of PHP applications to compare the performance of PHP 7 vs PHP 5.6. These tests compared requests per second across the two versions. This relates to the speed at which code is executed, and how fast queries to the database and server are returned. These tests showed that PHP 7 runs twice as fast and you will see additional improvements in memory consumption.

How Can Mobomo Help?

Mobomo’s team is highly experienced, not only in assisting with your conversion, but with the review of your code to ensure your environment is PHP 7 ready.  Our team of experts will review your code and uncover the exact amount of code that needs to be converted. There are a good number of factors that could come into play and affect your timeline. The more customizations and smaller plugins that your site contains, the more complex your code review and your eventual conversion could be. Overall, depending on the complexity of the code, your timeline could vary but this would take a maximum of 3 weeks.

Important Things to Know:

  1. How many contributed modules does your site contain?
  2. How many custom modules does your site contain?
  3. What does your environment look like?
Sep 28 2018
Sep 28

Pairing Composer template for Drupal Projects with Lando gives you a fully working Drupal environment with barely any setup.

Lando is an open-source, cross-platform local development environment. It uses Docker to build containers for well-known frameworks and services written in simple recipes. If you haven’t started using Lando for your local development, we highly recommend it. It is easier, faster, and relatively pain-free compared to MAMP, WAMP, VirtualBox VMs, Vagrant or building your own Docker infrastructure.

Prerequisites

You’ll need to have Composer and Lando installed:

Setting up Composer Template Drupal Project

If you want to find details about what you are getting when you install the drupal-project you can view the repo. Otherwise, if you’d rather simply set up a Drupal template site, run the following command.

composer create-project drupal-composer/drupal-project:8.x-dev [your-project] --stability dev --no-interaction

Once that is done running, cd into the newly created directory. You’ll find that you now have a more than basic Drupal installation.

Getting the site setup on Lando

Next, run lando init, which prompts you with 3 simple questions:

? What recipe do you want to use? > drupal8
? Where is your webroot relative to the init destination? > web
? What do you want to call this app? > [your-project]

Once that is done provisioning, run lando start—which downloads and spins up the necessary containers. Providing you with a set of URLs that you can use to visit your site:

https://localhost:32807
http://localhost:32808
http://[your-project].lndo.site:8000
https://[your-project].lndo.site

Setup Drupal

Visit any of the URLs to initialize the Drupal installation flow. Run lando info to get the database detail:

Database: drupal8
Username: drupal8
Password: drupal8
Host: database

Working with your new Site

One of the useful benefits of using Lando is that your toolchain does not need to be installed on your local machine, it can be installed in the Docker container that Lando uses. Meaning you can use commands provided by Lando without having to install other packages. The commands that come with Lando include lando drush, lando drupal, and lando composer. Execute these commands in your command prompt as usual, though they'll execute from within the container.

Once you commit your lando.yml file others can use the same Lando configuration on their machines. Having this shared configuration makes it easy to share and set up local environments that have the same configuration.

Jul 26 2018
Jul 26

Intro

In this post, I’m going to run through how I set up visual regression testing on sites. Visual regression testing is essentially the act of taking a screenshot of a web page (whether the whole page or just a specific element) and comparing that against an existing screenshot of the same page to see if there are any differences.

There’s nothing worse than adding a new component, tweaking styles, or pushing a config update, only to have the client tell you two months later that some other part of the site is now broken, and you discover it’s because of the change that you pushed… now it’s been two months, and reverting that change has significant implications.

That’s the worst. Literally the worst.

All kinds of testing can help improve the stability and integrity of a site. There’s Functional, Unit, Integration, Stress, Performance, Usability, and Regression, just to name a few. What’s most important to you will change depending on the project requirements, but in my experience, Functional and Regression are the most common, and in my opinion are a good baseline if you don’t have the capacity to write all the tests.

If you’re reading this, you probably fall into one of two categories:

  1. You’re already familiar with Visual Regression testing, and just want to know how to do it
  2. You’re just trying to get info on why Visual Regression testing is important, and how it can help your project.

In either case, it makes the most sense to dive right in, so let’s do it.

Tools

I’m going to be using WebdriverIO to do the heavy lifting. According to the website:

WebdriverIO is an open source testing utility for nodejs. It makes it possible to write super easy selenium tests with Javascript in your favorite BDD or TDD test framework.

It basically sends requests to a Selenium server via the WebDriver Protocol and handles its response. These requests are wrapped in useful commands and can be used to test several aspects of your site in an automated way.

I’m also going to run my tests on Browserstack so that I can test IE/Edge without having to install a VM or anything like that on my mac.

Process

Let’s get everything setup. I’m going to start with a Drupal 8 site that I have running locally. I’ve already installed that, and a custom theme with Pattern Lab integration based on Emulsify.

We’re going to install the visual regression tools with npm.

If you already have a project running that uses npm, you can skip this step. But, since this is a brand new project, I don’t have anything using npm, so I’ll create an initial package.json file using npm init.

  • npm init -y
    • Update the name, description, etc. and remove anything you don’t need.
    • My updated file looks like this:
{ "name": "visreg", "version": "1.0.0", "description": "Website with visual regression testing", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" } }   "name": "visreg",  "version": "1.0.0",  "description": "Website with visual regression testing",  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1"

Now, we’ll install the npm packages we’ll use for visual regression testing.

  • npm install --save-dev webdriverio chai wdio-mocha-framework wdio-browserstack-service wdio-visual-regression-service node-notifier
    • This will install:
      • WebdriverIO: The main tool we’ll use
      • Chai syntax support: “Chai is an assertion library, similar to Node’s built-in assert. It makes testing much easier by giving you lots of assertions you can run against your code.”
      • Mocha syntax support “Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun.”
      • The Browserstack wdio package So that we can run our tests against Browserstack, instead of locally (where browser/OS differences across developers can cause false-negative failures)
      • Visual regression service This is what provides the screenshot capturing and comparison functionality
      • Node notifier This is totally optional but supports native notifications for Mac, Linux, and Windows. We’ll use these to be notified when a test fails.

Now that all of the tools are in place, we need to configure our visual regression preferences.

You can run the configuration wizard by typing ./node_modules/webdriverio/bin/wdio, but I’ve created a git repository with not only the webdriver config file but an entire set of files that scaffold a complete project. You can get them here.

Follow the instructions in the README of that repo to install them in your project.

These files will get you set up with a fairly sophisticated, but completely manageable visual regression testing configuration. There are some tweaks you’ll need to make to fit your project that are outlined in the README and the individual markdown files, but I’ll run through what each of the files does at a high level to acquaint you with each.

  • .gitignore
    • The lines in this file should be added to your existing .gitignore file. It’ll make sure your diffs and latest images are not committed to the repo, but allow your baselines to be committed so that everyone is comparing against the same baseline images.
  • VISREG-README.md
    • This is an example readme you can include to instruct other/future developers on how to run visual regression tests once you have it set up
  • package.json
    • This just has the example test scripts. One for running the full suite of tests, and one for running a quick test, handy for active development. Add these to your existing package.json
  • wdio.conf.js
    • This is the main configuration file for WebdriverIO and your visual regression tests.
    • You must update this file based on the documentation in wdio.conf.md
  • wdio.conf.quick.js
    • This is a file you can use to run a quick test (e.g. against a single browser instead of the full suite defined in the main config file). It’s useful when you’re doing something like refactoring an existing component, and/or want to make sure changes in one place don’t affect other sections of the site.
  • tests/config/globalHides.js
    • This file defines elements that should be hidden in ALL screenshots by default. Individual tests can use this, or define their own set of elements to hide. Update these to fit your actual needs.
  • tests/config/viewports.js
    • This file defines what viewports your tests should run against by default. Individual tests can use these, or define their own set of viewports to test against. Update these to the screen sizes you want to check.

Running the Test Suite

I’ll copy the example homepage test from the example-tests.md file into a new file /web/themes/custom/visual_regression_testing/components/_patterns/05-pages/home/home.test.js. (I’m putting it here because my wdio.conf.js file is looking for test files in the _patterns directory, and I like to keep test files next to the file they’re testing.)

The only thing you’ll need to update in this file is the relative path to the globalHides.js file. It should be relative from the current file. So, mine will be:

const visreg = require('../../../../../../../../tests/config/globalHides.js'); const visreg = require('../../../../../../../../tests/config/globalHides.js');

With that done, I can simply run npm test and the tests will run on BrowserStack against the three OS/Browser configurations I’ve specified. While they’re running, we can head over to https://automate.browserstack.com/ we can see the tests being run against Chrome, Firefox, and IE 11.

Once tests are complete, we can view the screenshots in the /tests/screenshots directory. Right now, the baseline shots and the latest shots will be identical because we’ve only run the test once, and the first time you run a test, it creates the baseline from whatever it sees. Future tests will compare the most recent “latest” shot to the existing baseline, and will only update/create images in the latest directory.

At this point, I’ll commit the baselines to the git repo so that they can be shared around the team, and used as baselines by everyone running visual regression tests.

If I run npm test again, the tests will all pass because I haven’t changed anything. I’ll make a small change to the button background color which might not be picked up by a human eye but will cause a regression that our tests will pick up with no problem.

In the _buttons.scss file, I’m going to change the default button background color from $black (#000) to $gray-darker (#333). I’ll run the style script to update the compiled css and then clear the site cache to make sure the change is implemented. (When actively developing, I suggest disabling cache and keeping the watch task running. It just makes things easier and more efficient.)

This time all the tests fail, and if we look at the images in the diff folder, we can clearly see that the “search” button is different as indicated by the bright pink/purple coloring.

If I open up one of the “baseline” images, and the associated “latest” image, I can view them side-by-side, or toggle back and forth. The change is so subtle that a human eye might not have noticed the difference, but the computer easily identifies a regression. This shows how useful visual regression testing can be!

Let’s pretend this is actually a desired change. The original component was created before the color was finalized, black was used as a temporary color, and now we want to capture the update as the official baseline. Simply Move the “latest” image into the “baselines” folder, replacing the old baseline, and commit that to your repo. Easy peasy.

Running an Individual Test

If you’re creating a new component and just want to run a single test instead of the entire suite, or you run a test and find a regression in one image, it is useful to be able to just run a single test instead of the entire suite. This is especially true once you have a large suite of test files that cover dozens of aspects of your site. Let’s take a look at how this is done.

I’ll create a new test in the organisms folder of my theme at /search/search.test.js. There’s an example of an element test in the example-tests.md file, but I’m going to do a much more basic test, so I’ll actually start out by copying the homepage test and then modify that.

The first thing I’ll change is the describe section. This is used to group and name the screenshots, so I’ll update it to make sense for this test. I’ll just replace “Home Page” with “Search Block”.

Then, the only other thing I’m going to change is what is to be captured. I don’t want the entire page, in this case. I just want the search block. So, I’ll update checkDocument (used for full-page screenshots) to checkElement (used for single element shots). Then, I need to tell it what element to capture. This can be any css selector, like an id or a class. I’ll just inspect the element I want to capture, and I know that this is the only element with the search-block-form class, so I’ll just use that.

I’ll also remove the timeout since we’re just taking a screenshot of a single element, we don’t need to worry about the page taking longer to load than the default of 60 seconds. This really wasn’t necessary on the page either, but whatever.

My final test file looks like this:

const visreg = require('../../../../../../../../tests/config/globalHides.js'); describe('Search Block', function () { it('should look good', function () { browser .url('./') .checkElement('.search-block-form', {hide: visreg.hide, remove: visreg.remove}) .forEach((item) => { expect(item.isWithinMisMatchTolerance).to.be.true; }); }); }); const visreg = require('../../../../../../../../tests/config/globalHides.js');describe('Search Block', function () {  it('should look good', function () {    browser      .url('./')      .checkElement('.search-block-form', {hide: visreg.hide, remove: visreg.remove})      .forEach((item) => {        expect(item.isWithinMisMatchTolerance).to.be.true;      });

With that in place, this test will run when I use npm test because it’s globbing, and running every file that ends in .test.js anywhere in the _patterns directory. The problem is this also runs the homepage test. If I just want to update the baselines of a single test, or I’m actively developing a component and don’t want to run the entire suite every time I make a locally scoped change, I want to be able to just run the relevant test so that I don’t waste time waiting for all of the irrelevant tests to pass.

We can do that by passing the --spec flag.

I’ll commit the new test file and baselines before I continue.

Now I’ll re-run just the search test, without the homepage test.

npm test -- --spec web/themes/custom/visual_regression_testing/components/_patterns/03-organisms/search/search.test.js

We have to add the first set of -- because we’re using custom npm scripts to make this work. Basically, it passes anything that follows directly to the custom script (in our case test is a custom script that calls ./node_modules/webdriverio/bin/wdio). More info on the run-script documentation page.

If I scroll up a bit, you’ll see that when I ran npm test there were six passing tests. That is one test for each browser for each test. We have two test, and we’re checking against three browsers, so that’s a total of six tests that were run.

This time, we have three passing tests because we’re only running one test against three browsers. That cut our test run time by more than half (from 106 seconds to 46 seconds). If you’re actively developing or refactoring something that already has test coverage, even that can seem like an eternity if you’re running it every few minutes. So let’s take this one step further and run a single test against a single browser. That’s where the wdio.conf.quick.js file comes into play.

Running Test Against a Subset of Browsers

The wdio.conf.quick.js file will, by default, run test(s) against only Chrome. You can, of course, change this to whatever you want (for example if you’re only having an issue in a specific version of IE, you could set that here), but I’m just going to leave it alone and show you how to use it.

You can use this to run the entire suite of tests or just a single test. First, I’ll show you how to run the entire suite against only the browser defined here, then I’ll show you how to run a single test against this browser.

In the package.json file, you’ll see the test:quick script. You could pass the config file directly to the first script by typing npm test -- wdio.conf.quick.js, but that’s a lot more typing than npm run test:quick and you (as well as the rest of your team) have to remember the file name. Capturing the file name in a second custom script simplifies things.

When I run npm run test:quick You’ll see that two tests were run. We have two tests, and they’re run against one browser, so that simplifies things quite a bit. And you can see it ran in only 31 seconds. That’s definitely better than the 100 seconds the full test suite takes.

Let’s go ahead and combine this with the technique for running a single test to cut that time down even further.

npm run test:quick -- --spec web/themes/custom/visual_regression_testing/components/_patterns/03-organisms/search/search.test.js

This time you’ll see that it only ran one test against one browser and took 28 seconds. There’s actually not a huge difference between this and the last run because we can run three tests in parallel. And since we only have two tests, we’re not hitting the queue which would add significantly to the entire test suite run time. If we had two dozen tests, and each ran against three browsers, that’s a lot of queue time, whereas even running the entire suite against one browser would be a significant savings. And obviously, one test against one browser will be faster than the full suite of tests and browsers.

So this is super useful for active development of a specific component or element that has issues in one browser as well as when you’re refactoring code to make it more performant, and want to make sure your changes don’t break anything significant (or if they do, alert you sooner than later). Once you’re done with your work, I’d still recommend running the full suite to make sure your changes didn’t inadvertently affect another random part of the site.

So, those are the basics of how to set up and run visual regression tests. In the next post, I’ll dive into our philosophy of what we test, when we test, and how it fits into our everyday development workflow.

Jul 23 2018
Jul 23
Moshe Weitzman

I recently worked with the Mass.gov team to transition its development environment from Vagrant to Docker. We went with “vanilla Docker,” as opposed to one of the fine tools like DDev, Drupal VM, Docker4Drupal, etc. We are thankful to those teams for educating and showing us how to do Docker right. A big benefit of vanilla Docker is that skills learned there are generally applicable to any stack, not just LAMP+Drupal. We are super happy with how this environment turned out. We are especially proud of our MySQL Content Sync image — read on for details!

Pretty docks at Boston Harbor. Photo credit.

The heart of our environment is the docker-compose.yml. Here it is, then read on for a discussion about it.

Developers use .env files to customize aspects of their containers (e.g. VOLUME_FLAGS, PRIVATE_KEY, etc.). This built-in feature of Docker is very convenient. See our .env.example file:

The most innovative part of our stack is the mysql container. The Mass.gov Drupal database is gigantic. We have tens of thousands of nodes and 500,000 revisions, each with an unholy number of paragraphs, reference fields, etc. Developers used to drush sql:sync the database from Prod as needed. The transfer and import took many minutes, and had some security risk in the event that sanitization failed on the developer’s machine. The question soon became, “how can we distribute a mysql database that’s already imported and sanitized?” It turns out that Docker is a great way to do just this.

Today, our mysql container builds on CircleCI every night. The build fetches, imports, and sanitizes our Prod database. Next, the build does:

That is, we commit and push the refreshed image to a private repository on Docker Cloud. Our mysql image is 9GB uncompressed but thanks to Docker, it compresses to 1GB. This image is really convenient to use. Developers fetch a newer image with docker-compose pull mysql. Developers can work on a PR and then when switching to a new PR, do a simple ahoy down && ahoy up. This quickly restores the local Drupal database to a pristine state.

In order for this to work, you have to store MySQL data *inside* the container, instead of using a Docker Volume. Here is the Dockerfile for the mysql image.

Our Drupal container is open source — you can see exactly how it’s built. We start from the official PHP image, then add PHP extensions, Apache config, etc.

An interesting innovation in this container is the use of Docker Secrets in order to safely share an SSH key from host to the container. See this answer and mass_id_rsa in the docker-compose.yml above. Also note the two files below which are mounted into the container:

Configure SSH to use the secrets file as private keyAutomatically run ssh-add when logging into the container

Traefik is a “cloud edge router” that integrates really well with docker-compose. Just add one or two labels to a service and its web site is served through Traefik. We use Traefik to provide nice local URLs for each of our services (www.mass.local, portainer.mass.local, mailhog.mass.local, …). Without Traefik, all these services would usually live at the same URL with differing ports.

In the future, we hope to upgrade our local sites to SSL. Traefik makes this easy as it can terminate SSL. No web server fiddling required.

Our repository features a .ahoy.yml file that defines helpful aliases (see below). In order to use these aliases, developers download Ahoy to their host machine. This helps us match one of the main attractions of tools like DDev/Lando — their brief and useful CLI commands. Ahoy is a convenience feature and developers who prefer to use docker-compose (or their own bash aliases) are free to do so.

Our development environment comes with 3 fine extras:

  • Blackfire is ready to go — just run ahoy blackfire [URL|DrushCommand] and you’ll get back a URL for the profiling report
  • Xdebug is easily enabled by setting the XDEBUG_ENABLE environment variable in a developer’s .env file. Once that’s in place, the PHP in the container will automatically connect to the host’s PHPStorm or other Xdebug client
  • A chrome-headless container is used by our suite which incorporates Drupal Test Traits — a new open source project we published. We will blog about DTT soon

Of course, we are never satisfied. Here are a couple issues to tackle:

Mar 23 2017
Mar 23

Preface

We recently had the opportunity to work on a Symfony app for one of our Higher Ed clients that we recently built a Drupal distribution for. Drupal 8 moving to Symfony has enabled us to expand our service offering. We have found more opportunities building apps directly using Symfony when a CMS is not needed. This post is not about Drupal, but cross posting to Drupal Planet to demonstrate the value of getting off the island. Enjoy!

Writing custom authentication schemes in Symfony used to be on the complicated side. But with the introduction of the Guard authentication component, it has gotten a lot easier.

One of our recent projects required use to interface with Shibboleth to authenticate users into the application. The application was written in Symfony 2 and was using this bundle to authenticate with Shibboleth sessions. However, since we were rewriting everything in Symfony 3 which the bundle is not compatible with, we had to look for a different solution. Fortunately for us, the built-in Guard authentication component turns out to be a sufficient solution, which allows us to drop a bundle dependency and only requiring us to write only one class. Really neat!

How Shibboleth authentication works

One way Shibboleth provisions a request with an authenticated entity is by setting a "remote user" environment variable that the web-server and/or residing applications can peruse.

There is obviously more to Shibboleth than that; it has to do a bunch of stuff to do the actual authenticaiton process. We defer all the heavy-lifting to the mod_shib Apache2 module, and rely on the availability of the REMOTE_USER environment variable to identify the user.

That is pretty much all we really need to know; now we can start writing our custom Shibboleth authentication guard:



namespace AppBundle\Security\Http;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;

class ShibbolethAuthenticator extends AbstractGuardAuthenticator implements LogoutSuccessHandlerInterface
{
    
    private $idpUrl;

    
    private $remoteUserVar;

    
    private $urlGenerator;

    public function __construct(UrlGeneratorInterface $urlGenerator, $idpUrl, $remoteUserVar = null)
    {
        $this->idpUrl = $idpUrl;
        $this->remoteUserVar = $remoteUserVar ?: 'HTTP_EPPN';
        $this->urlGenerator = $urlGenerator;
    }

    protected function getRedirectUrl()
    {
        return $this->urlGenerator->generateUrl('shib_login');
    }

    
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $redirectTo = $this->getRedirectUrl();
        if (in_array('application/json', $request->getAcceptableContentTypes())) {
            return new JsonResponse(array(
                'status' => 'error',
                'message' => 'You are not authenticated.',
                'redirect' => $redirectTo,
            ), Response::HTTP_FORBIDDEN);
        } else {
            return new RedirectResponse($redirectTo);
        }
    }

    
    public function getCredentials(Request $request)
    {
        if (!$request->server->has($this->remoteUserVar)) {
            return;
        }

        $id = $request->server->get($this->remoteUserVar);

        if ($id) {
            return array('eppn' => $id);
        } else {
            return null;
        }
    }

    
    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        return $userProvider->loadUserByUsername($credentials['eppn']);
    }

    
    public function checkCredentials($credentials, UserInterface $user)
    {
        return true;
    }

    
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        $redirectTo = $this->getRedirectUrl();
        if (in_array('application/json', $request->getAcceptableContentTypes())) {
            return new JsonResponse(array(
                'status' => 'error',
                'message' => 'Authentication failed.',
                'redirect' => $redirectTo,
            ), Response::HTTP_FORBIDDEN);
        } else {
            return new RedirectResponse($redirectTo);
        }
    }

    
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        return null;
    }

    
    public function supportsRememberMe()
    {
        return false;
    }

    
    public function onLogoutSuccess(Request $request)
    {
        $redirectTo = $this->urlGenerator->generate('shib_logout', array(
            'return'  => $this->idpUrl . '/profile/Logout'
        ));
        return new RedirectResponse($redirectTo);
    }
}

Let's break it down:

  1. class ShibbolethAuthenticator extends AbstractGuardAuthenticator ... - We'll extend the built-in abstract to take care of the non-Shibboleth specific plumbing required.
  2. __construct(...) - As you would guess, we are passing in all the things we need for the authentication guard to work; we are getting the Shibboleth iDP URL, the remote user variable to check, and the URL generator service which we need later.
  3. getRedirectUrl() - This is just a convenience method which returns the Shibboleth login URL.
  4. start(...) - This is where everything begins; this method is responsible for producing a request that will help the Security component drive the user to authenticate. Here, we are simply either 1.) redirecting the user to the Shibboleth login page; or 2.) producing a JSON response that tells consumers that the request is forbidden, if the client is expecting application/json content back. In which case, the payload will conveniently inform consumers where to go to start authenticating via the redirect property. Our front-end application knows how to handle this.
  5. getCredentials(...) - This method is responsible for extracting authentication credentials from the HTTP request i.e. username and password, JWT token in the Authorization header, etc. Here, we are interested in the remote user environment variable that mod_shib might have set for us. It is important that we check that the environment variable is actually not empty because mob_shib will still have it set but leaves it empty for un-authenticated sessions.
  6. getUser(...) - Here we get the credentials that getCredentials(...) returned and construct a user object from it. The user provider will also be passed into this method; whatever it is that is configured for the firewall.
  7. checkCredentials(...) - Following the getUser(...) call, the security component will call this method to actually verify whether or not the authentication attempt is valid. For example, in form logins, this is where you would typically check the supplied password against the encrypted credentials in the the data-store. However we only need to return true unconditionally, since we are trusting Shibboleth to filter out invalid credentials and only let valid sessions to get through to the application. In short, we are already expecting a pre-authenticated request.
  8. onAuthenticationFailure(...) - This method is called whenever our authenticator reports invalid credentials. This shouldn't really happen in the context of a pre-authenticated request as we 100% entrust the process to Shibboleth, but we'll fill this in with something reasonable anyway. Here we are simply replicating what start(...) does.
  9. onAuthenticationSuccess(...) - This method gets called when the credential checks out, which is all the time. We really don't have to do anything but to just let the request go through. Theoretically, this would be there we can bootstrap the token with certain roles depending on other Shibboleth headers present in the Request object, but we really don't need to do that in our application.
  10. supportsRememberMe(...) - We don't care about supporting "remember me" functionality, so no, thank you!
  11. onLogoutSuccess(...) - This is technically not part of the Guard authentication component, but to the logout authentication handler. You can see that our ShibbolethAuthenticator class also implements LogoutSuccessHandlerInterface which will allow us to register it as a listener to the logout process. This method will be responsible for clearing out Shibboleth authentication data after Symfony has cleared the user token from the system. To do this we just need to redirect the user to the proper Shibboleth logout URL, and seeding the return parameter to the nice logout page in the Shibboleth iDP instance.

Configuring the router: shib_login and shib_logout routes

We'll update app/config/routing.yml:



shib_login:
  path: /Shibboleth.sso/Login

shib_logout:
  path: /Shibboleth.sso/Logout

You maybe asking yourself why we even bother creating known routes for these while we can just as easily hard-code these values to our guard authenticator.

Great question! The answer is that we want to be able to configure these to point to an internal login form for local development purposes, where there is no value in actually authenticating with Shibboleth, if not impossible. This allows us to override the shib_login path to /login within routing_dev.yml so that the application will redirect us to the proper login URL in our dev environment.

We really can't point shib_logout to /logout, though, as it will result in an infinite redirection loop. What we do is override it in routing_dev.yml to go to a very simple controller-action that replicates Shibboleth's logout URL external behavior:



...

  public function mockShibbolethLogoutAction(Request $request)
  {
      $return = $request->get('return');

      if (!$return) {
          return new Response("`return` query parameter is required.", Response::HTTP_BAD_REQUEST);
      }

      return $this->redirect($return);
  }
}

Configuring the firewall

This is the last piece of the puzzle; putting all these things together.







services:
  app.shibboleth_authenticator:
    class: AppBundle\Security\Http\ShibbolethAuthenticator
    arguments:
      - '@router'
      - '%shibboleth_idp_url%'
      - '%shibboleth_remote_user_var%'

---






imports:
  - { resources: config.yml }
  - { resources: security.yml }

---

imports:
  - { resources: config.yml }
  - { resources: security_dev.yml } 

---






security:
  firewall:
    main:
      stateless: true
      guard:
        authenticators:
          - app.shibboleth_authenticator

      logout:
        path: /logout
        success_handler: app.shibboleth_authenticator

---





security:
  firewall:
    main:
      stateless: false
      form_login:
        login_path: shib_login
        check_path: shib_login
        target_path_parameter: return

The star here is actually just what's in the security.yml file, specifically the guard section; that's how simple it is to support custom authentication via the Guard authentication component! It's just a matter of pointing it to the service and it will hook it up for us.

The logout configuration tells the application to allocate the /logout path to initiate the logout process which will eventually call our service to clean up after ourselves.

You also notice that we actually have security_dev.yml file here that config_dev.yml imports. This isn't how the Symfony 3 framework ships, but this allows us to override the firewall configuration specifically for dev environments. Here, we add the form_login authentication scheme to support logging in via an in-memory user-provider (not shown). The authentication guard will redirect us to the in-app login form instead of the Shibboleth iDP during development.

Also note the stateless configuration difference between prod and dev: We want to keep the firewall in production environments stateless; this just means that our guard authenticator will get consulted in all requests. This ensures that users will actually be logged out from the application whenever they are logged out of the Shibboleth iDP i.e. when they quit the web browser, etc. However we need to configure the firewall to be stateful during development, otherwise the form_login authentication will not work as expected.

Conclusion

I hope I was able to illustrate how versatile the Guard authentication component in Symfony is. What used to require multiple classes to be written and wired together now only requires a single class to implement, and its very trivial to configure. The Symfony community has really done a great job at improving the Developer Experience (DX).

Setting pre-authenticated requests via environment variables isn't just used by mod_shib, but also by other authentication modules as well, like mod_auth_kerb, mod_auth_gssapi, and mod_auth_cas. It's a well-adopted scheme that Symfony actually ships with a remote_user authentication listener starting 2.6 that makes it very easy to integrate with them. Check it out if your needs are simpler i.e. no custom authentication-starter/redirect logic, etc.

Aug 09 2016
Aug 09

If automated testing is not already part of your development workflow, then it’s time to get started. In this post, I’ll show you how to use Behat to test that your Drupal site is working properly.

The post Testing Your Drupal Site with Behat appeared first on php[architect].

Jun 23 2016
Jun 23

These days, it’s pretty rare that we build websites that aren’t some kind of redesign. Unless it’s a brand new company or project, the client usually has some sort of web presence already, and for one reason or another, they’ve decided to replace it with something shiny and new.

In an ideal world, the existing system has been built in a sensible way, with a sound content strategy and good separation of concerns, so all you need to do is re-skin it. In the Drupal world, this would normally mean a new theme, or if we’re still in our dream Zen Garden scenario, just some new CSS.

However, the reality is usually different. In my experience, redesigns are hardly ever just redesigns. When a business is considering significant changes to the website like some form of re-branding or refresh, it’s also an opportunity to think about changing the content, or the information architecture, or some aspects of the website functionality. After all, if you’re spending time and money changing how your website looks, you might as well try to improve the way it works while you’re at it.

So the chances are that your redesign project will need to change more than just the theme, but if you’re unlucky, someone somewhere further back along the chain has decided that it’s ‘just a re-skinning’, and therefore it should be a trivial job, which shouldn’t take long. In the worst case scenario, someone has given the client the impression that the site just needs a new coat of paint, but you’re actually inheriting some kind of nasty mess with unstable foundations that should really be fixed before you even think about changing how it looks. Incidentally, this is one reason why sales people should always consult with technical people who’ve seen under the bonnet of the system in question before agreeing prices on anything.

Even if the redesign is relatively straightforward from a technical point of view, perhaps it’s part of a wider rebranding, and there are associated campaigns whose dates are already expensively fixed, but thinking about the size of the website redesign project happened too late.

In other words, for whatever reason, it’s not unlikely that redesign projects will find themselves behind schedule, or over budget - what should you do in this situation? The received agile wisdom is that time and resources are fixed, so you need to flex on scope. But what’s the minimum viable product for a redesign? When you’ve got an existing product, how much of it do you need to rework before you put the new design live?

This is a question that I’m currently considering from a couple of angles. In the case of one of my personal projects, I’m upgrading an art gallery listings site from Drupal 6 to Drupal 8. The old site is the first big Drupal site I built, and is looking a little creaky in places. The design isn’t responsive, and the content editing experience leaves something to be desired. However, some of the contributed modules don’t have Drupal 8 versions yet, and I won’t have time to do the work involved to help get those modules ready, on top of the content migration, the new theme, having a full-time job and a family life, and all the rest of it.

In my day job, I’m working with a large multinational client on a set of sites where there’s no Drupal upgrade involved, but the suggested design does include some functional changes, so it isn’t just a re-theming. The difficulty here is that the client wants a broader scope of change than the timescales and budget allow.

When you’re in this situation, what can you do? As usual with interesting questions, the answer is ‘it depends’. Processes like impact mapping can help you to figure out the benefits that you get from your redesign. If you’ve looked at your burndown rates, and know that you’re not going to hit the deadline, what can you drop? Is the value that you gain from your redesign worth ditching any of the features that won’t be ready? To put it another way, how many of your existing features are worth keeping? A redesign can (and should) be an opportunity for a business to look at their content strategy and consider rationalising the site. If you’ve got a section on your site that isn’t adding any value, or isn’t getting any traffic, and the development team will need to spend time making it work in the new design, perhaps that’s a candidate for the chop?

We should also consider the Pareto principle when we’re structuring our development work, and start by working on the things that will get us most of the way there. This fits in with an important point made by scrum, which can sometimes get forgotten about: that each sprint should deliver “a potentially shippable increment”. In this context, I would interpret this to mean that we should make sure that the site as a whole doesn’t look broken, and then we can layer on the fancy bits afterwards, similar to a progressive enhancement approach to dealing with older browsers. If you aren’t sure whether you’ll have time to get everything done, don’t spend an excessive amount of time polishing one section of the site to the detriment of basic layout and styling that will make the whole site look reasonably good.

Starting with a style guide can help give you a solid foundation to build upon, by enabling you to make sure that all the components on the site look presentable. You can then test those components in their real contexts. If you’ve done any kind of content audit (and somebody really should have done), you should have a good idea of the variety of pages you’ve got. At the very least, your CMS should help you to know what types of content you have, so that you can take a sample set of pages of each content type or layout type, and you’ll be able to validate that they look good enough, whatever that means in your context.

There is another option, though. You don’t have to deliver all the change at once. Can you (and should you) do a partial go-live with a redesign? Depending on how radical the redesign is, the attitudes to change and continuous delivery within your organisation and client, and the technology stack involved, it may make sense to deliver changes incrementally. In other words, put the new sections of the site live as they’re ready, and keep serving the old bits from the existing system. There may be brand consistency, user experience, and content management process reasons why you might not want to do this, but it is an option to consider, and it can work.

On one previous project, we were carrying out a simultaneous redesign and Drupal 6 to 7 upgrade, and we were able to split traffic between the old site and the new one. It made things a little bit more complicated in terms of handling user sessions, but it did give the client the freedom to decide when they thought we had enough of the new site for them to put it live. In the end, they decided that the answer was ‘almost all of it’.

So what’s the way forward?

In the case of my art gallery listings site, the redesign itself has a clear value, and with Drupal 6 being unsupported, I need to get the site onto Drupal 8 sooner rather than later. There’s definitely a point that will come fairly soon, even if I don’t get to spend as long as I’d like working on it, where the user experience will be improved by the new site, even though some of the functionality from the old site isn’t there, and isn’t likely to be ready for a while. I’m my own client on that project, so I’m tempted to just put the redesign live anyway.

In the case of my client, there are decisions to be made about which of the new features need to be included in the redesign. De-scoping some of the more complex changes will bring the project back into the realm of being a re-theming, the functional changes can go into subsequent releases, and hopefully we’ll hit the deadline.

A final point that I’d like to make is that we shouldn’t fall into the trap of thinking of redesigns as big-bang events that sit outside the day-to-day running of a site. Similarly, if you’re thinking about painting your house, you should also think about whether you also need to fix the roof, and when you’re going to schedule the cleaning. Once the painting is done, you’ll still be living there, and you’ll have the opportunity to do other jobs if and when you have the time, energy, and money to do so.

Along with software upgrades, redesigns should be considered as part of a business’s long-term strategy, and they should be just one part of a plan to keep making improvements through continuous delivery.

Jun 02 2015
Jun 02

In April 2015, NASA unveiled a brand new look and user experience for NASA.gov. This release revealed a site modernized to 1) work across all devices and screen sizes (responsive web design), 2) eliminate visual clutter, and 3) highlight the continuous flow of news updates, images, and videos.

With its latest site version, NASA—already an established leader in the digital space—has reached even higher heights by being one of the first federal sites to use a “headless” Drupal approach. Though this model was used when the site was initially migrated to Drupal in 2013, this most recent deployment rounded out the endeavor by using the Services module to provide a REST interface, and ember.js for the client-side, front-end framework.

Implementing a “headless” Drupal approach prepares NASA for the future of content management systems (CMS) by:

  1. Leveraging the strength and flexibility of Drupal’s back-end to easily architect content models and ingest content from other sources. As examples:

  • Our team created the concept of an “ubernode”, a content type which homogenizes fields across historically varied content types (e.g., features, images, press releases, etc.). Implementing an “ubernode” enables easy integration of content in web services feeds, allowing developers to seamlessly pull multiple content types into a single, “latest news” feed. This approach also provides a foundation for the agency to truly embrace the “Create Once, Publish Everywhere” philosophy of content development and syndication to multiple channels, including mobile applications, GovDelivery, iTunes, and other third party applications.

  • Additionally, the team harnessed Drupal’s power to integrate with other content stores and applications, successfully ingesting content from blogs.nasa.gov, svs.gsfc.nasa.gov, earthobservatory.nasa.gov, www.spc.noaa.gov, etc., and aggregating the sourced content for publication.

  1. Optimizing the front-end by building with a client-side, front-end framework, as opposed to a theme. For this task, our team chose ember.js, distinguished by both its maturity as a framework and its emphasis of convention over configuration. Ember embraces model-view-controller (MVC), and also excels at performance by batching updates to the document object model (DOM) and bindings.

In another stride toward maximizing “Headless” Drupal’s massive potential, we configured the site so that JSON feed records are published to an Amazon S3 bucket as an origin for a content delivery network (CDN), ultimately allowing for a high-security, high-performance, and highly available site.

Below is an example of how the technology stack which we implemented works:

Using ember.js, the NASA.gov home page requests a list of nodes of the latest content to display. Drupal provides this list as a JSON feed of nodes:

Ember then retrieves specific content for each node. Again, Drupal provides this content as a JSON response stored on Amazon S3:

Finally, Ember distributes these results into the individual items for the home page:

The result? A NASA.gov architected for the future. It is worth noting that upgrading to Drupal 8 can be done without reconfiguring the ember front-end. Further, migrating to another front-end framework (such as Angular or Backbone) does not require modification of the Drupal CMS.

May 14 2015
May 14

As Drupal has evolved, it has become more than just a CMS. It is now a fully fledged Web Development Platform, enabling not just sophisticated content management and digital marketing capabilities but also any number of use cases involving data modelling and integration with an endless variety of applications and services. In fact, if you need to build something which responds to an HTTP request, then you can pretty much find a way to do it in Drupal.

“Just because you can, doesn’t mean you should.”

However, the old adage is true. Just because you can use use a sledgehammer to crack a nut, that doesn’t mean you’re going to get the optimal nut-consumption-experience at the end of it.

Drupal’s flexibility can lead to a number of different integration approaches, all of which will “work”, but some will give better experiences than others.

On the well trodden development path of Drupal 8, giant steps have been taken in making the best of what is outside of the Drupal community and “getting off the island”, and exciting things are happening in making Drupal less of a sledgehammer, and more of a finely tuned nutcracker capable of cracking a variety of different nuts with ease.

In this post, I want to explore ways in which Drupal can create complex systems, and some general patterns for doing so. You’ll see a general progression in line with that of the Drupal community in general. We’ll go from doing everything in Drupal, to making the most of external services. No option is more “right” than others, but considering all the options can help make sure you pick the approach that is right for you and your use case.

Build it in Drupal

One option, and probably the first that occurs to many developers, is to implement business logic, data structures and administration of a new applications or services using Drupal and its APIs. After all, Entity API and the schema system give us the ability to model custom objects and store them in the Drupal database; Views gives us the means to retrieve that data and display it in a myriad of ways. Modules like Rules; Features and CTools provide extensive options for implementing specific business rules to model your domain specific data and application needs.

This is all well and good, and uses the strengths of Drupal core and the wide range of community contributed modules to enable the construction of complex sites with limited amounts of coding required, and little need to look outside Drupal. The downside can come when you need to scale the solution. Depending on how the functionality has been implemented you could run into performance problems caused by large numbers of modules, sub-optimal queries, or simply the amount of traffic heading to your database - which despite caching strategies, tuning and clustering is always likely to end up being the performance bottleneck of your Drupal site.

It also means your implementation is tightly coupled to Drupal - and worse, most probably the specific version of Drupal you’ve implemented. With Drupal 8 imminent this means you’re most likely increasing the amount of re-work required when you come to upgrade or migrate between versions.

It’s all PHP

Drupal sites can benefit hugely from being part of the larger PHP ecosystem. With Drush make, the Libraries API, Composer Manager, and others providing the means of pulling external, non-Drupal PHP libraries into a Drupal site, there are huge opportunities for building complexity in your Drupal solution without tying yourself to specific Drupal versions, or even to Drupal at all. This could become particularly valuable as we enter the transition period between Drupal 7 and 8.

In this scenario, custom business logic can be provided in a framework agnostic PHP library and a Naked Module approach can be used to provide the glue between that library and Drupal - utilising Composer to download and install dependencies.

This approach is becoming more and more widespread in the Drupal community with Commerce Guys (among others) taking a libraries first approach to many components of Commerce 2.x which will have generic application outside of Drupal Commerce.

The major advantage of building framework agnostic libraries is that if you ever come to re-implement something in another framework, or a new version of Drupal, the effort of migrating should be much lower.

Integrate

Building on the previous two patterns, one of Drupal’s great strengths is how easy it is to integrate with other platforms and technologies. This gives us great opportunity to implement functionality in the most appropriate technology and then simply connect to it via web services or other means.

This can be particularly useful when integrating with “internal” services - services that you don’t intend to expose to the general public (but may still be external in the sense of being SaaS platforms or other partners in a multi-supplier ecosystem). It is also a useful way to start using Drupal as a new part of your ecosystem, consuming existing services and presenting them through Drupal to minimise the amount of architectural change taking place at one time.

Building a solution in this componentised and integrated manner gives several advantages:

  • Separation of concerns - the development, deployment and management of the service can be run by a completely separate team working in a different bounded context. It also ensures logic is nicely encapsulated and can be changed without requiring multiple front-end changes.
  • Horizontal scalability - implementing services in alternate technologies lets us pick the most appropriate for scalability and resilience.
  • Reduce complex computation taking place in the web tier and let Drupal focus on delivering top quality web experience to users. For example, rather than having Drupal publish and transform data to an external platform, push the raw data into a queue which can be consumed by “non-Drupal” processes to do the transform and send.
  • Enable re-use of business logic outside of the web tier, on other platforms or with alternative front ends.

Nearly-Headless Drupal

Headless Drupal is a phrase that has gained a lot of momentum in the Drupal community - the basic concept being that Drupal purely responds with RESTful endpoints, and completely independant front-end code using frameworks such as Angular.js is used to render the data and completely separate content from presentation.

Personally, I prefer to think of a “nearly headless” approach - where Drupal is still responsible for the initial instantiation of the page, and a framework like Angular is used to control the dynamic portion of the page. This lets Drupal manage the things it’s good at, like menus, page layout and content management, whilst the “app” part is dropped into the page as another re-usable component and only takes over a part of the page.

For an example use case, you may have business requirements to provide data from a service which is also provided as an API for consumption by external parties or mobile apps. Rather than building this service in Drupal, which while possible may not provide optimal performance and management opportunities, this could be implemented as a standalone service which is called by Drupal as just another consumer of the API.

From an Angular.js (or insert frontend framework of choice) app, you would then talk directly to the API, rendering the responses dynamically on the front end, but still use Drupal to build everything and render the remaining elements of the page.

Summing up

As we’ve seen, Drupal is an incredibly powerful solution, providing the capability for highly-consolidated architectures encapsulated in a single tool, a perfect enabler for projects with low resources and rapid development timescales. It’s also able to take its place as a mature part of an enterprise architecture, with integration capabilities and rich programming APIs able to make it the hub of a Microservices or Service Oriented Architecture.

Each pattern has pros and cons, and what is “right” will vary from project to project. What is certain though, is that Drupal’s true strength is in its ability to play well with others and do so to deliver first class digital experiences.

New features in Drupal 8 will only continue to make this the case, with more tools in core to provide the ability to build rich applications, RESTful APIs for entities out of the box allowing consumption of that data on other platforms (or in a headless front-end), improved HTTP request handling with Guzzle improving options for consuming services outside of Drupal, and much more.

Feb 27 2015
Feb 27

There are thousands of situations in which you do not want to reinvent the wheel. It is a well known principle in Software Engineering, but not always well applied/known into the Drupal world.

Let’s say for example, that you have a url that you want to convert from relative to absolute. It is a typical scenario when you are working with Web (but not just Web) crawlers. Well, you could start building your own library to achieve the functionality you are looking for, packaging all in a Drupal module format. It is an interesting challenge indeed but, unless for training or learning purposes, why wasting your time when someone else has already done it instead of just focussing on the real problem? Especially if your main app purpose is not that secondary problem (the url converter).

What’s more, if you reuse libraries and open source code, you’ll probably find yourself in the situation in which you could need an small improvement in that nice library you are using. Contributing your changes back you are closing the circle of the open source, the reason why the open source is here to stay and conquer the world (diabolical laugh here).

That’s another one of the main reasons why lot’s of projects are moving to the Composer/Symfony binomium, stop working as isolated projects and start working as global projects that can share code and knowledge between many other projects. It’s a pattern followed by Drupal, to name but one, and also by projects like like phpBB, ezPublish, Laravel, Magento,Piwik, …

Composer and friends

Coming back to our crawler and the de-relativizer library that we are going to need, at this point we get to know Composer. Composer is a great tool for using third party libraries and, of course, for contributing back those of your own. In our web crawler example, net_url2 does a the job just beautifully.

Nice, but at this point you must be wondering… What does this have to do with Drupal, if any at all? Well, in fact, as everyone knows, Drupal 8 is being (re)built following this same principle (DRY or don’t repeat yourself) with an strong presence of the great Symfony 2 components in the core. Advantages? Lots of them, as we were pointing out, but that’s the purpose of another discussion

The point here is that you don’t need to wait for Drupal 8, and what’s more, you can start applying some of this principles in your Drupal 7 libraries, making your future transition to Drupal 8 even easier.

Let’s rock and roll

So, using a php library or a Symfony component in Drupal 7 is quite simple. Just:

  1. Install composer manager
  2. Create a composer.json file in your custom module folder
  3. Place the content (which by the way, you’ll find quite familiar if you’ve already worked with Symfony / composer yaml’s):
    "require": {
      "pear/net_url2": "2.0.x-dev"
     }
    
  4. enable the custom module

And that’s it basically. At this point we simply need to tell drupal to generate the main composer.json. That’s basically a composer file generated from the composer.json found in each one of the modules that include a composer themselves.

Lets generate that file:

drush composer-rebuild

At this point we have the main composer file, normally in a vendor folder (if will depend on the composer manager settings).

Now, let’s make some composer magic :

drush composer update

At this point, inside the vendors folder we should now have a classmap, containing amongst others our newly included library.

Hopefully all has gone well, and just like magic, the class net_url2 is there to be used in our modules. Something like :

$base = new Net_URL2($absoluteURL);

Just remember to add the library to your class. Something like:

use Net_URL2;

In the next post we’ll be doing some more exciting stuff. We will create some code that will live in a php library, completely decoupled but at the same time fully integrated with Drupal. All using Composer magic to allow the integration.

Why? Again, many reasons like:

  1. Being ready for Drupal 8 (just lift libraries from D7 or D6 to D8),
  2. Decoupling things so we code things that are ready to use not just in Drupal, and
  3. Opening the door to other worlds to colaborate with our Drupal world, …
  4. Why not use Dependency Injection in Drupal (as it already happens in D8)? What about using the Symfony Service container? Or something more light like Pimple?
  5. Choose between many other reasons…

See you in my next article about Drupal, Composer and friends, on the meantime, be good :-).

Updated: Clarified that we are talking about PHP Libraries and / or Symfony components instead of bundles. Thanks to @drrotmos and @Ross for your comments.

Oct 22 2014
Oct 22

Along with Malcolm and other colleagues from the Capgemini Drupal team, I attended the recent Drupalcon in Amsterdam. And as well as admiring the Dutch attitude to cycling and its integration in the city (btw London, blue paint on the road != a cycle superhighway), we also caught up on the state of Drupal and its future. So here a few reflections from Drupalcon Amsterdam.

Drupal In The Enterprise - A Key Component In The Wider Web

I’ve been to a few Drupalcons now, and compared to previous years, use of Drupal in the enterprise (or more generally at scale) seems much more commonplace. Dries Buytaert’s (Drupal founder) keynotes have made reference to Drupal’s ability to integrate with other systems as a key strength, and in these types of projects, Drupal is not used as the all-in-one solution that maybe was more commonplace a few years ago.

Partly this is also due to the way the web has moved far beyond the idea of ‘a thing you use on your desktop computer’, and Drupal has shown itself to be adaptable to this. For example, the idea of Headless Drupal was a well covered topic this year. Of course, previous ‘cons have had talks on uses of Drupal with other technologies (e.g. node.js talk from London 2011) but whereas it seemed more an interesting edge case then, now there are many successful real-world projects adopting these ideas.

The Sessions

Based on my not-entirely-comprehensive memory of the subset of sessions I attended from past Drupalcons, this year there seemed to be many more talks which could have easily been at a frontend or PHP specific conference. Drupal 8’s use of Symfony 2 components and shift to making use of components Proudly Found Elsewhere is part of this.

A few talks that those of us who attended would recommend (not an exhaustive list). I won’t go into too much detail (that’s all in the slides and the video) but these are worth checking out.

Automated Frontend Testing

The types of frontend testing which can be automated, covering performance (Phantomas), CSS (Wraith) and end-to-end (CasperJS) and integrating this into your build workflow. Slides Video

Models & Service Layers; Hemoglobin & Hobgoblins

I think the PHP track is a welcome addition to Drupalcon. When developing custom functionality on projects here at Capgemini, we often write the business models and logic as separate classes to Drupal which are then ‘glued’ via hooks which implement those classes. That kind of separation has advantages with portability, testability and some amount of simplification in that Drupal isn’t a dependency. Video

Cory Doctorow’s Keynote

Very interesting talk on how open-source is (in some ways) critical to our individual freedom in the modern world. In an age where “a modern house is a computer that you co-inhabit”, if a system went down - or arguably worse, were controlled by overzealous authorities - it can become uninhabitable. What do we do in this case? Is the Apple iTunes/U2 debacle merely the thin end of the wedge? Interesting viewing for anyone who contributes or uses open source. Video

Drupal 8 And The Future

As Drupal 8 entered beta during the conference, it was an opportunity to check out the changes. The plugin system for extending functionality looks interesting. In Drupal projects at Capgemini we have adopted approaches such as abstracting business logic and objects into standalone libraries and classes, called from hooks and callbacks where we need integration with Drupal. This approach allows us easier unit-testing and portability of classes. D8’s plugin system looks like a good way of achieving those advantages while implementing a Drupal API.

Having spent a lot of time on projects wrestling with the various methods of deploying and updating configuration, the CMI (Configuration Management Initiative), which imports and exports YAML files to update and dump site configuration is a very welcome addition.

In the frontend, I’m looking forward to using the Twig templating. The idea of having cleaner PHP-free templates yet still with the flexibility to have filters and basic logic is going to help improve separation between the theme and module layer. It’ll be new to me (as will other things) but as with other components, they have been successfully used in other PHP projects so there is documentation and examples already out there. There are some smaller changes too - removing drupal.js’s dependency on jQuery (thereby gently encouraging use of native JS), updating the versions of included libraries (and committing to keeping them up-to-date during D8’s lifetime) and including no JavaScript by default are good steps to optimising the frontend.

Where things may be more challenging is the APIs which have both new object-oriented components and retain the hook and callback system in some combination (for example, declaring widgets via hook_element_info). To take an example from a core module, the file module’s managed_file widget functionality is spread across a number of callbacks as well as its own FileWidget class. It’s not the most straightforward development flow to follow. Where this has some advantages is that existing modules will not need a complete OO rewrite just to be compatible with D8 - a module author could do a simple port at first before rewriting to take advantage of the new APIs. But some care is need to ensure that the advantages of encapsulation, increased unit-testability and extendability that the OO patterns introduce are not compromised by dependencies on a particular hook or callback.

Taking The Leap

Finally, as Drupal 8 progressed from alpha to beta during Amsterdam Drupalcon, it does seem now that it can be realistically considered for projects coming up on the horizon. Obviously there will a lot more work going into the project to fix bugs and improve performance and so forth. But now the major API decisions and changes have been made. But with this iteration of Drupal incorporating many more features from the contrib world (Views, WYSIWYG, etc) and PHP (Symfony2 components), it looks to be a healthy position for use when that 8.0.0 finally lands.

Jan 31 2012
Jan 31

“Why is your window transparent?” a coworker asked me when she noticed my screen. I told her about how I do my CSS theming, and she pulled another coworker over and made me repeat the explanation. Since that seems like something other people might find handy, here it is.

Sass: Syntactically Awesome Sytlesheets

I rarely do CSS/front-end theming work, but when I do, I try to make it as fun and easy as back-end development. I use Sass (Syntactically Awesome Stylesheets) so that I can use nested selectors, variables, and mixins. This makes my code cleaner and easier to write. You’ll need Ruby in order to install Sass, but the tool will give you CSS that you can use on any web platform.

Browser-based tools

I prefer doing the initial tweaking in Google Chrome, because I like the way that the developer tools make it easy to modify the stylesheet. The Chrome CSS Reloader extension is handy, too. Most of the time, I make my CSS changes in the text editor, then use the CSS Reloader to reload the stylesheet without refreshing the page. This makes it easy to manually toggle the display of some elements while allowing me to refresh style rules. If I want to figure out the values for a few simple changes, I’ll sometimes make the changes directly in Chrome (you can use arrow keys to adjust values), then copy the values to my Sass source file.

Colors, sizes, and spaces

A second monitor is totally awesome and well worth it.

Designs rarely specify all the colours, sizes, and spacing needed. To quickly get the color of a pixel, I use WhatColor. This shows the hex code for colors, and allows me to quickly copy the code with the F12 shortcut key. If you want to change the shortcut key, the source is available as an AutoHotkey script.

To make it easier to match sizes and spaces, I use WinWarden to make my browser window 20% translucent. Then I carefully position it over my design reference until the important features match. Magnifixer makes it easier to line things up because it can magnify a fixed portion of the screen. By focusing Magnifixer on the part I’m working on, I can tweak CSS without straining my eyes.

When I know I’m going to be making a lot of changes, I use AutoHotkey to map a shortcut so that I can refresh the CSS with one keystroke instead of several. When I happen to have my USB foot pedal handy, I rig it up to refresh my stylesheet.

Regression testing

Sometimes my CSS changes modify other rules. Instead of laboriously checking each page after changes, I’ve figured out how to use Selenium WebDriver to write a Java program that loads the pages in Mozilla Firefox and Internet Explorer, capturing screenshots and numbering them according to the pages in my design reference. This means that I can run the program in the background or start it before taking a break, and then flip through all the screenshots when I get back.

Cross-browser testing

What’s CSS theming without the requirement of browser compatibility? Someday, when I need to deal with more browsers, I might look into Selenium RC. In the meantime, I develop in Chrome, my Selenium-based program makes it easier to test in Firefox and IE, and it’s easy enough to try the URLs in Safari as well. Virtual machines handle the rest of the requirements. 

So that’s how I’ve been doing CSS theming on this project. What are your favourite tips?

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