Upgrade Your Drupal Skills

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

See Advanced Courses NAH, I know Enough
Jun 15 2017
Jun 15

Tom Friedhof: There’s a lot of hype around integrating Pattern Lab with your Drupal theme these days. Particularly because Drupal’s template engine is now using twig, which is one of the template engines Pattern Lab uses.  The holy grail of having a living style guide and component library is now a lot more feasible! But what about Drupal 7 sites? Twig doesn't exist in Drupal 7.  Today I’m going to show you something we’re working on at active lamp to implement Pattern Lab templates in Drupal 7.

Hey guys, I’m Tom Friedhof, a solutions architect here at ActiveLAMP.  Let me first start off by defining what I mean when I a say living style and component library.  This idea can mean different things to different people. A living style guide and component library is the HTML, CSS, and Javascript that document the design of a user interface. The “living” part of that means that the style guide should be constantly in sync with the actual app that implements the interface as the design improves or changes.

How do you easily keep the real app and the style guide in constant sync?  That could be a lot of work, given that once the initial designs are done, the design iterations are typically done directly in the app being built, making the style guide obsolete and outdated.

That’s where the promise of Pattern Lab integration with Drupal comes in.  You can easily keep the style guide in sync, if your app depends on the style guide for all of it’s HTML, CSS, and Javascript. That’s why there is so much hype around building “Pattern Lab” themes in Drupal 8 right now. Drupal 8’s theme engine is a theme engine that Pattern Lab uses, and reusing the same twig templates that your UX Designer created in Pattern Lab within Drupal, is now an option.

Well, we’re still working on Drupal 7 sites, so how do we benefit from this approach in Drupal 7? To be honest, we’re still hashing out our approach to do this in Drupal 7.  We have the process built out enough, and we're using it on a new theme we developing for a client, but we’re still constantly iterating on the process, and improving it as we run into things.

What I want to show you guys today is the direction that we’re going, and I’m hoping to get your feedback in the comments so that we can continually improve and iterate on this system. First off, we decided not to use the twig version of Pattern Lab.  We spent half a day trying to get twig working in Drupal 7 with the twig for drupal 7 module, and realized we’d be going down a pretty deep rabbit hole just to make twig work in D7.

Rather than fight Drupal 7 and twig, we decided to use a much simpler template engine called Mustache.  Mustache is a language agnostic template engine, and there is a really nice PHP implementation of it. With that said, we installed the gulp version of Pattern Lab, which uses Mustache templates in JavaScript.  We now have the ability to share templates.

I’m going to jump into a demo here in a second. However, I’m not going to do a deep dive of how Pattern Lab works or how Drupal and Panels work.  I’ll dive deeper in future videos with those details if you’re interested.  Leave a comment if you want to see that stuff and we’ll put it on our list of content to share. I’m going to give you guys a 10,000 foot view of how things are shaping up with our Drupal 7 integration to Pattern Lab process.

All right, so here we are in our Drupal seven install. This is pretty much a vanilla Drupal installation. If I jump over to the Drupal directory, you can see here within my sites all modules file or directory, here are all the modules that I need for this actual demo that I'm gonna use for today. We like to use panels and panels everywhere, so what I'm going be demoing today is with panels and panels everywhere, but the stuff that I'm gonna show does apply to just regular template files if you don't want to use panels and just want to stick with the core TPL system within Drupal. One of the the other things that we have in here is a theme called Hills, this is where all the magic actually happens. One thing that you'll notice in this Hills theme is we have two directories called node modules and vendor. We're actually pulling in dependencies from NPM and from Composer or from Packagist into this theme. If we open up our package.jason, which actually defines the NPM dependencies, you can see that we're defining a dependency called hills-patternlab. This is basically the repo that holds our Pattern Lab instants, it's the living style guide that the UX designer uses to actually update the patterns, update CSS and make any changes that need to be changed in the UI.

The composer.json file is requiring the Mustache PHP implementation. We're using this library for obvious reasons to render the Mustache templates that we're pulling in from Pattern Lab. This theme needs to be instantiated with an NPM install and a composer install to get these dependencies and once you've done that, then you're ready to start working on the theme.

One other thing I want to do before I actually start building this our in Drupal is I want to show you the Pattern Lab instants. I am in our Hills directory, I can run NPM start and this should pull up our Pattern Lab instants. Here is our Pattern Lab instants, not going to go into the details of what Pattern Lab is, but essentially it's all the components that make up a website. For example, you can see a page header looks like that, if we wanted to see what the header looks like, it looks like this and all of these templates are basically Mustache templates within our Patterns Lab. Let me open up node modules so you can actually see these templates real quick. The Pattern Lab directory structure looks like this, within the source directory inside of Patterns we can go into organisms and actually look at what a header looks like within Pattern Lab. This is including a couple other patterns from within Pattern Lab so let's see what the navigation actually looks like by going in here. This is the HTML that make up a navigation.

This template includes other patterns within Pattern Lab, let me drill down to the primary links pattern. Here's what our primary links look like, you can see that this is outputting variables, for example, href and name here and then it's including yet another pattern within Pattern Lab, let me open that one as well. Here you can see that it's outputting more variables, classes and name. These variables are actually defined within Pattern Lab's data directory. I'm not going go into detail how that works, but let me just show you what that ends up rendering. You can see here's our organism header, that primary links pattern is this here. This is basically rendering data from Pattern Lab's data directory. If I go into the data directory just real quick, within the primary-links.json file you can see this is the actual data that it's pulling in. If we wanted to say staff services, this is going to rebuild and we see staff services here. That's essentially how Pattern Lab works with data in a nutshell. What I'm gonna show you guys is how we actually integrate this with Drupal. Eventually what's going to happen is these Mustache templates are going to render variables from Drupal and not the data specified in this Pattern Lab data directory.

Let's jump over to Drupal. Here's our Drupal installation. First thing that I'm going do is I'm going to switch the theme to our Hills theme, our Hail to the Hills theme, so I'm gonna enable this and set this as the default. Now I'm gonna open up the homepage in a new tab and drag that over here. So now we can see here's what we get out of the box with this Hail to the Hills theme, there's really nothing in this theme yet. There is stuff in the theme, but I'll get to that in a second, but this is what you'll get once you enable it initially. We're using Panels Everywhere with this theme so what I'm going to do is I'm going to go configure Panels Everywhere. Panels Everywhere gives you a site template by default, so I'm gonna come over here and edit it and I'm gonna add a new variant. We'll just call this default and I'm going come over here and choose a layout within the PL Templates layout category and I'm going to hit full width one column, continue and then we'll just work through this UI. Then I'm going to give it basically the basic content that we need to render so that you can actually see something on the page when you visit a page within the site. We'll create the variant here, we'll update and save that so now let's look to see what our homepage looks like.

Our homepage is starting to look a little bit better, we're basically hitting the default homepage for Drupal, which just shows the title and then a no front page content has been created yet. You noticed here in this layout tab, we had this category called PL Templates and it's pulling in full width and main content. Let me show you where these are defined, if I jump back into our theme, within our theme info hook or info file, panels allows you to specify a directory where you're going to define your layout plugins. The way you specify that is by using the string plugins panel layouts and then you just give it a path to your directory. Let me close node modules so this is a little bit easier to see. If I come into this layouts directory, you can see that I have two layouts specified here, we used the full width layout so I'm gonna jump into that first.

This isn't a tutorial on how to create plugins, but essentially what we're doing is we're just creating a ctools layout plugin. We've called this the full width one column, we've said the theme function or implementation for this is panels full width and you can see that we have a panels full width template here. So when this layout is used, it's going to actually use this template. If we just into that, all this template is doing is it's printing out whatever is in the content area. This has nothing to do with Patten Lab yet, but this is how you essentially setup a default template with regions within panels everywhere. Let's jump back to Drupal and go into our content area. You remember we have the default template set up now, but now let's start to pull in some of the patterns from Pattern Lab. If I come over here, this pattern here called organisms header, let's pull that into Drupal first. I'm gonna come in here and add content, I have this PL components over here and we have a pattern called header. I'm gonna click on that and this header is asking for four pieces of data, so I'm gonna give it the data that it needs. I'm gonna browse for a file, let's look at that, that looks good, we'll upload this, go to next, we'll say logo, logo. Then we'll give it a path and we'll tell it what main menu to use, we'll just say use this as the main menu and with help menu we'll just tell it to use the user menu for now, and then finish. Let's drag this up to the top, hit update and save and let's go see what happened. Let's go back to our homepage and voila, we've got a header pulled from Pattern Lab in here. You'll notice that the menu is not the same menu that's coming from Pattern Lab and why is that? It's because it's pulling the actual primary links from Drupal.

If we go into the menu system here, we chose the main menu to use, the main menu here and if we create another link here we can say another link, have this go to front. Then we come back to our homepage, you can see that this is actually pulling from Drupal. We have no sub-menus underneath that and that's why it's not showing anything underneath it. But you can see that we're actually using our own data from within Drupal.

How did we actually pull in this whole header section from Pattern Lab? Let's go back to where we actually pulled that in. I'm gonna go to structure, pages, back into our site template. We had this content type that we pulled in, this PL header content type. This is a ctools content type and you can define those with a content type plugin. Because this plugin only exists within this theme, we defined the ctools content type within this theme. The way we did that is within our info file, we're specifying where content types for ctools should live and we're saying those content types should live in the Pattern Lab directory, which is right here. This behavior isn't default behavior in ctools, so we did have to patch the ctools modules so that we could do this. You can check out that patch here and leave any comments if you have any comments or suggestions regarding that patch. It's a very small patch, but it basically allows us to define content types, ctools content types, within our theme and not have to define a module just for these content types.

Let's look inside of this Pattern Lab directory and see what we have. The way ctools plugins work is it'll traverse the directory that you've defined and look for any .inc files and read those in while it's processing plugins. Within the organisms header directory, I have a file called organisms_header_inc. The content type system within ctools will pick up this file and it'll read this variable that defines the actual plug in. You can specify other functions to be able to expose, for example, an edit form. Here you see we have a submit handler for that edit form. But here's where all the magic happens, here's a function that we've defined called preprocess. This is where we actually map the Drupal data into data that Pattern Lab understands and we pass this data to Mustache to actually render the pattern. Let me back up and show you what Pattern Lab is expecting to see within this content type. I'm going to open up a new PHP storm directory so that I don't have to continue to scroll up. Go into sites, all, themes, hills, node_modules, hills-patternlab, open a new window, yes. Here is the Hills Pattern Lab directory within that theme, that Hills theme. What I'm going to do is go into the pattern that we're actually pulling in and so it is here. This pattern is pulling in data from this data file and the hints that you can get from this data file is basically looking at what these patterns rely on. We're not producing or we're not outputting any data here, so what we need to do is we need to drill down to see where data actually is being output. If we go into navigation, we can see navigation still isn't outputting any data, it's still just including other atoms and molecules.

So let's jump into the primary links. Now primary links is starting to actually output data. We have that href file there or href variable, we have a name variable there. But then you can also see that it's pulling in yet another include. But this is where we want to start. We're using data here in this primary links component, within Pattern Lab you can specify data in this data directory. We have this primary links Jason file and we basically specified an object with a primary links key. Now Pattern Lab's going read into all these data files and essentially merge the objects so that you can reference them by whatever key is at the root of that object, they all get merged into the data json file. If we look here, primary links is being looped through and then the href and the name is being rendered out. If we look at this, primary links is an array with name and href. If we collapse these guys, you can see we have name, we have several links here. Staff services, work tools, news, administrative units, contact us, that all coincides with our pattern over here.

Within that pattern, coming back over here to primary links, you can see that it's including molecules drop down and that is here. That's also rendering or looping through the links and using the classes variable and the name variables. So if I come back into that data file and open one of these guys up, you can see here's the links array and there's the name and href that is being used. It looks like we're only specifying classes on this very last button here. If we come back here, you'll see that that class is actually specified there and that's what makes that look a little bit different.

Essentially what we're doing in Drupal is we're just mapping data to the data that Pattern Lab expects. Let's jump back over to Drupal and so now here's our Drupal content type. You can see here, essentially we're returning an array, nav bar brand. Here's our primary links, so that's what we just looked at, the primary links is essentially creating an array that looks like this, but in Drupal. You can see here, hills_menu_tree, this is essentially creating that array that Pattern Lab is expecting.

I'll show you an easier example of what that looks like as we continue to build out this page. Let's add another pattern to this site layout. If we come into the default template and we add content, go to Pattern Lab components, I'm going to add in a footer calling card. So that footer calling card, if we come over here into molecules, then footer, we can see the footer calling card looks like this. If we come into the template for that, that's a molecule under footer, the calling card looks like this. This takes several variables, it takes a title, phone, email and then it loops through a social array and outputs the href and the network we defaulted in Pattern Lab. If we look at the data that we defaulted in Pattern Lab, we can come over here to footer calling card and you can see that we've got a calling card key and then we've just specified the data down there.

We're gonna render this in Drupal so we created a content type that essentially has an edit form for all of this information. Let's just fill this out, information technology and let's just go sure and yes. Let's keep that there, update and save. Now there's our footer calling card. All right, you guys get the idea there, we're able to create content types, we're able to create an edit field that passes in data or we're collecting data and then we pass that data into Mustache and render the Pattern Lab template with the data that we are pre-processing.

What is you're working with content that isn't going to be a ctools content type, for example nodes? Let's create some nodes and see what that actually looks like. I'm going to come in here into configuration and we're going to devel generate a few nodes. I can come down here, hit generate content and let's just create 10 basic pages, we'll generate that. Now let's go back to our homepage here, so there we have five nodes listed on the homepage now. How do we actually style this so this looks like something? What I'm going to show is first thing I'm gonna do is I'm going to put this into a content container. Let me go over to our Pattern Lab, I'm gonna go to layouts and look at our main content. Our main content goes into a container that looks like this and the content is output inside of that container. What I'm going to do is I'm going to actually create this homepage as a view so we can actually control the template that's being output here. I'm gonna come over here to structure, go down to views and let's add a new view, let's call this homepage list, we'll continue and edit that.

We're gonna make this a content pane, I'm actually going to get rid of this page here, we didn't need that I should've unchecked it. Within that content pane, we're going to render fields and we're not really gonna be using the views output so uncheck that and then we'll also throw in the body here and we're going to limit that to 600 characters, so that's what our view is going to look like that we're going to use on the homepage. Let's go ahead and save that. What I'm gonna do is I'm gonna create a new front page over in page manager. Within page manager, I'm gonna add a custom page, we'll call this front page and then we'll give this the path of front and we're gonna check this box that says make this your site homepage, we'll continue. Then I'm going to choose the layout called main content and what that's going to do is that's going to use the layout from Pattern Lab that uses main content and I'll show you that here in a second.

I'll hit continue, continue and then inside of here, we're going to output the view that we just created. So here's that view there, so we'll save that and we'll hit finish there. Update and save so now we have a front page that's going to render a view called homepage list using the layout main content. So let's take a look to see what happened here, let's go back to the homepage and there you go, you can see that we're now outputting that actual view within the page content. This home site install shouldn't output here and this is actually being output by panels, so what we're gonna do is we're gonna disable that title there. If we come back here into content and then ... Actually this is going to be in the site template. We'll edit that, go into content and within the page content section, we're going to override the title and make it nothing, update and save that. Now we're getting a lot closer to what our styles look like in Pattern Lab.

Now the next step that we want to do is actually make this view look like something in Pattern Lab. What we're going to do is we're going to make that look like a two column stack view. We have this data here that's set up in a two column stack, we're gonna make the data from views output this template when it renders. Let's jump back into views, so let's go into the front page that we just created and go into the content and so here's that view. I'm going to open this cog here and edit this view and a new tab, so views gives you the ability to specify a theme file. So what we're gonna do is we're actually going to specify this theme file in our theme. I'm gonna copy that and then jump into our theme over here. So here's our Drupal theme, going to my templated directory let's create a views directory so that all our views live in the same directory within our templates directory. Let's create a file called views unformatted home page list.

Now, let's just put in hello world so that you can see that this is actually working. When we re scan the templates, views is going to pick up that template file as you can see now that it's bolded. We'll save this and refresh the homepage and you can see now it is outputting hello world, which is in our template file. How do we actually use the template that is in Pattern Lab? Let's go back into views, so this is where the magic happens in this theme. We have a variable expose called ‘m’, which is basically the Mustache connector to Pattern Lab. On that connector, we have a method called render, so this is where we're going to specify the actual template that we want to use within Mustache. There is a naming convention to this and we'll document what that naming convention is, but essentially what you need to do is specify what type of pattern it is, this is an organism so it's in organisms and then what the name of the template it, this is a two column stack. That's really it, that's all you have to do to render this template, so let's go ahead and save this and then look at our view here.

That didn't render anything, let's go back to our template and you can see that we're actually not printing anything out, so let's actually print out the results of that call and then let's see what happens. There you go, now we're actually printing out the template from Pattern Lab, but you can see that this is actually pulling the data from Pattern Lab, it's pulling out its default data from Pattern Lab. How do we actually make it put our own data? Just like the content types that I was showing you, we can send it a map of how our data should look. There's two ways we can do this, this method here, render, actually takes two arguments. One of them is an array and I'm gonna show you that first and this array is the actual map that the component is expecting. If we look to see what the component is expecting, let me jump back over to our Pattern Lab and then go into the data file that the two column stack is expecting, we can see that it's expecting an array with a two column stack as a key and then that as an array of objects with card as the key and then title and nutgraf.

What I'm going to do is I'm actually gonna just pull some of that data out of there. Let's go back to our Drupal theme and paste that in here. Obviously json syntax doesn't work in PHP, so we need to convert some of this, so I'm gonna make that an array so that looks more like what PHP can understand. Now what I'm going to do is copy this array, but we also need a key of what it's expecting. What it's expecting as the key is primary links, sorry we're looking at the two column stack, what is that expecting, two column stack is what that's expecting. Let's grab that, so now this should do it, probably because that ends the map there. Now we have this two column stack, we're actually passing it data so you can pass it whatever data you want, but essentially this is what Drupal is looking for, so if you have your data then just go ahead and do it right here. Let's see what this actually looks like when we save that and then come back over to Drupal and then hit refresh. You can see how it's printing out five cards with the same data in there.

We have another way of actually mapping this data and this is through a pre-process callback. The way that works is there's a third parameter that you can pass to this render function. Let me delete that array that we just defined and what we're gonna do for the second parameter is we're just going to actually pass it the variables that Drupal knows about. Inside of a Drupal theme, when you're working with your template, there's a variable exposed called variables that you can use and then you can output whatever variables you want. What we're going to do is we're gonna actually pass that to a callback that we define here and we'll pass that in as ‘v’ just so that we don't confuse it with variables here. What's happening behind the scenes is this variables is being passed into this callback and now you can run PHP logic to actually pre-process your variables. Just to show you what variables looks like, let's demo that so you can see what's actually being passed into this callback. If we hit save there, refresh this, you can see here is what the view is actually outputting and what we really want within this data is the results that the view is outputting. Here's all the data that the view is outputting, so this is what we want to actually map to what Drupal is expecting.

