Author

Nov 15 2016
Nov 15

Recently, I was asked to migrate a fairly straightforward website from Drupal 6 to 8: a blog; some feature articles; some static pages; a fair amount of uploaded images. I thought it would be a great candidate for reviewing what the Migrate UI bundled with core looks like, since its introduction in Drupal 8.1.0.

Although the Migrate framework more generally permits arbitrarily complex migrations, many people's first port of call will be the UI, so I thought it would be interesting to chart a user journey through its use: highlighting what went well, what went badly, and (most importantly) what looked problematic but turned out to be straightforward.

Kicking off a Drupal 6-to-8 migration with the UI

There's an excellent drupal.org guide page on running a UI-based migration into Drupal 8, and I'll try not to repeat too much of that here. The steps they describe are completely correct, although I just want to make a few comments on the experience of actually going through them.

A cautious beginning, then ploughing on

Before getting started, I made quite sure that my Drupal 6 and 8 installations reported healthy statuses, with no problems or warnings:

This includes trivial things like trusted host patterns: even if you don't think it might cause a problem, the fact that we have Drupal sites contacting each other and accessing each others' filesystems meant I wanted to be certain everything was working fine.

I then installed the three Migrate modules, and Drupal made it clear to me that they were experimental, which made me pause (which I think is good: to make sure you're happy with what you're doing):

I then navigated to /upgrade to run the migration as described on the d.o page. Despite the source D6 website being quite straightforward, the list of modules whose configuration was entirely unknown to the out-of-the-box migration procedure was a little worrying (click for bigger):

Some of those omissions made sense (admin_menu, jquery_ui, php, and a few custom modules); some of them were disappointing but expected (views, googleanalytics); some were a bit more worrying and looked like they might lead to content left behind (image*, date*). Still, in the spirit of adventure, I continued regardless.

First impressions

Well, the site still worked! and although the migration log was very verbose, there were no real surprises in it:

The log is linked directly from the "migration finished" page so it's easy to go and inspect the results: just don't be put off by the number of pages!

Configuration had been migrated: the site title, slogan and email address were immediately apparent. The files appeared to be in the same folder on the new website, and arbitrary user registration was still locked down.

One immediate problem I spotted was a warning about a missing block:

It turns out that the D6 website was using the Aggregator module: which core D8 has available to it, but isn't enabled by default. Unfortunately, enabling the module at this late stage caused fatal errors, and it was easiest to just roll back and re-run the migration with that module enabled. Ideally the 6-to-8 migration would've spotted that I had aggregator available (but disabled) in Drupal 8 and asked about it, but it was quick to re-run anyway.

It was made clear there was going to be no color migration; and theming is always radically different between Drupal versions: so as expected the theme and other visuals remained unchanged.

How well was content and users migrated?

Users

Users were migrated OK and their passwords were preserved. However, the D8 site's admin user (UID=1) had been set up with a nonstandard username as recommended for security reasons; this was replaced with the (guessable "admin") username during the migration:

Where Drupal 8 had its own suitable analogue of an old Drupal 6 permission, configuration for that permission was copied across successfully. However, one slight problem was with the duplication of a particular role: the D8 Administrator role (which had special status in the new website) was joined by a lowercase "administrator" role (which had no particularly special status.) This meant that administrator users were not automatically getting the expected permissions in the new site.

Nodes

All content types seemed to be migrated fine, along with their created dates and other field information. All node content was migrated into those types. Despite the warnings elsewhere in this blogpost, content migration alone was a major success!

One problem that plagued all content was that the text input formats from Drupal 6 had been migrated across into Drupal 8, to sit alongside the out-of-the-box formats. You'd think this was an advantage, but content noted as being in those formats (i.e. all rich-text fields) was not output to the page:

In the editing interface, the rich-text editor wasn't associated with the migrated input format, more evidence that the migration of configuration was the problem here:

When the input format is switched to one previously available in Drupal 8, unmigrated, then the rich-text editor kicks in:

And, after being saved, the content is visible:

The simplest resolution to this across all content was a post-hoc sweep of the input fields, changing the format name at the database layer, which I'll discuss below.

Images

All image files were migrated as file entities, and the files were still present in the same place on the file system. Again, file migration was a major success and takes a lot of the usual heavy lifting out of how one would migrate content.

However, even with the media_entity module suite enabled at the point of migration, no media entities are created, and they're especially not created retroactively. In addition, inline images embedded with ImageBrowser were broken, because the filter was no longer functioning on the input format: this led to literal tags being displayed of the form [ibimage==...==...]. We'll discuss the fix for this below too.

Views

No views were migrated:

which the eagle-eyed will have expected, but still seems a shame. I dread to think what might have become of Drupal 7 if there weren't a good upgrade path from CCK available when it came out!

It seems Views was dropped from core in part because it wasn't (could never be) complete, but this argument alone seems very "perfect the enemy of the good". Moreover, it's not consistent with a lot of core functionality: Dries himself admits image management in core is "basic", and one person's basic is another's partial. I'm not convinced it's compatible with the fundamental concept of contrib being there to extend core, either: if nothing in core is partial, then there's nothing to extend.

For those with many, many views to migrate, there's now a contributed project to migrate Views, which gives some hope. In the mean time, for the rest of us, the only way to have Drupal 6 Views in the new Drupal 8 website is to build them again from scratch, although there were some savings to be made, as we'll see below.

Quick fixes vs. building from scratch

Users and roles

Manual: the simple fixes here were: rename the administrator account; and reassign the administrator role. The fact that most permissions that made sense in both 6 and 8 were preserved was a boon here, although future work in the website would probably require further manual assignment of permissions new to Drupal 8.

Fixing input formats

Automatic: after diagnosing that a simple change of the input format sufficed, and discussing with the client to ensure it was OK to do so, all input formats for both node and comment body contents were changed to a Drupal 8 format.

This was automated with the following code. A postmigrate module was created, in line with the Extending and Altering Drupal post in my series of articles on Drupal 8 APIs. Put the following code in the file postmigrate.install in the module's folder:

<?php
 
/**
 * @file
 * Install/uninstall hooks.
 */
 
/**
 * Implements hook_install().
 */
function postmigrate_install() {
  // Change text format on all bodies to be basic HTML.
  $table_infixes = ['', '_revision'];
  foreach ($table_infixes as $infix) {
    db_update("node{$infix}__body")
      ->fields(['body_format' => 'basic_html'])
      ->execute();
  }
  db_update("comment__comment_body")
    ->fields(['comment_body_format' => 'basic_html'])
    ->execute();
 
  // Invalidate any node entity caches through a tag.
  $cacheTagService = \Drupal::service('cache_tags.invalidator');
  $cacheTagService->invalidateTags(['node_values']);
  return;
}

This module runs SQL directly against the Drupal 8 database, and so is probably not recommended if you have a complicated data storage setup in D8. However, it should work fine otherwise, and after changing the input formats clears the caches for node pages, so their display will change to show the changed state of the content input format.

Rebuilding views

Mixed approach: because there were only a few views in the Drupal 6 site, and these had similar structures (differing only e.g. in content type). This made them ripe for an initial burst of manual

The process was as follows:

  1. Use drush config-export to export the site's entire configuration to a directory.
  2. Create an exemplum view, to be used as the model for several others.
  3. Use drush config-export again, to export configuration for this one view, and note the filename for it.
  4. Copy this file to the postmigratemodule, in subfolder config/install/.
  5. Make copies of the file in the same folder; rename them suitably, and edit them to match the differing requirements for path, filtering etc. (also changing the UUID each time: see this blogpost on fields for more info.)
  6. Uninstall and reinstall postmigrate to enable the views (deleting them first if they were already present).

Using this method, one initial view configuration was forked into four different files and edited each time, saving a lot of manual point-and-click work.

Fixing embedded images

Mixed approach: there were sufficiently few posts with embedded images that it was sufficient to create a view, filtering on any content whose body contains the word "ibimage". This view then served as a tool for administrators, to check any content with broken embed code in it, and rewrite it accordingly.

Summary

Drupal 6 to 8 migration is arguably ready, even though it might arguably not be complete. Migration of content and files—usually the worst bits of a Drupal upgrade—is implemented. Aside from a couple of bugs in input formats (to which your own situation might not be sensitive), this part of the migration bundled with core works well.

The experience of running a migration is generally OK, although there are a couple of points where you have to hold your breath and just move onto the next step. The long list of site elements that won't migrate (including date and image support modules), and the long list of log notices afterwards, both give more pause for thought than, it turns out, they needed to.

The experience of dealing with the aftermath of a migration is also good, although the omission of Views and media_entity entities will be a disappointment to some people all the same. Also, because so much of the Drupal 8 work required will be in the theming, it'll be important to manage expectations of what a newly migrated D6->D8 site will look like prior to theming work.

When I presented these findings to the Oxford Drupal User Group, someone who had done more migrations into Drupal 8 suggested that it was possible to use core's migration as a starting point: run a test migration; tweak content types and other structure to your satisfaction; export the migrated site's configuration; set up a brand-new site, using this configuration, using the config_installer install profile; then write a custom migration that would do the right thing, migrating into this new site. However, treating the migration UI as a "first pass" like this is clearly different from some people's expectations of what such a UI is intended to do.

Overall, though, it's great to have a UI that can handle so much of the major-version migration with only a few clicks, although (as with every major-version migration) it's important to be clear to potential users of the UI that it's never going to be a simple operation, even for simple sites.

Nov 15 2016
Nov 15

In this tutorial series on using Display Suite, we’ve covered the two fundamental use-cases of the module: how to modify layouts and use Display Suite fields.

Now we’ll take a closer look at one of its sub-modules: “Display Suite Switch View Mode”.

The “Display Suite Switch View Mode” module allows an editor to switch which view mode is used on a content page. By default, Drupal will use the “Full content” view mode (if enabled) on content pages, i.e., “node/1”.

But what if you want to choose between two different “Full content” view modes? Well this module has you covered.

So instead of being stuck with a single view mode, you could have one for a layout with a sidebar and another for pages which go full width.

2016-11-08_22-05-03

In this tutorial, you’ll learn how to configure and use the”Display Suite Switch View Mode sub-module.

Getting Started

You’ll need Display Suite installed and ready to go. Read the “Getting Started” section in the first tutorial on how to do this.

The only extra work you’ll have to do is enable “Display Suite Switch View Mode”.

2016-11-08_21-20-36

Create New View Mode

I’ll assume you’ve already configured the “Full content” view mode. Let’s now create a view mode for the second “Full content”.

1. Go to Structure, “Display modes”, “View modes” and click on “Add new Content view mode”.

2016-11-08_21-22-26

2. Click on Content from the “Choose view node entity type”.

2016-11-08_21-23-47

3. Enter “Full content sidebar” into Name, then click on Save.

2016-11-08_21-25-22

At this point we’ve created the view mode, let’s now configure it.

Configure View Mode

1. Go to Structure, “Display Suite” and click on “Manage display” on the Article row.

2. Scroll down to the “Custom display settings” and enable “Full content sidebar”.

2016-11-08_21-27-25

3. Click on the “Full content sidebar” tab and configure the view mode using Display Suite.

I won’t cover how to enable a layout here since it’s covered in this tutorial in detail: “Using Display Suite in Drupal 8: How to Customize Content Pages“.

How to Switch View Modes

Once everything’s been configured, go to the article form and you should see a “Display settings” vertical tab.

Within the tab you can switch view modes by selecting them from the drop-down.

2016-11-08_22-05-03

Permissions

The sub-module offers a useful set of permissions. They can be granted on a per content type basis or you can get access to the drop-down on all content types.

2016-11-09_21-35-47

Summary

By using this module and creating a set of useful view modes, you’ll create a flexible CMS which editors would enjoy using. If you have a requirement to handle different layouts for content types then give this module a go.

FAQs

Q: Can I have this functionality on other entity types?

No, unfortunately this is only available for content types.

Nov 15 2016
Nov 15

Our clients are often looking to reach their audiences via email campaigns, and MailChimp is one of the solutions we frequently recommend for this. MailChimp makes it easy to create and manage email campaigns while also providing beneficial analytics on user behavior.

Earlier this year I wrote a blog post showing how to use Composer Manager along with the Mailchimp API v2.0 PHP package to subscribe users to mailing lists in a Drupal 6 or 7 custom module without the need for the Mailchimp contributed module.

However, since then, MailChimp API v3.0 was released and Mailchimp announced that v2.0 (and all prior versions) will no longer be supported after 2016.

So in this blog post, I’ll demonstrate how to accomplish the same objective using the new MailChimp API v3.0, and I’ll expand the tutorial to also include some Drupal 8 specifics.

Background

To quickly summarize the key takeaways from my previous blog posts on Composer Manager and subscribing users to MailChimp lists using the old API:

  • Composer is a tool for managing PHP libraries that your project depends on.
  • Challenges arise managing project-wide dependencies when custom and contributed modules specify their own unique dependencies.
  • Composer Manager is a contributed module for Drupal 7 (and formerly Drupal 6) that addresses these challenges and allows contributed and custom modules to depend on PHP libraries managed via Composer.
  • Using a Composer managed PHP package for the MailChimp API, we can easily subscribe users to MailChimp lists in a Drupal custom module without relying on the Mailchimp module.
  • While the Mailchimp contributed module is great, sometimes all you need is a simple, lightweight method for subscribing users to mailing lists.

One important development since my previous posts is that Composer Manager has been deprecated for Drupal 8. Improvements introduced in Drupal 8.1.0 allow modules to rely on Composer managed dependencies without the need for the Composer Manager module.

Implementation

There are a few steps we must take so that we can subscribe users to mailing lists in our custom module. We’ll review each of these steps in detail:

  • Add the MailChimp API v3.0 PHP library as a dependency of our custom module.
  • Ensure that the library is installed for our project.
  • Properly use the library in our custom module to subscribe users to mailing lists.

Specify the dependency

ThinkShout maintains the Mailchimp contributed module and we were very excited to see that as part of the effort to “get Drupal off the island” they also released a PHP library for MailChimp API v3.0.

To use this new library, we must specify it as a dependency of our custom module. We do that in a composer.json file that sits in our custom module’s root directory and requires that library via the following code:

{
  "require": {
    "thinkshout/mailchimp-api-php": ">=1.0.3"
  }
}

Install the library

Composer is intended for projects and therefore requires a Drupal site to have a single composer.json, so things get complicated when individual modules specify their own dependencies.

For Drupal 7 sites (or still active Drupal 6 sites), the Composer Manager contributed module handles this by merging the requirements specified by each custom and contributed module’s composer.json files into a single, consolidated, site-wide composer.json file.

So for Drupal 6/7 projects we’ll need Composer Manager installed and enabled.

Once enabled, we can generate the consolidated composer.json and then install all of the site’s dependencies that file specifies (including the MailChimp API v3.0 PHP library specified by our custom module) in one of two ways:

From the command line, we can run the following drush commands:

$ drush composer-json-rebuild
$ drush composer-manager install

Alternatively, we could include the following lines in an update hook:

// Re-build Composer Manager composer.json and run composer update.
drush_composer_manager_composer_json_rebuild();
drush_composer_manager('update');

For Drupal 8 sites, the process is slightly different. As mentioned previously, as of release 8.1.0, Drupal core directly uses Composer to manage dependencies and the Composer Manager module is no longer necessary. For Drupal 8 sites, we should follow the Drupal.org instructions for managing dependencies for a custom project. Following those instructions ensures that all of the site’s dependencies, including the MailChimp library specified by our custom module, are installed.

