Upgrade Your Drupal Skills

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

See Advanced Courses NAH, I know Enough
Dec 18 2019
Dec 18

Install the latest version:

Versions of Drupal 8 prior to 8.7.x are end-of-life and do not receive security coverage.

To mitigate this issue in any version of Drupal 8, you can also block access to install.php if it's not required.

Additional information

All advisories released today:

Updating to the latest Drupal core release will apply the fixes for all the above advisories.

Dec 09 2019
Dec 09

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

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

The Benefits of Drupal 8

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

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

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

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

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

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

So why wait? 

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

Nov 22 2019
Nov 22

This article was originally posted on Thunder.org and is reposted here with the permission from Community Manager Julia Pradel. 

Not everyone has the necessary resources to engage their own design team. Our Certified Thunder Integrator (CTI) Ramsalt has recognized this need and developed a generic theme that will be available to other Thunder users as an open-source product.

The idea for the theme emerged a few years ago: “We wanted to develop a generic design which newspapers could easily customize to their individual needs” explains Ramsalt’s CEO Yngve Bergheim. “We had a starter kit in mind which could either be used as is, or easily tweaked by a designer.”

The first task was to gather all of the requirements for a design. We arranged focus groups with digital editors from several newspapers to understand their needs. “We also drew upon our own pool of experience,” says tech lead Stephan Zeidler. Ramsalt has made numerous magazines and newspapers since 2011. The analytic process ended up in a 51 pages design requirement specification and corresponding wireframes.

[embedded content]Example of Longform/featured articles


Art director Evgeny Pugachev led the design process while Stephan Zeidler was tech lead. The CTI Ramsalt Lab has offices in several countries among them Sweden, Norway, the Netherlands and Russia, and the Thunder development is directed from the German office in Berlin. According to Stephan, the greatest challenge with the theme’s development was ensuring that everything would be reusable - and at the same also be customizable. Stephan, therefore, relied on a component-based approach: “It is certainly significantly more complicated and takes longer at the beginning of the project but the risk of regressions is much reduced”.

Simple to adjust

The component-based approach also enables Stephan to capture updates from the numerous Drupal modules. “Since we use our own HTML templates rather than the standard Drupal templates, adjustments are much simpler than they would otherwise be.” Another advantage in his view is the lean markup which makes the site significantly quicker and also delivers plus points in terms of SEO aspects. The theme has also been put to the test and further optimized in order to achieve the best possible results in Google’s Pagespeed. It was a project by itself and led to the publication of a series of articles on Planet Drupal, under the heading The ultimate guide for faster Drupal.

The theme was conceptualized over a period of six months with two designers, challenged with the help of several customers and continuously developed along the way - and it is still a work in progress. The three-person development team working with Stephan, also wants to examine whether Drupal’s Color Module can be integrated and how the design could also be used as a demo theme by other CTIs.

 

Get the new design now!


For company chief, Yngve Bergheim, there is no question about whether the Ramsalt design will be made available to Thunder users: “Anyone that wants to try out the new design can drop us an email on [email protected]. - We want to use the theme as a showcase for publishers evaluating Thunder. Publishers already have the best technology in place in the Thunder distro, the best and biggest community. What is lacking now is a good looking design on the bodywork that fits the top-notch “Porsche” engineering we have in Thunder”, says Bergheim.

Open-source

The design is aimed to be released as an open-source module on drupal.org as soon as the integration with Thunder works seamlessly. There is still some work left: “The design currently makes many assumptions, like how the menu and various article variants look, that there is a search bar or that authors are shown with their names, pictures and even job titles” explains Stephan. The fields for these points did not exist in a standard Thunder. “And that is also a good thing, Thunder should remain as generic as possible” stresses Stephan. This does, however, pose him and his team the question of how the theme can, together with its Thunder installation, show its full effectiveness out of the box. Which is our goal, to have the theme in the Thunder distro eventually.

Nov 14 2019
Nov 14

Submitted by karthikkumardk on Thursday, 14 November 2019 - 11:14:32 IST

The SimpleTest module has been deprecated in Drupal 8, and will be removed in Drupal 9.

Production sites should never have SimpleTest module installed since it is a tool for development only.

contributed module is now available for those who wish to continue using SimpleTest during the transition from Drupal 8 to 9.

However, developers are encouraged to write tests with PHPUnit, and to use the phpunit command line test runner: https://www.drupal.org/docs/8/phpunit/running-phpunit-tests

Note that the final decision to deprecate SimpleTest still has some dependencies on the in-progress Drupal 9 issue so exact details of the deprecation may be revised (#3075490: Move simpletest module to contrib).

Thanks :)

Nov 12 2019
Nov 12

As you know Composer is a great tool to manage packages and their dependencies in PHP, while in Drupal 8.8 is going to more composer compatible, you can find composer cheatsheet in the following.

Installing dependencies

composer install

Downloads and installs all the libraries and dependencies outlined in the composer.lock file. If the file does not exist it will look for composer.json and do the same, creating a composer.lock file.

composer install --dry-run

Simulates the install without installing anything.

This command doesn’t change any file. If composer.lock is not present, it will create it.

composer.lock should always be committed to the repository. It has all the information needed to bring the local dependencies to the last committed state. If that file is modified on the repository, you will need to run composer install again after fetching the changes to update your local dependencies to those on that file

Adding packages

composer require vendor/package 
## or in a short way
composer req vendor/package 

Adds package from vendor to composer.json’s require section and installs it

composer require vendor/package --dev

Adds package from vendor to composer.json’s require-dev section and installs it. This command changes both the composer.json and composer.lock files.

Removing packages

composer remove vendor/package

Removes vendor/package from composer.json and uninstalls it This command changes both the composer.json and composer.lock files.

 

Updating packages

composer update

Updates all packages

composer update --with-dependencies

Updates all packages and its dependencies

composer update vendor/package

Updates a certain package from vendor

 
composer update vendor/*

Updates all packages from vendor

composer update --lock

Updates composer.lock hash without updating any packages This command changes only the composer.lock file.

PS: the all above comments will work to install drupal , just keep in mind in all drupal modules,  vendor=drupal, it means if you want to install a module, just change vendor name in above command wit drupal.for example

I want to install  Nothing  module, the url of the module is https://www.drupal.org/project/nothing so the command for install it is 

composer req drupal/nothing

Development with composer and packages is much much easier than legacy code.

Additional link:

https://getcomposer.org/download/

Nov 08 2019
Nov 08

The API that the JSON:API module makes available is centered on Drupal's entity types and bundles. Every bundle receives its own, unique URL path, which all follow a shared pattern

HTTP Methods

JSON:API specifies what HTTP Methods to accept. Those are: GET, POST, PATCH, and DELETE. Notably, PUT is not included.

  • GET - Retrieve data, can be a collection of resources or an individual resource
  • POST - Create a new resource
  • PATCH - Update an existing resource
  • DELETE - Remove an existing resource

Authentication

Typically some form of authentication is used for POST requests. The examples below all use Basic Authentication. Enable the HTTP Basic Authentication module, set the permission for the API user (and role) and set the encoded username and password to the 'Authorization' request header.

Headers

Make sure to use 'Content type' and 'Accept' headers when appropriate

Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

Response codes

The JSON:API Specification also dictates acceptable responses. The Drupal implementation uses a subset of those. The module can respond with the following codes:

  • 200 OK - All successful GET and PATCH requests
  • 201 Created - All successful POST requests (response includes the newly created resource)
  • 204 No Content - All successful DELETE requests

And here's the detailed documentation - https://www.drupal.org/docs/8/modules/jsonapi/get-post-patch-and-delete

And here's the sample postman collection - https://gitlab.com/heykarthikwithu/drupal-jsonapi---sample-api-calls

Thanks :)

Nov 05 2019
Nov 05

The Drupal Pitch deck has been created, as part of the Promote Drupal initiative, to support and strengthen the position of those in sales roles who present Drupal to decision makers and buyers. We want to help elevate Drupal via agencies, co-ops, and independents. It is an initiative I have led, in close partnership with Suzanne Dergacheva and Ricardo Amaro and involving over 100 contributors.

The Drupal Pitch Deck slides

Born out of a meeting of European Drupal leaders in Darmstadt. In just 12 months ago The Drupal Pitch Deck has come a long way. Version 2.0 of the deck is available now, contains 108 slides in all, and 73 case studies representing the best Drupal projects from agencies across the globe

It was fantastic to see the project featured during introductions ahead of the DriesNote and Suzanne Dergacheva present The story of how the pitch deck came to be at the Drupal Initiatives Keynote at DrupalCon Amsterdam. Seeing non code contributions from so many people being celebrated on this global stage was a real highpoint of the conference for me.

Call for content remains open, you can Add Your Slide Here. With the latest and greatest Drupal projects celebrated at the International Splash Awards we are calling all agencies to submit their incredible new case studies.

In preparation for DrupalCon the team at CTI Digital worked to deliver a solution which allowed all deck content to be transferred into Drupal 8. Integrated to Lingotek at translation management system which enables us to start the internationalisation of the pitch deck. Special thanks must go to Richard Roberts at Lingotek who worked tirelessly over the week of DrupalCon on boarding community translators.

Now that we have systems in place we are actively inviting people to volunteer to translate slides into their language here.

Stages of development

Call for front end developers

All but stage 7 is complete now. We are keen to attract front end developers to join the effort to produce the presentation layer, a Drupal theme. What we have in mind is detailed here

Promote Drupal Pitch Deck Version 2.0 released

During the Birds of a Feather “Bof” meeting we released Version 2.0 of the Pitch Deck which you can download now.

Pitch Deck BoF

Photo: Alex Moreno

Contribution day

Non code contributions to Drupal is a theme close to my heart. So I was delighted to see 2 tables full of people translating and creating new content at the Contribution Day.

Contribution day table
 

Not only this, some of the team were first time contributions and only registered on Drupal.org for 3 weeks. For me this is what success looks like.

Issue queue recognising non code contributions

In addition to translation we saw several subject experts drafting new slides providing supporting evidence as to why Drupal is a prime choice in Higher Education and for Government.

New slides

We still need volunteers in far greater numbers to achieve the translation into 16 languages which is underway. Right now we are calling for people speaking English and the following languages to volunteer.

  • Arabic
  • Bulgarian
  • Catalan
  • Dutch
  • English
  • Farsi (Persian)
  • French
  • French
  • German
  • Hebrew
  • Hindi
  • Hungarian
  • Italian
  • Japanese
  • Polish
  • Portuguese
  • Slovak
  • Spanish
  • Thai
  • Turkish

In conclusion the Pitch Deck Initiative has achieved far more than we could ever have imagined on that day in Darmstadt last year. With the right support from community members we will soon deliver decks in 19 languages. It really is down to you! It’s an ideal opportunity to contribute your skills in bite size chunks. As you’ve already seen there are plenty of ways to join our movement.

On behalf of Ricardo, Suzanne and myself many thanks to all who have participated. We look forward to meeting you too, everyone is welcome!

Oct 28 2019
Oct 28

The Drupal 8 version of the Salesforce Suite provides a powerful combination of features that are ready to use and mechanisms for adding custom add-ons you may need.  What it does not yet have is lots of good public documentation to explain all those features.

A recent support issue in the Salesforce issue queue asked for example code for writing queries. While I’ll address some of that here, there is ongoing work to replace the query interface to be more like Drupal core’s.  Hopefully once that’s complete I’ll get a chance to revise this article, but be warned some of those details may be a little out of date depending on when you read this post.

To run a simple query for all closed Opportunities related to an Account that closed after a specific date you can do something like the following:

      $query = new SelectQuery('Opportunity');
      $query->fields = [
        'Id',
        'Name',
        'Description',
        'CloseDate',
        'Amount',
        'StageName',
      ];
      $query->addCondition('AccountId', $desiredAccountId, '=');
      $query->conditions[] = [
        "(StageName", '=', "'Closed Won'",
        'OR', 'StageName', '=', "'Closed Lost')",
      ];
      $query->conditions[] = ['CloseDate', '>=', $someSelectedDate];
      $sfResponse = \Drupal::service('salesforce.client')->query($query);

The class would need to include a use statement for to get Drupal\salesforce\SelectQuery; And ideally you would embed this in a service that would allow you to inject the Salesforce Client service more correctly, but hopefully you get the idea.

The main oddity in the code above is the handling of query conditions (which is part of what lead to the forthcoming interface changes). You can use the addCondition() method and provide a field name, value, and comparison as lie 10 does. Or you can add an array of terms directly to the conditions array that will be imploded together. Each element of the conditions array will be ANDed together, so OR conditions need to be inserted the way lines 11-14 handle it.

Running a query in the abstract is pretty straight forward, the main question really is what are you going to do with the data that comes from the query. The suite’s main mapping features provide most of what you need for just pulling down data to store in entities, and you should use the entity mapping features until you have a really good reason not to, so the need for direct querying is somewhat limited.

But there are use cases that make sense to run queries directly. Largely these are around pulling down data that needs to be updated in near-real time (so perhaps that list of opportunities would be ones related to my user that were closed in the last week instead of some random account).

I’ve written about using Drupal 8 to proxy remote APIs before. If you look at the sample code you’ll see the comment that says: // Do some useful stuff to build an array of data.  Now is your chance to do something useful:

fields = [
            'Id',
            'Name',
            'Description',
            'CloseDate',
            'Amount',
            'StageName',
        ];
        $query->addCondition('AccountId', $desiredAccountId, '=');
        $query->conditions[] = [
            "(StageName", '=', "'Closed Won'",
            'OR', 'StageName', '=', "'Closed Lost')",
        ];
        $query->conditions[] = ['CloseDate', '>=', $someSelectedDate];
        $sfResponse = \Drupal::service('salesforce.client')->query($query);
 
    if (!empty($sfResponse)) {
        $data['opp_count'] = $sfResponse->size();
        $data['opps'] = [];
 
        if ($data['opp_count']) {
            foreach ($sfResponse->records() as $opp) {
                $data['opps'][] = $opp->fields();
            }
        }
    }
    else {
      $data['opp_count'] = 0;
    }
    // Add Cache settings for Max-age and URL context.
    // You can use any of Drupal's contexts, tags, and time.
    $data['#cache'] = [
        'max-age' => 600, 
        'contexts' => [
            'url',
            'user',     
        ],
    ];
    $response = new CacheableJsonResponse($data);
    $response->addCacheableDependency(CacheableMetadata::createFromRenderArray($data));
    return $response;
  }
}

I left out a couple details above on purpose. Most notable I am not showing ways to get the needed SFID for filtering because you need to apply a little security checking on your route/controller/service. And those checks are probably specific to your project. If you are not careful you could let anonymous users just explore your whole database. It is an easy mistake to make if you do something like use a Salesforce ID as a URL parameter of some kind. You will want to make sure you know who is running queries and that they are allowed to see the data you are about to present. This is on you as the developer, not on Drupal or Salesforce, and I’m not risking giving you a bad example to follow.

Another detail to note is that I used the cache response for a reason.  Without caching every request would go through to Salesforce. This is both slower than getting cached results (their REST API is not super fast and you are proxying through Drupal along the way), and leaves you open to a simple DOS where someone makes a bunch of calls and sucks up all your API requests for the day. Think carefully before limiting or removing those cache options (and make sure your cache actually works in production).  Setting a context of both URL and User can help ensure the right people see the right data at the right time.

Oct 22 2019
Oct 22

Contextual filters in Drupal allow you to add or remove information (content) to the currently displayed view. The filter acts dynamically based on the URL.

If the provided argument value is in the URL, the view will contain certain results, if the value is not in the URL, the view will be filtered with other results.

This whole concept implies certain complexity, so the best way to clarify it is with an example. 

Keep reading if you want to grasp the idea behind contextual filters in Drupal 8!

Step #1. Create the View

For the purpose of this tutorial, I have created 11 articles with an image and body text.

190930 drupal basic workflow

  191019 contextual filers 001

The goal of this exercise is to create a block with a view displaying articles, related to the currently viewed post. 

  • Click Structure > Views > Add view
  • Set the following options
    • Show Content of type Article
    • Create a Block
    • Display a Grid of fields
    • Choose 12 items per block
  • Click Save and edit

191019 contextual filers 002

  • On the FIELDS section click Add
  • Search for the Image field and select it
  • Click Add and configure fields

191019 contextual filers 003

  • Link the image to the Content

Notice that I created a squared image style (Configuration > Image styles), to display it in the view. More on Image styles on a future tutorial. 

  • Click Apply

  191019 contextual filers 004 

  • In the FIELDS section click the dropdown arrow and select Rearrange

191019 contextual filers 005

  • Drag the Image field above the Title
  • Click Apply

191019 contextual filers 006 

  • Click Grid Settings in the FORMAT section
  • Change the number of columns to 2
  • Click Apply

191019 contextual filers 006

  • Click Save to save the view

 Step #2. - Place the View Block

  • Click Structure > Block layout
  • Scroll down to the Sidebar second region
  • Click Place block

191019 contextual filers 008

NOTICE: I have also removed the 2 blocks on the Sidebar first region.

  • Search for the name of your view in the search box
  • Click Place block

191019 contextual filers 009

  • Restrict the block only to the Article content type
  • Click Save block

191019 contextual filers 010

  • Go to the frontend of your site
  • Open one of your articles.

You will see the block displaying the view the way you have just configured it. However, the currently displayed article will also appear within the view results. That is not user-friendly and looks less professional.

191019 contextual filers 011

Step #3. - Views Contextual Filters

  • Hover your mouse over the block  
  • Click the pencil icon and Edit view

  191019 contextual filers 012

  • Click ADVANCED to display the right-hand column of Views UI
  • Click Add to ad a Contextual filter

191019 contextual filers 013

  • Display only the filters related to Content
  • Select the Entity (Content) ID as a contextual filter
  • Click Add and configure contextual filters

191019 contextual filers 014

This view is displayed in a block. Blocks do not have URLs to reference, so you have to add this “connection” manually. 

  • Click When the filter value is NOT available
  • Select Provide default value
  • Choose Content ID from URL
  • Click Apply

191019 contextual filers 015

  • Scroll down to the Preview section

This is where you can test how the contextual filter works. The system will take the value of the Article (in this case) ID from the URL and according to that value, it will filter and present the right view. 

One thing to notice is that Drupal is smart enough to internally figure out the node id, even if you have enabled Pathauto, or have changed the URL manually in the node edit form.   

  • Enter the ID of one of your articles
  • Click Update preview

191019 contextual filers 016

The view will display just the element related to that particular article. This is not what we want to have. As a matter of fact, it is the exact opposite of what we want to achieve.

  • Click the Content: ID filter
  • Scroll down and click MORE
  • Check Exclude
  • Click Apply

191019 contextual filers 017

By clicking exclude, you are basically telling Drupal to display all results of the view, except the one related to the currently displayed article. 

  • Click Save to save the view

If you go to one of your articles, you will see a block displaying all other related publications, but not the one you are reading.

191019 contextual filers 018

This tutorial only scratches the surface of what is possible with contextual filters. I hope this has helped you to clarify the concept a little more.

Thanks for reading! 


About the author

Jorge lived in Ecuador and Germany. Now he is back to his homeland Colombia. He spends his time translating from English and German to Spanish. He enjoys playing with Drupal and other Open Source Content Management Systems and technologies.
Oct 17 2019
Oct 17

The Drupal 8 Salesforce Suite allows you to map Drupal entities to Salesforce objects using a 1-to-1 mapping. To do this it provides a series of field mapping types that allow you to select how you want to relate the data between the two systems. Each field type provides handling to help ensure the data is handled correctly on each side of the system.

As of this writing the suite provides six usable field mapping types:

  • Properties — The most common type to handle mapping data fields.
  • Record Type — A special handler to support Salesforce record type settings when needed.
  • Related IDs — Handles translating SFIDs to Drupal Entity IDs when two objects are related in both systems.
  • Related Properties — For handling properties across a relationship (when possible).
  • Constant — A constant value on the Drupal side that can be pushed to Salesforce.
  • Token — A value set via Drupal Token.

There is a seventh called Broken to handle mappings that have changed and need a fallback until its fixed. The salesforce_examples module also includes a very simple example called Hardcoded the shows how to create a mapping with a fixed value (similar to, but less powerful than, Constant field).

These six handle the vast majority of use cases but not all.  Fortunately the suite was designed using Drupal 8 annotated plugins , so you can add your own as needed. There is an example in the suite’s example module, and you can review the code of the ones that are included, but I think some people would find an overview helpful.

As an example I’m using the plugin I created to add support for related entities to the webform submodule of the suite (I’m referencing the patch in #10 cause that’s current as of this writing, but you should actually use whatever version is most recent or been accepted).

Like all good annotated plugins to tell Drupal about it all we have to do is create the file in the right place. In this case that is: [my_module_root]/src/Plugins/SalesforceMappingField/[ClassName] or more specifically: salesforce_webform/src/Plugin/SalesforceMappingField/WebformEntityElements.php

At the top of the file we need to define the namespace, add some use statements.


Next we need to provide the required annotation for the plugin manager to use. In this case it just provides the plugin’s ID, which needs to be unique across all plugins of this type, and a translated label.

/**
 * Adapter for Webform elements.
 *
 * @Plugin(
 *   id = "WebformEntityElements",
 *   label = @Translation("Webform entity elements")
 * )
 */