If we come back into here, what we'll do is we'll return an array that Pattern Lab is expecting, that array expects to have this key so we'll copy that and then that key has a bunch of cards that are associated with it. What we're gonna do is we're actually gonna do the pre-process just to keep this clean in a separate function, so I'll just define this as process card data. In this function that we're going to define now, we'll just copy this function guy here. This function's going to need to take the data that we're passing it, so pass in ‘v’ here and we'll pass in ‘v’ here, but really what we really need from ‘v’ is just the results from the view, so maybe we just pass in ‘v’ view results. Then down here we can just say that this is going to be called the results, since it's an array of results.

Now, essentially what we need to do is we need to create this data format again with this function that we're using inside of Drupal. What we'll do is we're just going to loop through the results as result and we're going to create what we need. Actually we need to specify that data array up here and then let's return the data array down here. What we need to do is specify each element of the data array. That's going to be equal to another array and in that array... Let's see what that needs to look like, that needs to have a card key with another array with title, nutgraf and href. We're just gonna leave href off, since we don't have the links yet. Title, nutgraf and href. So let's go back here and let's start to set up what this looks like. It needs title, it's gonna be something, nutgraf and href. We also need this to be in an array with cards, so let's actually create the card here and pull this inside of the card. Now this is starting to look a lot like the data that Pattern Lab is expecting.

Now let's actually map the data from views. If we come back over here and we look at what we have, we have each one of these objects, we have the note title and we have the field body. Essentially we just need to write that into the template, no title and then for the body we have field body zero rendered markup. For the href, we do have the NID so I guess we can pass that here. All right and that should be all that we need, so if we save this and then go back and refresh this, that didn't work. Let's take a look to see what we did wrong here. I'm going to output our variables again and just make sure that we map this properly. View, result ... So we got view, ‘v’, result. View is an array, it's not an object, this will probably fix it. So we have ‘v’, view, result, view is an object, result is an array object. We're looping through the array and then an object. Let's save this and see if that actually works and get rid of this criminal.

There we go, there is our views data within our template from Pattern Lab. The idea is that the Drupal theme developer just needs to specify one file that renders the template from Pattern Lab while passing it the variables that Pattern Lab is expecting or passing a callback function that our Mustache connector can then call and map out the variables that Pattern Lab is expecting.

So that’s the direction we’re going.  Hopefully that gives you the idea of what we’re trying to do. We don’t have any HTML, CSS, or JavaScript in our theme.  Any changes needed in those files get pushed upstream into the living style guide, and we pull the changes back down into Drupal.

There’s a lot going on under the hood in this theme to make all of this work. We’re thinking that this theme will end up as a base theme that you can extend, to take advantage of all this functionality.  However, that is still yet to be determined and we may change our minds on that approach.  If you have an opinion on that, please let us know in the comments.

There are definitely some trade offs to using this living style guide approach, and those trade offs exist regardless of the Drupal version you use.  I plan to release a future video to talk about the benefits and disadvantages of the living style guide approach with Drupal.  Taking this approach definitely does not fit every Drupal theme.  More about that later.

Also, we’re going to be releasing more videos as we iterate on this theme, so if you’re interested in following along with us, make sure you subscribe to our channel. Thanks for watching!

May 18 2017
May 18

Imagine you have a view that lists upcoming events on your Drupal 8 site. There’s a date filter that filters out any event who’s start date is less than the current date. This works great until you realize that the output of the view will be cached in one or many places (dynamic page cache, internal page cache, varnish, etc). Once it’s cached, views doesn’t execute the query and can’t compare the date to the current time, so you may get older events sticking around.

One way of fixing this is to assign a custom cache tag to your view, and then run a cron task that purges that cache tag at least once a day, like so:

/**
 * Implements hook_cron().
 */
function YOUR_MODULE_cron() {
  // Invalidate the events view cache tag if we haven't done so today.
  // This is done so that the events list always shows the proper "start"
  // date of today when it's rendered. If we didn't do this, then it's possible
  // that events from previous days could be shown.
  // This relies on us setting a custom cache tag "public_events_block" on the
  // view that lists the events via the views_custom_cache_tag module.
  $state_key = 'events_view_last_cleared';
  $last_cleared = \Drupal::state()->get($state_key);
  $today = date('Y-m-d');
  if ($last_cleared != $today) {
    \Drupal::state()->set($state_key, $today);
    \Drupal::service('cache_tags.invalidator')->invalidateTags(['public_events_block']);
  }
}

Assuming you have cron running just after midnight, this will refresh the cache of the view’s block and the page at an appropriate time so that events from the previous day are not shown.

May 11 2017
May 11

Step 6: Configure Your Entity Browsers

Just like the "Media" View displays we discussed in Step 3, each media bundle needs its own Entity browser (plus one for WYSIWYG embedding). Each browser will be set up almost exactly the same with a few small but key differences (admin/config/content/entity_browser).

Settings – Using a modal display for field-based browsers helps to keep the node edit form clean and having no selection plugin streamlines the editor experience. When using a modal view, using tabs as the widget selector is a handy way to partition the browser functionality. If creating an embeddable browser you must use the iframe display plugin to prevent AJAX errors.

On the display screen you can choose to set a height and width for your modal and the link text that will be shown at the bottom to allow editors to use their selected image. Leave auto open entity browser unchecked for non-embeddable browser. The Inline Entity form module will control how we open field-based browsers. For embeddable media you will want to auto open since entity embed automatically uses a modal to house the browser iframe.

The widget selector screen will always show a no configuration message unless you are using a custom selection plugin and unless you are using the multi-step option for your selection plugin, there will also be nothing to configure on the selection display page.

Widget plugins control the functionality of the entity browser. Each plugin defines a piece of the media browser. The first plugin I use is the browser view that displays the media library. Since I also want editors to be able to upload media right in the modal if they can’t find something they like, I also add an Entity Form widget that uses the form display of the media bundle. This ensures that my custom fields will be available to editors when uploading media. The embeddable entity browser will need to have an entity form plugin for each type of media.

Pro tip:

When using the Entity Form widget, set the entity type to media—not media bundle. This is misleading, but if you use the media bundle option you will get the global media bundle form (for adding new bundles) instead of the form for a specific bundle when adding new media.

May 08 2017
May 08

H5PH5P is an open source platform-independent authoring and display system for interactive content. Presentations, quizzes, and other interactive content can be created and displayed using building blocks known as H5P content types (different from Drupal content types). Once a piece of content is created it's easily exported to another H5P system. The development environment is open and well documented, allowing the creation of custom H5P content types.

H5P attributes include:

  • Available in Drupal 7, WordPress, and Moodle
  • Open Source
  • Content is exportable to any other H5P system
  • Uses JavaScript and HTML 5
  • Results tracking for content types such as quizzes
  • xAPI (Tin Can) integration
  • Drupal 7 hook system integration
  • Drupal development environment

Unfortunately there is no Drupal 8 version yet.

There are a variety of H5P content types, including containers such as accordions and sliders which can nest other content types. Some examples are:

  • Arithmetic Quiz
  • Course Presentation
  • Dialog Cards
  • Drag the Words
  • Fill in the Blanks
  • Timeline
  • Interactive Video

The complete list is at https://h5p.org/content-types-and-applications

H5P defines a file packaging format named the ".h5p specification", or simply, H5P file. An H5P file is a zip archive bundling HTML, JSON, JavaScript, and media files. It can contain one or more of a content type, content export, API implementation, application, or JavaScript library.

Drupal Integration

H5P is installed in Drupal in two steps.

  1. Drupal H5P module
    The H5P module is installed using the standard module installation process. It handles the Drupal integration.
  2. H5P Content Types and support files
    H5P content types and the files to support them are installed into a H5P Library manager provided by the H5P module. An H5P archive file of the content types and other support libraries is downloaded from the H5P site and uploaded into the Drupal H5P library.

H5P Content Library

Screenshot of H5P Content Library in Drupal

Content Creation

The Drupal integration contains a H5P node type named, “Interactive content”. When a H5P node is created there is a selector for the H5P content type. For example, quiz, presentation, or dialog card. When a H5P content type is selected the editor for the content type is loaded interactively. The author then creates the desired content.

H5P Content Selector

Screenshot of H5P content type selector

H5P Flashcards content editor

Screenshot of editor for H5P Flashcards content type

Once saved the content is presented when the node is viewed.

H5P Development

The H5P project provides a Drupal development environment (including a developer mode), online documentation, and a forum.

The various specifications and basics for getting started are well documented, and include a “hello world” example. H5P at its heart is JavaScript with a PHP wrapper for integrating with a website. Someone's ability to learn the framework will depend on their comfort with JavaScript.

Coding the editor component that creates and edits the content type typically requires as much work as coding the display for the content type. Custom editor widgets can be written. Existing H5P editor widgets can also be used though they are not documented.

The H5P Drupal hooks provide a clean method of adding CSS stylesheets and modifying H5P behaviour without modifying the base H5P code. Some tasks are complicated by the asynchronous nature of JavaScript loading and the use of iFrames.

Pros and Cons

H5P is continuously changing and improving. These pros and cons are a snapshot of my experience as of May 2017.

Pros:

  • Plug and play interactive content
  • Easy to share content
  • Option for turning off content sharing feature
  • Large variety of content types
  • Open source
  • The H5P team is approachable
  • There is a good content development environment for Drupal
  • The content creators I worked with were able to quickly and easily generate content using H5P
  • Drupal hooks available

Cons:

  • Documentation on some content types is lacking
  • Trial and error is often required to figure out options for some of the sophisticated content types
  • Though some of the content type editors are excellent, some are obtuse or confusing
  • There is no Drupal 8 version
  • Content creators are endlessly creative, you will have to deal with content types being “close but not exactly what I want”
  • There isn't a lot of good guidance on developer workflow if you want to contribute back to the project
  • Staff focused on content creation will probably have favoured tools -- for example, Articulate Storyline -- and push back on an unknown tool such as H5P

Further Reading

May 02 2017
May 02

No more performance anxiety encore!

At our April 2017 meeting Renée Stephen gave the Vancouver Drupal User Group (VanDUG) an encore of her Pacific Northwest Drupal Summit (PNWDS) presentation: No more performance anxiety! The presentation walked us through the formal process of server load testing.

Renée's current gig as Technical Consultant at Acquia gives has given her lots of experience on the subject and she knows how to present. It's always a pleasure when someone deeply steeped in domain knowledge gives a great presentation.

I can't begin to summarize the entire presentation. Renée's slide-deck is available for download at the presentation description on the PNWDS website: No more performance anxiety: get your Drupal site tuned and ready to take the stage! Direct PDF link: PNWDS 2017 - No more performance anxiety.pdf

Here are the take-aways that surprised me:

  • The standard definition of load testing is backend server oriented and does not include front-end performance issues. For example, large hero images or JavaScript widget rendering. While these are important they are not part of this discipline and usually require different tool sets.
  • You'll want at least 2 days, possibly more, to familiarize yourself with jMeter.

I was also reminded of how much server and tool knowledge is required if you're the one doing the remediation. No single detail is exceedingly complicated but each technology in the stack has its particulars, tools, and metics.

Here are the tools Renée mentioned in her presentation:

Profiling Toolkit

  • Blazemeter Recorder
  • Postman
  • HAR
  • jMeter

Dynamic & Static Analysis

  • Blazemeter / jMeter
  • Apachebench (ab)
  • New Relic / TraceView / XHProf
  • WebPage Test
  • Chrome Inspector
  • Server logs and stats
  • varnishstat / varnishlog
  • Redis monitor / memcached-tool
  • Drupal Devel module WebProfiler

She also made a repo of her jMeter example files available at https://github.com/reinette/loadtest

A big thank you to Renée for presenting. I missed the presentation at PNWDS and was happy for the second change to see it.

Apr 11 2017
Apr 11

As a Swiss-based Drupal Agency, we have to create a lot of multilingual sites. Since Switzerland has three official languages (German, French, Italian) and even one more national language (Rumantsch), we are used to this requirement and we found our way with Drupal to make this an easy task (usually). We mainly used node translations in Drupal 7 for maximum flexibility. We used to separate languages from each other using the various i18n modules, language specific menus, blocks, URL-patterns, terms and so on.

With Drupal 8, things changed.

I struggled a little doing multilingual sites in Drupal 8 the same way I was used to in Drupal 7 because node translation is not available anymore (which is good) so I had to find another way to achieve the same easy to handle translations system. For us and for our clients. Let me explain, what I have learned.

Drupal 8 multilanguage

Image: drupal8multilingual.org

Drupal 8 issues multilanguage challenges

Challenge 1: Node add / edit menu handling

The main challenge I had using Drupal 8, was the ease to build your menus directly from the node creation page. You can do it, but only for the initial language. If you try to add a translated node to another menu or rename the item, it always ends up moving / renaming the source node instead of adding a link to the translation. So it can become quite confusing building a navigation directly from the node creation page or to add translations to the menu. A workaround was to add all navigation items manually in the menu administration if you are using a menu per language. With lots of languages and menus / items, this is not really a convenient task. Fortunately, translations from the node creation page have been implemented with a later release of Drupal 8.

Challenge 2: Untranslated Nodes show up in Menu

Another thing which bothered me was that untranslated nodes show up in the navigation (if you use only one menu). This can be quite confusing since most of the times not every page is translated in every language. Or in some languages, you need a little more than in others. You can read a lot about this topic and the reasons behind (e.g. here and here). However you do it, it's always wrong in some situations and perfectly fine in others. But to be “limited” and “locked in” to a certain way is not nice and you have to deal with it. To sum up, once a node is put into a menu, it will show up everywhere. Regardless if there are translations or not.

Challenge 3: Language Switcher shows all languages – always.

Somewhat confusing is the Language Switcher. In Drupal 7, a language link was not available or strikethrough if there was no translation available. In Drupal 8, every language is always visible and linked. So if you look on a German page which is only available in German, the language switcher will present you all language links to the same node. A click on those language links mainly changes the interface language but the node content remains the same (since not translated). Usually also with a drupalish URL (node/xxxx) because there is no translation for the node and therefore also no URL alias available. This behavior is confusing and wrong in my point of view

An example to illustrate the above-written challenges.

multilanguage issues with Drupal 8

English Front-Page with mixed navigation items.

The screen above shows an installation with 2 languages (English and German). The English Page is a basic page which has a translation. English is selected. If you choose Deutsch on the language switcher, the English Page becomes Deutsche Seite (see image below) and shows the German content. So far so good. But the second menu item you see with the title Über uns (nur Deutsch) should not appear here since it's only available in German. But it does. And if you actually go on this page, you will see the German text with everything English around it and no URL-Alias (/node/2 in this example). This is usually not very useful for us.

German only Page – Language Switcher visible.

Also, the language switcher shown in the image above is from my point of view wrong or not very useful. It shows a link to the English version, but there is no English translation for this node. So why is it there? To see a German page with English decoration? Not sure. But I want to get rid of this link or at least modify it to be stroked through if the language is not available.

How to fix improve this?

Luckily, the Drupal community is always good for help. After some “research” on the web, I finally found (besides lots of discussions and comments in the issue queues) a way to achieve the desired setup.

To sum up again: I want to see only menu items which are available in my language and only see a link to another language, if a translation is available.

Since there is no patch and still some ongoing discussions on drupal.org you need to implement it on your own. Implement the following two modules.

Hide untranslated menu items

Code from drupal.org/node/2466553. Credits go to michaelkoehne.

getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
      ->getId();
    foreach ($variables['items'] as $key => $item) {
      if (!$variables['items'][$key] = MYMODULE_checkForMenuItemTranslation($item, $language)) {
        unset($variables['items'][$key]);
      }
    }
  }
}

function MYMODULE_checkForMenuItemTranslation($item, $language) {
  $menuLinkEntity = MYMODULE_load_link_entity_by_link($item['original_link']);

  if ($menuLinkEntity != NULL) {
    $languages = $menuLinkEntity->getTranslationLanguages();

    // Remove links which are not translated to the current language.
    if (!array_key_exists($language, $languages)) {
      return FALSE;
    }
    else {
      if (count($item['below']) > 0) {
        foreach ($item['below'] as $subkey => $subitem) {
          if (!$item['below'][$subkey] = MYMODULE_checkForMenuItemTranslation($subitem, $language)) {
            unset($item['below'][$subkey]);
          }
        }
      }
      return $item;
    }

  }
}

function MYMODULE_load_link_entity_by_link(MenuLinkInterface $menuLinkContentPlugin) {
  $entity = NULL;
  if ($menuLinkContentPlugin instanceof MenuLinkContent) {
    $menu_link = explode(':', $menuLinkContentPlugin->getPluginId(), 2);
    $uuid = $menu_link[1];
    $entity = \Drupal::service('entity.repository')
      ->loadEntityByUuid('menu_link_content', $uuid);
  }
  return $entity;
}

Hide untranslated languages in language switcher

Code from drupal.org/node/2791231 (slightly adapted. Links get a class, not removed by default). Credits to Leon Kessler.

 $link) {
      try {
        if ($entity->getTranslation($lang_code)->access('view')) {
          $new_links[$lang_code] = $link;
        }
      }
      catch (\InvalidArgumentException $e) {
        // This language is untranslated so do not add it to the links.
        $link['attributes']['class'][] = 'not-translated';
        $new_links[$lang_code] = $link;
      }

    }
    $links = $new_links;

    // If we're left with less than 2 links, then there's nothing to switch.
    // Hide the language switcher.
    if (count($links) < 2) {
      $links = array();
    }
  }
}

/**
 * Retrieve the current page entity.
 *
 * @return Drupal\Core\Entity\ContentEntityInterface
 *   The retrieved entity, or FALSE if none found.
 */
function MYOTHERMODULE_get_page_entity() {
  $params = \Drupal::routeMatch()->getParameters()->all();
  $entity = reset($params);
  if ($entity instanceof ContentEntityInterface) {
    return $entity;
  }
  return FALSE;
}

Please note: The code above is from Drupal.org and therefore thanks to the original authors linked above.

Enable those two modules and you're all set!

I did not encounter any issues yet using those two modules. If ever something changes in the way Drupal handles those cases, you just need to switch off the modules and everything should be back to normal. So nothing to lose right?

There are other attempts to this by altering the menu block. One of them is Menu Block Current Language but I had no luck with this one. On my most recent project, it worked with one menu but not if you separate your menu by two blocks (different starting levels).

I would love to hear how you guys handle those cases or how you deal with I18N in general. I'm sure there are a gazillion other ways to do it.

Apr 11 2017
Apr 11

The European Drupal Business Days 2017 take place in Frankfurt from 18.05.-20.05.2017. We are a Platinum sponsor and support the event. In addition, we would like to share our expertise in major publishing projects with Thunder.

[embedded content]

At the European Drupal Business Days, not only decision-makers, marketing managers or CXOs meet, but also customers for Drupal services. The event takes place at the Radisson Blu in Frankfurt am Main. Through the input of the various speakers from very different areas, each participant of the event can learn something new.