Use the library

Once we have the MailChimp API v3.0 PHP library installed, we can use it in our custom module to subscribe users to mailing lists.

We suggest creating a dedicated function for subscribing users to email lists which can then be called throughout the custom module. For our purposes, we modeled that function off of the Mailchimp module (version 7.x-4.6) mailchimp_subscribe_process() function.

We implemented the following function, which can be reviewed and modified for your specific purposes:

<?php
/**
 * Add an email to a MailChimp list.
 *
 * This code is based on the 7.x-4.6 version of the Mailchimp module,
 * specifically the mailchimp_subscribe_process() function. That version of
 * the Mailchimp contrib module makes use of the ThinkShout PHP library for
 * version 3.0 of the MailChimp API. See the following for more detail:
 * https://www.drupal.org/project/mailchimp
 * https://github.com/thinkshout/mailchimp-api-php.
 *
 * @see Mailchimp_Lists::subscribe()
 *
 * @param string $api_key
 *   The MailChimp API key.
 * @param string $list_id
 *   The MailChimp list id that the user should be subscribed to.
 * @param string $email
 *   The email address for the user being subscribed to the mailing list.
 */
function mymodule_subscribe_user($api_key, $list_id, $email) {

  try {
    // Set the timeout to something that won't take down the Drupal site:
    $timeout = 60;
    // Get an instance of the MailchimpLists class.
    $mailchimp = new \Mailchimp\MailchimpLists($api_key, 'apikey', $timeout);

    // Use MEMBER_STATUS_PENDING to require double opt-in for the subscriber. Otherwise, use MEMBER_STATUS_SUBSCRIBED.
    $parameters = array(
      'status' => \Mailchimp\MailchimpLists::MEMBER_STATUS_PENDING,
      'email_type' => 'html',
    );

    // Subscribe user to the list.
    $result = $mailchimp->addOrUpdateMember($list_id, $email, $parameters);

    if (isset($result->id)) {
      watchdog('mymodule', [email protected] was subscribed to list @list.',
        array([email protected]' => $email, [email protected]' => $list_id), WATCHDOG_NOTICE
      );
    }
    else {
      watchdog('mymodule', 'A problem occurred subscribing @email to list @list.', array(
        [email protected]' => $email,
        [email protected]' => $list_id,
      ), WATCHDOG_WARNING);
    }
  }
  catch (Exception $e) {
    // The user was not subscribed so log to watchdog.
    watchdog('mymodule', 'An error occurred subscribing @email to list @list. Status code @code. "%message"', array(
      [email protected]' => $email,
      [email protected]' => $list_id,
      '%message' => $e->getMessage(),
      [email protected]' => $e->getCode(),
    ), WATCHDOG_ERROR);
  }
}

With that function defined, we can then subscribe an email address to a specific Mailchimp mailing list through the following function call in our custom module:

mymodule_subscribe_user($api_key, $list_id, $email);

Conclusion

By taking advantage of the modern PHP ecosystem built on reusable Composer managed packages, we can easily build or adapt a custom module to subscribe users to mailing lists without the MailChimp contributed module.

Lastly, a special thanks to ThinkShout for their hard work maintaining the MailChimp module and creating the library, on which this approach depends!

About the author

Recent posts by Savas Labs

Oct 25, 2016

A step-by-step guide to how we deploy our gulpified Jekyll site to GitHub Pages using Travis, opening the door for...

Oct 19, 2016

How we improved our company site’s performance with a better Jekyll workflow

Sep 23, 2016

SEO trends 2017 and Drupal 8 as the best option for your long-term marketing campaign.

Nov 14 2016
Nov 14

A lot of effort goes into engaging your visitors to ‘Sign-up’ or ‘Contact’ you. You send them a warm and fuzzy invitation to complete the form, tell them all the great reasons why they should complete the form… but who likes to complete a form? You can help guarantee a smooth sign-up process and increase the completion rate of your web forms with these five tips.

#1 Make it Flow

Before you begin designing that web form, it is always good to create a User Flowchart. Working to establish the form completion process from start to finish, a flowchart will help you:

  • Determine what information is needed (and when)

  • Decide what actions and interactions are appropriate

  • Determine the order of actions

  • Make considerations for new patterns to aid the completion process

A User Flowchart can begin with a simple Flow Outline, which can then be placed in a flowchart diagram and later illustrated using low-fidelity paper prototypes to find the most natural set of actions. When creating the outline consider the following:

  • The Business Objective

    • What is the main objective of the website for achieving successful completion of the form? (ie, we want to gather as many email addresses as possible.)

    • What is the required information needed from the person completing the form? (ie, we need their name and email, and since our site is only for adults we also need their birthdate.)

  • The User Persona

    • Take advantage of the information gained from the User Personas to focus on the user’s various needs and considerations. What problem do they want to solve and how can this form help them?

    • What devices do they access most frequently to complete web forms? It’s good to know in advance if most of the users complete forms on their mobile phones and/or if they have inferior internet connectivity.

  • The Entry Point

    • When designing a User Flowchart, keep in mind the point of entry. Perhaps they arrive after clicking the Call to Action on the homepage. But often web forms are a part of an email or social media campaign, or the user arrives at the form after an organic search. The users should be treated differently based on where they come from and may need ‘orientation’ when they arrive. Consider all possibilities.

#2 Keep it Short and Sweet

Don’t ask for information that’s not needed. Your sign-up or contact form should only ask for the bare necessities needed in order to accomplish that goal. People will usually stick around long enough to enter their name, email address, and password. Anything more than that should be the absolute minimum amount of information needed, with further data obtained in follow-up communications. No one enjoys completing a form, so keep it as simple as possible!

  • Email Address

    • Forward thinking email form fields provide suggestions for fixes when the email address has been entered incorrectly. … Did you mean @gmail.com?

    • If you include an auto fix for mistyped email addresses you won’t need to require the user to enter it twice. Otherwise, it’s is a good approach to provide the extra guarantee that they’ve got it right.

    • When the form is for creating an account or signing up for a newsletter, a current practice is to use the email address for the account instead of providing a separate username. This will cause less frustration with creating one that is not already in use, as well as remembering it every time they log in.

  • Name

    • The person’s name is really only needed in instances where account personalization or custom communication is used. A frequent approach is to provide one field for their full name. This is a bonus since some users may have more than two words that make up their full name, and one field takes less time to complete (especially on mobile devices). Check first to see if the system requires the first name to be isolated for marketing purposes.
       

  • Password

    • Enough with the confirm password already! They will lower your conversion rates. Give the user the option to actually SEE the password they’re entering with a ‘show password’ toggle and they won’t have to enter it twice.

    • Include a Password Strength Indicator. You can get creative with messaging to encourage users to try harder when creating a more secure password like Geeklist does: “Crack Time: 5 minutes”

    • Give them the ability to never have to enter their password again with the ‘Remember Me’ feature.

#3 Make it Easy to Read

Including the labels and inputs, consider the context being used for all text on the page  and work to ensure your font sizes are large enough to be legible on all devices. The amount of content on the page should be considered while using best practices for accessibility.

  • Recent trends are a 14px font size at minimum.

  • When specifying a 16px font size for mobile devices, iOS will not zoom in when the user taps the field, because it’s not needed. This approach can be less distracting especially when there are multiple form fields on the page.

  • Consider the maximum amount of characters that will be needed in all cases to ensure enough room is provided to complete each field. For example, some zip codes in other countries use a varying number of digits.

#4 Inform Everything

  • Label All Things

    • The label of the form field you want the user to complete should ALWAYS remain visible. The labels can be placed outside of the field near the top, right, or left — or even better — use the Infield Top Aligned Label. This popular new approach has been found to be the quickest to scan, has the best flow, and takes up less real estate. The labels are placed inside of the field, jumping to the top left corner as the user begins typing. Either way, at no point should the user lose sight of the information that’s needed.
       

  • Inline Form Validation

    • Inform the user as they progress if anything has been entered incorrectly or if a field is missing information. Don’t make them click the ‘Submit’ button at the end of the form only to receive a bunch of red text telling them what they have to re-do.

    • Micro interactions such as a simple green check or a red ‘X’ along with a brief message as the user completes the form will improve the workflow.

    • Tell them if their CAPS LOCK IS ON.
       

  • Required or Optional?

    • Inform the user which fields are required and which are optional for the form to be accepted. An asterisk is often used to designate required information, but they are ignored by screen readers so make sure the required fields include the HTML5 ‘required’ attribute or the aria-required set to true.
       

  • Field Details

    • Explaining the information needed for each field is another great approach. If your Registration Sign-up Form will require a password with at least 6 unique characters with 2 of them numbers, tell them! Does the phone number field require a a +, or a country code, or an area code? Tell them or show them.
       

  • Progress Bar

    • A form that’s broken into logical steps is easier to complete. If there are multiple steps that require multiple screens to complete, add a progress bar so the user knows where they are in the process.

    • If possible, add a link to the completed steps in the progress bar so the user can go back if needed.
       

  • Safety

    • Make your users feel safe during sign-up by informing them about your terms, policies, or rules.

    • Ensure them you will not share their information or spam their email.

    • Provide an easy way to cancel or opt out at any time, without much effort.

#5 Must be Mobile

While optimizing your site for mobile devices, any forms on your site should also be carefully considered. Not only are the screens smaller, but often the connections are slower, and entering text can be a bit tricky, so reducing the number of required fields is especially important. Luckily, recent innovation for mobile forms have provided modern solutions and compression techniques that could actually encourage sign-up on a mobile device:

Additional Resources
The 5 Commandments of Accessible Forms
Finger-Friendly Design: Ideal Mobile Touchscreen Target Sizes
Why the Confirm Password Field Must Die
Build It with the User in Mind: How to Design User Flow 

Nov 14 2016
jam
Nov 14
Drupal gets better when companies, organizations, and individuals build or fix something they need and then share it with the rest of us. Our community becomes better, stronger, and smarter when others take it upon themselves to make a positive difference contributing their knowledge, time, and energy to Drupal. Acquia is proud to play a part, alongside thousands of others, in some of the stories making tomorrow’s Drupal better than today’s. One of them Preston So’s.
Nov 14 2016
Nov 14

A logical progression from Website organization is defining a naming convention for URL paths. URL paths should follow a consistent naming convention throughout all of your websites. Only under exceptional circumstances should a URL path name deviate from an established naming convention for a Website.

Best practices for URL path naming conventions recommend consistency in how sections, sub-sections, pages, and sub-pages are written. For most websites, I recommend URL paths follow the general naming convention below. 

     http://domain.com/SECTION/SUB-SECTION/PAGE/SUB-PAGE

This basic structure gives users an idea of where they are in the site’s hierarchy of pages. This can be especially important considering the volume of traffic that enters the site from web searches that will bypass the homepage and take visitors directly into deeper pages in the site. It’s also a good practice for improving the SEO value of your site’s pages, as it provides more specific context for the content of the page.

Section

Under this convention, SECTION is the top-level “directory,” and generally refers to the category under which subsequent content resides. For example, in the URL path http://domain.com/about, “About” is a primary category that often appears in a main menu, and thus receives a top-level URL path.

I generally like SECTION names to be one continuous string of letters without hyphens or underscores (e.g. about, services, people, etc.) because that makes for shorter top-level URL paths, however two word hyphens may also be acceptable if they aren’t too long. Given that top-level SECTION names are usually the label-names of your main navigation, it’s additionally wise to keep them clear, simple and concise.

Acronyms and abbreviations should be avoided because they often don’t make sense to visitors unfamiliar with the abbreviations. That being said, some abbreviations, such as http://domain.com/faq, may work so long as they make logical sense to most visitors.

If your Website has multiple users who are able to write URL path names, I recommended defining in the governance plan some limitation for who may write top-level directory names. These are typically the most highly sought-after URLs in a Website, and you will want to have a well-defined process for how those are distributed and assigned. A free-for-all is probably not a good process.

Sub-Section

SUB-SECTION is the second-level directory, if one exists. Using About as an example, “Meet Our Team” is the second-level “directory” in the URL path:

     http://domain.com/about/team

since “Meet Our Team” is just one of the sub-sections under “About” in this example.

SUB-SECTION names also may be one continuous string of letters without hyphens or underscores, such as:

     http://domain.com/about/team

or a string of words separated by hyphens:

     http://domain.com/about/meet-our-team.

The choice between the two really depends on whether the additional words add value to the user’s understanding of location, and/or if the string of words adds SEO value because it captures important descriptive words for the content of the page.

In the example above, the words “meet our” really don’t add much information, and the shorter URL path name is simpler. Simplicity may become more important as you add pages to sub-sections and the URL path names become very long.

Some URL path names may appear to deviate from this rule if a sub-section does not actually exist, in which case the sub-section location would be occupied by the page name.

Page

Pages on the “Meet Our Team” site would then have a URL path structure of:

     http://domain.com/about/team/PAGE-NAME

where PAGE-NAME could be any number of different page names. PAGE-NAMEs should generally describe the content of the page based on the page’s title. This can be expressed either as a single word (if a single word sufficiently describes the page), such as:

     http://domain.com/about/team/consultants

where “consultants” is a page for information about consultants on the team titled “Consultants”; or by a string of hyphenated words, such as:

     http://domain.com/about/team/website-consultants

where “website-consultants” is a page about Website consultants on the team titled “Web Consultants.”

For the purposes of SEO, at the page level, I generally prefer to include all of the keywords in a page’s title (separated by hyphens) in the URL path, especially when it adds descriptive value.

Sub-Page

As follows, sub-pages for any of the pages in the “Meet Our Team” site would have a URL path structure:

     http://domain.com/about/team/PAGE-NAME/SUB-PAGE-NAME SUB-PAGE-NAMEs

should follow the same rules as PAGE-NAMEs, however sub-page names may require longer strings of hyphenated names as pages become more detailed and specific:

     http://domain.com/about/team/consultants/drupal-content-management-system

Conversely, if sub-pages are breaking out content into simpler categories, they may benefit from shorter names:

     http://domain.com/about/services/web-platforms/drupal

rather than:

     http://domain.com/about/services/web-platforms/drupal-content-management...

All of that being said, you should determine the system that works best for your needs and stick to it. Just keep it simple, logical, and as memorable as possible so that it is easy for all users to implement.

Multiple-Word Names

When writing URL paths with multiple-word names, I recommend using hyphens, such as:

     http://domain.com/about/services/web-platforms/drupal-content-management...

rather than underscores:

     http://domain.com/about/services/web_platforms/drupal_content_management...

or concatenation:

     http://domain.com/about/services/webplatforms/drupalcontentmanagementsystem

Use of underscores makes it far too easy for a user to misread an underscore as a space, especially when the URL path is hyperlinked:

     http://domain.com/about/services/web_platforms/drupal_content_management...

Most hyperlinks are underlined to indicate to users that a section of text is a hyperlink.

Concatenation is more obviously problematic because it simply creates confusing URL paths.

Aliases & Redirects

How URL path aliases and redirected URL paths are handled will depend on the policies of your organization and the platform you use for your Website. I highly recommend you define the rules and processes surrounding URL aliases and redirects in your governance plan, and here are some questions to consider along those lines.

  • How are URL aliases and redirects managed in your Web environment?
  • Who manages URL aliases and redirects?
  • Is there a process or procedure for requesting an alias or a redirect?
  • May anyone request a URL alias or redirect?
  • Are redirects to Websites outside of your domain or server environment permitted?
  • Who determines whether a URL alias or redirected URL path is appropriate or not?
  • Are there any special rules for using top-level directories as URL path aliases or redirected URL paths?