Now we define the class itself which must extend SalesforceMappingFieldPluginBase.

class WebformEntityElements extends SalesforceMappingFieldPluginBase {

With those things in place we can start the real work.  The mapping field plugins are made up of a few parts: 

  • The configuration form elements which display on the mapping settings edit form.
  • A value function to provide the actual outbound value from the field.
  • Nice details to limit when the mapping should be used, and support dependency management.

The buildConfigurationForm function returns an array of form elements. The base class provides some basic pieces of that array that you should plan to use and modify. So first we call the function on that parent class, and then make our changes:

 /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $pluginForm = parent::buildConfigurationForm($form, $form_state);
 
    $options = $this->getConfigurationOptions($form['#entity']);
 
    if (empty($options)) {
      $pluginForm['drupal_field_value'] += [
        '#markup' => t('No available webform entity reference elements.'),
      ];
    }
    else {
      $pluginForm['drupal_field_value'] += [
        '#type' => 'select',
        '#options' => $options,
        '#empty_option' => $this->t('- Select -'),
        '#default_value' => $this->config('drupal_field_value'),
        '#description' => $this->t('Select a webform entity reference element.'),
      ];
    }
    // Just allowed to push.
    $pluginForm['direction']['#options'] = [
      MappingConstants::SALESFORCE_MAPPING_DIRECTION_DRUPAL_SF => $pluginForm['direction']['#options'][MappingConstants::SALESFORCE_MAPPING_DIRECTION_DRUPAL_SF],
    ];
    $pluginForm['direction']['#default_value'] =
      MappingConstants::SALESFORCE_MAPPING_DIRECTION_DRUPAL_SF;
    return $pluginForm;
 
  }

In this case we are using a helper function to get us a list of entity reference fields on this plugin (details are in the patch and unimportant to this discussion). We then make those fields the list of Drupal fields for the settings form. The array we got from the parent class already provides a list of Salesforce fields in $pluginForm[‘salesforce_field’] so we don’t have to worry about that part.  Since the salesforce_webform module is push-only on its mappings, this plugin was designed to be push only as well, and so limits to direction options to be push only. The default set of options is:    

'#options' => [
    MappingConstants::SALESFORCE_MAPPING_DIRECTION_DRUPAL_SF => t('Drupal to SF'),
    MappingConstants::SALESFORCE_MAPPING_DIRECTION_SF_DRUPAL => t('SF to Drupal'),
    MappingConstants::SALESFORCE_MAPPING_DIRECTION_SYNC => t('Sync'),
 ],

And you can limit those anyway that makes sense for your plugin.

With the form array completed, we now move on to the value function. This is generally the most interesting part of the plugin since it does the work of actually setting the value returned by the mapping.

  /**
   * {@inheritdoc}
   */
  public function value(EntityInterface $entity, SalesforceMappingInterface $mapping) {
    $element_parts = explode('__', $this->config('drupal_field_value'));
    $main_element_name = reset($element_parts);
    $webform = $this->entityTypeManager->getStorage('webform')->load($mapping->get('drupal_bundle'));
    $webform_element = $webform->getElement($main_element_name);
    if (!$webform_element) {
      // This reference field does not exist.
      return;
    }
 
    try {
 
      $value = $entity->getElementData($main_element_name);
 
      $referenced_mappings = $this->mappedObjectStorage->loadByDrupal($webform_element['#target_type'], $value);
      if (!empty($referenced_mappings)) {
        $mapping = reset($referenced_mappings);
        return $mapping->sfid();
      }
    }
    catch (\Exception $e) {
      return NULL;
    }
  }

In this case we are finding the entity referred to in the webform submission, loading any mapping objects that may exist for that entity, and returning the Salesforce ID of the mapped object if it exists.  Yours will likely need to do something very different.

There are actually two related functions defined by the plugin interface, defined in the base class, and available for override as needed for setting pull and push values independently:

  /**
   * An extension of ::value, ::pushValue does some basic type-checking and
   * validation against Salesforce field types to protect against basic data
   * errors.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   * @param \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface $mapping
   *
   * @return mixed
   */
  public function pushValue(EntityInterface $entity, SalesforceMappingInterface $mapping);
 
  /**
   * An extension of ::value, ::pullValue does some basic type-checking and
   * validation against Drupal field types to protect against basic data
   * errors.
   *
   * @param \Drupal\salesforce\SObject $sf_object
   * @param \Drupal\Core\Entity\EntityInterface $entity
   * @param \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface $mapping
   *
   * @return mixed
   */
  public function pullValue(SObject $sf_object, EntityInterface $entity, SalesforceMappingInterface $mapping);
 

But be careful overriding them directly. The base class provides some useful handling of various data types that need massaging between Drupal and Salesforce, you may lose that if you aren’t careful. I encourage you to look at the details of both pushValue and pullValue before working on those.

Okay, with the configuration and values handled, we just need to deal with programmatically telling Drupal when it can pull and push these fields. Most of the time you don’t need to do this, but you can simplify some of the processing by overriding pull() and push() to make sure the have the right response hard coded instead of derived from other sources. In this case pulling the field would be bad, so we block that:

  /**
   * {@inheritdoc}
   */
  public function pull() {
    return FALSE;
  }

Also, we only want this mapping to appear as an option if the site has the webform module enabled. Without it there is no point in offering it at all. The plugin interface provides a function called isAllowed() for this purpose:

  /**
   * {@inheritdoc}
   */
  public static function isAllowed(SalesforceMappingInterface $mapping) {
    return \Drupal::service('module_handler')->moduleExists('webform');
  }

You can also use that function to limit a field even more tightly based on the mapping itself.

To further ensure the configuration of this mapping entity defines its dependencies correctly we can define additional dependencies in getDependencies(). Again here we are tied to the Webform module and we should enforce that during and config exports:

  /**
   * {@inheritdoc}
   */
  public function getDependencies(SalesforceMappingInterface $mapping) {
    return ['module' => ['webform']];
  }

And that is about it.  Once the class exists and is properly setup, all you need to do is rebuild the caches and you should see your new mapping field as an option on your Salesforce mapping objects (at least when isAllowed() is returning true).

Oct 15 2019
Oct 15

What a UX designer thinks will be quite different from what a mechanical engineer thinks, which will be worlds away from what an artist thinks.

For example,

  • I am a trained civil engineer. As an engineer, design is in providing the minimal technical solution that fits the brief.
  • I often work in the role of a (web) site architect, where design is in accurately modelling business data to provide efficient and scaleable solutions.
  • I was never great at graphic design as my photoshop-fu is weak, but I always understood that as a graphic desiger, design is in creating beautiful interfaces for people to interact with.

As a developer, which takes up most of my daily work, I take website designs created by others and implement these into real, usable, functional software. I'm going to talk about things I have seen on real projects, with real clients and perfectly competent teams, where the design actually hindered the build process.

Building The Foundations, Out of TNT

Design can easily make or break a project, and graphic design is easily the most impactful of all design processes. From this point on, any references to 'design' will refer to web design, the graphical design of a web site, such as is often delivered as a Photoshop file (.psd) for implementation by developers.

I have seen great projects with great project teams really struggle because a design, whilst beautiful, was very difficult to implement. Conversely, a design that facilitates ease of implementation can make the project a joy to work on, and will result in a happy client and success all round. Site owners love something that they can 'sign off' on, and more often than not, the first thing that is signed off is the design, which can become a Bible against which the entire project is measured. It is little wonder that design can have such wide-ranging implications.

Deep Impact

There are many ways in which design can impact upon a project.

It's a safe assumption that a website will be built upon a content management system (CMS) - in Annertech's case, we use Drupal. The CMS will have a way of doing things, and the design can work with it, or the design can hinder it.

Nowadays, every site should be a responsive site. But does your design naturally lend itself to being responsive? This does not mean that as a designer you should create separate designs for multiple screen-sizes, but rather that a given design should naturally adjust and flow for different devices. In fact, having a separate design for mobile and tablet-sized screens to desktop can actually hinder development because of inconsistencies of design elements across Photoshop files. Without a solid understanding of how devices interact with and render a page, how page elements float and stack and expand and contract, you run the risk of a design that requires undue effort to force onto a small screen, resulting in a sub-optimal end product. When designing adaptive layouts, content order really matters too. The natural order and flow of DOM elements (if you are not a developer, read: "things on the page") should not have to be adjusted based upon screen width. To do so adds unnecessary complexity and will again probably impact upon performance - how quick your site is rendered on a screen for users.

An Artful Work of Fantasy

Sometimes a design will show visual effects that CSS simply will not produce. Whilst often these effects can be created with enough Javascript and imagery, often the trade-offs (maintainability, performance, page weight) are not worth the gain. Mobile performance, especially, can fall victim here.

A Font is Worth 1000 Pictures

Any designer worth their salt will tell you that font choice is hugely important. This is undeniably true. But the following things are often forgotten when choosing fonts:

  • A font can add considerably to page weight, depending on how many weights/styles you include.
  • On large and complex pages the Flash of Unstyled Text (the screen showing default fonts before the correct ones get to load) when using javascript-based font-replacement techniques can by very jarring. It can also be rather slow to go away on older browsers/machines.
  • Fonts can be expensive, and clients do not always want to pay for them. The smart money says: find out what the font budget is before you do your design. For example, a Photoshop design showing Proxima Nova (€615.99) will never look like a site built using Arial. This will cause untold friction between developer, designer and client over the build process.
  • Not all fonts are created equal. Some fonts might look lovely on a crisp MacBook Pro with retina display, but make sure you look at them on Windows, with a shoddy old 17" monitor. Often that is quite a different experience.

50 Shades of Grey

Great design is all about subtlety and attention to detail. However, this should not deliver a licence for the inclusion of unnecessary detail.

For example, a consistent and concise colour palette is a thing of beauty. However, more than a dozen shades of grey, many indistinguishable from one-another to the lay user, is merely an expensive waste. Again, try out the design on a low-budget monitor: can you tell the difference between #ffffff and #f4f4f4? If not, you probably don't need that level of subtlety and should simplify your design. Yeah, that's right: shots fired in the Needless-Shades-of-Grey wars.

To put it another way, consistency of design elements is a really powerful tool in a web designer's arsenal. Consistently presented elements, re-used in a logical manner, can endlessly simplify CSS, speed up site builds and improve performance. Clearly this is a desirable outcome!

An Appeal for Sanity

Speaking as a developer, this is my plea to designers everywhere to think about how your design can be implemented. Every addition to the design will have an impact on the build and probably on the end user. Is it necessary? Will it enhance or hinder? The ideal is design in the browser, so that you can mock up interactions, see how DOM elements (again, "things on the page") react to changes in screen width and look at what CSS can achieve and what it can't. This is not about asking the designer to do development, but rather to ensure that the agreed-upon design can be practically implemented.

Shucks, as a designer, you might even ask the developer "hey, any problems implementing this before I ask for sign-off from the client?".

Website owners: It's Up to You

Prospective site owners: people who would like to get a Drupal site built. This appeal I direct to you: "Do not accept the artful work of fancy."

There are two possible scenarios stemming from an impractical design.

  1. If you get the design before contracting a development team, the price will be higher than otherwise, as the design makes it more difficult.
  2. If the design is late and the developers have already begun, the project will be late as the effort required will be far greater than originally estimated.

Rather, ask for a design that works with your choice of CMS. One that facilitates responsiveness. A design that is not unnecessarily complicated. These are often the most beautifully simple, accessible designs. Everybody wins.

Love Your Developers

This final plea is one directly related to Photoshop. It is an amazing tool, and one that facilitates wonderful-looking sites. However, I open PSDs with dread. But it does not have to be that way. Herewith, a couple of tips to make the dev in your life happy:

  1. Name your layers. Names like 'Layer 35 Copy' make developers sad. We who are not conversant with the mysteries of Photoshop really find semantically named layers useful! (such as "Sidebar block, heading")
  2. Apply your layer effects. Unless one actually possesses a copy of Photoshop, one cannot see layer effects. Gimp and Preview won't parse them. Be nice to your devs and apply the effects to the layers that require them so that when we slice up a layer, we get the colour you intend and not a pale imitation.

Conclusion

Modern websites are really complex, and it takes a team of dedicated, skilled people to create them. The designer is often the first onto the green field site, and is arguably the person with the most far-reaching power. I suspect that many designers simply do not realise the depth and breadth of their power.

I think that in an absolute ideal, a designer would work alongside the developers, rather than rather than handing over "signed off designs", to create a site that is a harmonious thing of beauty.

Let's work together.

* No sites were harmed in the writing of this blog post
** Whilst all examples come from real life, names have been changed to protect the guilty parties
*** We'd love some cake, if you're sharing

If you want to discuss Annertech helping you build an award-winning website, please feel free to contact us by phone on 01 524 0312, by email at [email protected], or using our contact form.

Oct 09 2019
Oct 09