Subjects of the sessions are for example: issues such as brand communication or content management topics that help Drupal projects to success. In addition, social media strategies play a role as well as project management in Drupal projects. Total should be taught how Drupal projects become successful.

The keynote speakers

Here are some of the great speakers this year:

  • Collin Müller, Business Development, from Hubert Burda Media
  • Zach Chandler, Web Strategist at Stanford University

Anja from undpaul will give a lecture as part of Collin Müller's keynote session on "Our experience with Thunder in the real world". Another keynote speaker from Vodafone is planned, but not fixed yet. More information about all the entries submitted so far, you find here: Sessions.

Get in Touch in Frankfurt

Do we meet in Frankfurt? Now secure tickets under www.drupalbusiness.org

Apr 06 2017
Apr 06

After implementing some larger enterprise Drupal 8 websites, I would like to share some insights, how to solve common issues in the deployment workflow with Drupal 8 CMI.

Introduction to Drupal CMI

First of all, you need to understand, how the configuration management in Drupal 8 works. CMI allows you to export all configurations and its dependencies from the database into yml text files. To make sure, you never end up in an inconsistent state, CMI always exports everything. By default, you cannot exclude certain configurations.

Example:

If you change some configuration on the live database, these configurations will be reverted in the next deployment when you use

drush config-import

This is helpful and will make sure, you have the same configuration on all your systems.

How can I have different configurations on local / stage / live environments?

Sometimes, you want to have different configurations on your environments. For example, we have installed a “devel” module only on our local environment but we want to have it disabled on the live environment.

This can be achieved by using the configuration split module.

What does Configuration Split?

This module slightly modifies the CMI by implementing a Config Filter. Importing and exporting works the same way as before, except some configuration is read from and written to different directories. Importing configuration still removes configuration not present in the files. Thus, the robustness and predictability of the configuration management remains. And the best thing is: You still can use the same drush commands if you have at least Drush 8.1.10 installed .

Configuration Split Example / Installation Guide

Install config_split using composer. You need need at least “ 8.x-1.0-beta4” and > drush 8.1.10 for this guide.

composer require drupal/config_split "^1.0"

Enable config_split and navigate to “admin/config/development/configuration/config-split”

drush en config_split -y

Optional: Installing the chosen module will make the selection of blacklists / greylists way more easier. You can enable chosen only on admin pages.

composer require drupal/chosen "^1.0"

I recommend you to create an “environments” subfolder in your config folder. Inside this folder you will have a separate directory for every environment:

Drupal 8 Configuration Management Folders

Now you can configure your environments:

Config Split in Drupal 8 Configuration Management

The most important thing is, that you set every environment to “Inactive”. We will later activate them according to the environment via settings.php

Config Split settings with the Drupal 8 Configuration Management

Here is my example where I enable the devel module on local:

Dev Environment Example

Activate the environments via settings.php

This is the most important part of the whole setup up. Normally, we never commit the settings.php into git. But we have a [environment]-settings.php in git for every environment:

settings.php (not in git)

variables-dev.php (in git and included in the settings.php of dev)
variables-live.php (in git and included in the settings.php of live)
settings.local.php (in git and included locally)

You need to add the following line to the variables-[environment].php. Please change the variable name according to your environment machine name :

// This enables the config_split module
$config['config_split.config_split.dev']['status'] = TRUE;

If you have done everything correctly and cleared the cache you will see  “active (overriden)” in the config_split overview next to the current environment.

Now you can continue using

drush config-import -y
drush config-export -y

and config_split will do the magic.

How can I exclude certain Config Files and prevent them to be overridden / deleted on my live environment?

The most prominent candidates for this workflow are webforms and contact forms . In Drupal 7, webforms are nodes and you were able to give your CMS administrator the opportunity to create their own forms.

In Drupal 8 webforms are config entities , which means that they will be deleted while deploying if the yml files are not in git.

After testing a lot of different modules / drush scripts, I finally came up with an easy to use workflow to solve this issue and give CMS administrators the possibility to create webforms without git knowledge:

Set up an “Excluded” environment

First of all, we need an “excluded” environment. I created a subfolder in my config-folder and added a .htaccess file to protect the content. You can copy the .htaccess from an existing environment, if you are lazy. Don't forget to deploy this folder to your live system before you do the next steps.

FoldersExcluded

Now you can exclude some config files to be excluded / grey-listed on your live environment:

webform.webform.*
contact.form.*
Greylist Webform in Config Split

Set the excluded environment to “Inactive” . We will later enable it on the live / dev environment via settings.php.

Enable “excluded” environment and adapt deployment workflow

We enable the “excluded” environment on the live system via variables-live.php (see above):

// This will allow module config per environment and exclude webforms from being overridden
$config['config_split.config_split.excluded']['status'] = TRUE;

In your deployment workflow / script you need to add the following line before you do a drush config-import:

#execute some drush commands
echo "-----------------------------------------------------------"
echo "Exporting excluded config"
drush @live config-split-export -y excluded

echo "-----------------------------------------------------------"
echo "Importing configuration"
drush @live config-import -y

The drush command “ drush @live config-split-export -y excluded ” will export all webforms and contact forms created by your CMS administrators into the folder “excluded”. The “drush config-import” command will therefore not delete them and your administrators can happily create their custom forms.

Benefit of disable “excluded” on local environment

We usually disable the “excluded” environment on our local environment. This allows us to create complex webforms on our local machine for our clients and deploy them as usual. In the end you can have a mix of customer created webforms and your own webforms which is quite helpful.

Final note

The CMI is a great tool and I would like to thank the maintainers of the config_split module for their great extension. This is a huge step forward making Drupal 8 a real Enterprise CMS Tool.

If you have any questions, don't hesitate to post a comment.

Mar 29 2017
Mar 29

Hang on, doesn't that mean that the age old problem of people's heads getting chopped off will rear it ugly head (excuse the pun)? In the olden days, yes; but given the AMAZING work the Drupal Media team has done, we were able to use a cropping tool (Image Widget Crop) to allow editors to choose how each image would look for each image style created. This means one image uploaded to the site, reused in many representations, without fault. How we did that can be explained in another blog post - for now, these screenshots should suffice to show how seamless our solution works:

Drupal 8 media crop - landscapeDrupal 8 media crop - portrait

And now for our solution to allow editors to choose which version of the image they wanted for teasers. What we did was created another text field with two options 'Landscape' and 'Portrait'.

Drupal 8 node edit form teaser section

Then in the twig file for the teaser view mode (node--teaser.html.twig) we checked what the value of this field was. We then used the 'Twig Tweaks' module to load the image with the corresponding image style.

The code looks like this:

This blog post was inspired by Third & Grove's blog post - One Image Field, Multiple Aspect Ratios.

Mar 28 2017
Mar 28

When I joined the Drupal community I felt that I arrived in the enthusiastic, welcoming and positive environment. I felt that all contributions are appreciated and that we're all following more or less the same goal. This belief was also mostly the source of motivation for my extensive contributions to the Drupal 8 Media initiative in the past 4 years or so. This has dramatically changed in the last year or so and seems to be getting worse all the time.

Our community has governance and conflict-resolution rules. Everything should be clear and transparent. At least in theory. But in practice things don't work that way. Decisions (political and technical) are often made behind closed doors where only small fraction of the community is allowed to participate. Decision processes are nontransparent and leadership doesn't seem to feel any need to improve that. This was also the main reason why I recently decided to discontinue my DA membership.

I think that, in order to survive in the long term, we'll need to reform our community to become truly transparent and democratic. We've been "living" in a dictatorship and it has been working for us so far. But history shows that too much concentration of power in an small ruling clique almost always leads to its abuse (I strongly recommend this book).

My impression is that the community in general is getting increasingly toxic. It feels that there is more and more hypocrisy, lies, secret goals and partial interests being involved (and I think that the lack of transparency contributes to that). Best indicator for in my case are the community events which have (with some rare bright exceptions) become a burden instead of enjoyment for me. I still enjoy meeting some people that have become my friends during the years, but I recently started seeing the community in general as increasingly negative, abusing and exhausting.

Stress and bad mood directly linked to the happenings in the Drupal started affecting my personal life, including relations with my family. This is not acceptable and I decided to take some time off to think about the situation and to decide if and to what extent I want to remain active in the community. This decision was not made solely due to the most recent ousting (which also clearly showed how the community and its leadership actually work). It is based on many events that happened in last year or so.

This is my personal decision and has nothing to do with my employer. I really enjoy working at MD Systems and have no intentions to introduce any changes into that part of my life.

Mar 25 2017
Rob
Mar 25

Continuous Integration & Delivery: Resources

High performing software development teams will use some form of an agile methodology to produce their work, releasing it in iterations, or even continuously. Awareness can be seen as the root of agility in these development environments. An example of increasing agility by increasing awareness can be seen in implementations of continuous integration, which is the maximizing and automating of awareness during software development.

We recently did a webinar with Pantheon to go past the tooling hype and look at the benefits, of the Continuous Integration & Delivery possible on their platform, for developers, project managers, and clients. 

[embedded content]

We also put Acquia Pipelines Beta through similar paces and delivered the following webinar, giving a glimpse of what’s coming soon for Continuous Integration & Delivery on their platform.

[embedded content]

Below are links to resources and more information on our work in this area:

  • Our  Drupal scaffold - A starting point for any new Drupal 8 project that comes equipped with many best practice features and tools, including pre-baked CircleCI and TravisCI integration
  • Rob’s 2016 Badcamp session talks about our work on the scaffold and explains the nuts and bolts.
  • See the full article from Kelly on how Awareness Enables Agility.
  • We’re proud to provide Continuous Delivery services. See some of that work here.

Get to know more about who we are. Or, contact us here to work with us.

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.

Mar 22 2017
Mar 22

Tomorrow I'll be giving a workshop about the Drupal 8 media. As part of it we'll build a "media" site from scratch. We will start with the standard Drupal installation, add modules and configuration and see how far we can get.

If you are planning to attend the workshop and want to be fully productive I'd ask you to take some time and prepare your development environment. We will need Drupal 8 checkout with the following modules:

Besides that we'll also need Dropzone and Slick libraries, which you can install based on the docs provided in the README files of the respective modules ([1], [2]).

You can download all dependencies manually or use the project template that I provided for you. Simply clone the repository and run composer install && composer drupal-scaffold in the project root.

Mar 20 2017
Mar 20

Once again, the whole Electric Citizen team is going on a trip to DrupalCon North America.

The annual pilgrimage for Drupal users, designers, project managers, developers and open-source enthusiasts lands in Baltimore this year – April 24th-28th. We’ll be taking in loads of sessions, keynote talks, trainings, and summits. And of course, lots of team-building fun.

Expect to see an uptick on Twitter and Facebook, as well as some new photos and blog posts when we get back. We usually come back from DrupalCon with lots of new ideas and energy to put them into action, especially around Drupal 8.

If you’re planning to be in Baltimore, let us know at @elecitizen on Twitter. We’d love to connect with new friends, or reconnect with old ones.

Mar 16 2017
Mar 16

The Splash Awards 2017

We were there: at the first German Splash Awards 2017 in Hamburg. The award show with Dutch roots took place for the first time in Germany.

Above all, the Splash Awards are designed to honor those who make remarkable use of Drupal. Not only Drupal agencies, but also individual Drupal developers are taken into account with their submitted projects. In addition to eight awards, a Drupalista of the Year was also selected. The Drupalista award is designed to highlight the people who have made a significant contribution to the Drupal community and have been specially dedicated to the Drupal community last year.

The nominees, the categories and the jury

27 projects were nominated in nine categories. The submitted projects were diverse and came from different fields such as the food, health, e-learning, chemical and publishing industries. undpaul was nominated in the category publishers/media with the project "Mein Schöner Garten". The jury of the Splash Awards 2017 included Jeffrey A. "jam" McGuire, Robert Douglass, Meike Jung, Rouven Volk and Marc Dinse.

The location

In the heart of St. Pauli, the award ceremony took place in two locations in the clubhouse. The reception as well as the after show party were arranged at kukuun, while the actual awarding took place at Häkken. The exceptional location, the professional service staff and the successful aftershow party put the awards uniquely in the scene.

The winners

All winners in the respective categories can be found here.

undpaul wins Award

We are proud to have received the award for best project in the category publishing & media. A big thank you to everyone involved!

Mar 06 2017
Mar 06

As part of our ongoing Drupal Commerce module walkthrough, I'm going to show you how to create custom Products. The Commerce Custom Products module allows the creation of custom line items on Products for customer input. Custom line items for Products are essential when the customer must define something about the Product that they're adding to the cart. A few examples of how you may use Commerce Customizable Products includes:

  • Events or other registrations
  • Donations
  • Inscriptions
  • Personal messages on made-to-order products
  • Pizza orders
  • Personalized gift baskets

Drupal Commerce Module Installation

You will need to have the following modules downloaded and installed:

Required Modules

Dependencies

I have enabled all Drupal Commerce modules, the dependencies, and the Commerce Custom Product module for this walkthrough. 

Customizable Products with Product Types, Products, and Product Displays

This tutorial builds on my previous tutorials. You will need to create a Product Type, add your Products, and a create Product Display. These will become your custom Product with Custom Line Items.

I also strongly recommend you watch the Custom Products YouTube tutorial that goes along with this article. You can follow my previous Drupal Commerce guides below to get you started:  

For this tutorial, I have created a basic Product Type called "Event." I have two Products for event dinners:

  1. Dinner 1: $19.99
  2. Dinner 2: $23.99

I created a Content Type for my Product Display, and I've created a Product Display node.

A Future Commerce Customizable Products

Since my event is a dinner, I should collect dietary information from my customer. To collect this information, I'll need to create a Product with Custom Line Items.

Create Customizable Products

Navigate from Administration → Store → Configuration → Line Item Types. Select Add a Product Line Item Type.

Name your custom Line Item Type. Select save Line Item Type.

Create Custom Line Item Type

Add and configure your Line Item fields.

Add and Configure Customizable Line Item Type fields

On all fields that require customer input, select Include this field on the Add to Cart form.

Configure Custom Line Item

Finish adding and configuring your other fields. Save and adjust the display settings on your Line Item Type.

Customized Line Item Type Display Settings

Save your Line Item Type Display settings.

Navigate from Administration → Structure → Content Types. Select Manage Display on the Product Display you will using for your customized Products.

Manage Display Settings on Commerce Product Display for Customized Products

Under the Product Reference field, update your Add to Cart line item type. Change to your new Line Item type for your Customized Product Line Items.

Custom Products: Configure Custom Line Item Add to Cart Line Item Settings

Save your changes. Navigate to your Product Display node to view your customized Product.

Drupal Commerce Customizable Product with Custom Line Items

Next up, I'll show you how to incorporate price changes with custom Products using Drupal Commerce and Rules.

Reach out If you're interested in having us build an e-commerce solution in Drupal for you or your organization. Think this tutorial is useful? Don't forget to share!

Mar 06 2017
Mar 06

In the modern world of web / application development, using package managers to pull in dependencies has become a de-facto standard. In fact, if you are developing enterprise software and you aren't leveraging package managers I would challenge you to ask yourself why not?

Drupal was very early to adopt this mindset of pulling in dependencies almost a decade ago when Dmitri Gaskin created an extension for Drush (the Drupal Shell) that added the ability to pull contributed modules by listing them in a make file (I think Dmitri was 12 years old when he wrote the Drush extension, pretty amazing!). Since that time, the make extension has been added to Drush core.

Composer is the current standard for putting together PHP applications, which is why Drupal 8 has gone this direction, so why not use Composer to put together Drupal 7 applications?

First off, I want to clarify what I'm not talking about in this post. I am not advocating that we ditch Drush all together, I still find value in other aspects of what Drush can do. I am specifically referring to the Make aspect of Drush. Is Drush Make still necessary?

This post is also not about Drupal Console vs Drush, both CLI tools add tremendous value to development workflow, and there isn't 100% overlap with these tools [yet]. I think we still need both tools.

This post is about how I came to see the benefit of switching to Composer from Drush Make. I recommend making this move for Drupal 7 and Drupal 8. This Drupal Composer workflow is not new, it has been around for a while. I just never saw a good reason to make the jump from Drush Make to this new process, until now. We have been asked in the comments on previous posts, "Why haven't you adopted the Composer process?" I now have a good reason to change our process and fully jump on board with Composer building Drupal 7 applications. We appreciate all the comments we get on our blog, it sharpens everyone involved!

We have blogged about the Composer workflow in a previous post on our [Drupal 8 build process]({% post_url 2016-07-13-drupal-8-development-in-docker-redux %}) in the past, but the main motivation there was to be proactive about where PHP application development is going [already is]. We didn't have a real use case for the switch to Composer until now. This post will review how I came to that revelation.

Dependency Managers

I want to make one more point before I make the case for Composer. There are many reasons to use package managers to pull in dependencies. I'll save the details for another blog post. The main reason developers use package managers is so that your project repository does not include libraries and modules that you do not maintain. That is why tools like Composer, npm, Yarn, Bower, and Bundler exist. Hook up your RSS reader to our blog, I'll explain in more detail in a future post, but for now I'll leave this link to the Composer site explaining why committing dependencies is a bad idea, in your project repo.

Version Numbers

The #1 reason to make the switch to Composer is the ability to manage version numbers. You may be asking "What's the big deal, Drush Make handles version numbers as well?" let me give you a little context of why using Composer version numbers are a better approach.

The Back Story

Recently in a strategy meeting with one of our enterprise clients, we were discussing how to approach launching 100's of sites on one Drupal Core utilizing multiple installation profiles on top of Acquia Site Factory. Our goal was to figure out how we could sanely manage updating potentially dozens of installation profiles without explicitly defining each version number of the profile being updated. This type of Drupal architecture is also a topic for a future blog post, but for now read Acquia's explanation of why architecting with profiles is a good idea.

As a developer, it is common place to lock down versions to a very specific version so that we know exactly what versions we are using / deploying. This is the reason composer.lock, Gemfile.lock, yarn.lock, and npm shrinkwrap exist. We have experienced the pain of unexpected defects in applications due to an obscure dependency changing deep in the dependency tree. Most dependency managers have a very explicit command for updating dependencies, i.e. composer update, bundle update, yarn upgrade respectively, which in turn update the lock file.

A release manager does not need to know explicitly which version of a dependency (installation profile, module, etc), to release next, she simply wants the latest stable release.

Herein lies the problem with Drush Make. There are practices that exist that solve both the developer problem and release manager problem that do not exist in Drush Make, but do exist in Composer and other application development environments. It's a common pattern that has been around for a while, it's called semantic versioning.

Semantic Versioning

If you haven't heard of semantic versioning (semver), go check it out now. Pretty much every package manager I have dealt with has adopted semver. Adopting semver gives the developer, or release manager, the choice of how to update dependencies within their app. There are very distinct numbers in semver for introducing breaking changes, new features, and bug fixes. How does this play into what problem use cases I mentioned above?

A developer has the ability to specify in the composer.json file specific versions, while leaving the version number flexible to pull in new bug fixes and feature improvements (patch and minor releases). Look at the example below:

{
  "name": "My Drupal Platform",
  ...
  "require": {
	...
    "drupal/drupal": "~7.53.0",
    "drupal/views": "^3.14.0"
  },
  ...
}

The tilde ~ and caret ^ symbols have special meanings when specifying version numbers. The tilde matches the most recent minor version (updates patch release number, the last number), the caret will update you to the most recent major version (updates minor release number, the middle number).

The above example basically says, use the views module at version 3.14, and when version 3.15 comes out, update me to that version when I run composer update.

Breaking changes should only be introduced when you update the first number, the major release. Of course, if you completely trust the developer writing the contributed code this system would be enough, but not all developers follow best practice, which is why the lock file was created and the need to explicitly run composer update.

With this system in place, a release manager now only needs to worry about running one command to get the latest stable release of all dependencies. This command could also be hidden behind a nice UI (a CI Server) so all she has to do is push one button to grab all the latest dependencies and push to a testing site for verification.

Understanding everyones needs

In the past, I didn't have a good reason to move away from Drush Make, because it did the job, and Drush is so much more than Drush Make. The strategy session we had was eye opening. Understanding the needs from an operations perspective, while not jeopardizing the integrity of the application led us down a path to see a problem that the wider development community at large has already solved (not just the PHP community). It's very rewarding to solve problems like this, especially when you come to the conclusion that someone has already solved the problem! "We just had to find the path to the water! (--A.W.)"

What do you think about using Drush Make vs Composer for pulling together a Drupal Application? Leave us your thoughts in the comments.

Feb 23 2017
Feb 23

Since its relaunch in 2015, the Drupal 7 powered precore.net has been gaining popularity among artists and design students to become their go-to platform. Until today, design students have uploaded over 700 portfolios providing guidance to enrolling candidates. These portfolios are linked to over 500 art faculties of hundreds of universities.

Before enrolling in a course, a candidate can research their local university and study other students' portfolios or enroll in their local design course to prepare for the entry tests - all of it on precore.net.

On top of that, students provide and collect support on the precore.net forum which boasts over 20000 users who have written nearly 250000 posts. This may be the biggest and most beautiful forum built on top of Drupal core.Frontpage

The most powerful feature however may be the ability for guests to create most of the site's content without having to go through any type of registration process. Visitors can go ahead and correct their school's information just by clicking 'edit'. Likewise, anyone can write a blog post - no account or personal information needed. We think this technology has massively contributed to the quantity and quality of content on precore.net.

While the numbers of design students, universities and art schools registering with the platform has been growing steadily, the visionaries behind the project, Ingo Rauth and Wolfgang Zeh from projektgestalten, recently decided to take the platform to the next level by bringing it to jobseekers and providers as well. Consequently gbyte has implemented the event functionality and the new job board.

This is not going to be the last improvement though, apparently artists have lots of creative ideas and we look forward to implementing them. We feel that this project is a great showcase of Drupal's possibilities and if you would like to learn more about the project or its implementation, make sure to leave a comment below or contact us via the contact form.

Check out other technology-centric posts about the project as well as more screenshots on the project page.

Feb 16 2017
Feb 16

In this Drupal 7 tutorial, I'm going to explain the differences between a Product Display and Products when using the Drupal Commerce module. Then, I'll show you how to build a Product Display for your e-commerce store.

Understanding Product Display concepts in Drupal Commerce

A Product Display can be any Drupal entity with a Product Reference field that is used to display your Products to your customers. Product Displays can be taxonomy vocabularies, views, users, and nodes.

A key to understanding Drupal Commerce is that it separates Products from the Product Display. We’ve already built a Product Type and added Products to that Product Type in the previous Drupal Commerce tutorial. Yet, there’s no public method to see or purchase products yet. That’s where the Product Display comes in. Drupal Commerce separates Products from their Product Displays for a number of reasons, essentially it allows display of Products to be more versatile.

Creating a Product Display Content Type

If you recall from my last Products tutorial, our Drupal e-commerce store is a boutique that sells wines. We priced different vintages of the same wine at different price points and included different images for the vintages. This represents a Product Variation in the Product itself, but it also succinctly represents one of the advantages of breaking out Products from the Product Display. For instance, I may have two vintages of the same type of wine and with different inventory levels, but I don’t want to display these vintages as completely separate Products. I want to have the vintage be an option for my customers on the Product. Therefore, I need a solution that allows a seamless display for my customers to choose their purchase.

Let’s dive into creating a Product Display for our wine.

Navigate to Structure → Content Types → Add Content Type. Name your Content Type and adjust the Content Type settings according to your needs.

Create a Product Display Content Type

You can also customize fields on this Product Display Content Type to fit your Product Display needs.

Add and configure a new field for the Product Reference. When adding the new field, you'll see a new field format option called "Product Reference" as seen below.

Add a Product Reference field to your Product Display

Configure the Product Reference field on your Product Display Content Type.

Drupal Commerce, Product Reference Field Configuration

Configure the display settings by selecting Manage Display on your Product Display Content Type.

Drupal Commerce, Product Display Content Type: Manage Display settings

In the below image, notice the additional fields on the display settings. These fields are shown on the Content Type after the addition of the Product Reference field, and they represent the fields on your Product Type.

Drupal Commerce Product Display Content Type, Display Settings

You may want to adjust the field order and other display setting options here. For my Product Reference field, I do want to display an Add to Cart form, but I want to adjust the settings of this field. I want my customers to have the ability to enter the quantity of the Products they're selecting to order, so I'll select "Display a textfield quantity widget on the add to cart form," select Update. Save your changes.

Drupal Commerce Add to Cart settings

You can now begin adding your individual Product Displays by adding nodes to this Product Display Content Type. So, you'll navigate from Content → Add Content and begin adding content to your Product Display. For my Drupal e-commerce store, I've created three Products:

  1. 2014 Pinot Noir
  2. 2016 Pinot Blanc
  3. 2015 Pinot Blanc

Since I want my Pinot Blanc wines to appear in a singular Product Display, I will only need to add two nodes, which will be my Product Displays:

  1. Pinot Noir
  2. Pinot Blanc

Here's an example of the node creation for the Product Display below.

Drupal Commerce Product Display

After saving, I now have Product Displays to display my Products to my customers. Because we selected the vintage field as an Attribute on the Add to Cart form and since we have two Products on the Pinot Blanc Product Display, my customer can toggle the vintage to select their Product. Toggling the vintage will now change both the image and price of the Product they're viewing. As you can see from my Pinot Noir, this select widget is not available on Products with a singular Product Reference.

Drupal Commerce Product Display, Attributes in Action

Drupal Commerce Product Display

Stay tuned for more tutorials on how to customize your Drupal Commerce site. If you're interested having us build an e-commerce solution that's aligned with your Drupal web strategy and marketing objectives, reach out. Think this tutorial is useful? Don't forget to share!

Feb 15 2017
Feb 15

One way to start is to check the session that gave at the Drupal dev days Milano in June 2016. I went through the architecture of the module and most common use cases.

[embedded content]

I also proposed a Media workshop for Drupal dev days Seville where I want to cover the entire Drupal 8 Media ecosystem from the site builder's perspective. Besides that I also proposed a session about my recent experiments with Elixir. Not necessarily Drupal or PHP related, but I think that looking beyond our bubble can be very beneficial.

Feb 08 2017
Feb 08

In this first in a series of Drupal Commerce Guides, we work through setting up the relevant Drupal CMS modules and taking the first steps in our e-commerce site creation tutorial. To get started, we need to understand what Commerce's Product and Product Types are, as well as how to implement them.

Understanding Products and Product Types

Products vs Product Types in Drupal Commerce Module

Let’s say you own a boutique with an online e-commerce store where you might sell gift baskets, wine, and perhaps tickets to special events. These are your Product Types and to put it simply, they are just the types of Products that you sell. Within these Product Types, you sell may sell a variation of individual Products. For instance, within a wine Product Type, you may sell a Pinot Noir wine and a Pinot Blanc wine. Pinot Noir and Pinot Blanc are individual Products of the Product Type wine. A Product Type is not unlike a Content Type in many ways. In fact, it was Drupal 7's entity system that inspired the team behind the project, Commerce Guys, to structure and build Drupal Commerce using entities. In Drupal Commerce, a Product Type is a specific bundle based on a custom product entity much like my example with wine. Each bundle can have fields attached to it with product attributes and variations to further define Products, much like you would define fields in Content Types.

Products can be easily compared to Nodes as well. They're product content added to their respective Product Types.

Module Installation

In this tutorial, I'm assuming that you already know how to download and install modules, so I've foregone those steps. Here's a one-liner for Drush to grab the stable/suggested version and dependencies:

drush en commerce -y

Required Modules

Dependencies

For reference, I've enabled all Commerce related modules for this Drupal Commerce tutorial.

I’ve installed a few unrelated modules that you may see in my tutorial video above. Those include:

Create a Custom Product Type

Let's begin adding a Product Types in Drupal Commerce. When you enabled the Product UI module earlier, a basic Product Type was created. A basic Product Type includes:

  • a product SKU
  • the title of the product
  • a price field
  • a status field

Let's create a custom Product Type.

Navigate from Administration → Store → Products → Product Types. Select Add Product Type.

Drupal Commerce Tutorial: Creating Product Types

Configure the Product Type, then select: "Save and add fields."

Drupal Commerce Tutorial: Configure Product Types

The base Product Type fields are created by default when you add a new Product Type, see below. Add fields to customize your Product Types.

Drupal Commerce Tutorial: Creating Product Types

For my wine Product Type, I've added an image field and a List (text) field to define my wine type. These two fields are known as informational field variations. In other words, these fields will not alter the price of my Product. Instead, these fields will provide additional information about my Product.

I'll also add a List (text) field for a vintage selection. My vintage selection will alter how the Product looks and the price of my Product, however. Therefore, I will select "Enable this field to function as an attribute on the Add to Cart forms."

Drupal Commerce Tutorial: Creating Product Types with Attributes

Next, adjust the Display settings on your Product Type. Choose Manage Display and adjust accordingly. Typically, I hide the Product SKU, Status, and most Field Labels. Save and begin adding your Products.

Drupal Commerce Tutorial: Creating Product Types and Managing the Display

Add Products to your new Product Type

Navigate to Administration → Store → Products → Add a Product. Enter the Product information and save.

Drupal Commerce, Add Product

Drupal Commerce, Create Product

Once you've added your Products, it's time to learn about creating Product Displays to make your Products available to your customers.

Reach out If you're interested in having us build an e-commerce solution in Drupal for you or your organization. Think this tutorial is useful? Don't forget to share!

Feb 06 2017
Feb 06

Drupal 8 has very good media handling support. Media team has (and still is) working hard to make Drupal the best CMS in the world when it comes to managing media. We have many modules in the contrib space that solve most of the common use cases in the domain. There is one problem though; there are many of them and some of them are quite complex and abstract. I've noticed that many times users struggle to completely understand what each module is responsible for, which features it comes with and specially how they all together fit into the bigger picture.

There are so-called feature modules (such as File entity browser, Media, Content browser, Media entity browser, ...) and distributions (such as NP8, Thunder, Lightning, ...) which ship with default configuration for the 80% use case. They are plug and play solutions, but it is also possible to use them as a base for learning and research of the ecosystem.

But unfortunately that's not enough. While some people learn the quickest by exploring existing solutions (myself included) that isn't the case for everyone. A lot of people need more guidance and those are the users that we're currently not supporting as much as we should. In order to drive further adoption of the media ecosystem and Drupal 8 itself we need to solve this knowledge sharing problem that I believe we have.

I was thinking about this problem a lot lately and I think I came up with an idea that could help us solve it.

It is a book.

A problem solving oriented book which would guide users through the ecosystem, explain individual parts and, most importantly, offer a bunch of recipes for the common problems. It wouldn't be one of those 800+ pages technical books (who has time to read that?!). Rather it would be a compact source of information which you can have on your desk and use it when you run into a problem. We all want to build websites and the purpose of this book would be to help you do that as fast and as efficiently as possible.

Book would produced by the people that designed and built the Drupal 8 media ecosystem, which would ensure highest levels of quality. It would be released under a Creative commons license with its sources publicly available on GitHub. Printed and compiled eBook versions would be sold through the standard channels.

Why copyleft?

I honestly believe into the free sharing of knowledge in our society. My opinion is that the only way to evolve our civilization is to freely share the knowledge that we have. There are also practical reasons besides the philosophical one. Making the book publicly available ensures that it will be likely updated as the ecosystem and Drupal itself evolve and change. This wouldn't necessarily be the case if the standard copyright license would be used.

Great idea! Why didn't you realize it already?

I am glad that you agree! :) Well... it is not that easy. Producing a real book is not that simple and it also comes with quite some expenses. There is the cost of the content production, proofreading, design, print, shipping, ... I've done a back of a napkin calculation and estimated that we'd need around 20.000€/$21.500/17.000GBP to do it.

My idea was to start a crowdfunding campaign to raise this amount. Backers would, depending on the perk level, get an eBook, print edition or both. Besides that they'd also get early access to the repository with the ability to provide feedback during the process of writing.

Now I need your feedback

I need to hear from you. Is this something that would benefit the community? Is there any better way to educate users about the ecosystem? Would you prefer an online video course instead of a book? In-person training? Something else? Would you be prepared to back the crowdfunding campaign? If yes, what amount would you be prepared to invest?

Please use the form below to share your thoughts. Thank you! I appreciate it.

Feb 03 2017
Feb 03

In my previous blog post on managing microsites with Drupal 8 I promised to write something further and fuller about designing web APIs. This is less directly about Drupal 8, but I will comment on how to implement the recommendations here in Drupal 8.

These are the things that I take time to think about when building a web API.

As a developer, it’s all too easy, and too tempting, to just jump right into coding something. It’s certainly a weakness I suffer from and that I have to cope with.

Before putting the proverbial pen to paper, though, it’s really important to understand why we’re building an API in the first place. What are the problems we’re trying to solve? What do the users need or want?

With regard to building an API, that means thinking about the consumers of the data provided by your API. If you’re building a decoupled CMS, the main user is the frontend system. In other circumstances it may also mean other websites, embedded widgets, apps on mobile devices, and so on. Whatever it is, due consideration needs to be given to the needs of those consumers.

That means understanding your user’s needs, examining the patterns of behaviour of those users, and ultimately translating those into a design.

Sound like familiar language? Yes, that’s the language of visual designers and user experience specialists. In my books, I’d suggest that means you would do well to work closely with specialist design colleagues when designing and building an API.

Your web API needs to be designed: needs; behaviours; analysis; patterns; traits; design; feedback; improve.

Be an artisan with your API

Take time. Research. Think. Plan. Design.

Beware, Drupal

When you’re working with Drupal, it is too easy to jump over the design step. Drupal does so much out of the box that it’s too easy to start coding without thinking properly about what we’re coding.

The availability bias when you’re a specialist Drupal developer, having it as the go-to toolkit, is that we think about the solutions to the problems (if we’ve even got as far as articulating the problems) in a Drupally way. For instance, since Drupal has a menu system it’s easy to think about navigation in a decoupled CMS system in terms of the way Drupal handles the menu system, which prevents you from thinking about other ways of handling navigation.

The same is true with Drupal 8’s support for REST. Drupal 8 core includes REST resources for most entities in a Drupal installation. That’s very useful. But, it can also make you lazy, just using these core RESTful API endpoints for nodes or comments or whatever, with all the guff they include, without even thinking about whether they’re appropriate, whether all the guff they include is appropriate, whether it’s useful or formatted appropriately.

That goes also for REST exports from Views. They can be useful, giving you a quick way of creating a RESTful API endpoint. The problem is, thought, that also confines you to working with the way Views works and what it can produce. You may find that a problem if you want to support optionally requesting for additional objects to be embedded in the response, for instance (see below).

Resist the temptation! Instead, take the time to think from the other end first.

I’ll return to the question of designing your API below, but first we need to talk about documentation, since designing and documenting your API can be part of the same process.

Yeah, I know. Most devs find this just the dullest thing in the world to write. With a web API, though, it’s incredibly important. If you want people to actually be able to use your API, they need to know how to work with it. It’s horrible trying to work with an undocumented or under-documented API.

So, what should go into the documentation for a web API? Here’s some pointers.

The basics:

API reference

Yeah, this is probably what everyone thinks of when they think of documentation for a web API, but it is in fact only part of the documentation—maybe the most important part, but only part.

There a plenty of good blog posts and descriptions of what your API reference should include, so there’s no need for me to reiterate that here.

The most important thing to say, though, is that, beyond identifying resource paths, actions and parameters, your reference should describe in full both what the request should and the response will look like.

Mock server

It is incredibly helpful to include a mock server with your API documentation. Preferably, your mock server will handle the documented requests and responses of each resource.

This will help those building apps and tools that will consume your API to get up-and-running quickly.

For gold stars and a round of applause:

Tutorials, guides, cookbooks

If your API gets to be any substantial scale then the developers who use your API will find it incredibly useful to have some tutorials and guides included in your documentation.

These should cover common tasks, or how to work with specific sections of your API. A guide to ‘best practices’ with your API may be appropriate to help people make the most out of your API.

Check out the guides in MailChimp’s API documentation for a good example. Twitter’s API docs ‘best practice’ section are great as well.

Quick start

One invaluable guide is the ‘getting started’ or ‘quick start’ guide. This can often be just a single page, with a succinct summary of the things you need to do to get going.

The YouTube API ‘getting started’ page is a useful example.

Useful tools

There’s lots of useful tools out there to help you get started when you document your API design. Here’s some suggestions.

API Blueprint is an open-source high-level API design language that is very useful for writing your documentation. The language is similar to Markdown, so it’s easy to work with. There are a number of SaaS tools offering services based on API Blueprint. One that I really like is Apiary.io (though they’ve recently been bought by Oracle so who know where that’ll take them), but there are others, like Gelato.

You might also consider Read the Docs and daux.io amongst others. There’s also the Open API Initiative, which is ‘focused on creating, evolving and promoting a vendor neutral API Description Format,’ though the initiative is ‘based on the Swagger Specification.’ Open API is an initiative of Swagger.io, and they have a list of tools and frameworks using the specification. The OpenAPI specification is on GitHub.

Whatever you use, your documentation should (probably) end up in a public location so that other developers can use it. (An exception might be for an API used in a secure decoupled system.)

So, let’s return more directly to the question of designing your web API.

An important rule of thumb for me is to ‘keep it simple, stupid.’ There is no need to include anything more in the resources of your API than is necessary.

I say this as a long-time Drupal developer, knowing full well that we have a superpower in overcomplicating things, all those extra divs and classes all over the markup, all those huge arrays.

This is still true in the core REST resources of Drupal 8. For example, when GETting the core Content resource for node 10 /node/10?_format=json the response gives us …

{
"nid": [
{
"value": "10"
}
],
"uuid": [
{
"value": "6bfe02da-b1d7-4f9b-a77a-c346b23fd0b3"
}
],
"vid": [
{
"value": "11"
}
],

}

Each of those fields is an array that contains an array that contains the value name:value pair as the only entry. Whew! Exhausting. An array within an array, when there’s only one level-1 array ? Really? Maybe we could render that a little more simply as …

