Chromatic: Atomic Drupal Development: Building Pieces Before Pages

Planet Drupal - Mon, 2015/02/16 - 6:12pm

Many designers are praising the benefits of Atomic Design. Rather than designing pages, Atomic Design focuses on designing systems of individual, reusable components. Designers aren’t – or at least shouldn’t be – the only ones thinking this way. From content strategy to QA, the entire team must be on the same atomic page.

Development is one area of a project that stands to benefit the most from this change in thought. Organizing a codebase by individual components keeps developers out of each other’s hair, reducing the code and effort overlap that often occurs when building by page or section. It also makes the codebase much easier to understand and maintain. Developers will know where to find code and how to fix, alter, or extend it, regardless of the original author. After enforcing coding standards, only git’s history will know who wrote what. This all saves time and money.

Because there are many ways to do anything in Drupal, building every component with the same approach is crucial. In the Drupal world, this approach is known as “the Drupal way”.

Building a component the Drupal way

Individual blocks, panel panes, or other UI elements would be examples of a component in Drupal. They are placed into regions within layouts to build pages. Other pages may use the same component in the same or different regions. A given component may vary across pages, but the design and intended functionality are similar. A simple search form is a good example, but they can be much more complex.

Design deliverables often arrive as complete pages. If the designers haven’t already, identify the components that each page consists of. Break up the page’s layout into regions and those regions into components. Determine which components live on more than one page and if they vary between them. It also helps to identify different components that share design or functionality with others. It’s important to recognize early if they will be sharing code.

Before writing a line of code, determine where in the codebase the component will live. Organize custom modules by content types or sections and add relevant components to the same modules. A module exported with Features should be treated no differently than one created by hand; don’t be afraid to add custom code to them (please do). The end goal is to have all back-end and (most) front-end code for a given component living in the same module.

Warning: This article is about to move fast and cover more ground than it should. It will move from back-end to front-end. There are many wonderful resources about each topic covered below, so they will be linked to rather than recreated. This will instead provide a high level overview of how they fit together and will highlight the most important pieces.

Component containers and placement

The most common container for a custom component is a block, created with a series of hooks. Contributed modules like Context can help place them on the page. More complex projects may choose to build pages with the Panels module. For pages built with Panels, custom panel page plugins are a component’s container of choice.

The decision between blocks and Context, Panels, or another approach is important to make early in the project. It is also important to stick with the same approach for every component. This article will focus less on this decision and more on how to construct the markup within the container of choice.

View modes and entity_view()

If the component displays information from a node or another type of entity, render it with a view mode. View modes can render different information from the same entity in different ways. Among other benefits, this helps display content in similar ways among different components.

Create a view mode with hook_entity_info_alter() or with the Entity view modes contributed module. This module also provide template suggestions for each entity type in each view mode. Render an individual piece of information with a view mode inside of a component using entity_view() (you’ll need the Entity API module) or node_view(). Alter the entity’s information as needed using a preprocess function and adjust the markup in a template. Those pieces will be discussed later.

If a component lists more than one entity or node, build a view with the Views contributed module. It is best if the view renders content with view modes using the Format options. Create Views components with the Block (or Content pane for Panels) display(s). Views also provides template suggestions to further customize the markup of the component. The exported view should live in the same module as the code that customizes it. EntityFieldQuery might be worth considering as an alternative to using Views.

hook_theme() and render arrays

If the component does not display information from an entity, such as a UI element, build it with hook_theme(). Drupal core and contributed modules use hook_theme() to build elements like links and item lists. This allows other modules to override and alter the information used to render the element. Default theme functions and templates can also be overridden to alter their markup.

Choose a name for the element that will identify it throughout the codebase. Outline what information the element will need to build the desired output. Use these decisions to define it using hook_theme(). Again, keep this hook in the same custom module as the rest of the code for the component.

To render a hook_theme() implementation, construct a render array. This array should contain the name of the implementation to render and any data it needs as input. Build and return this array to render the element as markup. The theme() function is a common alternative to render arrays, but it has been deprecated in Drupal 8. There are advantages to using render arrays instead, as explained in Render Arrays in Drupal 7.

