May 29 2019
May 29

Have a few menus on your site & looking for a quick way to add or change the menu classes and attributes? Use the theme_menu_tree__[menu_name] override in your theme’s template.php file to change Drupal 7 menu list class and attributes:

// template.php

/**
 * Override theme_menu_tree().
 */
function theme_menu_tree($variables) {
  return '<ul class="menu">' . $variables['tree'] . '</ul>';
}

/**
 * Override theme_menu_tree__[menu_name]().
 */
function theme_menu_tree__main_menu($variables) {
  return '<ul class="menu">' . $variables['tree'] . '</ul>';
}

The code above will allow you to easily change all menu ul classes and other attributes or just the main menu’s ul classes and attributes.

Change Drupal 7 Menu List Class

Looking for a module to change Drupal 7 menu list class & attributes?

Unfortunately, I haven’t been able to find one that handles the individual menu ul instances cleanly, but the Menu Attributes module is a start. It gives users the ability to set the following attributes for each menu item — this does not help with setting the ul classes & attributes:

  • id
  • name
  • target
  • rel
  • class
  • style
  • accesskey

What about Drupal 8? Check this out article out by Tamas Hajas: Drupal 8 Twig: add custom CSS classes to menus (based on menu name).

Related Articles

Like this:

Like Loading...

Apr 30 2019
Apr 30

Drupal is to release its latest version, Drupal 8.7, on the 1st May 2019. Review the entire Drupal product roadmap here.

Drupal 8.7 is a significant update for Marketers, Copywriters, Site Managers, and Creatives. It brings a new Media Library and Layout Builder, Drupal’s first drag-and-drop content manager, recently revealed at DrupalCon Seattle 2019

[embedded content]

 DrupalCon Seattle 2019

This update sees Drupal 8 retain its relevance in an emerging world of instant site builders, like Squarespace and Wix. Where Drupal has always stood out for its back-end capabilities and flexibility with API integrations, the new Layout Builder empowers Content Managers and Marketers. The user-friendly system allows Content Editors to maintain control over their content, throughout its journey to the end user. It also provides enhanced reactivity to the customer experience, as Site Managers can make edits without the assistance of a developer.

Of course, this isn’t just a standard drag-and-drop editor. Drupal 8.7 comes with a whole host of features you won’t find on low-end editors. These include instant multi-page management and the flexibility of powerful editorial workflows.


What is the Drupal Layout Builder?

The Drupal Layout Builder is a drag-and-drop content management tool. It allows non-technical individuals to design layouts in a structured way that adheres to the standard across the site. The new Layout Builder encourages users to take control, introducing blocks which help them to achieve designs and functionalities previously only editable in the developer's domain.

Key features include:

  • Modular template builder
  • Drag-and-drop paragraph editor
  • Permissions workflows
  • World-Class Accessibility 

[embedded content]

 Drupal 8.7 Layout Builder Recording

 

Simple, Reactive Page Management

Using the layout builder, Site Managers and Marketers can create new pages from templates. To build on these templates, users can insert new blocks from the pop-out sidebar that do not exist elsewhere on the site. Once the Site Manager has added a block, they can preview it instantly. At this point, if the editor isn’t happy, they can swap out blocks or replace images, text, buttons and more!

Users have recognised that it can be challenging to move huge, pre-built blocks and paragraphs in full preview. Using the preview toggle, users can now switch out of the full ‘Content Preview’ mode to a slicker block view. This simplified interface makes reordering blocks quick and easy. This differs from alternative drag-and-drop editors as the collapsed block editor sits within the same page. Therefore, editors can drag blocks across columns, as well as up and down.


Accessibility

The Drupal project has a long-standing commitment to accessibility and has been a leader in accessibility for many years. In 2018 Drupal Founder, Dries Buytaert, reaffirmed this commitment by stating that the forthcoming Layout Builder must be fully accessible.

The full 8.7 system is navigable by keyboard, in order to conform to Web Content Accessibility Guidelines, as recommended by the World Wide Web Consortium. This means that the drag-and-drop editor was designed with consideration for Site Managers, Marketers and Developers amongst us with specific accessibility requirements. Ultimately, the latest Drupal update will make agency life and in-house marketing that much more accessible to everyone.

[embedded content]

 Navigating Layout Builder by Keyboard

Workflows

The Layout Builder supports essential activities such as adding, saving and previewing content, or publishing data. The latest update also supports more complex features, such as content staging or approval workflows, using granular controls and notifications for the governance of each layout. This is a great win for marketing teams, as it de-centralises the content management process. Site managers can submit site updates safely, with version controls and final permission escalation.

For more complex updates, Drupal 8.7 supports workflows which push pages through multiple teams. For example, an initial submission which is then passed via testing teams, SEO managers, translation and localisation experts for international audiences, and final senior sign off.


Templates

The Layout Builder also includes a templating feature, useful for sites with large quantities of content. For enterprise sites, Content Managers can edit collections of pages all at once using the Layout Template Editor. Not only can they be edited in unison, they can also be rearranged while retaining their unique content. The ability to re-structure multiple pages at once saves a huge amount of time when one block needs to be changed across multiple locations.

Layout-Builder-template-modeThe Layout Builder in template editing mode

The Drupal Layout Builder was built entirely on Open Source contributions made by 123 contributors and 68 worldwide organisations.

Drupal 8.7 Layout Builder Contributors

The 123 contributors (DrupalCon Seattle 2019: Driesnote)

 

Media Library

Drupal 8.7 included the release of a Media Library, to make asset management faster for Site Managers, particularly within the drag-and-drop format.

[embedded content]

 The Media Library in action

 

The Media Library is a pop-out window from which images and video can be inserted into the webpage. The library pulls content from the organisation’s existing bank of images, hosted within Drupal. Or, users can upload media directly from their cloud or hard drive.

The addition of the Media Library allows Site Managers to insert or change images or video more efficiently than ever. The user selects the area where the image will be added and opens the Media Library. They can then select from existing images or upload multiple new assets at once. Once uploaded, users can remove or reorder any images ready for import. Once happy with the images, the user can add metadata and any extra information (like links), or change the format to video.

The Media Library was made possible by Open Source contributions from 310 individuals and 122 organisations.

Drupal 8.7 Media Library Contributors

The 310 contributors (DrupalCon Seattle 2019: Driesnote)

 

Technical updates

There have also been a host of additional updates and tweaks to Drupal, improving its speed and background functionality. Such updates include adding JSON:API as a core module and providing a consistent way of displaying JavaScript Messages. For the full list of technical updates, visit the Drupal website here.

What’s Next?

Administration UI - Drupal 8.8 or 8.9

The administrative side of Drupal, where site managers navigate the back end and manage content, has been close to untouched for the past 10 years.

The User Interface (UI) is currently being redeveloped to be aligned and reflect the software behind Drupal, giving it a modern look and feel. This includes better use of space (and white space) and more contrasting features. The additional space also means its more accessible, and will receive a WYSIWYG integration.

Drupal 8.8 UI

Proposed UI for Drupal 8.8

 

Sign up to email alerts to find out more or talk to our Drupal Web Development Experts about upgrading your Drupal Platform.

 

Get in touch
Apr 01 2019
Apr 01

Vienna, VA March 19, 2019—Mobomo,

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

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

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

Feb 22 2019
Feb 22

 custom theme pictured near a pre-built theme

When implementing Drupal or any CMS for that matter, you can jump-start development and save time with pre-built themes. However, these themes can also hamstring your efforts to deliver content in the way you envisioned. 

An advantage of a pre-built theme is that they are usually already tested and will work as designed right out of the gate. On the other side, building a custom theme ties your web presence tightly with your brand identity and feels more like a singular experience. In this post we will try to determine if you should build a theme to match a custom design, or use a pre-built theme and try to fit your needs into the pre-packaged solution.

What is a CMS theme?

First, let's talk about what a theme even is and what its role in the website is. Themes exist for the most part in the presentation layer of your site. A theme will generally consist of templates for markup, CSS, and JavaScript. A theme is the rendered interpretation of the content data being returned by the backend CMS system. The theme determines the HTML structure through its templates and the look and feel of the HTML through its CSS and javascript files.

Brainstorm your next development project with an Ashday Drupal expert! Request your free session today. 

A pre-built Drupal theme may also include small pieces of custom code or custom views depending on what is needed. Often times they will also come with some predefined content types and usage examples. Similarly, pre-built Wordpress themes can also have some custom code or dependencies on additional plugins. A pre-built theme can’t accommodate a lot of custom needs or integrations and in many cases need to be hacked, ( significantly altering the code in a way that will likely eliminate any hope of support ), to get them to do anything beyond their design.

In the world of themes there are free themes and premium themes. Premium themes have a cost, usually a one-time fee or subscription, and a license and terms of use. There is a cottage industry around the creation of premium themes, individuals build attractive looking layouts and load them up with the entire kitchen sink of design patterns from sliders to parallax video backgrounds, then provide varying levels of support for them. The marketing behind these themes make them out to be the one-size fits all web solution. In reality, they often fall short of what you actually need and cause unnecessary bloat from the included features that you don’t need or use. That’s not to say that they are a bad solution, sometimes it is exactly what is needed for a project with very loose requirements.

About Drupal Themes

For Drupal, themes are broken up into a few different categories. There are base themes that don’t provide any visual design but do provide structure for HTML markup and some basic functionality. Base themes require a custom child theme that extends them to finish out the look and feel of the site. Related to custom themes in Drupal are distributions, these include a theme but also a pre-configured suite of contributed and custom modules. Distributions are generally built around specific project types like CRMs, e-commerce, education, or government to name a few. 

If you are considering using a pre-built theme, whether it’s a premium or free theme with Drupal, you should consider if you even need to use Drupal at all. Pre-built themes bypass a lot of the flexibility that Drupal can provide, and you may be able to achieve your goals with a more streamlined SaaS website builder solution. Pre-built themes make a little more sense for a CMS like Wordpress that is designed for a specific task like blogging. If you are looking to do more than a basic brochure style site or blog with Wordpress, you should think about a custom theme. 

Pre-built themes can save time up front during your initial build phase. They can also end up consuming more time than a custom theme would if anything needs to be modified or added to in any way. If you have plans to add an integration or custom feature in a future phase of your site, the pre-built theme could add more time in development and end up costing more in the long run. In short, if your project is a square peg that fits in the pre-built theme’s square hole, then the pre-built theme is the way to go, but this scenario is rare. In most cases you want your site to be tailored to your business and have a user experience that feels intentional and purpose-built. This is something that can only be achieved with a lot of planning and a custom theme.

Offer for a free consultation with an Ashday expert

Dec 17 2018
Dec 17

Drupal is an enormously welcoming community with countless online forums and community events to learn about the platform. Its open-source knowledge sharing and peer review is arguably second-to-none, and thanks to Acquia's Drupal certifications the Drupal learning process is becoming more consolidated.

However, nothing can quite beat the quality, focus, and hard work that goes into publishing a book. We’ve quizzed our Drupal developers and members of the Manchester tech community to find out which books every Drupal developer must read.


Drupal-Specific Books

 

Drupal 8 Module Development

Drupal 8 Module Development: Build and customize Drupal 8 modules and extensions efficiently

By Daniel Sipos

This book is a great welcome to Drupal 8, introducing you to the architecture of D8 and its subsystems, for a thorough foundational understanding. It guides you through creating your first module and continues to build upon your skills with more functionalities that all modern developers need to know.

View on amazon

Drupal Development Cookbook

Drupal 8 Development Cookbook - Second Edition: Harness the power of Drupal 8 with this recipe-based practical guide

By Matt Glaman

Using a fun, easy-to-follow recipe format, this book gives you an expansive look at the basic concepts of Drupal 8, in a step-by-step fashion. While this sometimes misses out on the ‘why’ of an action, it makes building new modules approachable and unintimidating for any level of developer.

View on amazon

Ambitious, intelligent, and a great Drupal developer? Check out our careers page.

CTI Careers

Drupal 8 Explained

Drupal 8 Explained: Your Step-by-Step Guide to Drupal 8

by Stephen Burge

Written in no-nonsense plain English, this book is great for any Drupal beginner. It’s been praised as the day-to-day reference book that any new developer should keep handy on their desk.

View on amazon

Drupal 8 Blueprints

Drupal 8 Blueprints: Step along the creation of 7 professional-grade Drupal sites

By Alex Burrows

This Drupal 8 guide will take you through 7 real Drupal 8 sites to demonstrate the latest practices in action. This all-encompassing view provides a look at the reasoning and methodology behind certain practices, and context for their larger impact on the site.

View on amazon

Definative Guide To Drupal 7

The Definitive Guide to Drupal 7 (Definitive Guide Apress)

by Benjamin Melancon

While new sites are being built in Drupal 8, it’s important the remember that many of the sites you’ll work on and maintain are in Drupal 7. This comprehensive book provides the nuts and bolts of any Drupal 7 site, to build a powerful and extensible system. Some concepts are slightly dated, so we’d recommend cross-checking online occasionally.

View on amazon

Pro Drupal 7 Development