{
"nid": "10",
"uuid": "6bfe02da-b1d7-4f9b-a77a-c346b23fd0b3",
"vid": "11",

}

… which might help our API’s consuming applications to parse and use the JSON data more easily. Like I said above, I’d suggest that just using the core entity REST resources isn’t often the place to start.

The simplicity mantra should pervade your API design. Include only the data that is needed for the consuming apps. Pare it down, so it’s as easy to read as possible.

As a result, when you come to build that API in your Drupal 8 backend system, it will demand a good discipline on you of not just throwing out in the API resource responses what’s easiest but rather what’s best.

What’s in a name?

This is true in particular when it comes to your naming conventions and API resource paths.

Don’t just add root-level endpoints ad infinitum. Use well-structured paths for your resources where the depth of the path elements make sense together. The result should be that your resources are explorable via a browser address bar. E.g.

GET /articles/5/comments/19

… makes intuitive sense as a path: get comment 19 on article 5.

On the other hand, don’t just add depth to your resource paths unnecessarily. Separating things out with some logic will help make things intelligible for developers using your API. E.g.

GET /articles/comments

Umm? What’s that? The comments on articles — why would I want that? However …

GET /comments?contenttypes=articles

… is more obvious — a path to get comments, with a content types filter. Obvious. It also suggest we might be able to filter content types with a comma-separated list of types—nice!

Find a straightforward naming convention. Make the names of resource endpoints and data fields obvious and sensible at first glance.

Overall, make the way you name things simple, intuitive and consistent. If the title field of a data object in your resources is called ‘title’ in one place, ‘name’ in others and ‘label’ in still others, for instance, then it adds unnecessary complexity for writing reusable code.

When designing your web API, it needs to be simple to use and work with. Help users to get just what they want from your API.

Support limiting response fields

You’ll make developers smile if you provide a way of limiting the fields that are returned in a response. You don’t always want to get everything from a resource. Being able to choose exactly what you want can help speed up usage of an API.

For example, consider supporting a fields parameter, that could be used like this:

GET /articles/5?fields=id,title,created

Support auto-loading related resources

The opposite might also be important, being able to load extra resources in the same request. If a request can combine related resources then fewer requests will need to be made, which again will help speed up using an API.

Supporting an embed query parameter could give you this. For example:

GET /articles/5?embed=author.name,author.picture,author.created

… would enable users to load also the article author’s name, their picture and the date their account was created. Note the dot syntax, which might be useful.

Flexible formats

Another way of making it easy for users is to support flexibility in the format of the data in the response. JSON is usually what people want to handle, but some do still prefer to use XML.

There’s also the problem that JSON has no support for hyperlinks, the building blocks of the web, which is a curiosity as the W3C admit. There are JSON protocol variants that attempt to address this, like HAL and JSON-LD, but I refer you to a fuller discussion of JSON and hypermedia and some useful resources on hypermedia and APIs from Javier Cervantes at this point.

When designing your API, you should expect it to have a certain lifetime. In fact, it’s bound to last long enough to need changing and improving. But what do you do about rolling out those changes?

Your devs will need the flexibility to change things, especially if they find bugs, and they’ll get frustrated if they can’t adapt the API to make improvements.

Your users need reliability and stability, though, and they’ll get frustrated if the API keeps changing and their consumer app dies without warning.

So, from the start, include versioning.

A pretty sensible thing is use a path element to specify the version number. E.g.

GET /api/v1/articles/5

You could use a query parameter instead, of course, though since query parameters are optional that would mean that without the version parameter your API would return the latest. Consumers who’d inadvertently missed including the version in their requests would be vulnerable to changes making their app die, which might result in some flame support emails.

Make sure there’s a way for your users to let you know when they have problems, there find a bug, or whatever.

If its an internal API, like with a decoupled CMS and frontend, then that is probably your bug tracker.

If it’s a public API, then you’ll need some public way for people to contact you. If you host your repository on e.g. GitHub then there’s support for issues baked in.

Respond.

Giant lists of bugs that never get addressed are soul-crushing.

Authentication and security

You’ll probably want to include some authentication to your API. You shouldn’t rely on cookies or sessions for your API as it should be stateless. Instead, by using SSL (you’re using SSL, right? yes, you’re using SSL.), you can implement a token-based authentication approach.

However, where a token approach is inappropriate, OAuth 2 (with SSL) is probably the best way to go. Here’s some further discussion on API security and authentication, if you’d like to read in more depth.

Caching

HTTP has a caching mechanism built in — woot! Just add some response headers and do some validation on request headers and it’s there.

I’ll point you elsewhere to read more about the 2 key approaches, ETag and Last-Modified.

Use HTTP status codes

HTTP defines lots of meaningful status codes that can be returned in your API responses. By using them appropriately, your API consumers can respond accordingly.

Useful errors

If a request has an error, don’t just return an error code. Your API should provide a useful error message in a format with which the consumer can work. You should use fields in your error message in the same way that a valid response does.

In summary, when building an API it’s not healthy to just jump in and start writing the code for the API from a specification. Neither is it healthy to just rely on the default resources of CMS tools like Drupal 8. APIs always need to be tailor-made for the task.

APIs need to be designed.

If you can make your web API simple to understand and adopt, easy to work with, incorporating plenty of flexibility, if it’s stable and reliable and well-supported, then you’re well on your way to being the proud owner of a healthy API.

Jan 29 2017
Jan 29

Sculpin generator

I can hear you asking: "What the hack is that?" Let me quote the Sculpin's authors:

Sculpin is a static site generator written in PHP. It converts Markdown files, Twig templates and standard HTML into a static HTML site that can be easily deployed.

Few days ago a need for a very simple website arose which was way too simple to use Drupal 8 for it. Even Wordpress would be way over the top. On the other hand I really wanted to try static HTML generators for a while and this seemed a perfect opportunity to do that.

There are many static HTML generators out there, Jekyll probably being the most popular (it is also supported by GitHub pages, which makes hosting trivial). I, however, decided to go with Sculpin because it is written in PHP and is using Symfony and Twig. I am already more or less familiar with all these technologies, which made the task a bit easier.

Result?

Few hours, very simple Bootstrap based theme, FlexSlider, some Markdown and violà! Site was done and running. It is performant, I can host it literary everywhere, no need to clear caches every time when something behaves strange, no updates, security out of the box, ...

I could totally use something similar for this blog too. Heresy against The religion of Drupal™ you say? Maybe.... But think about it. I am already using Markdown (not really a WYSIWYG fan) to write my posts. That wouldn't change at all. I use Disqus for comments, which would play perfectly fine with static HTML. I could use Liquid Forms or something similar to run the contact form or simply ask people to reach out via Twitter or IRC. That's it. It could probably be done in a day while it took me 3 or 4 days to migrate my Drupal 7 blog to Drupal 8. Not to mention the significantly easier maintenance.

I might even consider doing that when the migration to Drupal 9 comes around. We'll see what the hip thing at that time will be...

All this got me thinking...

Solutions like Jekyll and Sculpin are gaining popularity in the lowest end of the web market. By that they are eating into what used to be market of CMSes like Drupal and Wordpress just a few years ago. Benefits are clear (mainly performance and easy maintenance). The user experience and the ease of use is still on the CMS side, but for slightly tech savvy users it is completely doable. And this might very likely change in the next few years (every software tries to improve over time, right). That said, this kind of tools might (together with pure SaaS solutions) dominate the lower-end web market in the future.

"But Drupal 8 is enterprise-oriented. That's what we care about!" you'll say. OK. Probably true, but...

It is easier than ever to build custom web projects in PHP. In the times before Composer, Packagist and all other nice stuff that we have today existed it was total PITA to find and bring a bunch of 3rd party libraries together to help you build a custom app. In just a few short years this became much simpler and will become even easier as our tools and ecosystem evolve. And PHP is not alone in this world. There are many new and modern languages/platforms that are all doing similar things from this perspective. All of them have some kind of package manager, dependency resolver, repositories of 3rd party packages, etc. It is to be expected that this will only continue. Tools will become even easier to use, 3rd party libraries/packages will become more powerful and building custom projects based on them even faster.

Higher-end projects usually have some budget to invest into development. What would you choose if the cost of development using a CMS like Drupal would be similar to the cost of building a custom project? Specially if you don't need all the features and complexity that CMS offers?

"Are you saying that Drupal is going away?" you ask.

Of course not. Drupal is a great tool that can efficiently solve many problems. But there are definitely better tools for some others. It also seems that there is strong competition on all sides of the web market, which is eating into the pie that was reserved for traditional CMSes in the past. Drupal will need to think about this and position itself into that segment of the market where it is the strongest. The days of "Drupal for everything" are clearly over.

What is your opinion about this? What do you think future will bring us? Let's continue the discussion in the comments below!

Jan 25 2017
Jan 25

There are lots of situations in which you need to run a series of microsites for your business or organisation — running a marketing campaign; launching a new product or service; promoting an event; and so on. When you’re with Drupal, though, what options do you have for running your microsites? In this article I review and evaluate the options in Drupal 8, make a recommendation and build a proof of concept.

Joe BakerConvivioPublished in

16 min read

Jan 25, 2017

A client brought me an interesting problem recently, something they need to solve for their production Drupal site. They are an international humanitarian agency who, alongside their main production website, want to run some microsites for a number of their public campaigns. Although they could run them on the main site, they’ve found too many limitations in trying to do that. Campaign teams, frustrated with the lack of flexibility and slow protocols for getting changes made to support their bespoke needs, have often gone off with their small budget and dynamic team to create something quick that fits their campaign with Squarespace or Wordpress or something.

That made the campaigners really happy. But, when the campaign or event lapsed, the campaign site quickly got out of date and went unloved, the campaign team moved on and no-one could remember how to log into the system and it became abandoned.

Hearing this story was so familiar — the same thing often happened when I was a senior developer at Oxfam International.

So, they said, could something be done about it? What, if anything, could be done with Drupal to support campaigners get their microsites running? What would give them the fast, bespoke solution to their microsite problems, whilst still keeping all the content well-managed and being able to share that content with the main site or other microsites?

I scratched my chin and had a think.

Since some of its earliest versions, Drupal has included a feature for multi-sites — running several sites from a single codebase installation, sharing the core system, contributed and custom modules and themes. Each multisite has its own database, its own settings and configuration, its own content, and so on. Ideally, it also means updates can be done once.

So, multisites could be an option. Many people find them to be a real workhorse for their context, and often they are right on the money.

Why use multisites

The Drupal.org documentation for multisites includes a simple rule-of-thumb for when to multisite:

As a general rule on whether to use multisite installs or not you can say:

- If the sites are similar in functionality (use same modules or use the same drupal distribution) do it.

- If the functionality is different don’t use multisite.

(DrupalCon Austin [June 2014] held a interesting debate on Drupal multi-sites, its pros and cons, gotchas and suggestions, which is available on YouTube.)

There’s several compelling reasons to use them.

First, having a single codebase to maintain is a huge plus. Forked codebases can soon become orphaned, and unloved codebases become fraught with problems too quickly.

Second, multisites often mean there is also a single hosting platform to maintain, which is also a major advantage.

That can often mean, thirdly, that multisite installations can make better use of resources, both the server resources and financial, personnel or other physical resources. For example, since multi-sites share the same core and modules, that code need only go into the opcode cache once, saving server resources.

Caveat: is the end of multisites support on the horizon?

It should be noted that a proposal has been made to deprecate support for multisites in Drupal, with a view to removing it in the future.

The basic argument for this is that it’s an ‘old skool’ way of thinking about handling multiple sites. Git and Composer create practices and codebase structures that point in other directions.

The modern approach to multi-site is: git — Same code, different sites. Under your control. And well-maintainable.

There are a number of positive reactions to that proposal, which are variations on a theme:

+1. Multisite is a historical oddity at this point and I’d never tell anyone to use it.

But there are many more negative reactions, which largely go along these sorts of lines:

-1. Multisite has been a workhorse for a ton of Drupal sites and is well established in our code.

In that light, Drupal’s multi-site feature is likely to stay around for a while.

Classic problems with Drupal multisites …

It’s not all a bed of roses, though. There are some classic sticking points when working with Drupal multisites.

First off, handling traffic. One site’s traffic spike can be another site’s nightmare when the hosting resources are all hogged by The New York Times tweeting a link to a page on a site of yours; one site’s ‘BEST DAY EVA!’ can be the worst of times for all the rest.

The load on your database server may also be an issue. Multisites often use a single database server, and heavy load or slow queries in one DB can impact the performance of others. This might even be caused in the normal running of your Drupal sites, such as when running cron.

Running updates often causes headaches. When you update code, you’re updating all your sites at once. That means the updates are deployed, well, instantly across all your sites, but if they need update processes to run, such as updating the database, that can throw unexpected problems or errors.

And the worst of the worst: a small piece of poorly written, inadequately reviewed or tested code mysteriously jumps itself onto production — that never happens, right? No one ever lets that happen, do they? *ahem* — and takes down all your sites at once! It’s just an urban myth, a story to scare the children with at night, right? Never happens.

… and how to mitigate them

There are of course a number of ways to foresee these things happening and be ready for them.

On the performance questions, with smaller demands you can just ride it out — sites on the same hosting platform are fairly tolerant of resources being shared around, and the spare capacity is there for times just like there.

For larger performance demands, handling the pressure is a challenge in any hosting set-up, dedicated hosting just as much as shared. With modern cloud infrastructure, the option of scaling up your infrastructure or spinning up a new cluster when you’re experiencing ongoing heavy demand is much easier than in the past, especially if you plan for it as a possibility.

The next set of mitigations are all about best practice.

For starters, test, test, test. Don’t let any code onto production that hasn’t been tested thoroughly.

Have a solid release process that you always follow. If possible, include dev, staging and quality assurance stages. This should give you lots of points to catch things before they’re released onto your production sites.

Automate all the things. There are lots of ways of automating things to ensure they run consistently and quickly too, from shell scripts up to continuous integration tools. Use them.

And finally, be intelligent. With code changes that need database updates, for example, design your code so that it can be deployed to handle an interval before the database is updated. Or, with important but more volatile updates, be smart about choosing the time of day and week that you deploy it. Don’t ever push something out at 5pm on a Friday afternoon if you want to stay friends with your colleagues, your customers and your family.

Well, yes, in short, kinda. You could run microsites using Drupal’s multi-site feature. Things would work fine, though of course you’d have all the problems described above and have to take the mitigating actions.

However, it wouldn’t solve all the needs described above without some smart thinking. Plus, I’d suggest that you would also have some other problems to solve.

First, multisites all use different databases (sharing databases and tables is possible with Drupal multisites, but really unadvisable!) so the need of a single place for managing all the site content wouldn’t really be satisfied. The way around that would involve using web services, posting and pulling content from one site to another.

Neither would we have a unified search. There are fairly straightforward ways around that, using a tool like Apache Solr. The sites would need to share an index, with each document in the index including a site field, and there’s a contrib module that does that already (although no Drupal 8 version yet).

Lastly, and maybe more pertinently, you would still have all the ‘Drupalisms’ to live with. First of those is the visual design layer, the public user’s interface for the sites, what gets called the ‘theme layer’ in Drupal lingo. Many designers really dislike Drupal’s theme layer, and would really prefer to work with the pure frontend tools they use in other contexts. Drupal 8 has made major strides forward with the theme layer so it’s not as tough for designers as it once was, it’s true, but many (most?) frontend specialists would still rather not work with it.

Some consider influential Drupal figures consider multisites as ‘not enterprise grade’ and opinions like that are worth considering if your situation is enterprise scale.

There are a few other ways of supporting microsites with Drupal that might be worth considering.

Domain Access

The Domain Access project was created to support just this kind of functionality. The project overview says as much:

The Domain Access project is a suite of modules that provide tools for running a group of affiliated sites from one Drupal installation and a single shared database. The module allows you to share users, content, and configurations across a group of sites.

This might work. However, there are many of the same problems with core multisites described above with this approach, with one additional one: everything in one database.

Our experience of using it, and this is echoed by others too, is that with a small number of very similar sites Domain Access can work well. With a larger number of fairly different sites, it’s a right pain and actually makes things quite difficult, requiring lots of complicated custom code.

Organic Groups

The Organic Groups suite of modules could be a solution for building microsites. The project allows users to create a ‘group’ within a Drupal site. The group can have its own users, admins, content, menus, even its own visual design. However, it would need every microsite to sit internally, within the main site, so does not solve the need to supporting external sites on their own domain. So, not really the perfect fit.

Best practice: with Git

I quoted above from @sun in the discussion on deprecating multisite support about the modern best practice:

The modern approach to multi-site is: git — Same code, different sites. Under your control. And well-maintainable.

This is certainly my standard recommendation and will give you many advantages: independence of sites for performance, design, etc; single codebase to maintain (though you’ll have a challenge developing and maintaining the variations you’ll want or need for each microsite); better control over updates; and so on.

You might even look writing an install profile to make a full distribution, though with Drupal 8 there is less of a need to do this. With Drupal 8, I’d advocate that you use Drupal Composer to build your site and just export your full site config into your repo (being careful to remove any sensitive settings from the repo with your .gitignore file).

Or you might also consider using Aegir to manage your multiple sites — use Drupal to deploy Drupal, if that’s not too much Inception.

So if multisites could work but would be a bit of a pain, the other Drupal approaches are even less appealing, and you’d rather not keep multiplying Drupal installations, how else could we do microsites with Drupal?

Well, there are two major moves in modern web development that might help here: RESTful web services, and decoupled CMS architectures (a.k.a. ‘headless’ CMS). My proposal for managing microsites in Drupal 8 depends on both these ideas:

  • Treat your Drupal site as a pure content management system (CMS) — a content hub that allows authors, editors and administrators to create, update and manage the content for which they’re responsible, but doesn’t have any meaningful frontend presentation layer to it.
  • Present the data of the content in the hub CMS via a RESTful API.
  • Implement a separate frontend for the visual presentation layer that communicates with the content hub CMS via the API.

There need be no limit to the number of frontends that use the CMS’s API (though practically you may limit access with firewalls, CORS or some other means) so you could power a primary public site, other sub-sites, native mobile apps or even another CMS or two, each potentially with their own visual design. The limit is your own imagination and situation.

RESTful web services and Drupal 8

A new addition to Drupal 8 is the RESTful Web Services API. REST resources can be exposed to allow other things to talk to/consume/feed a Drupal site. Many core entities have REST resources, but it is also fairly easy to build custom REST resources. (There a number of interesting web services contrib projects that are worth considering, such as the GraphQL project that presents a GraphQL schema, and the RELAXed Web Services project that extends the core REST resources.)

Design your own web services API

The freedom to build custom REST resources in Drupal 8 allows a lot of freedom in designing a RESTful API.

In a forthcoming blog post I’ll write in more about designing an API. For now, all I need to say is you need to actually design your API. Don’t simply use the out-of-the-box Drupal core REST resources — think about the RESTful API that would best serve the frontend you want to have.