This post is part of a larger series of posts, which make up a Guide to Digital Governance Planning. The sections follow a specific order intended to help you start at a high-level of thinking and then focus on greater and greater levels of detail. The sections of the guide are as follows:

  1. Starting at the 10,000ft View – Define the digital ecosystem your governance planning will encompass.
  2. Properties and Platforms – Define all the sites, applications and tools that live in your digital ecosystem.
  3. Ownership – Consider who ultimately owns and is responsible for each site, application and tool.
  4. Intended Use – Establish the fundamental purpose for the use of each site, application and tool.
  5. Roles and Permissions – Define who should be able to do what in each system.
  6. Content – Understand how ownership and permissions should apply to content.
  7. Organization – Establish how the content in your digital properties should be organized and structured.
  8. URL Naming Conventions – Define how URL patterns should be structured in your websites.
  9. Design – Determine who owns and is responsible for the many aspects design plays in digital communications and properties.
  10. Personal Websites – Consider the relationship your organization should have with personal websites of members of your organization.
  11. Private Websites, Intranets and Portals – Determine the policies that should govern site which are not available to the public.
  12. Web-Based Applications – Consider use and ownership of web-based tools and applications.
  13. E-Commerce – Determine the role of e-commerce in your website.
  14. Broadcast Email – Establish guidelines for the use of broadcast email to constituents and customers.
  15. Social Media – Set standards for the establishment and use of social media tools within the organization.
  16. Digital Communications Governance – Keep the guidelines you create updated and relevant.

Stay connected with the latest news on web strategy, design, and development.

Sign up for our newsletter.
Nov 14 2016
Nov 14

Latest DrupalConsole rc-9 is out including several changes and fixes.

Support for command aliases

Aliases for commands added making easy to memorize by typing less. You can find aliases definition at https://github.com/hechoendrupal/drupal-console-core/blob/master/config/dist/aliases.yml

Support to execute the DrupalConsole Launcher on Windows platform

This PR https://github.com/hechoendrupal/drupal-console-launcher/pull/51 fixes the `\vendor\bin\drupal.php` file not found error.

Execute DrupalConsole from any directory within your Drupal site

No need to stay at site root directory. You can now switch to any directory as modules, themes, web/modules/custom or any other directory within your Drupal site. This was possible using the DrupalFinder project https://github.com/webflo/drupal-finder/

NOTE: Having a configuration file containing `root: web` on the site is no longer required. You can keep the file but is required to remove that value from your `path/to/drupal8/console/config.yml`

Improvements on the `init` command 

The interactive mode for the init command now ask you and show a list of directories where to copy the configuration files.

Update instructions:

Nov 12 2016
xjm
Nov 12

As a best practice, development tools should not be deployed on production sites. Accordingly, packaged Drupal 8 stable releases will no longer contain development PHP libraries, because development code is not guaranteed to be secure or stable for production.

This only applies to a few optional libraries that are provided with Drupal 8 for development purposes. The many stable required libraries for Drupal 8, like Symfony and Twig, will still be included automatically in packaged releases. Drupal 7 is not affected.

Updating your site

To adopt this best practice for your site, do one of the following (depending on how you install Drupal):

  • If you install Drupal using the stable release packages provided by Drupal.org (for example, with an archive like drupal-8.2.2.tar.gz or via Drush), update to the next release (8.2.3) as soon as it is available. (Read about core release windows.) Be sure to follow the core update instructions, including removing old vendor files. Once updated, your site will no longer include development libraries and no further action will be needed.
  • If you use a development snapshot on your production site (like 8.2.x-dev), you should either update to a stable release (preferred) or manually remove the dependencies. Remember that development snapshots are not supported for production sites.
  • If you install your site via Composer, you should update your workflows to ensure you specify --no-dev for your production sites.

Development and continuous integration workflows

If you have a continuous integration workflow or development site that uses these development dependencies, your workflow might be impacted by this change. If you installed from a stable Drupal.org package and need the development dependencies, you have three options:

  1. Install Composer and run composer install --dev,
  2. Use a development snapshot (for example, 8.2.x-dev) instead of a tagged release for your development site, or
  3. Install the development dependencies you need manually into Drupal's vendor directory or elsewhere.

However, remember that these development libraries should not be installed on production sites.

For background on this change, see Use "composer install --no-dev" to create tagged core packages. For more information on Composer workflows for Drupal, see Using Composer to manage Drupal site dependencies.

Nov 11 2016
Nov 11

In such a time, i want to place blocks in sidebar region with the dynamic weight. It means the blocks should render in different position for each page request. I have searched and tried lots of method but unfortunately i can’t find proper method to do that. So i have decided to do that with some hacky way.

Drupal 8 is providing a hook to alter the region template_preprocess_region, it would prepares values to the theme_region. I have planned to use the hook to alter the block's position to be rendered in the region.

Adding the following codes in THEMENAME.theme file would solve the problems,

function themename_preprocess_region(&$variables) {
  if ($variables['region'] == 'sidebar_second') {
    $variables['elements'] = shuffle_assoc($variables['elements']);
    $content = '';
    foreach ($variables['elements'] as $key => $value) {
      if (is_array($variables['elements'][$key])) {
        $content .= \Drupal::service ('renderer')->render($value);
      }
    }
    $variables['content'] = array(
      '#markup' => $content,
    );
  }
}

function shuffle_assoc($list) {
  if (!is_array($list)) {
    return $list;
  }

  $keys = array_keys($list);
  shuffle($keys);
  $random = array();
  foreach ($keys as $key) {
    $random[$key] = $list[$key];
  }
  return $random;
}

It is working well in my site but i know it is the hacky way, not sure about the proper way to do that. If anyone of you know about this kindly share it in the comments :)

Nov 11 2016
Nov 11

The Field API allows custom data fields to be attached to Drupal entities and takes care of storing, loading, editing, and rendering field data. Any entity type (node, user, etc.) can use the Field API to make itself “fieldable” and thus allow fields to be attached to it. Other modules can provide a user interface for managing custom fields via a web browser as well as a wide and flexible variety of data type, form element, and display format capabilities.

The Field API defines two primary data structures, Field and Instance, and the concept of a Bundle. A Field defines a particular type of data that can be attached to entities. A Field Instance is a Field attached to a single Bundle. A Bundle is a set of fields that are treated as a group by the Field Attach API and is related to a single fieldable entity type.

For example, suppose a site administrator wants Article nodes to have a subtitle and photo. Using the Field API or Field UI module, the administrator creates a field named ‘subtitle’ of type ‘text’ and a field named ‘photo’ of type ‘image’. The administrator (again, via a UI) creates two Field Instances, one attaching the field ‘subtitle’ to the ‘node’ bundle ‘article’ and one attaching the field ‘photo’ to the ‘node’ bundle ‘article’. When the node system uses the Field Attach API to load all fields for an Article node, it passes the node’s entity type (which is ‘node’) and content type (which is ‘article’) as the node’s bundle. field_attach_load() then loads the ‘subtitle’ and ‘photo’ fields because they are both attached to the ‘node’ bundle ‘article’.

Field definitions are represented as an array of key/value pairs.

Note that the above answer has been excerpted from the Drupal API Documentation, where more information can be found.

Nov 11 2016
Nov 11

Twig can be extended in many ways; you can add extra tags, filters, tests, operators, global variables, and functions. You can even extend the parser itself with node visitors. In this blog,

I am going to show you how to create new custom twig filters in drupal. For example we are going to create a filter to remove numbers from string, will explain with hello_world module.

Create hello_world folder in modules/custom/ folder with the following files,

1. hello_world.info.yml // It would contains normal module .info.yml file values, Check here for more details

2. hello_world.services.yml // It would contain following lines,