Drupal is a wonderful Content Management System with tons of features that solve many problems for editors and content managers. A developer can take different approaches to achieve the same result, and the Drupal update process is no exception.

It is possible to update Drupal either with Composer, Drush, or manually within the CPanel interface. The first two methods imply that you have at least mid-level experience with the command line and secure shell access to your public host. The third method is more visual and is suitable for developers beginning with Drupal.

Keep reading, if you want to learn how to update your Drupal site with this method.

Step #1. The Local Installation

This tutorial assumes, you already have managed to create a local installation, as described in steps #6 and #7 of this tutorial. This tutorial will build upon that example.

  • Enter the SSH mode of the virtual machine (Scotch box) 

vagrant up

vagrant ssh

190930 drupal basic workflow

  • Access the public directory of your virtual machine

cd /var/www/public   

  • Enter 192.168.33.10 on the address bar of your browser to access the site
  • Click Configuration > Maintenance mode
  • Check Put site into maintenance mode
  • Click Save configuration

190930 drupal basic workflow 001

The local site is now in maintenance mode. You need to create a backup of the database and of the codebase. 

  • In the terminal of your PC, type:  tar -zcvf drupal-backup.tar.gz .

To create a compressed file called drupal-backup.tar.gz of the public directory. This process will take about one minute. 

190930 drupal basic workflow 002

To create a copy of the database type: 

mysqldump -u root -p my_drupal_8 > /var/www/public/my_drupal_8.sql

  • Enter root as password (you won’t see any characters rendered on the screen)

190930 drupal basic workflow 003

Notice that these two files are now stored inside the public directory within the virtual machine and also in the public directory located at mydrupalbox in your projects folder. 

190930 drupal basic workflow 004

 Step #2. - Installing on a Production Server

On a regular hosting provider, you normally install your application (e.g. Drupal) with a one-click-install procedure. 

190930 drupal basic workflow 005

The hosting provider will assign a Username and Password for the newly created account. We need these, to edit the settings.php file of the installation we are going to import. 

  • Click the link to CPanel
  • Click File manager within the Files section

190930 drupal basic workflow 006

  • Click on the public_html folder on the left 

190930 drupal basic workflow 007

On the right is the Drupal codebase installed by the system of your hosting provider.

  • Select all files and folders
  • Press Delete
  • On the menu bar Click Upload, a new tab will open

190930 drupal basic workflow 008

  • Click Select file
  • Upload the compressed file you created in the last step

190930 drupal basic workflow 009

  • Select the file
  • Click Extract
  • Click Extract file(s)
  • Click Close
  • Select the tar.gz file and press Delete
  • Press Confirm
  • Open the sites/default folder
  • Select the settings.php file
  • Click the pencil on the menu bar, to edit the file
  • Scroll down to the end of the file
  • Change the database, username, and password with the ones you got from your hosting provider (hint: a better approach is to edit the file before compression on your local installation)


To find out the database name, head over to CPanel. In the Databases section, click  phpmyadmin 

190930 drupal basic workflow 011

The database name is on the left. 

190930 drupal basic workflow 012

  • Edit the settings.php file accordingly 
  • Click Save changes
  • Click Close

190930 drupal basic workflow 013.0

 Step #3. - The Database

  • In phpmyadmin scroll down and click Select all, to select all tables

190930 drupal basic workflow 013

  • On the dropdown select DROP
  •  Click Yes/ok

190930 drupal basic workflow 014

The database is now empty.

  • Click Import
  • Select the database backup you created in the last step

190930 drupal basic workflow 015

  • Click Continue

The system will prompt you, once the import process has finished.

190930 drupal basic workflow 016

  • In the address bar of your browser type:  mysitedomain.com/user 
  • Enter your Username and password - make sure that you change these in your user profile, in case you had a less secure password in your local installation
  • On the address bar type: mysitedomain.com/update.php

You will be redirected to the Update screen

  • Click Continue

190930 drupal basic workflow 018

If everything goes well, the system will prompt you to continue to the Front page or the Administration pages. 

  • Click Administration pages
  • Click Configuration > Maintenance mode
  • Uncheck Put site into maintenance mode
  • Click Save configuration

190930 drupal basic workflow 019

How to Update Drupal Core

The first thing you have to check on your local installation is the status of core and contrib modules. 

After putting your local installation on maintenance mode, and making backups of the codebase and the database, position your cursor at the root folder of your local installation (the composer.json file is there)

  • Type: composer outdated "drupal/*"   

To check for outdated modules.

  • To update modules type: composer require drupal/modulename     

Just like re-installing the module.

190930 drupal basic workflow 020

You can update all modules, but as you can see, the drupal/core package is not listed. 

190930 drupal basic workflow 021

Honestly, I don’t know what this is about, however, this is simple to solve. 

  • Edit the composer.json file

Omit the “replace” section and place the “drupal/core”: ”^8.x” statement inside the “require” section.

190930 drupal basic workflow 022

190930 drupal basic workflow 023

rm composer.lock     -To delete the file.

sudo rm -R vendor    -To delete the folder

 composer update drupal/core --with-dependencies     -To update Drupal core. This will also generate the vendor folder and the composer.json file.

190930 drupal basic workflow 024

  190930 drupal basic workflow 025

Now you need to start over with step #2. You will not need to upload the database this time.  

I hope you liked this tutorial.

Thanks for reading!


About the author

Jorge lived in Ecuador and Germany. Now he is back to his homeland Colombia. He spends his time translating from English and German to Spanish. He enjoys playing with Drupal and other Open Source Content Management Systems and technologies.
Sep 25 2019
Sep 25

Yesterday the digital experience world and the Drupal community received the long awaited answer to the question: What’s going to happen with Acquia? When it was announced, first on Bloomberg that Vista Equity Partners would be buying a majority stake in Acquia which it values at $1B. 

Many were caught off guard by the timing, but an event like this had been expected for a long time. After receiving nine rounds of venture funding totaling $173.5M, it was time. As the leader and largest company in the Drupal space, Acquia has a center of gravity that leaves many asking a new question: What Now for Drupal?

What Are the Angles?

Before I attempt to answer what I think this means for Drupal and the Drupal community, I think it is worthwhile to at least speculate on the strategy Acquia plans to pursue as a part of Vista. It seems that everyone I have heard from both offline and online since the announcement yesterday are speculating on the Vista angle (i.e. why did they want Acquia?). As TechCrunch led with “Vista Equity Partners...likes to purchase undervalued tech companies and turn them around for a hefty profit…” Well that’s pretty much what a PE firm does. And to me less interesting than asking: What does Acquia want from Vista?

What I believe Acquia wanted to get out of this is a heavy weight partner with capital and connections that could help develop Acquia into a more formidable competitor to Adobe, Sitecore and other digital experience platforms (“DXP”). It was just last week that Salesforce Ventures made a very sizeable $300M investment in Automattic, the parent company of WordPress. Things are heating up with all of the top digital experience platforms and no one is going to survive, let alone stay in the front of the pack, without some serious capital behind them. 

Who Wins?

I believe Acquia plans to use Vista’s investment and resources to continue making targeted acquisitions and investments to become a more robust and powerful digital experience platform. I would expect them to grow their suite of products, invest even more heavily in sales and marketing to increase revenue and grow its installed base of customers. 

Vista will then have a more valuable asset from which to pursue either an IPO or a strategic acquisition. It is possible this will follow the pattern of Marketo, which Vista bought and then sold to Adobe for a $3B profit or Ping, which they recently took public in an IPO

So there are mutual interests being met and a fair valuation that gets the necessary attention - so both parties win. I also think customers win from increased product development, competition, and a more robust ecosystem.

What Does This Mean For Drupal?

I think this is the best of all possible scenarios for both Drupal (the product) and the Drupal community. While many will bemoan the intrusion of a large private equity firm into the sacred space of an open source community, change was inevitable and it comes with predictable tradeoffs that have to be measured in the context of a new reality for the space. The community needs the indirect investment that this deal provides and it far outweighs the alternatives. If you assume that there were only a few possible scenarios for Acquia that were going to play out sooner or later, they would be:

  1. Organic growth / status quo - In my opinion, the worst scenario due to the dynamics of the market converging. Without a huge infusion of capital like the Vista deal into Acquia, Drupal simply wouldn’t be able to compete fast enough to stay in the top DXP category against Adobe, Sitecore, Salesforce and WordPress. 

  2. IPO - As a liquidation event for VC investors, this could be perhaps the most lucrative, but the public markets are fickle and I believe that would be very hard on a large open source community and product like Drupal due to the dynamics of control for a public company. This may yet come to pass as the end game for Vista, but I think it is good it was not the immediate play. 

  3. Strategic Acquisition - Salesforce, Amazon, Google, IBM and others of this size would be likely acquirers. Again, this may yet come to pass, but it would not have been an ideal immediate short term play for Drupal because of the weight of influence it would add to the community and open source dynamic.  

  4. PE - Obviously, what did happen. This deal brings the financial strength and strategic opportunities without the messiness of the public markets or a new giant controlling the ecosystem. 

As for the direct benefits to the Drupal project, I take Dries at his word in the personal statement he made on his blog that this strategy will allow Acquia to provide even more for Drupal and the community including: 

  • Sponsor more Drupal and Mautic community events and meetups.
  • Increase the amount of Open Source code [sic] contributed.
  • Fund initiatives to improve diversity in Drupal and Mautic; to enable people from underrepresented groups to contribute, attend community events, and more.

Those are all things that directly benefit the community and make open source Drupal better in addition to the opportunities that the deal affords Acquia to better compete against its rivals. 

How Things Line Up From Here…

Consolidation and funding in the digital experience platform (“DXP”) space are going to make for a wild ride as the top players continue to unveil pieces of their strategy.  

  • Adobe - With Magento and Marketo neatly tucked up, Adobe remains the most competitive player both in terms of market share and the comprehensiveness of the offering, though cost and proprietary lock-in into a single homogenous platform are continued weaknesses. 

  • Acquia / Drupal - Recent acquisitions of platform components like Mautic and Cohesion are likely to continue or increase after the Vista deal in an effort to bring an open and more heterogeneous alternative to bear against the others. 

  • Sitecore - The recent acquisition of a top service provider, Hedgehog followed by the subsequent announcement that Sitecore was laying off 7% of its workforce can’t be interpreted as strong signs of health, but the enterprise market is full of Microsoft ecosystems that will be partial to Sitecore’s underlying technology. 

  • Automattic / WordPress - I have a less insight into the WordPress space than I do Drupal, but the SalesForce Ventures investment doesn’t feel like an attempt to gain a CMS for its own offering (sidenote: Salesforce does have a “CMS” and its Ventures has invested in other CMS’s like Contentful).  Founder Matt Mullenwig told TechCrunch  that Automattic doesn’t want to change course. With the new influx of cash, there won’t be any big departure from the current lineup of products and services. “The roadmap is the same. I just think we might be able to do it in five years instead of 10,” Their recent acquisition of Tumblr is part of a strategy I don’t fully understand, but seems to be a continued volume market move into the larger media space and less about competing with the other platform providers. However, $300M could go a long way in tooling the platform for lots of purposes. 

I also think there is a lot more to watch on the related martech front surrounding customer data. In April, Salesforce and Adobe announced (in the same week) that they were acquiring competing Customer Data Platform (CDP) products. So this is about the whole digital experience stack; where we are likely going to see more acquisitions and consolidation is beyond the CMS. 

What Does This Mean For Our Clients?

Despite the race to create the killer platform, most of our clients have consciously, or organically, adopted heterogenous digital experience platforms. This means they rely on many different components to “weave” together solutions that meets their unique requirements. As Forrester explains, DX is both a platform and a strategy and despite the influence of these major software and cloud players, a “digital experience” needs to be created - that includes strategy, customer research, UX, design, content, brand and the integration of custom and legacy software, and data sources in addition to purchased software. Still, we believe our customers do need to be aware of the changing dynamics in the market and in particular how consolidation will affect their platform investments. 

What Does This Mean For Phase2?

At Phase2, this news comes with much interest. We were one of the very first Acquia partners named after the company was founded in 2008. Over the last 10+ years, we have shared, and continue to share, numerous clients. We are also prolific contributors and implementers in the Drupal space who have been a part of some of the biggest and most impactful Drupal moments over the last ten years. We ourselves, once invested heavily in creating many products that extended and enhanced the capabilities of Drupal because we believe it is a powerful platform for creating digital experiences. 

Over time, as our agency grew and moved “up market”, we have diversified our expertise and have become Salesforce partners, developed Commerce experience, and enhanced our Design, UX and creative capabilities. We also use WordPress, Javascript frameworks for decoupled sites,  and static site generators in conjunction with a wide variety of marketing technologies to create digital experience platforms that go beyond websites and CMS

We will continue to monitor the trends and prepare and enable ourselves to create digital experiences that advance our clients goals and we fully expect Drupal will remain a key component of building those experiences well into the future. 

Sep 20 2019
Sep 20

Drupal is well known for its stability and security out-of-the-box. However, we all know how dangerous the internet can be with all the risks of having your site attacked. There are particular situations in which an extra security measures are needed. This tutorial will deal with specific ways to secure your Drupal site, and the modules involved in this process. 

Let’s get started!

The Out-of-the-Box Features

The Drupal theming system has been improved in Drupal 8 with the use of the templating language, Twig. Twig templating has many advantages over PHP templating. One of them is that it is much easier to visualize on code. Another advantage is the fact, that all variables passed to the template are auto-escaped automatically. That minimizes the risk of a variable including a result that could break the HTML, and therefore your site. The risk is also minimized because you do not have to write custom PHP code in your templates anymore.

The PHP input filter module was part of the Drupal core in Drupal 7, but in Drupal 8, it is a contributed module. This measure eliminates vulnerabilities.

Drupal 8 implemented the trusted hosts configuration. This allows you to associate the Drupal codebase with a specific domain, to prevent online spoofing attacks

Due to the new programmatic approach of Drupal, modules can be enhanced in their functionalities by adding plugins. These plugins add behaviors to the module. The code stays clean and easy to analyze.

The use of Composer as package manager opens the door to new development possibilities for Drupal Open Source software, and it also helps to maintain all modules and keep their dependencies up-to-date and working properly. This is a key factor for the stability of Drupal systems.

How to Enhance Security on Access - Contrib Modules

190919 drupal security

There are two alternatives:

  • Lock attack vectors within the system
  • Limit vulnerabilities by restricting or changing system functions and operations, taking the responsibility from the user

Here are some modules, which provide this kind of functionality:

Automated Logout

Link: https://www.drupal.org/project/autologout

This module allows you to configure the time period for users to be logged in on your site. You can configure different time periods for different user roles, assuming that a user with a higher role, i.e. with access to more valuable information or resources on the site, would need to log in more frequently, than a user with a lower role. 

Session Limit

Link: https://www.drupal.org/project/session_limit

With the Session limit module, you can determine the limit of simultaneous sessions per user on 2 different browsers. If you set the session limit to 1 and open a new session in another browser, the session of the first browser will automatically expire.

Login Security

Link: https://www.drupal.org/project/login_security

Login Security allows site administrators to authenticate user only from valid IP addresses, that way, it is possible to grant or restrict access to your site to whole countries if needed, just by configuring the right domain. Login security restricts also the number of login attempts, so brute force attacks can be avoided. An extra feature of this module is the fact that it can hide Drupal login error message. The attacker will have another problem trying out if the account he wants to access even exists. 

Security Kit    

Link: https://www.drupal.org/project/seckit

Security Kit allows developers to change response headers. This is useful for very specific security needs on sites with high probabilities of Cross-site scripting, Cross-site request forgery, and origin driven attacks.

Honeypot

Link: https://www.drupal.org/project/honeypot

Honeypot prevents robots from filling out the forms of your site, by determining if the user is human or not. It uses two identification methods. One of them is by using a hidden form field, which is not visible to humans if the field has been filled out, Honeypot detects this and blocks the submission. The other method is by taking the time in seconds, in which the form has been filled out. A low value here (2-3 seconds), would speak for a robot, so the module would block  this submission too.

CAPTCHA 

Link: https://www.drupal.org/project/captcha

A captcha is a challenge-response test, to determine whether the user is human or not. This way, the goal of blocking fake form submissions, is achieved since robots will not be able to decipher the captcha text or image.

Auditing - Checking Procedures

190919 drupal security 001

It is always important to permanently review the system logs. This is even more important if your site has already been compromised. The analysis of all this data will help you also to track transactions within your system and perform checks on the ongoing state of the system. A rule of thumb is to log as much data as possible - always!

Some of the modules, which provide this type of functionality are listed below:

Site Audit

Link: https://www.drupal.org/project/site_audit

Site audit performs a static analysis of the whole system, against a set of recommended configurations. The module also stores reports of every audit. By performing this check, you as a developer can be sure and confident that your site is meeting the required security standards.

Security Review

Link: https://www.drupal.org/project/security_review

Security review, like Site audit,  makes also an analysis of the system, but this time, against a set of potential security implications on your site, like file permissions, text formats, and potentially malicious PHP or JS code on the frontend. It also stores reports. 

Login History