My heartfelt recommendation is you do this, designing your API, using the skills of those who’re best at designing things — your designers. They understand best what your users want to do on your sites, will be able to describe what data they want for the frontend (content with/without markup, etc.) and help you design the API that is most appropriate to your needs.

There are some API design golden rules and best practices that you should consider. Also I’d recommend using an API design tool like Apiary.io or Swagger.io. They’re invaluable for many reasons, not least of which is the lovely documentation they generate and mock data servers they include that can help frontend devs get going quickly.

Decoupled frontend

With the content hub now presenting the managed content as RESTful data, we just need a standalone frontend system to present your website to your users: one for your primary site, and one for each of your microsites. Your frontend specialists can then work with the right tools for the task, then.

There are several advantages to consciously uncoupling the content management and the frontend.

Freedom: frontend specialists are free to the implement the user experience with native tools that are built for the job.

Performance: everything in this architecture can be streamlined. The CMS simply presents the content data. The frontend focuses on the display logic.

Experience: the website can respond to users in real time, communicating back and forth with the CMS to give real-time interactions in the browser.

Future proof: it becomes much easier to replace any part of the system as you require, such as redesigning the website without re-building the CMS.

So, how might we do this practically in Drupal 8? Here’s how I tackled it.

First, I thought about designing a quick prototype API that could be used to describe microsites and their content. I used Apiary.io to design it, and you can view the API at docs.campaignmicrosites.apiary.io.

Jan 22 2017
Jan 22

Letting users create content without having to register (or going through any other annoying process) is becoming an important customer engagement strategy.

When you allow anonymous users to create content on your website, you want this content to go through a moderation process before it becomes publicly available. To implement this in Drupal, the anonymous user has to be given permission to create content and the content type needs to be unpublished by default.

The problem with Drupal 7 and Drupal 8 is that as soon as the anonymous user saves new content, they loose access rights to it and get redirected to an 'Access denied' page which is not very user friendly.

In addition to the above, you may want the anonymous user to be able to edit or even delete their own content in case they find an error right after submitting it. Users often find typos or other kinds of mistakes right after content submission.

Gbyte created the Session Node Access module to tackle exactly these issues. The module allows administrators to grant certain user roles (not only anonymous users) specific permissions to content they created. These permissions last only as long as the browsing session lasts; after that, the regular permissions apply again. This way it is possible to allow guests or users of a certain role to keep access to their content, even if it is pending for approval.

Now Session Node Access has been ported to Drupal 8 - thank you to Gaël Gosset for doing the initial porting.

Right now this module works only with nodes, we may implement it for other entities in case of demand.

Feel free to download Session Node Access from its module page.

Session Node Access configuration screen:

Session Node Access configuration screen

Jan 19 2017
Jan 19

Today I released Entity browser 8.x-1.0-beta4. Release includes some nice features; specially Improved MultiStep selection display, which vastly improves editorial experience.

This is also the last release before the feature freeze, which will happen on February 3rd 2017. No new features will be accepted after that day until 8.x-1.0 is released. Feature requests that are not breaking backward compatibility will be accepted after that.

Huge thanks to all contributors. It has been an interesting and very rewarding ride!

Jan 09 2017
Jan 09

Drupal is an open source project and really depends on its community to move forward. It is all about getting to know the CMS, spreading the knowledge and contribute to projects.

I will give you some ways to get involved, even if you are not a developer there is a task for you!

A group of Drupal mentors at DrupalCon 2016 in Dublin

Drupal Mentors – DrupalCon Dublin 2016 by Michael Cannon is licenced under CC BY-SA 2.0

Participating in user support

Sharing your knowledge with others is very important to the community: it is a nice thing to do and you might also learn some things by doing so. Whatever your skill level, you can give back to the community with online support. There are many places where you can give support starting with the Support Forums. You can also go to Drupal Answers which is more active than the forums or subscribe to the Support Mailing list. If you prefer real-time chat, you can also join #drupal-support channel on IRC or the Slack channels.

Helping out on documentation

Community members can write, review and improve different sorts of documentation for the project: community documentation on drupal.org, programming API reference, help pages inside the core software, documentation embedded in contributed modules and themes etc.

Contributing is a good way to learn more about Drupal and share your knowledge with others. Beginners are particularly encouraged to participate as they are more likely to know where documentation is lacking.

If you are interested, check out the new contributor tasks for anyone and writers.

Translating Drupal interface in your own language

The default language for the administration interface is English but there are about 100 available languages for translations. There is always a need for translations as many of these translation sets are incomplete or can be improved for core and contributed modules.

All translations are now managed by the translation server. If you are willing to help, all you have to do is logging into drupal.org and join a language team. There is even a video to learn how the translation system works and a documentation.

You can also help to translate documentation into your language. Most language-specific communities have their own documentation so you should get in touch with them directly. To learn more, see the dedicated page.

Improving design and usability

The idea is to improve the usability especially in Drupal 8 regarding the administration interface. The focus is mainly on content creation and site building. The community has done many research to understand the problems that users run into and how the new improvements performs. The purpose is also to educate developers and engage designers in order to grow the UX-team. You can visit the Drupal 8 UX page for more details and join the usability group.

Writing a blog post about Drupal

Writing a blog post about Drupal is a good way to share your knowledge and expertise. There are many subjects to explore, technical or not: talking about a former project you developed or writing a tutorial, telling about the state of a version or sharing about an event you attended… And if you are lucky enough your post can be published on the Weekly Drop, the official Drupal newsletter!

Don't forget to reference your blog post on Planet Drupal, this platform is an aggregated list of feeds from around the web which shares relevant Drupal-related knowledge and information.

You can also find our Drupal related blog posts on the Liip blog.

Testing core and modules

Testing Drupal projects is necessary to make the platform stable and there are many things to test! If you have a technical background, you can help to review patches or to write unit tests.

For non-technical people, you can provide some feedback about usability of the administration interface that will help to improve the user experience. Follow the process to give a proper feedback.

Contributing to development

There are many ways to contribute code in core and “contrib” projects such as modules or themes.

You can first help to improve existing projects by submitted patches. This would be the natural thing to do when you work with a module and you notice a bug or a missing feature: search in the corresponding issue queue if the problem have been noticed before. If not, post a message explaining the issue and add a snippet of code if you found a potential fix. Then you can create a patch and submit it into the issue queue.

You can also contribute to new projects by creating your very own module or theme or create a sandbox for more experimental projects.

Attending events

The Drupal association organizes many events all around the world to promote the CMS and gather the community.

One of the biggest events are the Drupalcons. A Drupalcon gathers thousands of people and lasts about one week including 3 full days of conferences. These conferences cover many topics: site building, user experience, security, content authoring etc. You can also join sprints to contribute to Drupal projects and social events to meet the members of the community. Check out our report about DrupalCon Barcelona 2015!

“Drupal Dev Days” conferences occur once a year and gather developers to discuss and present topics technically relevant to the community. You can join sprints, intensive coding sessions and technical conferences.

You can also join DrupalCamps to meet your local community. These events last one or two days and focus on sharing knowledge amongst the community. You can attend conferences and sprints.

There are also many Drupal meetups which are free events happening in many cities in the world. Presentations and discussions finish around nice drinks and appetizers.

Sponsoring events

The community holds conventions and meetups in many countries and being a sponsor will not only help Drupal development but it will also enable you to be noticeable within the community. There are different levels of sponsorings that will offer from mentions on social media to advertising online and at the exhibition space of the event. All you have to do is getting in touch with the event organizers. By the way, Liip will sponsor the Drupal Mountain Camp in Davos this year!

Offering a donation

You can give donations to the Drupal association through the website in order to support drupal.org infrastructure and maintenance, worldwide events such as Drupalcons. The donations are either in Euros or Dollars.

You can also become a member of the Drupal Association for the same purpose, as an individual member or an organization member. The minimal fees are 15 Euros. Find more information about membership on drupal.org.

Conclusion

Drupal projects are constantly improving thanks to passionate volunteers who work on many subjects: development, documentation, marketing, events organization, supports… There is for sure a task that will suit you and it only takes small time commitment to make changes.

So join the great Drupal community and start getting involved!

Jan 09 2017
Jan 09

One of the ones that seems fairly stable and has a good set of features without being overly complex is the Geolocation Field module. We've used it on a site recently with great success, and in this blog post we will cover the fundamentals of how to use this module.

Add a Geolocation Field to your Content

After enabling the module, the first step you need to do is add a geolocation field to the entity you want to associate a location with. Locations are stored as latitude and longitude value pairs on the entity. This can be any entity type, but for the purposes of this we chose to create a Location content type and add a geolocation field to that.

The default configuration for new geolocation fields is to provide latitude and longitude text boxes on the node edit form. This may be suitable for some sites, but we needed the ability for the user to enter in an address which is then geocoded, and to be able to adjust the pin location if the calculated co-ordinates were incorrect (as is often the case with Irish addresses).

Luckily, the geolocation field module provides this functionality out of the box. On the "manage form display" page in the entity configuration, you can choose the type of input widget the editors will use. The "Geolocation Google Geocoder" is the option you need. You may want to configure your Google Maps API key at admin/config/services/geolocation if using this option however.

Geolocation field - manage form display settings

Similarly, the module also provides a number of options to choose from on the "manage display" page. In our case we chose to display the location on a Google map, rather than outputting the latitude and longitude values.

Geolocation field - manage display settings

After selecting the "Geolocation Google Map" display output, you can then customise its display. For example, you can choose between a Road Map view and Satellite Map view, set the map zoom level, disable/enable various map controls and dimensions.

You can now create your Location content and associate a latitude and longitude with each. Below is a screenshot of what the edit form can look like. Here we have manually entered in an address and the Google geocoder has calculated the latitude and longitude from that. Note, it's not possible to drag and drop the pin to a different location (which caught me out a few times), instead clicking anywhere else on the map will move the marker there.

Geolocation Google Geocoder widget

Create a View

After adding all of our mapped locations, we needed the ability to display them all on one Google Map view. To do this we created a new view of our content, and in the view format settings, we choose "Geolocation - Common Map". In order for this view format to work, you will need to add the geolocation field latitude and longitude co-ordinates to the view and a title for each location (which will appear in the popup). You can also optionally add an image field (make sure to choose the file uri output here) to the view which will be used as a marker for each location. This allows you to customise the marker per node.

Geolocation views format settings

Similar to the manage display settings on the node, you can also configure the map controls, zoom level, and so on. One other setting worthy of mention is the "JSON styles" setting. This allows you to embed a JSON encoded styles array to customise the look and feel of the rendered map. This is incredibly powerful and allows you to have a custom Google Map style that matches the design and colour palette of your site. Styled Google maps are easy to define using services such as Snazzy Maps.

The Results

Not everything we needed was quite there so we contributed a number of patches back to the module to make this happen, all of which have now been added to the module, yay!

Using the Geolocation Field module, we were able to map all our Location nodes and produce a map as can be see at the top of this article. If you want to see it in action, visit Glanbia Nutritionals.

Other Modules

At the time of launch, the only other modules that were available were Styled Google Map and Simple Google Maps. However, neither of these supported all the features we needed. Since then, a beta version of the Leaflet module has also been released. Have you used any of these or other mapping modules in Drupal 8? We'd love to hear what you thought of them. Why not let us know by leaving a comment below?

Jan 06 2017
Jan 06

Are you excited about the recent improvements in Drupal core Media? Would you like to join us at one of the next sprints and help us reach our goals? Now you can!

Drupal Mountain camp

Drupal Mountain Camp 2017 will happen between 16th and 19th February in the lovely Davos. Drupal, code community, snow, fondue, outdoor activities and much more. Definitely something that should not be missed!

And the best part? There will be Media sprint going on throughout the event. Eager to join? Simply add yourself to the sprint attendance list and show up. We promise you the best sprint ever!

Jan 02 2017
Jan 02

In December media team met in Berlin and sprinted on Drupal core media improvements for a week.

Today's @drupalmedia sprinters. Awesome group that is making #Drupal the best media management CMS! pic.twitter.com/G2LqD603pH

— Janez Urevc (@slashrsm) December 15, 2016

I demonstrated the results of the sprint in a short video.

[embedded content]

Demo is based on the sandbox project that includes the following patches:

Dec 06 2016
Dec 06

The TWG coding standards committee is announcing three coding standards changes for final discussion. These appear to have reached a point close enough to consensus for final completion. The process for proposing and ratifying changes is documented on the coding standards project page. A change to this process is being proposed to streamline the interaction between the coding standards body, Drupal Core, and the Coder project, please provide any feedback on that issue.

Announced for final discussion:

Official coding standards updates now ratified:

Formerly announced issues that need an issue summary update

These issues have a lot of support but need an update to formalize the proposal so that they can be ratified and applied.

These proposals will be re-evaluated during the next coding standards meeting currently scheduled for December 20th. At that point the discussion may be extended, or if clear consensus has been reached one or more policies may be dismissed or ratified and moved to the next step in the process.

Nov 21 2016
Nov 21

UX Ireland conference took place at the Trinity Biomedical Sciences Institute, a very modern facility beside the classic grounds of Trinity College. The conference featured a great line-up of keynoters and speakers such as Jon Kolko (author of acclaimed books including “Well-Designed” or “Exposing the Magic of Design”) and Brenda Laurel.

As usual with a conference of this nature, Annertech attended in force, with about 50% of our frontend/design team attending one or both days. I got a lot of takeaways from the talks and workshops: here's a synopsis of them:

Creativity (by involving the whole team in the design process)

The first day started with a great session. Kolko’s “Be the lion tamer: Manage the chaos of creativity” was a joy to watch.

He described how getting the whole team involved in the design process increases creativity. Self-critique is common among designers during the iteration process. Constructively applying that concept to group critique will not only increase creativity but also will make us designers feel better and the rest of the team feel good too. This, in turn, helps to focus and increase trust.

For this to work the designer needs to do certain things: acknowledging feelings, managing ambiguity, letting them run amok, and setting a vision.

His point was interesting on the importance of making the thing first (doesn’t matter if it is good initially) as it will simply start the process and help the team to articulate constraints.

Another takeaway was Jon’s emphasis on rules and how they destroy creativity (unlike the constraints). I really enjoyed the talk, very uplifting.

Design for Scale and Impact

My main takeaway from “Service design at scale: designing for impact” by Oli Shaw was the importance of starting small to lead into the final product. It was very interesting to see how starting with atomic design (and our curiosity to understand the problem) will lead into features (flow, uses cases), the final product and so on.

When (re)designing an interface this is very clear. He gave the example of redesigning a button and how such a seemingly small change can affect loads of different things such as Customer experience, Employees experience, Technology systems, Business processes or even 3rd party/partner business.

As designers we want to prove the value of design, we want to create impact, in one word, we want “change”, because, let’s face it, for us a design “is everything”. He explained the importance of measuring this impact, for us designers to prove our point. Looking at impact has an extra benefit as he said  “looking at how to measure the impact (of a solution) can actually help in focusing on the real problem”.

Understand + Find Patterns + Don't Hi-Fi Everything

I found Denise Burton’s “Design language systems: beware the hobgoblins” one of the highlights of the first day. Starting again at atomic design, I liked her definition of Design Language as the DNA of your brand (what I normally call identity) and her recommendation when creating a Design Language System is to understand that you shouldn’t do it all. Start with the top level nav (for example) and apply to other parts of the design.

Efficiencies and consistency, which are what we want for a good design language system can be achieved by understanding the user, finding patterns and not hi-fing everything. Keeping in mind of course that banality may be an issue if we just “lego” things together, there is a risk of stopping thinking.

Intent for the Good

Day two started with Brenda Laurel and her “Staying grounded in a sea of new 'realities'" key talk which was a history lesson on Virtual Reality that went beyond the present day and into the future. I liked her idea of doing Desig /Research to prove (users) point to the client. It was a very interesting talk.

Yes We Can

Next, I decided to explore the workshops rather than the theoretical sessions and I went to see Matthew Lee running a session about “Research for startups... yes, you can!” which started with an overview of typical research methods (that is, the first half diamond of the first diamond of the The Double Diamond Design Process - not sure I could squeeze the word 'diamond' in there any more!). I really enjoyed how he adapted these to small budgets on what he called research for startups by making it cheap and fast.

He described the excuses clients usually have such us “we don’t have enough money” (Only cost is time), “we don’t have enough time” (one day to one week), “we can follow our gut” (You are not the user) or “my idea is the best” (Humility).

Then Matthew continued with some suggestions on how a guerrilla approach could apply to the startup environment, with ethnographic research/interviews becoming “Field Studies”, stakeholder interviews “Executive Interview”, Focus Groups turning into “Round Table discussions” and Usability Testing becoming “Street Testing”.

A Couple of Workshops to Finish it off

My hands-on experience continued with “ExperienceOps: continuous design in agile teams”, led by Simon Bostock, who highlighted that designers have only a limited amount of control of various elements of the process ranging from an almost 100% control to almost no control. I guess we have to accept that we have no control over certain aspects.

It was followed by another workshop, “Introduction to structured content” by Bonny Colville-Hyde. The first thing I realised as soon as the session started was how much her division of content into taxonomy, content types, fields, paragraphs, etc matches the Drupal world. It was a good session, maybe designers that are not involved in site planning, migration or site building tasks would have found it more revealing.

And that was it.

Overall I think all of the annertechies enjoyed it, I certainly did anyway. As with most conferences, I couldn’t go to all I wanted to. There were really interesting talks by fellow drupalists like Daniel Alb’s “Content is king: the DNA of designing a citizen-centred local authority website for dlrcoco.ie” or Conor Cahill’s “Researching the experiences of people cycling”.

These drupal related talks can possibly be seen again at http://drupalcampcork.com/. If you haven’t registered yet, please do, it is a free event bringing together Drupal developers, themers, end users and those interested in learning more about Drupal for two days of talks, sessions and collaborative discussions. Taking place at Cork Institute of Technology (CIT), see you there.

Nov 18 2016
Nov 18

Man, it's gonna be great!

But then a little voice pipes up: 'It's too complicated! We're trying to do too much! Can't we simplify this?' Nobody wants to listen to the nay-sayer, and the project proceeds apace. In due course, the complicated and extensive nature of the project begins to take its toll. Budgets run dry. Completion dates make a faint whizzing noise as they fly by. And yet the project isn't finished. Cracks appear, bugs sneak through and by the end, you just can't wait until it's over. The love of your life has turned into a horror-show that is slowly leeching the joy from existence.

The little voice, long forgotten, can no longer even be heard.

Let's do things differently! On time, on budget, in scope and on point. Wouldn't that be lovely? One important strategy on any project is the championing of simplicity. For any given item, be it design, feature or content, is to ask: "Can this be simplified? Is it currently over-complicated?"

Simple does not mean Stupid

A simple site need not be one that is devoid of functionality. Nor is it one with an overly simplistic data model or information architecture. It is one which has had the fat trimmed from it; it only includes the elements that are actually needed. Often it is in the identification of the actual needs and the elimination of flights of fancy that the greatest challenge and real rewards lie.

Simple is not Ugly