Pro Drupal 7 Development (Expert's Voice in Open Source)

by Todd Tomlinson

This book is for slightly more ambitious developers as it quickly jumps through the basic modules to the more complex. Breaking down the development of APIs and improvements to Drupal 7, this book will have any Drupal Developer producing complex modules in no time.

View on amazon

Essential Development Books

Many coding principles span development languages and frameworks. Here are our essentials for any developer seeking the ability to produce high quality, clean code.

The Clean Coder

The Clean Coder: A Code of Conduct for Professional Programmers

By Robert C. Martin

This book delves into the difference between good and bad code. Split into 3 parts, the book first discusses principles, patterns, and practices of writing clean code. Real world case studies follow, before the book finishes with the signs of bad code and problem solving skills needed to de-bug and refresh any code base.

View on amazon

CSS

CSS Secrets: Better Solutions to Everyday Web Design Problems

by Lea Verou

CSS Secrets explains how to code common 'real world' solutions with CSS. Condensing the most useful and practical examples, this book is a more exciting read than the often extensive paperbacks which try to cover absolutely everything.

View on amazon

PHP and Javascript

Learning PHP, MySQL & JavaScript 5e (Learning PHP, MYSQL, Javascript, CSS & HTML5)

By Robin Nixon

Begin expanding your language stack with this multifaceted book. PHP is essential for any Drupal developer as it forms the core language of the Drupal framework. Meanwhile, learning Javascript, CSS and HTML5 will empower you to deliver more complex solutions.

View on amazon

And lastly, an open source book about… open source

The Cathedral & the Bazaar

By Eric S. Raymond

While this piece is slightly dated, it’s underlying concepts are still highly relevant and give great insight into the origins and essence of open source. It’s also free, so definitely still worth having a skim through… if you can handle the formatting!

Read it for free

I hope you've found some great reads here, if you've got a personal favourite please let us know below. Also if you're interested in advancing your Drupal career, please check out our careers page to see if there's a position perfect for you.

Careers at CTI Digital

Nov 09 2018
Nov 09

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

PR News Award on a table.

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

Screenshot of a Tweet posted by the PR News. Source

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

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

Screenshot of a Tweet from Vaccine Makers team. Source

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

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

Oct 29 2018
Oct 29

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

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

This session will leave you with: 

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

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

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

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

[embedded content]

Sep 18 2018
Sep 18

A slick new feature was recently added to Drupal 8 starting with the 8.5 release  — out of the box off-canvas dialog support.

Off-canvas dialogs are those which slide out from off page. They push over existing content in order to make space for themselves while keeping the existing content unobstructed, unlike a traditional dialog popup. These dialogs are often used for menus on smaller screens. Most Drupal 8 users are familiar with Admin Toolbar's use of an off-canvas style menu tray, which is automatically enabled on smaller screens.

Admin toolbar off-canvas

Drupal founder Dries posted a tutorial and I finally got a chance to try it myself.

In my case, I was creating a form for reviewers to submit reviews of long and complicated application submissions. Reviewers needed to be able to easily access the entire application while entering their review. A form at the bottom of the screen would have meant too much scrolling, and a traditional popup would have blocked much of the content they needed to see. Therefore, an off-canvas style dialog was the perfect solution. 

Build your own

With the latest updates to Drupal core, you can now easily add your own off-canvas dialogs.

Create a page for Your off-canvas content 

The built in off-canvas integration is designed to load Drupal pages into the dialog window (and only pages as far as I can tell). So you will need either an existing page, such as a node edit form, or you'll need to create your custom own page through Drupal's routing system, which will contain your custom form or other content. In my case, I created a custom page with a custom form.

Create a Link

Once you have a page that you would like to render inside the dialog, you'll need to create a link to that page. This will function as the triggering element to load the dialog.

In my case, I wanted to render the review form dialog from the application full node display itself. I created an "extra field" using hook_entity_extra_field_info(), built the link in hook_ENTITY_TYPE_view(), and then configured the new link field using the Manage Display tab for my application entity. 

/*
 * Implements hook_entity_extra_field_info().
 */
function custom_entity_extra_field_info() {
  $extra['node']['application']['display']['review_form_link'] = array(
    'label' => t('Review Application'),
    'description' => t('Displays a link to the review form.'),
    'weight' => 0,
  );
  return $extra;
}

/**
 * Implements hook_ENTITY_TYPE_view().
 */
function custom_node_view(array &$build, Drupal\Core\Entity\EntityInterface $entity, Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
  if ($display->getComponent('review_form_link')) {
    $build['review_link'] = array(
      '#title' => t('Review Application'),
      '#type' => 'link',
      '#url' => Url::fromRoute('custom.review_form', ['application' => $entity->id()]),
    );
  }
}

Add off-canvas to the link

Next you just need to set the link to open using off-canvas instead of as a new page.

There are four attributes to add to your link array in order to do this:

      '#attributes' => array(
        'class' => 'use-ajax',
        'data-dialog-renderer' => 'off_canvas',
        'data-dialog-type' => 'dialog',
        'data-dialog-options' => '{"width":"30%"}'
      ),
      '#attached' => [
        'library' => [
          'core/drupal.dialog.ajax',
        ],
      ],

The first three attributes are required to get your dialog working and the last is recommended, as it will let you control the size of the dialog.

Additionally, you'll need to attach the Drupal ajax dialog library. Before I added the library to my implementation, I was running into an issue where some user roles could access the dialog and others could not. It turned out this was because the library was being loaded for roles with access to the Admin Toolbar.

The rendered link will end up looking like:

<a href="https://www.zivtech.com/review-form/12345" class="use-ajax" data-dialog-options="{"width":"30%"}" data-dialog-renderer="off_canvas" data-dialog-type="dialog">Review Application</a>

And that's it! Off-canvas dialog is done and ready for action.

off-canvas-demo-gif
Sep 03 2018
Sep 03

...And the story of how two unlikely organisations drove innovation in the Drupal Platform.

While delivering continual support for an energy clients Drupal website, we wanted to implement a Postcode Lookup feature, with auto-complete functionality. Existing solutions were either too basic or needlessly expensive, but we couldn’t justify building a new solution from scratch. As luck would have, I discovered at our weekly Drupal 8 meeting that my colleagues working on a Not-For-Profit site required autocomplete capabilities for the address lookup on the donations page.

These two very different organisations, shared a mutual requirement. Recognising the value of a Postcode Lookup across different sectors and services warranted the investment in developing and contributing the module to the open source community.

For The Not-For-Profit, the team had used the PostCodeAnywhere PHP API (now Loqate) by writing their own JavaScript to complete the autocomplete functionality. But this was proving more and more time consuming; initially, it wasn’t even clear that the service offered a JavaScript widget.

The solution that the team built for the client was quite custom and specific, utilising the Address module’s more rigid form fields. So the end result wasn’t something we could quickly or easily contribute back to the community.

Clearly this was a feature that would benefit the Drupal experience if there was a permanent publicly available fix. When discussing how different organisations may use this feature, I came to the conclusion that it needed to be available as part of the widely adopted webform module that provided the popular drag-and-drop interface.


The Solution

The Postcode Lookup is fully responsive, has autocomplete capabilities, functions smoothly on an enterprise level, and has a comprehensive database to pull from for global addresses. All of this is available as a stand-alone widget, or as part of the existing webform module.

loqate-module_drupal8The Drupal 8 Loquate module in action


How it works

A user starts to type a postcode and the field will suggest addresses based on the text entered. Upon choosing an address from the drop-down list, a whole set of address fields are populated. This was achieved using Loqate’s (then PostCodeAnywhere) paid “Address Capture” JavaScript API, which was really quick and easy to implement.

To add Postcode Lookup to the Webform, we created the Loqate module. All you need is the Webform module and a Loqate API key and you’re up and running with a Postcode Lookup autocomplete field that you can put in any form on your site.

But that's not the end of it…

Going forward we are planning to add:

  • Integration with the Address module: This could have extensive use-cases, as this module is used heavily by the Commerce module and would make setting addresses for buying things significantly easier.
  • The ability to automatically change required fields based on a user's location, to improve international experience.
  • Toggles for manual entry vs postcode entry.
  • General code improvements, for better maintainability and more use-cases.

Co-Author: Rakesh James, Drupal Developer at CTI Digital

Cover Photo Cred: @thenomadbrodie 

Interested in working with us? Check out our vacancies here.

Careers at CTI Digital

May 18 2018
May 18

The Content Moderation core module was marked stable in Drupal 8.5. Think of it like the contributed module Workbench Moderation in Drupal 7, but without all the Workbench editor Views that never seemed to completely make sense. The Drupal.org documentation gives a good overview.

Content Moderation requires the Workflows core module, allowing you to set up custom editorial workflows. I've been doing some work with this for a new site for a large organization, and have some tips and tricks.

Less Is More

Resist increases in roles, workflows, and workflow states and make sure they are justified by a business need. Stakeholders may ask for many roles and many workflow states without knowing the increased complexity and likelihood of editorial confusion that results.

If you create an editorial workflow that is too strict and complex, editors will tend to find ways to work around the  system. A good compromise is to ask that the team tries something simple first and adds complexity down the line if needed.

Try to use the same workflow on all content types if you can. It makes a much simpler mental model for everyone.

Transitions are Key

Transitions between workflow states will be what you assign as permissions to roles. Typically, you'll want to lock down who can publish content, allowing content contributors to create new drafts only.

Transitions Image from Drupal.orgTransitions between workflow states must be thought through

You might want some paper to map out all the paths between workflow states that content might go through. The transitions should be named as verbs. If you can't think of a clear, descriptive verb that applies, you can go with 'Set state to %your_state" or "Mark as %your_state." Don't sweat the names of transitions too much though; they don't seem to ever appear in an editor-facing way anyway.

Don't forget to allow editors to undo transitions. If they can change the state from "Needs Work" to "Needs Review," make sure they can change it back to "Needs Work."

You must allow Non-Transitions

Make sure the transitions include non-transitions. The transitions represent which options will be available for the state when you edit content. In the above (default core) example, it is not possible to edit archived content and maintain the same state of archived. You'd have to change the status to published and then back to archived. In fact, it would be very easy to accidentally publish what you had archived, because editing the content will set it back to published as the default setting. Therefore, make sure that draft content can stay as draft when edited, etc. 

Transition Ordering is Crucial

Ordering of the transitions here is very important because the state options on the content editing form will appear as a select list of states ordered by the transition order, and it will default to the first available one.

If an editor misses setting this option correctly, they will simply get the first transition, so make sure that first transition is a good default. To set the right order, you have to map each state to what should be its default value when editing. You may have to add additional transitions to make this all make sense.

As for the ordering of workflow states themselves, this will only affect ordering when states are listed, for example in a Views exposed filter of workflow states or within the workflows administration.

Minimize Accidental Transitions

But why wouldn't my content's workflow state stay the same by default when editing the content (assuming the user has access to a transition that keeps it the same)? I have to set an order correctly to keep a default value from being lost?

Well, that's a bug as of 8.5.3 that will be fixed in the next 8.5 bugfix release. You can add the patch to your composer.json file if you're tired of your workflow states getting accidentally changed.

Test your Workflow

With all the states, transitions, transition ordering, roles, and permissions, there are plenty of opportunities for misconfiguration even for a total pro with great attention to detail like yourself. Make sure you run through each scenario using each role. Then document the setup in your site's editor documentation while it's all fresh and clear in your mind.

What DOES Published EVEN MEAN ANYMORE?

With Content Moderation, the term "published" now has two meanings. Both content and content revisions can be published (but only content can be unpublished).

For content, publishing status is a boolean, as it has always been. When you view published content, you will be viewing the latest revision, which is in a published workflow state.

For a content revision, "published" is a workflow state.

Therefore, when you view the content administration page, which shows you content, not content revisions, status refers to the publishing status of the content, and does not give you any information on whether there are unpublished new revisions.

Where's my Moderation Dashboard?

From the content administration page, there is a tab for "moderated content." This is where you can send your editors to see if there is content with drafts they need to review. Unfortunately, it's not a very useful report since it has neither filtering nor sorting. Luckily work has been done recently to make the Views integration for Content Moderation/Workflows decent, so I was able to replace this dashboard with a View and shared the config.

Using Views for a Moderation DashboardMy Views-based Content Moderation dashboard.

Reviewer Access

In a typical editorial workflow, content editors create draft edits and then need to solicit feedback and approval from stakeholders or even a legal team. To use content moderation, these stakeholders need to have Drupal accounts and log in to look at the "Latest Revision" tab on the content. This is an obstacle for many organizations because the stakeholders are either very busy, not very web-savvy, or both.

You may get requests for a workflow in which content creation and review takes place on a non-live environment and then require some sort of automated content deployment process. Content deployment across environments is possible using the Deploy module, but there is a lot of inherent complexity involved that you'll want to avoid if you can.

I created an Access Latest module that allows editors to share links with an access token that lets reviewers see the latest revision without logging in.

Access Latest lets reviewers see drafts without logging inAccess Latest lets reviewers see drafts without logging in

Log Messages BUG

As of 8.5.3, you may run into a bug in which users without "administer content" permission cannot add a revision log message when they edit content. There are a fewissues related to this, and the fix should be out in the next bugfix release. I had success with this patch and then re-saving all my content types.

May 14 2018
May 14

Last weekend I attended my first ever Drupal Sprint organised by NWDUG.

My background with Drupal is slightly unconventional: as a newbie to Drupal, who only became aware of its existence just under a year ago, I’ve had a fast-track journey with the software whilst working at CTI Digital. I don’t have an in-depth knowledge of the technical side of Drupal, but as I work in Marketing, exploring the history and culture around Drupal, I’m quickly becoming a bit of an expert. Therefore, attending my first sprint was a great insight into the world of Drupal.

IMG_6029

The May Sprint Team

 

The sprint was organised by NWDUG and we were happy to offer up our office space, as a large space with comfy seats and plentiful coffee is something always appreciated at a sprint. The space is actually open for anyone to use, so if you’re interested in holding a Drupal event, please get in touch any time.

 

Here’s what went on at the sprint:

9:30am

Everyone arrived, chipper and excited for the day. The first thing I noticed was how friendly and welcoming everyone was, even though I obviously wasn’t your standard Sprint attendee. Coffee and some light bites were shared out before we headed to our event space, named ‘The Garden’, for the welcome brief, given by Phil Norton.

Phil talked us through what would happen throughout the sprint and took special care to ensure first-time sprinters were set up and knew how to get involved. There were also a few non-technical activities, for newbies like me to get involved with.

Dc_GnsiWAAAKT8H-129037-edited

Phil's welcome address in 'The Garden'


10am

The Sprint begins! Those interested in doing some development discussed which issues they’d like to get involved with, then broke into teams and got to work. Again, I was delighted to see just how engaged all the first-time sprinters were; no-one was left confused or overwhelmed by the Sprint.


11am

A few of us broke off into a Case Study Workshop. Working in Marketing, I’m a big fan of a beautifully written case study, so we created a task force to review how we can encourage more members of the Drupal community to celebrate their work within the Drupal case study section. We used the AIDA model to break down the journey of writing a case study for developers and marketers. Then, we discussed the blockers and opportunities at each stage.

case study workshop

The case study workshop in full swing

 

Lunch!

Pizza and more pizza! After a busy morning everyone had a break to eat pizza, play pool, and socialise. Thank you to Access, for co-providing the pizza with us. There was also time for a quick group photo and an impromptu dance break, where a mini sprinter taught the developers how to do The Floss. Unfortunately no future ‘Britain's Got Talent’ winners were discovered, but everyone definitely enjoyed themselves!

[embedded content]The Drupal Floss

 

1pm

Back to sprinting: the developers resumed their issue teams and the second non-technical activity took place. Paul Johnson took video interviews, detailing the origin stories of how the attendees got involved with Drupal in the first place. Members of the sprint group discussed how Drupal has changed their lives, something that Rakesh recently delved into on our blog. It was inspiring to hear the developments of personal stories and journeys with Drupal.

IMG_6220

Post lunch sprinting

 

3pm

Before we knew it, the sprint was over! In summary: it was a brilliant day for technical and non-technical individuals alike. Afterwards a few of the group went for some celebratory drinks to soak up the success of the day.

What did we achieve?

There were a total of:

  • 16 patches applied
  • 5 were successfully reviewed and tested by the community (RTBC
  • 2 issues completely fixed.

Along with the open source contributions, we achieved:

  • A significant development into the accessibility of case study writing
  • The capture and documentation of the origin stories of multiple Drupal advocates

Special Thanks

Finally, I’d like to take some time to give special thanks to a few individuals on the day:

Our MVPs - Gemma Butler and Craig Perks

Gemma and Craig came down to keep the day running smoothly and it couldn’t have happened without them. From first aid to countless other essential roles, Gemma and Craig really made the day what it was and we couldn’t say thank you enough!

Rakesh James

Rakesh got the ball rolling for this sprint in the first place and was the driving force in helping it happen. Thank you Rakesh and hopefully this isn’t the last time you’ll be making something like this happen.

Phil Norton

Phil heads up the North West Drupal User Group and provided the community to form the sprint of such a welcoming and successful group of multi-talented individuals. So thank you Phil for such a great day!

And thank you to everyone else who attended;

  • Peter Jones
  • Des Fildes
  • Nigel White
  • James Davidson
  • Lesley Moreira
  • Tony Barket
  • Richard Sheppard
  • Phil Wolstenholme
  • Steve Hilton
  • Syed Huda
  • John Cook
  • Daniel Harper
  • Andrew Macpherson
  • Rachel Lawson (From The Drupal Association)
  • Craig Perks
  • Michael Trestianu
  • Paul Johnson
  • Andrew J

Interested in attending the next Drupal Sprint? Follow  and  on twitter to hear about the next one.

.

Apr 05 2018
Apr 05

Drupal 8.5 was released on the 7th of March 2018 with a host of new features, bug fixes, and improvements. There are plenty of exciting updates for developers in this blog. Or if you're a business owner, click here to find out what this means for you.

Any projects using Drupal 8.4.x can and should update to Drupal 8.5 to continue receiving bug and security fixes. We recommend using composer to manage the codebase of your Drupal 8 projects.

For anyone still on Drupal 8.3.x or earlier I recommend reading the Drupal 8.4.0 release notes as Drupal 8.4 included major version updates for Symfony, jQuery, and jQuery UI meaning it is no longer compatible with older versions of Drush.

One of the great things we noticed from the update was the sheer number of commits in the release notes.

Seeing all the different issues and contributors in the release notes is a good reminder that many small contributions add up to big results.

Dries Buytaert, Founder of Drupal

So what are the highlights of the Drupal 8.5 release?

Stable Releases Of Content Moderation And The Settings Tray Modules

One of the changes to the way Drupal is maintained is the new and improved release cycle and adoption of semantic versioning. Major releases used to only happen once every couple of years, Drupal now uses a much smaller release cycle for adding new features to core of only 6 months. New features are added as “experimental core modules” and can be tested, bug fixed and eventually become part of Drupal core.

One example of the shorter release cycle is the BigPipe module. The module provides an implementation of Facebook’s BigPipe page rendering strategy, shortening the perceived page load speed of dynamic websites with non-cacheable content. This was an experimental module when Drupal 8.1 was released and became a part of Drupal core as a stable module in 8.2.

In Drupal 8.5 the BigPipe module is now enabled by default as a part of Drupal’s standard installation profile. BigPipe is actually the first new feature of Drupal 8 to progress from experimental to stable to being a part of a standard installation profile.

There are two exciting modules now stable in the update, they are:

  • Settings Tray
  • Content Moderation

Settings Tray is a part of the “outside-in” initiative where more of the content management tasks can be done without leaving the front end of the website, managing items in context such as editing the order of the menu items in a menu block.

The Content Moderation module allows the site builder to define states in which content can be placed such as “draft”, “needs review” and to define user permissions necessary to move content between those states. This way you can have a large team of authors who can place documents into draft or needs review states, allowing only website editors with specific permissions to publish.

New Experimental Layout Builder

Sticking with experimental modules, Drupal 8.5 sees the introduction of a new experimental layout builder. This module provides the ability to edit the layouts of basic pages, articles and other entity types using the same “outside-in” user interface provided by the settings tray.

This allows site builders to edit the layout of fields on the actual page rather than having to use a separate form in the backend. Another feature is the ability to have a different layout on a per-page / item basis if you so wish with the ability to revert back to the default if it doesn’t work for you. There’s still a long way to go and is currently only a basic implementation but it should be improving significantly over the coming months and hopefully will see a stable release in Drupal 8.6.

umami-8.5-layout-builder

The experimental layout builder in action 

PHP 7.2 Is Now Supported

This is the first version of Drupal to fully support the latest version of PHP. Support is not the only aspect of this release though, site owners are now also warned if they try to install Drupal on a version of PHP less than 7.0 they will no longer be supported by Drupal as of March 7, 2019.

Drupal 8.5 now also uses Symphony Components 3.4.5 since Symfony 3.2 no longer receives security coverage. I expect Drupal 8 to remain on 3.4 releases until late 2021 or the end of Drupal 8's support lifetime (whichever comes first). Finally, PHPUnit now raises test failures on deprecated code.

Media Module In Core Improved And Now Visible To All Site Builders

Drupal 8.4 added a Media API into core which was based on all the hard work done on the contributed Media Entity Module. The media module provides “media types” (file, audio, video, and image) and allows content creators to upload and play audio and video files and list and re-use media. The core media module can be expanded by the installation of key contributed modules which add the ability to add externally hosted media types such as YouTube and Vimeo videos.

The module has been present in the codebase but was hidden from the module management interface due to user experience issues. These issues have now been taken care of and anyone who has access to the module management page can now enable the module.


New “Out of the Box” Demo Site

One of the key initiatives is the “out of the box experience”. The aim is to showcase what Drupal can do by providing a simple to install demo website (called Umami presently) with example content, configuration, and theme.

According to Drupal, the main goal of the demo site is:

To add sample content presented in a well-designed theme, presented as a food magazine. Using recipes and feature articles this example site will make Drupal look much better right from the start and help evaluators explore core Drupal concepts like content types, fields, blocks, views, taxonomy, etc.

The good news is that Drupal 8.5 now comes with the demo website available as an installation profile. The profile is “hidden” at the moment from the installation GUI but can be installed using the command line / drush.

The demo website still needs a lot of work but the groundwork is firmly in place and may become selectable as an installation profile for demonstration and evaluation purposes in a future release of Drupal 8.5.x. I recommend users not to use the Umami demo as the basis of a commercial project yet since no backward compatibility or upgrade paths are provided.

Migrate Architecture, Migrate Drupal and Migrate UI Modules are now Stable

This item almost deserves its own blog post as it’s such a major milestone for Drupal, with over 570 contributors working on closing over 1300 issues over a 4 year period. As such the Migrate system architecture is considered fully stable and developers can write migration paths without worrying about the stability of the underlying system.

The Migrate Drupal and Migrate UI modules (which are used for Drupal 6 and 7 migrations to Drupal 8) are also considered stable for upgrading sites which are not multilingual, with multilingual support still being heavily worked on.

There is also support for incremental migrations meaning that the website can be worked on while the content is still being added on the site being upgraded/migrated from.

More information can be found in the official migrations in Drupal 8.5.0 post.

Links to Drupal 8 User Guide

Now on a standard installation you are greeted with a welcome page and a link to the new and improved Drupal 8 User Guide. While only a small addition, we can see this as a major win as it will improve the evaluation experience for new users.

Future Drupal Development

There is currently a proposed change to the 6-month release cycle to reduce it to a 4-month cycle because, according to Drupal, "currently, given time for alpha, beta and rc releases, issues that narrowly miss the beta window have to wait eight months to get into a tagged release."

This will require 2 core branches to be supported at once and additional work for core committers. However, new features and bug fixes will be available sooner so it will be interesting to see what the outcome of the proposal is.

What Does This Mean For Business Owners?

You’ll need to ensure you’ve updated your site from Drupal 8.4.5 to 8.5.0 to continue receiving bug and security fixes. The next of which is scheduled to be released on April 4th, 2018. If, however, you are on Drupal 8.3.x and below we urge you to read the release notes for Drupal 8.4.0 as there were some major updates to consider. These include a jump from jQuery 2 to 3 which may have some backward compatibility issues affecting any slideshows, carousels, lightboxes, accordions and other animated components.

Drupal 8.4 also dropped support for Internet Explorer 9 and 10 where ay bugs that affect these browsers will no longer be fixed and any workarounds for them have been removed in Drupal 8.5.

If your website is still on Drupal 7 then this is a good time to consider migrating to Drupal 8 as the hard work carried out on the migrate modules mentioned above will streamline the process of adopting the new platform.

If you have any questions about migrating your Drupal 7 website to Drupal 8 please let us know and we'll ensure one of our experts are on hand to help.

Get in touch

Important Dates

See https://www.drupal.org/core/release-cycle-overview for more:

  • 8.6.0 Feature Freeze: Week of July 18, 2018
  • 8.6.0 Release: September 5, 2018
  • 8.7.0 Feature Freeze January 2019
  • 8.7.0 Release: March 19, 2019
Mar 08 2018
Mar 08

This post was originally published on May 22, 2013 and last updated March 8, 2018 thanks to some helpful input by Steve Elkins.

Drupal 7 is a haus at combining CSS & JS files. This can help boost page performance & optimization easily, but if not used right, can do the complete opposite. In this post, we’ll go over how to load JS & CSS files based on conditionals like URL, module, node, views and more.

Before we dive in, get somewhat familiar with the drupal_add_js and drupal_add_css functions. We’ll use these to load the actual JS and CSS files.

hook_init – runs on every page

/**
 * Implements hook_init()
 *
 * @link https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_init/7.x
 */
function HOOK_init() {

  // Using the equivalent of Apache's $_SERVER['REQUEST_URI'] variable to load based on URL
  // @link https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/request_uri/7
  if (request_url() === 'your-url-path') {
    drupal_add_js( /* parameters */ );
    drupal_add_css( /* parameters */ );
  }
}

Using hook_init is one of the simplest methods to load specific JS and CSS files (don’t forget to replace HOOK with the theme or module machine name).

Be careful, this method get’s ran on every page, so it’s best to use this method only when you actually need to check every page for your conditional. A good example, loading module CSS and JS files. A bad example, loading node-specific CSS and JS files. We’ll go over that next.

There’s also a similar preprocess function, template_preprocess_page you could use, but it too get’s ran on every page and is essentially the same as hook_init.

template_preprocess_node – runs on node pages

/**
 * Implements template_preprocess_node()
 *
 * @link https://api.drupal.org/api/drupal/modules%21node%21node.module/function/template_preprocess_node/7.x
 */
function TEMPLATE_preprocess_node(&amp;$vars) {
  // Add JS &amp; CSS by node type
  if( $vars['type'] == 'your-node-type') {
    drupal_add_js( /* parameters */ );
    drupal_add_css( /* parameters */ );
  }
   
  // Add JS &amp; CSS to the front page
  if ($vars['is_front']) {
    drupal_add_js( /* parameters */ );
    drupal_add_css( /* parameters */ );
  }
   
  // Given an internal Drupal path, load based on node alias.
  if (drupal_get_path_alias(&quot;node/{$vars['#node']-&gt;nid}&quot;) == 'your-node-id') {
    drupal_add_js( /* parameters */ );
    drupal_add_css( /* parameters */ );
  }
}

Using template_preprocess_node is perfect when loading JS and CSS files based on nodes (don’t forget to replace TEMPLATE with the theme machine name). Since it only get’s run on nodes, it’s great to use when you want to load CSS and JS files on specific node types, front pages, node URLs, etc.

template_preprocess_views_view – runs every view load

/**
 * Implements template_preprocess_views_view()
 *
 * @link https://api.drupal.org/api/views/theme%21theme.inc/function/template_preprocess_views_view/7.x-3.x
 */
function TEMPLATE_preprocess_views_view(&amp;$vars) {
  // Get the current view info
  $view = $vars['view'];

  // Add JS/CSS based on view name
  if ($view-&gt;name == 'view_name') {
    drupal_add_js( /* parameters */ );
    drupal_add_css( /* parameters */ );
  }

  // Add JS/CSS based on current view display
  if ($view-&gt;current_display == 'current_display_name') {
    drupal_add_js( /* parameters */ );
    drupal_add_css( /* parameters */ );
  }
}

Using template_preprocess_node is useful when loading JS and CSS files when a particular view is being used (don’t forget to replace TEMPLATE with the theme machine name).

Helpful Methods for Conditionals

Here’s a few helpful Drupal methods you can use for your conditionals. Have one you use often? Let me know in the comments below.

  • request_uri – Returns the equivalent of Apache’s $_SERVER[‘REQUEST_URI’] variable.
  • drupal_get_path_alias – Given an internal Drupal path, return the alias set by the administrator.

<

h3>Looking like a foreign language to you?

Not a developer or just lost looking at the code snipplets above? Shoot me a question in the comments below, or give these ‘plug-and-play’ modules a try for a GUI alternative:

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Mar 06 2018
Mar 06

During the CXO day at Drupalcamp London, Dave O’Carroll the Head of Digital at War Child delivered a compelling speech on how Drupal has aided their mission in supporting the future and well-being of children living in some of the world’s most dangerous war zones.

When Warchild UK began to feel their website could no longer facilitate their day to day needs they began to consider a Drupal rebuild or even using an alternative technology. The existing Drupal platform was unfriendly towards images and so couldn’t reflect their work on the ground in its true light. Being unresponsive was also a major issue for the site.

After conducting research and consulting with peers, War Child UK came to the conclusion that Drupal still remained far above the rest in aiding the charity to continue their work and simply needed an update to meet their evolving needs.


When the time came for us to replace our website we were open to using different systems. But it soon became obvious that Drupal would remain the right choice

Dave O'Carroll

When making the decision to stay with Drupal, 4 key areas were turning points in confirming their decision.

1. Compatibility

War Child UK are acutely aware of the world of software solutions out there. Despite the natural desire to focus on having an aesthetically pleasing website, the websites ability to seamlessly take on integrations like MailChimp, Stripe, and SalesForce was deemed essential. As most of these software APIs and plugins are Drupal friendly, sticking with Drupal in this regard was a no-brainer.

The team at War Child UK dedicate themselves to changing the lives of children and spending as much time and money out on the field as possible. Being a charity, they also have to provide a great deal of accountability on where their money comes from and where it goes, so investment in digital can be incredibly difficult to justify. But by using Drupal, its compatible nature means the charity can spend more resources on helping children, not conducting systems integrations.

Having done this many times before, I knew the best websites are the ones that play nice with the other children - they integrate well.

Dave O'Carroll

2. Ease of use

War Child needed to give content creators the independence to upload their own stories so their messages could be told from the heart, and not dilluted by multiple teams. If they were able to train staff to directly upload content, War Child's work would be able to be projected in near real time.

Dave explained, with previous experience of Wordpress and Squarespace at other charities he had found the staff would receive training but come back repeatedly to clarify how to perform daily tasks. The simple intuitive administration screens we configured for War Child meant that, with Drupal, staff needed to be shown just once. This saves War Child time, and time saves money.

Our HR team, who don’t spring to mind as digital experts, are able to manage their own site section. It’s great they are able to have a degree of freedom. 

Dave O'Carroll

 

3. Support

The flexibility of Drupal provides support for all of War Child’s goals. War Child needs to be more flexible and creative to stand alongside larger charities with far bigger communications teams and marketing resource. The vast community surrounding Drupal means that no matter how improbable an idea appears to be, the community always manages to push up gems to make an idea reality.

Warchild_main_image-1 

With a big fat creative idea, there always seems to be a way to do it with Drupal

Dave O'Carroll


4. Future Proofing

What if I get hit by a bus? A concerning idea, but something that applies to War Child UK immensely. With thousands of children relying on the charity, they can't afford to not plan for the ‘what ifs’. Drupal's intuitive CMS already makes it easy to pick up where the last person left off. We crafted a solution to take this capability further and built a system to the best possible standards. This stronger governance means if War Child ever need to move agencies, replace key team members or work with freelancers the continuity will still be there and save them time and money, allowing War Child to focus on their mission.

Conclusion

All too often children are portrayed as the collateral damage of war. War Child wanted their site to portray a different story and so we implemented designs that placed children at the heart of the new website, you can read the full website case study here. The new platform allows War Child to overcome past restraints and think outside the box for future campaigns. We look forward to continuing to help those at War Child to support children in new innovative ways for years to come. One of their recent campaigns ‘Robot’ has been particularly moving, please watch the video below.

 

[embedded content]

 

Visit the war child website

 

Jan 31 2018
Jan 31

Illustration of person scratching head at fork in the road

This is the first part in a series on how not to ruin your life on your next Drupal project. Sound extreme? Well, if you’ve ever suffered the crushing defeat of working your tail off on a lengthy project only to sit there at the end after launch feeling like you just came out of the opening night of Star Wars: The Phantom Menace (ie: severely disappointed and a bit confused), then you know that it is indeed extreme. We spend a majority of our day at work and when it’s not rewarding or energy-giving, it’s a real drag.

So what is the formula? Well, a blog post isn’t going to solve all your problems - but - there are certainly key approaches that we have taken that have helped us avoid catastrophe time and time again. Translation? We’ve managed an extremely high customer satisfaction rate for over two decades. What’s been happening here seems to be working so we pay a lot of attention to what it is exactly that we are doing and assess why we think it’s working. If you want a high-level bird's-eye view, check out our process page. We are going to get a bit downer and dirtier here though.

Ultimately, we want you to go home to your family at the end of the day saying “GUESS WHAT I DID AT WORK TODAY EVERYONE!!” (like we do) instead of “Can we just order pizza and go to bed at 7?”.

 We’ve identified 3 essential components to kicking a project off right, the first of which will be covered in this post. They are the following:

  1. Aggressive and Invested Requirements Gathering
  2. Relentless Ideation
  3. Atomic Preparation

So let’s start with Aggressive and Invested Requirements Gathering. We spent a lot of time thinking about this and I realized it comes down to the adjectives. Everyone knows (mostly) about requirements gathering, but it’s a minefield of unasked questions, unanswered questions, misconceptions, forgetfulness, and chaos. The solution? Take ownership of this baby from the beginning and treat it like it’s your project - it’s your passion - and do what it takes to nail it down. Getting answers that make your life easier, despite your suspicions that the client is maybe not thinking it through, doesn’t help anyone. Take no shortcuts and care about everything.

“Take ownership of this baby from the beginning.”

Here are 3 specific goals:

Assess priorities (theirs and yours!)

Priorities are key because we can easily get hung up on things that ultimately aren’t that important. On the flip side, there are things that are tremendously important to one of the two parties, and hence, it must be important to both. So the client says I care most about X, then Y, then Z. In your head you’re thinking “Yikes, Z has a huge unknown element that I’d like to solve quickly to understand the implications.” So talk about it. Repeat their priorities back to them and state your own and find that happy middle ground where you can pursue the project in an efficient and effective way while also focusing on what matters. It sounds simple, but unspoken expectations or concerns are a plague in project management.

Determining constraints (time, money, features, personnel)

I still love the age-old project management triangle that says that for any given project, you can choose 1 of the 3 key priorities in a project: time, money or features. This means that you can’t simply dictate the budget and the schedule and also expect a very rigid set of requirements. The problem is that despite even stating this, there is a lot of pressure from the client to set the expectation on all three and that simply isn’t possible. So it’s critical early on to sort out what the real constraints are. Ok, you would like this to stay under $50k. Is that a hard cap or could you go over if you felt it was worth it? So you want this launched by January 1st. Is that more of a clean-sounding date or is this tied to a fiscal year, or some other real deadline? Ok, so you want features X, Y and Z. Which of those would be deal breakers to not have? This kind of questioning is very helpful because early on in the build phase, you can make intelligent decisions about how and when to collaborate with the client since you know the significance of obstacles or changes of directions that impact these things.

The last thing I’m throwing on top of this triangle is the concept of personnel. We’ve found that knowing who your stakeholders are, who your end users are, who your editors and admins are - early on - is critical. I’ve literally had meetings where we’re deep into requirements and then I meet the person who has veto power over everything and the thing goes sideways. We’ve learned as well that there is a repeating sales cycle when new stakeholders arrive because convincing the last three people doesn’t mean you’ve convinced the next three. I’ve also had times where a stakeholder makes some critical decisions, but then after talking to the people “on the ground”, I find that he was simply just wrong on some of the day-to-day operations. It’s good to talk to everyone, but also find out each person’s role in the big picture. Often times we’ve found ourselves advocating on behalf of lower level employees who often bring up important and practical issues that decision-makers are often overlooking. It’s a delicate balance, but if the system isn’t welcomed and adopted well by it’s primary users, the project will sink even if the ones writing the checks are getting what they think they want.

Reading between the lines

This is tied to the item above in a lot of ways, but stands on it’s own as an important point. When you’ve done this long enough, you learn that most of what is asked for by a potential client is not always really the point. Often there is a hidden goal or motivation that has led to the formation of a feature request. Even if that request perfectly solves the need, it’s still important to discover that need because it can affect the implementation and guide the specifics. For example, if a request is made to let users download an export of tracking data, but you dig and find out that actually they’re just using this tool to turnaround and upload it into a remote system and it’s a bit of a pain, maybe building a web service is better where their system can talk directly to ours and users can step out of the daily grind. 

Conclusion

So in summary - gathering requirements the same way you date someone you’re thinking of marrying. Care about it and pursue it as if it’s the most important thing you’ve got going with an end goal of a lifetime of happiness.

Up Next: Running a Drupal project the right way: Part 2 - Relentless Ideation 

Free offer, talk to a seasoned Drupal expert.

Jan 31 2018
Jan 31

Illustration of person scratching head at fork in the road

This is the first part in a series on how not to ruin your life on your next Drupal project. Sound extreme? Well, if you’ve ever suffered the crushing defeat of working your tail off on a lengthy project only to sit there at the end after launch feeling like you just came out of the opening night of Star Wars: The Phantom Menace (ie: severely disappointed and a bit confused), then you know that it is indeed extreme. We spend a majority of our day at work and when it’s not rewarding or energy-giving, it’s a real drag.

So what is the formula? Well, a blog post isn’t going to solve all your problems - but - there are certainly key approaches that we have taken that have helped us avoid catastrophe time and time again. Translation? We’ve managed an extremely high customer satisfaction rate for over two decades. What’s been happening here seems to be working so we pay a lot of attention to what it is exactly that we are doing and assess why we think it’s working. If you want a high-level bird's-eye view, check out our process page. We are going to get a bit downer and dirtier here though.

Ultimately, we want you to go home to your family at the end of the day saying “GUESS WHAT I DID AT WORK TODAY EVERYONE!!” (like we do) instead of “Can we just order pizza and go to bed at 7?”.

 We’ve identified 3 essential components to kicking a project off right, the first of which will be covered in this post. They are the following:

  1. Aggressive and Invested Requirements Gathering
  2. Relentless Ideation
  3. Atomic Preparation

So let’s start with Aggressive and Invested Requirements Gathering. We spent a lot of time thinking about this and I realized it comes down to the adjectives. Everyone knows (mostly) about requirements gathering, but it’s a minefield of unasked questions, unanswered questions, misconceptions, forgetfulness, and chaos. The solution? Take ownership of this baby from the beginning and treat it like it’s your project - it’s your passion - and do what it takes to nail it down. Getting answers that make your life easier, despite your suspicions that the client is maybe not thinking it through, doesn’t help anyone. Take no shortcuts and care about everything.

“Take ownership of this baby from the beginning.”

Here are 3 specific goals:

Assess priorities (theirs and yours!)

Priorities are key because we can easily get hung up on things that ultimately aren’t that important. On the flip side, there are things that are tremendously important to one of the two parties, and hence, it must be important to both. So the client says I care most about X, then Y, then Z. In your head you’re thinking “Yikes, Z has a huge unknown element that I’d like to solve quickly to understand the implications.” So talk about it. Repeat their priorities back to them and state your own and find that happy middle ground where you can pursue the project in an efficient and effective way while also focusing on what matters. It sounds simple, but unspoken expectations or concerns are a plague in project management.

Determining constraints (time, money, features, personnel)

I still love the age-old project management triangle that says that for any given project, you can choose 1 of the 3 key priorities in a project: time, money or features. This means that you can’t simply dictate the budget and the schedule and also expect a very rigid set of requirements. The problem is that despite even stating this, there is a lot of pressure from the client to set the expectation on all three and that simply isn’t possible. So it’s critical early on to sort out what the real constraints are. Ok, you would like this to stay under $50k. Is that a hard cap or could you go over if you felt it was worth it? So you want this launched by January 1st. Is that more of a clean-sounding date or is this tied to a fiscal year, or some other real deadline? Ok, so you want features X, Y and Z. Which of those would be deal breakers to not have? This kind of questioning is very helpful because early on in the build phase, you can make intelligent decisions about how and when to collaborate with the client since you know the significance of obstacles or changes of directions that impact these things.

The last thing I’m throwing on top of this triangle is the concept of personnel. We’ve found that knowing who your stakeholders are, who your end users are, who your editors and admins are - early on - is critical. I’ve literally had meetings where we’re deep into requirements and then I meet the person who has veto power over everything and the thing goes sideways. We’ve learned as well that there is a repeating sales cycle when new stakeholders arrive because convincing the last three people doesn’t mean you’ve convinced the next three. I’ve also had times where a stakeholder makes some critical decisions, but then after talking to the people “on the ground”, I find that he was simply just wrong on some of the day-to-day operations. It’s good to talk to everyone, but also find out each person’s role in the big picture. Often times we’ve found ourselves advocating on behalf of lower level employees who often bring up important and practical issues that decision-makers are often overlooking. It’s a delicate balance, but if the system isn’t welcomed and adopted well by it’s primary users, the project will sink even if the ones writing the checks are getting what they think they want.

Reading between the lines

This is tied to the item above in a lot of ways, but stands on it’s own as an important point. When you’ve done this long enough, you learn that most of what is asked for by a potential client is not always really the point. Often there is a hidden goal or motivation that has led to the formation of a feature request. Even if that request perfectly solves the need, it’s still important to discover that need because it can affect the implementation and guide the specifics. For example, if a request is made to let users download an export of tracking data, but you dig and find out that actually they’re just using this tool to turnaround and upload it into a remote system and it’s a bit of a pain, maybe building a web service is better where their system can talk directly to ours and users can step out of the daily grind. 

Conclusion

So in summary - gathering requirements the same way you date someone you’re thinking of marrying. Care about it and pursue it as if it’s the most important thing you’ve got going with an end goal of a lifetime of happiness.

Up Next: Running a Drupal project the right way: Part 2 - Relentless Ideation 

Free offer, talk to a seasoned Drupal expert.

Jan 18 2018
Jan 18

During the redesign process of a website, there are many small changes that can ultimately affect the traffic of the new site. The key is to identify any changes that might break SEO, or changes that might affect the way the site looks to search engine spiders ahead of time to avoid traffic drops. In the end, we want the site to look fresh and new while still getting the same traffic, or more, as the old design. 

At Zivtech, we look at many factors in the planning phase of a website redesign project and try to identify those that could cause drops in traffic after the new design is launched. Once these have been identified, we ensure all of these tasks have been completed before launch. Let’s take a look at some of these factors and how to avoid traffic drops on your next website redesign project.

Meta Tags

We typically build sites with Drupal, so the Metatag module handles much of the meta tag configuration and display on the site. If you aren’t using Drupal though, there could be some changes to your front-end design that could affect your meta tags and confuse search engine spiders. You’ll need to make sure that all of your pages have meta tags and that there aren’t any duplicates. 

Broken Links

Broken links are a huge problem during website redesigns. This could be a result of changes in the menu structure or in path structures for content types. Broken links mean that users and search engines can’t find the pages they’re looking for, which can really wreak havoc on your site traffic statistics. 

To avoid broken links in Drupal, we can use the Link checker module, but there are also third party tools that can be used for non-Drupal sites. Google Search Console provides some additional tools to identify broken links and 404 pages too.

404 page

URL Redirects

Broken redirects or missing redirects to new URLs are also a big problem on site redesigns. These typically happen due to changes in URL patterns or menu structures. The Redirect module in Drupal provides an interface to add redirects for your pages without any coding experience. Non-Drupal sites can use .htaccess files or redirect statements in their web server configuration to ensure that all URLs that are changing have proper 301 redirects.

XML Sitemap

As URLs are changed on your site during a redesign, you’ll want to ensure that the XML sitemap has updated URLs that match the new ones. The XML sitemap module handles this for us on a Drupal site. 

If you aren’t running Drupal, a plugin for your CMS may handle this, or you’ll need to generate a new sitemap using third party tools. Once this has been completed, you can log in to Google Search Console and resubmit your sitemap for indexing.

Google Analytics

If you forget to place your Google Analytics tracking code in your new site’s markup before launch, you can end up in the dark when it comes to traffic fluctuations. The Google Analytics module handles the placement of this tracking code on a Drupal website, and even provides a status warning on the Drupal status page if the tracking ID has not been configured yet. 

Those who aren’t using Drupal should follow the instructions provided by Google Analytics to place the code snippet in their site’s markup, or use a plugin provided by their CMS of choice. With the Google Analytics tracking code in place, your organization can get a much better overview of how your site performs after the redesign launches. It’s much easier to track your successes or failures in your redesign if you were already running Google Analytics, but a relaunch is a great time to start using it too. 

While the factors in this post are some of the most important that we look at during a site redesign project at Zivtech, each project is unique and could require additional changes to your site to ensure you avoid traffic drops after launching your new design. 

Overall, you want to identify any changes that could affect URLs, meta data, and even content structure that search engine spiders or your visitors might be confused about. Even small changes or a missing meta tag can affect your search engine rankings, which can lead to traffic drops. Do your future self a favor and make a list of the individual factors that could affect your site. Then ensure that list is completed before calling your next website redesign a success.
 

Oct 10 2017
Oct 10

As a Drupal expert, many of the projects I’ve done over the years have been marketing websites. Drupal is widely understood as a content management system that’s used to power sites like ours, but this is actually only the tip of the iceberg of what Drupal can do for an organization. Our team has used Drupal to build a variety of complex custom web applications that help companies work more efficiently.

Do you need an intranet?

We’ve used Drupal to build intranets that securely keep internal content and documents for staff eyes only. Drupal has an abundance of community features that make it easy to have wikis, commenting, user profiles, and messaging. Many organizations we’ve worked with integrate their intranet with their LDAP or other Single Sign On system. 

Radial intranetRadial's intranet allows team members to quickly locate information about co-workers

We’ve also used Drupal for our own intranet for the past eight years. Our intranet helps keep our internal knowledge base easy to access and organizes information like our servers, sites, clients, and projects.

Do you run on spreadsheets and email?

Some of the projects I’ve really enjoyed developing have used Drupal as a tool to increase the efficiency of critical business processes. Organizations tend to rely heavily on Excel or Google spreadsheets and email to manage information and communications. When your needs outgrow those tools, it’s time for a web application.

ConantConant's SmartDeps web application improved their workflow and allowed them to stop relying on email

Have you outgrown Excel?  

Data organization needs often outgrow the spreadsheet sweet spot. Typically, you’ll see some of the following problems:

  • Versions of a spreadsheet are getting emailed around.
  • Mistakes are being made in a spreadsheet, causing serious problems.
  • Data has been deleted and lost.
  • To minimize mistakes, one person has been made the editor of the spreadsheet, bottlenecking the process.
  • Manual work is being done where it doesn’t need to be. For example, does someone check the spreadsheet every week and then manually send out emails based on information there?

A web application like Drupal stores data safely in a database and provides an interface for people to access and update the data in a much more controlled way than a spreadsheet can. You can decide who should be able to see the data (which is always up to date) and who should be allowed to edit it or delete it. You can also control data validation, greatly reducing mistakes in data entry. You can track changes to the data. You can make easy to read reports. You can create automated workflows, like sending automated emails for example.

The best part of all this? This type of development work typically costs much less than what you spent on your marketing website. Mainly that’s because you don’t need custom design work and implementation on this kind of tool. 

Have you outgrown Email?

I have to admit, email is not my friend. I’m a project-based worker, and I need my written communication organized by project and by task. When I’m cc’ed on an email with ten people on it and the conversation veers from one topic to another while the subject line stays the same, I really can’t follow what’s going on. It seems as though the only way to keep up with these emails is to do nothing but tend to one’s email. And what happens when a new person is hired and all the history of your organization can be found only in old emails that they don’t have?

No organization can completely remove the reliance on email these days. But if you are running your business on email, a web application may be able to help. 

Often a Software as a Service solution (SaaS) can help organize communication. For communications surrounding sales leads, Salesforce can help. For discussions, Slack. For project-based organization, Jira or Basecamp. But if you have a very specific process around some of your communications, a custom Drupal-based application can be a great fit.

Here are a few examples our team has worked on: 

  • A legal printing company was relying on email to get work requests from customers, then emailing back and forth with estimates and questions. We built them a custom web application in which the customers enter in the request and the system organizes the process, greatly speeding up the work and automating many aspects.
  • A foundation was receiving grant applications by email and organizing the applicants and review process in Excel. We built a system to manage the entire process online.
Copland FoundationThe Aaron Copland Fund for Music can now manage their grant cycles entirely from the web app

Need help?

If you have a pain point at work that revolves around organization or access of information, an efficient solution that saves you time and money might be easier to come by than you think. Search for a SaaS product geared toward your needs, and if you find your needs are too unique for what’s out there, let’s talk about a custom web application.
 

Jul 06 2017
Jul 06

You’re about to begin a huge overhaul of your higher education website and one of the first steps is choosing a content management system. It’s likely that Drupal and WordPress have come up in your research, and you may be trying to decide between the two.

Drupal and WordPress are often compared to one another because they’re both open source content management systems. Both are capable of creating clean, responsive websites that are easy to manage for content editors. The functionality of both can be extended using third party code. And the code for both is openly available for anyone to use, change, and distribute, meaning there are no licensing fees like those required by closed source options. 

There are a significant number of higher education websites on Drupal; Harvard, Brown, and Oxford University all use the CMS, to name a few. According to Drupal.org, 71% of the top 100 universities use Drupal. And there’s some sound reasoning behind that.

Both WordPress and Drupal have strengths and are well suited for a diverse range of projects. WordPress was primarily built for standalone websites or blogs with minimal variation in content types. Drupal was built for more complex, feature rich websites that require significant interconnectivity between pages or site sections, like those required by higher education. 

Here are some factors to consider when choosing between the two content management systems. 

Complex Architecture

If you’re setting out to redesign a higher ed website, you’re likely looking at a fairly complex endeavor. Your website probably requires more complicated architecture than most; you’ll need various sections that are targeted toward different groups of users, such as prospective students, current students, alumni, faculty, and staff. 

Drupal’s ecosystem was built around cases like these. It can handle thousands of users and different content types. Upgrades in Drupal 8 have also resulted in better caching features that make for improved page load times. 

WordPress works well for general, standalone marketing sites, but it will struggle with aspects like multiple install profiles, content sharing networks, consistency, maintainability, and connectivity with other parts of the site.

Users and Permissions

Your website also most likely has extensive user and permission requirements. Different groups will need to perform different tasks and interact with the site in a variety of ways. You may also have different departmental sites that will need to be managed by different teams while staying consistent with branding guidelines.  

Drupal allows for multi-site functionality that can also be centrally managed. Different users and departments can be given diverse permissions and roles so that you can limit their capabilities to just what they need and nothing more.

Security

No CMS is completely immune to security vulnerabilities. It’s possible that WordPress has had more security issues in the past simply due to the fact that it’s a more widely used CMS. WordPress relies heavily on plugins when used for more complex websites, and these plugins are often susceptible to security issues. 

Drupal is well known as a very secure content management system and is trusted by WhiteHouse.gov and other federal government sites. Drupal has a dedicated security team that receives security issues from the general public and coordinates responses. Issues are resolved as quickly as possible and users are alerted to vulnerabilities through regular announcements. The security team also provides documentation on how to write secure code and how to secure your site. With these practices, you can rest assured that all of your student and faculty data would be protected. 

Ease of Use

For simpler sites, WordPress beats Drupal when it comes to ease of use. Because it was developed for less complex, standalone websites, it’s very easy to get it up and running, even for those who aren’t very tech savvy. Drupal’s complexity means it has a steep learning curve and takes longer to build. 

Drupal is a feature-rich CMS that can build more advanced sites, but it also requires more technical experience. You need a team of experts with ample experience to get your project accomplished, and this is likely to be more expensive than a team of WordPress developers. 

But the extra price that you pay for a team of experts will pay off in the end when you have a website that is capable of doing everything you need it to. Drupal's high barrier to entry with respect to module development also means the quality of modules available is higher, and the choices are fewer but more obvious. 

Which Should You Choose?

When it comes down to it, Drupal is likely the better choice between the two. It’s clear that while WordPress has its strengths, Drupal is a better choice for more advanced sites, like those required by higher education.

Drupal provides a strong base to begin rapidly building a complex system. It’s often the CMS of choice for large websites that require significant interconnectivity between different sections. It also allows for a wide range of user roles and permissions, and security is a priority for the entire community. All of these aspects make it a great CMS choice for higher education websites.
 

Jun 13 2017
Jun 13

Computers are finicky. As stable and reliable as we would like to believe they have become, the average server can cease to function for hundreds of different reasons. Some of the common problems that cause websites or services to crash can’t really be avoided. If you suddenly find your site suffering from a DDOS attack or a hardware failure, all you can do is react to the situation.
 
But there are many simple things that are totally preventable that can be addressed proactively to ensure optimal uptime. To keep an eye on the more preventable issues, setting up monitoring for your entire stack (both the server as well as the individual applications) is helpful. At Zivtech, we use a tool called Sensu to monitor potential issues on everything we host and run.
 
Sensu is a Ruby project that operates by running small scripts to determine the health of a particular application or server metric. The core project contains a number of such scripts called “checks.” It’s also very easy to write custom checks and they can be written in any language, thus allowing developers to easily monitor new services or applications. Sensu can also be run via a client server model and issue alerts to members of the team when things aren’t behaving properly.

Server checks

As a general place to start, you should set up basic health checks for the server itself. The following list gives you a good set of metrics to keep an eye on and why it is in your best interest to do so.

RAM

What to check

Monitor the RAM usage of the server versus the total amount of RAM on the server.

Potential problem monitored

Running out of RAM indicates that the server is under severe load and application performance will almost certainly be noticeable to end users.

Actions to take

Running low on RAM may not be a problem if it happens once or twice for a short time. Sometimes there are tasks that require more resources and this may not cause problems, but if the RAM is perpetually running at maximum capacity, then your server is probably going to be moving data to swap space (see swap usage below) which is much slower than RAM. 

Running near the limits of RAM constantly is also a sign that crashes are eminent since a spike in traffic or usage is surely going to require allocating resources that the server simply doesn’t have. Additionally, seeing spikes in RAM usage may indicate that a rogue process or poorly optimized code is running, which helps developers address problems before your users become aware of them.

Linux swap usage

What to check

Check swap usage as a percentage of the total swap space available on a given server.

Potential problem monitored

When the amount of available RAM is running short or the RAM is totally maxed out, Linux moves data from RAM to the hard drive (usually in a dedicated partition). This hard drive space is known as swap space. 
 
Generally, you don’t want to see too much swap space being used because it means that the available RAM isn’t enough to handle all the tasks the server needs to perform. If the swap space is filled up completely, then it means that RAM is totally allocated and there isn’t even a place on disk to dump extra data that the system needs. When this happens, the system is probably close to a crash and some services are probably unresponsive. It can also be very hard to even connect to a server that is out of swap space as all memory is being used completely at this point and new tasks must wait to run.

Actions to take

If swap is continually running at near 100% allocation, it probably means the system needs more RAM, and you’d want to increase the swap storage space as part of this maintenance. Keeping an eye on this will help ensure you aren’t under-allocating resources for certain machines or tasks.

Disk space

What to check

Track current disk space used versus the total disk space on the server’s hard drives, as well as the total inodes available on the drives.

Potential problem monitored

Running out of disk space is a quick way to kill an application. Unless you have painstakingly designed your partitions to prevent such problems (and even then you may not be totally safe), when a disk fills up some things will cease working. 
 
Many applications write files to disk and use the drive to store temporary data. Backup tasks rely on disk space as do logs. Many tasks will cease functioning properly when a drive or partition is full. On a website running Drupal, a full drive will prevent file uploads and can even cause CSS and JavaScript to stop working properly as well as data not being persisted to the database.

Actions to take

If a server is running low on space, it is relatively easy to add more. Cloud hosting providers usually allow you to attach large storage services to your running instance and if you use traditional hardware, drives are easy to upgrade. 
 
You might also discover that you’ve been storing data you don’t need or forgot to rotate some logs which are now filling up the drive. More often than not, if a server is running out of space, it is not due to the application actually requiring that space but an error or rogue backup job that can be easily rectified.

CPU

What to check

Track the CPU usage across all cores on the server.

Potential problem monitored

If the CPU usage goes to 100% for all cores, then your server is thinking too hard about something. Usually when this happens for an extended period of time, your end users will notice poor performance and response times. Sites hosted on the server might become unresponsive or extremely slow.

Action to take

In some cases, an over-allocated CPU may be caused by a runaway processes but if your application does a lot of heavy data manipulation or cryptography, it might be an indication that you need more processing power. 
 
When sites are being scraped by search providers or attacked by bots in some coordinated way, you might also see associated CPU spikes. So this metric can tip you off to a host of issues including the early stages of a DDoS attack on the server. You can respond by quickly restarting processes that are misbehaving and blocking potentially harmful IPs, or identify other performance bottlenecks.

Reboot required

What to check

Linux servers often provide an indication that they should be rebooted, usually related to security upgrades.

Potential problem monitored

Often after updating software, a server requires a reboot to ensure critical services are reloaded. Until this is done, the security updates are often not in full effect.

Action to take

Knowing that a server requires a reboot allows your team to schedule downtime and reduce problems for your end users.

Drupal specific checks

Zivtech runs many Drupal websites. Over time we have identified some metrics to help us ensure that we are always in the best state for security, performance, search indexes, and content caching. Like most Drupal developers, we rely on drush to help us keep our sites running. We have taken this further and integrated drush commands with our Sensu checks to provide Drupal specific monitoring.

Drupal cron

What to check

Drupal’s cron function is essential to the health of a site. It provides cleanup functions, starts long running tasks, processes data, and many other processes. Untold numbers of Drupal’s contributed modules rely on cron to be running as well.

Potential problem monitored

When a single cron job fails, it may not be a huge problem. But the longer a site exists without a successful cron run, the more problems you are likely to encounter. Services start failing without cron. Garbage cleanup, email notifications, content updates, and indexing of search content all need cron runs to complete reliably.

Action to take

When a cron job fails, you’ll want to find out if it is caused by bad data, a poorly developed module, permissions issues, or some other issue. Having a notification about these problems will ensure you can take proactive measures to keep your site running smoothly.

Drupal security

What to check

Drupal has an excellent security team and security processes in place. Drush can be used to get a list of modules or themes that require updates for security reasons. Generally, you want to deploy updates as soon as you find out about them.

Potential problem monitored

By the time you’ve been hacked, it’s too late for preventative maintenance. You need to take the security of your site’s core and contributed modules seriously. Drupal can alert site administrators via email about security alerts, but moving these checks into an overarching alerting system with company wide guidelines about actions to take and a playbook for how to handle them will result in shorter times that a given site is vulnerable.

Action to take

Test your updates and deploy them as quickly as you can.

Be Proactive

It’s difficult to estimate the value of knowing about problems before they occur. As your organization grows, it becomes more and more disruptive to be dealing with emergency issues on servers. The stress of getting a site back online is exponentially more than the stress of planned downtime.

With a little bit of effort, you can detect issues before they become problems and allocate time to address these without risking the deadlines for your other projects. You may not be able to avoid every crash, but monitoring will enable you to tackle certain issues before they disrupt your day and will help you keep your clients happy.
 

Jun 08 2017
Jun 08

It’s no secret that Drupal is incredibly powerful when it comes to its capabilities as a content management system. Many businesses choose Drupal not only because of the lower cost that comes with it being open source, but also because it can be customized to build out the exact features that they need. But how does it stack up for the content editors?

At Zivtech, we recently launched our new Drupal 8 site. As a member of the marketing team, I spend a significant amount of time writing and editing our site’s content, whether that’s static services page content, upcoming events, or new blog posts. Needless to say, I want the experience to be intuitive, very user-friendly, and headache free. And I definitely don’t want to have to bother our developers with questions about where to find things or how to make edits.

Drupal 8 has seen improvements in a lot of areas when compared to Drupal 7, and content editing is no exception. Here are some of my favorite content editing improvements in Drupal 8.

A WYSIWYG is Included in Core

Drupal is comprised of its core codebase, and then thousands of modules that can be added for custom functionality. A WYSIWYG (meaning “what you see is what you get”) is used to provide standard text editing options when adding content across an entire site, and used to require separate module installation in Drupal 7.

WYSIWYG

WYSIWYGs are useful for a number of reasons. A key objective when using a CMS is that the content will always come out looking uniform. Fonts, sizes, headings, and colors should always be consistent. A uniform site looks cohesive and makes sense. If you have the option to choose a size, font, and color for each specific post, each individual post may look fine, but the site as a whole will look chaotic. You can provide users with all the options that they need in about fifteen buttons. 
 
The WYSIWYG CKEditor was finally added to Drupal core with the release of Drupal 8, which is a huge improvement. You no longer need to install a separate module for this functionality.

Resizing Images is as Easy as Pie

Adding images to blog posts used to be a bit of a struggle for me because I couldn’t resize them once I uploaded them into the body of the post. Our new D8 site allows me to easily drag the corner of an image to resize. This is a major time saver and also no longer makes me want to pull my hair out.

Resizing ImagesI resized this image of an image. It was super easy.

Quicker Edits with Quick Edits

Drupal 8 also offers the option for quick editing. This means that content editors no longer have to navigate to the node edit page to make a quick change. Edits can be made directly from the view of the content.

User Roles and Permissions (Still)

While it’s not new with Drupal 8, user roles and permissions are still worth mentioning. Drupal offers the ability to pick and choose which site users get which types of permissions. This means you can restrict access to less tech savvy people so that they don’t accidentally break something. Content editors can just worry about editing content. 

Frustrated by your own content editing experience? Get in touch with us about a switch to Drupal 8.

Dec 20 2016
Dec 20

War Child UK describes itself as “a small charity that protects children living in some of the world's most dangerous war zones”. Founded in 1993, the charity works with vulnerable children and communities in war torn areas; providing safe spaces, access to education, skills training and much more to ensure that children’s lives are not torn apart by war.

War Child International has multiple offices all over the world, protecting, educating, and empowering marginalised children.

The Short Brief

The UK team came to us with a mission: to get a new site live as soon as possible. They’d done the planning and got the design; we needed to implement it quickly.

The previous War Child UK site wasn’t responsive, so they felt there were missing many donation opportunities from supporters on mobile and tablet devices. They also wanted a bold new design, with a high focus on imagery, for the highest possible impact and to create empathy.

From a Content Management System (CMS) point of view, they wanted to rationalise and consolidate content types, so the site could be easily managed without large overheads. Every penny counts for charities, and the website should enable them to get information and campaigns out quickly and easily, without a large website team or dependency upon external agents.

The original site also integrated with Stripe and Salesforce, and they wanted to ensure this functionality remained to provide a seamless experience for their donors, and reduce the need for internal training on the new site.

They also had a deadline: they wanted the have the new site up and running in time for a new donation drive for Christmas.

We sat down and crunched some numbers. We calculated that we could have one three week sprint before we had to deploy to live. We got to work.

‘good enough and live’ is better than perfect but in development for months.


How?

So, that was our mission: To build and launch a Minimum Marketable Product (MMP) with donations, and a simplified CMS in a single three week sprint. It had to be a polished product that would serve them during one of their busiest periods, without a loss of critical functions, such as donations. A MMP achieves the earliest possible route to market and therefore brings benefits sooner without cutting corners. With a tight deadline this approach was right.

Their previous site was Drupal, which we have a lot of experience with. There are many pre-existing modules available, such as Stripe and Salesforce that meant we could produce what they needed without much customization, which freed the team up to focus on providing the best site we could

We knew we had to get things right first time - we didn’t have time for cycles of iterations or lots of bugs back from the client. We always aim for right first time, but with this deadline it was imperative. We started writing Acceptance Criteria.

Warchild-iPad.jpg

Acceptance Criteria is a method of writing out conditions that the software must meet to be accepted by the client, or users, or other stakeholders. They’re written in non-technical terms, using terms specific to the business or organisation in question. They are the one version of the truth of what we’re building, understood and signed off by the lead developer, the QA person, and the client.

The acceptance criteria combined with the designs meant we had a clear vision of what each piece of functionality should do and look like before we started work, and the client knew what to expect from our work before seeing it.

The client was on board with the MMP model, realising that:good enough and live’ is better than perfect but in development for months.We started planning the next two sprints while development work was happening on the first sprint, so War Child’s stakeholders had continued visibility of what was future work was, and access to a backlog for long term future planning.

[embedded content]

The small number of essential features meant we could still be flexible in what we offered in the first sprint - even bringing in small features from the backlog when we realised it would be useful for go live and that it would fit in our time scales.

We learned a lot from this small, fast project: that an MMP site is possible in weeks not months, but that requires forward planning, flexibility, and buy-in from all members of the team. We learned a lot technologically as well, integration with Stripe and Salesforce and customising it for War Child UK’s set up.

blog-warchild-mobile.jpg

War Child UK now have in place a mobile donation platform underpinned by a powerful Drupal CMS. This is just the beginning. Thanks to Drupal’s extensibility and with our Agile process there are a series of additional features in the pipeline, all aimed at placing War Child in a better place to help children in crisis.

War Child UK now have in place a mobile donation platform underpinned by a powerful Drupal CMS. This is just the beginning. Thanks to Drupal’s extensibility and with our Agile process there are a series of additional features in the pipeline, all aimed at placing War Child in a better place to help children in crisis.

Mosul appeal: War Child have a team on the ground right now providing safe spaces and emergency care for 6,000 boys and girls who have fled the city.

Read the full case study

Nov 15 2016
Nov 15

This post is the second in a series covering Zivtech's usage of Gulp for front-end development in Drupal 8.

In the last post, I covered how to setup Gulp for teamwork on Drupal 8 projects. In this post, I'll go over how to get started with writing Gulp tasks. I'll also break down a specific task for Sass linting to ensure good code quality.

Maintainable and Readable Gulp tasks

With any mid-to-large sized Drupal 8 theme, it's really easy for the main Gulp file (gulpfile.js) become unwieldy and complex. With dozens of tasks doing all kinds of automated work, before too long, gulpfile.js becomes a soup of illegible code.

Additionally, members of your team might have different ways of naming Gulp tasks. One person might write a Sass building task called "buildSass" and another might create an identical task called "css."

It'd be nice to strip down gulpfile.js, make it readable, and somehow compartmentalize each task separately. Also, we want to cut down on task naming variations and create a unified system for structuring our tasks.

My current favorite way to handle these wishes is gulp-require-tasks. Basically, each task is written as an individual, CommonJS style module. Then, the tasks are arranged in directories, and that directory structure defines the task name. It is a very simple and predictable way to setup Gulp tasks.

Structuring Gulp tasks

Start off by creating the file tree structure below:

├── project/ │ ├── .gitignore (ignore node_modules, gulpfile.yml) │ ├── package.json │ ├── gulpfile.js │ ├── default.gulpfile.yml │ ├── sass │ │ ├── styles.scss │ ├── js │ │ ├── scripts.js │ ├── gulp-tasks │ │ ├── styles │ │ │ ├── lint.js │ │ │ ├── build.js │ │ ├── scripts │ │ │ ├── lint.js │ │ │ ├── build.js

The YAML settings file, default.gulpfile.yml, was discussed in the last post of this series, if you need a refresher.

gulp-require-tasks lets these tasks be accessible according to their structure. For example, to build the styles, you'll run "gulp styles:build" and to lint the JavaScript, you'll run "gulp scripts:lint." If you don't like the colon delimiter, you can change that too.

Update Gulp settings

In the last post we started the default.gulpfile.yml, and now we'll edit that same file to add in settings for the Gulp tasks we'll create in this project.

Open the file: it should look like this:

themeName: "myTheme" themeDescription: "myTheme description"

Expand on that by adding settings for source and destination paths of Sass and JS:

themeName: "myTheme" themeDescription: "myTheme description" styles: src: "sass//*.scss", dest: "css" lint: enabled: true failOnError: false scripts: src: "js//*.js", lint: enabled: true failOnError: false

Under the "styles" and "scripts" sections of the YAML, you can see I added some linting options too. From within the YAML settings, people can enable or disable linting, and also decide if they want the Gulp process to stop when linting errors are detected.

Pulling these settings out of the Gulp tasks themselves and into this YAML file means that developers don't have to search through the tasks looking for settings to change. Instead, they have every setting exposed to them in this one, concise file.

Importing tasks for Gulp

We haven't written any Gulp tasks yet, but we can go ahead and setup importing them so they can be used.

Open up the gulpfile.js we started in the last post. It should look like this:

(function () { 'use strict'; var gulp = require('gulp'); var yaml = require('js-yaml'); var fs = require('fs'); var assign = require('lodash.assign'); // read default config settings var config = yaml.safeLoad(fs.readFileSync('default.gulpfile.yml', 'utf8'), {json: true}); try { // override default config settings var customConfig = yaml.safeLoad(fs.readFileSync('gulpfile.yml', 'utf8'), {json: true}); config = assign(config, customConfig); } catch (e) { console.log('No custom config found! Proceeding with default config only.'); } })();

If you recall, we loaded the default.gulpfile.yml and overrode that with any settings from gulpfile.yml if it exists. The gulpfile.yml file has the exact same structure has default.gulpfile.yml, but settings can have different values. This lets other developers on the team override some settings if needed.

At this point in gulpfile.js, the config is loaded and ready to be used. Next, we integrate gulp-require-tasks.

(function () { 'use strict'; var gulp = require('gulp'); var yaml = require('js-yaml'); var fs = require('fs'); var assign = require('lodash.assign'); var gulpRequireTasks = require('gulp-require-tasks'); // read default config settings var config = yaml.safeLoad(fs.readFileSync('default.gulpfile.yml', 'utf8'), {json: true}); try { // override default config settings var customConfig = yaml.safeLoad(fs.readFileSync('gulpfile.yml', 'utf8'), {json: true}); config = assign(config, customConfig); } catch (e) { console.log('No custom config found! Proceeding with default config only.'); } gulpRequireTasks({ path: process.cwd() + '/gulp-tasks', arguments: [config] }); })();

Setting up gulp-require-tasks is super easy. We tell it where our gulp tasks are located, in the "gulp-tasks" directory.

Then, to each module (i.e. 1 module will be 1 Gulp task) in the directory, gulp-require-tasks passes arguments to each task. The first argument is always gulp itself. The "arguments" setting for gulp-require-tasks is an array of other things you want to pass to each module. I've opted to pass in "config," which is the object representing the settings merge in the YAML files.

This is essentially all you need in gulpfile.yml. However, I also like to add shortcut tasks too, that combine other tasks for quicker use. For example, general "build" and "lint" tasks might be like this:

gulp.task('build', ['styles:build', 'scripts:build']); gulp.task('lint', ['styles:lint', 'scripts:lint']);

Modular Gulp tasks

Let's start off creating the Sass linting task. To help with this, I recommend using gulp-sass-lint. You'll want to read over how to setup sass-lint, which I won't cover in detail here. Essentially, you create a .sass-lint.yml file in the root of the project. That file contains all the rules you want to validate; for example, should developers avoid styling with IDs or should they use RGB rather than HEX values for colors.

After sass-lint rules are in place, open up the styles linting file. Here you'll see the guts of the linting task:

'use strict'; var cached = require('gulp-cached'); var sassLint = require('gulp-sass-lint'); var gulpif = require('gulp-if'); module.exports = function (gulp, options) { if (options.styles.lint.enabled) { return gulp.src(options.styles.src) .pipe(cached('styles:lint')) .pipe(sassLint()) .pipe(sassLint.format()) .pipe(gulpif(options.styles.lint.failOnError, sassLint.failOnError())); } else { return console.log('css linting not enabled'); } };

For the three required packages, you'll want to "npm install" them of course. Don't forget the "--save-dev" flag to get those packages stored in package.json!

The bulk of the code exists within the standard, CommonJS "module.exports" directive. A Gulp process is passed into the task as well as the set of options from default.gulpfile.yml.

We start off by running a quick if/else check so that we short-circuit out of this task if the user disabled Sass linting. Then, we pipe in the files that we selected in the Gulp settings' "styles.src" section. Files are then piped through gulp-cached, which keeps a list of the source files (and contents!) in memory. This makes the task faster.

Next, the styles are linted and the results are formatted and reported out to the console. Finally, we use gulp-if to determine if the Gulp process gets terminated now should there be linting errors.

The sky's the limit

I leave it as an exercise for the reader to go about developing the other Gulp tasks. In the next post, I'll go over some other, more complicated Gulp tasks to show more advanced usage. Until then, you're more than welcome to look over and reference our own Gulp tasks we publish for Bear Skin.

Posts in this series

  1. Use Gulp for Drupal 8 with Teams, Part 1: Gulp Setup
  2. Use Gulp for Drupal 8 with Teams, Part 2: Creating tasks
Oct 26 2016
Oct 26

Gulp is a mainstay of front-end development nowadays. Of course, like all front-end development tools, there is a massive proliferation of build systems, from Webpack to SystemJS and Grunt to Gulp. Yet, we at Zivtech find ourselves using mostly Gulp, particularly when dealing with Drupal 8 projects.

This article is the first of a series of posts where I outline how Zivtech uses Gulp. In this first part, I'll talk about our reasoning and setup process.

Why does Zivtech use Gulp for Drupal 8?

The choice of Gulp over other front end tools is due to how Drupal utilizes front-end assets. It's perfectly fine to use something like Webpack or Browserify with Drupal, but those all-encompassing, "build and combine all the things!" systems are best used for projects that don't have a built-in asset pipeline. For example, Drupal concatenates and minifies CSS and JS for us, and it's really just over-compiling (is that a word?) to use something that Drupal obviates.

Also, we use Gulp over Grunt or even Broccoli (because yes, that's a thing too) strictly because Zivtech does a lot of node.js development as well. The concept of streams and buffers in Gulp are used throughout node.js, and it makes sense that we'd align with our other development.

Many projects and distributed teams

As a client services company, Zivtech has many projects and several teams working on projects. Thus, our building tasks have to be somewhat abstract so as to apply to most situations. So the first step to conquering the Gulp pipeline is figuring out a way to make the tasks themselves static, but let the configuration remain changeable.

Some examples of these changeable settings include: the website address that Browsersync should proxy when watching your development. It's possible that this website address could change on a per-user basis too. Also, the website name would change on a per-site basis too.

Within each project, we could just alter the Gulp tasks directly to account for these differences. Yet some people on the team may not be too familiar with Gulp and you might be sending them into the weeds trying to suss out "that one weird setting" they should change.

At this point you might be thinking we should make a settings file for each project's Gulp tasks, and you'd be correct if so! The Gulp tasks remain the same, but the settings always change.

As it turns out, Drupal 8 has a preferred method for settings files: the YAML format. Being a flexible guy, I vote for just sticking with what the system wants. Thus, our new settings files will be written in YAML.

Using YAML for Gulp settings

First, let's think about how we're going to implement settings from a big picture perspective. We've already determined that we'll work in YAML and we'll have a default group of configuration settings available. We also want each member of the team to be able to override some settings to fit their situations.

It makes sense that we'll have a file called default.gulpfile.yml for the default settings. Gulp should merge another file, we'll call it gulpfile.yml, on top of the default. The default settings get tracked in Git or your chosen version control system, but the other one should not. This allows for complete flexibility of any setting you or one of your teammates might want.

In default.gulpfile.yml, start off by creating some basic settings:

themeName: "myTheme" themeDescription: "myTheme description"

Next, create a gulpfile.yml to contain your customized settings:

themeName: "myRenamedTheme"

When Gulp runs, the themeDescription setting should match default, but the themeName setting should be overridden.

Finally, in your gulpfile.js:

(function () { 'use strict'; var gulp = require('gulp'); var yaml = require('js-yaml'); var fs = require('fs'); var assign = require('lodash.assign'); // read default config settings var config = yaml.safeLoad(fs.readFileSync('default.gulpfile.yml', 'utf8'), {json: true}); try { // override default config settings var customConfig = yaml.safeLoad(fs.readFileSync('gulpfile.yml', 'utf8'), {json: true}); config = assign(config, customConfig); } catch (e) { console.log('No custom config found! Proceeding with default config only.'); } })();

Now, when you run any Gulp task, your config files will get merged by lodash. One day, Object.assign will be more widely available, and lodash won't be needed any longer. For now, things work fine this way.

You'll notice that loading the custom config is in a try ... catch block. We do that so there are no show-stopping errors if the custom config is not found. Additionally, if it's not found we can let the user know that only default settings are in use.

Wrapping up

Well, this has been a high-level explanation of how and why we use Gulp at Zivtech for D8 projects.

In the coming articles in this series, I'll expand on the simple gulpfile.js and default.gulpfile.yml files started. I plan to outline our process for linting and compiling CSS, linting and compiling JavaScript, and a couple extra tasks too, like integrating Bower and favicon generation. Until then!

Posts in this series

  1. Use Gulp for Drupal 8 with Teams, Part 1: Gulp Setup
  2. Use Gulp for Drupal 8 with Teams, Part 2: Creating tasks
Oct 26 2016
Oct 26

One of my biggest pet-peeves is creating Drupal 7 empty menu link titles since there’s no out-of-the-box solution. As a result it can be difficult to create stylized links, such as icons or background images. After many frustrating sessions I finally sat down to find a way to make this happen. Consequently, I began to think this was an impossibility and was unable to find a solution already in existence that did exactly what I needed it to do. However, Drupal 7 empty menu link titles are absolutely possible with just this one little snippet! Have no fear, theme_menu_link to the rescue!

Using <none> to Create Drupal 7 Empty Menu Link Titles

drupal 7 empty menu link titles

drupal 7 empty menu link titles

First of all, you must start by using the snippet provided below and will need to enter <none> as the link title in order to render it empty. To accomplish this, in your theme’s template.php file add:

/**
 * Implements theme_menu_link().
 *
 * @link https://api.drupal.org/api/drupal/includes!menu.inc/function/theme_menu_link/7.x
 */
function your_theme_menu_link($vars)
{
  $element = $vars['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }

  if ( '<none>' === $element['#title'] )
  {
    $element['#title'] = '';
  }

  $output = l($element['#title'], $element['#href'], $element['#localized_options']);

  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}

theme_menu_link returns HTML for menu and submenu links, so that it can be used to alter the menu’s output. In the above, we’re checking to see if the menu link title has been set to <none>. If this has been done correctly it removes the title text while leaving the link intact. Be sure to check your work before moving on because sometimes the simplest mistakes in the beginning will cause you grief in the future.

Finally, be sure to clear your cache if you’re not seeing the change!

Have you already added this snippet and yet not seen anything change? It’s probably due to Drupal not yet seeing the new hook in your code. In order to fix this, you’ll need to clear your cache so that Drupal will register the changes you’ve made. Most of the time, this will fix issues like these quickly rather than spending hours trying to debug something that truly isn’t broken.

You can also use this hook to alter other menu link attributes. For instance, if you wanted to avoid using the Menu attributes module you’re able to use this hook to add or remove classes.

For more information on theme_menu_link, see https://api.drupal.org/api/drupal/includes!menu.inc/function/theme_menu_link/7.x.

Is there a Drupal module that can handle this?

Of course there is! Icon API accomplishes this in addition to some extra features you may find useful. I’ve never used it personally, and I’d rather stay away from modules that don’t produce production releases. Consequently, if you have created or know of a module that can handle this feel free to shoot me a line in the comments below and I’ll gladly take a look at it to potentially include in this post as a footnote. In conclusion, don’t ever believe something is impossible because you’re often just a few days of banging your head against the wall away from a breakthrough!

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

May 16 2016
May 16

With the release of Drupal 8 comes the new CLI to generate boilerplate code, interact and debug Drupal (for earlier versions of Drupal, see drush-related coder module tools). The transition from drush to drupal can be a little bit frustrating learning the new commands. To help ease the stress, I’ve put together a list of the most common Drupal 8 Console commands.

Drupal 8 Console Commands

Drupal 8 Console has been designed to facilitate the Drupal 8 adoption while making development and interaction more efficient and enjoyable. Use the cheat sheet below will help you hit the ground running with Drupal Console.

Drupal 8 Console: Cache Commands

# Rebuild and clear all site caches.
$ drupal cache:rebuild

# Rebuilds all caches
$ drupal cr all

# Rebuild discovery cache
$ drupal cr discovery

Drupal 8 Console: Module Commands

# Display current modules available for application
$ drupal module:debug

# Download module or modules in application
$ drupal module:download

# Install module or modules in the application
$ drupal module:install

# Uninstall module or modules in the application
$ drupal module:uninstall

Drupal 8 Console: Image Commands

# List image styles on the site
$ drupal image:styles:debug

# Execute flush function by image style or execute all flush images styles
$ drupal image:styles:flush

Drupal 8 Console: User Commands

# Displays current users for the application
$ drupal user:debug

# Delete users for the application
$ drupal user:delete

# Clear failed login attempts for an account.
$ drupal user:login:clear:attempts

# Returns a one-time user login url.
$ drupal user:login:url

# Generate a hash from a plaintext password.
$ drupal user:password:hash

# Reset password for a specific user.
$ drupal user:password:reset

Drupal 8 Console: Generate Commands

# Generate an Authentication Provider
$ drupal generate:authentication:provider

# Generate commands for the console.
$ drupal generate:command

# Generate & Register a controller
$ drupal generate:controller

# Generate the DrupalConsole.docset package for Dash
$ drupal generate:doc:dash

# commands.generate.doc.data.description
$ drupal generate:doc:data

# Generate documentations for Commands
$ drupal generate:doc:gitbook

# Generate a new content type (node / entity bundle)
$ drupal generate:entity:bundle

# Generate a new config entity
$ drupal generate:entity:config

# Generate a new content entity
$ drupal generate:entity:content

# Generate an event subscriber
$ drupal generate:event:subscriber

# Generate a new "FormBase"
$ drupal generate:form

# Generate an implementation of hook_form_alter() or hook_form_FORM_ID_alter
$ drupal generate:form:alter

# Generate a new "ConfigFormBase"
$ drupal generate:form:config

# Generate a module.
$ drupal generate:module

# Generate module permissions
$ drupal generate:permissions

# Generate a plugin block
$ drupal generate:plugin:block

# Generate CKEditor button plugin.
$ drupal generate:plugin:ckeditorbutton

# Generate a plugin condition.
$ drupal generate:plugin:condition

# Generate field type, widget and formatter plugins.
$ drupal generate:plugin:field

# Generate field formatter plugin.
$ drupal generate:plugin:fieldformatter

# Generate field type plugin.
$ drupal generate:plugin:fieldtype

# Generate field widget plugin.
$ drupal generate:plugin:fieldwidget

# Generate image effect plugin.
$ drupal generate:plugin:imageeffect

# Generate image formatter plugin.
$ drupal generate:plugin:imageformatter

# Generate a plugin mail
$ drupal generate:plugin:mail

# Generate plugin rest resource
$ drupal generate:plugin:rest:resource

# Generate a plugin rule action
$ drupal generate:plugin:rulesaction

# Generate a plugin type with annotation discovery
$ drupal generate:plugin:type:annotation

# Generate a plugin type with Yaml discovery
$ drupal generate:plugin:type:yaml

# Generate a custom plugin view field.
$ drupal generate:plugin:views:field

# Generate a profile.
$ drupal generate:profile

# Generate a RouteSubscriber
$ drupal generate:routesubscriber

# Generate service
$ drupal generate:service

# Generate a theme.
$ drupal generate:theme

Drupal 8 Console: Cron Commands

# List of modules implementing a cron
$ drupal cron:debug

# Execute cron implementations by module or execute all crons
$ drupal cron:execute

# Release cron system lock to run cron again
$ drupal cron:release

Drupal 8 Console: Theme Commands

# Displays current themes for the application
$ drupal theme:debug

# Download theme in application
$ drupal theme:download

# Install theme or themes in the application
$ drupal theme:install

# Uninstall theme or themes in the application
$ drupal theme:uninstall

Drupal 8 Console: Views Commands

# Display current views resources for the application
$ drupal views:debug

# Disable a View
$ drupal views:disable

# Enable a View
$ drupal views:enable

# Display current views plugins for the application
$ drupal views:plugins:debug

Drupal 8 Console: Translation Commands

# Clean up translation files
$ drupal translation:cleanup

# Determine pending translation string in a language or a specific file in a language
$ drupal translation:pending

# Generate translate stats
$ drupal translation:stats

# Sync translation files
$ drupal translation:sync

Drupal 8 Console: Site Commands

# List all known local and remote sites.
$ drupal site:debug

# Import/Configure an existing local Drupal project
$ drupal site:import:local

# Install a Drupal project
$ drupal site:install

# Switch site into maintenance mode
$ drupal site:maintenance

# Switch system performance configuration
$ drupal site:mode

# Create a new Drupal project
$ drupal site:new

# Show the current statistics of website.
$ drupal site:statistics

# View current Drupal Installation status
$ drupal site:status

Drupal 8 Console: Database Commands

# Launch a DB client if it's available
$ drupal database:client

# Shows DB connection
$ drupal database:connect

# Drop all tables in a given database.
$ drupal database:drop

# Dump structure and contents of a database
$ drupal database:dump

# Remove events from DBLog table, filters are available
$ drupal database:log:clear

# Display current log events for the application
$ drupal database:log:debug

# Restore structure and contents of a database.
$ drupal database:restore

# Show all tables in a given database.
$ drupal database:table:debug

Drupal 8 Console: Create Commands

# Create dummy comments for your Drupal 8 application.
$ drupal create:comments

# Create dummy nodes for your Drupal 8 application.
$ drupal create:nodes

# Create dummy terms for your Drupal 8 application.
$ drupal create:terms

# Create dummy users for your Drupal 8 application.
$ drupal create:users

# Create dummy vocabularies for your Drupal 8 application.
$ drupal create:vocabularies

Drupal 8 Console: Miscellaneous Commands

# Display basic information about Drupal Console project
$ drupal about

# Chain command execution
$ drupal chain

# System requirement checker
$ drupal check

# Displays help for a command
$ drupal help

# Copy configuration files to user home directory.
$ drupal init

# Lists all available commands
$ drupal list

# Update project to the latest version.
$ drupal self-update

# Runs PHP built-in web server
$ drupal server

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Mar 22 2016
Mar 22

Alan Stanley taught me this trick at an Islandora Camp a few years ago, and when trying to remember it this morning I messed up one critical piece. So I’ll post it here so I have something to refer back to when I need to do this again.

The Drupal Devel module includes a menu item for executing arbitrary PHP code on the server. (This is, of course, something you want to set permissions on very tightly because it can seriously wreck havoc on your day if someone uses it to do bad things.) Navigate to /devel/php on your Islandora website (with the Devel module enabled), and you’ll get a nice, big &lg;textarea> and an “Execute” button:

Execute arbitrary PHP using Drupal Devel module.

Execute arbitrary PHP using Drupal Devel module.

In this case, I’m generating the TECHMD datastream using the FITS module and displaying the results of the function call on the HTML page using the Devel module’s dpm() function:

include drupal_get_path('module', 'islandora_fits') . '/includes/derivatives.inc';
$object= islandora_object_load('demo:6');
$results = islandora_fits_create_techmd($object, False, array('source_dsid' => 'OBJ'));
dpm($results);

include drupal_get_path('module', 'islandora_fits') . '/includes/derivatives.inc'; $object= islandora_object_load('demo:6'); $results = islandora_fits_create_techmd($object, False, array('source_dsid' => 'OBJ')); dpm($results);

Works like a charm!

Nov 19 2015
Nov 19

Need an array of user roles in your Drupal 8 site? Say goodbye to user_roles(), say hello to user_role_names().

This function will return an associative array with the role id as the key and the role name as the value.

/**
 * Retrieves the names of roles matching specified conditions.
 * @link https://api.drupal.org/api/drupal/core!modules!user!user.module/function/user_role_names/8
 */
function user_role_names($membersonly = FALSE, $permission = NULL) {
  return array_map(function($item) {
    return $item->label();
  }, user_roles($membersonly, $permission));
}

For more information, see https://api.drupal.org/api/drupal/core!modules!user!user.module/function/user_role_names/8.2.x.

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Nov 18 2015
Nov 18

Looking for how to create new module permissions in Drupal 8? Look no further, $module.permissions.yml to the rescue!

In Drupal 8 permissions are now defined in $module.permissions.yml file instead of using hook_permission().

Drupal 8 Static Permissions

Create a new file in the root of your module folder and name it my_module.permissions.yml.

# In my_module.permissions.yml file.
access all views:
  title: 'My module settings'
  description: 'A custom permission for your module settings page.'
  restrict access: TRUE

Drupal 8 Dynamic Permissions

In Drupal 8, you can support dynamic permissions by referencing a function that will dynamically define those permissions. This callback defines the permissions for core’s filter module.

# In filter.permissions.yml
permission_callbacks:
  - Drupal\filter\FilterPermissions::permissions
<?php
// in FilterPermissions.php

class FilterPermissions {
  public function permissions() {
    $permissions = [];
    // Generate permissions for each text format. Warn the administrator that any
    // of them are potentially unsafe.
    /** @var \Drupal\filter\FilterFormatInterface[] $formats */
    $formats = $this->entityManager->getStorage('filter_format')->loadByProperties(['status' => TRUE]);
    uasort($formats, 'Drupal\Core\Config\Entity\ConfigEntityBase::sort');
    foreach ($formats as $format) {
      if ($permission = $format->getPermissionName()) {
        $permissions[$permission] = [
          'title' => $this->t('Use the <a href="https://benmarshall.me/drupal-8-module-permissions//@url">@label</a> text format', ['@url' => $format->url(), '@label' => $format->label()]),
          'description' => String::placeholder($this->t('Warning: This permission may have security implications depending on how the text format is configured.')),
        ];
      }
    }
    return $permissions;
  }
}
?>

For more information, see https://www.drupal.org/node/2311427.

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Jul 15 2015
Jul 15

Regardless of industry, staff size, and budget, many of today’s organizations have one thing in common: they’re demanding the best content management systems (CMS) to build their websites on. With requirement lists that can range from 10 to 100 features, an already short list of “best CMS options” shrinks even further once “user-friendly”, “rapidly-deployable”, and “cost-effective” are added to the list.

There is one CMS, though, that not only meets the core criteria of ease-of-use, reasonable pricing, and flexibility, but a long list of other valuable features, too: Drupal.

With Drupal, both developers and non-developer admins can deploy a long list of robust functionalities right out-of-the-box. This powerful, open source CMS allows for easy content creation and editing, as well as seamless integration with numerous 3rd party platforms (including social media and e-commerce). Drupal is highly scalable, cloud-friendly, and highly intuitive. Did we mention it’s effectively-priced, too?

In our “Why Drupal?” 3-part series, we’ll highlight some features (many which you know you need, and others which you may not have even considered) that make Drupal a clear front-runner in the CMS market.

For a personalized synopsis of how your organization’s site can be built on or migrated to Drupal with amazing results, grab a free ticket to Drupal GovCon 2015 where you can speak with one of our site migration experts for free, or contact us through our website.

_______________________________

SEO + Social Networking:

Unlike other content software, Drupal does not get in the way of SEO or social networking. By using a properly built theme–as well as add-on modules–a highly optimized site can be created. There are even modules that will provide an SEO checklist and monitor the site’s SEO performance. The Metatags module ensures continued support for the latest metatags used by various social networking sites when content is shared from Drupal.

SEO Search Engine Optimization, Ranking algorithm

E-Commerce:

Drupal Commerce is an excellent e-commerce platform that uses Drupal’s native information architecture features. One can easily add desired fields to products and orders without having to write any code. There are numerous add-on modules for reports, order workflows, shipping calculators, payment processors, and other commerce-based tools.

E-Commerce-SEO-–-How-to-Do-It-Right

Search:

Drupal’s native search functionality is strong. There is also a Search API module that allows site managers to build custom search widgets with layered search capabilities. Additionally, there are modules that enable integration of third-party search engines, such as Google Search Appliance and Apache Solr.

Third-Party Integration:

Drupal not only allows for the integration of search engines, but a long list of other tools, too. The Feeds module allows Drupal to consume structured data (for example, .xml and .json) from various sources. The consumed content can be manipulated and presented just like content that is created natively in Drupal. Content can also be exposed through a RESTful API using the Services module. The format and structure of the exposed content is also highly configurable, and requires no programming.

Taxonomy + Tagging:

Taxonomy and tagging are core Drupal features. The ability to create categories (dubbed “vocabularies” by Drupal) and then create unlimited terms within that vocabulary is connected to the platform’s robust information architecture. To make taxonomy even easier, Drupal even provides a drag-n-drop interface to organize the terms into a hierarchy, if needed. Content managers are able to use vocabularies for various functions, eliminating the need to replicate efforts. For example, a vocabulary could be used for both content tagging and making complex drop-down lists and user groups, or even building a menu structure.

YS43P

Workflows:

There are a few contributor modules that provide workflow functionality in Drupal. They all provide common functionality along with unique features for various use cases. The most popular options are Maestro and Workbench.

Security:

Drupal has a dedicated security team that is very quick to react to vulnerabilities that are found in Drupal core as well as contributed modules. If a security issue is found within a contrib module, the security team will notify the module maintainer and give them a deadline to fix it. If the module does not get fixed by the deadline, the security team will issue an advisory recommending that the module be disabled, and will also classify the module as unsupported.

Cloud, Scalability, and Performance:

Drupal’s architecture makes it incredibly “cloud friendly”. It is easy to create a Drupal site that can be setup to auto-scale (i.e., add more servers during peak traffic times and shut them down when not needed). Some modules integrate with cloud storage such as S3. Further, Drupal is built for caching. By default, Drupal caches content in the database for quick delivery; support for other caching mechanisms (such as Memcache) can be added to make the caching lightning fast.

cloud-computing

Multi-Site Deployments:

Drupal is architected to allow for multiple sites to share a single codebase. This feature is built-in and, unlike WordPress, it does not require any cumbersome add-ons. This can be a tremendous benefit for customers who want to have multiple sites that share similar functionality. There are few–if any–limitations to a multi-site configuration. Each site can have its own modules and themes that are completely separate from the customer’s other sites.

Want to know other amazing functionalities that Drupal has to offer? Stay tuned for the final installment of our 3-part “Why Drupal?” series!

Jun 02 2015
Jun 02

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

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

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

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

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

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

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

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

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

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

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

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

The result?

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

May 29 2015
May 29

In the past four years there has been an explosion of new technologies in front-end development. We are inundated with new projects like Bower, Cucumber, Behat and KSS. It is a lot to take in. At the past two Drupalcons there have been sessions about this overload (Austin 2014, My Brain is Full: The state of Front-end developement). Essentially those sessions are asking “What the hell is going on?”

As John Albin pointed out in his 2015 DrupalCon presentation, Style Guide Driven Development: All hail the robot overlords!, being a front-end developer now means constantly learning. The pace at which front-end development is evolving is too much to keep up with. There’s not enough time to read about the latest tools and techniques, let alone implement them! What we need is someone — or something — to do most of the work for us, so we can focus on better development.

Everyone is describing the one little piece they’ve created, but don’t explain (or even reference!) the larger concepts of how all of these elements link together.

Frank Chimero, July 2014 Designer News AMA

So what big picture will help us understand today’s new front-end technologies? I’ve been doing front-end web development since 2007 (when building layouts with tables was the thing to do). Recently I realized that the current front-end flux is easily explainable as the beginning of a momental shift in web development: web development is embracing agile development. And the entire way we build websites is being turned inside out.

How does web development do agile? It creates styleguide-driven development (SGDD).

Styleguide-Driven Development (SGDD)

Styleguide-Driven Development (SGDD) is a practice that encourages the separation of UX, design & frontend from backend concerns. This is achieved by developing the UI separately in a styleguide. By separating the UI and backend tasks so they don’t rely on each other, it allows teams to iterate fast on prototypes and designs without having to make changes to the backend. With careful planning they should plug-and-play together nicely.

Styleguide-Driven Development isn’t just limited for big teams working on large applications, but the core concepts of developing UI elements separately in a style guide (living or static) can still benefit a sole developer working on a single page app.

The only requirements for styleguide-driven development are:

Front-end Technology Categories

We can categorize new front-end projects into just three categories:

  • Front-end Performance (make shit faster)
    The front-end is where you see most of the lag while browsing websites, so it is critical to focus in this area.
  • Components (make shit modular)
    Automation to ensure what you build today doesn’t break what you built yesterday.
  • Continuous Integration (Automate shit)
    A way of bundling reusable chunks of HTML, CSS, JavaScript and other assets.
NodeJS is an excellent example of a project that integrates all three. It’s web service is all about performance, incorporates packages that’s all about components and you build your project with a package.json to help automate things.

If you understand those three concepts, you can make sense of any of today’s new front-end technologies. There may be hundreds of new projects, but they are just different programming languages, different platforms, different projects and different APIs implementing one or more of those three ideas.

A core concept of agile development is reducing risk by controlling and minimizing your risk. One of the tools to prevent risk of regressions and minimize the risk of refactoring is continuous integration. While back-end developers and devops have been working on this for a while now, we are only now starting to see it in the front-end as those developers slowly get training in agile.

And to minimize complexity and risk of failure, front-end developers have started to develop components of HTML, CSS, and JS that are reusable and maintainable. Bootstrap? Foundation? Those are just pre-made reusable component libraries. But custom-designed websites and apps are also using the same technique while building custom component libraries.

Even as agile creeps into all the layers of web development, we still need a grand-unifying process that makes the new agile web development possible, unifying back-end, front-end, design, everything. Surprisingly, the once-derided style guide is the key.

Back in the day, website designs were always accompanied by style guides. Even if they weren’t out-of-date before they were delivered (“Ignore that part… I didn’t have time to update it after client feedback”), they always became out-of-date quickly. Since they were separate documents, they didn’t get maintained to reflect the current state of the website and became orphaned documents. But thanks to agile’s continuous integration, style guides can now be auto-generated from the website’s own source code, ensuring that the style guide and the website never get out of sync.

Component-based Web Designs

Patterns are big business in IT. You can’t get far in OO programming before hitting a book about design patterns, stressing the need for standardized solutions to particular problems. When it comes to web development though, design patterns never really hit off. Maybe because of the chaotic nature of the so-called web standards, maybe because we as an industry are just not ready for them yet. That’s no reason to ignore their potential though.

Large web applications generally have a lot of CSS files and often have many developers working on those files simultaneously. With the advent of so many frameworks, guidelines, tools, and methodologies (OOCSS, SMACSS, BEM, etc.), developers need a CSS architecture that is maintainable, manageable, and scalable. The answer is web components.

Web components are a collection of standards that are working their way through the W3C. They allow us to bundle up markup and styles into reusable HTML elements that are truly encapsulated. What this means is we need to start thinking about component-based CSS development. You’ll hear web development components go by many names:

  • “Object” in OOCSS
  • “Module” in SMACSS
  • “Block” in BEM’s Block-Modifier
  • “Web component” in HTML

Once components are planned, it’s easy to write a structure that handles all requirements. Components should be built to be:

  1. Applied to a loose collection of HTML elements
  2. Repeatable
    (even if never repeated)
  3. Specific
    Replace CSS specificity with specific names
  4. Self containing
    Styles do not bleed onto anything else
  5. Nest-able

This especially helps when building a site with user contributed content. WordPress, Drupal, Joomla and other CMS‘s use WYSIWYG editors where often times you’ll have no control of the elements or classes used. Having a base component that set’s default styles for anchors, headlines, paragraphs and others will make it a lot easier to style contributed content.

CSS Design Components

When building projects, think of everything as a component. A great example is the SMACSS approach:

  1. Base Components
  2. Layout Components
  3. Components
    • Component (BEM) (.flower)
    • Element (BEM) (.flower__petals)
    • Modifier (BEM) (.flower--tulip)
    • State (.flower:hover, .flower.is-pollinating, media queries, print styles)
    • Skin (.is-night .flower, should effect many components)
Drupal 8 Component-based CSS Approach

Drupal 8 uses the same component-based CSS design pattern (https://www.drupal.org/node/1886770):

.the-component
.the-component--modifier
.the-component__an-element
.the-component--modifier__an-element
.the-component.is-state
.the-component:hover
@media all { .the-component {} }
.the-skin .the-component

Remember not to make it complicated. Never build a class like .channel-tab__guide__upcoming-video__info__time. Avoid nesting components, elements and modifiers all in one. Also don’t try to be a perfectionist. You’ll end up spending a ton of time trying to decide what to name something instead of developing it.

Sucking at something is the first step to becoming sorta good at something.

The “Fugly” Selector Hack for Drupal

Have trouble inserting a class on an element in Drupal? This is especially a problem with links. Though Drupal offers many hooks to drill down to most containers, it’s sometimes hard to add a class to minor elements like the anchor tags.

// Pretty classes.
%feature__title-link {

}

// Ugly classes.
.feature__title a {
  &:link,
  &:visited {
    @extend %feature__title-link;
  }
  &:hover,
  &:focus {
    @extend %feature__title-link-is-hover;
  }
}

In the example above, the anchor tag is the container I don’t have access to. Instead I would have preferred to add the class .feature__title-link directly to the anchor tag. Unfortunately, sometimes you’ll be forced to apply this kind of selector hack when working with Drupal.

Continuous Integration with Automated Style Guides

Style guides promote a systematic approach to composing layouts, which used to be just a task within the user interface development process. Incorporating style guides into the development process places importance on the tools used to build the component catalogue.

With an automated style guide documenting your custom component library, building a website becomes straight-forward.

  1. Pick a feature to begin development on.
  2. Look through the existing style guide to see if it already contains a design component that you can use as-is or tweak.
  3. If the new feature requires a new component, designers and front-end developers should work together to design and implement it.
  4. Repeat.

Immunize your code — don’t get sick!

The problem with style guides is keeping them up-to-date. It takes time, valuable time that could be used to develop your project. Due to the resources and time involved, many companies completely avoid building them as it becomes cost prohibitive. Doing this is like not immunizing your kid. Sooner, rather than later your project will become sick. Symptoms include bloat, spaghetti code and design inconsistencies. As time goes on, the symptoms will become overwhelming and you’ll feel the need to put your project down and start from scratch.

That’s where styleguide-driven development comes into play. It’s ability for continuous integration or automation will save you time to focus on actual development.

Styleguide-Driven Development

Knyle Style Sheets (KSS) to the rescue!

As you write your CSS, software like KSS can automatically generate style guides for you with styleguide-driven development. KSS (https://github.com/kss-node/kss-node) is a popular one due to it’s simplicity. It’s basically a spec to write CSS comments so the parser can automatically generate a style guide for you.

/*
Button

Your standard button suitable for clicking.

:hover     - Highlights when hovering.
.shiny     - Do not press this big. shiny, red button.

Markup: index.html (optional)

Style guide: components.button (defines hierarchy)
*/
.button {

}
.button.shiny {

}

Used in conjuction with a task runner like Grunt, it’ll become a powerful allie in your web development workflow saving you a ton of time. With one command you can:

  1. Build CSS from Sass/LESS/etc.
  2. Linting for CSS/Sass/JavaScript
  3. Minify and concatenate scripts/images
  4. Build a updated style guide
  5. Visual regression testing
  6. Live reload

Take it further and create a gem file to install and load your project dependencies (Sass, Susy, Grunt, etc.) This makes it easier for new developers to get the project setup on their locals.

Additional Resources

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

May 20 2015
May 20

Boost the performance of your Drupal 7 website, improve usability and help with SEO by making content load via AJAX in just a few steps.

Drupal AJAX is a cinch to implement—as it should be since core is loaded with it. In just a few of steps I’ll show you how to use jQuery and Drupal’s hook_menu() function to quickly build a AJAX function to return anything from HTML to a JSON array.

Simple Drupal AJAX JSON Implementation

/**
 * Implementation of hook_menu().
 * @see https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_menu/7
 */
function moduleName_menu() {

  // Setup a URL to retrieve the JSON array.
  $items['node/%/moduleName/pageviews'] = array(
    'page callback'     =&gt; 'moduleName_get_pageviews',
    'page arguments'    =&gt; array(3),
    'type'              =&gt; MENU_CALLBACK,
    'access arguments'  =&gt; array('access content'),
    'delivery callback' =&gt; 'moduleName_ajax'
  );

  return $items;
}

/**
 * Returns the number of pageviews for a node ID.
 */
function moduleName_get_pageviews($nid) {

  // Some fancy function that returns pageviews.
  return fancyPageviews($nid);
}

/**
 * Renders a JSON array.
 */
function moduleName_ajax($pageviews) {

  // Tell the browser to expect JSON data.
  // @see https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/drupal_add_http_header/7
  drupal_add_http_header('Content-Type', 'application/json');

  // Output the JSON result
  // @see https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_json_output/7
  print drupal_json_output(array('pageviews', $pageviews));

  // Perform end-of-request tasks.
  // @see https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_page_footer/7
  drupal_page_footer();
}

With the above code (after clearing cache), visit yoursite.com/node/55/moduleName/pageviews to return a JSON array with the number of pageviews for node ID 55. More information on the hooks and functions used can be found below:

You can then use this URL and jQuery.getJSON() to return the data via AJAX.

;( function( $ ) {
  &quot;use strict&quot;;

  // When document is ready...
  $( function() {

    // Get the JSON result.
    $.getJSON( &quot;node/55/moduleName/pageviews&quot;, function( data ) {

      // Add the number of pageviews to the page.
      $( &quot;#pageviews&quot; ).text( data.pageviews );
    });
  });

})( jQuery );

Or if you need to pass data to the AJAX script:

;( function( $ ) {
  &quot;use strict&quot;;

  // When ready...
  // @see http://www.benmarshall.me/drupal-behaviors/
  Drupal.behaviors.myModule = {

    // Arguments to pass to the AJAX script.
    vars arguments = { status: 'awesome' };

    // Send the arguments &amp; return the JSON data.
    $.getJSON( &quot;node/55/moduleName/pageviews&quot;, arguments ).done( function( data ) {

      // Add the number of pageviews to the page.
      $( &quot;#pageviews&quot; ).text( data.pageviews );
    });
  };

})( jQuery );

For more information on $.getJSON(), see http://api.jquery.com/jquery.getjson/.

You’ll also notice it’s using something called Drupal.behaviors. This is essentially a document ready for all content, including new content that get’s added to the page after load. For instance, if a modal is added to the page via AJAX and a function that’s already been initialized needs to run on the modal, normally you’d have to force event delegation. For a quick introduction to Drupal behaviors, see http://www.benmarshall.me/drupal-behaviors/.

A Closer Look

Like with everything in Drupal, there’s a number of ways to implement AJAX, but which is best? Let’s dive a little deeper into Drupal AJAX and take a look at how, why and when you can use this powerful feature.

AJAX outside the Form API is new in Drupal 7. It allows back and front-end developers the ability to leverage high performance and solid JSON and HTML responses. You can use this feature to update blocks, nodes, pages and any other element with better performance on the client and server-side vs. loading AHAH page fragments.

Drupal AJAX with jQuery

jQuery provides a few different AJAX commands, depending on your exact requirements. Here is the simplest Ajax call you can make with jQuery:

$( &quot;#someDiv&quot; ).load( url );

What this is saying is “Find the div with the id of ‘someDiv’ and load the html that you find at the location ‘url’ into this div”.

The jQuery utility functions below provide for the extra flexibility you need when dealing with data coming back from the server that needs to be parsed.

// https://api.jquery.com/jquery.get/
$.get( url, parameters, callback );

// http://api.jquery.com/jquery.post/
$.post( url, parameters, callback );

// http://api.jquery.com/jquery.ajax/
$.ajax( options, settings );

// http://api.jquery.com/jquery.getjson/
$.getJSON( url, data, success );

// http://api.jquery.com/load/
$.load( url, data, complete )

The only difference between $.get and $.post is the HTTP request method used to send your parameters (an array passed as the second argument) to the server. Very often in Drupal, you won’t need to send any parameters because the url you will be calling will be a menu callback you have set up as, for example, ‘ajax/get/node_details’ taking one argument, ‘nid’ and so you would simply make the call to ‘ajax/get/node_details/123’ and not need to send your nid parameter as a parameter in the second argument.

Additional Resources:

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Dec 31 2014
Dec 31

As 2014 draws to a close, I look back at the year and realize... holy crap I traveled a lot! I hadn't actually done a fully tally yet, but here's the full rundown:

Sunshine PHP - Miami, FL - February Drupal South - Wellington, New Zealand - February Florida Drupal Camp - Orlando, FL - March MidCamp - Chicago, IL - March Museums and the Web - Baltimore, MD - April Lonestar PHP - Dallas, TX - April Drupal Association Webinar - Online - May php[tek] - Chicago, IL - May DrupalCon Austin - Austin, TX - June Refactor::Chicago (User group) - Chicago, IL - May Nomad PHP (User group) - Online - June Crafting Code Tour - Minneapolis, MN; Milwaukee, WI; Cincinnati, OH - July Design 4 Drupal - Boston, MA -July Twin Cities Drupal Camp - Minneapolis, MN - August Madison PHP - Madison, WI - September DrupalCon Amsterdam - Amsterdam, The Netherlands - September Symfony Live - New York, NY - October Higher Ed Web - Portland, OR - October BADCamp - San Francisco, CA - November php[world] - Washington, DC - November

In all, I flew 64,082 miles (103,130 kilometers for the metric fans in the audience), presented 29 times, with 13 distinct presentations at 20 conferences and user groups across 3 continents, and spent 82 days on the road (not counting non-conference travel). You know what that means?

It means I created about 10 metric tonnes of carbon pollution.

The downside of business travel

Jet fuel is a major contributor to greenhouse gas emissions. The more you fly, the more carbon dioxide and other waste gases you contribute to the atmosphere and the more we continue the downward spiral of human-created climate change. Flying is way worse than driving in that regard. Most people don't fly all that much but if you're a frequent conference-goer like I am (and like I know a great many of my friends and colleagues are) then air travel pollution is a significant contributor to us destroying our world.

I know some people have called for a reduction in air travel, powered by remote-conferencing technologies, but as anyone who has actually used them knows they are at best a very useful but poor substitute for in-person interaction. Humans are social beings and we are not going to stop traveling to spend time hanging out and learning from each other. That's a pointless battle to fight.

A partial solution

Fortunately, there is an alternative. Many companies offer "carbon credits". The basic idea is that if you generate 1 tonne of carbon dioxide, you invest in funding some project that will reduce overall carbon dioxide output (or equivalent from other greenhouse gases like methane) by an equivalent amount. That could range from reforestation efforts to methane burnoff to any number of other techniques. The end result is that you are, in effect, "carbon neutral". It's less ideal than reducing your greenhouse gas emissions in the first place but it can reduce your impact.

It's also far, far cheaper than you would expect. I chose this year to offset my travel with credits from a company called TerraPass, as my company Palantir.net has worked with them before. (The carbon offset industry is too new to be regulated, so be careful of scams.) The cost of offsetting 1000 lbs of carbon dioxide? $5.95 USD. That's it. Less than breakfast at Starbucks. That means offsetting all of my air travel in 2014 is a mere $130. Adding in my home energy usage and driving brought the total up to about $260. That's it. You probably spent more than that on your phone.

So I did. And you should too.

Your turn

I know many of my readers are frequent conference travelers and speakers. Many of them cross an ocean much more than I do. Friends, that means you're churning out just as much greenhouse gas pollution as I am, if not more. It's ridiculously cheap to compensate, and only takes a few minutes.

My challenge to you then is this: Offset yourself. I'm not going to tell people to stop going to conferences (that would be rather hypocritical), but I am going to call on everyone who attended or spoke at a conference to, at least, buy offsets for their air travel if not their full carbon footprint. You spent more on the ticket than you will on the offsets. (If you were a speaker and got your ticket free, you spent more on the cab from the airport.) If you can afford to attend a conference, you can afford a latte grande's worth of carbon offsets.

No, it won't cure the world, but every little bit helps. And if we can make it a trend and an expectation, especially for we frequent flyers, it can have a larger impact.

Conference organizers, you too

I know of only one conference that offered attendees the option of purchasing carbon offsets at registration, and that was DrupalCon Chicago 2011. Conference Organizers: Let's make it easier for people to go neutral for your conference.

Partner with some reputable carbon offset company, give people a calculator for their travel distance, and let them buy offsets along with their ticket, T-shirt, and whatever else. Make it optional, sure. (Opt-out would be nice, but possibly not feasible without some default travel distance for the calculation.) But put it there in people's faces. For most people it will cost less than the T-shirt.

Make that your 2015 resolution: At least make your business travel carbon-neutral. It's cheaper than a gym membership and much easier to stick with. And you don't even have to break a sweat.

See you next year

And I'll see many of you again this year at Sunshine PHP, DrupalCon Bogota, Midwest PHP, Lonestar PHP, and other conferences yet to come. Just make sure to travel environmentally-friendly to get there.

Share with

Sep 24 2014
Sep 24
This article was originally published by Drupal Watchdog in the winter 2014 edition by Fabian Franz.

The Salesforce Suite of Drupal modules is an easy way to connect Drupal to Salesforce, a Customer Relationship Management system used by retailers and non-profits alike, which allows non-technical staff to create extensive reports — reports that would be difficult to create using Drupal alone.

Although entities can be synchronized to Salesforce objects — and custom mappings created — there is lots more that can be done with Salesforce. Let’s take a look.

Getting Started

For openers, you’ll need:

To get the Developer Edition, create a developer account at https://developer.salesforce.com/signup.

Once you’re in Salesforce, you’ll quickly notice that the site seems overwhelming. A complete overview is way beyond the scope of this article; the most important objects for our purposes are Campaigns, Leads, Contacts, and Cases.

There are many other extensions for Salesforce, extensions that provide new object types. Also, existing object types can be extended in much the same way as in Drupal.

As a best practice, always work in a sandbox environment when not working with a dev instance. It will help ensure that you can create a proper development -> testing -> production workflow.

To create a sandbox (Enterprise, Performance, Unlimited, and Database.com), go to Setup » Sandboxes » Create new Sandbox.

As the final step in this first part of the process, create an application to connect Drupal to Salesforce by going to Setup » Create » Apps and clicking on New application under Connected App. Enter the basic information (e.g. “Drupal Integration”) and activate oAuth. Enter a callback URL to your local instance. If your local development Drupal site resides at http://localhost/salesforce-test/, then your callback URL is http://localhost/salesforce-test/salesforce/oauth_callback. Select api and offline_access as scopes.

Be sure to keep your consumer key and consumer secret handy, and you’re ready to move on.

Next Steps

Download the ‘salesforce-7.x-3.x’ module and enable the salesforce_mapping and salesforce_push modules. In your Drupal site, go to Configuration » Salesforce » Authorize and enter your consumer key and secret.

If you are using a sandbox, you need to enter, under the advanced settings, https://test.salesforce.com/ as the Salesforce endpoint. After logging in, you will be prompted for the permissions specified earlier; after clicking ‘Allow’, you’ll be back at Drupal with the message “Salesforce OAUTH2 authorization successful.” At the bottom of the screen will be a list of resources.

Before mapping the user object, create field_first_name and field_last_name fields within Drupal for the user entity at Configuration » People » Account Settings » Manage Fields.

You’re now able to map the User account to a contact by going to Structure » Salesforce » Salesforce Mappings and adding a Salesforce module called “User Mapping”.

Fill out the fields as seen in the image below, and check the three action triggers (entity create / update / delete). Save, and edit your own user account at People » Edit. Add the first name and last name, and you’ll see that the user account has been synchronized with a Salesforce record (see below).

A Ticket System for Authorized Users

A typical use case is to collect data in Drupal, and then process the data in Salesforce. But for this article, we will create a quick ticket system for authorized uses that will create cases within Salesforce, using the Entityform module, which allows creating forms that can be used for collecting data — similar to Webform, but using Drupal fields.

Download and enable the Entityform module and go to Structure » Entityform Types » Add Entityform Type. Enter Ticket as the name, and select authenticated user as the role. Save the form type and add a message-long text field to it.

Next, map the entityform submission entity with the ticket bundle to a Salesforce case object like the user account. Map the field_message field to the Case description; map the user who creates the case; select Related Entities » User; and map that to Contact ID (see below).

Save the mapping and go to the submit/ticket URL (available from the Structure » Entityform Types screen), enter a message, submit it, and — voila! — your ticket has been created as a case within Salesforce.

Tip: If you copy the Salesforce ID from the message, you can go directly to https://emea.salesforce.com/ID to see the newly created record. (The emea prefix is for the developer edition.)

Webforms

While Entityform is quite pwerful, form variations are not easily workable because only one bundle can be mapped to one object type. But with the help of the Webform and Salesforce Webform Map modules, in combination with Entityform, it is possible to create a Salesforce mapping per object-type once, and potentially re-use it across hundreds of different web forms. In this scenario, one webform is represented by a campaign in Salesforce, and recursive object creation is enabled using different Salesforce mappings.

Conclusion

Salesforce and Drupal are a powerful combination. The Salesforce module allows you to map complex Drupal structures to Salesforce, and by using Entityform, simple data entry forms can easily be created.

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

May 21 2014
May 21

I recently needed to delete a image style that was no longer being used with a update handler. Being that Drupal’s documentation is less than informative, I did some digging and finally figured it out. Check out how to create, flush and delete image styles below.

Programmatically Create an Image Style

The code below will create an image style named, avatar that will scale images to 64×64:

&lt;?php
$style = image_style_save(array('name' =&gt; 'avatar'));
$effect = array(
  'name' =&gt; 'image_scale',
  'data' =&gt; array(
    'width' =&gt; 64,
    'height' =&gt; 64,
    'upscale' =&gt; TRUE,
  ),
  'isid' =&gt; $style['isid'],
);
image_effect_save($effect);

Or, you can create image styles with a Drupal hook using hook_image_default_styles:

&lt;?php
function hook_image_default_styles() {
  $styles = array();
  $styles['avatar'] = array(
    'effects' =&gt; array(
      array(
        'name' =&gt; 'image_scale',
        'data' =&gt; array(
          'width' =&gt; 200,
          'upscale' =&gt; 1,
        ),
        'weight' =&gt; 0,
      ),
      array(
        'name' =&gt; 'image_crop',
        'data' =&gt; array(
          'width' =&gt; 200,
          'height' =&gt; 200,
        ),
        'weight' =&gt; 1,
      ),
    ),
  );

  return $styles;
}

Programmatically Delete an Image Style

&lt;?php
image_style_delete(image_style_load('my_image_style'));

Don’t forget to flush…

You may need to flush the image style before Drupal will let you delete it. You can flush image styles using two different methods:

Flush Image Styles with Drupal Console

# List image styles on the site
$ drupal image:styles:debug

# Execute flush function by image style or execute all flush images styles
$ drupal image:styles:flush

For a list of other useful Drupal 8 Console commands, see benmarshall.me/drupal-8-console-commands/.

Flush image styles with Drush

$ drush image-flush

This will create a list of options with all of your defined image styles. For more information run:

$ drush help image-flush

Programmatically flush image styles

&lt;?php
image_style_flush('STYLE_NAME');

Or, if you want to flush all image styles:

&lt;?php
foreach (image_styles() as $style) {
  image_style_flush($style);
}

More on Drupal Image Styles

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Jan 17 2014
Jan 17

Migrating comments from Drupal to DisqusEven if you've never heard of Disqus before, you've almost certainly seen it. With slick social integration, support for a variety of platforms (including WordPress, Blogger, Tumblr, and Drupal) and a rapidly expanding user base, Disqus has become one of the most popular hosting services for website comments. If you've had misgivings about the commenting system you're using – or just envied the functionality and polish of other systems – you may get to a point where you decide (as we did for our Forum One blogs) to make the switch to Disqus.

Making this switch is fairly straightforward – but what about all those wonderful comments that your blogs have earned over the years? You don't want to lose all the valuable discussion, tips and virtual high fives from your online fans, do you? Probably not. So if you're using Drupal and looking to upgrade to Disqus from a system like Mollom, there are various resources that already exist for manually migrating those comments, but nothing explains the process from A-Z, so I've compiled this step-by-step guide to show you how to manually do the job.

There are two primary ways to migrate comments: (1) Using the API to automate the whole process by directly connecting to Disqus from Drupal and move the comments for you (which isn't working at the moment); or (2) Using the Disqus XML export tool to migrate comments from Drupal in XML format which you can then import manually into Disqus.

Versions

  • Disqus module (Do NOT use 6.x-1.9 which was the stable version at the time of writing this. In normal Drupal fashion the Dev version is the one to use which is 6.x-1.x-dev released Nov 22, 2013 which contains the extra features needed to do this.)
  • This was done in Drupal 6 though D7 is very similar

Step 1 - Module Enabled

Enable both Disqus and Disqus Migrate modules (Disqus Migrate provides migration tools for moving comments between Disqus and the Drupal comment system). Disqus has a great reference for this.

Note: There are additional steps to enable Disqus (ie. downloading and installing the API library, adding your Disqus keys and verifying connection with Disqus, as well as actual Drupal access permissions) which are well documented in the list of references I've provided at the foot of this article. Since those steps are primarily used for setting up the module rather than carrying out the actual migration, I will not review those steps here.

Step 2 - Export Drupal Comments

  • Navigate to the Disqus export page /admin/content/comment/disqus_export which contains two buttons, Export Awaiting Comments Using API (which doesn't work as of writing this) and Export All Comments to XML File which is the one you should click.
  • Select Export All Comments to XML File (This option is explained as Exporting via XML will just gather all of your websites comments and format them for importing manually into Disqus)
  • Save the file to your local file system.

At this point you will have all the comments from your site in XML format which we will not import into Disqus.

Step 3 - Import Drupal Comments Into Disqus

  • Log into Disqus and navigate to Admin -> Discussions (Tab) -> Import (Tab)
  • Select the Generic WXR sub-tab option.
  • Select the Upload WXR file browser button and select your XML file you saved locally.
  • Select Upload and Import button.

Upon completing this, the comments will be imported to Disqus and you might want to do some house cleaning of those comments using the Disqus Admin interface tools.

Step 4 - Optional, but pretty much needed

After the comments are imported you may notice that some comments that exist on your Drupal nodes are not being displayed in Disqus. This is most likely caused by URL aliases. Since Disqus maps comments to nodes by path, this means that example.com/node/32 and example.com/how-to-play-ball may be the same node, but Disqus doesn't know that – so the result is that those comments will only show for the URL that was in the export XML file. What we need to do now is provide Disqus URL mapping.

  • In Disqus navigate to Admin -> Discussions (Tab) -> Tools (Tab)
  • Select Start URL Mapper. This takes you to a page that will give you a list of comment paths Disqus knows so you can provide manual path mapping information OR you can have Drupal create a mapping file for you. I chose to do this using a custom script.This page shows you the format it expects the CSV format (comma separated value) file to be in:
  • Follow the link to download the CSV file from Disqus to your local file system and name it disqus-urls.csv.
  • Copy this CSV file to your Drupal root directory.
  • Create a file with the following PHP code in that same Drupal directory called disqus-custom-script.php

<?php

$base = 'http://forumone.com/';

$n = strlen($base);

foreach (file('disqus-urls.csv') as $url) {

  $path = substr(trim($url), $n);

  $source = drupal_get_normal_path($path);

  if ($source != $path) {

    echo "$base$path, $base$source\n";

  }

  else {

  $source = drupal_get_path_alias($path);

  echo "$base$path, $base$source\n";

  }

}

  • Browse to the PHP file (or execute your preferred way so you can see echo output). Browsing to it with yoursite.com/disqus-custom-script.php assuming you named your PHP file that and saved it in the root directory as asked.This will give you output that can be saved into a CSV file and will be in the exact format that Disqus expects.
     
  • In Disqus navigate back to Admin -> Discussions (Tab) -> Tools (Tab) -> Start URL Mapper (Button) and upload the text file containing the output from our PHP script.

Make sure you give it a few minutes to complete, as the mapping in Disqus isn't instantaneous, but you should start seeing your comments appear where they should for the URLs that were in the mapping CSV file.

That's it! Below I've provided a list of references that you can use when following these steps. If this guide is helpful for you, or if you discover a different solution, please leave us a comment ;)

References

Jan 08 2014
Jan 08

Bootstrap is a great Drupal theme that makes it so your form elements and other Drupal things get output with proper Twitter Bootstrap CSS attributes.  One downside to it is that the popular Webform module has elements that don't get styled by the Bootstrap Drupal theme and then they look like unstyled form fields.

To fix it, go to Bootstrap's theme/process.inc file.  Inside it, add 'webform_email' to the 'types' array in the _bootstrap_process_input() function.  This will style Webform's special email field.  Other fields likely have different types.  The reason it doesn't get styled is because the 'types' array is coded to look for only default types and not the special ones that Webform is using.

If you want to see what the #type is on an element, I recommend installing the Devel module and calling "dpm($element);" inside the theme/alter.inc bootstrap_element_info_alter() function.  This will output all of the elements on your current Webform.

Happy Bootstrapping!

Jul 01 2013
Jul 01

Although the Drupal Kaltura module (6.x-2.0-beta2) is great for most video play, it doesn’t always play nice with Organic Groups. Recently I was tasked with using the module on an existing Drupal 6 Commons site. The problem was that Kaltura media nodes do not automatically inherit the group association, when created in a group context. In other words; when there is a GET parameter for a group id (gid) present in the node add page for kaltura_entry content types, Kaltura content would not be associated with the group like other group post content types. This is because the module relies on notifications from the Kaltura service before a node is actually created, at which point, the parameter has no relevance. So all we needed to do was pass some data to Kaltura and have Kaltura pass it right back to us.

After some extensive research, I finally came across this documentation page. The section "Passing Partner Data to the KCW Widget" (KCW = Kaltura Contribution Wizard) explains that we do have a partnerData key in the variables passed to the Contribution Wizard widget and then on to Kaltura. In fact, the module already does something similar to pass the user ID. All we had to do was plug the gid in there then handle the returned data. This does require a bit of patching to the contributed module.

First, plugging in our group id. This required adding the following to line 47 of kaltura/kaltura_client/kaltura_helpers.php

if(array_key_exists('gids', $_GET)){

$flashVars["partnerData"] .='|[email protected]'. filter_var($_GET['gids'][0], FILTER_SANITIZE_NUMBER_INT);  

  }

Note that the values are delimited by pipes, and paired with an @. Next, we had to figure out how to handle the returned data. This required modifying the kaltura_notify_node_entry_add() function in kaltura/includes/kaltura.notification.inc to assign the node to a group during node construction. I was not entirely sure how to do this off the top of my head, so I relied on the suggestions in this Drupal stack exchange post and dropped the following code in around line 206 right before node_save($node).

if(array_key_exists('gid', $partner_data)){

$node->og_initial_groups[0][$partner_data['gid']] = $partner_data['gid'];

$node->og_groups[0] = $partner_data['gid'];

$node->og_public = 0;

$gnode = node_load($partner_data['gid']);

$node->og_groups_names[0] = $gnode->title;

}

As always, when modifying a contributed module, I saved these changes in a patch file in the repository so they can be tracked and re-applied in the event that we upgrade the module later (if the patch is not already applied by then).

Apr 15 2013
Apr 15

Sites using shared databases for tables like shared users are great for sharing users between sites. It works for many other entities as well. The tricky part is using Solr indexing on this content.

The way Solr indexes things is when a new entity that should be indexed is added it is marked for Solr indexing as well. This works great but it's limitation is that the Solr index itself is stored in the current site's database. This means that if you have Site A and Site B and Site A adds a user (to the shared user table that Site B also uses), site A will mark it to be indexed by Solr. In turn Solr will add it to Site A's Solr index, but Site B still misses the Solr index marking (since as far as site B is concerned it now always existed.) To solve this problem I created a Cron job hook in a module that is used on both sites that scans the Solr index for items of a desired type and then compares them to the actual shared table to see if any are missing in the Solr index. If items are found that are not in the Solr index, they are added.

This is beneficial for many reasons. For example if you have views that use a Solr index for content you want to make sure everything in your shared table is in this index. In my case user searches in site A were missing users that were created on on Site B.

Why do a Cron hook (instead of hook_node_insert)? You need to make sure the other site is able to find the entities that it didn't create. Cron is great since it runs on both sites no matter what and checks. Insert response hooks will only work on the current site being used to add the user, but the other site is unaware even if they both share that same module. Site B will not respond to a node insert done on Site A with an insert hook.

The most important part of this is search_api_entity_insert which actually marks an item as to-index.

// Ensure that users are indexed correctly, regardless of which site they were created on.
// Since users can be created on two sites, search_api_entity_insert($entity, $type) might
// not be called, which results in an incomplete user index.
function MYMODULE_cron() {
  // Make sure search_api module exists
  if (module_exists('search_api')) {
    // I am searching for users so this is my type. This could be a different type if 
    // not being used for users
    $user_type = 'user';
    $conditions = array(
      'enabled' => 1,
      'item_type' => $user_type,
      'read_only' => 0,
    );

    // Each type in the search_api index has a different ID. That ID can be different 
    // even between sites that share the same item type so it is important to do this 
    // to get the Solr ID of the type of entity you are loading for use in the following 
    // steps. We of course will only get one index back.
    $indexes = search_api_index_load_multiple(FALSE, $conditions);
    if (!$indexes) {
      return;
    }
    
    // For the one Solr ID index found
    foreach ($indexes as $index) {
      // User type exists
      // Select all users from the shared users table that are not present in the search 
      // index on this local site.
      // Note that the users table is set to use the shared database:table in 
      // settings.php of both sites.
      // The following drupal query essentially does this sql query:
      //    select u.uid from SHARE_db.users as u 
      //      where uid not in 
      //      (select item_id from THISSITE_db.search_api_item
      //       where index_id = ThisSolrUserTypeID);

      $query = db_select('users', 'shared_u');
      $query->addField('shared_u', 'uid');
      
      $query_exists = db_select('search_api_item', 'indexed_users');
      $query_exists->condition('indexed_users.index_id', $index->id, '=');
      $query_exists->addExpression('NULL');
      $query_exists->where("indexed_users.item_id=shared_u.uid");

      $query->notExists($query_exists);
      $results = $query->execute();

      // Great idea to add a log that users are found that are about to be indexed since 
      // this is running in cron. That way if something goes wrong we can at least see 
      // that this started.
      if ($results) {
        watchdog('MYMODULE', 'Adding shared users to search index');
      }

      // $results now holds all the users that need to be indexed because they were not 
      // found in the current site's Solr index.
      foreach ($results as $result) {
        // The user record doesn't appear to have been indexed, so call
        // search api's search_api_entity_insert directly and make it so.
        search_api_entity_insert(user_load($result->uid), $user_type);
        // You can un-comment the following line if you want to see each entity you are 
        // adding to be indexed by Solr.
        //watchdog('MYMODULE', 'Adding user ' . $result->uid);
      }
    }
  }
}

As a follow up note this only handles entity adds. If an entity is removed a similar function needs to be created to un-index the entity as well. You can use search_api_entity_delete.

If there is interest or if it would be helpful we could put together a Birds of a Feather at Drupalcon Portland (2013) for this. Let us know! 

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