Link: https://www.drupal.org/project/login_history 

Login history adds a report to the database with a log of every user login, including timestamp, IP address, and user agent information. As stated before, it is always good to log as much information as possible.

Authentication Measures

190919 drupal security 002

Often, the importance of the information, implicate a reduction of usability. Users take instead of that the extra hassle of these additional authentication procedures.

The modules that you can use for this purpose are listed below: 

Two-factor Authentication  

Link: https://www.drupal.org/project/tfa

Two-factor Authentication provides an additional verification step, which ensures the integrity of the user authenticating. It also provides an API to support different plugins (provided by modules), which integrate several authentication services, like the Google Authenticator module.

simpleSAMLphp Authentication 

Link: https://www.drupal.org/project/simplesamlphp_auth

This module will allow you to replace the default Drupal login with a single-sign-on implementation. The module communicates with identity providers for authenticating users. That way you can validate the identity of the user through a service like Twitter, Facebook or Google

Password Policy

Link: https://www.drupal.org/project/password_policy

The Password Policy module defines a set of rules to force users to have strong passwords. It also forces users to change their password from time to time, depending on the configured options. Password Policy provides an API to define your own set of rules. 

Password Strength

Link: https://www.drupal.org/project/password_strength

This module provides a star rating widget, for users to test the strength of their passwords. You can leverage the API of Password Policy to force users to enter a password with a high rating (minimum rating).

Encryption

190919 drupal security 003

The data at rest (data that is not being used) should be encrypted to prevent attacks of all types. The encryption provides solutions at all levels:

  • Hosting
  • Server
  • CDN
  • Drupal system

As a rule of thumb, and to guarantee the highest security, the best way is to perform encryption at a low level of this stack.

You should always use HTTPS and SSL for all your web traffic, and you should also ask your hosting or cloud provider about full disk encryption.

Some useful modules are:

Key

Link: https://www.drupal.org/project/key

The Key module manages the system and API keys. It provides an API with options to store and retrieve sensitive keys like API keys or encryption keys. The site admin can decide where to store these keys in the system. Examples of API keys are the public keys for services like AWS, PayPal, or MailChimp.

Encrypt

Link: https://www.drupal.org/project/encrypt

The Encrypt module is an API, which provides a common algorithms utility to encrypt and decrypt Drupal application data. Its API is leveraged by many modules, which make use of algorithms to encrypt/decrypt (Real AES, Diffuse), modules to encrypt data, like Field Encrypt and File Encrypt and other modules for more specific use cases, like Pubkey Encrypt.

File Encrypt

Link: https://www.drupal.org/project/file_encrypt

This module focuses on the file system, it performs a check of the encryption on all files.

Field Encryption

Link: https://www.drupal.org/project/field_encrypt

This module encrypts data at the field level, that is, it encrypts field values.

 DevOps (Developer Operations)

190919 drupal security 004

The development process is critical to proactively maintaining the security. You should always use code repositories and pull requests for all your files. Other measures imply performing regular code reviews, tag each one of your code releases, keep the site code always up-to-date (this includes JS libraries), and try always to avoid manual procedures because these entail mistakes. Always try to automate your scripts and use a tool like DRUSH.

Some of the relevant modules in this category are:

Coder

Link: https://www.drupal.org/project/coder

This module has PHP Code Sniffing extensions to test the code on your site and compare it against the coding standards of Drupal.org. Coder will not do anything on your UI. It is rather a command-line tool.   

Hacked

Link: https://www.drupal.org/project/hacked

The Hacked module scans the code of your core and contrib folders and compares it against the code hosted at Drupal.org. It shows the differences between both codebases, so you can take the proper measures regarding your code. 

Backup and migrate

Link: https://www.drupal.org/project/backup_migrate

This is a classic among Drupal modules. Backup and migrate performs regular backups of the codebase and of the database, so you can restore them, for example on a fresh installation. This is very useful if your system has been compromised, and you want to restore it. 

Environment

Securing the infrastructure, in which the system is hosted, is as important as securing Drupal itself. Try always to mitigate attacks before they happen. This module list is supposed to help you with that purpose. 

  1. Use a coding workflow - making sure that the best code ends at the production environment. 
  2. Make a very detailed analysis of the logs - there are very useful tools for this matter, like Splunk or the ELK stack.
  3. If it is possible, try to use cloud-based environments - these are more secure than hosted environments. 
  4. Try to use CDNs every time you can - this acts as a firewall preventing malicious attacks early in the process.
  5. Make sure you have an up-to-date failover environment and test what would happen in case of a failover. 

Please, leave us your comments and questions below.  Thanks for reading!


About the author

Jorge lived in Ecuador and Germany. Now he is back to his homeland Colombia. He spends his time translating from English and German to Spanish. He enjoys playing with Drupal and other Open Source Content Management Systems and technologies.
Sep 11 2019
Sep 11

Portland, OR - The Drupal Association, an international nonprofit organization, welcomes its newly appointed board members to help advance its mission to unite a global open source community to build, secure, and promote Drupal. The Association’s Board of Directors ratified the appointment of five new board members in September, including: Grace Francisco, Lo Li, Owen Lansbury, Ryan Szrama and Leslie Glynn, who was elected for the community-at-large seat.

“We are excited to have these amazing individuals join us in our efforts to broaden our reach into diverse communities and to grow Drupal adoption. They bring a wide range of experiences and expertise to the Association that will enhance our opportunities to reach new audiences, support the Drupal community and elevate the Drupal project around the world,” said Adam Goodman, Drupal Association Board Chair. “We welcome Grace’s significant work in developer relations, developer marketing and program management; Leslie’s experience as a developer and project manager long emphasized by her years of contributions as a Drupal community member; Owen’s creative problem-solving, local Drupal association and DrupalCamp experience and business leadership skills; Lo’s extensive work in content management, brand promotion and tech platforms alongside her advocacy for women in technology; and Ryan’s product and service development and business skills coupled with his strong relationships in the Drupal community. We look forward to working with all of our new board members to achieve the Association’s strategic goals.”

grace's headshot photoGrace Francisco joined MongoDB in July as Vice President, Worldwide Developer Relations. Prior to that, she served as Vice President of Developer Relations and Education at gaming platform Roblox where she doubled the size of active developers to 2+ million. A seasoned developer relations leader with over 20 years of experience in software, she has co-authored three patents and led worldwide developer initiatives at Microsoft, Intuit, Yodlee and Atlassian. Francisco graduated cum laude and holds a BBA in Business Management from Golden Gate University.

“I am super excited to join the Drupal Association board,” said Francisco. “I first encountered the Drupal project back in 2010 while I was at Microsoft doing outreach to open source projects - building bridges to open source communities. It’s wonderful now, almost a decade later, to help from the other side to build bridges from Drupal to other tech organizations to broaden Drupal’s adoption.”

leslieg's headshot photoLeslie Glynn has more than thirty years of experience in the tech field as a software developer and project manager. She has been a freelance Drupal Project Manager and Site Builder since 2012. Glynn is very active in the Drupal community as an event organizer (Design 4 Drupal, Boston and NEDCamp), sprint organizer, mentor, trainer and volunteer. She is the winner of the 2019 Aaron Winborn Award. This annual award recognizes an individual who demonstrates personal integrity, kindness, and above-and-beyond commitment to the Drupal community.

“Being a volunteer at numerous Drupal camps and DrupalCons has given me the opportunity to meet and learn from many diverse members of the Drupal community,” said Glynn. “I hope to bring that knowledge and experience to my work on Drupal Association initiatives. One of the things I would like to help with is growing Drupal adoption through new initiatives that reach out to underrepresented and diverse groups through an increased presence at secondary schools and universities and to groups, such as Girls Who Code, in the tech space.”

owen's headshot photoOwen Lansbury is co-founder of PreviousNext, an independent Australian digital design and development company that has been one of the world's most prolific code contributors to the Drupal project. With 25 years’ professional experience and a background in Fine Art, Digital Media and User Experience Design, Lansbury blends creative problem solving with the business skills required to sustain his own company and work successfully with complex customers. He is also an active leader within the Australian and New Zealand Drupal community, bringing DrupalCon to Sydney in 2013, acting as Track Chair at several regional events and chairing the DrupalSouth Steering Committee.

Lansbury said, “As a long-term Drupal community contributor in Australia and New Zealand, I'm excited about the opportunity to bring my grassroots experience to the Association board at a global level. I've always been a bit jealous of our developers contributing code to Drupal, so being able to contribute my own business and community leadership experience to the Association board is a great opportunity for me to give something back at a global level."

lo's headshot photoLo Li is the Senior Vice President, CIO of Global Consumer Solutions at Equifax. She has spent the past two decades leading global multi-billion dollar corporations for some of the world’s most renowned hospitality and retail brands in the world, working with hundreds of teams dispersed in the UK, China, Singapore and India. Some of her work includes the creation for dynamic pricing and predictive analytics engines for global hotels; and scaling big data and Agile to enable business transformation at large retailers including double digit growth plans for digital and international presence. She brings a deep understanding of how to translate corporate visions and strategies into simple, elegant solutions - using her international business acumen and technology background as both a business enabler and a competitive differentiator. Li, who is multilingual - fluent in Mandarin, Portuguese, Spanish and English - is the recipient of several industry accolades and serves on the Board of Directors for several national nonprofit organizations. She received her Bachelor’s and Master’s degree from the University of Georgia.

Li said, “I am thrilled to join the Drupal Association board because of the incredible open source community that has been fostered. The nurturing and growth of communities, like the one we have at Drupal, are the very catalyst to help organizations leap forward and provide an incubator for new ideas and thought leadership amongst digital citizens. It's truly an honor to be able to help shape the future of such a great organization!”

ryan's headshot photoRyan Szrama co-founded Commerce Guys in 2009 to offer Drupal-based eCommerce consulting and development services. He was the project lead of Drupal’s most popular eCommerce framework, Drupal Commerce, from its creation to its eventual use on over 60,000 websites. In 2016, Ryan acquired control of Commerce Guys from his partners, leading the company to rebrand to Centarro and launch new product and support offerings that enable teams to build with confidence on Drupal Commerce.

"My personal goals align perfectly with the mission of the Drupal Association: uniting a global open source community to build Drupal,” said Szrama. “I've been privileged to build a career in this community as a long-time contributor turned business owner, and I'm continually inspired by the members of this board to think bigger and give back more. I hope to apply my knowledge and experience to board initiatives that empower more people to better themselves and their organizations by using and contributing to Drupal."

The newly-elected members will join the following Association board members, continuing their service in the upcoming term: 

  • Baddý Sonja Breidert, 1xINTERNET

  • Dries Buytaert, Acquia

  • Luma Dahlbacka, Charles Schwab & Co

  • Suzanne Dergacheva, Evolving Web

  • Adam Goodman, Northwestern University’s Center for Leadership

  • Mike Lamb, Pfizer

  • Audra Martin-Merrick, Red Backpack Limited

  • George Matthes, Johnson & Johnson

  • Vishal Mehrotra, Tata Consultancy Services

  • Ingo Rübet, BOTLabs GmbH

  • Michel van Velde, One Shoe

About Drupal

Drupal is one of the leading content management software platforms that has been used to create millions of websites around the world. There are 46,000 plus developers with 1.3 million users on Drupal.org, and Drupal has the largest open source community in the world. Drupal has great standard features, easy content authoring, reliable performance and excellent security. What sets it apart is its flexibility; modularity is one of its core principles. Its tools help you build the versatile, structured content that ambitious web experiences need.

About Drupal Association

The Drupal Association is an international non-profit organization that engages a broad audience about Drupal, the leading CMS open source project. The Association promotes  Drupal adoption through the work and initiatives of a worldwide community of dedicated contributors, and support from individual and organizational members. The Drupal Association helps the Drupal community with funding, infrastructure, education, promotion, distribution and online collaboration. For more information, visit Drupal.org.

###

Sep 09 2019
Sep 09

Some different modules and plugins can alter the display of a view in Drupal, for instance, to alternate the order of image and text every new row, or to build some kind of stacked layout. 

It is possible to alter the display of a view with just some lines of CSS code instead. This approach has many advantages, being the fact of not having to install and update a module, the most relevant one.

Keep reading to learn how!

Step #1. - The Proposed Layout

190828 theming views

As you can notice, we can divide the layout into six columns and five rows. There are empty cells in the grid, whereas other cells contain one item of the view across many cells (grid area). The Drupal view shows a list of articles and their titles. The view format is unformatted list.

Step #2. - Create an Image Style

To ensure that all images are squared, it is necessary to configure an image style and set it as display style in the view.

  • Click Configuration > Image styles
    190828 theming views 001
  • Click Add image style
    190828 theming views 002
  • Give the new image style a proper name, for example, Crop 600x600.

It is always a good idea to include some reference about the dimension or the proportion of the image style. That helps when having multiple image styles configured.

  • Click Create new style
  • Select Crop from the dropdown
  • Click Add
    190828 theming views 003
  • Set height and width for the crop effect (make sure both dimensions are equal)
  • Leave the default crop anchor at the center of the image
  • Click Add effect
    190828 theming views 004
  • Make sure the image effect was recorded properly and click Save
    190828 theming views 005

Step #3. - Create the View

You can read more about rewriting results in Views here.

  • Save the view
  • Click Structure > Block layout
  • Scroll down to the Content section
  • Click Place block
    190828 theming views 013
  • Search for your block
  • Click Place block
  • Uncheck Display title
  • Click Save block
    190828 theming views 014
  • Drag the cross handle and place the block above the Main content
  • Scroll down and click Save blocks

Step #4. - Theming the View

There are 3 classes you need to target to apply the layout styles to the view:

  • .gallery-item  (each content card will be a grid)

  • #block-views-block-front-gallery-block-1 .view-content

  • #block-views-block-front-gallery-block-1 .view-row

We set the specificity of the CSS styles on the block. The classes .view-content and .view-row are default Views classes. Theming only with these would break the layout of other views on the site, for example, the teaser view on the front page.

Hint: I am working on a local development environment with a subtheme of Bartik. There is much more about Drupal theming at OSTraining here.
If you don’t know how to create a subtheme in Drupal yet, and you are working on a sandbox installation, just add the code at the end of the file and please remember always to clear the cache.

/core/themes/bartik/css/layout.css 

Let’s start with the content inside the .gallery-item container. It will be a grid with one column and 4 rows. The image will cover all 4 rows, whereas the title text will be located on the last row. To center the title on its cell, we declare the link tag as a grid container too.

  • Edit the CSS code:
.gallery-item {
    display: grid;
    grid-template-rows: repeat(4, 1fr);
}
 
.gallery-item a:first-of-type {
    grid-row: 1 / span 4;
    grid-column: 1;
}
 
.gallery-item a:last-of-type {
   grid-row: 4;
   grid-column: 1;
   display: grid; /* Acting as a grid container */
   align-content: center;
   justify-content: center;
   background-color: rgba(112, 97, 97, 0.5);
   color: white;
   font-size: 1.2em;
}

 Make the images responsive.

  • Edit the CSS code:
img {
   display: block;
   max-width: 100%;
   height: auto;
}

As already stated, we need a grid with 5 rows and 6 columns. After declaring it, map every position in the grid according to the layout with an area name. The empty cells/areas will be represented with a period. 

  • Edit the CSS code:
#block-views-block-front-gallery-block-1 .view-content {
 display: grid;
 grid-template-columns: repeat(6, 1fr);
 grid-template-rows: repeat(5, 1fr);
 grid-gap: 0.75em;
 grid-template-areas:
 ". thumb1 main main main thumb2"
 ". thumb3 main main main thumb4"
 ". thumb5 main main main thumb6"
 "secondary secondary thumb7 thumb8 thumb9 ."
 "secondary secondary . . . .";
 max-width: 70vw;
 margin: 0 auto;
}

Now it’s time to assign each grid item to its corresponding region.

  • Edit the CSS code:
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(1) {
   grid-area: main;
}
 
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(2) {
   grid-area: secondary;
}
 
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(3) {
   grid-area: thumb1;
}
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(4) {
   grid-area: thumb3;
}
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(5) {
   grid-area: thumb5;
}
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(6) {
   grid-area: thumb2;
}
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(7) {
   grid-area: thumb4;
}
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(8) {
   grid-area: thumb6;
}
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(9) {
   grid-area: thumb7;
}
 
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(10) {
   grid-area: thumb8;
}
#block-views-block-front-gallery-block-1 .view-content > .views-row:nth-of-type(11) {
   grid-area: thumb9;
}

I think this is a practical way to layout Views items the way you want without the need of installing extra modules, which could unnecessarily affect the performance of your site. 

The Media Queries

The layout will break at around 970px, because of the font size. 

  • Edit the CSS code:
@media screen and (max-width: 970px) {
 .views-row > div .gallery-item > a:nth-child(2) {
   font-size: .9em;
 }
}

To change the layout, just add a media query with a new grid-template-areas distribution, and of course, we have to change the way the rows and columns are distributed The items are already assigned to their respective areas.

  • Edit the CSS code:
@media screen and (max-width: 700px) {
 .view-content {
   grid-template-columns: repeat(2, 1fr);
   grid-template-rows: repeat(10, auto);
   grid-template-areas:
     "main main"
     "main main"
     "thumb1 thumb2"
     "thumb3 thumb4"
     "secondary secondary"
     "secondary secondary"
     "thumb5 thumb6"
     "thumb7 thumb8"
     "thumb9 thumb9"
     "thumb9 thumb9";
 }
}

This layout will work even with the smallest device screen.

I hope you liked this tutorial. Thanks for reading!


About the author

Jorge lived in Ecuador and Germany. Now he is back to his homeland Colombia. He spends his time translating from English and German to Spanish. He enjoys playing with Drupal and other Open Source Content Management Systems and technologies.
Aug 30 2019
Aug 30

For over a decade* the Drupal community has gathered in volunteer-led “camps”, based on the BarCamp model, to follow in that camp’s initial goals:

  • Introduce web developers to the Drupal platform.
  • Skill sharing among established Drupal developers
  • Give back to the Drupal project (e.g. fix bugs, documentation, lesson materials)

The scope of Drupal Camps has expanded as our community has grown and matured, and camps now serve everyone in the community, not just developers. They serve as an on-ramp for new developers, a networking opportunity for clients and agencies, a marketing opportunity for service providers, and much more.

The Drupal Event Organizers have documentation of over 50 volunteer-led events with over 10,000 attendees worldwide in the past year, and we know there are almost double this number that we don’t have good data for. These events have evolved organically, with little central organization, and are estimated to comprise more than one million dollars in sponsorship and ticket sales worldwide, yearly.

The Event Organizers have organized in various forms over that time… from various documentation efforts to our current monthly meeting format. With Kaleem’s instigation, the group started toward a more formal organization in late 2018, and that process is almost a reality. 

We’ve established a formation board composed of organizers from across the globe and have been collaborating on a charter for the Event Organizers Working Group over the past few months. We’re looking forward to presenting it soon and beginning the next chapter of the Drupal Event Organizers.

Thanks to the following folks who have contributed to the effort thus far.

Our Formation Board members:

And our trusted advisers:

Possibly starting at Drupal Camp Toronto, 2006? If you know of an earlier camp, please let us know in the comments.

Aug 12 2019
Aug 12
Why is my entity untranslatable? Unifex Tue, 08/13/2019 - 11:49

Drupal has pretty good multilingual support out of the box. It's also fairly easy to create new entities and just add translation support through the annotation. These things are well documented elsewhere and a quick search will reveal how to do that. That is not what this post is about. This post is about the UX around selecting which fields are translatable.

On the Content Language page at http://example.com/admin/config/regional/content-language you can select which fields on your nodes, entities and various other translatable elements will be available on non-default language edit pages. The section at the top is the list of types of translatable things. Checking these boxen will reveal the related section. You can then go down to that section and start selecting fields to translate, save the form and they become available. All nice and easy.

I came into the current project late and this is my first exposure to this area of Drupal. We have a few content types and a lot of entities. I was ticking the box for the entity I wanted to add, jumping to the end of the form and saving it. When the form came back though it was not selected. I could not figure out why. It wasn't until a co-worker used the form differently to me that the issue was resolved. Greg ticked the entity, scrolled down the page and found it, ticked some of the checkboxen in the entity itself and then saved the page. The checkbox was still ticked.

The UX on this pretty good once you know how it works. It could be fixed fairly easy with a system message pointing out that your checkbox was not saved because none of the items it exposed were selected.

I feel a patch coming on…

Drupal 8 Planet Drupal
Aug 12 2019
Aug 12

Banner graphic with the names of lots of languages

I'm delighted to report that much progress has been made since my last post about Pitch Deck Internationalisation just 2 weeks ago. Because of this we are moving to the next phase, translation itself.

Teams at CTI Digital and Lingotek are nearing completion of environments allowing translators to work on multilingual Drupal Pitch Deck content.

From early September we will open these tools for community volunteers to participate in a Global Translation Sprint. Right now we are calling for linguists within the community to make themselves known.

Screenshot of the pitch deck, looking at a slide about UX Magazine

What are we looking for?

Do you have a few hours available in September to participate in the Translation Sprint? We’d love to hear from you via this form before 26th August.

What will I be doing?

  1. Attend a 30 minute webcast to understand how to translate in Lingotek
  2. To be effective we are looking for translators who have available a number of hours during September at their convenience
  3. All translation can be completed remotely and iteratively from the convenience of your home or office (remote)
  4. You will be translating Case Study slides such as the one shown below
  5. We will issue you with specific tasks based on your indicated time availability

Not only will you be contributing to a key strategic initiative of the Drupal project, all participants will be acknowledged via contribution credits. This is an ideal opportunity to contribute to Drupal without code.

Volunteer now!

Please provide your details via this form before 26th August to be eligible to participate. And thank you!

Got questions?

If you have any questions please contact Paul Johnson.

Jul 31 2019
Jul 31

Approaching 20 years old, the Drupal Community must prioritize recruiting the next generation of Drupal Professionals

Kaleem ClarksonFerris Wheel in Centennial Olympic Park in Atlanta, Georgia

Time flies when you are having fun. One of those phrases I remember my parents saying that turned out to be quite true. My first Drupal experience was nearly 10 years ago and within a blink of an eye, we have seen enormous organizations adopt and commit to Drupal such as Turner, the Weather Channel, The Grammys, and Georgia.gov.

Throughout the years, I have been very fortunate to meet a lot of Drupal community members in person but one thing I have noticed lately is that nearly everyone’s usernames can be anywhere between 10–15 years old. What does that mean? As my dad would say, it means we are getting O — L — D, old.

For any thriving community, family business, organization, or your even favorite band for that matter, all of these entities must think about succession planning. What is succession planning?

Succession planning is a process for identifying and developing new leaders who can replace old leaders when they leave, retire or die. -Wikipedia

That’s right, we need to start planning a process for identifying who can take over in leadership roles that continue to push Drupal forward. If we intend to promote Drupal as the solution for large and small enterprises, then we should market ourselves as a viable career option to lure talent to our community.

There are many different way’s to promote our community and develop new leaders, one of which is mentorship. Mentorship helps ease the barrier for entry into our community by providing guidance around how our community operates. The Drupal community does have some great efforts taking place in the form of mentoring such as Drupal Diversity & Inclusion (DDI) initiative, the core mentoring initiative and of course the code and mentoring sprints at DrupalCon and DrupalCamps. These efforts are awesome and should be recognized as part of a larger strategic initiative to recruit the next generation of Drupal professionals.

Companies spend billions of dollars a year in recruiting but as an open-source community, we don’t have billions so

… what else can we do to attract new Drupal career professionals?

This year’s Atlanta Drupal Users’s Group (ADUG) decided to develop the Drupal Career Summit, all in an effort to recruit more professionals into the Drupal community. Participants will explore career opportunities, career development, and how open source solutions are changing the way we buy, build, and use technology.

  • Learn about job opportunities and training.
  • Hear how local leaders progressed through their careers and the change open source creates their clients and business.
  • Connect one-on-one with professionals in the career you want and learn about their progression, opportunities, challenges, and wins.

On Saturday, September 14 from 1pm -4:30pm. Hilton Garden Inn Atlanta-Buckhead 3342 Peachtree Rd., NE | Atlanta, GA 30326 | LEARN MORE

Student and job seekers can attend for FREE! The Summit will allow you to meet with potential employers and industry leaders. We’ll begin the summit with a panel of marketers, developers, designers, and managers that have extensive experience in the tech industry, and more specifically, the Drupal community. You’ll get a chance to learn about career opportunities and connect with peers with similar interests.

We’re looking for companies that want to hire and educate. You can get involved with the summit by becoming a sponsor for DrupalCamp Atlanta. Sponsors of the event will have the opportunity to engage with potential candidates through sponsored discussion tables and branded booths. With your sponsorship, you’ll get a booth, a discussion table, and 2 passes! At your booth, you’ll get plenty of foot traffic and a fantastic chance to network with attendees.

If you can’t physically attend our first Career Summit, you can still donate to our fundraising goals. And if you are not in the position to donate invite your employer, friends, and colleagues to participate. Drupal Career Summit.

Jul 25 2019
Jul 25

Recently, a dedicated group of volunteers launched the first version of a Drupal pitch deck. It features case studies of Drupal success stories from around the globe, grouped by use case. And slides about the benefits and key differentiators, to help decision makers answer the question “Why should we use Drupal?” It pulls from some of the content of the Drupal promo video presented at DrupalCon Seattle.

The goal is to have marketing materials that agencies can use to pitch Drupal. But I’ve also used materials from this deck to put together slides at Drupal events (picking out university case studies for a higher ed summit, and presenting the opening slides to kick off a Drupal summit).

International participation is part of the Drupal’s Values & Principles, and part of the success of this pitch deck project will be its use around the globe. To achieve that, we want to make as much of the material available in as many languages as possible. And that’s where we need help. Not just from volunteers who want to localize the material into different languages. But also from volunteers who want to set up a system that will allow us to create the translations. Our goal is to maintain the slide deck content in a sustainable way, that promotes contribution and permits translation into multiple languages.

We’ve put together some ideas for a system that would use a Drupal website to manage the versioned content and translations for the slides. Lingotek, a cloud-based translation services provider, has generously provided a free instance of their translation management tool to facilitate translation at scale by volunteers, and to generate slide decks on the front-end we are planning to explore existing frameworks like Reveal.js, together with Views. Here are some details of the proposal and a diagram of what this could look like.

CTA

translation process diagram

We (the pitch deck team: Paul Johnson, Suzanne Dergacheva, and Ricardo Amaro) are open to ideas about how to do this and what the architecture should be. We want to make sure that the solution is inclusive, accessible, and easy to maintain. We are also looking for volunteers to help implement this. The above plan would require Drupal site building and front-end development work. And, eventually, translations.

Here’s a link to the idea on Drupal.org. If you’re interested in getting involved, you can jump in and comment on the issue, reach out to us individually, or jump into the #promotedrupal channel on Drupal Slack or join our regular promote Drupal meetings.

Jul 25 2019
Jul 25

Submitted by karthikkumardk on Thursday, 25 July 2019 - 15:29:44 IST

file_scan_directory is deprecated and has been moved to the file_system service.

Before:

$files = file_scan_directory($directory);

After

if (is_dir($directory)) {
  $files = \Drupal::service('file_system')->scanDirectory($directory);
}

When possible, you should inject the FileSystemInterface into your constructor.

Original source - https://www.drupal.org/node/3038437

Jul 23 2019
Jul 23

Here at Phase2, we’re excited to participate in the premiere Drupal government event, Drupal GovCon, held at the National Institutes of Health campus in Bethesda, Maryland where we'll once again be a platinum sponsor.

We hope you will join us for one of North America’s largest Drupal camps, this week.  

You can find Phase2 at our sponsor booth and all over the session schedule:

Why Migrate To Drupal 8 Now

With Drupal 9’s release impending, there has been a resurgence of chatter around Drupal 6/7 migration. If your government organization is still on Drupal 6 or 7 you will won’t want to miss this session. You can read more about the subject here from our on-site presenters, Tobby Hagler, Director of Engineering, and Felicia Haynes, Vice President of Accounts.

Measuring What Matters: Using Analytics To Inform Content Strategy

Content Strategy is the backbone to any successful digital experience. It’s also rarely considered an analytical process, but it should be! Catch our session to learn more, and in the meantime, read about the top 3 content strategy tips for government ahead of Jason Hamrick’s session.

Accessible Design: Empathy In A World With No Average

Our Accessibility expert, Catharine McNally, has a special treat for her session’s attendees: she’ll be hosting some interactive empathy building exercises, to showcase the impact of accessible design for citizens. This is a unique opportunity for anyone involved in the design, content, and UX of their organization’s/agency’s digital experience.

Personalization & Government: The Odd Couple or The Perfect Match?

Personalization has become the new standard, across industries, for improving customer experience, but how can personalization be leveraged in government? Join our CEO, Jeff Walpole, and Vice President of Business Development, Ben Coit,  to explore use cases and how governments can continue thinking about the next generation of citizen experiences.

Read more about scaling personalization in our recent whitepaper

Jul 19 2019
Jul 19

Redis is an open-source, networked, in-memory, key-value data store that can be used as a drop-in caching backend for your Drupal

Add the Redis module from Drupal.org. You can install and enable the module from the command line.

Edit sites/default/settings.php to add the Redis cache configuration. These are the mandatory, required Redis configurations for every site.

// Use Redis for caching.
$conf['redis_client_interface'] = 'PhpRedis';
// Point Drupal to the location of the Redis plugin.
$conf['cache_backends'][] = 'sites/all/modules/redis/redis.autoload.inc';
$conf['cache_default_class'] = 'Redis_CacheCompressed';
$conf['cache_prefix'] = array('default' => 'pantheon-redis');
// Do not use Redis for cache_form (no performance difference).
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
// Use Redis for Drupal locks (semaphore).
$conf['lock_inc'] = 'sites/all/modules/redis/redis.lock.inc';

Enable the module via from /admin/modules

Verify Redis is enabled by going to the Dashboard and clicking "Connection Info". If you see the Redis cache connection string, Redis is enabled

Visit /admin/config/development/performance/redis and open Connection Information to verify the connection.

And once the Redis server is connected, one could use the PhpRedis functions to set the key & value pairs on Redis as seen below

function _get_value_redis_cache($key) {
    try {
        $redis = Redis_Client::getClient();
        return $redis->get($key);
    }
    catch (Exception $exception) {
        watchdog('redis_cache', t('Error, while getting the value from redis cache.'), custom_log(array($key, $redis)), WATCHDOG_ERROR);
    }
}

function _set_value_redis_cache($key, $value) {
    try {
        $redis = Redis_Client::getClient();
        $redis->set($key, $value);
        $now = time();
        $redis->expireAt($key, $now + 900);
        $redis->save();
    }
    catch (Exception $exception) {
        watchdog('redis_cache', t('Error, while setting the value from redis cache.'), custom_log(array($key, $value, $redis)), WATCHDOG_ERROR);
    }
}

Once these generic functions are ready, one could utlize this functions for setting and getting the values based on the keys as seen below

$key = "_get_tmp_value_from_redis";
$tmp = _get_value_redis_cache($key);
if (empty($tmp)) {
    $tmp = get_actual_value_from_db();
    _set_value_redis_cache($key, $tmp);
    return $tmp;
}
else {
    return $tmp;
}

cheers :)

Jul 17 2019
Jul 17

The Migrate Drupal UI module provides a web browser user interface for upgrading from Drupal 6 / 7 to Drupal 8. There is a pre-upgrade analysis which displays a list of legacy modules that will be upgraded and will not be upgraded. Included in those that will be upgraded are modules that do not need an upgrade, such as the Help module. In order for this analysis to be correct, some Drupal 8 modules must provide information in a MODULE_NAME.migrate_drupal.yml file in the module's migrations/state directory.

This applies to Drupal 8 modules that:

  • Provide migrations from a Drupal 6 or Drupal 7 module, or
  • Intend to provide those migrations in the future, or
  • Are a successor to a Drupal 6 or Drupal 7 module and want to communicate that no migration is needed.

This does not apply to modules that are brand new in Drupal 8 and have nothing to communicate about any Drupal 6 or Drupal 7 modules.

Syntax

finished:
  6:
    source_module: destination_module
    source_module_2: destination_module
    source_module_3:
    - destination_module
    - destination_module_2

  7:
    source_module: destination_module
    source_module_3:
    - destination_module
    - destination_module_2

not_finished:
  7:
    source_module_2: destination_module

As can be seen above, the data in migrations/state/MODULE_NAME.migrate_drupal.yml consists of migration sets where each set is a source module for a legacy Drupal version (6 or 7), and one or more destination modules for the current Drupal version (8). The source module and destination modules correspond to the source_module and destination_module definitions in the migrations. And each set can be declared either 'finished' or 'not_finished'. For a set to be "finished", all of the migrations for the set must exist. If a module maintainer knows that they have not yet provided all of the migrations that are needed from a given source module to one or more destination modules, then they should declare that set as "not_finished".

Merging state across provider modules, source modules, and destination modules

Each module's migrations/state/MODULE_NAME.migrate_drupal.yml file defines the state of the migrations that are provided (or intended to be provided in the future) by that module. In most cases, destination modules are the sole providers of migrations to themselves. For example, the dblog module is the sole module that provides migrations from earlier versions of itself to itself. In some cases, modules provide migrations for other destination modules. For example, the Content Translation module provides migrations from earlier versions of the Statistics module to the current version of the Statistics module. This is in addition to the migrations provided by the Statistics module itself.

The Migrate Drupal module considers a source module / destination module pair as not finished if there is any provider that declares it as not finished. For example, in the above example, if the Content Translation module in its .migrate_drupal.yml were to declare that statistics: statistics were "not_finished", then Migrate Drupal considers that pair to be not finished, even if the Statistics module itself is finished with the migrations that it intends to provide.