services:
  hello_world.twig_extension:
    arguments: [[email protected]']
    class: Drupal\hello_world\TwigExtension\RemoveNumbers
    tags:
      - { name: twig.extension }

3. src/TwigExtension/RemoveNumbers.php It would contain followings in that,


namespace Drupal\hello_world\TwigExtension;


class RemoveNumbers extends \Twig_Extension {    

  /**
   * Generates a list of all Twig filters that this extension defines.
   */
  public function getFilters() {
    return [
      new \Twig_SimpleFilter('removenum', array($this, 'removeNumbers')),
    ];
  }

  /**
   * Gets a unique identifier for this Twig extension.
   */
  public function getName() {
    return 'hello_world.twig_extension';
  }

  /**
   * Replaces all numbers from the string.
   */
  public static function removeNumbers($string) {
    return preg_replace('#[0-9]*#', '', $string);
  }

}

Enable the hello_world module and clear the cache, then you could use the “ removenum “ filters in your twig file,


{{ twig-value-with-numbers | removenum }}

It would remove the all numbers from the string, enjoy with your custom filters !

Download the hello_world module here

Nov 11 2016
Nov 11

One of the most favourite and  valuable features in drupal is multisite configuration, Drupal 8 provide simple way to create multisite it reduced lots of works. The following steps shows to configure multisite in drupal 8,

  • Should have more than one domain and databases, I am going to use the domain (www.domain1.com, www.domain2.com) and databases (domain1, domain2).
  • Create two folders in drupal-8/sites/ folder with domain1, domain2 name, the folder path would be like this drupal-8/sites/domain1/ and drupal-8/sites/domain2/
  • Create files/ folder in both the folder (drupal-8/sites/domain1/files)
  • Copy the default.settings.php file and paste it into the both folder then rename it as settings.php ( drupal-8/sites/domain1/settings.php, drupal-8/sites/domain1/settings.php)
  • Edit the settings.php file for domain1 to adding the database,
$databases['default']['default'] = array (
  'database' => 'domain1', // Change value to domain1 for www.domain.com and domain2 for www.domain2.com.
  'username' => 'root',
  'password' => 'root',
  'prefix' => '',
  'host' => 'localhost',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);
  • Copy the drupal-8/sites/example.sites.php file and paste in on the same location then change the file name to sites.php (drupal-8/sites/sites.php)
  • Add the following line in the bottom of the drupal-8/sites/sites.php file
$sites = array(
 'domain1' => 'domain1.com', // Folder name => Domain name.
 'domain2' => 'domain2.com',
);

Thats all, both domain would works well with the different db with a single instance.

Nov 11 2016
Nov 11

I needed a way to check the currect user has permission to view the currect/particular page, Searched lot finally got the exact way, going to show the tricks to you in this blog.

Drupal has an api called " drupal_valid_path " , Normally it used to test the url is valid or not. but the trick is that, It also check the user has permission to view the currect/particular page.

It will return TRUE If path is valid and user has permission to view the page, otherwise it will return FALSE,

For example,

$path = current_path();
if (drupal_valid_path($path)) {
  // Your code here.
}
Nov 11 2016
Nov 11

Most of the times developers don't like the GUI, It makes feel lazy. Drupal has a tool (Drush) to do some management work from command line.

And also the installing the drupal site makes very lazy while doing with browser, The Drush has an option to install the full site with a single command.

The Following command will install the drupal in standard method,

drush site-install standard --account-name=admin --account-pass=[useruser_pass] --db-url=mysql://[db_user]:[db_pass]@localhost/[db_name]
Nov 11 2016
Nov 11

Read our Roadmap to understand how this work falls into priorities set by the Drupal Association with direction and collaboration from the Board and community.

The Drupal Association team has been getting back to work after coming back from DrupalCon Dublin in September. For the engineering team, October has been focused on some back-end services and infrastructure that support the Drupal project, while we continue to move forward on some longer term front facing initiatives.

Drupal.org updates

Promoting Drupal by Industry

Last month we talked about the new homepage we released for Drupal.org, and using those editorial tools to build a membership campaign. We hinted that additional changes will be coming soon. While we're not ready to launch this new content - we can talk about it in some greater detail.

Dries Buytaert, the project founder, has called Drupal the platform for ambitious digital experiences. That phrase expresses the incredible power and flexibility of Drupal, but also encapsulates an aspect of Drupal that can be difficult for newcomers. It can be very hard for newcomers to Drupal to understand how to take a base install of Drupal core, and extend that to achieve that ambitious vision.

We want to help close that gap in understanding—to help evaluators see how Drupal achieves these ambitions. To do this, we'll be creating a series of landing pages that focus granularly on how Drupal creates success stories in particular industries. Look for more on this topic in coming months.

DrupalCon Vienna Site Launched

Vienna 2017 Logo

As is tradition, during the closing session of DrupalCon Dublin we announced that the next DrupalCon in Europe will be held in Vienna! We launched the splash page announcing the event at vienna2017.drupal.org and we have information about sponsorship and hotel reservations already available.

DrupalCon Vienna will happen from the 25th to 29th of September 2017, and we'll hope to see you there!

More flexible project testing

We've made a significant update to how tests are configured on the Automated Testing tab of any project hosted on Drupal.org. Automated testing, using the DrupalCI infrastructure, allows developers to ensure their code will be compatible with core, and with a variety of PHP versions and database environments. In October, we updated the configuration options for module maintainers.

Maintainers can now select a specific branch of core, a specific environment, and select whether to run the test once, daily, on commit, or for issues. Issues are limited to a single test configuration, to ensure that the code works in a single environment before being regression tested against multiple environments on on-commit or daily tests.

Better database replication and reliability

Behind the scenes, we've made some updates to our database cluster - part of our infrastructure standardization on Debian 8 environments managed in Puppet 4. We've made some improvements to replication and reliability - and while these changes are very much behind the scenes they should help maintain a reliable and performant Drupal.org.

Response to Critical Security Vulnerabilities

DirtyCow Public Domain Logo

When it rains, it pours—a maxim we take to heart in Portland, Oregon—and that was especially true in the realm of security in October. The most widely known vulnerability disclosed was the 'DirtyCow' vulnerability in the Linux kernel. A flaw in the copy-on-write system of the Linux kernel made it possible, in principle, for an unprivileged user to elevate their own privileges.

Naturally, responding to this vulnerability was a high priority in October, but DirtyCow was not the only vulnerability disclosed, as security releases were also made for PHP, mariadb, tar, libxslt, and curl. We mitigated each of these vulnerabilities in short order.

Community Initiatives

Community initiatives are a collaboration; with dedicated community volunteers building improvements to Drupal.org with the architectural guidance and oversight of the Drupal Association engineering team.

Drupal 8 User Guide

The Drupal 8 User Guide is getting very close to being available on Drupal.org. We are working closely with contributor jhodgdon to resolve some perplexing inconsistencies between what we're seeing in our development environment and in our initial production deployment.

Dreditor

markcarver who is currently leading the charge to port Dreditor features to Drupal.org, has invited anyone interested in contributing to join him in #dreditor on freenode IRC or the Dreditor GitHub.

Documentation Maintainership

Finally, we want to continue to encourage the community to become maintainers of Drupal documentation. If you are a developer interested in contributing code to the new documentation system, please contact tvn.

———

As always, we’d like to say thanks to all the volunteers who work with us, and to the Drupal Association Supporters, who made it possible for us to work on these projects.

If you would like to support our work as an individual or an organization, consider becoming a member of the Drupal Association.

Follow us on Twitter for regular updates: @drupal_org, @drupal_infra

Nov 11 2016
Nov 11

Very often in a migration of Drupal 6/7 to Drupal 8, have a need to run and test the migration many times. This applies more to sites that are very active, where site editors are updating or adding new content.

Keep in mind that the Migration API in Drupal 8 offers a few paths to run migrations. The first is a user interface to make migrations through the path /upgrade. Through this method, the migration process is once and you can not make any customizations.

The other method is to use drush to upgrade. And it is done by using these steps:

  1. Generate migration configuration. Example:
    drush migrate-upgrade --legacy-db-url=mysql://root:[email protected]/drupal6 --legacy-root=/var/www/drupal6 --migration-prefix=”” --configure-only) 
    
  2. Migrating structure and configuration of the old site, eg variables, blocks, vocabularies, content types, etc. Example:
     drush migrate-import --tag=Configuration 
    
  3. Make configuration changes generated by migration. Example: revert the default text in Drupal 8's default email welcome messages for new user that were changed by migration. Make other changes as necessary too. Then export the configuration. Example:
    drush config-export 
    
  4. Finally migrate all content of nodes, terms of taxonomies, etc. Example:
    drush migrate-import --tag=Content 
    

In a normal flow, step # 1 is executed only once to generate all migrations. Step # 2 is run and iterated upon a few times until the settings for the new site are all right. But after a stable configuration is establed, it can be ignored by the rest of the process once we have stored all the generated configuration in step #3. Finally, step #4 can easily be executed more than once.

With the attached patch, it is possible to do all the points above, migrations are generated and a tag type assigned to each migration depending on its type. Configuration for migrating Configuration and Content for migration of content. This is a game changer. You can now migrate all the configuration of a site, get sign-off on the site structure with a sample of content, then schedule a go-live data to pull over all the remaining content. Before, this it was terribly difficult and laborious to figure out what was content and what was site configuration. Now that isn't a problem.

Nov 11 2016
Nov 11

The Haversine formula is one of the easiest to use pieces of complicated math I've had the pleasure to use. If you're not familiar with it, it's pretty simple in theory - it's an extension of the Pythagorean formula from a grid to the surface of a sphere, which basically means that you can use it to measure the distance between two points on a sphere (1).

"But what," I hear you ask through the secret microphone hidden in your keyboard, "does this have to do with Drupal?"  And the answer is - search.  I've worked on a number of projects over the years where users wanted to search for things which were some distance from a central point - a zip code, a city, or the like.  This can be done with apache solr these days, but sometimes apache solr isn't what you need. Either you’re not doing a keyword search and just filtering your nodes (show me all mexican restaurants near 12th and Vine) or else you don't think you need the extra complexity of adding an Apache Solr instance to the project.  An index of restaurants isn't a bad idea for an example, so let’s build one.  In the tradition of Drupal demos, we'll say we're creating a restaurant search engine, which we will name 'Shout'.  So, we spin up a copy of Drupal 7, set up the usual database, add a 'Restaurant' node type, download Fivestar* to do ratings, set up a few quick taxonomies (cuisine, price range [low, medium, high], and maybe style [sit-down, food court, fast food]) which we add to the restaurant node type.

Step 1

Create a node type with location information.  To store the address there’s two good options: the Location module, which grew out of CCK, and the Address Field module, which comes from the Commerce module.

Step 2

Add the latitude and longitude to the nodes - if you’re using the location module you can enable storing those values in the same field, but if you’re starting with the address field you need to add a field which stores that information.  I recommend the Geofield module.

Step 3

Finally, you will need to set up geocoding - the process of assigning latitude and longitude based off of an address.  There’s plenty of services which will do this for you, and if you’re using the location module, then you can enable it there.  Alternately you can use the Geocoder module to store these values.

Example

Following along with our Shout example, let's add the addressfield, geofield, and geocoder modules, which will also in turn require the geoPHP and ctools modules.  Add the Address field and tell it to store a postal address, set up a geofield on the restaurant node as well and set the widget to 'geocode from another field', and take a look at the configuration of geocoder in admin/config/content/geocoder.  You can use the google api in batch for free, as long as you don't get too crazy with the number of requests per day.  This being an example site, I think we'll be safe, but when doing a commercial site it's always best to read the Google terms of service,sign up for an API key, and close cover before striking.

image of haversine formula implementation

I've named the Address field field_address, and in a fit of originality I've named the geofield field_map_location.  Once I had everything set up, I entered a few local restaurants and ran cron to make sure that I was getting data in the field_data_field_map_location table - I suggest you do the same.  (Well, to be honest, at first I wasn't getting data, but that's why we test our examples when writing blog posts.)

Step 4

Once you've got locations set up, the next step is your search engine.  For this task I suggest the Search API module, which allows you to define your own indexes, and to switch search engines in the future as the need arrives.  You’ll also need the Search API DB and Search API Pages modules.

Step 5

We'll start by setting up a service - in this case, just gave it an obvious name and select the Database engine.

image of haversine formula implementation

 

Step 6

Then we'll create an index - although Search API creates a Default node index when it's enabled, we want one just for restaurant nodes.  So we'll click on 'Add Index', give it a name of 'Restaurant Index', select that we want to index Restaurant Nodes, and put in a quick description to remind us of what it is, and select the server we just created.

image of haversine formula implementation

 

Step 7

After that, go into index fields for the index and select at least the title and the 'main body text' for indexing - I suggest including the address as well.  It's also important to add the Location field that you're using, and include the latitude and longitude values in the index.  When you can't find a field, expand the 'Add Related Fields' at the bottom and look for them there, and make sure you save your changes before leaving the page.

image of haversine formula implementation

image of haversine formula implementation

Finally, on the filter tab I suggest excluding unpublished nodes, as well as Ignoring case and adding the HTML filter.

With all that setup, use the search_api_pages module to set up a search page for the index you've constructed.

image of haversine formula implementation

With data and index set up, it's time to add the location filtering.  Let's add a quick block to filter with:


/**
 * Implements hook_block_info().
 */
function example_block_info() {
  return [
    'location' => [
      'info'  => t('Search Location Filter'),
      'cache' => DRUPAL_CACHE_GLOBAL,
    ],
  ];
}


/**
 * Implements hook_block_view().
 */
function example_block_view($delta) {
  if ($delta == 'location') {
    $block['subject'] = t('Filter by location:');
    $block['content'] = drupal_get_form('example_location_filter_form');
  }
  
  return $block;
}


/**
 * This form allows the user to restrict the search by where they are.
 */
function example_location_filter_form($form, &$form_state) {
  
  $form['center'] = array(
    '#type' => 'textfield',
    '#title' => t('From'),
    '#description' => t('Enter a zip code or city, state (ie, "Denver, CO")'),
    '#maxlength' => 64,
    '#size' => 20,
    '#default_value' => isset($_GET['center']) ? $_GET['center'] : '',
  );
  
  $distances = [5, 10, 20, 50];
  foreach ($distances as $distance) {
    $options[$distance] = t('Within @num miles', array([email protected]' => $distance));
  }
  $form['radius'] = [
    '#type' => 'radios',
    '#title' => t('Distance:'),
    '#options' => $options,
    '#default_value' => isset($_GET['radius']) ? $_GET['radius'] : 5,
  ];
  
  $form['submit'] = [
    '#type' => 'submit',
    '#value' => t('Filter'),
  ];
  $parameters = drupal_get_query_parameters(NULL, ['q', 'radius', 'center']);
  $form['clear'] = [
    '#type' => 'markup',
    '#markup' => l(t('Clear'), current_path(), array('query' => $parameters)),
  ];
  return $form;
}


/**
 * Validation handler for location filter.
 */
function example_location_filter_form_validate(&$form, &$form_state) {
  if (!empty($form_state['values']['center'])) {
    $location = trim($form_state['values']['center']);
    // Is this a postal code?
    $point = example_location_lookup($location);
    if (empty($point)) {
      form_set_error('center', t('%location is not a valid location - please enter either a postal code or a city, state (like "Denver, CO")', ['%location' => $location]));
    }
  }
}


/**
 * Form submit handler for location filter form.
 */
function example_location_filter_form_submit(&$form, &$form_state) {
  $parameters = drupal_get_query_parameters(NULL, ['q', 'radius', 'center']);
  if (!empty($form_state['values']['center'])) {
    $parameters['radius'] = $form_state['values']['radius'];
    $parameters['center'] = $form_state['values']['center'];
  }


  $form_state['redirect'] = [current_path(), ['query' => $parameters]];
}

In this case, <code>example_location_lookup()</code> looks for a latitude/longitude pair for a given location entered by the user, which I'm leaving as an exercise for the reader in hopes to keep this post short.  It should return an array with the keys 'lat' and 'long', at least.  For testing, you can have it return a fixed point until you've got that setup, like:

function example_location_lookup($location) {
  return array('lat' => 39.7392, 'long' => -104.9903);
}

So, now we can return to the Haversine formula.  Once you've got the position entered and passed along, it's time to match it against our restaurants.  Doing complex math is hard, so after a few moments of thought, we realize that anything more than the radius miles north or south, or east and west, of the center point will be too far away to bother including in the search radius, so we'll first filter on a range of latitude and longitude around the center, and then filter by the haversine formula to knock out everything outside of the circle.  For implementing the Haversine formula in SQL, I'm indebted to Ollie Jones of Plum Island Media, who does a great job of demystifying the formula here.

/**
 * Implements hook_search_api_db_query_alter().
 */
function example_search_api_db_query_alter(SelectQueryInterface &$db_query, SearchApiQueryInterface $query) {
  $field_name = variable_get('example_location_field_name', 'field_location');


  // Do we have a location?
  if (isset($_GET['center']) && isset($db_query->alterMetaData['search_api_db_fields'][$field_name . ':lat'])) {
    $location = $_GET['center'];
    $radius = isset($_GET['radius']) && is_numeric($_GET['radius']) ? $_GET['radius'] * 1 : 5;
    $point = example_location_lookup($location);
    if (!empty($point)) {
      // Basically, we make a subquery that generates the distance for each adventure, and then restrict the results from that to a bounding box.
      // Then, once that subquery is done, we check each item that survives the bounding box to check that the distance field is less than our radius.
      $latitude_field = $db_query->alterMetaData['search_api_db_fields'][$field_name . ':lat']['column'];
      $longitude_field = $db_query->alterMetaData['search_api_db_fields'][$field_name . ':lon']['column'];
      $table = $db_query->alterMetaData['search_api_db_fields'][$field_name . ':lat']['table'];
      
      $sub_query = db_select($table, 'haversine');
      $sub_query->fields('haversine', ['item_id', $latitude_field, $longitude_field]);
          // Calculate a distance column for the query that we'll filter on later.
      $sub_query->addExpression("69.0 * DEGREES(ACOS(COS(RADIANS(:p_lat))
                                      * COS(RADIANS($latitude_field))
                                      * COS(RADIANS(:p_long - $longitude_field))
                                      + SIN(RADIANS(:p_lat))
                                      * SIN(RADIANS($latitude_field))))", 'distance', [':p_lat' => $point['lat'], ':p_long' => $point['long']]);
          // Filter out anything outside of the bounding box.
      $sub_query->condition($latitude_field,  [$point['lat'] - ($radius / 69.0), $point['lat'] + ($radius / 69.0)], 'BETWEEN');
      $sub_query->condition($longitude_field, [$point['long'] - ($radius / 69.0), $point['long'] + ($radius / (69.0 * cos(deg2rad($point['lat']))))], 'BETWEEN');
      $db_query->join($sub_query, 'search_distance', 't.item_id = search_distance.item_id');
      $db_query->condition('search_distance.distance', $radius, '<');
    }
  }
}

And there you go.  In my example, I set up the page as search, and tested with the url: search/diner?radius=500&center=denver, and got back the Denver Diner, but not the New York Diner.

* It's not certain depending on which version of fivestar you get, but you might need to download the entity api module as well. Just in case you're following along at home.

(1) We're just going to ignore the fact that the Earth isn't a perfect sphere for the purposes of this article - there's a degree of error that may creep in, but honestly if you're trying to find locations within 300 miles of a city, there's already enough error creeping in on the 'center' of a city that the close approximation of the Haversine formula is a relief.

Nov 11 2016
Nov 11

After the socialist party upgraded civicrm to version 4.6 a month ago they are experiencing performance issues. In this blog I will round up our quest for performance improvements. But before that some facts about their installation.

  • +/- 350.000 contacts
  • +/- 300 users who can access civicrm and see members in their local chapter
  • +/- 2700 groups
  • There are several campaign websites linked to CiviCRM and one of their successfully campaigns leads to 7500 new contacts per week in the system
  • Running  on a VPS with 4 CPU cores and 8GB of RAM
  • around 40 active extensions

Since yesterday we have added New Relic as a monitoring tool. With New Relic we can monitor and look back in the history. We can also see all the details in each request. So we can analyze the performance. 

Above is the screenshot of the monitoring of the last 24 hours.  The red/rose squares indicates when the overall performance is poor (more than 2 seconds per request). We also see that MySQL has a big part in the  largest peaks.

The screenshots above shows the slowest queries and the slowest mysql operations. One observation is that it looks like that the MySQL delete statements are slowing the system down.

It is not clear what exactly those delete statements are or what is causing those to be slow. That is one of the questions to look into next.

Another thing we want to look into is the tuning of the MySQL database configuration and we also want to get familiar with New Relic.

Do you have any thoughts? Or did you do any performance improvements you did? We can use any help and we will keep posted about our quest for performance.

Nov 11 2016
Nov 11

When we received the new designs for the Ixis site it was evident that they contained separate design elements which were shared across several pages, from the homepage to departmental landing pages to the “About us” page. We thought this was a perfect use case for the Paragraphs module, which allows site editors to "choose on-the-fly between predefined Paragraph Types… instead of putting all of their content in one WYSIWYG body field."

Most content types on the new Ixis site contain a Paragraphs field. An editor can create multiple Paragraphs of any defined type and sort them to specify the elements and layout of the node's content.

Paragraph types can be anything from a simple text block or image to a complex and configurable slideshow. Paragraph types are essentially fieldable entities and the Paragraphs module allows the creation of these types. Each defined type can have it’s own set of relevant fields, all added via the Drupal UI and exporting to config.

So, to support the elements outlined in our page designs we added Paragraph types for:

  • Call to action - areas of bold background colour and large text;
  • Download - a downloadable asset or file;
  • Gallery - a gallery list of images;
  • Image - a single, responsive image;
  • Testimonial - a quote or testimonial;
  • Text - basic, filtered HTML edited with CKEditor;
  • Text with Callout - regular body text coupled with a styled "callout";
  • Twitter - an embedded Twitter widget;
  • Video - an embedded video from a 3rd-party site such as YouTube.

All these Paragraph types give editors some flexibility and choice when authoring a page designed with several of these elements.

Styling

The rendered output of Paragraphs entities can be altered using a paragraph.html.twig file in the site’s theme. For example:

{%
  set classes = [
    'paragraph',
    'paragraph--type--' ~ paragraph.bundle|clean_class,
    view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
    cta_style ? 'cta-style--' ~ cta_style|clean_class,
  ]
%}
<div {{ attributes.addClass(classes) }}>
  <div class="container">
    {% block paragraph_content %}
      <div class="row">
        <div class="col-sm-12">
          {{ content }}
        </div>
      </div>
    {% endblock paragraph_content %}
  </div>
</div>

The rendered output of each individual Paragraph type can also be affected using a suggested Twig template, for example we have paragraph--testimonial.twig.html for appropriately rendering a testimonial quote and cited author.

In some places we’ve used a field combined with a preprocess to provide multiple variations of the same paragraph. You can see this in action above with the cta_style variable which gives us a standard or inverted dark style for Call to action paragraphs.

Content Migration

During the initial content migration, we migrated directly into a Text Paragraph in the new Paragraphs field for some content types such as blog posts. To do this, we needed a new process plugin:

/**
 * Saves D6 Page Body field to D8 Page Paragraph (Textarea) field.
 *
 * @MigrateProcessPlugin(
 *   id = "node_paragraph_textarea"
 * )
 */
class NodeParagraphTextarea extends ProcessPluginBase {
  ...
}

We used a slightly modified version of the example plugin in this article by Amit Goyal. Then in our migration.d6.node__blog.yml we removed:

...
body/format:
  plugin: migration
    migration: d6_filter_format
    source: format
body/value: body
body/summary: teaser
...

and replaced with the new process plugin to instead migrate the source body into the Paragraphs field:

...
field_paragraphs:
  plugin: node_paragraph_textarea
  source: body
...

In summary, Paragraphs is a great alternative to a single WYSIWYG editor for site editors who want to be able to lay out complex pages combining text, images, video, audio, quotes or any other advanced component. Here's some further reading:

Nov 11 2016
Nov 11

Everything about building a website or a web application is not just coding and hosting an app. It includes a thorough ecosystem research and co-designing a scalable product to cooperate and compete within the networked internet of things. Drupal is the perfect platform to build large systems like CRM system or ERP system, which is complicated as well as data oriented.

The data acquired is first organized appropriately and then analyzed to make essential business decisions. Various underlying platforms serve critical aspects in the complete system, which work really well with applications developed with Drupal.  Management, governance and security are always on the top of the list when it comes to media and entertainment companies.

Building a complex website with Drupal is like a ladder worth climbing. You will have complete access to modules created by some of the most sought after developers in the world also, your website will run on a CMS that is designed for maximum scalability, customization and reliable maintenance. You can get endless features with Drupal using the horde of modules available, many of which are maintained by professional developers. Read more about reducing costs with big data.

How can Drupal facilitate a complicated data oriented website?  Let us look into some key features that Drupal has to offer.

CONTENT TYPES: With content types and views you can build easy to use forms that will aggregate the information entered, in all the required places. For example, when a user wants to add a new event to the site, they can fill out a simple form which will mainly include fields for the title, long or short descriptions or both, venue, date and time, duration of the event and the required Call-to-Action links. After the user submits the information, all the pieces of information are put in their rightful place including a brief introduction in the calendar, full description on the events page and a teaser on the homepage.

The same concept is used for  any type of content one would like to apply onto their website. User types, products, ads, teasers etc.

FLEXIBILITY: Drupal is a really flexible platform. The right developers can shape the system into whatever you need. It is configured to suit your needs today and also scalable to a large extent to facilitate your future needs.

SECURITY: Drupal has a really good track record in terms of being secure. It has an organized process for verifying, investigating and publishing possible security issues.
It has a dedicated team which is constantly working with the community to address security issues and they come up. 
Members of the security team sometimes perform analyses of core or contributed project code, especially if there is a weakness that can be found by easy scanning. 

SCALABILITY: If your website gets hit with a lot of traffic, it is possible that your site can go down and it won't matter even if you are delivering the world’s best digital experience. Drupal has the capability to keep your website running when you are really popular. More than a million sites are powered by Drupal worldwide for eg: Grammy awards and NBC Olympics because the get hit with traffic bursts at times. Drupal’s scalability ensures that your site will perform fabulously and always run on turbo mode even on the busiest days. 

Drupal is a great choice for for sites that will continue to grow over time. The perfect example would be examiner.com which keeps growing.

ROBUSTNESS: Apart from its scalability, Drupal platfrom is quite capable and it can handle a small mom-and-pop marketing brochure websites to huge data oriented sites like grammy.com (which can handle millions of users on the website within a period of two hours without crashing or even a glitch). No matter what size project you are looking at, Drupal is quite adequate and efficient to handle it.

FLEXIBLE FRAMEWORK: Rather than just a CMS, Drupal is a flexible framework. Drupal offers a solid foundation of solutions that majority of websites and web systems require. you can build on top of that to create any application that you require. Additionally, once the system is built in Drupal, not only can you bolt on new features in the future, there is a large community of users out there that can pick up where one left off.

OPEN SOURCE COMMUNITY:
The Drupal community is massive and very active. Of all the technology communities with which We’ve interacted, not one matches the Drupal community. Everyone is focused around the act of sharing and helping their fellow Drupal users grow. Rarely does one stumble across someone that isn’t willing to share or educate. And most of the time the answer to one of your questions (challenges) is just a Google search away. This helps shorten development time so that your websites are up and running quickly even if you come across a challenge. 

Here are some real-world examples of using Drupal for Big Data in action:

  • Consumer product companies and retail organizations are monitoring social media like Facebook and Twitter to get an unprecedented view into customer behavior, preferences, and product perception.
  • The government is making data public at both the national, state, and city level for users to develop new applications that can generate public good. 
  • Financial Services organizations are using data mined from customer interactions to slice and dice their users into finely tuned segments. This enables these financial institutions to create increasingly relevant and sophisticated offers.
  • Advertising and marketing agencies are tracking social media to understand responsiveness to campaigns, promotions, and other advertising mediums.
  • By embracing social media, retail organizations are engaging brand advocates, changing the perception of brand antagonists, and even enabling enthusiastic customers to sell their products.
  • Web-based businesses are developing information products that combine data gathered from customers to offer more appealing recommendations and more successful coupon programs.

To conclude, Drupal is the most sought after platform to build complicated data oriented systems by larger companies. It can power small to large sized businesses alike. It has a great open source community. It’s features like security and scalability are more advanced as compared to the other content management platform and development framework providing companies. It can be incorporated with big data management and is the perfect platform for it because of it’s robustness.
 

Nov 11 2016
Nov 11

First of all, sorry for the late blog. This blog refers to the drupal themes updates on November 1st. I'm currently travelling China and while I rushed to get the release out before my departure, the blog had to wait a little longer.

TL;DR

Glazed Logistics Design And Reaching Product-Market Fit

With the release of the Logistics design we addded a unique and beautiful theme to our collection while at the same time the core products only needed minor adjustments. This is an indication that the products have achieved a state of stability and product-market fit. SooperThemes now pivots to focus more on creating new designs and features based on the current core products. Of course this doesn't mean we don't add new features at all, there will always be a need for change in a turbulent environment like Drupal frontend development. 

Creating Great Design For The Drupal Community

In the past year we have laid the neccessary ground work that is needed to provide the Drupal community with much desired high quality designs. The site building workflow with Glazed theme and Carbide Builder is incredibly fast, efficient and produces precisely designed responsive Drupal websites. This doesn't just improve productivity of our customers and our customers' content creators but also our own productivity. At this point we completely design our Glazed demos using just the theme and drag and drop builder, no photoshop or coding. This big gain in productivity really allows us to focus more on art direction, photography and design. For our logistics demo we created a set of unique 3D isometric line icons, and we curated a collection of beautiful stock photography to really create the right atmosphere for our niche design. We can afford to produce such detailed niche designs thanks to the productivity gains we made with Glazed theme and Carbide Builder. Our goal of closing the gap with the top tier multi-purpose WordPress themes is now appearing on the horizon.  

Glazed Magazine Component and Drupal 8

This stability also means we will start planning our Drupal 8 upgrade and migration paths. The next couple of months we will focus on ramping up the design release cycle and on adding a new magazine component to our Glazed CMS distribution. We want to avoid spending months on Drupal 8 migration while the Drupal 7 product offering is only at an 80% market fit. We are aiming to offer more than just great theme settings and drag and drop functionality: expect a multitude of niche designs with fully features demo content in a turn-key installation profile. We strive to become Drupal's first "Mega Theme".

Value As A Service

As a subscription Drupal shop, we really focus on building long-term relationships with our customers and with the Drupal community at large. We make decisions based on what we think provides the most value to the most people. An important part of making those decisions in listening to the community. If you can spare a minute, please write a comment on the blog and describe what you would value the most in a Drupal theme. One feature I'm think about adding to the distribution is ready-made translation configuration as an optional component in the Glazed CMS distribution, let me know in the comments if that is something you would value.

Nov 10 2016
Nov 10

Start: 

2016-11-15 12:00 - 2016-11-17 12:00 UTC

Organizers: 

Event type: 

Online meeting (eg. IRC meeting)

The monthly security release window for Drupal 8 and 7 core will take place on Wednesday, November 16.

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

There will be no bug fix or feature release on this date. The next window for a Drupal core patch (bug fix) release for all branches is Wednesday, December 07. The next scheduled minor (feature) release for Drupal 8 will be on Wednesday, April 5.

Drupal 6 is end-of-life and will not receive further security releases.

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

Nov 10 2016
jam
Nov 10
A conversation with our newest community representative to the Drupal Association Board, Director at Large, Shyamala Rajaram, recorded walking to the New Orleans Convention Center during DrupalCon NOLA 2016.
Nov 10 2016
Nov 10
Matt and Mike sit down with a number of cross-functional Drupal and WordPress developers to talk about the differences and similarities between the platforms, concepts, and communities.
Nov 10 2016
Nov 10

We’re raising funds for 2017 Drupal community programs by clearing out our Drupal merchandise. Everything must go to make room for new things to come. What better time for a big Drupal swag sale, than holiday time! Give your friend, co-worker, or favorite module maintainer a Drupal hoodie, coffee mug, t-shirt, and more.

All merchandise is 50% off. Just use the coupon code BUYBYE. Sale ends 12/31!


Visit the Store

Nov 10 2016
Nov 10

Dynamic Style Guides in Drupal 8 with KSS

With a smile on my face I sat down at my desk and installed Drupal 8. I’ve been following along with the all of the feature announcements and now I had my first Drupal 8 project. The client was open-minded and receptive to ideas, so I decided to not only explore Drupal 8 but to see how far I could push it—I was going to create a living style guide.

The designer in me loves style guides. They allow me to talk through design choices and serve as a point of reference for discussions with marketing, design, and development. When you have new needs you add a component to your style guide to see how it fits in, and when a component retires you can remove it. The pain point with style guides is that they are their own artifact and frankly, once created, they rarely get tended to or updated.

Keeping It Living

Drupal 8 solves this problem with its “get off the island” thinking. This means that instead of needing to create something “in Drupal,” I was free to use tools from around the Web. A pair of my favorite style guide tools—Twig and KSS—work wonderfully with Drupal 8.

Every website has a wealth of components that need to be built and maintained. The header may have the site logo, navigation, search bar; the footer has utility navigation, social media, and a feed of the latest content; and the main content area has all the wonderful things that folks come to the site for, articles, image galleries, and forms to sign up for more information.

When we use a component-driven design approach, we are better able to maintain a site and provide consistency. We can predict changes across the whole site. By having a style guide, a client can see how the design comes together and understand how the whole will work.

What is KSS?

KSS (or Knyle Style Sheets) is documentation for humans. You enter some information into your CSS (or SASS, LESS, etc.) and when the CSS is processed by KSS, a style guide is created.

Let’s go through a common example: creating buttons. For our buttons, we’re going to create a call to action button and a disabled button. We’ll start by adding the following comment to the top of our buttons.scss file.


// Buttons
//
// .button--call-to-action - Call to action button.
// .button--disabled - Disabled button.
//
// Markup: buttons.twig
//
// Style guide: components.button
//

Let’s breakdown the content of this comment and how it relates to KSS.

The first line, “Buttons,” is the header for the section in the style guide.

The next few lines define our alternate classes for the buttons. This is because KSS will generate all the examples that we need to demonstrate the different states of the button.

For the markup, there are two ways to integrate it with KSS. The first, which isn’t shown here, is to actually write the code in the CSS comment, e.g. <a href="#" class="button {{ modifier_class }}">{{ label }}</a>. We aren’t doing that here because we want the markup to be in its own file so that it can be used by Drupal templates. Because of that, we point to a separate TWIG file.

The last line in the comment, “Style guide,” is how we keep the style guide organized. References can be either be numbers (1.2.1) or alpha (a.b.a or components.button). Use whatever makes sense for you and your team.

Using KSS to Build Components

Let’s build another component, a promo card, to show this process. This promo card is going to be a self-contained element on the site that will be used to promote content and entice users to click through.

Here is the HTML for the promo card as card--promo.twig:

<article 
  {% if attributes %}
    {{ attributes.addClass('card-promo') }}
  {% else %}
    class="{{ classes }} {{ modifier_class }}"
  {% endif %}
>
  <h2>{{ label }}</h2>
  {% if content.body %}
    {{ content.body }}
  {% else %}
    {{ body }}
  {% endif %}
</article>

Here is the SCSS for the promo card as card--promo.scss:


.card-promo {
  border: 1px solid rebeccapurple;
  border-radius: 3px;
  max-width: 300px;
  padding: 20px;

  h2 {
    margin-top: 0;
    color: rebeccapurple;
    font-family: $font-family--garamond; 
    font-size: 1.5em;
    text-transform: none;
  }

  &:hover,
  &.pseudo-class-hover {
    border-color: red;
    color: red;

    h2 {
      color: red;
    }
  }
}

And now we add our KSS comment at the top of card--promo.scss:


// Promo Card
// This promo card is used to promote content on the site.
//
// :hover - Hover state for the promo card.
//
// Markup: card--promo.twig
//
// Style guide: components.card.promo
//

Bringing all this together in the style guide shows us what the card will look like.

Promo card

Making Components out of Components

Now that the single promo card has been built we can create an example of what a row of three promo cards might look like in the site.

Since we are using TWIG, we will simply include card--promo.twig into our new component, card--triptych.twig. (A triptych is a piece of artwork shown in three panels. This is a bit of my art history studies influencing my naming conventions.)

Here is card--triptych.twig:

<section class="card-triptych-wrapper">
  {% include 'card-promo.twig' %}
  {% include 'card-promo.twig' %}
  {% include 'card-promo.twig' %}
</section>

And here is the corresponding card--triptych.scss:


.card-triptych-wrapper {
  display: flex;
  flex-flow: row nowrap;

  .card-promo {
    margin: 0 10px;
  }
}

Now that we have the HTML and CSS written, let’s add the KSS comment at the top of card--triptych.scss:


// Promo Card Triptych
// This shows the cards in a row of three, just like on the home page.
//
// Markup: card--triptych.twig
//
// Style guide: components.card.triptych
//

And here you can see the triptych in action:

Promo card triptych

Adding KSS Components to Drupal Templates

Now that we’ve put together a few components and got the client’s acceptance, it is time to connect our templates with Drupal templates. We’re going to connect up the promo card with an article teaser view.

Now we will setup our Drupal template. We start by creating the file that we need, node--article--teaser.html.twig. Inside this file we will be extending our original card file, card--promo.twig, and overwriting generic style guide content with Drupal-specific content.

{#
/**
 * Extending the base template for Drupal.
 */
#}
{% extends "@styleguide/card-promo.twig" %}

With this in place every change or edit that we make to our promo cards will be reflected on the live Drupal 8 site!

Creating Dynamic Style Guides Benefits the Whole Project

This component-driven approach is a big win for everyone in the process. The client wins because they can always see what is going on in their site via the style guide and make decisions based on live comps. Backend developers win because connecting Drupal templates to other TWIG files is an easy process. Frontend developers win because they can use their own organization structure or methodology for building components. And designers (who code) win because they can use their own skills to create components.

If you’d like to play with KSS and Drupal yourself here is a repo for you.

Stay tuned next week for part three of our frontend style guide miniseries, when Evan Willhite will cover atomic design principles with Pattern Lab!

Nov 10 2016
Nov 10

TLDR;

  1. Add "Reverse order in admin view" option: https://www.drupal.org/node/2821631
  2. Fix a problem that causes the queue to be always required when using "Limit to a specific entity queue": https://www.drupal.org/node/2478685
  3. Add a tab for Entityqueue on content types: https://www.drupal.org/node/2145441
  4. Make "Contextual links" work for views using Entityqueue: https://www.drupal.org/node/2825773

When using the Entityqueue module in Drupal 8 as a tool for editors and site admins to order content, you will end up working on the following use cases:

  • Use case 1: Use Entityqueue as a filter: shows only the items chosen in the queue.
  • Use case 2: Use Entityqueue as a loose sorting tool: does NOT limit the items based on queue, but prioritizes the items chosen in the queue to be displayed first, then shows the rest, perhaps in a reverse chronological order.

These are the most common use cases we use at Vardot for our clients when we build a site.

Use case 1 works perfectly if you use Entityqueue as is.

However, use case 2 does not work properly. Therefore, we have contributed (or contributed to), two patches that would make life easier to build a solid experience using the Entityqueue module in Drupal 8.

Added to that, we also patched two missing features that existed in Nodequeue, and should now exist in Entityqueue for Drupal 8.

Note: this post was written in November 10, 2016, which until this date, these patches are not yet committed to Entityqueue. Please review the patches, we hope that they get committed and become part of the next Entityqueue release.

1. Queue is always required when using "Limit to a specific entity queue"

Issue link: https://www.drupal.org/node/2821631

Needed for use case 2, you will most likely need your view to limit results to only items in the entity queue your joining in.

Limit to a specific entity queue - Drupal 8 Entityqueue

 

2. Get the good old "Reverse order in admin view" option

Issue link: https://www.drupal.org/node/2478685

For use case 2, this option will come in handy, since you will be sorting in reverse chronological order after the items in the queue are shown first.
Therefore, this nice workaround allows you check "Reverse order in admin view" to ensure the items in queue appear first in view when you sort.

Reverse order in admin view - Drupal 8 Entityqueue

 

3. Get the good old Nodequeue tab to appear along with content tabs

Issue link: https://www.drupal.org/node/2145441

If I'm an editor or a site admin, it wouldn't make sense to me to see the queues that I can add a piece of content to.

This tab has been missed from Entityqueue, now it comes back.

Entityqueue tab - Drupal 8 Entityqueue

4. Get Contextual Links to send you directly to the queue edit page

Issue link: https://www.drupal.org/node/2825773

Plans for this is to integrate with the new outside-in approach of Drupal 8.2 using the Settings Tray module.

This patch provides you as an editor or site admin, to go directly to the queue from the front end using the contextual links, instead of searching for the queue by its name from the admin view.

Entityqueue Contextual links - Drupal 8 Entityqueue

Let's hope these patches get committed and pushed to Entityqueue module.

This tab has been missed from Entityqueue, now it comes back.

Nov 10 2016
Nov 10

Last week Acquia announced a partnership with Magento. I wanted to use this opportunity to explain why I am excited about this. I also want to take a step back and share what I see is a big opportunity for both Drupal, Acquia and commerce platforms.

State of the commerce market

First, it is important to understand what is one of the most important market trends in online commerce: consumers are demanding better experiences when they shop online. In particular, commerce teams are looking to leverage vastly greater levels of content throughout the customer's shopping journey - editorials, lookbooks, tutorials, product demonstration videos, mood videos, testimonials, etc.

Old commerce versus new commerce

At the same time, commerce platforms have not added many tools for rich content management. Instead they have been investing in capabilities needed to compete in the commerce market; order management systems (OMS), omnichannel shopping (point of sale, mobile, desktop, kiosk, etc), improved product information management (PIM) and other vital commerce capabilities. The limited investment in content management capabilities has left merchants looking for better tools to take control of the customer experience, something that Drupal addresses extremely well.

To overcome the limitations that today's commerce platforms have with building content-rich shopping experiences, organizations want to integrate their commerce platform with a content management system (CMS). Depending on the situation, the combined solution is architected for either system to be "the glass", i.e. the driver of the shopping experience.

Lush as an example of content and commerce converging Lush.com is a nice example of a content-rich shopping experience built with Drupal and Drupal Commerce.

Drupal's unique advantage for commerce

Drupal is unique in its ability to easily integrate into ambitious commerce architectures in precisely the manner the brand prefers. We are seeing this first hand at Acquia. We have helped many customers implement a "Content for Commerce" strategy where Acquia products and Drupal were integrated with an existing commerce platform. Those integrations spanned commerce platforms including IBM WebSphere Commerce, Demandware, Oracle/ATG, SAP/hybris, Magento and even custom transaction platforms. Check out Quicken (Magento), Puma (Demandware), Motorola (Broadleaf Commerce), Tesla (custom to order a car, and Shopify to order accessories) as great examples of Drupal working with commerce platforms.

We've seen a variety of approaches to "Content for Commerce" but one thing that is clear is that a best-of-breed approach is preferred. The more complex demands may end up with IBM WebSphere Commerce or SAP/hybris. Less demanding requirements may be solved with Commerce Tools, Elastic Path or Drupal Commerce, while Magento historically has fit in between.

Additionally, having to rip and replace an existing commerce platform is not something most organizations aspire to do. This is true for smaller organizations who can't afford to replace their commerce platform, but also for large organizations who can't afford the business risk to forklift a complex commerce backend. Remember that commerce platforms have complex integrations with ERP systems, point-of-sales systems, CRM systems, warehousing systems, payment systems, marketplaces, product information systems, etc. It's often easier to add a content management system than to replace everything they have in place.

This year's "State of Retailing Online" series asked retailers and brands to prioritize their initiatives for the year. Just 16% of respondents prioritized a commerce re-platform project while 41-59% prioritized investments to evolve the customer experience including content development, responsive design and personalization. In other words, organizations are 3 times more likely to invest in improving the shopping experience than in switching commerce platforms.

The market trends, customer use cases and survey data make me believe that (1) there are hundreds of thousands of existing commerce sites that would prefer to have a better shopping experience and (2) that many of those organizations prefer to keep their commerce backend untouched while swapping out the shopping experience.

Acquia's near-term commerce strategy

There is a really strong case to be made for a best-of-breed approach where you choose and integrate the best software from different vendors. Countless point solutions exist that are optimized for narrow use cases (e.g. mobile commerce, marketplaces and industry specific solutions) as well as solutions optimized for different technology stacks (e.g. Reaction Commerce is JavaScript-based, Magento is PHP-based, Drupal Commerce is Drupal-based).

A big part of Acquia's commerce strategy is to focus on integrating Drupal with multiple commerce platforms, and to offer personalization through Lift. The partnership with Magento is an important part of this strategy, and one that will drive adoption of both Drupal and Magento.

There are over 250,000 commerce sites built with Magento and many of these organizations will want a better shopping experience. Furthermore, given the consolidation seen in the commerce platform space, there are few, proven enterprise solutions left on the market. This has increased the market opportunity for Magento and Drupal. Drupal and Magento are a natural fit; we share the same technology stack (PHP, MySQL) and we are both open source (albeit using different licenses). Last but not least, the market is pushing us to partner; we've seen strong demand for Drupal-Magento integration.

We're keen to partner with other commerce platforms as well. In fact, Acquia has existing partnerships with SAP/hybris, Demandware, Elastic Path and Commerce Tools.

Conclusion

Global brands are seeing increased opportunity to sell direct to consumers and want to build content-rich shopping journeys, and merchants are looking for better tools to take control of the customer experience.

Most organizations prefer best of breed solutions. There are hundreds of thousands of existing commerce sites that would like to have more differentiation enabled by a stronger shopping experience, yet leave their commerce capabilities relatively untouched.

Drupal is a great fit. It's power and flexibility allow it to be molded to virtually any systems architecture, while vastly improving the content experience of both authors and customers along the shopping journey. I believe commerce is evolving to be the next massive use case for Drupal and I'm excited to partner with different commerce platforms.

Special thanks to Tom Erickson and Kelly O'Neil for their contributions to this blog post.

Nov 10 2016
Nov 10
How to Use the Drupal 8 Video Embed module

In this tutorial, I will explain how to use the Drupal 8 Video Embed module so that you can easily add YouTube videos to your Drupal 8 site.

1

Now we have the Video Embed module installed, we need to add a field to the content. In this example, I will use the Article content type, but you can go ahead and use any content type you like.

  • Go to Structure > Content types > Article > Manage fields.
  • Add a field from the dropdown for new fields. Select the "Video Embed" option. 
  • Give a "Label" to the field.

2

On the next couple of screens, you can choose field settings. I'm just going to skip of those settings and leave the default choices in place. When you finish saving, your field will show, as in the image below:

3

Now we need to test that the field is working.

  • Go to Content > Add content > Article.
  • Add the URL for a YouTube video.

4

  • Save the article.
  • You should see that the video is displayed as below.

5

If for some reason you can not get the YouTube to load that you have selected, it may be that the video has display and load restrictions set from YouTube. You can confirm this by testing other videos inside your article.

Video on using the Video Embed module

This video is taken from our "How to Build Drupal 8 Sites" class:

[embedded content]

About the author

Daniel is a web designer from UK, who's a friendly and helpful part of the support team here at OSTraining.

View the discussion thread.

Nov 10 2016
Nov 10
hopes and fears about security providers - a survey

It's no secret that Drupal's success depends heavily on the collaborative community culture and the continuous communication process between all members of the community. It’s not for nothing that we embrace the “come for the code, stay for the community” mantra.

Today we're asking you - an agency, freelancer or a lone webmaster - to think with us a little bit about the quality of security protection your service provider delivers to ensure your website and online services are running smoothly.

It doesn't matter if it's a hosting company, a PaaS solution, an onshore or offshore provider who takes care of all your online operations - it's all about whom you trust to take care about your business being fully protected security-wise.

Speaking of the security service your provider delivers - what parts of it are of the real importance to you? What things you hope should be given for granted, and what things scare you to death in case something goes wrong? 
 
With the data collected from this little survey - just two questions about security-related hopes and fears, we are going to showcase and pinpoint main communication problems which exist between the contractor (or a service provider) and the stakeholder (or a client) when they talk about the security in SLAs and in daily interactions. 

Feel free to vent your thoughts and feelings on everything related to hardware security, data protection, sensitive data collection and storage, prevention of external attacks and common Internet threats, keeping the infrastructure and the contributed codebase up to date - we want to hear from you!

 
Show me the anonymous poll (no login or email address required)

Thank you in advance! Do you have any further questions or suggestions? Contact us

Nov 10 2016
Nov 10

I bet this opening sounds familiar to you.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Nov 10 2016
Nov 10

Here are Simple steps to get started with theming for a Drupal newbee.

Steps to develop a theme with Zen as the base theme:

1. Analyse the full design which is given in template.

2. Unzip the zen theme, you can find the folder called “STARTERKIT”.

3. Rename that folder “STARTERKIT” with you theme name eg: “my_theme”.

4. This is the folder for your new theme. (Follow the instructions given by Zen theme).

5. Rename STRATERKIT.info.txt to my_theme.info file - this provides basic information about the theme like theme version, theme core version (drupal version), Stylesheets & JS files used in the template files.

6. Understand the structure of a drupal template regions and Define the regions for your design.

7. Regions are used to place a block or content.

8. Create your regions and introduce it in the .info file first.

Sample structure of .info file

name = My Theme

description = My Theme is my first theme for drupal 7.

screenshot = screenshot.png

core = 7.x base

theme = zen

// Stylesheet

stylesheets[all][] = css/styles.css

// JS

scripts[] = js/script.js

// Regions used in my_theme

regions[header] = Header

regions[navigation] = Navigation bar

regions[highlighted] = Highlighted

regions[content] = Content

regions[sidebar_first] = First sidebar

regions[sidebar_second] = Second sidebar

regions[bottom] = Page bottom

regions[footer] = Footer

regions[page_top] = Page top

regions[page_bottom] = Page bottom

8. Open the template.php and theme-settings.php file, then rename the functions with your theme name.

For ex:

// Before renaming

function STARTERKIT_preprocess_html(&$variables, $hook) {

$variables['sample_variable'] = t('Lorem ipsum.');

// The body tag's classes are controlled by the $classes_array variable. To

// remove a class from $classes_array, use array_diff().

$variables['classes_array'] = array_diff($variables['classes_array'],

array('class-to-remove'));

}

// After renaming

function my_theme_preprocess_html(&$variables, $hook) {

$variables['sample_variable'] = t('Lorem ipsum.');

}

9. We can add variables for basic page elements in template.php file.

For ex:

function my_theme_preprocess_html(&$variables) {

// Construct page title.

if (drupal_get_title()) {

$head_title = array(

'title' => strip_tags(drupal_get_title()),

'name' => check_plain(variable_get('site_name', 'Drupal')),

);

}

else {

$head_title = array('name' => check_plain(variable_get('site_name',

'Drupal')));

if (variable_get('site_slogan', '')) {

$head_title['slogan'] = filter_xss_admin(variable_get('site_slogan', ''));

}

}

$variables['head_title_array'] = $head_title;

$variables['head_title'] = implode(' | ', $head_title);

}

In that above example we construct the page title and assign that into the variable. Now we can use the $head_title variable throughout all the templates. In a similar manner you can create any no of variables.

10. If you need to change the template copy the files from zen base theme (Eg: page.tpl.php, node.tpl.php) and paste it into your templates folder.

For ex:

Create page.tpl.php file, it contains the code for the body of the page. You can modify that as per your requirement.

Reference links:

https://www.drupal.org/project/zen

https://www.drupal.org/node/2710573

http://johnalbin.github.io/zen-style-guide/

SASS:

What is SASS?

Sass (Syntactically Awesome StyleSheets) is an extension of CSS. Sass allows you to use things like variables, nested rules, mixins, inline imports, and more, all with a fully CSS-compatible syntax. It helps keep large stylesheets well-organized, and get small stylesheets and running quickly with the help of the Compass style library.

Key benefits of using Sass:

1. Sass provides variables as a way to store information that you want to reuse throughout your stylesheet.

For ex:

Use Variable for defining Font Face, Colours, Line height, Width - These are values used across site. Setting as variables helps us to manage change easily.

// Sass file

$page-width: 1280px;

$margin-left_right-auto : 0 auto;

page-width {

max-width: $page-width;

margin: $margin-left_right-auto;

}

// CSS Output

.page-width {

max-width: 1280px;

margin: 0 auto;

}

2. Sass provides Mixins, these are like functions in php. You can declare a mixin with arguments and use it throughout the site. There are also predefined mixins for Box shadows, Font Styles.

For ex: Mixin

//Sass file

@mixin height-width-100 {

width: 100%;

height: 100%;

}

.news-slider {

@include height-width-100;

}

.news-content {

@include height-width-100;

}

// CSS Output

.news-slider { width: 100%; height: 100%; } .news-content {

width: 100%;

height: 100%;

}

3. In Sass @extend is one of the most useful features that allows us to share a set of CSS properties from one selector to another.

For ex:

//Sass file

.height-width-100 {

width: 100%;

height: 100%;

}

.news-slider {

@extend .height-width-100;

}

.news-content {

@extend .height-width-100;

}

// CSS Output

.height-width-100, .news-slider, .news-content {

width: 100%;

height: 100%;

}

4. Sass @import pull the file before it compiles the CSS. Its is used to import (include) the raw CSS-file into different files. @import "path of your file";

For ex: @import 'base/fonts'; // in style.ccs

In the above example fonts will be imported to style.ccs file from the path base/fonts.

Reference links:

http://sass-lang.com/documentation/file.SASS_REFERENCE.html

http://www.webdesignerdepot.com/2014/08/5-reasons-you-should-be-using-sa...

https://www.sitepoint.com/sass-basics-the-mixin-directive/

Steps to have SASS working with your Drupal 7 theme

1. Let’s test if SASS is installed and compiling. Use your toolkit to compile your SASS directory or run compass watch from the command line in your theme directory.

2. You can add the styles to the .scss file. After saving your change, refresh the page and you can see the difference.

3. After saving that .scss file, compass watch command is executed automatically and it shows the modified file name.

Key tips and learning

1. Analyse full design, measure the spaces, width & height then write css.

2. Include the font, icons(i.e Font Awesome) and import the mixins,css3.

3. Write the css for mobile platform first, then using media query and alter that for tablets and desktops.

For ex:

/**

* Header

*/

.header-logo {

float: left;

max-width: 210px;

}

// For tablet and desktop

@media only screen and (min-width: 768px) {

.header-logo {

max-width: none;

}

}

In the above example, for mobile the logo width is fixed for 210px and for tablet and desktop logo width is not fixed. By this way only we can write the css.

4. In template page only one h1 is used, we can use h2,h3...h6 more than once. But only one h1 tag should be used.

5. If you use float to align the div, use clearfix code for its parent div.

For ex:

<!DOCTYPE html>

<html>

<head>

  <title>My Theme</title>

  <style type="text/css">

  .logo-img-div {

    float: left;

    width: 50%;

  }

  .logo-slogan-div {

    float: left;

    width: 50%;

  }

  .clearfix:after {

    content: " "; 

    visibility: hidden;

    display: block;

    height: 0;

    clear: both;

  }

</style>

</head>

<body>

  <div class="header-content clearfix"> // Parent Div

    <div class="logo-img"> //Child Div with float

      <img src="http://www.unimitysolutions.com/blog/steps-theme-development-drupal-7-us...">

    </div>

    <div class="logo-slogan"> //Child Div with float

      <p>This is my theme</p>

    </div>

  </div>

</body>

</html>

6. CSS Naming Conventions is one of the most fundamental and important part of developer activities. Naming conventions help us a lot making our code more readable, predictable. And when it comes to code modification and debugging, conventions help us to easily find needed part of code. 

For eg:

.is-hidden    { display:    none !important; }

.is-invisible { visibility: none !important; }

.block        { display: block        !important; }

.inline       { display: inline       !important; }

.inline-block { display: inline-block !important; }

.left  { float: left  !important; }

.right { float: right !important; }

.text-left   { text-align: left   !important; }

.text-center { text-align: center !important; }

.text-right  { text-align: right  !important; }

In above example the css class selectors are related to their properties.

// Correct way to declare the css selectors

.left { 

  float: left;

}

.right { 

  float: right; 

}

// Worst way of declare the css selectors

.left-div-content { 

  float: left; 

}

.right-div-content { 

  float: right; 

}

7. Use the colors, fonts and images which is defined in the template you have. Create image cache for image sizes. Use Display Suite, it allows you to take full control over how your content is displayed using a drag and drop interface. We can arrange nodes, views, comments, user data etc. We can also use Panels to segregate the layout. It makes layout segregation easier.

Watch our for more of my blogs! My next blogs are going to be on Drupal 8 theming & use of Panels and Display suites!

Nov 09 2016
jam
Nov 09
[32] Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt, ut labore et dolore magnam aliquam quaerat voluptatem.
Nov 09 2016
Nov 09

by David Snopek on November 9, 2016 - 1:08pm

As you may know, Drupal 6 has reached End-of-Life (EOL) which means the Drupal Security Team is no longer doing Security Advisories or working on security patches for Drupal 6 core or contrib modules - but the Drupal 6 LTS vendors are and we're one of them!

Today, there is a Moderately Critical security release for the Views Send module to fix a Cross Site Scripting (XSS) vulnerability.

Views Send enables you to send mail to multiple user from a View.

The module doesn't sufficiently filter potential user-supplied data when it's previewing the mail which can lead to a Cross Site Scripting (XSS) vulnerability.

This vulnerability is mitigated by the fact that an attacker must have a role with the permission "mass mailing with views_send".

You can download the patch.

If you have a Drupal 6 site using the Views Send module, we recommend you update immediately! We have already deployed the patch for all of our Drupal 6 Long-Term Support clients. :-)

If you'd like all your Drupal 6 modules to receive security updates and have the fixes deployed the same day they're released, please check out our D6LTS plans.

Note: if you use the myDropWizard module (totally free!), you'll be alerted to these and any future security updates, and will be able to use drush to install them (even though they won't necessarily have a release on Drupal.org).

Nov 09 2016
Nov 09

Security of the Drupal website is a important stuff for the site owners, site developers.This blog post has my presentation at the Drupal Camp Mumbai that  intended for Drupalers who want to avoid security loop holes while writing code or architecting solutions. We delved into common security issues that ails custom code and has both vulnerable and secure code snippets.This is mostly about my encounters and experience after doing 50+ project application reviews and also a good guideline for new contributors.

Hack Proof Your Drupal Site from Naveen Valecha

Next article:  A guide to review Project Applications.

Nov 09 2016
Nov 09

The composer.json file schema contains a script section that allows projects to define actions that are executed under certain circumstances. The most recognizable use for this section is to define events that happen at defined times during the execution of Composer commands; for example, the post-update-cmd runs at the end of every composer update command.

However, Composer also allows custom commands to be defined in this same section; an example of this is shown in the composer.json schema documentation

{
    "scripts": {
        "test": "phpunit"
    }
}

Once this custom command definition has been added to your composer.json file, then composer test will do the same thing as ./vendor/bin/phpunit or, equivalently, composer exec phpunit. When Composer runs a script, it first places vendor/bin on the head of the $PATH environment variable, so that any tools provided by any dependency of the current project will be given precedence over tools in the global search path. Providing all the dependencies a project needs in its require-dev section enhances build reproducibility, and makes it possible to simply “check out and go” when picking up a new project. If a project advertises all of the common build steps, such as test and perhaps deploy as Composer scripts, it will make it easier for new contributors to learn how to build and test it.

Whatever mechanism your project uses for these sorts of tasks should be clearly described in your README or CONTRIBUTING document. Providing a wrapper script is a nice service, as it insulates the user from changes to the default parameters required to run the tests. In the Linux world, it the sequence of commands make, make test, make install has become a familiar pattern in many projects. Make has a rich history, and is often the best choice for managing project scripts. For Composer-based projects that are pure PHP, and include all of their test and build tools in the require-dev section of their composer.json file, it makes a lot of sense to use Composer scripts as a lightweight replacement for Make. Doing this allows contributors to your project to get started by simply running git clone and composer require. This works even on systems that do not have make installed.

An example of a scripts section from such a project is shown below:

{
    "scripts": {
        "phar": "box build .",
        "cs": "phpcs --standard=PSR2 -n src",
        "cbf": "phpcbf --standard=PSR2 -n src",
        "unit": "phpunit",
        "test": [
            "@unit",
            "@cs"
        ]
    }
}

The snippet above offers the following actions:

  • phar: build a phar using the box2 application.
  • cs: run the PHP code sniffer using PSR2 standards.
  • cbf: run the PHP code beautifier to correct code to PSR2 standards, where possible.
  • unit: run the PHP unit tests via phpunit.
  • test: run the unit tests and the code sniffer.

One thing to note about Composer scripts, however, is that you might notice some changes in behavior when you run certain commands this way. For example, PHPUnit output will always come out in plain unstyled text. Colored output makes it a lot easier to find the error output when tests fail, so let’s fix this problem. We can adjust our definition of the test command to instruct phpunit to always use colored output text, like so:

{
    "scripts": {
        "test": "phpunit --colors=always"
    }
}

There is another difference that may affect some commands, and that is that standard input will be attached to a TTY when the script is ran directly from the shell, but will be a redirected input stream when run through Composer. This can have various effects; for example, Symfony Console will not call the interact() method if there is no attached TTY. This could get in your way if, for example, you were trying to write functional tests that test interaction, as the consolidation/annotated-command project does. There are a couple of options for fixing this situation. The first is to explicitly specify that standard input should come from a TTY when running the command:

{
    "scripts": {
        "test": "phpunit --colors=always < /dev/tty"
    }
}

This effectively gets Symfony Console to call the interact() method again; however, the down-side to this option is that it is not as portable; composer test will no longer work in environments where /dev/tty is not available. We can instead consider a domain-specific solution tailored for Symfony Console.  The code that calls the interactive method looks like this:

if ([email protected]_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
    $input->setInteractive(false);
}

We can therefore see that, if we do not want to provide a TTY directly, but we still wish our Symfony Console command to support interactivity, we can simply define the SHELL_INTERACTIVE environment variable, like so:

{
    "scripts": {
        "test": "SHELL_INTERACTIVE=1 phpunit --colors=always"
    }
}

That technique will work for other Symfony Console applications as well. Note that the SHELL_INTERACTIVE environment variable has no influence on PHPUnit itself; the example above is used in an instance where PHPUnit is being used to run functional tests on a Symfony Console application. It would be equally valid to use putenv() in the test functions themselves.

That is all there is to Composer scripts. This simple concept is easy to implement, and beneficial to new and returning contributors alike. Go ahead and give it a try in your open-source projects—who knows, it might even increase contribution.

Topics Development, Drupal Planet, Drupal
Nov 09 2016
Nov 09

Have you ever stared at your computer screen with a deer-in-headlights expression on your face thinking “I have no idea where to even start with this…”? That was me about a month ago when I was asked to help theme a Drupal 8 project for the very first time. Getting started theming in Drupal 8, still being in a fairly new iteration with a programming style differing from Drupal 7, was both an exciting and daunting task. It was exciting in the sense that I heard good things from those who’ve already started theming in D8, and daunting because there’d been a lot of changes between D7 and D8.

One of the differences between Drupal 7 and 8 is template files; PHPTemplate (.tpl.php) files were replaced with Twig (.html.twig) files. Twig is a robust and elegant template engine for PHP. Once I started working with Twig, I instantly loved it. I found it to be lightweight, fairly quick to pick up, and very readable. Not only that, but I had what felt like ultimate control to the markup, including wrapping elements and rendering exactly the ouput I needed. Often with Drupal 7, wrapping elements in a <div> requires assistance from a back-end developer.

With this newfound enthusiasm, I set out to write the best twig code ever! In order to find the output I needed, I used the Twig function dump(). This function “dumps” a variable’s information right on the screen. This proved highly useful until I realized I needed to dig deeper into the arrays and objects contained within the variable. There was only so much guess work I could do here before getting epically frustrated, seemingly wasting valuable time looking for an image file’s path.

Though there are a handful of debugging methods to choose from, I had the best luck getting what I needed by using PHPStorm to debug Twig files. That’s right, front-end friends, PHPStorm isn’t just for back-end PHP-coding devs. It can be a great tool for front-end programmers as well!

After following the steps listed in Lubomir Culen’s post about debugging Twig templates, I began to look for templates in the following path sites/default/files/php. From my understanding, opening a template folder gains access to the current template version the project is using, hence the long hash.

Content rendering 1

If a change is made to the template, an additional hash file is created and a new breakpoint will need to be set. If at any point the hash template files get overwhelming, clearing the cache (running drush cr all) will reset the PHP folder and the template files, reducing the hash files to one per template folder.

First off, I needed to acclimate myself to translating PHPStorm syntax into Twig. For example, copying a variable name in PHPStorm produces a syntax like this: $context[‘page’][‘#title’]->arguments[[email protected]]. That gets translated into the twig file like so: page[‘#title’].arguments[[email protected]]. Here’s what my PHPStorm screen looked like while working on this solution:

Content rendering 2

Some patterns and tricks I found helpful:

  • Ignoring $context and starting with the main content variable.
  • Strip array syntax, i.e. [‘page’] = page.
  • If arrays exist next to each other, separate them with periods. Ex. [‘page’][‘content’] = page.content.
  • If an array has a #, @, or other symbol associated, keep its integrity. No period is needed here. Ex. [‘page’][‘#title’] = page[‘#title’], and arguments[[email protected]] stays the same.
  • If an arrow exists, treat the method (what comes after the ->) in the same manner as arrays. Ex. [‘#title’]->arguments = [‘#title’].arguments
  • If you’re having trouble rendering the desired output, try adding .value to the end of the render code and see if that does the trick.
  • Use dump() simultaneously with PHPStorm’s suggested variable path.
  • Refer to the Twig documentation for other handy built-in features.

Up until the moment I got PHPStorm doing the heavy lifting, my team and I were relying soley on the dump() Twig function. We were halfway through the project when I discovered a value was no longer present. The disappearance was due to a template’s reliance on a value being rendered via an array placement, i.e. content.tile.3['#markup'], the ‘3’ referring to the 4th placement in the ‘tile’ array. To alleviate potential confusion, ‘tile’ happened to be the custom field group where the field_to_render existed, and the field_to_render was the 4th field in the list of fields. When a field was moved within the ‘tile’ field group, the code broke. Once I had access to the phpstorm debugger, I was able to see a better way to render this element, i.e. content.field_to_render. It suddenly dawned on me that our project needed some tidying, so I rolled up my sleeves and got to work.

These are the strategies I established during my clean-up process:

  • Create the shortest render code possible with the closest placement to the main content variable. This will be the most stable. My array placement example mentioned previously is a good example of this. The same value can be present and rendered in numerous ways.
  • If rendering a field, use this pattern: content.field_to_render. This will render the field object, inheriting any backend logic that’s been applied to that field existing in the view_mode you are theming.
  • If you prefer having just the markup or integer value, try adding a .value to the end. Examples: content[‘#node’].nid.value will provide just the node id, and content.node_title will render the title object whereas content[‘#node’].title.value will render the title as a string.
  • The first element in an array might be the most stable. For example, we often use the media module which can add complexity to a media item’s data structure. In order use a node’s image as a background for a <div>, this is the best approach we found: <div class=”banner-image” style="background-image: url()"> .

Any change can be tough to navigate, but it’s often well worth the effort. My experience theming in Drupal 8 thus far has been lovely, and fairly intuitive. I find it offers front-end developers more authority over the markup than its predecessor, and makes me excited for the future of theming in Drupal 8. If you were at all daunted by the thought of theming in Drupal 8, I hope this post helps you in your future twig debugging endeavors!

Note: Devel and Kint are a couple additional tools available for debugging Twig variables, and I mention those in case others find them useful. More information on how to set those tools up for debugging Twig files (and more!) can be found in this Drupal 8 Theming Guide and on Amber Matz’s Let’s Debug in Drupal 8! post.

If you’re new to Drupal 8 theming, I would start with the resources Amber specifies in her “Editor’s notes”, and sqndr’s D8 theming docs. Debugging twig files is an intermediate topic.

If you have any personal experience with Drupal 8 theming, or insight you’d like to share, I’d love to hear about it in the comments section!

Get In Touch

Questions? Comments? We want to know! Drop us a line and let’s start talking.

Learn More Get In Touch
Nov 09 2016
Nov 09

Choosing CMS platform is very crucial for organizations. Without broad understanding of requirements and impressive set of features to match the requirement choosing CMS could be daunting and tricky. Here is a comparison between Drupal Vs AEM (Adobe Experience Manager) and Sitecore.

First let’s understand what Drupal is?

Drupal is the #1 platform for web content management among global enterprises, governments, higher education institutions, and NGOs. Flexible and highly scalable, Drupal publishes a single web site or shares content in multiple languages across many devices. Technology and business leaders transform content management into powerful digital solutions with Drupal … backed by one of the world’s most innovative open source communities.

Key differentiator between Drupal and AEM or Sitecore are

  1. Drupal is “ A Web content management built by the Largest community of developers.” AEM or Site core are “WCM + Analytics + Personalization all in one. Proprietary & Licenses are needed”.
  2. Through Drupal Do we can actually select best of breed solutions to meet the needs of delivering the complete Web experience instead of buying all the features in proprietary systems.
  3. Ease, Speed & Cost are key factors favourable to Drupal over other CMS platforms.

Setting record straight as Enterprise Web Content Management System and breaking all the myths Drupal holds 10 position in the CMS category in 2016 according to Datanyze Universe, a US based Technographics company. With accretion of Drupal 8, organizations acquired better ability to deliver right content to right people at right time on right device. Also, Drupal blends content with commerce to build contemporary e-commerce portals which enhance customer experiences through out buying cycle.

Some of the marquee Drupal implementations worldwide are listed below

Large Hi-tech companies like GE, Pinterest

Entertainment companies like Grammy, NBC

Retail companies like Whole foods, Royal Mail, Puma

Sports websites like NBA, Rio Olympics 2016

Famous Life Science companies like Pfizer, Johnson & Johnson

Renowned NGOs like World Economic Forum, Rotary International

Government organizations like The White House, City of Boston

World class educational institutes like Harvard, Stanford

50% of top Financial Services companies like HDFC Life, Aegon Religare, Thomson Reuters etc. use Drupal

Drupal Vs. AEM or Sitecore

Feature

Drupal

AEM or Sitecore

Differentiator

A Web content management built by the Largest community of developers.

Ease, Speed & Cost benefits are it's advantage. 

WCM + Analytics + Personalization all in one.

Proprietary & Licenses are needed. 

Flexibility

Drupal being more a platform is more flexible.

Being in open source, there is no need to wait for a Roadmap to implement any immediate need or flexibility.

Flexibility, built like a Lego, adapts to the needs.

It's Innovation friendly!

Being Proprietary, getting newer features may need to wait for them to implemented as part of the Road Map. 

Speed of Development

Faster implementations, easier prototyping

Needs more time

Responsive

Helps build customized user experiences, solutions that help in building responsive websites.

User experience and building responsive interfaces are available.

Integration capabilities

REST APIs in the core & Integratable

Integratable - relies on partners to integrate

Enterprise fit

 Meets all Enterprise criteria 

Meets all Enterprise criteria

 Security

Dedicated Security

Million eyes on the code

Process to communicate the issues in a more open and transparent manner

Security directed as by proprietary team

Scalability 

Highly scalable, integrates with memcache, varnish and other caching systems that speeds up the sites

Scalable 

Cloud capabilities

Integrates on the cloud, can be built to autoscale to optimize utilization

Support on cloud limited

Maintenance

Sign Up with any Drupal shop

Vendor agnostic approach is possible

Proprietary

End User training

Drupal 8 has usability as key feature

Easy to use

Cost

 Source code is free - pay more for value add

License costs are high

Apart from above mentioned features Drupal is chosen as CMS platform by most of the organizations because of it’s innovative features with thousands of plugins offering customization. Drupal offers flexible and adaptable toolkit emphasizing efficiency and speed. Also one of the unique feature of Drupal is its transparency. Developers prioritize and mitigate security risks both in Core Drupal and Drupal Contribution Modules owing to deliver quality results.

Contemplating above information it is no wonder that Drupal is relatively replacing other CMS platforms like Sitecore, AEM and many more.

Nov 09 2016
Nov 09

After our world tour of Drupal Camps took a lift-off in Africa, it continued its journey in Asia. We concluded that Drupal activities in Africa are poorly represented and on the other hand predicted that Drupal Camps are more spread across the world’s largest continent. We also expected not to find the most of Drupal activities gathered in one country, like it was the case in South Africa. We were quite right.

Before we take a look at the most important Drupal Camps in Asia, we should explain that at the beginning of this year, everything was under the shade of DrupalCon. It was organized from 18-21th of February for the first time in Mumbai. It captured all of Asia's attention, so organizing Drupal Camps around that period of time would be a waste of energy, time and money. Sorry, but the facts sometimes hurt. Nevertheless, the attention from the colourful city of Mumbai eventually, after a long period of time, switched to other places, like Drupal Camp Vietnam, which was organized for the first time in Hanoi in March.

Drupal Camp Delhi

 

Drupal Camps to look forward to

Today, all the heads in Asia should be turned to Delhi, where Drupal Camp Delhi will take place at the end of the week, precisely from 12-13th of November. This event is one of the largest in Asia and it brings together thousands of students, developers, executives, business users … to develop, design, and support a Drupal platform. It will be held at Jaypee Institute of Information Technology with speakers like Swastik Pareek, Abhishek Anand, Hussain Abbas and many more, who attract visitors far beyond North India every year.

The only possible downside of this Drupal Camp, which can massively influence its attendance, is recent news about pollution in Delhi. The situation is so bad that the Indian government had to shut down schools for three days. Moreover, the pollution was so bad that the air quality index ran out of numbers to measure it. You can read more about this emergency situation here.

On the bright side, there is another Drupal Camp coming to you soon. It's Drupalcamp Cebu, a single day event, which will open its doors on 19th of November on Cebu, Philippines. It's organized for the third time. There, you will be able to learn about business, front-end, back-end and DevOps with experts like Johnnie Fox, Gerald Villorente, Joan Maris Rosos, Chris McIntosh and so on.

Drupal Camp Cebu

If you think that this weeks you are able to expend your Drupal knowledge only in Delhi, you are wrong. DrupalCamp Taipei is also scheduled for this Saturday (12th November). It will host names like John Albin Wilkins in Ming Chuan University in Taiwan. Unlike in Africa, the admission is not free. In fact, it is not free on all of the described events. Your horizon will not be widened for free even in DrupalCamp TLV Israel, which concludes this year busy November of Drupal Camps. It will be held on 29th November in Tel Aviv. Newcomers and expert will be addressed by Bojan Zivanovic, Michael Schmid, Amir Taiar, Inbal Jona and many others.

Drupal Camp Taipei

 

Drupal Camps, which did not make it this year

Of course Asia is not an exception when it comes to »lost« Drupal Camps. Although some of them, like DrupalCamp Singapore and Drupal Camp Pune, did not see the daylight this year we must conclude that Drupal Camps and Drupal activities in general are far more spread and evolved in Asia than in Africa. It will be interesting to see the comparison with Europe and North America, but more about that in one of our next blog posts.

Nov 09 2016
Nov 09

Shan asks,

Hi folks- I am looking for an out of box eCommerce solution that meets the following criteria and hope to get some pointers on few solutions that's already available in the market.

There are certainly some decent self-hosted e-commerce solutions on the market, but I wouldn't really say any are "out of the box" -- all are going to require a fair amount of setup and configuration, not to mention provisioning a secure environment. A SaaS offering handles a lot of the hard work for you, and is as "out of the box" as you can get. Anything else opens you up to a lot more work to do it right, and not expose yourself to a bunch of risk.

That said, we do a lot of custom e-commerce, and our platform of choice is Drupal Commerce. The big news is, Drupal Commerce 2.0, for Drupal 8, just reached Beta last month, which means there is an supported upgrade path from here on. And it's looking like a great solution, though there's still quite a bit of work to be done.

First, to answer your questions:

  1. Visually appealing site. I have checked number of templates from themeforest/squarespace, etc but would love to see a fresh approach/look & feel beyond the traditional templates.

The flagship, launch customer for Drupal Commerce 2 is https://www.obermeyer.com/ .

Drupal has no limitations on how a site can be styled or themed. There are not that many custom themes for Drupal 8 yet available on the theme sharing sites, but Bootstrap is fully baked and ready, and we've deployed several Drupal 8 sites using a bootstrap-based custom theme. The theme system for Drupal 8 is much improved from previous versions, using the Twig template system...

Basically anything that can be done on the web can be done in Drupal. And for Commerce, you just have some more elements to theme (add-to-cart buttons, order templates, emails, etc).

  1. Hosted solution so we can expand the capabilities to meet our long term needs than a SaaS solution.

Drupal can be hosted at a huge number of hosts. For e-commerce, we would highly recommend hosting with a host that has appropriate PCI compliance, and use a dedicated virtual server. We put most of our e-commerce clients on a virtual server in Amazon AWS or Google GCE. (See our hosting guide for more...)

  1. Native App: This vertical doesn't need a mobile app yet for MVP but would love to keep that as an option and expand eventually beyond the desktop version. The platform should be scalable to build a native app eventually.

Drupal 8 has great mobile-responsiveness in its core -- it's a pretty decent experience to administer content from your cell phone. With a well-done theme, you may not need an app. If you want a native app, Drupal 8 has a decent web API for interacting with everything -- there are more and more "headless" Drupal sites that are simply a back end for a native app or an Angular/React/etc app.

Regarding scaling, Drupal 8 is blowing away other PHP-based systems on performance benchmarks, largely through some very intelligent caching. There's a new "BigPipe" module that loads "expensive" parts of the page after the rest of the page has rendered, allowing the site to feel really fast, while loading the user-specific shopping cart after the rest of the page has rendered. In addition to being extremely snappy, the caching layers greatly reduce server load, allowing it to handle a lot more traffic -- and the same caching mechanisms are used for web service calls as well as rendered HTML, and for authenticated users as well as anonymous. (Ok, not quite as well, but far better than competing systems).

  1. Product Images: Need ways to provide better viewing tools to look at the product images more clearly, true color, 3D views, drop the product to the room and experience it, etc.

Drupal 8's Media initiative provides some best-of-breed media management tools. See https://drupal-media.gitbooks.io/drupal8-guide/content/ for documentation of what's easy to do now -- slideshows, video, cropping, embedding any content in another page, etc.

For an example in action, check out https://www.obermeyer.com/catalog/womens/payton-down-jacket?v=6065 to see several different display options for photos. For True Color/3D, you're limited by what web browsers can do... if you have a plugin of some kind that will accomplish what you're after in a web browser, it can be used in Drupal.

Now, for the other stuff -

Why Drupal Commerce?

Drupal Commerce, compared to other shopping cart systems, is not a stand-alone e-commerce solution. Instead, it's basically a library that adds e-commerce support to Drupal, including: Shopping cart workflow, product entities that can be attached to any other Drupal entity, orders, payment gateways, shipping/tax/fulfillment modules, reports.

There are two big reasons why this is great:

  1. Commerce becomes a fully-integrated part of a much broader content management system. This means you can easily show products related to a blog post, product reviews, ratings, etc. And turn just about anything in Drupal to something that can be sold in the cart -- memberships (roles), event registrations, hotel bookings, physical goods, web service calls, digital downloads, content creation credits.
  2. Most other commerce packages may be great for the shopping cart and fulfillment side of things, but they end up not having a great content management user experience, and often are entirely separate applications that only share a theme with the rest of your site.

Flexibility and a great user experience is why you should consider Drupal Commerce, either 1 or 2.

Why Drupal 8?

If you haven't looked at Drupal recently, you should check out Drupal 8. While it shares a lot of concepts with earlier versions of Drupal, under the hood it's an entirely different system. It's now completely object-oriented, built upon the Symfony framework and uses modern dependency-injection patterns instead of the old mystifying hook system. If you like building on a modern framework, it's that -- but with a lot of the stuff you need already done, such as an authentication/authorization layer, a robust form API, a powerful theme/templating system.

Compared to earlier versions, the biggest win is the upgrade path -- Drupal has matured to the point where we're able to handle upgrades as a part of routine maintenance, instead of having to do a major upgrade project. We've already had significant new functionality added to 8.1 and 8.2, and if you stay current, the jump to 9.0 will not be drastic (just a housecleaning to remove stuff that's been deprecated along the way).

Stuff that used to be ridiculously hard in Drupal has gotten far easier, thanks to the OO framework. The UX is vastly improved. The mobile support is top notch. And there's a built-in migration framework, which, combined with the web services, makes it very easy to get any kind of data into or out of Drupal, when integrating with other systems.

Why Commerce 2?

Drupal Commerce 1 was built for Drupal 7, and while it epitomizes the benefits outlined above, the biggest downside was how much work you had to do to get it functional. There's a "kickstarter" that will get you up and running quickly, though it made some decisions for you that we found problematic later, so we generally had to put together everything from scratch (or our own base). This means defining all the order states and transitions, building all the email notifications, programming rules for what happens at checkout/payment fully received, creating report templates and sales dashboards, creating the cart displays, etc.

Drupal Commerce 2 is built for Drupal 8, and they have, much like Drupal 8 itself, started completely over with the benefit of experience. They took the opportunity to compare the user experience of all the other major shopping carts -- Magento, WooCommerce, Shopify, Squarespace, BigCommerce, etc -- and implemented a "best of breed" base user experience for the shopping cart, taking away a big chunk of the setup work necessary for Commerce 1.

But there's some other big improvements, too:

  • Multi-vendor/multi-store straight out of the gate. You can define a single store -- or a whole shopping mall -- out of the same Drupal instance.
  • Multiple checkout workflows. The Obermeyer site supports 3 different checkout user experiences -- retail customer, wholesale, and loyalty customers -- with entirely different shopping cart workflows, all under the same store.
  • Fully internationalized Address and Tax libraries. Instead of building these solely for Drupal Commerce, the Commerce team factored out this functionality into PHP libraries that are now used by other shopping carts to handle the needs of stores that sell internationally.
  • Migration support. You can migrate data from Ubercart and Commerce 1 today, and migrations from other popular carts such as Magento, OS Commerce, WooCommerce, Wix, etc are planned -- and not difficult for somebody experienced in Drupal migrations to build.

Why not Drupal Commerce?

The biggest reasons would be cost, and the amount of effort it takes to get a great user experience. Which is really the same thing.

For Commerce 1, pretty much everything you might need is there -- but you're building on a platform with no more than 3 or 4 years of remaining life before you would need to do a substantial upgrade (to Commerce 2). And there's quite a bit of setup to do to get a nice user experience...

For Commerce 2, the main thing is that not everything is quite there yet. Shipping, for example, is being worked on today, as I write this. There are only a couple payment gateways implemented just yet (though those are pretty easy to code). I don't think anyone is tackling fulfillment modules just yet (if you want to integrate with an external fulfillment vendor, for example), and a lot of the glue for memberships and event management still needs to be done.

If you are looking for the flexibility of a custom solution, need robust e-commerce, and want a solution that is going to be solid and current for the next decade, you won't find a better fit than Drupal Commerce, especially if you're willing to deal with some early implementation pain.

Let us know if you have any questions, or need a partner to help you get started with Drupal Commerce!

And kudos to the Commerce Guys for all their great work getting this out the door!

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