Custom templates

Drupal renders all markup through templates and theme functions. Use templates to construct markup instead of theme functions. Doing so makes it easier for front-end developers to build and alter the markup they need.

Templates place variables provided by entity_view(), render arrays, and preprocess functions into the markup. They should live in the “templates” directory of the same module as the rest of the component’s code. The name of a template will come from theme hook suggestions. Underscores get replaced with dashes. Tell hook_theme() about the template for each element it defines.

There should be no logic in the template and they should not have to dig deep into Drupal’s objects or arrays. They should only use an if statement to determine if a variable has a value before printing its markup and value. They can also use a foreach to loop through an array of data. Further manipulation or function calls should happen in a preprocess function.

Preprocess functions

Use preprocess functions to extract and manipulate data such as field values and prepare them for the template. They are the middleman between the input and the output.

Preprocess functions follow the naming convention of hook_theme() implementations. Common base themes often use Drupal core’s preprocess functions, such as hook_preprocess_node(), in their template.php file. Keeping all preprocess functions in one file will create a mess in no time. Instead, place preprocess functions in the modules that define the parts their working with. This might be the custom feature that contains the exported content type.

jQuery/JavaScript files

Create a separate JavaScript file for each component that needs custom JavaScript. Place it in a “js” directory within the module and name the file after the component. Be sure to use the Drupal behavior system and name the behavior after the module and component.

Add the JavaScript file to each page the component will appear on. If the component appears on most pages, it might be best to just add it to every page. This will cause less HTTP requests with JavaScript aggregation enabled. The best way to do so is with hook_page_build(). JavaScript files can also be attached to entities rendered through view modes within hook_entity_view(). The best way to add JavaScript to a hook_theme() implementation is by attaching it to the render array.

Sass components

When using a CSS preprocessor like Sass, there isn’t much of a penalty to dividing the CSS into many files. Create a new Sass partial for each component and give the file the same name as the component. Keep them in a “components” directory within the Sass folder structure. Unlike all other code mentioned in this article, it is often best to keep all CSS for these components within the theme. Only keep CSS that supports the core behavior of the component in the module. Consider what styles should persist if it were a contributed module used with other themes.

In the component’s template, base the class names off of the component’s name as well. This makes it easy to find the component’s Sass after inspecting the element in the source. Follow the popular BEM / SMACSS / OOCSS methodologies from there.

Coming up for air

As mentioned, there are often endless ways to complete the same task in Drupal. This makes learning best practices difficult and “the Drupal way” will vary in the minds of different experts. The best way to grasp what works best is to start building something with other people and learn from mistakes. The approach outlined in this article aligns with common practice, but mileage will vary per project.

Regardless of approach, focusing on components before pages will only become more important. Drupal content is already displayed on everything from watches to car dashboards. The web is not made of pages anymore. Designers have begun to embrace this and Drupal developers should too; everyone will benefit!


Makak Media: Taking BackDrop For A Test Drive

Planet Drupal - Mon, 2015/02/16 - 5:41pm

So the first BackDrop release is out there in the wild ready for a quick test drive! We're excited to see where this fork of Drupal 7 leads as we believe it to be a good complementary system to Drupal with a long term future.

First off we checked under the hood to get things configured and found the settings.php file in the root folder, which makes for easier access. Also all those txt files have been removed including the CHANGELOG.txt file, which we remove by default, as it supplies useful info to any hacker out there!

Naturally the installation process is very similar to Drupal but with a few less settings giving it a simpler feel.

Upon installation you're presented with a responsive admin menu with a slightly different structure to the standard Drupal menu. Responsiveness out of the box is great and the new menu again has a simpler look.

read more


DrupalDare: G-WAN as a static Drupal file server

Planet Drupal - Mon, 2015/02/16 - 5:26pm
So now that we have concluded that it's easy to setup distribution of files on a separate subdomain, what about using a completely other web server (or in this case an application server)? Will it blend?