Similarly, a given source module is considered not finished overall, if there exists at least one destination module for which it is declared as not finished. For example, there are migrations from the Drupal 6/7 Menu module to several Drupal 8 destination modules (System, Menu UI, and Custom Menu Links). If any one of those pairs (e.g., menu: system, menu: menu_ui, or menu: menu_link_content) were declared as not finished (by any provider module), then on the Migrate Drupal UI pre-upgrade review screen, the Menu module would be listed as "will not be upgraded".

Usage

If the Drupal 8 module is not providing migrations, now or in the future, for its legacy version then create a migrate_drupal.yml. Declare a finished migration for each legacy Drupal version. See scenario 1 below.

If the Drupal 8 module is or will be providing migrations for a legacy module then create a migrate_drupal.yml file. For each source_module:destination_module pair used by the migrations in your module do the following for Drupal 6 and Drupal 7.

  • If the migrations for the pair are complete add a line in the "finished" array for the relevant Drupal version.
  • If at least one migration for a pair exists but the pair is not finished add an entry to "not_finished" for the relevant Drupal version.
  • If the migrations needed for the pair do not exist then add a line in the "not_finished" array for the relevant Drupal versions.

Examples

Scenario 1. A successor to a legacy module that for any reason will not be providing a migration. Let's use Pirate as the example. Currently, if Pirate is enabled on the legacy site it will be displayed as will not be upgraded when it should be listed as will be upgraded. To make that happen simply declare a migration set with pirate as the source module and destination module as finished.

finished:
  6:
     pirate: pirate
  7:
     pirate: pirate

Scenario 2. The legacy version of your module has content and configuration that needs to be upgraded. Your module provides two migrations with the same source_module:destination_module pair for both Drupal 6 and Drupal 7 and all migrations are finished.

finished:
   6:
     google_analytics: google_analytics
   7:
     google_analytics: google_analytics

Scenario 3. Your module provides migrations. The Drupal 6 version is complete but the Drupal 7 is not. Note there may be zero or more migrations for Drupal 7 in your module but more are needed for it to be complete.

 finished:
    6:
      google_analytics: google_analytics
  not_finished:
    7:
      google_analytics: google_analytics

Scenario 4. Your module provides migrations for other modules with many pairs, such as Commerce Migrate Module.

finished:
    6:
      node: commerce_product
      system: commerce_store
    7:
      node: commerce_product
      commerce_product: commerce_product
      system: commerce_store
  not_finished:
    6:
      uc_orders: commerce_order
    7:
      uc_orders: commerce_order
      commerce_order: commerce_order

Scenario 5. Your module provides a migrate field plugin for a legacy field, such as Address Module.

  finished:
    6:
      adressfield: address
    7:
      adressfield: address

Scenario 6. Menu, JQuery UI, Blog, Color and many other modules moved directly into Core. These are denoted as 'core' for the destination and are treated specially. They are marked as finished since these do not have an upgrade path and site upgraders do not need to look for an equivalent project to install in Drupal 8.

finished:
  6:
    blog: core
    blogapi: core
    calendarsignup: core
    color: color
  7:
    blog: core
    bulk_export: core
    contextual: core
    ctools: core

Cheers :)

Jul 11 2019
Jul 11

On September 12–14, at Hilton Garden Inn Atlanta-Buckhead

Kaleem ClarksonKyle Mathews, 2019 DrupalCamp Atlanta Keynote

Trainings

Jul 08 2019
Jul 08

For the past three years, developers, IT, and marketing professionals have gathered in NYC for “Decoupled Days, a growing but impactful event with influential speakers and change agents from across the tech space, to share and learn about decoupled architecture solutions for some of the world’s leading brands and organizations.

While the topic of decoupled architecture solutions may seem hyper-specific for a two-day conference, there is an aggressively (growing) interest and investment in decoupled architecture strategies across industries, all to enable the digital brand experiences they require to stay competitive.

Decoupling the front end of an organization’s platform from their back end allows for more flexible design capabilities and the ability to update the design much faster at the speed that marketing teams need to move. When the back end of your website is decoupled, you can easily integrate and swap micro-services in and out to provide the latest and most useful tools and functionality without a complete site redesign.  

Here at Phase2, we work with many of our enterprise clients on decoupling their digital architectures to meet their brand experience goals. We’re thrilled to participate in the organization, sponsorship, and thought leadership of this event. If you plan to attend this year’s event, (and we think you should!), be sure to check out some of Phase2’s front-end leaders as they share best practices and cutting-edge tooling in the following sessions:

We hope you’ll join us July 17th-18th in NYC to learn more about business, technology, and diversity when it comes to decoupled architectures for seamless omnichannel brand experiences that inspire audiences.

Jul 01 2019
Jul 01

If you are running an old version of Drupal 8, it is likely that your site can be compromised by the known vulnerabilities. And to guard your site against possible hacks, you should update Drupal core to latest stable release in 8.x branch.

Drupal 8 Update | Joshi Consultancy Services

Updating Drupal 8 core

There are two ways to update Drupal 8 core:

1. Manually

2. Using composer

Below, we will learn how to use these methods to update Drupal 8 core.

1. Manually updating Drupal 8 core

If you are not using or managing your Drupal 8 website using composer, here are the steps to update your Drupal 8 core:

  • Tack backup of your site, both codebase and the Database. Download latest release of Drupal 8 core.
  • Copy all the files and directories from downloaded version except 'sites' and 'modules'. We assume you did not make changes to any core modules or themes. If you need to, take a backup of .htaccess and 'profiles' directory as well.
  • Overwrite your site codebase with copied files and directories.
  • Restore all the files that you previously modified.
  • Perform DB update and composer update.
  • At this stage, do not perform an update to contrib modules. Contrib module updates are not consistent and you can not rely on them to be act so. This is very efficient method when you did not alter any core or contrib module/theme files.

2. Using Composer

You can also update your Drupal 8 website using composer. This is most convenient way to update Drupal 8 website. You must have SSH access to sever in order to carry out the composer commands and update Drupal 8 core.

  • Execute composer update
  • Once done, execute drush updb
  • For consistency and to make sure everything is in order, execute drush cr

Congratulations! You have just updated your Drupal 8 website!!

Jun 23 2019
Jun 23
Starting a new Drupal 8 project? And the first thing you might do is to install a module, but which one first. There are a few obvious ones to install and sometimes these have no relation with the functionality of your project but they always help you in the background.
Jun 19 2019
Jun 19

(Available as freelancer)

Joris Snoek

Business Consultant
/ Drupal Developer

Last month we worked in a project where we implemented a progressively decoupled Drupal platform. We needed a React.js frontend to to all kind of magic that was less available in Twig. Also, this way frontend engineers and backend engineers could work more loosely together, which is great.

Main reason we choose progressive decoupled instead of fully decoupled is because we wanted to make use of Drupal's roles, permissions and authentication, plus some other Drupal native stuff that in fully headless would become very cumbersome to deal with.

Check out this blog on 'How to decouple Drupal in 2019' and find out if you also need Drupal beheading or not.

React libraries dynamically in Drupal

The target was to implement the React.js libraries in Drupal pages, so React would load withín Drupal and we could use all native Drupal goodies like authentication.

By the way: you can also use Drupal authentication when fully decoupled, check this article

So, the thing with React is: every time you release a new version of your App, you'll have to render a new build, that sort of looks like this:

More specifically, the .js and .css files we need to load in Drupal are defined in asset-manifest.json:

So, those files need to be loaded in Drupal, and change every time you run a new build in your React App for example with npm run build.

But you can't add these React javascript libraries to your theme's YOURTHEME.libraries.yml because with the next build the links be be different.

hook_library_info_build() to the rescue

Aaaah, so Drupal 8 provides us with hook_library_info_build() that will save our day (づ。◕‿‿◕。)づ

Now, how we did this:

Implement the Drupal hook in your .module file (For highlighting's sake, I added .php, loose that. #nobrainer):

As you see, it will read React's asset-manifest.json and registers all .js and .css files of React.js as a library in Drupal.

Next up, you can render this library for example in a Controller like this:

Wrap up

So that's how we integrated React.js within Drupal pages and combined the power of a React frontend with the power of Drupal goodies, in a 'progressively decoupled' way.

Please let me know if you have any questions.

Jun 12 2019
Jun 12

Some years ago, a frontend developer colleague mentioned that we should introduce SASS, as it requires almost no preparation to start using it. Then as we progress, we could use more and more of it. He proved to be right. A couple of months ago, our CTO, Amitai made a similar move. He suggested to use ddev as part of rebuilding our starter kit for a Drupal 8 project. I had the same feeling, even though I did not know all the details about the tool. But it felt right introducing it and it was quickly evident that it would be beneficial.

Here’s the story of our affair with it.

For You

After the installation, a friendly command-line wizard (ddev config) asks you a few questions:

The configuration wizard holds your hand

It gives you an almost a perfect configuration, and in the .ddev directory, you can overview the YAML files. In .ddev/config.yaml, pay attention to router_http_port and router_https_port, these ports should be free, but the default port numbers are almost certainly occupied by local Nginx or Apache on your development system already.

After the configuration, ddev start creates the Docker containers you need, nicely pre-configured according to the selection. Even if your site was installed previously, you’ll be faced with the installation process when you try to access the URL as the database inside the container is empty, so you can install there (again) by hand.

You have a site inside ddev, congratulations!

For All of Your Coworkers

So now ddev serves the full stack under your site, but is it ready for teamwork? Not yet.

You probably have your own automation that bootstraps the local development environment (site installation, specific configurations, theme compilation, just to name a few), now it’s time to integrate that into ddev.

The config.yaml provides various directives to hook into the key processes.

A basic Drupal 8 example in our case looks like this:

hooks:
  pre-start:
    - exec-host: "composer install"
  post-start:
    # Install Drupal after start
    - exec: "drush site-install custom_profile -y --db-url=mysql://db:[email protected]/db --account-pass=admin --existing-config"
    - exec: "composer global require drupal/coder:^8.3.1"
    - exec: "composer global require dealerdirect/phpcodesniffer-composer-installer"
  post-import-db:
    # Sanitize email addresses
    - exec: "drush sqlq \"UPDATE users_field_data SET mail = concat(mail, '.test') WHERE uid > 0\""
    # Enable the environment indicator module
    - exec: "drush en -y environment_indicator"
    # Clear the cache, revert the config
    - exec: "drush cr"
    - exec: "drush cim -y"
    - exec: "drush entup -y"
    - exec: "drush cr"
    # Index content
    - exec: "drush search-api:clear"
    - exec: "drush search-api:index"

After the container is up and running, you might like to automate the installation. In some projects, that’s just the dependencies and the site installation, but sometimes you need additional steps, like theme compilation.

In a development team, you will probably have a dev, stage and a live environment that you would like to routinely sync to local to debug and more. In this case, there are integrations with hosting providers, so all you need to do is a ddev pull and a short configuration in .ddev/import.yaml:

provider: pantheon
site: client-project
environment: test

After the files and database are in sync, everything in post-import-db will be applied, so we can drop the existing scripts we had for this purpose.

We still prefer to have a shell script wrapper in front of ddev, so we have even more freedom to tweak the things and keep it automated. Most notably, ./install does a regular ddev start, which results in a fresh installation, but ./install -p saves the time of a full install if you would like to get a copy on a Pantheon environment.

For the Automated Testing

Now that the team is happy with the new tool, they might be faced with some issues, but for us it wasn’t a blocker. The next step is to make sure that the CI also uses the same environment. Before doing that, you should think about whether it’s more important to try to match the production environment or to make Travis really easily debuggable. If you execute realistic, browser-based tests, you might want to go with the first option and leave ddev out of the testing flow; but for us, it was a desirable to spin an identical site on local to what’s inside Travis. And unlike our old custom Docker image, the maintenance of the image is solved.

Here’s our shell script that spins up a Drupal site in Travis:

#!/usr/bin/env bash
set -e

# Load helper functionality.
source ci-scripts/helper_functions.sh

# -------------------------------------------------- #
# Installing ddev dependencies.
# -------------------------------------------------- #
print_message "Install Docker Compose."
sudo rm /usr/local/bin/docker-compose
curl -s -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" > docker-compose
chmod +x docker-compose
sudo mv docker-compose /usr/local/bin

print_message "Upgrade Docker."
sudo apt -q update -y
sudo apt -q install --only-upgrade docker-ce -y

# -------------------------------------------------- #
# Installing ddev.
# -------------------------------------------------- #
print_message "Install ddev."
curl -s -L https://raw.githubusercontent.com/drud/ddev/master/scripts/install_ddev.sh | bash

# -------------------------------------------------- #
# Configuring ddev.
# -------------------------------------------------- #
print_message "Configuring ddev."
mkdir ~/.ddev
cp "$ROOT_DIR/ci-scripts/global_config.yaml" ~/.ddev/

# -------------------------------------------------- #
# Installing Profile.
# -------------------------------------------------- #
print_message "Install Drupal."
ddev auth-pantheon "$PANTHEON_KEY"

cd "$ROOT_DIR"/drupal || exit 1
if [[ -n "$TEST_WEBDRIVERIO" ]];
then
  # As we pull the DB always for WDIO, here we make sure we do not do a fresh
  # install on Travis.
  cp "$ROOT_DIR"/ci-scripts/ddev.config.travis.yaml "$ROOT_DIR"/drupal/.ddev/config.travis.yaml
  # Configures the ddev pull with Pantheon environment data.
  cp "$ROOT_DIR"/ci-scripts/ddev_import.yaml "$ROOT_DIR"/drupal/.ddev/import.yaml
fi
ddev start
check_last_command
if [[ -n "$TEST_WEBDRIVERIO" ]];
then
  ddev pull -y
fi
check_last_command

As you see, we even rely on the hosting provider integration, but of course that’s optional. All you need to do after setting up the dependencies and the configuration is to ddev start, then you can launch the tests of any kind.

All the custom bash functions above are adapted from https://github.com/Gizra/drupal-elm-starter/blob/master/ci-scripts/helper_functions.sh, and we are in the process of having an ironed out starter kit from Drupal 8, needless to say, with ddev.

One key step is to make ddev non-interactive, see global_config.yaml that the script copies:

APIVersion: v1.7.1
omit_containers: []
instrumentation_opt_in: false
last_used_version: v1.7.1

So it does not ask about data collection opt-in, as it would break the non-interactive Travis session. If you are interested in using the ddev pull as well, use encrypted environment variables to pass the machine token securely to Travis.

The Icing on the Cake

ddev has a welcoming developer community. We got a quick and meaningful reaction to our first issue, and by the time of writing this blog post, we have an already merged PR to make ddev play nicely with Drupal-based webservices out of the box. Contributing to this project is definitely rewarding – there are 48 contributors and it’s growing.

The Scene of the Local Development Environments

Why ddev? Why not the most popular choice, Lando or Drupal VM? For us, the main reasons were the Pantheon integration and the pace of development. It definitely has the momentum. In 2018, it was the 13th choice for local development environment amongst Drupal developers; in 2019, it’s at the 9th place according to the 2019 Drupal Local Development survey. This is what you sense when you try to contribute: the open and the active state of the project. What’s for sure, based on the survey, is that nowadays the Docker-based environments are the most popular. And with a frontend that hides all the pain of working with pure Docker/docker-compose commands, it’s clear why. Try it (again), these days - you can really forget the hassle and enjoy the benefits!

Jun 05 2019
Jun 05

The latest version of Drupal is version 8.7.2. You’re familiar of course. In fact, you’ve been on pins and needles ever since version 8.7.1(a). I’m sure you’ve been instasnaptweeting ever since it was issued.

OK, back to reality: You’re definitely more concerned with getting the data you need, driving great brand interactions, and maintaining costs (and keeping your InfoSec or IT teams happy)—than the latest CMS version.

However, what if I told you that your outdated Drupal 6 or 7 instance could actually hinder you from innovating, drain your budget, and potentially cause unnecessary security risks? And that once you get to Drupal 8, migration costs, security updates, and best-of-breed functionality (like content management and media libraries) from core Drupal contributions will help you deliver the audience experiences that grow your business.

So, should you migrate to Drupal 8 immediately? Yes.

Here’s why:

  • More languages? Not a problem: multilingual capabilities - It doesn’t take an engineering background to know that creating a multilingual site is not an easy task. Taking a step back, there are so many questions to consider:

    • Should content be displayed in a single native language?

    • What percentage of your site traffic is in English vs. other languages?

    • How should you handle media files?

    • Is there a risk if changes are incurred by translations?

    • Will the translations be handled properly? Who will handle translations?

The good news is that creating a multilingual site became a lot easier with Drupal 8 with benefits for both site admins and end users. Drupal 8 is now part of “core” (the basic features). In previous versions of Drupal, you needed to install extra modules (collection of files that contain some functionality)  just to support multilingual, which meant a lot more work, added costs and additional maintenance. Drupal 8 brings multilingual support to core with 4 modules, localized content (which makes usability and translations easier so that content translation can be possible for all types, including taxonomies, field types et al) and there are 100+ default languages included.

  • Ease of content editing - Building layouts has never been more intuitive than with Layout Builder! The tl;dr for Layout Builder allows fielded content on the back-end, but a true drag and drop front-end editing experience. There are even more added benefits including a flexible, admin interface, use of contextual links while keeping structured data. And you can now create layouts for templated content with Layout Builder. Many of Drupal’s competitors don’t allow such a templated approach to be done in browser.  (P.S. Learn more on this fantastic page-editing experience from my colleague, Caroline Casals here.)

  • Responsiveness for all - Responsive behavior is no longer a nice-to-have, but de rigueur.  This was an add-on in Drupal 7, but a built-in feature with Drupal core includes built-in themes that are mobile responsive. Additional web services now allow for content to be accessible from Alexa, Siri, and other virtual assistants.

  • Speed matters! - Drupal 8 has features that will make your websites faster without the need for a lot of technical experience. “Cache tags” are used making caching more efficient and also page loads faster.

  • More robust security - Drupal 8 is the stable version of Drupal; functionalities and major modules have been ported over and are now supported by the Drupal open-source community.

  • Integration friendly - Drupal 8 is set-up so that site administrators can easily use APIs to connect to a number of digital tools. Think: your deep integrations, like web analytic platforms, customer relationship management (CRM), email campaigns, social networks and marketing automation systems; you can rest easier that they’ll perform and communicate in concert.

So why else should you invest now? Drupal 7 is currently on life support.  As of November 2021, Drupal 7 will reach it’s “end of life” (EOL) which means that the version will no longer be supported by core maintainers.  

“No longer being supported” also means the following:

Drupal 9 is scheduled to be released next year (2020) which gives companies about a year to upgrade to Drupal 8. Don’t panic, but develop a reasonable plan for when you'll stop investing in your Drupal 7 platform, keep your site as up-to-date as you can (this will help security), and get on Drupal 8 as fast as you can. Still have questions? Give me a shout.

Jun 04 2019
Jun 04

Historically, migrating your content management system (CMS) or content platform from one major version of Drupal to the next was nothing short of a Herculean task.

Every new version of Drupal meant rebuilding existing functionality, converting (or migrating) your content, and accepting significant changes along the way. Because of this, it’s become commonplace to see stakeholders want to leapfrog Drupal versions (e.g., 5 to 7, or 6 to 8), to extend the life of both their old and new platforms for as long as possible for the least amount of transitional pain.

But this is no longer the case.

If you’ve been swimming in Lake Drupal for the last year, you’ve already heard the clarion call to prepare for Drupal 9, due to release in June of 2020. Most of the messaging has been tailored towards planning ahead for your migration, regardless of what version your CMS sits on today.

All too often, many of those plans call for waiting until Drupal 9 is ready before migrating away from your older platform… you know, to leapfrog ahead and save yourself the pain of CMS migration more frequently than you need.

And that’s only half the story.

If you’re not already on Drupal 8, the time to migrate is now. Drupal 9’s release within a year marks the end of life for Drupal 7. You could be incurring unnecessary security risks, all manner of technical debt, and a deluge of growing time-to-cost barriers — all while missing out on the most useful Drupal 8 features for marketers and developers like Layout Builder, an extensible media management system, and editorial workflow. Most importantly, Drupal 8 is essentially Drupal 9, so you’ll be ready for that upgrade when the time comes without another major effort.

Read: When the time comes, your Drupal 8 site can become Drupal 9 without migrating again.

TL;DR: Migrate Out of 6 or 7 Before 9 Drops

If you already know you need to migrate from Drupal 6 or Drupal 7, but you’re not sure where to begin, read this primer to help you scope, identify, and take steps to start the process.

If you’re still not convinced why you should already be migrating, here’s why it’s critical to begin migration ASAP.

If you’re on 6

  • Drupal 6 support has already ended (as of February 2016). If you’re still on this version, you’ve got unmitigated security risks that, if left unchecked, could cost your organization unforeseen resources or damages.

  • Migration from Drupal 6 will not be part of Drupal 9 core. It will be deprecated in Drupal 8.8 and removed in Drupal 9 to become a contrib module.

  • Core migration maintainers will manage the contrib module and support it for a while, but it will eventually become community owned. That leaves the future direction of that module unclear.

If you’re on 7

  • Support ends in 2021 (and that’s not too far off!). If you haven’t planned or budgeted for this, it’s time to start now, especially if your budget planning is a traditional calendar year

  • You might have painful memories of past Drupal migration. While previous versions were, in fact, incompatible across migrations, this is not the case from Drupal 7 to Drupal 8

  • This is the “last great migration.” Migrating from Drupal 8 to future versions (Drupal 9 and beyond) won’t require a similar migration effort. Upgrading from Drupal 8 to Drupal 9 will be more or less a drop-in-replacement as a version bump. Relatively speaking, there will be significantly less effort in upgrading from Drupal 8.9 to Drupal 9.0 than in previous core versions.

  • You don’t want to spend the next 12-16 months on an old system that you’re already wanting to upgrade. Just rip the band-aid off now. Drupal 9 is essentially a version of Drupal 8 — so the wait is needless, and will only be more complex and costly when making a two-version jump.

  • When Drupal 7 support is officially dropped, security updates will only be managed by third-party vendors.

[Note for developers: here’s how to navigate some of the more complex aspects of 8 on D7.]

[Note for marketers: even two years ago, we hosted a webinar on the benefits of Drupal 8 for marketers.]

But Drupal 8 Isn’t Drupal 9, Yet

On the day of release, Drupal 9.0 will be the same as Drupal 8.9, but with these significant differences:

  • External dependencies (such as Symfony) will be upgraded to the latest major version.

  • Deprecated code in Drupal 8 will be removed, potentially breaking custom or contrib modules still using that code.

Otherwise, there will be no significant core API breaking changes (as in previous major version upgrades), maintaining all the same core features and functionality. This means that you can effectively upgrade from Drupal 8 to Drupal 9 without overhauling your CMS or migrating content, simply by updating a point release.

Migrating to Drupal 8 now will prepare you for Drupal 9, but you will still need a Drupal 9 readiness plan. Knowing what is being deprecated and how that affects your CMS is essential to your roadmap. However, with a readiness plan in hand, your Drupal 8/9 platform’s lifespan will be significantly increased.

Bottom-line: The thing that you’re waiting for is already here. Don’t cling to an old system that doesn’t meet your needs anymore — and is potentially costing you more time, money, and increasing your security risk. 

Resource Bank:

May 27 2019
May 27
Damn you, DEV-MASTER! jflynn Mon, 05/27/2019 - 16:12 Category Development Tags Drupal Planet Comments Generic
May 20 2019
May 20

We are on our journey to master the Drupal performance, after having our previous Part 1: Caching published a couple of weeks ago, we've been lucky enough to get into Issue 386 of TheWeeklyDrop newsletter, Planet Drupal, and got much love and good feedback on Twitter.

If you haven't already read the first part of the series, the ultimate guide for faster Drupal: Part 1 Caching, please feel free to read that article too.


Note: You don't necessarily have to do all of these, some items listed here are replaceable with each other as well, so proceed with caution!

Faster Drupal - Part 2: Aggregation and CDN

  • The one and the only holy grail: Advanced CSS/JS Aggregation
    On every Drupal optimization post you’d read you have to setup and configure AdvAgg module, but you gotta do what you gotta do!
    AdvAgg features and core benefits are listed on the module page completely, so go ahead and read them all, configure it the way that works best for you and move on
    Advanced CSS/JS Aggregation Drupal module

    Note: If you have Mod Pagespeed you might not need AdvAgg module, make sure that you don't overlap your own work

    But that’s not all, if you are on Drupal 7, you should consider checking Speedy module as well, in some areas, this might work a bit better so make sure to check it out as well
    Speedy module

  • For good JavaScript minification in Drupal, you can use modules such as minify but we’d like to recommend minifyJS instead, they listed the differences and benefits on their module page so check it out
    Drupal MinifyJS module

  • CDNize the whole project, as much as you can! You may use CDN module too

  • Move JavaScript to the footer if necessary, some JS files need to be rendered in the head based on the use case and what does the JS do! Also in Drupal 8, it’s quite easy to append your necessary library (Read it JS files) in the footer in twig template files

  • Consider if you can make your own scripts defer/async (a new challenge when it comes to Drupal js aggregation)

Okay, this round was much easier thanks to AdvAgg module for taking care of half of the things we need to do for us! Note that on the frontend side you can Uglify, Minify and make sure everything that you code, will become compressed, whether it’s CSS, JS or even images or SVG files! Now let's get to it, Image optimization. 

Image optimization

  • Drupal 8: Use the Responsive Image module wherever possible and create the appropriate styles. It uses the tag which is what we really want

  • One might say we have one too many image optimization modules in Drupal, which is a good thing! For that we tested some, experienced with some of them and here’s what we suggest: Use blazy and lazyload_images (Drupal 8 that uses IntersectionObserver instead of scrolling events), Also consider: lazyloader and image_lazy_loader when using the picture module for responsive images in Drupal 7. There is also a lazy loading option that works well

  • Image optimization: for main images/icons used in the design (Yes you can optimize SVG files as well), also the best tool for that is not in Drupal, try ImageOptim desktop app, Also there’s an API-based service available with a Drupal 7 module, take a look here, might worth setting/selling this up to clients

    Also in the same context, we can use ReSmush.it which is free (But should donate some beer to them)
    Drupal 7 Module, Drupal 8 Module

  • Image formats like JPEG 2000, JPEG XR, and WebP often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. There's a really good module that help you serve WebP, it's called, you guessed it; WebP.

  • Serve WebP images with your web server with the MOD PageSpeed by Google for Apache and Nginx.
    Or conditionally serving WebP images with Nginx.
     

Bonus tip: Even favicons should be optimized. Sometimes people ignore the weight of a favicon file. You shouldn’t! 

 

For the next week, we will be covering subjects regarding Drupal database/web server tweaks & improvements, stay tuned.

Written by Sohail LajevardiSohail Lajevardi
Developer at Ramsalt Lab

May 02 2019
May 02
Where is drush? Unifex Fri, 05/03/2019 - 10:58

Part of me is suspecting that I may be one of the lucky 10,000 today but I figure it's worth putting this out there because if I wasn't aware of this then there may be others too. It turns out that the version of Drush that you just installed may not be the version of Drush that executes your command.

So, as it happens there's a number of ways to install Drush. Older OSs may have it in the package management system, you may have just installed it globally using the instructions on the site, or, if your project is managed by composer it may have been installed as a site-local version. In my case I had messed it up just a little and had multiple versions hanging around and, despite having definitely downloaded and installed drush 8.2.3 to /usr/local/bin/drush and I confirmed that this was being called via which drush when I ran drush --version it informed me I was running version 9.6.2.

The thing that I didn't know... Drush will check the directory the site is in to see if there is a local-site version installed and pass off the request to that. So despite having Drush 8.2.3 installed and called from the command line the request was finding the local copy and returning results from that. If it wasn't for the fact that this was a Drupal 7 site and I'd inadvertently installed Drush 9.x locally via composer. If it wasn't for the fact that Drush 9.x doesn't support Drupal 7.x I'd never have known that this was how it worked.

Big thanks to Kirill for correcting my brain meat on this.

Planet Drupal
Apr 26 2019
Apr 26

 

 

In the first part of this blog, we had completed the installation and had also created blocks for custom block types. In this part, we will see how to configure the TB mega menu so that we can get the structure of the menu ready as per our design.

 

Configuring the TB mega menu and placing the TB mega menu block in a region are two separate things.

 

The TB mega menu can be configured for an existing menu. So, you need to ensure that you have a complete hierarchy of menu ready before you begin the configuration. However, you can modify the links later on from the TB mega menu configuration page.

 

If you already have a menu that you want to use then you are already a step ahead! If not, then go to /admin/structure/menu and click on the Add menu. Create the menu as you normally would.

 

For demonstration purposes, we will be using the below menu structure. Let the name of this menu be Example menu:

 

Parent 1

    -Child (1)

        -Child (1) content

    -Child (2)

        -Child (2) content

        -Sub child (1)

            -Sub child (1) content (This content will be displayed over the child (2) content)

        -Sub child (2)

            -Sub child (2) content (This content will be displayed over the child (2) content)

    -Child (3)

    -Child (4)

Parent 2

    -Child (1)

    -Child (2)

        -Sub child (1)

            -Sub child (1) content (This content will be displayed over the child (2) content)

        -Sub child (2)

            -Sub child (2) content (This content will be displayed over the child (2) content)

    -Child (3)

Parent 3

    -Child (1)

    -Child (2)

    -Child (3)

Implementation

Now that we have a clear idea of how we want our menu to look like we can start implementing the TB mega menu.

 

Before we do so, one thing we had noticed earlier is that there were contents embedded in the menu itself for certain menu items. The contents include:

  1. Title

  2. Image

  3. Description

 

Some of the block contents had all of the above fields while some of the block contents may only have the title and description. Also, we need another content which would have neither of the above. We would come to this part later on.

 

Since we know what the hierarchy of the menu is and what content the menu items need to have let us create these contents first so that we have the block ready (more on this later) when we start configuring the menu.

 

The contents we have for the menu items are rendered via a block. These blocks will be later on placed while configuring the menu.

 

Flashback time

 

Let’s rewind time! Earlier we had created a block type with certain fields. These fields were left on the user to create as it is a pretty straight forward process. For this demonstration purpose let us create the following fields for our block type.

  1. To create fields for the block type, go to admin/structure/block-types and click on Add block type.  Specify the Label and a description. Once done, click on Save block type.

  2. Next, you will be taken to the block type listing page which is /admin/structure/block-types. On this page you will have the option to Manage fields. You can add, edit or delete the fields for the particular block type from here.

  3. Once you click on the Manage fields option, you will be redirected to a page wherein you will be able to add or modify the fields.

  4. Initially you will have the following fields present by default:

    1. Label: this field corresponds to the name of the block.

    2. Title: this field corresponds to the title of the block.

    3. View mode: this field corresponds to the view mode of the bean.

    4. Revision settings: this field corresponds to the revision of the block.

    Note: these fields are provided by the bean module itself.

  1. Add the following fields by specifying a label and selecting the type:

    1. Menu item image:

      1. Label: Menu item image

      2. Field type: Image

      3. Widget: Image

You can add an image style to this field by going to the Manage display tab. Over there, click on the gear icon to the extreme right of this image field.

d8_manage_display

Once you do so, further configuration options will open. You will see an option to provide an Image style. Click on it and select the image style you want. Additionally, you can link this image to the content or the file. To do so, click on the Link image to option and select the desired option from the dropdown menu. Once done, click on Update and save the block type.

 

d8_update_save

 

    1. Menu item description:

      1. Label: Menu item description

      2. Field type: Long text

      3. Widget: Text area (multiple rows)

        The below image shows where you can create a field.

 

       

d8_menu_item

 

  1. Once done, save it and you will have your block type ready with the fields.

  2. Now you are ready to create the content for the block.

 

Creating content for the blocks

  1. To create the content for a menu item, go to /block/add/menu-item-content-block

  2. Fill out the below fields:

    1. Label: This is a mandatory field. This field corresponds to the blocks name i.e. this is the name of the block.

    2. Menu item image: This is an optional field. If we want to have an image in the content then that needs to be inserted here. On clicking browse, the media browser opens from where we can select the image file from our local storage or that residing on the server itself.

    3. Title: This refers to the title of the content.

    4. View Mode: This is a mandatory field. This field provides the default view mode for the bean. It would have a default option selected. Leave it as it is. This does not need to be modified.

    5. Menu item description: This refers to the description of the content.

    6. After the necessary information has been filled up, save the block.

  3. Now, the content for a particular menu item has been created as a block. Similarly, we can create blocks for other menu items. There can be a case where a particular menu item does not have an image. It only has a title, description and a link. In such a case, while creating the contents in the block as we did above, leave out the Menu item image blank i.e. without uploading anything in it. For another case, we would also require a common empty block, which would have nothing other than the block label. I will address this later on as where we exactly need it.

 

Now that we have the content ready we can start configuring the TB mega menu.

 

Configuring the TB mega menu

 

Initial configuration

  1. To configure the TB mega menu go to /admin/structure/tb-megamenu.

  2. Click on the config link for the menu that you want to be displayed.

  3. A page like the one below would open.

d8_initial_config

 

  1. This lists the 1st tier of menu items which we are referring to as the Parent menu item links with some options. The options include:

    1. Style: leave it as default.

    2. Animation: this might be selected as none. Change it to fading or some other animation style. This is because if no animation is selected then all the menu item contents would appear one above another and not only on hover, which is not what we want.

    3. Delay (ms): specify an animation delay as required.

    4. Duration (ms): specify an animation duration as required.

    5. Auto arrow: to hide the arrows next to items that have a submenu.

    6. Always show submenu: collapse submenus when browsing on small screens.

  2. This is all that we need to configure for the initial items visible when this page loads for the 1st tier (Parent) menu items.

  3. Now, let us move inside these links.

Creating child menu links

  1. Each of the child menu links is wrapped in containers. Let us name them for ease of use:

    1. Let us call the box that contains all the elements as the Container.

    2. Let us call the box that contains the elements directly as the Wrapper.

    3. Let us call the menu items as Elements.

  2. A visual representation will better support the explanation:

    1. Container.

             

d8_child_menu

 

  1. Wrapper.

 

d8_wrapper

 

  1. Element.

 

d8_element

 

  1. If there is a need to modify a certain menu link then that can be done by clicking on the Edit Links option on the right-hand corner of the page. This will redirect you to the menu link configuration page. Let us see below where it is

 

d8_edit_links

 

Add content to child (1)

  1. Click on Parent 1.

  2. Click on the first Element which is the child (1).

d8_parent1

 

  1. You will be able to see the option of Sub menu above. The value will be set as No. Toggle this option to Yes and a submenu for the child (1) will appear.

 

d8_child(1)

 

  1. Note: This submenu does not correspond to menu item links i.e. this is not for displaying a child menu link or any menu link to be precise. This submenu is for placing the content as a block. Menu items which have child menus will automatically appear under the respective menu items as they have been configured in /admin/structure/menu or by going into Edit Links as discussed above.

  2. We had earlier created a content for this which we would be placed as a block here. To do so, now you have to click on the submenu Element.

  3. Then click on the option which says Blocks: Select Block.

 

d8_blocks

 

  1. On doing so a drop down will appear with all the blocks.

 

d8_drop_down

 

  1. Select the block which has the content for this child menu item.

  2. In doing so the content will appear and look something like this:

 

d8_content_appear

 

  1. Do not worry if the design seems to break. This is just the configuration page and the design can be handled entirely through the CSS.

  2. Hence we have created content for a child menu.

Add content & submenu to the child (2)

Our design had a child (2) menu item which had two submenu links as well as content. This is a bit tricky. The functionality we sought was that:

  1. Hovering on the child (2) would display:

    1. The submenu links.

    2. The content for the child (2).

  2. Hovering on the submenu link for the child (2) would display:

    1. The content for the submenu links instead of the child (2) content, also for the second child menu link.

 

Let us see how we can achieve this.

  1. As per our menu structure, on clicking on the child (2) Element a sub menu link should appear.

  2. According to our design, the content should be placed just beside the submenu link for the child (2).

  3. To do so, select the Wrapper of the submenu link and an option will appear which says Add/remove Column.

  4. Click on the “+” sign for the Add/remove Column to add a column beside it.

  5. On doing so a column will be added beside the menu item link.

d8_column

 

  1. Now we need to add content to this block. So, like we had previously added, we can add content for the same by clicking on the Blocks option.

Note: the submenus may appear a bit too small. This could be easily fixed with custom CSS. For demonstration purposes, I had given a fixed width of 600 to the submenu Container.

  1. To do that, select the submenu Element of the child (2) and toggle the Sub menu to Yes

 

d8_sub_menu

 

  1. Once the block is added it will look something like this:

 

d8_block_added

Add no content for submenu of the child (2) of Parent 2

  1. Child (2) has two submenus:

    1. Submenu 1 (has its own content).

    2. Submenu 2 (does not have its own content).

  2. The tricky part is the second submenu not having content. In that case, the content of the child (2) will be shown when we hover on submenu 2. But this should not be the case as hovering on submenu 2 should show empty.

  3. To do this we need to place an empty block which we had created earlier

 

d8_empty_block

 

  1. Doing this would mean that when we hover on the submenu then no content will be shown and it would appear empty

 

Once done, click on the Save button to save the configuration.

 

The TB mega menu that we created should look something like this:

  1. With the menu looking like this:

d8_mega_menu

 

  1. The underlying menu links looking like this:

 

d8_underlying_menu
  1. The menu links with its submenu links and contents looking like this:

d8_menu_links

 

  1. The submenu links with its content look like this:

 

d8_S_links

The blocks might appear like the ones above but with CSS this can be easily fixed and the blocks can appear in one particular place.

 

This TB mega menu that we have configured is essentially a block. Once done, save it. Then go to /admin/structure/block, select the TB mega menu that you configured and place it in the desired region according to your theme region. Voila! You have your TB mega menu ready!

 

There are some points to take note of.

  1. Remember to turn on animation. It would be none initially. If an animation is not set then all the blocks that you place for the menu items will all appear at once, one on top of another.

  2. Remember to provide permission to the bean block else, it will not appear for the anonymous user. To do so:

    1. Go to /admin/people/permissions.

    2. Search for this term your_bean_block_name block (where your bean block name is the name of your block).

    3. Look for the your_bean_block_name block: View Bean.

    4. Tick mark the checkbox for anonymous user.

    5. Clear all cache and check the site for the anonymous user. You will have the block in the TB mega menu shown for the anonymous user.

 

You now have a completely configured TB mega menu on your site! You can add images, videos, texts quite easily now through blocks.


P.S: If you have missed out the 1st part of this blog, you can check it over here.

Apr 26 2019
Apr 26

The world as we know it did not always come with the TB mega menu for Drupal 7. Traditional menu implementations included writing the entire HTML and designing it as per the needs or using default drupal menu parallelly with other contrib modules to support different requirements This would often take days or even weeks to implement. Even after completion, the client may ask you to make changes and things may go haywire. Changing every HTML element is a daunting task! Another approach may be to use certain modules offered by Drupal to create a menu. The problem with this approach is that, though the menu might look simple, it would be a daunting task to make it completely configurable within a small time frame.

 

This is where TB mega menu comes in to save the world!

 

“TB Mega Menu allows you to create a mega menu with an innovative back-end user interface and synchronized with Drupal core menu.” - drupal.org

 

The TB mega menu gives the user an option for a completely configurable approach in terms of building a menu from scratch. Today we are going to discuss this implementation over Drupal 7. It allows the user to create a mega menu with images, text, video, using a block.

 

There is one dependency though that these things can be inserted via a block.

 

The installation and implementation are pretty straight forward but there are certain hairpins that can be the cause of a car crash if not carefully configured.

The problem

Recently, one of our clients had requested a menu which will have content like images, videos, links, text, etc. for each of the respective menu links, while being completely configurable at the same time. Now, this was a task which called up for challenges. It might appeal to one, to create the menu with bootstrap. The only problem with this being, it wouldn’t be so much of a configurable option for the user. Anytime there would be any changes needed to be made, the client would have had to come to us and wouldn’t be able to directly change it themselves. To have such a configurable option is a pretty daunting task!

 

This is where the TB mega menu module stepped into our help. The content we talked about earlier i.e. images, videos, texts, etc. essentially could be placed in the menu through blocks. Great isn’t it? Well not so much. You will see later on why.

 

As one dilemma seemed to hit the exit gate, another stepped in to fill its shoes. The basic block Drupal 7 offers give the user the option to enter details for the following fields only:

  1. Block title

  2. Block description

  3. Block body

 

And that’s essentially it. If you were to insert an image, video or a link then you would be stuck. One thing you could do is to create a block programmatically with the required fields but that’s one block. What if you needed every content you place in the mega menu for each of the respective links to be different?

 

This problem has been addressed in Drupal 8 with the concept of block types. Block types are essentially like content types wherein you can add fields of different type and later on add content for that particular block type respectively. You can have multiple block types with each block type having a different set of fields. These blocks can then be placed anywhere you like. But this is for Drupal 8. Fortunately, Drupal 7 presents a module which allows users to do the same. The module named bean now comes to the rescue!

 

“What is Bean?

Think of a Bean as a method to provide new types (compared to node this would be a content type) which then provides an add the content interface to create as many blocks as you require (see screenshot below). The bean content can then be placed around the site just like any other block.-drupal.org

 

Through this bean module, we can create a block type with the required fields and then have multiple blocks of that block type.

 

We now know what are the things required to kickstart the implementation we seek. So, let us now start the implementation.

Installation

  1. First, we need to install the TB mega menu.

  2. Then we need to install the bean module.

  3. Check if bean_admin_ui is enabled. If not then enable it. This will give us the UI to create the block type.

 

Before we start with the implementation of TB mega menu we need to have our content ready for the respective menu items.

Creating a block type

When the bean and bean_admin_ui modules are enabled, there will be an option to create block types understructure. To create a block type,

  1. Go to /admin/structure/block-types/add.

  2. Specify a name and description for the block and save it.

  3. Saving the block type will take you to the block type listing page (/admin/structure/block-types). Here you will be able to see all the block types that you have created.

  4. Now, that you have created a block type, you have to add fields to it. Similarly, like in content types, here, you have to click on the manage fields link in the block type listing page.

  5. From here you can create the fields you want. After doing so save the block type.

  6. Now, you have a block type created with fields in it. You can choose to add a block for this block type as we would do for content. We will be looking at it soon.

  7. Similarly, you can create as many block types as you want.

 

Adding a block for a block type

  1. Now, that you have a block type ready, you can add the content for it i.e. creating the blocks.

  2. To add a block go to block/add. Here you will be presented with a list of block types that you had created. From here you can choose to add a block for a respective block type. You can also go to /admin/content/blocks, which is the block listing page for the blocks created for custom block types, and click on Add block.  One thing to note here is that you would not be adding a block by going into /admin/structure/block/add because this is for adding the default block that Drupal 7 provides.

  3. Fill in the required fields and save. A block will be created.

 

You now have your content ready to be placed in the TB mega menu as a block.

 

Creating a menu

TB mega menu uses the menu that you already have on your system and lets you configure that accordingly. Creating a menu is a straightforward approach and you need to create the menu as you normally would by going into /admin/structure/menu and then click on the Add menu.

 

Configuring the TB megamenu

You have two essential things ready:

  1. The blocks (the contents that need to be placed in the menu).

  2. The menu itself.

 

Let us start configuring the TB mega menu!

 

  1. Go to /admin/structure/tb-megamenu.

  2. The TB mega menu is configured upon an existing menu (refer above). Select the menu that you want to configure by clicking on the respective menu’s config option.

  3. The menu links can also be modified from this configuration page. If you need to modify the links you can do so by clicking on the Edit links option.

  4. The config page shows 6 options initially:

    1. Style

    2. Animation

    3. Delay

    4. Duration

    5. Auto arrow

    6. Always show submenu

  5. The first level of menu items is shown initially. Let us, for example, take this as:

    1. Parent 1

    2. Parent 2

    3. Parent 3

  6. On clicking on Parent 1, we would have the option to

    1. Add a submenu

    2. Add an extra class

    3. Icon

    4. Item caption

  7. The child menu links will appear in the same order and relation as created in the menu /admin/structure/menu.

  8. This Parent 1 menu item will have it’s child menu links shown in a container.

  9. On clicking on this container, we will have the option to

    1. Add a row below this container

    2. Hide when collapse

    3. Specify a width

    4. Align the items as we like

    5. Add an extra class

  10. The container further contains a wrapper which contains the child menu links. We have an option to:

    1. Add/remove columns. We can add a column in parallel to the child menu links if we want

    2. Hide when collapse

    3. Set grid size for the column

    4. Insert a block in that column that we added

    5. Show block title

    6. Add an extra class

  11. On moving further and clicking on the child menu link we are presented with the option to

    1. Add a submenu. If we add a submenu we would have the option to insert a block in that submenu

    2. Group the submenus. This means that the submenus would appear below the child menu links

    3. Break column

    4. Add an extra class

    5. Icon

    6. Item caption

  12. On moving further into the sub-menu we would be able to see that the sub-menu is wrapped in a wrapper. On selecting the wrapper, we would be able to

    1. Add a row

    2. Hide when collapse

    3. Specify the width of this sub-menu

    4. Align text

    5. Add an extra class

  13. On moving further and selecting the block in the sub-menu we would have the option to

    1. Add/remove a column

    2. Hide when collapse

    3. Set grid size

    4. Add a block

    5. Show the block title

    6. Add an extra class

  14. You can have as many child menu items as you want and blocks with them.

Placing the block

The TB mega menu that you created is essentially a block. So you would have to place it in a region like other blocks.

  1. Go to /admin/structure/blocks.

  2. Search for the TB mega menu block that you created and place it in the desired region and save it.

  3. On the specified page the TB mega menu will appear.

Note

Blocks permission

You have implemented the blocks with bean module by creating block types with and then creating blocks (the content that we need to show) for it. This block needs to be given permission. To do so:

  1. Go to /admin/people/permissions.

  2. Search for this term your_bean_block_name block (where your bean block name is the name of your block).

  3. Look for the your_bean_block_name block: View Bean permission option.

  4. Check the permission for the anonymous user.

  5. Clear all cache and check the site for the anonymous user. You will have the block in the TB mega menu shown for the anonymous user.

All blocks inside TB megamenu appearing at once

  1. One thing to keep in mind is that when creating a TB mega menu for the first time if there are sub-menus and blocks inside them then they would all appear one on top of each other.

  2. This is because the animation is set to none.

  3. You would have to select the animation as fading or any other animation style. It is only then that on hovering, the blocks would appear else not.

Apr 19 2019
Apr 19

What we learned from our fellow Drupalists

Lisa Mirabile

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

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

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

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

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

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

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

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

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

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

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

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

  1. How we define wicked awesome content
  2. How we translate indicators into actionable metrics
  3. The technology stack we use to empower content authors

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

A before-and-after view of our admin theme

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

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

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

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

Apr 12 2019
Apr 12

For us, the Paragraphs module is the holy grail of structured content creation.

With Paragraphs it is relatively uncomplicated to define prefabricated content elements that define the structure of the corresponding content. These can then simply be placed in the desired content by editors.

Paragraphs default display

This allows editors to create clearly structured content without a lot of effort and to fall back on recurring content structures. The editors simply select the desired element from the list of available content elements, fill in the corresponding fields and the content is output in the specified structure. This is extremely helpful when creating more complicated page layouts where you want to use the same structures over and over again.

Is there a better way?

We have asked ourselves and our clients' editors how to further simplify and improve the input using Paragraphs, or what might interfere with the editorial process when using Paragraphs.

It has often been mentioned here that it is quite annoying to have to drag the content elements to the desired position after adding them. This is especially cumbersome for content with many content elements. It would be much better to be able to insert the element right at the corresponding position.

Paragraphs with add_in_between

Fortunately, there is the Paragraphs Features module from the Thunder Core team. This module extends Paragraphs by inserting a button between each content element to open the modal dialog for adding more elements. 

Using these buttons, editors can insert the elements in the correct position as desired and do not have to move them first.

 

Beautiful. But is there an even better way?

Editors always add the same elements to certain content. The question arose whether these content elements could not be inserted preferentially, i.e. without first having to open the dialog.

In addition, some editors were disturbed by the large number of buttons: after each single content element a button for adding further elements appears. *sigh*

So we thought about how to make the buttons less annoying. 

Buttons you don't see don't interfere. Accordingly, with our new module Paragraphs Editor Enhancements, we have simply hidden the buttons. 

With some applications and tools (e.g. Apple Mail or Slack) the buttons for certain actions only become visible when you point the mouse over a certain area. Exactly this function has also been implemented for the buttons: only when you point the mouse over an existing content element, the buttons for adding become visible above and below the element.

new styling for Paragraphs add_in_between

In addition, the most important content elements should also be able to be inserted directly with a click. 

So we had to add two new buttons for the most important content elements to the button to open the dialog.

Editors are no longer disturbed by the large number of buttons and can simultaneously insert the most important content elements with just one click.

Great! But can you make it even much better?

Another often mentioned improvement suggestion concerned the dialog for adding content elements themselves.

Paragraphs dialog

If you have many elements to choose from, the dialog quickly becomes confusing. In addition, editors often find it difficult to find the right elements. On the basis of the title of a content element one cannot always immediately conclude on the actual purpose of the element and cannot imagine how the element is represented in the content.

With Paragraphs Editor Enhancements we have completely redesigned the dialog. We've added the ability to filter the list of content elements so editors can quickly find the desired elements through the title and description of the element.

redesigned Paragraphs dialog

In addition, the representation of the elements in the dialog has been revised. Each element shows the title and the description as well as an image (if uploaded in the element's configuration).
As an alternative to displaying the elements as tiles, you can also display the elements as a list.

As a bonus, you can create categories for content elements and assign the individual elements to one or more categories. 

This gives editors a faster and better overview of the available content elements and allows them to find the desired element more quickly and easily.

Whew. Do you have any more?

We wouldn't be undpaul if that was all.

Some time ago, one of our clients was faced with the problem of having to add the same elements in the same order over and over again. 

As a simple example, one can imagine this as follows: an introductory text followed by an image, then a two-column text and finally a text with an image.

For the editors, this meant that the corresponding content elements had to be inserted in the correct order for each individual content item. 

Wouldn't it be great if you could add the desired elements with just one click, so that the editorial staff could concentrate on entering the actual content?

redesigned Paragraphs dialog with Paragraphs Sets

The solution to this problem was the Paragraphs Sets module.

Paragraphs Sets are used to define groups of content elements. These groups can be added to the content just like the usual elements.

This saves editorial members the hassle of searching out and inserting individual elements and allows them to start entering the corresponding content directly.

Of course, Paragraphs Editor Enhancements and Paragraphs Sets also work together. The element groups of Paragraphs Sets are displayed in a separate category in the dialog and can also be found using the filter function. 

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