A simple design will capture the elegance of form, forgoing the unnecessary in the pursuit of perfection. In this era of responsive design, simplicity shines. Single column, full width designs are far more readily made responsive than more complex designs. Accessibility also benefits from simplicity. Naturally, the fewer tricks, hacks and workarounds used to bring a design to light, the more likely it is to be accessible by default. Also, with less thinking needed for the actual design implementation, it leaves more room to build the site in such a way as to benefit the most people.

Drupal is rather opinionated in the way it expects you to build your website's theme. That can be a frustrating experience, if you have not learned how it works. However, imperfect as it is, the theme system is very, very powerful and can actually help a themer to realise that design dream. The simplicity champion says: work with the system, don't fight it. Figure out the Drupal way and make it work for your design. Simplicity lends itself to theme harmony.

Lastly, minimalism as a design school is a beautiful thing, albeit sometimes difficult to achieve. Simplicity strips away the noise from a design until you are left with just the signal.

Simple will not be Useless

Simplicity includes the functionality that people need to get things done. It eliminates the things that people never use. You might look at eye tracking or click tracking data to figure out what people use and iterate your design to improve it over time. Real data from real users is invaluable for this process.

A simplicity champion will also reign in the wilder ideas of functionality: for example, maybe you don't need full, continuous, synchronous communication between your CRM and your website. Maybe one-way communication (i.e. web-to-lead style communication) would actually be sufficient. Or maybe periodic data imports from the site meets all the requirements, in which case the site only needs to be able to export data.

A simplicity champion will not be blinded by a request that comes tightly coupled with a suggested solution, but will reach beyond to figure out the real core requirements and design solutions to meet those.


Simple will be Beautifully Functional

On a massive scale, Google is simple. In effect, it's a one page website with only an input field and then some results returned. But at heart it is beautifully functional. You type in your request, it gives you back suggestions. We love this approach and try to make it work on all projects that we design and build. Take, for example, the www.housing.gov.ie website of the Department of the Housing, Planning, Community and Local Government. A limited colour palette, simple fonts, a simple layout... and a great-looking site that works across devices and transforms what was once a highly complex maze of documents into a very easy to use, information rich asset for the department and all its customers.

Overly Complex is always Expensive & Difficult to Maintain

Complex sites are not only more difficult and costly to build, but this trend continues throughout the lifecycle of the project. With many moving parts, changes need to be planned with greater care and tested far more extensively in order to avoid unintended consequences. Even supposedly simple changes can become large enterprises. Sometimes complexity is unavoidable and that is fine: all these hurdles can be overcome, but it is worth considering the long term effect of your design & requirements choices at the beginning of your project. Your site is not just for Christmas.

Websites Are Like Whiskey

Minimalism is the art of stripping back everything unneeded until you are just left with the core of necessity. In this way, a minimalist site can be thought of like a good whiskey. On the surface, it's simple to look at and made of only a handful of ingredients. But its minimalist appearance belies the depth of complexity present in the process through which it is distilled into being. Skilled craftspeople with decades of knowledge put their love of their craft to use to build you the ultimate product.

Just like excellent whiskey, excellent websites are the product of a process honed over thousands of hours of experience, resulting in beautiful, simple sites that are a joy to use.


Would you like to benefit from our crafting process? Contact us to chat about how we can bring the beauty of simplicity to your project.

Nov 10 2016
Nov 10

Clients sign off on designs. You build a website for them based on these designs. It looks quite like the designs, but not exactly like them. It's not your fault. It's not the client's fault. But wouldn't it be nice if you could build what the client signed off?

Why are the websites we build not exactly like what the client signs off and why is it nobody’s fault? Here’s three (good) reasons:

  1. Websites in the real world use real content – not all titles have 5 words, images have different dimensions, etc.
  2. Designs are in static (image) format so can’t be tested on real devices and screen widths such as phones, tablets, desktops, and smart TVs. So, even though you've got “mobile” designs, they were designed for a specific mobile screen size, but mobile screen sizes can be anything from 3.5 inches to 11 inches.
  3. The designs were completed in my most hated design tool – Photoshop, which renders design elements (especially fonts) different to how browsers do. For example, a thin font in Photoshop might be much fatter in Firefox. Why not just see what it’s really going to look like.

Photoshop is for editing photos (the clue is in the name) not designing websites. If your designer comes to you in 2016+ with designs created in Photoshop, you’ve hired the wrong designer.

Surely there’s an interface designer that is better than Photoshop? There is: SketchApp - built especially for designing user interfaces, but it still falls waaaay short when you want to give your clients designs that they can touch and feel and smell and see exactly what they are going to get. SketchApp is great for rapid prototyping and early stage mockups. It’s great for quickly designing ‘patterns’ or ‘elements’ but not for full designs – again, you can’t expect clients to get a true feeling for how their website works rather than looks by giving them static images of it.

Right, Mark, is there a solution to this conundrum? Yes. It’s called “Design in the Browser” - use the tool that the design will be accessed in to create the design. Give your clients a coded-up prototype. Get your design ideas into code, send your client a link to the website. Let them test it on their phone, on their tablets, on their teenagers’ PlayStations, on their desktops. Let the CEO scream when it doesn’t work on his Windows XP with IE8 as the browser he refuses to let go of. And then explain to him that he wouldn’t have known that if we had sent him a Photoshop document and if he wants it to work on his dinosaur of a machine, it’s going to cost him 30% more. Let him make his decision based on real world interactions.

Do you have a magic workflow that can slay all the dragons?

Here’s my 10 Step Plan for Losing Weight (or at least reducing technical (frontend) debt):

  1. Discovery: see what the client wants.
  2. Research: find out what the client actually needs.
  3. Rapid prototyping 1: use pen and paper, post-it notes, anything to come up with quick ideas about what a design might encapsulate, what a workflow might look like, how an interaction might function.
  4. Rapid prototyping 2: use SketchApp to create quick outlines of what elements of the design might look like (from herein called ‘components’). For example, a search box (input and submit button with bounding border), a news teaser (teaser image, title, post date, snippet, read more link), etc.
  5. Create each design component as an actual coded object. Write the HTML for the structure, the CSS for the layout and styles, and the JavaScript for any interactivity.
  6. Use these design components to create fully-fledged mockups of sample pages of the new website – homepage, listing page, full article – complete with real sample content and images from the client's website.
  7. Send a link to the prototype to the client. This is their designs delivered. Ask for feedback.
  8. Make changes based on client feedback.
  9. Get sign off for the designs from the client.
  10. Use the HTML, CSS, JS from the prototype in the real world implementation of the designs. In short, create a website exactly like what the client was expecting. Not an approximation of it, the thing itself – so the product they get is the product they sign off.

10 Reasons Why Your Client Needs to Insist You Design in the Browser

  1. We use real world content to test that the designs work with the same type of content our clients create.
  2. We can test these designs on the devices they are ultimately going to be consumed on – phones, tablets, desktops, etc.
  3. QA for the frontend begins very early: as the client is signing off the designs, they are signing off the frontend of the website.
  4. QA becomes an on-going item throughout the website build, not something tacked on at the end.
  5. If the client wants an updated design – for example, she would like all text on buttons to be uppercase, we can simply edit the .button class in our CSS and not have to go through 40 PSDs to change each instance of it, saving you time and effort and the client money.
  6. Because we have an interactive prototype of the website, we can use this for regression testing. So, if you add a new feature to the website in Phase 2, you can easily check that the new feature doesn’t break any of the present features.
  7. The client always has the most up-to-date copy of the designs. All they need to do is click on the link you have sent them to see what has changed.
  8. You are providing your client with a styleguide. They can mark this against their print brand guidelines to make sure both are in sync.
  9. When a new feature is requested your client will already have a list of pre-defined design components to choose from. This means you may not need to invent new ones – again, a money saver for the client.
  10. There are no surprises or hidden charges. The client gets what they client is paying for.

I know, I know. This sounds difficult. It sounds like a new way of working. It’s going to take time and effort to implement this workflow. You build websites with Drupal, does this mean you will have to maintain two versions of the frontend?

I come with solutions, not problems. Our tool of choice for this approach is an “Atomic Design” system called PatternLab. This lets us do everything listed above. Using Version 2 of this allows us to integrate the templates that we create for PatternLab directly into our Drupal workflow. What does this mean? Well, without blowing your mind too much, it means that the design that the client signs off is the actual code that is going to be used in the Drupal theme. We do not copy/paste the CSS and JS from one place to another, we do not have anything magic to try to keep two systems in sync. We provide the client with a URL such as styleguide.example.com and they can refer to that as the canonical design as a static HTML prototype while example.com will be the Drupal implementation of it – pulling the templates, CSS, and JS into its system.

Thanks to the great work from the folks behind PatternLab and with some very generous help from the great team at Phase2 who first created a Drupal version of it, we are able to design in the browser, get sign-off from our clients, and then focus on developing the CMS with the frontend work already complete.

Ooooh. That sounds nice doesn’t it? Tune in for part 2 of this series where I’ll detail how to use PatternLab with Drupal. Or, even better, come to Drupal Camp Cork on November 25 and 26 where I’ll be giving a presentation about all of this.

Nov 07 2016
Nov 07

1) Check if a user has a permission

@ceaucari wanted to check if a user had permission to do something, and if so certain code would execute. Like everything, it's simple when you know the answer.

{% if user.hasPermission('administer nodes') %}
  ... do something
{% endif %}

Thanks to @hj for providing it.

Check if a user has a permission in Drupal Twig

2) How to print comments separate from fields in a node template

Print comment and comment form fields separately

This one was fun, for no other reason than I was up late having a bottle of beer on a Friday evening when my friend Preston So needed help printing comment fields in nodes (mid-afternoon his time). The specific request was to get the variable for a custom comment type that he wanted to print in a node template. After some late night (by European time zones) investigation, and kinting the hell out of {{ content ... }} I came up with a variable to show the custom comments and another to show the custom comment form.

  {% set custom_comments = content.field_custom_comments.0.comments %}
  {% set custom_comments_form = content.field_custom_comments.0.comment_form %}
  {{ custom_comments }}
  {{ custom_comments_form }}
Print comments and form in Drupal Twig

3) Add body class based on field value

Sometimes you have a field on a content type and you want to take the value of that field and add it as a body class in your HTML. We often do this on our websites so users can choose a background colour for the header on a node-by-node basis, or choose how wide a structured content item should be, for example. This is exactly what @danny_englander needed to do:

Add body class based on field value

Our solution for this was to use THEME_preprocess_html, using code such as this:

function weather_preprocess_html(&$variables) {
  // Get the value of the "Site Section" field and add it as a class on <body>
  // This allows us to have specific colours used within each site section
  // _as long as_ each node is tagged with a site section.
  $node = \Drupal::routeMatch()->getParameter('node');
  if ($node instanceof \Drupal\node\NodeInterface) {
    if ($node->field_site_section) {
      $section_style = $node->field_site_section->value;
      $variables['attributes']['class'][] = $section_style;
    }
  }
}
Print value of node field in body class in Drupal 8

4) Override a twig template from a module using another module

Sometimes modules provide templates with them, such as paragraph.html.twig in the paragraphs module. Sometimes you want to override that template with a custom module (rather than your theme) so the override is available to all themes being used (if you were using themekey for example, or Seven for site editing and your custom theme for the frontend).

This is what Jim Birch needed to do. And after asking the question he found a solution himself and posted it to the Slack. Here's the code:

/**
 * Implements hook_theme_registry_alter().
 */
function bootstrap_paragraphs_theme_registry_alter(&$theme_registry) {
  $module_path = drupal_get_path('module', 'bootstrap_paragraphs');

  // Use the templates in the boostrap_paragraphs module.
  $theme_registry['paragraph__default'] = $theme_registry['paragraph'];
  $theme_registry['paragraph__default']['path'] = $module_path . '/templates/paragraph';
  $theme_registry['paragraph__default']['template'] = 'paragraph--default';
  $theme_registry['paragraph__accordion'] = $theme_registry['paragraph__default'];
  $theme_registry['paragraph__accordion']['template'] = 'paragraph--accordion';
  $theme_registry['paragraph__carousel'] = $theme_registry['paragraph__default'];
  $theme_registry['paragraph__carousel']['template'] = 'paragraph--carousel';
  $theme_registry['paragraph__modal'] = $theme_registry['paragraph__default'];
  $theme_registry['paragraph__modal']['template'] = 'paragraph--modal';
  $theme_registry['field__paragraph__field_column_content'] = $theme_registry['field'];
  $theme_registry['field__paragraph__field_column_content']['path'] = $module_path . '/templates/field';
  $theme_registry['field__paragraph__field_column_content']['template'] = 'field--paragraph--field-column-content';
}
Override a twig template from a module using another module

ADDED BONUS EXTRA FEATURE: In true Drupal fashion, a co-developer of his found an even better solution. Here's that code:

/**
 * Implements hook_theme().
 */
function bootstrap_paragraphs_theme($existing, $type, $theme, $path) {
  return [
    'paragraph__default' => [
      'base hook' => 'paragraph',
    ],
    'paragraph__accordion' => [
      'base hook' => 'paragraph',
    ],
    'paragraph__carousel' => [
      'base hook' => 'paragraph',
    ],
    'paragraph__modal' => [
      'base hook' => 'paragraph',
    ],
    'field__paragraph__field_column_content' => [
      'base hook' => 'paragraph',
    ],
  ];
}
Override a twig template from a module using another module

5) Save render array as variable

This blew my mind. I always thought of saving strings or fields as variables, but as @lauriii pointed out you can save render arrays as variables as well - makes sense when you think about it!

{% set variable_name %}
  {% for item in national_office_address %}
    {{ item.address_line1 }}
    {{ item.postal_code }}
    {{ item.country_code }}
  {% endfor %}
{% endset %}
Save render array as variable

6) Override all CSS from a library except one file

Say you have a library of CSS which contains loads of CSS you don't need and just a little bit you do - maybe you want to override everything in classy except one file, well you can. Of course you can. This is what @mark wanted to do. And @alexbea was to the rescue:

parent/parent-lib: false #removes the whole parent library

parent/parent-lib:
  css:
    css-file.css #allows you to bring back in just the file you want.
Override all CSS from a library except one file

That's it for Volume 2. Naturally there was loads of more learning and teaching and sharing and helping going on. Join us here.

Oct 18 2016
Oct 18

In the fall of 2016, the Rainforest Alliance and Last Call Media launched an exciting redesign of www.rainforest-alliance.org, built on Drupal 8, employing seasoned agile software development methodologies.  Our productive partnership with the Rainforest Alliance resulted in a technically groundbreaking site that allowed users unprecedented access to the riches of their content after just four months of development.  The tool is now primed to drive the Rainforest Alliance’s critical end-of-year development activities. 

Our relationship with the Rainforest Alliance began in August of 2013 when LCM undertook a massive Drupal 6 to Drupal 7 upgrade.  We enjoy a strong relationship with the Rainforest Alliance team, working together to continuously deliver strategic value in their digital properties, and were proud to be chosen for a full site redesign and upgrade.

The lobby at RA Headquarters in NYC.The lobby at RA Headquarters in NYC.

Over the years, RA has cultivated a repository of structured content to support their mission.  While the content is primarily displayed as long form text, there is a wide variety of metadata and assets associated with each piece of content.  One of the primary goals of the new site was to enable discovery of new content on the site through automatic selection of related content driven by the metadata of the content the user was viewing.  Additionally, RA had a future requirement for advanced permissioning and publishing workflows to enable stakeholders outside of the web team to play a role in the content lifecycle.  

After some initial consideration, the Rainforest Alliance and Last Call Media decided to build a responsive Drupal 8 website, which included both building out new content types and migrating existing content from their then-current Drupal 7 site. It needed to launch on a 4 month timeline, by the end of September 2016.

Why Drupal 8

Drupal 8 was selected for this project based on several factors.  First, its focus on structured data fit well with Rainforest Alliance’s need for portable and searchable content.  Second, the deep integrations with Apache Solr allowed for a nuanced content relation engine.  Solr was also used to power the various search interfaces.  Third, Drupal has historically had powerful workflow tools for managing content.  While these tools weren’t quite ready for Drupal 8 when we built it, we knew they would be simple to integrate when they were ready.  In short, Drupal was a perfect fit for the immediate needs, and Drupal 8 met the organization’s longer term goals.

Why Agile/Scrum

To meet the 4 month timeline, the project followed a highly collaborative, agile project management style (Scrum) such that RA could provide wireframes, design and UX direction, technical specifications, user testing and QA for all content types, and LCM would carry out all Drupal Development, including theming, and project management, providing guidance based on our expertise and best practices. 

Furthermore not all requirements were known at the outset and many things were known to potentially need to go a different direction depending on some of the outcomes along the way. Agile methodologies avoid the “big reveal” better than other styles of project management. Issues requiring a change in direction are raised in near realtime, resulting in saved time, in the long run, by better avoiding going in the wrong directions.

Backlog Development, Grooming, and Refinement

The above photo is from our Project Sizing and Sprint Forecasting 2 day workshop, on-site at RA Headquarters in NYC.
The above photo is from our Project Sizing and Sprint Forecasting 2 day workshop, on-site at RA Headquarters in NYC.

Leading up to Sprint 1, for a period of 4 weeks, I worked as a Product Owner (PO) and Agile Coach, with the Rainforest Alliance (RA) webteam in a Business Owner (BO) role, and Rob Bayliss, as a Subject Matter Expert (SME) from Last Call Media (LCM), to build and groom the initial backlog. During this time, we coached RA on Agile/Scrum and being effective in the Business Owner role. 

Together, meeting twice per week, we groomed and refined the project backlog to the point where SME guesstimated sizing seemed reasonable for forecasting purposes. We did this sizing together too with each epic guesstimated for size by Rob, on note cards. We went through each of these note cards together with RA in planning poker style, where everyone guessed at how big they thought the epic was and then, revealing Rob’s guesstimate, we compared the group’s sizing differences. It didn’t take everyone too long to pick up on Rob’s style of sizing, but many misconceptions and misunderstandings were revealed when someone’s sizing guess was wildly off from someone else’s. This exercise fine tuned our alignment on the backlog items and allowed for more accurate forecast sizing. 

Sprint Forecasting

Based on the sizing exercise, we set to strategically sorting our epic note cards into sprint piles. The strategy was to group cards into earlier sprints piles based not only on the importance of the epic but also on how helpful it would be to have that epic in place for later sprints. A grouping was considered full when it reached resource capacity, which was determined by adding the sizing from each note card up to an agreed upon threshold. It turned out we were able to forecast 7 sprints worth of backlog items, with approximately 2 more sprints worth of “nice-to-haves” as well as some epic cards determined to be no longer needed.

The result was each sprint’s goal being forecasted to better enable following sprint goals and concurrent releases for user testing, feedback, and iteration. Additionally, as the project budget and timeline only allowed for 6 sprints, our forecast safely assumed for a backlog of certain items being left undone at the final public release after the 6th sprint. This concept of moving items to a backlog for after sprint 6 would become a critical one later in the project as complexities were uncovered, new directions emerged, and priorities changed.

6 Sprint Forecast