Acquia: Development based on Drupal's Fundamental Particles - Brad Czerniak

Planet Drupal - Mon, 2015/02/16 - 1:34pm
Language Undefined

Presenter Brad Czerniak caught my eye with a blog post entitled "10 things I learned using Drupal at a hackathon," based on his experiences taking part in the #hackDPL (Detroit Public Library) competitive hackathon. In our podcast interview we talk about that – before moving on to Brad's session about the Drupal development best practices he and his team use at Commercial Progression in Michigan.


Annertech: Enlightening - The Dark Art of Solr Search with Drupal

Planet Drupal - Mon, 2015/02/16 - 12:41pm
Enlightening - The Dark Art of Solr Search with Drupal Why this blog post?

Often when I add a search function to a Drupal website using Apache Solr, I'm amazed at how complex some people think this is. Many developers/site builders are of the belief that this is some kind of very-hard-to-master black art. They could not be more wrong.

So what I want to contribute back to the Drupal community is an understanding of how Solr works, why/how it differs from Drupal Core Search module, and the benefits Solr has over core search.

Categories: The Drupal 8 plugin system - part 2

Planet Drupal - Mon, 2015/02/16 - 11:38am

We saw in part 1 how plugins help us in writing reusable functionality in Drupal 8. There are a lot of concepts which plugins share in common with services, like:

  1. limited scope. Do one thing and do it right.
  2. PHP classes which are swappable.

Which begs the question, how exactly are plugins different from services?
If your interface expects implementations to yield the same behaviour, then go for services. Otherwise, you should write it as a plugin. This needs some explaining.
For instance, if you are creating an interface to store data in a persistent system, like MySQL or MongoDB, then it would be implemented as a service. The save() function in your interface interface will be implemented differently for both the services, but the behaviour will be the same, i.e., it takes data as input parameters, stores them in the respective data store and returns a success message.

On the other hand, if you are creating an image effect, it needs to be a plugin. (It already is. Check image effects as plugins). The core concept of image plugins is to take in an image, apply an effect on it and return the modified image. Different image effects yield different behaviours. An image scaling effect might not produce the same behaviour as that of an image rotating effect. Hence, each of these effects need to be implemented as a plugin. If any module wants to create a new image effect, it needs to write a new plugin by extending the ImageEffectBase class.

Plugins used in core

Let's take a look at the major plugin types provided by Drupal 8 core. An example plugin of each plugin types will be the subjects of future blog posts.

  1. Blocks
    Drupal 8 finally got blocks right. Custom blocks can be created from the BlockBase class.

  2. Field Types, Field Widgets and Field Formatters
    Check part 1 for how this is done in Drupal 8.

  3. Actions
    Drupal 8 allows module developers to perform custom actions by implementing the ActionBase class. Blocking a user, unpublishing a comment, making a node sticky etc. are examples of actions.

  4. Image Effects
    Image effects are plugins which manipulate an image. You can create new image effects by extending ImageEffectBase. Examples of core image effects are CropImageEffect and ScaleImageEffect.

  5. Input filters
    User submitted input is passed through a series of filters before it is persisted in the database or output in HTML. These filters are implemented as plugins by implementing the FilterBase class.

  6. Entity Types
    In Drupal parlance, entities are objects that persist content or configuration in the database. Each entity is an instance of an entity type. New entity types can be defined using the annotation discovery mechanism.

  7. Views related plugins
    A large collection of different plugin types are employed by views during the querying, building and rendering stages.

Plugin Discovery

Plugin discovery is the process by which Drupal finds plugins written in your module. Drupal 8 has the following plugin discovery mechanisms:

  1. Annotation based. Plugin classes are annotated and have a directory structure which follows the PSR-4 notation.

  2. Hooks. Plugin modules need to implement a hook to tell the manager about their plugins.

  3. YAML files. Plugins are listed in YAML files. Drupal Core uses this method for discovering local tasks and local actions.

  4. Static. Plugin classes are registered within the plugin manager class itself. This is useful if other modules should not create new plugins of this type.

Annotation based discovery is the most popular plugin discovery method in use. We will briefly look at how we create a new plugin type using this method in the next part.


DrupalDare: CDN, Cookieless Requests and Subdomains

Planet Drupal - Mon, 2015/02/16 - 10:52am
In this text I will go in to the topic of using a separate domain for serving your static files to avoid the client sending unnecessary cookies in the headers and why it may be or may not be a solution to speed up your website.

clemens-tolboom commented on issue clemens-tolboom/drupal-8-rest-angularjs#8

On github - Mon, 2015/02/16 - 9:29am
Feb 16, 2015 clemens-tolboom commented on issue clemens-tolboom/drupal-8-rest-angularjs#8

We now have the login block in place but the backend is not available. This require either basic auth or above mentioned drupal issue.

clemens-tolboom closed issue clemens-tolboom/drupal-8-rest-angularjs#3

On github - Mon, 2015/02/16 - 9:27am
Feb 16, 2015 clemens-tolboom closed issue clemens-tolboom/drupal-8-rest-angularjs#3 Solve the problem json versus hal+json

clemens-tolboom commented on issue clemens-tolboom/drupal-8-rest-angularjs#14

On github - Mon, 2015/02/16 - 9:27am
Feb 16, 2015 clemens-tolboom commented on issue clemens-tolboom/drupal-8-rest-angularjs#14

This is a won't fix. This project is not intended as a general solution. It tries to mimic garland front end usage only.

clemens-tolboom commented on issue clemens-tolboom/drupal-8-rest-angularjs#15

On github - Mon, 2015/02/16 - 9:26am
Feb 16, 2015 clemens-tolboom commented on issue clemens-tolboom/drupal-8-rest-angularjs#15

This is implemented now through MESSAGES and $scope.messages

clemens-tolboom commented on issue clemens-tolboom/drupal-8-rest-angularjs#13

On github - Mon, 2015/02/16 - 9:25am
Feb 16, 2015 clemens-tolboom commented on issue clemens-tolboom/drupal-8-rest-angularjs#13

Hmmm ... does gitflow add tags?

Drupal core announcements: Drupal core security release window on Wednesday, February 18

Planet Drupal - Mon, 2015/02/16 - 4:37am
Start:  2015-02-18 (All day) America/New_York Online meeting (eg. IRC meeting) Organizers:  David_Rothstein

The monthly security release window for Drupal 6 and Drupal 7 core will take place on Wednesday, February 18.

This does not mean that a Drupal core security release will necessarily take place on that date for either the Drupal 6 or Drupal 7 branches, only that you should prepare to look out for one (and be ready to update your Drupal sites in the event that the Drupal security team decides to make a release).

There will be no bug fix release on this date; the next window for a Drupal core bug fix release is Wednesday, March 4.

For more information on Drupal core release windows, see the documentation on release timing and security releases, and the discussion that led to this policy being implemented.


Drupalpress, Drupal in the Health Sciences Library at UVA: two new drupal distros – one for voting, one for 3d printing e-commerce

Planet Drupal - Sun, 2015/02/15 - 9:29pm

Two new drupal distributions available on github

** is the distribution behind - it’s an attempt to run a political campaign through a virtual proxy…

** – this is the code behind it’s an e-commerce solution for 3d printing… A lot of this is implemented in rules and other well-standardized code thanks to Joe Pontani - a talented developer here in Virginia.  Joe integrated several third party tools, and set up the UVa payment gateway through Nelnet.

Both sites are getting updates over the next few months – the Charlottesville Council website also has a drupalgap implementation on it – absolutely awesome toolset…

18F API compliance is another feature I’m pretty stoked about… I got most of that done with the oauth2 server, views datasource, services and a couple of great notification features done with rules + views  i’ll get that feature out asap = it’s really convenient – matching a profile2 taxonomy field onto content taxonomy fields for notifications with new content.

any questions – please drop a line in the comments below