The above spreadsheet shows a forecast of 6 Sprints worth of guesstimated epics, The concept of a forecast was an important one. Just like with the weather forecast, the further out it goes, the less it is to be expected to be accurate. The sprint forecast further became a living document for maintaining an evolving project vision across all of its iterations.

Agile Planning

With each sprint, we made three planning ceremonies available to the project. Pre-sprint grooming was a group exercise for the development team to go over the upcoming sprint’s wish list for the purposes of optimizing the official Sprint Planning meeting. Sprint Planning was held on the first day of a sprint and followed traditional Scrum guidelines. In Re-Forecasting, the team gave feedback from the trenches on the original forecast of SME guesstimates. This enabled the opportunity to adjust the forecast to be more realistic, evolving the project vision as it was adapted to these reports. Additionally, in later sprints, we began doing mid-sprint releases of completed work to be previewed. We did this to enable better planning and re-prioritization from the RA team.

The image above shows a typical daily standup meeting from the project.
The image above shows a typical daily standup meeting from the project.

For openness, I kept a Product Owner journal shared with the RA team. In it I tracked the daily standups, their sticking points and resolutions, as well as each day’s User Stories that were completed and the work-unit points that I awarded. This last piece of daily info was used to keep a realtime project build up chart.

Agile doesn’t tell us not to have a plan, but to always be planning.

A plan requires an awareness of things to consider for planning. Agility is the concept that we need to be ready to adapt our plans over time as we gain additional awareness. To that end, all of Scrum, from its Values to its Ceremonies, is designed to increase awareness, enabling better adaptation to change. The following build up chart is a Scrum artifact from this project that was used for the purpose of increasing awareness and better planning.

RA 6 Sprint Project Build Up Chart

The Build Up Chart additionally serves well for telling this project’s story across its six sprints. For example, one can tell things about the project just from this chart. The sharp upticks toward the end of each sprint are indicative of a new build, where substantially complex functionality is being attempted each sprint resulting in shippable increments on most stories not being realized until the very end or their sprint. One can also tell that this project was re-forecasted at least three times, resulting in the adjustments to the estimated project size over time.

Sprints 1 and 2

Sprints 1 and 2 stayed on track nicely, getting most of the critical core functionality in place. Some key Drupal 8 modules implemented during these sprints included Page Manager, Layout Plugin, Panels, as well as Search API/Search API Solr, Media Entity (and related modules), Entity Embed, Entity Browser, Inline Entity form, and Features. Core project functionalities are described by Jeff Landfried, lead project developer, below in the context of each of these Drupal modules.

Page Manager/Layout Plugin/Panels:
Page manager is a great tool for making it easy to create specialized landing pages, and when combined with Layout Plugin and Panels it provides the ability to use different layouts when viewing different node types (or other entity/bundle combination). Specialized landing pages were built as specialized page manager pages, many with their own layouts. All of the different full node displays were handled by Page Manager, using different variants for each node type.

Search API/Search API Solr:
Most content types have a “related content” section at the bottom of the page. Tagging content is one great way to handle something like this, but for our requirements we needed to have logic that was more robust than only showing other content with the same taxonomy terms. We went with Solr for this, specifically for the “more like this” (MLT) functionality that it provides. Search API Solr provided the interface for managing our servers and indexes, then with a custom block we were able to leverage MLT with our own boost criteria to help control how the related content lists were generated.

Media Entity (and related modules):
Drupal core provides file fields, which allow us to upload files to different entities, but this project had a requirement that we must be able to reuse the uploaded files, and have the ability to add additional related information for each file or image that is uploaded. Things like caption, image source, etc. On top of that, we needed to be able to display these files in different ways - in some places an image may display the caption as a tool tip, while in others it should display below the image. The Media suite of modules is perfect for this type of thing. We were able to use different modules from within the media ecosystem to handle images, embedded videos, and PDF documents, and add appropriate fields to each media entity bundle, and using Drupal core’s view mode system we were able to set up multiple displays for each media type.

Entity Embed / Entity Browser/Inline Entity form:
It hasn’t always been easy to empower content teams to easily add images and other entities to WYSIWYG fields, especially when those items need to be themed in a special way. Entity Embed allowed us to add new CKEditor buttons to the WYSIWYG that provide a dialog where the user can choose an entity that they want to appear in content, the view mode that they want it to display with, and then position it on either the left, center, or right side. One great thing about this is that the module uses a text format filter, so different text formats can display the embedded entities, while the others don’t. Entity Embed is primarily used for embedding images, but we also used it to give content editors the ability to embed blocks in their wysiwyg content as well.

Inline Entity Form allowed us to create entity reference fields, but gave content editors the ability to create the referenced entities right from the node edit form, something that can be a big time saver for content editors.

Entity Browser ties in with both Entity Embed and IEF by adding a button that opens a dialog displaying a view that allows users to select the entity that they want to use from a list, rather than having to remember media names, taxonomy names, or node titles and enter them into an autocomplete field.

These modules combined help make for a great editorial experience.

Features:
Drupal 8’s CMI initiative solved a lot of issues around managing configuration. That being said, we’ve found that bulk exporting/importing an entire site’s configuration isn’t a great workflow for our team that involves multiple environments and developers, each potentially having a few of their own special configuration options that need to be be set. Manually seeking out and overriding those configuration options in settings.php isn’t something that we decided was sustainable, and has its own drawbacks. The features module in D8 allows us to package and ship the configuration that we need to be consistent, while allowing us to leave out what may be different across environments (such as development only modules, css/js aggregation and page caching).

Sprint 3

Even though things were on track nicely across the first two sprints,  we could see work in progress and technical debt catching up with us during sprint 2. The first two sprints laid a tremendous amount of ground work, but also left as much technical debt. This resulted in a pivotal moment in the build chart, shown up close below, with progress dipping below target.

Sprint 3 shorfall

Notes from Sprint 3’s Planning Meeting:

This was forecasted as a really full sprint, but the team decided to only accept the stories above to make sure that there would be time to completely wrap up. The team is trying to be mindful of the amount of WIP tasks that already exist, and avoid creating more of those loose ends.

The Homepage was completed in Sprint 3. The above image is of the final homepage.The Homepage was completed in Sprint 3. The above image is of the final homepage.

Fewer Stories were committed to, meaning fewer work-unit points earned, resulting in a below target buildup, but the silver lining was that the results were beyond excellent with far less technical debt left over to be carried into future sprints.


Sprint 4

Sprint 4 Build up

For Sprint 4, we reconfigured project priorities with RA and reassessed forecasted story sizing. This reconfigured sprint forecasting resulted in batches of stories different than originally forecasted. It also resulted in the Estimated project size increasing. By the end of Sprint 4, we worked with RA to move tasks out of the project. This resulted in the Estimated Project size decreasing, putting the project on target with the build team’s velocity.

The team’s continued focus on careful commitment paid off big in this delivery in terms of comprehensive task completion, as well as delivering on a stretch goal, which nudged them just above target, leaving them in a great place for the next sprint. In addition to further iterating on the groundwork from the previous sprints, Sprint 4, by way of Drupal’s Panelizer,  brought with it Landing Pages and Content Hubs.

Landing Pages and Content Hubs

Panelizer:
When viewing taxonomy terms for several vocabularies we needed the ability to have a consistent layout, but to place different Custom Block entities on each term, which is essentially what Panelizer’s made for. The module doesn’t have full taxonomy term support yet, but the community is working to get it added, and the patches provided in this issue were far enough along that we were able to make it work without issue.

Editor experience

We were technically crushing it, but Sprint 3 was the beginning of a turning point that comes in every project worth discussing. We didn’t know it at the time but Sprint 3 was the transition point from Certainty to Doubt in this project’s Emotional Cycle.

emotional lifecycle

The idea is that first there is a honeymoon period of Optimism and Certainty, but inevitably things don’t always work out as expected and Doubt creeps in, pulling the team into a Pessimistic state. Good teams identify and adapt to this shift, moving from Doubt to Hope quickly with minimal emotional damage. With every project, I’ve tended to look to preempt the slip from Certainty to Doubt, somehow looking to skip to Hope or even somehow to Satisfaction. Reality, however, can often be too elusive until it smacks you right in the face. I’ve come to accept that traveling the path through Doubt, into the pessimism, is simply the sign that a project is attempting to do at least as much as it should. Doubt comes from the realization that not everything imaginable is realistic to expect. 

How do you know if you are doing as much as you could if you never run out of time to do more?

Pessimism is a part of the process of grieving the loss of things hoped for that now seem unrealistic. The uptick toward Hope comes from acceptance and adapting expectations to reality. 

Sprints 5 and 6

The following overlaying of the two graphs, Build Up and Emotional Cycle, show their relation visually.
 

overlaying of the two graphs, Build Up and Emotional Cycle

Reality will always win, but are you really on its team?

The ascension to Hope, on this project, can be attributed to an understanding of and a dedication to the five Scrum Values (Openness, Focus, Commitment, Respect, and Courage), followed by a more rapid iteration strategy, with frequent mini-releases during Sprint 6. Since most core functionality was solidly in place by this time, it became possible to squash larger numbers of site-wide bugs by relating them to the current sprint’s stories. This resulted in those stories shipping as more highly polished than was possible in previous sprints, while at the same time further iterating on stories from past efforts. Also, to increase awareness, and thereby project agility, during the final sprint, all Accepted Backlog Items were released and reviewed, as they were completed. The result was a highly collaborative finishing of the final shippable increment. At the close of Sprint 6, there were zero critical and only 3 moderate issues. The final Sprint/Project review had only 3 support questions.

screenshots

The project used its remaining time until launch day running extensive QA with the LCM Continuous Delivery team making adjustments, finally launching as arguably the most impressive Drupal 8 site launched within a year of the initial release of the latest major version of the Open Source CMS, and most importantly in time for Rainforest Alliance’s major end-of-year donation campaign. The site delivers on its promise to showcase the Rainforest Alliance’s exciting and informative messages and beautiful imagery, and stands as testimony for the efficacy of the agile approach.

Last Call Media is a full-service creative agency developing solutions for partners online and off through innovative strategy, branding, print, and digital design. Last Call Media enjoys work with purpose– building engaging solutions that assist and support organizations working to improve their communities.

*This post was written with the assistance of Rob Bayliss, Jeff Landfried, and Alan Wolf.

Oct 06 2016
Oct 06

I think I was pretty well prepared and knew what to expect. A couple of blogs from fellow Annertechies had helped to plan it, especially Mark's Get the Most out of DrupalCon Dublin.

Having become a father for the second time only two weeks before the event and spending the previous fortnight on paternity leave, I really enjoyed sharing a full week with my otherwise distributed work colleagues and, shall I say, friends. We even had a headquarters: booth 901, which was only a few steps away from the Drupal Ireland one.

Monday

Most of Monday was spent doing the pre-note rehearsal. I must say I really enjoyed being part of it. I had a pretty small part: I was one of the "O'Drupals", the trad band that would be playing a couple of tunes. As the conference took place in Ireland and I knew how to play the Irish drum called the bodhrán, I thought it would be a good way to break the ice.

I also found myself collecting stickers of previous DrupalCons. I have no clue why I did that, I suppose I wanted to go back in time and somehow compensate for my absence in previous events. I guess I wanted my laptop completely covered with these stickers like all the committed druapalists you see at the conference, they seem to have been everywhere! On second thoughts I decided to just keep the stickers, without trying to showcase something that didn't actually happen, so my laptop currently has only 2 stickers: DrupalCon Dublin and one for Drupal Ireland (that I happen to have designed myself).

Tuesday

Tuesday started early. I was there at 6 in the morning for a pre-note rehearsal. The last minute rehearsal went well as did the real performance. I think the O'Drupals played as good as we could have, a trad band consisting of 3 guitars (one of them electric), two bodhráns and an occasional flute here and whistle there didn't feel very traditional to me from the purist point of view, but hey, we did very very well, I think everybody enjoyed the music and we were even sharing the stage with the one and only Dries Buytaert, not a bad place to be when you are at the beginning of the second day of your first DrupalCon.

The highlight of the day for me was probably the Keynote by Dries, right after the prenote, I really enjoyed it. Really looking forward to start using the new D8 Block Placement or Menu settings tray. I think both are really going to affect site builders' usability. Also enjoyed his meaningful moments and how Drupal and its community actually improves people's lives. My lowlight would be "Streamlined Front-end Development with Pattern Lab and Twig", a session that I was really looking forward and that left me feeling like maybe I had too many expectations on this one.

I didn't make it to the welcome party that we, Drupal Ireland, had organised to be on a boat just outside the Convention Centre but I heard the following morning it was a great success and a lot of people went to have a pint of the black stuff with the local Drupal Community.

Wednesday

A mistake (I think) I made was not to attend the BoFs and to go to the sessions instead. "21 things I learned with Twig & Drupal" by MortenDK was the most enjoyable so far. I really enjoyed how he explained how designers and developers are thinking very different and how the themers kind of fall in the middle. By the end of his presentation I felt that I should have really be looking more often into the DrupalTwig Slack Channel and I already decided that I have to go to Frontend United in Athens next May.

It is amazing how much I took in of almost everything he said even though his non-stop presentation style reminded me of a Ramones concert where  songs are played at twice the original speed and one linked to each other with a "one two three four". I have already watched this talk on YouTube again. This is actually one of the good things I found at this DrupalCon. Sometimes there is an overlap of two sessions I wanted to attend: no problem, watch it later on YouTube. Sometimes I want to refresh something in particular as during the DrupalCon there is a lot to take in and energy and concentration levels reduce significantly as the day goes by: again YouTube saves the day.

As happened on Tuesday, I missed the evening side of the Conference. The Realex Web Awards 2016 took place that evening and ireland.ie, a collaborative project between Annertech, Big O Media and the Department of Arts, Heritage and the Gaeltacht, and others which happens to be the first site I worked on in Annertech around nine months ago, was nominated for "Best Arts and Culture" website and "Most Beautiful Website in Ireland" and you know what? It won them both!

And then it was announced that ireland.ie had won one more award, the overall icing on the cake "Best Website in Ireland" award. I felt so proud of my fellow annertechies and rest of the collaborators when I heard the news, it had been a really enjoyable project to work on and it was great to see it rewarded.

And finally, when things couldn't get better, there was one more trophy to collect by Alan, Anthony, Mark, Karen and Tom, my fellow colleagues representing us at the event. They went on to collect the "Web Agency of the Year" award. I truly believe days like these don't come very often, it is such an honour for me to be part of such an amazing team. 

Thursday

On Thursday I really enjoyed "Creating Layouts and Landing Pages for Drupal 8" by Suzanne Dergacheva and how she explores different theming approaches for landing pages such as using Paragraphs to define the call to actions or create a new content type for the call to actions and reference it with the Entity Reference Field and use the Inline Entity Form.

I also learnt something about DrupalCons the hard way: If you really want to go to something, don't go there just one minute before it starts, don't stop to talk to everybody you know and meet on the way to the second floor. "Drupal 8 hidden power: Entity Reference as a component-based site builder", a session I had been highly anticipating as one not to be missed already had a full room when I arrived, and I was forced to go somewhere else. I know, I can watch it in YouTube afterward, but being there in person would have been A1.

As with the rest of the night events, I couldn't make the Trivia Night but I really wish I had been to this historic occasion. Trivia Night was taking place in the country where it was born: in Ireland. And it was happening in a really astounding venue called the Round Room in the Mansion House. And this is something you can't really watch on YouTube. I will have to wait a full long year and get to it at DrupalCon Vienna.

Overall

In general it was a truly enjoyable and memorable experience, much more than I had anticipated. I know I didn't go to all the sessions I wanted to and that I missed the BoFs and most of the social side of the DrupalCon, but meeting great people at the stands, learning lots at the sessions, celebrating the awards and making new friends was more than enough to make it an extremely beneficial week.

I am already looking forward to the next one, it might be even better, at the next DrupalCon in September 2017.

Oct 05 2016
Oct 05

This year's DrupalCon was not different because of the happy coincidence that had Annertech scoop a raft of awards at the Realex Web Awards on the Wednesday (including "Web Agency of the Year"), but rather because of engagement and involvement.

Before the 'Con even occurred, the local team was preparing content, answering questions and, in my case, writing the 24 Hour Guide to Dublin. Seeing my work laid out beautifully in print in the DrupalCon programme was an unexpectedly great pleasure!

As a local, I had the opportunity to MC a keynote Q&A session. That was enormous fun, made all the more fun by a fantastic speaker, Emer Coleman. Coming off stage was a rush, lengthened by the deluge of interaction on Twitter as I was mentioned and our conversation bounced around the DrupalCon Twittersphere.

There was also the personal interest in both other keynotes as Annertechies took to the stage to chat to their speakers - Mark Conroy speaking to Dries at the "DriesNote" and Alan Burke chatting with Eduardo Garcia during the "Community Keynote". Suddenly it was not merely about entertainment any more - I cared. It had become relevant to me. I met Emer on Tuesday, in advance of the keynote, which meant that I was excited about it for most of a day of Drupalcon before even taking to the stage!

The DrupalCon prenote is always good fun - and I was several years in before I even discovered it! This year, taking part in it was very rewarding - from getting to know Jam, Cam, Adam and the crew a bit better, rocking out with the O'Drupals band, endless 12-bar blues in between rehearsals and finally being part of a very entertaining half hour show, I really felt that I was now part of the community. And I definitely made new friends who I'll be looking out for next time!

It was my first time to give a session at DrupalCon, speaking on the topic of "Happiness is ... Remote Working". I had spoken at camps and at Dev Days in Dublin, so public speaking was nothing new. But at DrupalCon, surrounded by my peers, talking to people at the top of their game, in a room full of people far cleverer than I am, it was a brand new experience. Andrew put it best: "Level unlocked!"

Although it was my first DrupalCon speaking slot, I had submitted talks for several years before and it made me think about what I had been doing wrong. Firstly, one must be able to prove that one can speak, so camps, Dev Days, Front End, other conferences and speaking opportunities are all good ways to beef up your speaker CV. Evidently I'd managed to convince the program team that I had cobbled together enough experience. Secondly, I read the track descriptions, and submitted sessions that attempted to deliver the things they were asking for. This is something I had neglected in years past: I would decide on a talk, write it up, and only then read the track descriptions (or even just the name!). Obviously, delivering what the program team wants is the most important hurdle. Here's the video of my talk:

Sep 29 2016
Sep 29

My fingers are trembling typing this. I can't believe it. This morning everyone in Annertech land is thinking "did that really just happen?" It appears it did, we are the web agency of the year!

Last night, to top off the other three awards we won - best arts and culture website, most beautiful website in Ireland, and best website (all for Ireland.ie) - we then went on to win Best Web Agency 2016.

Speaking to accept the award, Alan Burke thanked the great team we have in Annertech and our fantastic clients who trust us with such important work.

Afterwards, Stella Power had the following to say, "it's just amazing. I always knew we had a great team. We work so well together, we get on so well, we're not co-workers or colleagues, we're friends. And when working with your friends it's much easier to do great work. This award vindicates everything we've been doing to make Annertech the agency it is".

Please join me in congratulating Annertech on this fantastic news. Annertech: Web Agency of the Year 2016.

Pages

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