Upgrade Your Drupal Skills

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

See Advanced Courses NAH, I know Enough
Jul 16 2021
Jul 16

For the July 2021 SC DUG, I gave my new talk titled “Queries on Queries” which poses questions to ask yourself when migrating data between systems. Data migrations are often critical to project success, but all too often that are treating as a throw-away process. This talk is intentionally platform agnostic building from my experience with both Drupal and Salesforce.

[embedded content]

If you would like to join us please check out our up coming events on MeetUp. You’ll find our meeting times and, once you RSVP, remote connection information.

We frequently use these presentations to practice new presentations, heavily revised versions, and test out new ideas with a friendly audience. So if some of the content of these videos seems a bit rough please understand that is some of the point. If you want to see a polished version checkout our group members’ talks at camps and cons.

If you are interested in giving a practice talk, leave me a comment here, contact me through Drupal.org, or find me on Drupal Slack. We’re excited to hear new voices and ideas. We want to support the community, and that means you.

Jul 13 2021
Jul 13

Headless commerce is quickly becoming the gold standard in content management system architecture. In this article, Josh Miller delves into the capabilities of Drupal Commerce 2 for a headless setup.

Using Drupal Commerce 2 checkout for headless ecommerce

Drupal Commerce 2, like Drupal 9, was a big change from previous versions. The codebase is much different and it’s quite a learning curve when moving from older versions of Drupal, like 7 or 8. However, this is good. The new versions are modern and all-around better. I’ve had a number of revelations while working with Drupal Commerce 2 and Drupal 8 that made me smile. (If you haven’t upgraded to Drupal 9, check out my blog Drupal 8 to Drupal 9: The Easiest Major Upgrade in a Decade).

In this post, I’ll explore one revelation I had while working with Drupal Commerce 2’s checkout handling and how its forward-thinking development has paved the way (and encourages all new checkout panes to follow suit) for headless ecommerce using Drupal.

Drupal Commerce 2 checkout is not a form. Say what!?

Generally, when you think of checkout, you think of it as a sequence of events and one big final submission. This is further driven home by the idea that you can, and should, be able to go back and edit your checkout choices before the final submission. In Drupal Commerce 2, going back and forth between checkout steps is supported, but there is no final submission handler that saves everything.

Wait, what? That’s right, there’s no need to save all the data on the checkout form once checkout is completed. You see, all checkout panes (a step in the checkout process) have a submission event that gets called when it's time to save the data. So if you’re going to save data in a checkout pane, you have to do it after your customer has moved forward in the checkout process but before your customer is ready to commit to the checkout pane’s final value state (complete checkout). Submission is perceived to be at the end of checkout, not before.

On the surface that might make sense, in fact, this workflow being so obvious might even blind you to the implications. Since each pane is basically handling its own submission workflow, you can’t allow your form state to persist choices and not make a decision until the end. You’re probably, like me, thinking that saving data and reacting to data is the same thing. But this assumption is old, out-of-date, incompatible with best practices, and in checkout for Commerce 2, causes design problems.

Click to discover your ideal architecture with our analysis.

Explanation through an example: A checkout newsletter subscription

A common want is to include a little checkbox underneath a contact information email field where new or returning customers can opt-in to a newsletter. Sure, that’s no big deal, right?

Our customer expects that things in checkout aren’t real until they complete checkout (i.e. nothing is saved until they actually place the order). On the other hand, Drupal Commerce 2 expects all panes to save their data after a “continue to next-step” button gets clicked, submitting that pane.

Here’s how the checkbox would be made using our current form submission logic:

  1. Create a CheckoutPaneBase object that collects data through a checkbox.
  2. On the pane form submission, subscribe the customer to your newsletter.

Do you see the problem? If we react on pane submission (our only choice in our current way of thinking), we’ll subscribe the customer to our newsletter well before they are done with checkout. In fact, each time they see the first page of checkout and proceed to the second, they will be subscribed to our newsletter. Not only is this not what the customer would expect, but subscribing them multiple times is totally unnecessary and would likely cause problems. Subscribing the customer on pane form submission is the wrong approach.

This is where things get really trippy — and awesome and beautiful and wonderfully clever and great. You see, Drupal 8, which Commerce 2 is built around, has been designed to not require forms, form states and value persistence in order to trigger important actions. This is a whole new way of thinking and maybe the most important to our discussion. Previous to this, most Drupal 7 developers would have assumed that all forms require user-facing interfaces that would be submitted, but that is a pretty brutal assumption and has plagued a lot of Drupal installations over the years. If that was still the case, then form submissions are something that headless implementations of Drupal would never really trigger. There must be a better way.

Headless decoupling breeds better code using events.

If checkout was a single form with a final submission handler that submitted payment, subscribed users to newsletters, saved addresses to profiles, and did all the things you would expect all at once, then all the code that manages these things would have to react to a single form submission.

However, if we use Drupal's built-in event system instead, we suddenly have a much greater degree of control. But before we get into that, let’s first take a quick look at what events are and where they come from.

Drupal 8 made a big shift towards being object-oriented by adopting Symfony within its framework. Symfony provides a number of components useful in modern object-oriented programming, one of which is events. Events in Drupal 8 give developers a new way to extend and modify how interactions with core and other modules work. If you’re already familiar with Drupal 7, events are basically meant to replace hooks. Drupal 8’s event system documentation helps us to understand the basic concepts and components making up the event system.

  • Event Subscribers — Sometimes called "Listeners", are callable methods or functions that react to an event being propagated throughout the Event Registry.
  • Event Registry — Where event subscribers are collected and sorted.
  • Event Dispatcher — The mechanism in which an event is triggered, or "dispatched" throughout the system.
  • Event Context — Many events require a specific set of data that is important to the subscribers to an event. This can be as simple as a value passed to the Event Subscriber, or as complex as a specially created class that contains the relevant data.

Source: Drupal.org documentation, Subscribe to and dispatch events (link)

Getting back to our checkout scenario, if you use the events system and your checkout completion is simply a state transition from Draft to Completed, then other modules could subscribe to that transition event, take the saved data from the different pane submissions, and do whatever they want with it.

Do you see the beauty here? By forcing checkout panes to submit before the final submission, we (module builders, implementers, etc.) have a baked-in reason to store checkout decisions on the order so that order events can access them separately, giving us the ability to create orders with checkout decisions saved that can skip checkout completely and still have the events trigger the needed actions. This is quite powerful and opens up a whole new world of possibilities. Of course, since this is an implicit design choice, it’s up to the author of the module or code to see the reasons and embrace them.

Entity and event-based, instead of form-based

So to complete our newsletter subscription pane example using our new knowledge of events instead of form submissions, here’s what we would do:

  1. Create a CheckoutPaneBase object that collects data through a checkbox and saves it to the order (either through a field value or the ->setData typed data interface.
  2. Save this value on pane submission but don’t act on the value (i.e. don’t subscribe the user).
  3. Create an event subscriber and use the transition event you want to use as a trigger. Completing checkout makes the most sense.
  4. Treat the order value as a "request subscription to newsletter." Then, when the event fires and the event subscriber runs, it can look for the saved value and set the user to subscribed or not after it returns. This allows us to handle someone going through an event twice for some reason, like for multiple orders, etc.

Your customer gets subscribed to your newsletter when they, and you, expect them to. No forms are needed. ISN’T THAT AMAZING!

Thanks to the many authors of Drupal Commerce 2, including Bojan Živanović and Matt Glaman, who implemented this design choice years ago, many modules and implementations are simply technically better and likely ready for headless implementations now that headless is all-the-rage.

And best of all, from a developer standpoint, this also means the bulk of your most critical automated tests that interact with your code doesn’t have to access the checkout form. They simply have to have orders that get transitioned. This makes writing tests, which equates to better code, simpler.

Your Drupal Commerce experts

As a full-service Drupal agency, Acro Media has significant expertise in digital commerce architecture, ecommerce consulting and design, customer experience, Drupal development and hosting architecture. We would love the opportunity to work with you.

View Our Drupal Commerce Services

Editor’s note: This article was originally published on October 28, 2019, and has been updated for freshness, accuracy and comprehensiveness.

Jul 09 2021
Jul 09

In June for the SC DUG meeting Will Jackson from Kanopi Studios gave a talk about using MQTT with Drupal to connect to local IoT devices. A fan of home automation, Will has created a Drupal 8/9 version of the MQTT module. He is hoping to encourage more people in the Drupal community to join the fun.

[embedded content]

If you would like to join us please check out our up coming events on MeetUp. You’ll find our meeting times and, once you RSVP, remote connection information.

We frequently use these presentations to practice new presentations, heavily revised versions, and test out new ideas with a friendly audience. So if some of the content of these videos seems a bit rough please understand that is some of the point. If you want to see a polished version checkout our group members’ talks at camps and cons.

If you are interested in giving a practice talk, leave me a comment here, contact me through Drupal.org, or find me on Drupal Slack. We’re excited to hear new voices and ideas. We want to support the community, and that means you.

Jun 30 2021
Jun 30

Infinite scrolling is a technique used to show more content as the user scrolls down a page eliminating the need for the user to click to go to the next page. This is commonly implemented in popular social media apps.

This tutorial will demonstrate how to use the Views Infinite Scroll module to achieve this and also show options that can be used to customize the user interaction with the infinite scrolling behavior.

We will show you how to:

  • Install the module
  • Set up a simple view
  • Add the infinite scroll behavior
  • Customize the infinite scrolling behavior.

Drupal Views Series

Table of Contents

Getting Started

We can easily install Views Infinite Scroll using Composer:

composer require drupal/views_infinite_scroll

To enable you can use Drush:

drush en views_infinite_scroll -y

Step 1: Set up your View

For the purposes of this tutorial, we are assuming you already have a content type set up and have already generated enough content for it.

We are going to create a simple View that lists Articles (Title and Body fields).

Go to Structure -> Views -> Add view

Here is a screenshot of our simple View. There is nothing fancy. We are only listing published Articles and have created a Page display for it.

If you’re new to Views then check out our “Getting Started with Views” tutorial.

Step 2: Adding the Pager

In the Pager settings of your View, change the type to “Infinite Scroll” (leaving all the settings as default for now).

Also, in the Advanced section of your View, set “Use AJAX” to “yes”.

Here is how our View settings looks now:

Save your View and go to the URL of the View page to test out your Infinite Scroll. You should now see a “Load More” button in the pager section of your View page that looks like this:

And that’s it! You now have infinite scrolling for your View. However, there are more options that can be configured for your Infinite Scroll. These are all optional as we shall demonstrate them now.

Step 3 (Optional): Replace the button text

You can add tokens to your Infinite Scroll button to enhance the user’s experience.

In the pager section of your Views configuration page, open the settings of your Infinite Scroll pager as shown in the screenshot below:

Set the button text to “Load @next_page_count more (Total @total)” as shown in the screenshot below:

Now your Views Infinite Scroll Pager button text will look like this:

@next_page_count” and “@total” are called “tokens” in Drupal. The tokens are replaced with actual data automatically.

View Infinite Scroll supports the following tokens:

  • @next_page_count
  • @remaining_items_count
  • @total

Step 4 (Optional): Automatically Load Content

Currently, users would have to click on the “Load More” button to get the next set of content. The Views Infinite Scroll page has an option to automatically load content (without the need to click on the button).

Go to the settings of your Views Infinite Scroll pager and check the box “Automatically Load Content” and click on Apply.

Save your View and then test it. As you scroll to the bottom of your View, another set of content should automatically be loaded.

Warning: Enabling this setting means that the user never actually gets to the footer of your page until they have exhausted loading all of your content. For example, if you had 1000 articles, it would take a very long time to see the footer. This means that if you had important links in your Footer (like Privacy policy links etc), it’s almost unreachable.

Step 5 (Optional): Exposing Options to the User

Views Infinite Scroll allows you to expose settings to allow the user to control selected displays options. We will demonstrate by doing an example. In the Settings of your Views Infinite Scroll Pager, scroll to the “Expose Options” and check “Allow user to control the number of items displayed in this view”, then click on Apply and save your View.

This results in the following being added to the top of your View page:

This specific option will allow the user to select how many results are returned everytime they click on the “Load More” button.

Summary

Views Infinite Scroll is a neat module that allows you to add infinite scrolling behavior to your View. We have shown how you can use this module to achieve this infinite scrolling behavior and also demonstrated a few of its customizations along with one of it’s biggest pitfalls.

Editorial Team

About Editorial Team

Web development experts producing the best tutorials on the web. Want to join our team? Get paid to write tutorials.

Jun 23 2021
Jun 23
[embedded content]

Don’t forget to subscribe to our YouTube channel to stay up-to-date.

In Drupal, content is stored in the database. Views is a query builder that allows the user to extract content from the database and output it in various displays such as tables and lists. With Views, the user does not have to know or write any SQL queries. If you want to create a page or block in Drupal that lists any kind of content based on different filter criteria, you should use Views!

In this tutorial, we will explain what Drupal Views are and how to create it. We will also demonstrate some simple customizations such as page settings, filters, sorting, display options, exposed filters, permissions, creating a View Block and creating an admin page using Views. By the end of this tutorial, you will know how to create and customize a Drupal View.

Drupal Views Series

Table of Contents

Getting Started

As of Drupal 8, Views already comes packaged with Drupal core so there is no need to download anything. If you installed Drupal using the standard installation profile then it’ll be already installed.

Go to Extend and make sure Views and Views UI are installed.

How to Create a View

In this section, we will walk you through the process of creating a very simple View that lists  published Articles using the teaser view mode.

First, ensure you have enough article content on your website and ensure you are logged in as the administrator. Now let’s create the View.

1. Go to Structure -> Views (admin/structure/views) and click on “Add view”.

2. On the “Add view” page, fill out the fields as suggested in the screenshot below. All we are doing here is giving the view a name, selecting “Article” in View Settings and ticking the box “Create a page”. Every other field can be left as the default for now. Click on “Save and edit” when you are finished.

Views Creation Screen – Figure 1

And that’s it! You have successfully created your View. If you were to go to “/latest-articles” you can see the output of your View.

We will now explain the major parts of the Views configuration screen. We have highlighted different sections of the Views configuration screen in the screenshot below and labelled each section with a number for easier reference and explanation.

Views Config Screen – Figure 2

Label 1 – As the name suggests, this is the title of the View. This is the text that will appear as the title of the /latest-articles page.

Label 2 – This determines the output style of the view. Frontend themers can use this to style the output by overriding the default templates provided by Views. There are also contributed modules that can extend and provide more options such as Views Slideshow.

Label 3 – This determines how each row result of the View should be displayed. Currently it’s set to “Content” which allows us to choose different view modes like Teaser or Full Content. If you want to show just specific fields of your Articles, you can change it from “Content” to “Fields”. Then, you can select the fields you want to display in Views Config Screen Label 4.

Label 4 – Based on which Format style you choose above, this section will allow you to choose the specific fields to display.

Label 5 – This section allows you to define criteria for filtering your View results. Currently we are only showing published articles.

Label 6 – As the name suggests, we can define how to sort the View results. You can also sort on your content type fields by adding them here.

Label 7 – This is the path for your View page.

Label 8 – If you want to add your View page to any of your Drupal menus, this is where you can do it.

Label 9 – In this section you can define specific permissions for who is allowed to access your View.

Customizing your View

Let’s say we want to customize our current View to display a table layout with just Title and Body fields of the Article content type. But we also wanted to allow the user to input a text string that will filter the results against the Title. We will refer to the labelling in Figure 2 to help with our explanation.

1. Update the Format (Views Config Screen Label 2). Set it to Table. You can leave the default Table settings.

2. In doing Step 1, you may notice that Views automatically added the Title field in the Fields section (Label 4). Let’s add the Body field as well.

Click on “Add” in the Field section:

In the “Add fields” popup, search for “body” and click on “Add and configure fields”.

On the “Configure field: Content Body”, you can leave all the defaults and just click on Apply.

3. Now let’s demonstrate how to allow the user to enter text into a field that will automatically search against the Title field. In Drupal Views, this is called an “exposed filter”.

To create this exposed filter, click on “Add” in the Filter Criteria section (Label 5).

Then search for Title in the next screen and click on “Add and configure filter criteria”.

On the next screen, check the box “Expose this filter to visitors, to allow them to change it”. More options will automatically become available. Make sure to set the Operator to “Contains” and then click on “Apply”.

Tip: “Contains” means Views will use the string entered by the user and execute a SQL search in the database for any string that contains the characters entered in that order, i.e., “...LIKE %usertext%...” in SQL.

4. Now that we have set the Table Format, Title/Body fields and exposed filters, it’s time to save the View. This step can be easy to miss so don’t forget it!

Now if you view the actual View page, the View output should look like this:

Create Block using Views

A View Block is just a regular Drupal block except it originates from Views.

For demonstration purposes, let’s say we wanted to create a block version of the View page we created above.

There are two ways to do this. You can either click on “+Add” or click on “Duplicate as Block”. Both options are shown below:

Once you have done that you will notice you will now have “Block Settings” instead of “Page Settings”. This makes sense since now we are dealing with a Drupal Block.

Go ahead and save your View. Once the View is saved, a Drupal block is automatically generated and will be listed alongside all the other Drupal blocks.

Place the block anywhere in your Drupal site as you normally would place any Drupal block into a region. Here is a quick video of how to place a Drupal block into a region. We placed ours in the left sidebar and it looks like this:

You will notice our exposed filter is not being displayed in our Block. There is one extra step involved if you want to get exposed filters to work in View blocks. On the View configuration screen, inside of Advanced, set “Use AJAX” to yes and save your View. Here is how that looks:

Now our Views Block has the exposed filter which looks like this:

Create Admin Page using Views

Let’s say we wanted to use the View page we created above but place it within the admin UI and only accessible to a person with elevated permissions (in other words, not anonymous users). This is a screenshot of the end result we are trying to achieve:

There are a few things we need to edit in our existing View to achieve this. All of the changes we have to make will be in the Page Settings of our View config screen (See Figure 2). We need to update three things:

  1. Label 7 – Update the Path
  2. Label 8 – Update the Menu
  3. Label 9 – Update the Access Permission

1. Updating the Path: In the Views config screen, update the Path to “admin/content/latest-articles”.

2. Update the Menu: In the Views config screen, update the Menu. Clicking on “No menu” will take you to the Menu item entry config screen. On this screen, choose Menu Tab for Type, enter a Menu link title and set the Parent to “” and then click on Apply.

3. Update the Access: We can do this either by defining the Permission or by defining the role. For this tutorial, we will define the permission. In the Views config screen, click on “View published content” and change it to “Access the content overview page”.

4. Save your View!

Now if you go to “admin/content/latest-articles” as a logged in user, you should see your View page. If you tried going to this same page as an anonymous user you should get Access Denied.

Summary

In this tutorial, we introduced you to Views and some of its potential capabilities by providing some simple customizations. We specifically concentrated on demonstrating how to create a View Page and a View Block which list published Articles and also included a View exposed filter which allows the user to enter a text string to search against the Title. We also touched on how you can create an admin page using Views by updating its path, menu and permissions.

Views, which is in Drupal core as of version 8, is a very powerful tool and can be highly configured and customized. We hope we helped in getting you introduced to Views and the potential it has.

Editorial Team

About Editorial Team

Web development experts producing the best tutorials on the web. Want to join our team? Get paid to write tutorials.

Jun 19 2021
Jun 19

How do you enable that module for just the live site again?

Kaleem Clarkson

Let’s first start off with understanding what the Configuration Split module does. In simple terms, it allows you to have different site configurations for your different environments. For example, you want to turn off the Views UI module on your live site. Or you want to turn off your Google Analytics module on your local, dev, and test environments but still have it active on your live site.

There are so many great articles on setting up configuration split. Here are a few good ones that I suggest reading to get you caught up to speed.

In other words, say that you have already set up your config-splits a few months ago but now your client wants to add email support using the SMTP module but you only want this enabled on the live site so you don’t accidentally send out an email from your local site to 1000’s of users. ps — I have done it before Ouch :)

Well in order to add to the live configuration you need to enable the live config split. The natural first step is to go to the config-split UI and disable the develop configuration and enable the live config. Click Click Click. But nothing. Such a simple thing but why in the heck are you not able to enable the live configuration?

Ohhh snap, that settings.php file got me again.

One thing all of these tutorials have in common is that they show you how to set the active and inactive config-splits in your settings.php. For some servers, the code is slightly different but the idea here is that Drupal needs to somehow know what environment you are on in order to import the right configuration.

Yep! That darn settings.phpfile. The reason you cannot activate the live configuration settings in the UI is that the settings.phpfile overrides the UI click clicks. So you need to go to your file and either temporarily comment out that code or just reverse the logic. So here is what I do.

  1. Reverse the logic in the settings.php file. For me, I just have to switch out a ! in my code so that my dev and live environments are reversed.
  2. drush cr — Cache rules everything around me — Clear it
  3. drush cim Load all of your config from the live environment into your local
  4. Enable my new SMTP module.
  5. Edit the live config split and check the box next to the SMTP module
  6. drush cex — configuration export
  7. git checkout settings.php so that my file reverts back to my old settings
  8. drush cr— you know the drill clear that cache
  9. drush cimThis disables the SMTP module and loads just the development modules on your core
  10. git commit my changes

I then check my setting by doing a drush csim live. This command imports the settings from the live config. You can also check your config directories manually or with a git statusto ensure there are new files in both of your dev and live directories.

If any of you have a better way to enable and add some new configuration to the live environment without all of the steps, help a brother out and let me know in the comments.

Jun 18 2021
Jun 18

Drupal 7's end of life is scheduled for November 28, 2022. Up until then, the Drupal Security Team will continue to provide patches to Drupal 7 core and contributed projects should any security threats arise. After that point, however, the Drupal Security team will no longer support Drupal 7.

Is it Safe to Stay on Drupal 7?

If your organization is currently running Drupal 7, you’re faced with a decision on whether to upgrade to Drupal 9 or not.

Crafting a business case can help with your decision because it contains projections for initial costs and ongoing costs for making the upgrade investment vs. maintaining the status quo, as well as projections for revenue and savings. The business case exercise can further forecast the break-even point for your upgrade investment. However, in the case of future security threats, we can’t be confident of what the future ongoing costs will be, because we can’t predict when such security threats will arise, nor will we know the severity of them. 

What we can do, however, is make organizations that use Drupal aware of the risks of not upgrading. There are three general areas of risk: security, integrations, and functionality.

Security Risks

After Drupal 7 reaches the end of life, whenever security issues are identified in core or contributed modules, there won't be very much support to fix them. Site maintainers could find themselves in the position of having to spend a lot of time searching for security holes and fixing them. This risk gets compounded if there are a lot of contributed modules in your Drupal configuration. 

There will be a few agencies that will offer the service of maintaining your Drupal 7 platform post end-of-life. This will help greatly to secure your site if you’re willing to invest in hiring such an agency. One of their main tasks is to backport fixes for core and contrib issues. These fixes will of course not be included in the D7 upgrade path because there won’t be an upgrade path at all. As a point of reference, after Drupal 6 had reached its end of life, there weren't a disproportionate amount of security fixes needed for its core nor contributed modules. Still, the risk is not zero. Every aspect of a Drupal application must be considered to ensure there are no security gaps.

Another aspect of taking this path is that much of the time maintaining a site like this is spent managing and mitigating security risks rather than making improvements or implementing new features. For a good many developers, this is not rewarding work. 

In the history of previous Drupal security fixes, some have been pretty small -- one-line changes that take an hour to review and fix -- while others have taken days or even weeks of development time to analyze and produce a solution for. 

An advantage of choosing to upgrade a Drupal 7 site to Drupal 9 is that you gain all of the advantages of security improvements that were included in Drupal 8 and each subsequent feature upgrade. In this blog post, Peter Wolanin of Acquia details some significant security improvements included in the initial Drupal 8 release. Drupal 9 has additional advantages such as support for PHP 8.0.

Integration Risks

Certainly, security risks will come along, but another risk area in maintaining the status quo is that key integrations will eventually start to fail. For example, your Drupal environment may be integrated with another platform, and a key API on that platform is getting deprecated. Because the Drupal module that connects to it is no longer being actively maintained, you (or an agency you hire) will have to update the module or write a new custom module to keep integration working.

Functionality Risks

As the Drupal community continues to diminish the amount of activity on Drupal 7 core and contributed modules, especially after end-of-life, you basically lose those “free” updates. This is especially so with bug fixes. This forces you to either live with them or to fix them, or again, hire an agency to do it. If you do hire someone, that person won’t be as familiar with the project as one of the maintainers would be, so you’d have to factor in that additional investment. Indeed, some of these risks can be so critical that you end up rewriting large chunks of code to deal with them.

Not only do you miss out on the security improvements of Drupal 8/9 discussed above, not upgrading means you're missing out on many other improvements. Drupal 8 and 9 are built around a modern PHP stack including features such as Composer compatibility, Symfony components, modern OOP coding techniques, and more. While Drupal 7 has served our community well, it is not built upon the latest PHP libraries and development workflows that developers expect. This allows Drupal 8/9+ site owners the advantage of further enhancing their security posture by adding the Guardr security distro or module. While Drupal 8 and 9 have good security features, Guardr adds additional community vetted modules and settings which meet industry security requirements.

Talk To Us

As already mentioned, there are too many future unknowns to create a blanket business case for an upgrade investment. However, we can craft a business case specific to you based on the complexity of your existing Drupal 7 solution. We will factor in the number of modules you’re using, their complexity, the nature of your integrations with external systems, and more. We at Mediacurrent have performed this type of analysis for some of our clients to help them with their technology investment decisions and can do the same for you. Please contact us to learn more!

Jun 15 2021
Jun 15
[embedded content]

Don’t forget to subscribe to our YouTube channel to stay up-to-date.

When someone tweets a link from your website, Twitter can use Twitter Cards to attach rich photos, videos and media to Tweets.

By doing some minimal configuration changes on your Drupal site using the Metatag Module and the Twitter Cards submodule, users can see a “Card” added below the tweet that contains neatly formatted information coming from your website, as shown in Image 1 below.

Image 1 shows an example of a “Card”.

The cards are generated using HTML markup in the HEAD region of your Drupal site; that’s why the Metatag module is used.

Twitter will scrape your site and generate the card using the HTML meta tags.

Table of Contents

Twitter Cards

There are four variations of Twitter cards. They are:

  1. Summary Card – Displays Title, description, and thumbnail
  2. Summary Card with Large Image – As the name suggests, similar to Summary Card but with a larger image
  3. App Card – A Card with a direct download to a mobile app. Use this Card to drive app downloads
  4. Player Card – Displays video/audio/media.

Image 1 above shows a “Card” of type Summary with Large Image.

In this tutorial, we will look at the steps involved in setting up the “Summary Card with Large Image” Twitter Card.

Getting Started

The Metatag module has a dependency on the Token module. However, if you download and enable the Drupal module using Composer and Drush, the dependency is automatically taken care of as we will show you now.

Use composer to download the module:

composer require drupal/metatag

Once the Metatag module is downloaded using composer, the Token module, which is a dependency, will be downloaded automatically.

Then enable the “Metatag: Twitter Card” submodule:

drush en metatag_twitter_cards -y

The above Drush command will automatically enable the Metatag: Twitter Card submodule, Metatag module and Token module.

Finally, it is always a good idea to clear the cache after enabling Drupal modules:

drush cr

Configure Twitter Cards

By default, Twitter Cards can be added to any content type. We will now configure the Twitter Cards for the Article Content type.

1. Go to Configuration > Metatag (admin/config/search/metatag) and click on “Add default meta tags”.

2. On the next page, select “Article” (or whatever content type you want to configure) from the Type dropdown.

3. Then click on Save. This is required for the correct tokens to appear in the “Browse available tokens” window.

4. Edit the “Content: Article” configuration from the Metatag page.

5. Click on “Twitter cards” to expand the field set and then select “Summary Card with large image” from the Twitter card type dropdown.

6. Now, we have to add tokens into the correct fields. Click “Browse available tokens.” then click on Nodes.

NOTE: If you can’t see “Nodes”, this means you need to save the “default meta tag” option first then edit it again.

Fill in the following fields:

  • Description: [node:summary]
  • Site’s Twitter account: Add your twitter account, i.e., @webwashnet
  • Title: [node:title]
  • Page URL: [node:url]
  • Image URL: [node:field_image] (adjust the field name accordingly)
  • Image alternative text: [node:field_image:alt] (adjust the field name accordingly)

Find Image Field Token

For this type of Twitter card, an image field must exist in your content type. We will show you how to use Token to grab that image data. Click on “Browse available tokens”.

Then drill down by going to Nodes -> Image. This assumes you’re using the Image (field_image) field on the Article content type.

The token should be [node:field_image].

Once you have found the image entity URL, make sure your mouse focus is in the empty Image URL Twitter Card meta tag field, and then click on the image entity URL token value. This will copy/paste the token value into the Image URL field.

Find Image Field Token on Media Asset

If you’re using a media field instead of an image field for handling assets, then use the following token, [node:field_media:entity:thumbnail] (change the field_media name accordingly).

7. Configure any extra fields as needed, then scroll down and click on Save.

8. Once you have filled out the other Twitter Card fields with their respective token values, you should validate the end result markup using the Twitter Card Validator tool. We will now show you how to validate your Twitter card.

As you can see, Twitter successfully recognised our “Summary with large image” card and displayed the information correctly.

NOTE: You’ll need to make sure your website is publicly accessible for the validator tool to work.

View HTML Source

If you want to see the generated markup, view the HTML source on your Drupal site and look for the “twitter:*” meta tags.

Summary

Twitter can display a neatly formatted version of your website’s content whenever someone’s tweets a link to your content. There are various types of Twitter cards depending on your needs.

We have shown how you can use the Metatag module and Twitter Cards submodule to configure Drupal 8 to correctly send your website’s content to Twitter and how to validate your markup to ensure Twitter correctly parses your website content.

FAQ

Q: I changed the default meta tag configuration, but the tags are not changing?

Try clearing the site cache. Go to Configuration > Performance and click on “Clear all caches”.

Editorial Team

About Editorial Team

Web development experts producing the best tutorials on the web. Want to join our team? Get paid to write tutorials.

Jun 03 2021
Jun 03

Editor’s note: This the first post in a three-part Highlighting Accessibility series

In recent years, accessibility has become an essential factor for teams tasked with bringing new products, services, and experiences to market. The reason for this is clear: design works best when it works for everyone. Historically, though, either out of ignorance or intention, we have often designed with the assumption that all users are alike in their abilities to perceive and interact, but more and more we’re recognizing that just like food & nutrition, humans vary considerably in their preferences and restrictions. 

To be fair, it is much easier to assume that our users are largely homogeneous; that they not only share the same preferences and goals but also their ability to achieve those goals. As we learn more about the nature of human cognition and interaction, we come to appreciate how a whole host of physical, mental, and even social characteristics can influence the fundamental ways we perceive the world.

So what is accessibility?

Broadly speaking, accessibility describes the degree to which something can be entered, or used. Architects and civil engineers have long incorporated things like wheelchair ramps, motion- or button-activated doors as ways to improve accessibility in the physical world; businesses often offer telecommunications devices for the deaf (TDD) capabilities for sales/customer services phone lines; car retailers offer vehicle modifications to make them wheelchair accessible and operable by persons with a whole range of physical disabilities. All of these enhancements are the result of the painstaking work by affected groups and their advocates toward gradual recognition of and empathy toward (and laws protecting) the varying needs of all human beings. 

“The digital world has changed so many of our lives for the better and it’s crucial to make sure the same can be true for everyone.”

Troy Shields, Sr Front End Engineer, Zivtech

In the digital world, these enhancements are defined by the Web Content Accessibility Guidelines (WCAG), put forth by the World Wide Web Consortium’s (W3C) Web Accessibility Initiative (WAI). As one of the foremost advocates for the needs of all users, the WCAG and related guidelines serve as a north star for organizations and project teams looking to justly serve users of all abilities. Indeed, the guidelines are extensive and cover a wide range of topics and best practices, but the best place to start to familiarize yourself with accessibility is via their four principles:

Principle of Accessibility #1 Perceivable

1. Perceivable

Information and user interface components must be presentable to users in ways they can perceive.

Naturally, this is a given for any interfaces we create, but it’s easy to overlook how the nature of perceivability varies by ability. For low vision users, a simple thing like an icon, button, or image may not be perceivable at all. In this and similar scenarios, designers and builders need to account for this impairment with consistent use of alt text and other modifications. Now, think of a chart or infographic, how much more difficult might it be for a low-vision user to consume that information?

Principle of Accessibility #2 Operable

2. Operable

User interface components and navigation must be operable.

Once we’ve made our user interface fully perceivable, we must then ensure interactive elements are usable. This can be really challenging as there are so many adaptations that some of our users need to make in order to interact with the physical and digital world, most of which we take for granted. Users with visual impairments may have a hard time discerning and using things like mouse-over menus, confusing or unlabeled buttons, and the like. Moreover, users with physical disabilities may have a hard time completing form elements where multiple simultaneous maneuvers are required, eg CTRL + click.

Principle of Accessibility #3 Understandable

3. Understandable

Information and the operation of user interface must be understandable.

Understandable design creates and maintains consistent conventions that help users anticipate how the interface will perform as they progress through their journeys. It’s predictable in its use of design patterns and information architecture. Amazon sells a wide range of products, but its layout for books is the same as it is for sporting goods, as it is for clothing. Imagine if every product or product category had a unique layout - how challenging might that be for a user to anticipate where they might find the product specs or customer reviews?

Principle of Accessibility #4 Robust

4. Robust

Content must be robust enough that it can be interpreted reliably by a wide variety of user agents, including assistive technologies.

As the movement to accommodate people of different abilities has taken steam, so has the development of assistive technologies to help them. Today, there is a wide range of tools and devices that are designed to deliver improved user experiences for users with a wide range of physical abilities. Unfortunately, these assistive technologies do not all perform the same, so designers and builders must work to deliver a consistent experience. Consider web browsers like Chrome, Firefox, and Internet Explorers. All of these tools are built around standardized languages and frameworks like HTML (hypertext markup language) yet they all perform slightly differently. Imagine how broad the discrepancies might be for tools that aren’t based on any real widely accepted standards.

Principle of Accessibility BONUS: Robust

BONUS: Receptive

Interfaces should provide ways for users to provide feedback on their experience 

We humbly offer this as a fifth principle for your consideration. In the spirit of continuous improvement, we should always be looking to enhance the experiences we create, and that often starts by capturing feedback and learning from those we serve. Even with many hours of accessibility training, and several successful projects under our belt, our team recognizes that we can always get better at delivering exceptional experiences. We should all strive to be open to learning and feedback, and more consistent in our willingness to apply what we learn.

...

Overall, the WCAG Accessibility Principles seek to inspire empathy in designers and builders who are committed to creating digital experiences that work for all. They help establish internal project standards that are more thoughtful, curious, and ultimately more inclusive. The principles should help organizations and project teams factor accessibility in at the start of the project instead of just running some tests at the end. Indeed, accessibility is best executed when it’s built-in to the core processes of how we work, standardizing up-front approaches for how we approach elements like navigation and information architecture, being consistent with the use of interactive elements, and so on. 
 

"Accessibility should not be an afterthought, it should be an integral part of your design strategy right from the start. "

Barry Brooks, Creative Director, Zivtech

Indeed, delivering truly accessible experiences requires additional effort and forethought to achieve, but it’s absolutely worth it. When we enable more of our users to succeed in their journey, we succeed as well. 

Jun 01 2021
Jun 01

Are you still on Drupal 7 or 8?

All software, even that of Drupal’s top world ranking open source community, comes with a shelf life.

Drupal 7 is now a decade old, with the advent of Drupal 8 falling just four years behind. These previous major Drupal versions weren’t left in the dust with the release of Drupal 9 in the summer of 2020. But that support has an expiration date coming soon. Both versions 7 and 8 have set “End of Life” dates which means they will no longer be supported by the official Drupal community.

Version 9: Drupal in its Prime

Organizations are moving to Drupal 9 to reap the benefits of fresh features and community-supported innovation. The pace of adoption is faster than ever. It took one month to go from 0 to 60,000 sites on Drupal 9 compared to taking 7 months to get 60,000 sites on Drupal 7. Although good progress is being made with organizations moving to Drupal 9, there are still thousands of Drupal 7 and 8 sites live. If you have a Drupal 7 or 8 site, you need to start planning immediately to ensure you are prepared for support ending.

So, what is Drupal 7 and 8 End of Life?

End of Life marks the date when the Drupal community officially stops supporting older versions of Drupal. The Drupal community has always supported the current and previous versions of Drupal but with the launch of Drupal 9 last year and Drupal 10 scheduled for June 2022, “End of Life” is quickly approaching for Drupal 8 and Drupal 7’s days are numbered as well.

key dates for drupal 7 and 8

State of Drupal presentation (April 2021)

It might come as a surprise (and seem a little odd) that Drupal 8’s End of Life occurs before Drupal 7’s. There are a couple reasons behind this. First, the transition from Drupal 8 to Drupal 9 is not a significant effort in most cases. Drupal 9 is not a reinvention of Drupal, with only two key differences; updated dependencies and deprecating APIs. The Drupal Association illustrates the transition from Drupal 8 to 9 as just a station on the same track (versus moving the train to a different track entirely for previous upgrades). The other reason is Drupal 8 is dependent on Symfony 3 and Symfony 3’s end of life is November 2021.

drupal upgrade train track illustration

Source: Understanding How Drupal 9 Was Made, Drupal.org

For Drupal 7, the original end of life was set for November 2021 but due to the impact COVID-19 had on many organizations who are still on Drupal 7, no dependencies on Symfony 3, and the effort needed to upgrade from Drupal 7 to Drupal 9 (requiring a migration and site rebuild), the date was pushed out a year.

How does this impact you?

Drupal is an Open Source project with a uniquely robust security model:

  • Drupal has a dedicated team of Security professionals who proactively review core and contributed modules for vulnerabilities.
  • When a security vulnerability is identified, the Drupal Security Team is notified and code is quickly fixed to remove the vulnerability.
  • When a fix is available an announcement immediately goes out and a patch is released to the community. Drupal sites are also automatically notified that they need to upgrade.

When Drupal 7 and 8 support ends, there will be no more Drupal core updates to Drupal 7 and 8 - even for critical security issues. The contributed modules that power your site will also no longer be actively tested and reviewed, patches and security evaluation will depend on your internal resources.

A recent study indicates that nearly 12 million websites are currently hacked or infected. Ensuring you correctly handle the security implications of Drupal 7 and 8’s End of Life is essential.

What do YOU need to do?

Without taking active steps to protect your website, you are going to be vulnerable to a security breach. Drupal 7 and 8 are widely-used content management systems that have served as a platform for some of the world’s largest websites. It is public knowledge that support for it will be ending. It’s likely that hacking groups are waiting for official support to end to use security exploits that they have already discovered to increase the number of systems they can access before they're patched.

Mitigating this risk is much easier with an experienced partner. We advise our clients to take the following steps:

  1. Ensure your website will be secure after Community Support ends. You can do this by developing an internal plan to monitor future Drupal 7 or 8 security releases, or engaging with your Drupal hosting provider and agency to cover you while you plan and execute the move off of Drupal 7 or 8.
  2. If you’re on Drupal 7 or 8, it’s likely that the time is now for a reassessment of how you use the web. Partnering with an expert Drupal agency like Mediacurrent will help you to reassess your website plans, determine if your Digital Strategy is effective, and ensure your next platform serves your needs now and can adapt in the future.
  3. Once you have identified the correct platform, plan and execute your migration. By taking care of security first, and securing the right partner, you can take the time to correctly plan and build your next Digital Platform in Drupal.

Learn to love the upgrade

While Drupal 7 and 8 End of Life might mean more work for you, we view it as an opportunity. The way we consume information on the web has changed drastically since Drupal 7 and 8 launched, and if you are still on these versions and not planning on innovating, you are likely putting yourself at a serious competitive disadvantage.

In the longer term, sticking with Drupal 7 or 8 not only means you will be fighting a constant battle against security vulnerabilities, but also that you will be doing so with a dwindling number of allies. As time goes on, Drupal 7 and 8 sites will disappear. Fewer agencies will offer any sort of Drupal support for these versions. The talent pool of developers will dry up - anyone who learns Drupal today will be learning on newer releases.

Upgrading from Drupal 7 or 8 to Drupal 9 is the opportunity to revolutionize the way you think about the web as a business tool. If you have a Drupal 7 or 8 site, you have almost certainly had it for at least five years. How many little usability improvements have you considered in that time? Is your design dated? Does your site build reflect modern practices in SEO (Search Engine Optimization), accessibility, and user experience?

With Drupal 9, Upgrading is about more than just security

Out of the box, Drupal 9 offers a significantly more powerful feature set that allows you to build the modern digital experiences you need to compete on today’s web.

At this time, no new features are being added to Drupal 7 or 8. All the innovation is happening in Drupal 9!

Look at Drupal 9’s core features:

All the best of Drupal 8 - Drupal 8 came with many new features such as an improved authoring experience with Layout Builder, an API-first architecture that opens the door to a decoupled CMS, TWIG templating engine for improved design capabilities, and built-in web integrations to name a few. All of these features are carried over to Drupal 9.

Intuitive tools - Improving Drupal’s ease-of-use remains a top priority. Easy out of the box, a new front-end theme, and automatic updates are among the strategic initiatives for Drupal core.

Future upgrades - Upgrades will be seamless for future releases. You will no longer be forced to replatform as new versions are released.

Stay on the edge of innovation - Adopting Drupal 9 will give you access to the latest new feature releases, happening twice a year.

Powerful Distributions - If you’re planning a Drupal 9 project, you don’t have to start with a blank slate. Drupal distributions like Rain CMS can be used as the “starter” for your next Drupal project.

Prepare for an upgrade with a Drupal 9 Audit

Upgrading can certainly come with challenges. As you start planning for an upgrade, a good starting point is performing a readiness audit. An audit assesses the level of effort and provides recommendations for a smooth migration path to Drupal 9.

For more information on our Drupal 9 Readiness Audit, or to start the discussion about transitioning to Drupal 9, please visit our contact page or chat with us right now (see bottom right corner of the page). We would be happy to talk more about your project.

May 31 2021
May 31
[embedded content]

Don’t forget to subscribe to our YouTube channel to stay up-to-date.

Drupal comes with a toolbar which is useful when administering a Drupal site. If you log in and have the correct permissions, you’ll see a toolbar across the top of the page that allows you to access back-end configuration pages.

The Admin Toolbar module extends the functionality of the toolbar and gives you lots of extra features such as drop-down menus, access to cache and cron settings and an autocomplete search.

In this tutorial, you will learn how to install and configure Admin Toolbar and its sub-modules.

Table of Contents

Getting Started

Let’s begin by downloading the Admin Toolbar module.

Run the following Composer command:

composer require drupal/admin_toolbar

Then go to Extend and install Admin Toolbar and its three sub-modules.

Functionality around the toolbar is spread across four modules in total. Here’s a breakdown of what each module does.

Admin Toolbar

Provides an improved drop-down menu interface to the site toolbar.

Admin Toolbar Extra Tools

Adds menu links like Flush cache, Run Cron, Run updates, and Logout under the Drupal icon

Admin Toolbar Links Access Filter

Provides a workaround for the common problem that users with ‘Use the administration pages and help’ permission see menu links they don’t have access permission for. Once the issue https://www.drupal.org/node/296693 be solved, this module will be deprecated.

Admin Toolbar Search

Provides quick search functionality for configuration pages.

Let’s take a look at each module in more detail.

This module is the base module of Admin Toolbar. After installation, it provides drop-down functionality on top of the standard toolbar.

There is a new version 3.0.0 released recently, which requires Drupal 8.8 or above. With this version, a new configuration form was introduced to limit the number of bundles to display in the drop-down menu, resulting in performance issues.

To configure this new mechanism, go to:

Admin > Configuration > User interface > Admin Toolbar Tools

The default value is 20, but can be modified here. Just pay attention to the warning on this page which says ‘Loading a large number of items can cause performance issues.’. We can leave it 20 by default to start with.

This sub-module adds extra drop-down functionality to the base module by providing the following additional functions:

  • Additional menu items are available in the drop-down functionality
  • An extra Drupal logo icon will be attached to the left corner of the Admin Toolbar, which provides additional functions in a convenient manner:
  • Index – provides a list of functions indexed in alphabetical order
  • Flush all caches – flush all caches, or individual caches of the system.
  • Run cron – run a cron job immediately, instead of waiting for the default time period of 3 hours.
  • Run update – run a system update process, generally after system or module updates.
  • Logout – provide fast access to the logout function.

This sub-module offers a workaround for users which have the ‘Use the administration pages and help’ permission but not access to the specific pages. Menu items are still visible even if the user doesn’t have access.

Once https://www.drupal.org/node/296693 is fixed this module will be deprecated.

This sub-module doesn’t require any configuration, just install and you’re done.

An ‘Admin toolbar quick search’ box is provided on the Admin Toolbar. This is useful for beginners, site builders or administrators who are not familiar with Drupal. They can find the functions they are looking for, administrative or configuration pages by searching here.

Summary

Admin Toolbar is a must-have module on any Drupal site. It gives site administrators and builders a better user experience when managing content and configuration.

I especially like the quick search functionality offered by “Admin Toolbar Search”. This makes it easy to search for configuration pages.

Editorial Team

About Editorial Team

Web development experts producing the best tutorials on the web. Want to join our team? Get paid to write tutorials.

May 18 2021
May 18

php code on a laptop screen

To keep your organization at the forefront of open source security and innovation now's the time for a Drupal upgrade or migration to Drupal 9. Drupal 7’s end-of-life is November 2022, but if you’re currently on Drupal 8 the end-of-life hits in November 2021.

In this guide, we’ll cover Mediacurrent’s tried and tested approach to upgrading sites of all sizes. Kick-off with a codebase audit. Then, tackle code and compatibility issues. In the final mile, run a first-attempt upgrade to find and fix any remaining issues. And finally, the actual Drupal 9 upgrade.

Introduction

As you think about your upgrade path (whether moving from Drupal 7 or 8), a good starting point in preparing for Drupal 9 is performing a readiness audit. An audit will assess the level of effort and provide recommendations and preparations for a smooth upgrade or migration path to Drupal 9.

At a high level, a Drupal 9 upgrade process would look like this:

  1. Audit the codebase for deprecated code

  2. Audit the codebase for composer compatibility

  3. Fix deprecated code issues

  4. Fix composer compatibility issues

  5. Attempt Drupal 9 upgrade and see what’s left

  6. Perform actual Drupal 9 upgrade

In the first blog post of this Drupal 9 Upgrade series, I will focus on the first two steps and show you how to audit a codebase for Drupal 9 readiness. By the end, you will have a better understanding of the process and level of effort required for a successful upgrade and be more prepared to estimate a budget and timeline.

Audit for Drupal 9 Readiness

Performing an initial audit on the codebase is straightforward. This process should result in tickets in your task management system of updates to be performed way before the actual Drupal 9 upgrade release date.

Scan for deprecated code

Drupal-check is an invaluable tool for scanning files in a codebase to check their Drupal 9 readiness by looking for deprecated code -- basically code that was previously lingering around in Drupal 8 but is now removed from Drupal 9.

If drupal-check helps you during this process, and I’m sure it will, consider sponsoring the ongoing development and improvements of the project.

Install drupal-check

The most typical way to install drupal-check is to install it as part of the project via composer as a dev requirement. Be sure to review the drupal-check installation documentation.

composer require --dev mglaman/drupal-check

Run drupal-check

The drupal-check command can be run on any single file or directory. These steps assume it was installed in the project with composer, therefore the executable exists in the “vendor” folder and can be run as follows.

Here is an example of running the command against a contributed module that contains some deprecated code issues:

vendor/bin/drupal-check docroot/modules/contrib/allowed_formats

drupal-check error report

Now would be a good time to create a task in your task management system for addressing that deprecated code issue. Thankfully a solution already exists for the Allowed Formats contributed module that fixes this one particular issue.

That issue and fix were found by visiting the module’s project page that you are working on making Drupal 9 ready, search for “drupal 9” in the issue search box, and review what Drupal 9 related issues exist.

Allowed Formats module drupal 9 issue search

There is typically an issue labeled “Drupal 9 Deprecated Code Report”, but it may be named something else, and there may also be multiple related issues.

Allowed Formats module Drupal 9 issue list

Here is another run of drupal-check against another contributed module, which in this case, has no deprecated code issues.

vendor/bin/drupal-check docroot/modules/contrib/crop

drupal-check success report

While it appears at this time that this module is Drupal 9 ready per the drupal-check tests, it may not be completely Drupal 9 ready yet. In the next section, we’ll look at ways to check composer compatibility, which once the module is both composer compatible and no code deprecations present, it will be in great shape for the Drupal 9 upgrade.

Good, but not perfect

The drupal-check tool is very helpful, but it is not perfect. Again, consider sponsoring the project to help continue future development and improvements!

One of the false positives drupal-check may report relates to class usage. For example, it may be validating a class that is used by a module that no longer exists in the codebase, e.g. old code from a Drupal 7 migration that’s no longer used, so there’s nothing to do about that.

Also, sometimes drupal-check does not catch certain issues. For example, the codebase had a custom module that still contained a call to the `path.alias_manager` service, but that service is no longer available in Drupal 9 and was moved to `path_alias.manager`. However, drupal-check did not report this as an issue - I only found out about this issue once the Drupal 9 site was built and I tried to access the page that was controlled by the code that contained that old, removed service class call.

An alternative to drupal-check is to use the contributed module, Upgrade Status, to check on the Drupal 9 readiness of your existing site.

You should now have a good understanding of what custom and contributed packages need work to make them Drupal 9 ready. Be sure to keep notes or skip to the Issue Tracking section below.

Check composer compatibility

In addition to the deprecated code issues, the codebase also needs to be compatible with Drupal 9 from a composer perspective. Without packages being Drupal 9 supported in composer, composer will simply not allow the codebase to upgrade to Drupal 9.

What’s Not D9 Compatible?

A quick test you can do right away is to run this command, which will list all packages that are only supported by Drupal 8. These will need to be updated to also support Drupal 9.

composer why drupal/core | grep -Ev "\^9"

Essentially, this command tells us which other packages depend on Drupal core that do not yet have a 9 version in its composer metadata. Composer will not allow a Drupal 9 upgrade. Read more about the Composer Why command.

The output of the command will look something like the following:

Composer compatibility check results

These values come from the composer.lock file and are basically the list of packages used in the codebase that depend on drupal/core, specifically packages that only work with Drupal 8. This should be pretty much all of the themes, modules, and profiles, unless they have been kept updated on a regular basis and when security releases are available and necessary.

Just to be clear, the first lines that start with “drupal/core” can be ignored, the only ones to focus on are the other lines that reference contributed (or custom) modules.

For instance, in the example above the Facets module has a current version of “1.4.0”, or 8.x-1.4. This module will need to be updated to a later version, or a patch added that makes it Drupal 9 compliant; it might also be worth testing the current dev snapshot, the necessary fixes might have been committed, just not available as a full release yet. It appears for Facets module, the 8.x-1.5 version adds the Drupal 9 support.

Results in this output should be added as new tickets in the ticket management system of packages needing updates to address the deprecated code and composer compatibility issues.

Issue Tracking

To track the status of packages and their Drupal 9 readiness, I recommend creating a spreadsheet that helps track the ongoing upgrade process and what needs to be done. The below is just a small subset of changes needed, but I do recommend having multiple rows per package, in the cases where there may be multiple Drupal.org issues to cover all the D9 related fixes you’ll need.

Without getting too deep into it right now (saving for the next blog post), I’ve seen deprecated code issues be addressed in one Drupal.org issue, and the fix was committed to the latest version. But simply updating to the latest version did not make it Drupal 9 ready, because there were still composer compatibility fixes, and in some more rare cases, even still some deprecated code issues that were missed in the first pass. So, those issues may be split among multiple issues on Drupal.org.

Tracking Drupal 9 issues in spreadsheet

This planning, tracking, and documentation will help you as you continue through the Drupal 9 Upgrade process and keep tabs on what is remaining along the way. It may also serve as a good starting point or baseline for the next Drupal 9 upgrade process you may be involved in.

Conclusion

This blog post focused on the up-front audit process and preparation work required to understand the amount of work required to get into Drupal 9 readiness status. In the next blog post in this Drupal 9 Upgrade series, we will work on fixing the deprecated code and composer compatibility issues we discovered and documented as a result of this audit process.

Mediacurrent is a top 10 contributor on Drupal.org and has created solutions to accelerate, ease, and enhance the upgrade process. We can help you prepare for a Drupal 9 upgrade. Reach out anytime if you want to discuss your Drupal upgrade path or are interested in our team performing a Drupal 9 audit on your site and how we can help you succeed.

May 18 2021
May 18
[embedded content]

Don’t forget to subscribe to our YouTube channel to stay up-to-date.

Creating a block using views is pretty straightforward. You could create a block to display a list of published articles or ones that have been promoted to the front page. Then you can add that block into any theme region.

But you may encounter a situation where you no longer have any articles which are published and then you end up with an empty block.

Views comes with a feature that allows you to hide a block if no results are returned and this is what will be covered in this tutorial.

Table of Contents

Getting Started with a Simple Example

We need to display a block that lists all articles that have been promoted to the front page. This can easily be achieved by using a custom views block

The views configuration will look something similar to the following:

This is a block created from views, and we can place the block on the sidebar, like the following:

The criteria of the views setting is based on some articles having the ‘Promoted to front page’ option checked.

The Problem

However, sometimes articles may not be promoted at all.  As a result, there are no results returned from the views setup above, and the block will look like this:

How to Fix It

To avoid this situation, we can choose to Hide the Block when no results are returned.  In fact, there is an option of ‘Hide block if the view output is empty’ at the bottom corner of the views setting, which a lot of people might easily overlook.

Simply enable this option, and it is done.

With this option enabled, the block will disappear when the view returns no results, like the image below:

Summary

This ‘Hide block if the view output is empty’ option is actually one which is very useful, but it can be easily overlooked.

Editorial Team

About Editorial Team

Web development experts producing the best tutorials on the web. Want to join our team? Get paid to write tutorials.

May 14 2021
May 14

When you are used to working in Drupal 8 and beyond, having to make changes to custom Drupal 7 code can be unpleasant. If you’re lucky, the code was well written and maintained and you can make your changes without feeling like you’re adding to a house of cards. Too often, though, the code is in a state where it could really use refactoring.

One of the many nice changes Drupal 8 brought about was changing most of the code over to object-oriented programming, or OOP. There are many benefits to this and one of them is that it organizes most of the code into classes. In Drupal 7, all that code was dumped into the .module files because that’s how things were done back then. But it doesn’t need to be that way.

Why Add OOP?

Drupal 7 may not have the OOP framework that Drupal 8 built, and you still need the hooks, but there are benefits to adding OOP to your refactor:

  • Upgrades - It gets your custom code closer to Drupal 8/9. If there is any thought of an upgrade in the site’s future, having the custom modules as close to Drupal 8/9 as possible will make that upgrade easier.
  • Clean Code - It makes your Drupal 7 code cleaner and easier to maintain. Even if an upgrade is a long way off, having clean and organized code is much easier to maintain and reduces the chance of knocking down that house of cards when you need to make a change.
  • Easier Refactoring - It makes refactoring easier because you can work on a copy of the code that is moved to a new place rather than trying to do everything in place. As you move and refactor each function, you can easily see what code is refactored and what is still the old code.
  • Testing - It makes it easier to test your refactored code. There’s more on that in the “Testing the refactoring” section below. If you are following along with this blog post and making changes to your module as you go, you’ll want to read that section before you start.

An Example Module

For the purpose of examples, let’s say we are refactoring a custom module called XYZ Events. Our site is for company XYZ and this module is where we stored all the custom functionality related to our events.

This module has custom menu items, blocks, and a bunch of miscellaneous helper functions all sitting in the .module file and we want to clean that up.

I’ll reference this fictional module to provide examples along the way.

Make class loading simple

To make using classes much easier, start with a very handy contributed module: X Autoload. X Autoload lets you make use of the automagic class loading that Drupal 8 has just by putting your classes in the proper directories and setting the namespace. With that in place, you are ready to start moving your code into classes.

Whenever you add a new class, be sure to clear the cache before you try to use it.

Services for all the miscellaneous functions

While hooks and a few other things need to stay in the .module file, chances are there are a lot of miscellaneous functions that can be organized into one or more service classes. These won’t be true D8/9 services with the service.yml and all of that but they serve the same purpose. In theory, you could write your own service container if you wanted to push this even further but even just regular classes help.

Make the events service:

  • Add the directory “src” to the root of the xyz_events directory.
  • In there, add EventsService.php. It’s not required to have “Service” in the name but it helps make the purpose clear.
  • The basic outline of the class looks like this:

Move the code:

For each of the non-hook, non-callback functions in the .module file (and .inc files), copy it into the appropriate class. Some functions might make more sense in a site-wide utility class if they aren’t directly related to the module’s “theme”. Once it’s in its new home, do the cleanup and refactoring:

  • Change the function names to camel case and remove the module name (ie: xyz_events_get_event_list() becomes getEventList())
  • Add the public, protected, or private designation to the front. Since these used to be in a .module file, most of them are likely to be public. But, if any functions are only used by other functions that are now in the same class, those could be changed to protected or private.
  • Now is a good time to clean up any coding standards issues. I like to use Drupal 8/9’s standards if I know I’m on a PHP version that supports it such as using short array syntax. This gets it as close to D8/9 as possible.
  • Do whatever refactoring is needed to make the code easier to follow, improve performance, fix bugs, etc.

Update calls:

Using grep, check your whole site to find out all the places where that function was being called. For any place it’s being called that isn’t already in the class, change the call from the old function to the new method:

  • Add $events_service = new EventsService(); if that isn’t already in scope.
  • Change xyz_events_get_event_list() to $events_service->getEventList()

If the call is within the class already, change it to use “$this” instead of the service reference variable:

  • xyz_events_get_event_list() to $this->getEventList()

You now have all the miscellaneous custom code in a service (or multiple services if it makes sense to divvy them up). When moving to Drupal 8/9, all that’s needed is to update the class so that it’s a proper service container service and then change the calls to go through the container rather than using “new SomeClass()”.

Block classes

Drupal 8 introduced blocks as classes which is much cleaner than the old style that used multiple hooks. If you have multiple custom blocks each with a chunk of code, hook_block_view() can get quite long and hard to follow. While the hooks themselves are still needed, the actual code can be split off into classes. hook_block_info() stays the same but hook_block_view() becomes much simpler. 

  • If you haven’t already, add a directory “src” at the root of the module directory.
  • In “src” add a directory structure “Plugin/Block”.
  • For each block in hook_block_view():
    • Add a file in “Block” that is BlockNameBlock.php. Like services, the “Block” at the end isn’t required but makes it clearer what the class does. For our example module, we end up with UpcomingEventsBlock.php and FeaturedEventsBlock.php.
    • Take all the code for generating that block out of the hook and put it in the class.
    • Replace the content in the hook with a call to the class.
  • If your blocks have a lot of similar functionality, you can take advantage of inheritance and move the common functionality into a base block. In our case, since both blocks are listing events, we add EventListingBlockBase.php.

In the .module file we have:

/**
 * Implements hook_block_info().
 */
function xyz_events_block_info() {
  $blocks = [];

  $blocks['upcoming'] = [
    'info' => t('Show upcoming events'),
  ];

  $blocks['featured'] = [
    'info' => t('Show featured events'),
  ];

  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function xyz_events_block_view($delta = '') {
  $block = [];

  switch ($delta) {
    case 'upcoming':
      $block_object = new UpcomingEventsBlock();
      $block = $block_object->build();
      break;

    case 'featured':
      $block_object = new FeaturedEventsBlock();
      $block = $block_object->build();
      break;
  }

  return $block;
}

And then our blocks:

EventListingBlockBase.php

EventsService = new EventsService();
  }

  /**
   * Builds the content for the block.
   */
  abstract public function build();
  
  /**
   * Format the content into the array needed for the block.
   *
   * @param string $title
   *   The block title.
   * @param array $items
   *   The complete list of items.
   * @param string $empty
   *   The text to print if there are no items.
   * @param string $theme_hook
   *   The theme hook for the block content.
   *
   * @return array
   *   The block content array.
   */
  protected function formatContent(string $title, array $items, string $empty, string $theme_hook) {
    // Only keep the empty text if there are no items.
    $empty = (count($items) == 0) ? $empty : '';

    $variables = [
      'items' => $items,
      'empty' => $empty,
    ];

    $content = [
      'subject' => $title,
      'content' => theme($theme_hook, $variables),
    ];

    return $content;
  }

}

UpcomingEventsBlock.php and FeaturedEventsBlock.php both use the following code, just altering the “upcoming” to “featured” as appropriate.

EventsService->getEventList('upcoming')

    // What it should print if there aren't any.
    $empty = t('There are no upcoming events.');

    // The theme hook to use to format the contents of the block.
    $theme_hook = 'xyz_events_upcoming_events';

    return $this->formatContent($title, $items, $empty, $theme_hook);
  }

}

Now all the content for building each block is encapsulated in the class for that block. When moving to Drupal 8/9, add the block annotation that it uses to identify blocks and remove the block-related hooks from the .module file.

If your blocks need configuration, this can be taken a step further by adding the form code and save code as methods on the block class and then referencing those from hook_block_configure() and hook_block_save().

Menu items to controllers

While hook_menu itself usually doesn’t get too overwhelming due to the actual code for the menu items being in separate functions, it does contribute to the .module file bloat. It’s also a lot nicer to have the menu items be in individual controllers like in Drupal 8/9.

To make this happen:

  • If you haven’t already, add a “src” directory at the root of your module.
  • Add a “Controller” directory under that.
  • For each menu item, add a file in there that is SomeController.php. Like services, “Controller” isn’t required but it makes it clearer. Another option is to use “Page” if the item corresponds to a viewable page rather than an API callback. For our example module, we end up with “UpcomingEventsController.php” and “FeaturedEventsController.php”.
  • As with blocks, a base controller can be used if the controllers have similar code.
  • Replace the hook code with a reference to the class (explained below).

There are two ways that the hook_menu() code can reference your class. Using a static function on the class and calling it directly or using a wrapper function to call the object.

Static method:

  • In hook_menu:
    'page callback' => 'UpcomingEventsController::build',
  • The build method on the class needs to be static.

Wrapper method:

  • In hook_menu:
    'page callback' => 'xyz_events_controller_callback',
    'page arguments' => ['controller_class' => 'UpcomingEventsCoursesPage'],
  • function xyz_events_controller_callback() needs to be in the .module file. (see below)
  • The build method on the class does not need to be static as we are instantiating an object.

In the .module file:

/**
 * Implements hook_menu().
 */
function xyz_events_menu() {
  $items = [];

  $items['events/upcoming'] = [
    'title' => 'Upcoming events',
    'page callback' => 'xyz_events_controller_callback',
    'page arguments' => ['controller_class' => 'UpcomingEventsController'],
    'type' => MENU_NORMAL_ITEM,
  ];

  $items['events/featured'] = [
    'title' => 'Featured events',
    'page callback' => 'xyz_events_controller_callback',
    'page arguments' => ['controller_class' => 'FeaturedEventsController'],
    'type' => MENU_NORMAL_ITEM,
  ];

  return $items;
}

/**
 * Menu callback that wraps the controllers.
 */
function xyz_events_controller_callback($controller_class) {
  $controller_class = "\\Drupal\\xyz_events\\Controller\\$controller_class";
  $controller = new $controller_class();
  return $controller->build();
}

The classes:

EventListingControllerBase.php

eventsService = new EventsService();
  }

  /**
   * Builds the content for the page.
   */
  abstract public function build();
  
}

UpcomingEventsController.php and FeaturedEventsController.php have the same code with “upcoming” changed to “featured” as needed.

eventsService->getEventList('upcoming');

    $content = theme('xyz_events_upcoming_events', ['items' => $items]);
    return ['#markup' => $content];
  }

}

The rest of the hooks

While Drupal 7 relies on a lot of hooks and these need to be in a .module or .inc file so they can be found, there’s nothing requiring the actual code for the hooks to live in the functions. Like we did with blocks and menu items, the hook functions can serve as a wrapper around a call to a class where the actual code lives.

Testing the refactoring

While writing actual tests is the best way to test, that isn’t always possible with time and budget considerations. Still, you want to be sure your refactored code gets you the same results as the old code. Moving functions into classes while refactoring helps with that.

  • Add an include file to the root of the module. Ex: xyz_events_replaced_functions.inc
  • At the top of the .module file, add include_once 'xyz_events_replaced_functions.inc';
  • As you move functions into the classes, copy them into this file instead of deleting them from the .module file.

This keeps all the old functions active at the same time as the new ones which lets you test them in parallel within the same site.

Add this to the top of the module file:

/**
 * Implements hook_menu().
 */
function xyz_events_menu() {
  // Adds a testing page for dev use.
  $items['admin/code-test'] = array(
    'access arguments'  => array('administer content'),
    'description'       => 'Place to test code.',
    'page callback'     => xyz_events_test_code',
    'title'             => 'Code testing',
  );

  return $items;
}

/**
 * Place to put test code that is called from admin/code-test.
 */
function xyz_events_test_code() {
  print("Test completed.");
}


Within xyz_events_test_code() you can do something like this:

Within xyz_events_test_code() you can do something like this:

$events_service = new EventsService();
$old_list = xyz_events_get_event_list();
$new_list = $events_service->getEventList();

Set a breakpoint at the top of the function and then visit /admin/code-test on the site. You can then step through and compare what you get running the original function vs running your refactored function and make sure the result is either the same or has any differences that you intended with the refactor.

Once you have finished and are ready to commit your refactor, delete the include file, the include line, and the testing code.

Wrapping up

At this point, your .module file should be much smaller, consisting of just hooks and things like callback functions that can’t be moved into a class. Your directory structure should look a lot like a Drupal 8/9 module with all the code wrapped up into classes. There will still be work needed to move to Drupal 8/9 in dealing with the API changes but the actual structure of the code and where things are found shouldn’t need much changing. And maintaining the Drupal 7 code until that time should be a much more pleasant experience.

Further reference

This blog post came from actual client work but that work was inspired by others. These two were my biggest sources for reference:

I didn't get into forms above but here's an article that covers them: https://roomify.us/blog/object-oriented-forms-in-drupal-7/

May 12 2021
May 12
[embedded content]

Don’t forget to subscribe to our YouTube channel to stay up-to-date.

When someone shares a Facebook post with a link to your website, Facebook lets you control how your website content appears to others by parsing your Open Graph (OG) markup.

By doing some minimal configuration changes on your Drupal site using the Metatag Module and the Metatag: Open Graph sub module, you can define what specific content can be shown on Facebook regardless of whether it’s shared from the desktop or mobile web or a mobile app.

It is easier to explain by showing the end result of what we are trying to accomplish. For example, the homepage of www.webwash.net has the following OG markup inside of the :

If someone posted www.webwash.net to Facebook, then Facebook would parse the OG markup like this:

And the end result would look like this:

You can clearly see the corresponding OG tags for the content.

If you want to learn more about the OG tags. Click here for a detailed list and explanations of the Facebook OG tags.

In this tutorial, we are going to show you how to configure a content type to dynamically populate the Facebook OG tags using the Metagtag module and Metatag Open Graph sub module.

Table of Contents

Getting Started

The Metatag module has a dependency on the Token module. However, if you download and enable the Drupal module using composer and drush, the dependency is automatically taken care of as we will show you now.

Use Composer to download the module:

composer require drupal/metatag

Once the Metatag module is downloaded using composer, the Token module, which is a dependency, will be downloaded automatically.

Then enable the “Metatag: Open Graph” sub module:

drush en metatag_open_graph -y

The above drush command will automatically enable the Metatag: Open Graph sub module, Metatag module and Token module.

Finally, it is always a good idea to clear the cache after enabling Drupal modules:

drush cr

By default, Open Graph can be added to any content type. We will now configure Open Graph for the Article Content type.

1. Go to Configuration > Search and meta data > Metatag and click on “Add default meta tags”.

2. On the next page, select “Article” (or whatever content type you want to configure)  from the Type dropdown.

3. Then click on Save. This is required for the correct tokens to appear in the “Browse available tokens” window.

4. Edit the “Content: Article” configuration from the Metatag page.

5. Then in the Open Graph fieldset on the same page, click to expand it. You will now notice quite an exhaustive list of OG tags that you can populate. Firstly, we are going to demonstrate how to populate the Image OG tag.

For this to be successful, your Article content must have at least an image field. We will show you how to use Token to grab that image data.

Click on “Browse available tokens”.

From the Token window click on Nodes to drill down and find the content type fields.

NOTE: If you can’t see “Nodes”, this means you need to save the “default meta tag” option first then edit it again.

Fill in the following fields:

  • Content type: article
  • Page URL: [node:url]
  • Title: [node:title]
  • Description: [node:summary]
  • Image URL: [node:field_image] (adjust the field name accordingly)

Find Image Field Token

To use an image stored in an image field, click on “Browse available tokens”.

Then drill down by going to Nodes -> Image. This assumes you’re using the Image (field_image) field on the Article content type.

The token should be [node:field_image].

Find Image Field Token on Media Asset

If you’re using a media field instead of an image field for handling assets, then use the following token, [node:field_media:entity:thumbnail] (change the field_media name accordingly).

6.After you fill out all of your OG tags fields, click on Save and clear the Drupal cache. If you do not clear your cache, the OG fields may not populate for existing content.

7. Once you have filled out the other OG fields with their respective token values, you should validate the resulting OG markup using the Facebook Sharing Debugger tool. We will now show you how to validate your OG markup.

NOTE: Your website has to be publicly accessible for the debug tool to work.

8. First we need to create a test Article node (make sure to upload an image to our image field). Our test article looks like this:

9. Paste the url for this node into the Facebook Sharing Debugger tool. The output should look like:

As you can see, Facebook successfully parsed our OG markup and displayed the information correctly.

Summary

Facebook lets you control your website’s content whenever someone’s shares a link to your content regardless of whether it’s shared from the desktop or mobile web or a mobile app. Facebook does this by parsing the Open Graph (OG) markup provided by your website. We have shown how you can use the Metatag module and Metatag Open Graph sub module to configure Drupal 8 to correctly generate the OG markup needed by Facebook and we have also shown how to validate your OG markup to ensure Facebook correctly parses your website content.

FAQ

Q: I changed the default meta tag configuration, but the tags are not changing?
Try clearing the site cache. Go to Configuration > Performance and click on “Clear all caches”.

Editorial Team

About Editorial Team

Web development experts producing the best tutorials on the web. Want to join our team? Get paid to write tutorials.

May 11 2021
May 11

Workflow automation is key in saving time, and money, in all aspects of a business. Accounting is one department that benefits from automation and our Quickbooks integration for Drupal can help remove manual data entry and free staff up to focus on other business objectives.

Automating accounting workflows with Quickbooks integration for Drupal

We all know as business owners that time is money. The more time we can save, the more time we have to work on other tasks for our business.

This is common sense, and is something every business owner should be looking to improve on every single day.

  • How can you save time?
  • What can you automate?
  • What type of processes can you create to become more efficient?
  • What systems and softwares can you use to become more organized?

These are things that you need to be looking at to not only save time for you and your staff, but so you can get things done right the first time. Having solid processes, automation and efficiency is how you create a smooth running business, that's why we decided to help out.

How Acro Media is contributing to workflow automation

Still learning? Find more info on business automation >While it’s hard for us to know what specific needs, systems and processes your business would need in order to save time, we have been looking for a solution to help the majority of our clients.

One category we know every business could use some help on, and by help I mean automate, is accounting and bookkeeping. This can be a huge time suck.

Manually inputting product orders, customers, refunds, credit memos, and invoicing takes time. If you use Quickbooks and don’t have any type of automation or integration setup with your Drupal site, these tasks can eat up a lot of manpower every month. Manpower that could be used to hunt new accounts, research better products or services and in general find ways to make you business better, instead of doing menial tasks.

Not to mention, if you are doing all of these tasks manually, there is always a chance for human error, and we know, all of humans make mistakes.(Frantically searches for typos, again.)

This is why Acro Media has made an effort to develop a module that can integrate and connect your Drupal site straight to your Quickbooks account. This module eliminates any chance of human error and will save you a HUGE amount of time every month as all your data from your Drupal site will be automatically pushed into your Quickbooks account.

If your business is a little unique or you require functionality that our module doesn't currently have, we can build it for you. Gotta love open source!

To get a better visual idea of what our new Quickbooks module can do, have a look at the infographic below.

acro_quickbooks_display_ads_-_1.1_-_ap.jpg

How much time can you expect to save?

While there is no way for us to determine how much time you can save each month, we have put together a rough formula to see how this module can help you and your team save countless hours every single month.

We calculated the median time spent manually creating the following bookkeeping essentials:

  • Creation of an invoice or sales receipt: 2.5 min/order
  • Manual credit memo or credit note: 1 min/order
  • Payment processing or annotation: 1 min/order

Time saved = [amount of orders each month] X 4.5min

So, let’s turn that formula into a good old grade-school word/math problem:

You have a healthy ecommerce business, and your online store alone is generating 2,500 sales a month.

2,500 x 4.5 min is equal to 11,250 minutes a month. Or, 187.5 hours a month.

That means you are freeing up 1 full-time staff member and 1 part-time staff member every month by having your ecommerce site integrated and talking directly to Quickbooks. Not to mention the reduction in human error, the better data you will get out of your sales reports and the time your staff can now dedicate to anything other than manual data entry!

What’s next?

If you're looking for ways to save time in your business and focus on what matters most, reach out to our team and let’s see if this module is a right fit for your business.

Talk soon, and remember... time is of the essence.

Still have questions? Check out our business automation page >

Editor’s Note: This article was originally published on August 24, 2016, and has been updated for freshness, accuracy and comprehensiveness.

May 05 2021
May 05

Selecting a CMS for a university can be a challenging decision. There are so many needs and nuances to consider - costs of implementation and maintenance, a wide range of technical ability among site administrators, developers, and content editors, a variety of end-users looking for different information...and the list goes on and on. While your answer likely isn’t as easy as, “let’s just do what everyone else is doing,” better understanding why other universities made the choice they did can shed light on your decision-making process. 

Drupal is far and above the most used CMS in higher education - 26% of all .edu domain sites are in Drupal, including 71 of the top 100 universities. 

So why are universities like MIT, Georgia Tech, Butler, Stanford, Harvard and the rest of the Ivy League universities choosing Drupal? 

Simply put, Drupal makes good business sense, especially with the added benefits of Drupal 9. At Mediacurrent, we believe your website is your greatest digital asset and can be leveraged to accomplish organizational-wide goals. Drupal makes that possible. Here’s how:  

Communicate With All Students - Prospective, Current, and Alumni 

If you want to reach your full recruiting and fundraising potential, you need to communicate with your entire audience. There are a variety of Drupal features that ease the stress of common communication challenges. 

Language

Not only are their multiple languages spoken within the U.S., but our country hosts over a million international students. Drupal makes creating a multilingual digital experience simpler. Native language handling is built directly into Drupal 8 and 9 core APIs, giving you over 100 languages to choose from. With that functionality, it is easier than ever to engage with prospective students across the globe in a meaningful way.

Accessibility

The CDC estimates that 20% of U.S. adults identify as having a disability. These disabilities often hinder people’s ability to interact with the average website. Drupal is an inclusive community and has committed to ensuring that all features of Drupal conform with w3C and WCAG 2.0. Pair Drupal’s built-in accessibility tools with a strong higher-education-focused accessibility strategy and your potential audience could grow by 20%. The Siteimprove Drupal module can help you keep a close and proactive eye on your overall web accessibility. 

Technology

 According to the College Explorer Market Research Study, the average college student owns 5.6 devices and spends 137+ hours on them! This may seem like common sense now, but if you want to engage with students, you need to account for a variety of screen sizes. Thankfully, Drupal 8 was designed with a mobile-first mentality and includes out-of-the-box responsive functionality.  And that mobile mindset continues with Drupal 9. Features like editorial workflows, Layout Builder, and media management can support content delivery that is optimized for mobile access.  

Personalization

 Universities face added complexity when it comes to digital strategy due to the broad audiences they appeal to. With so many unique people coming to the same pages, content strategy, conversion path mapping, and optimization, and defining strong calls to action can be a struggle. By incorporating personalization into your content strategy, whether that is personalized based on user authentication or by integrating tools like Acquia Personalization or Salesforce Marketing Cloud, you can speak to the masses but make them feel like you’re speaking specifically to them. 

Reduce Overhead Costs + Increase Operational Efficiencies with Drupal

Drupal can have a dramatic impact on reducing overhead costs and increasing operational efficiency. Universities have a big need for multiple websites: departments, colleges, libraries, and student organizations all want their own website. The direct cost of supporting this many sites along with resourcing the training and support is expensive and encourages unnecessary technology sprawl. As an open source technology (no licensing fees!) along with the multisite feature, creating sites for these different groups is exponentially easier, more cost-effective, and ensures brand consistency. 

You can also increase efficiency, ensure content consistency and improve the user experience by creating a “source of truth”.

Write content once and publish it anywhere it’s relevant.

Having to update content such as a curriculum or an academic calendar on multiple pages is inefficient and unnecessary. Write once, publish everywhere, save time. 

Improve Brand Equity + Amplify Digital Strategy

As a university, your brand is a powerful asset. You spend significant energy and resources on building loyalty to bolster several organizational goals from recruiting efforts, engaging current students on campus, and fundraising among alumni.

With your website being the hub of your marketing strategy, it is critical for your CMS of choice to play nice with your marketing efforts.

Drupal is very SEO-friendly out of the box. There are also advanced configuration options available to support a more sophisticated SEO strategy. You can amplify your digital strategy by integrating your marketing tools and communication platforms directly with Drupal. And the 26% percent of other .edu sites using Drupal make integrating your university-specific tools to your website easier. 

Reduce Risk

I’d be remiss without mentioning open source security and GDPR compliance. As a university, you hold sensitive information about the students who have attended your school and they are trusting you to keep that secure.

The Drupal community is passionate about security and has an industry leading global security team to ensure your site is protected.

Additionally, as the landscape of privacy rights changes around the world, it’s in your best interest to stay on top of it and reduce the risk of being penalized for data collection practices. 

Speed up Your Time to Launch 

RainU logo

Drupal has a lot to offer to universities from the moment of install. We created RainU CMS to bring that out-of-box experience to the next level with a tailored approach. RainU is Drupal-based development platform that helps colleges and universities accelerate the web development process. 

Have questions about how Drupal and RainU can benefit your university? Let us know. We’d be happy to chat. 

Editor’s note: This post was originally published on July 18, 2018, and has been updated for accuracy and comprehensiveness.

May 05 2021
May 05

I proposed this session to DrupalCon, but it was not selected. I think that is good. I have had my fair share of stage time in DrupalCons in the past, new contributors should take the lead. However, I still did the work of creating the presentation, then recorded myself giving the talk.

This is a re-post of the article on the Lullabot blog.

Slides available here.

Drupal projects can be challenging. You need to have a lot of framework-specific knowledge or Drupalisms. Content types, plugins, services, tagged services, hook implementations, service subscribers, and the list goes on. You need to know when to use one and not the other, and that differs from context to context.

It is this flexibility and complexity that allows us to build complex projects with complex needs. Because of this flexibility, it is easy to write code that is hard to maintain.

How do we avoid this? How do we better organize our code to manage this complexity?

Framework logic vs. business logic

To start, we want to keep our framework logic separate from our business logic. What is the difference?

  • Framework logic - this is everything that comes in Drupal Core and Drupal contrib. It remains the same for every project.
  • Business logic - this is what is unique to every project—for example, the process for checking out a book from a library.

The goal is to easily demarcate where the framework logic ends and the business logic begins, and vice-versa. The better we can do this, the more maintainable our code will be. We will be able to reason better about the code and more easily write tests for the code.

Containing complexity with Typed Entity

Complexity is a feature. We need to be able to translate complex business needs to code, and Drupal is very good at allowing us to do that. But that complexity needs to be contained.

Typed Entity is a module that allows you to do this. We want to keep logic close to the entity that logic affects and not scattered around in hooks. You might be altering a form related to the node or doing with access or operate on something related to an entity with a service.

In this example, Book is not precisely a node, but it contains a node of type Book in its $entity property. All the business logic related to Book node types will be contained in this class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final class Book implements LoanableInterface {
  private const FIELD_BOOK_TITLE = 'field_full_title';
  private $entity;

  public function label(): TranslatableMarkup {
    return $this->entity
      ->{static::FIELD_BOOK_TITLE}
      ->value ?? t('Title not available');
  }

  public function author(): Person {...}
  public function checkAvailability(): bool {...}

}

Then, in your hooks, services, and plugins, you call those methods. The result: cleaner code.

1
2
3
4
5
6
7
8
9
10
11
12
13
// This uses the 'title' base field.
$title = $book->label();

// An object of type Author.
$author = $book->owner();

// This uses custom fields on the User entity type.
$author_name = $author->fullName();

//Some books have additional abilities and relationships
if ($book instanceof LoanableInterface) {
  $available = $book->checkAvailability() === LoanableInterface::AVAILABLE;
}

Business logic for books goes in the Book class. Business logic for your service goes in your service class. And on it goes.

If you are directly accessing field data in various places ($entity->field_foo->value), this is a big clue you need an entity wrapper like Typed Entity.

Focusing on entity types

Wrapping your entities does not provide organization for all of your custom code. In Drupal, however, entity types are the primary integration point for custom business logic. Intentionally organizing them will get you 80% of the way there.

Entities have a lot of responsibilities.

  • They are rendered as content on the screen
  • They are used for navigation purposes
  • They hold SEO metadata
  • They have decorative hints added to them
  • Their fields are used to group content, like in Views
  • They can be embedded

Similar solutions

This concept of keeping business logic close to the entity is not unique. There is a core patch to allow having custom classes for entity bundles.

When you call Node::load(), the method will currently return an instance of the Node class, no matter what type the node is. The patch will allow you to get a different class based on the node type. Node::load(12) will return you an instance of the Book class, for example. This is also what the Bundle Override module was doing.

There are some drawbacks to this approach.

  • It increments the API surface of entity objects. You will be able to get an instance of the Book class, but that class will still extend from the Node class. Your Book class will have all of the methods of the Node class, plus your custom methods. These methods could clash when Drupal is updated in the future. Unit testing remains challenging because it must carry over all the storage complexity of the Node class.
  • It solves the solution only partially. What about methods that apply to many books? Or different types of books, like SciFiBook or HistoryBook. An AudioBook, for example, would share many methods of Book but be composed differently.
  • It perpetuates inheritance, even into the application space. Framework logic bleeds into the application and business logic. This breaks the separation of concerns. You don’t want to own the complexity of framework logic, but this inheritance forces you to deal with it. This makes your code less maintainable. We should favor composition over inheritance.

Typed Entity’s approach

You create a plugin and associate it to an Entity Type and Bundle. These are called Typed Repositories. Repositories operate at the entity type level, so they are great for methods like findTaggedWith(). Methods that don’t belong to a specific book would go into the book repository. Bulk operations are another good example.

Typed Entity is meant to help organize your project’s custom code while improving maintainability. It also seeks to optimize the developer experience while they are working on your business logic.

To maximize these goals, some tradeoffs have been made. These tradeoffs are consequences of how Drupal works and a desire to be pragmatic. While theory can help, we want to make sure things work well when the rubber meets the road. We want to make sure it is easy to use.

Typed Entity examples

Your stakeholder comes in and gives you a new requirement: “Books located in Area 51 are considered off-limits.”

You have started using Typed Entity, and this is what your first approach looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * Implements hook_node_access().
 */
function physical_media_node_access(NodeInterface $node, $op, AccountInterface $account) {
  if ($node->getType() !== 'book') {
    return;
  }

  $book = \Drupal::service(RepositoryManager::class)->wrap($node);
  assert($book instanceof FindableInterface);
  $location = $book->getLocation();
  if ($location->getBuilding() === 'area51') {
    return AccessResult::forbidden('Nothing to see.');
  }

  return AccessResult::neutral();
}

You already have a physical_media module, so you implement an access hook. You are using the global repository manager that comes with Typed Entity to wrap the incoming $node and then call some methods on that Wrapped Entity to determine its location.

This is a good start. But there are some improvements we can make.

We want the entity logic closer to the entity. Right now, we have logic about “book” in a hook inside physical_media.module. We want that logic inside the Book class.

This way, our access hook can check on any Wrapped Entity and not care about any internal logic. It should care about physical media and not books specifically. It certainly shouldn’t care about something as specific as an “area51” string.

  • Does this entity support access checks?
  • If so, check it.
  • If not, carry on.

Here is a more refined approach:

1
2
3
4
5
6
7
8
9
10
11
12
function physical_media_node_access(NodeInterface $node, $op, AccountInterface $account) {
  try {
    $wrapped_node = typed_entity_repository_manager()->wrap($node);
  }  
  catch (RepositoryNotFoundException $exception) {
    return AccessResult::neutral();
  }

  return $wrapped_node instanceof AccessibleInterface
    ? $wrapped_node->access($op, $account, TRUE)
    : AccessResult::neutral();
}

If there is a repository for the $node, wrap the entity. If that $wrapped_entity has an access() method, call it. Now, this hook works for all Wrapped Entities that implement the AccessibleInterface.

This refinement leads to better:

  • Code organization
  • Readability
  • Code authoring/discovery (which objects implement AccessibleInterface)
  • Class testability
  • Static analysis
  • Code reuse

How does Typed Entity work?

So far, we’ve only shown typed_entity_repository_manager()->wrap($node). This is intentional. If you are only working on the layer of an access hook, you don’t need to know how it works. You don’t have to care about the details. This information hiding is part of what helps create maintainable code.

But you want to write better code, and to understand the concept, you want to understand how Typed Entity is built.

So how does it work under the hood?

This is a declaration of a Typed Repository for our Book entities:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * The repository for books.
 *
 * @TypedRepository(
 *    entity_type_id = "node",
 *    bundle = "book",
 *    wrappers = @ClassWithVariants(
 *      fallback = "Drupal\my_module\WrappedEntities\Book",
 *      variants = {
 *        "Drupal\my_module\WrappedEntities\SciFiBook",
 *      }
 *    ),
 *   description = @Translation("Repository that holds business logic")
 * )
 */
final class BookRepository extends TypedRepositoryBase {...}

The “wrappers” key defines which classes will wrap your Node Type. There are different types of books, so we use ClassWithVariants, which has a fallback that refers to our main Book class. The repository manager will now return the Book class or one of the variants when we pass a book node to the ::wrap() method.

More on variants. We often attach special behavior to entities with specific data, and that can be data that we cannot include statically. It might be data entered by an editor or pulled in from an API. Variants are different types of books that need some shared business logic (contained in Book) but also need business logic unique to them.

We might fill out the variants key like this:

1
2
3
4
5
variants = {
  "Drupal\my_module\WrappedEntities\SciFiBook",
  "Drupal\my_module\WrappedEntities\BestsellerBook",
  "Drupal\my_module\WrappedEntities\AudioBook",
}

How does Typed Entity know which variant to use? Via an ::applies() method. Each variant must implement a specific interface that will force the class to implement ::applies(). This method gets a $context which contains the entity object, and you can check on any data or field to see if the class applies to that context. An ::applies() method returns TRUE or FALSE.

For example, you might have a Taxonomy field for Genre, and one of the terms is “Science Fiction.”

Implementing hooks

We can take this organization even further. There are many entity hooks, and Typed Entity can implement these hooks and delegate the logic to interfaces. The logic remains close to the Wrapped Entity that implements the appropriate interface.

The following example uses a hypothetical hook_entity_foo().

1
2
3
4
5
6
7
8
9
10
11
/**
 * Implements hook_entity_foo().
 */
function typed_entity_entity_foo($entity, $data) {
  $wrapped = typed_entity_repository_manager()->wrap($entity);
  if (!$wrapped instanceof \Drupal\typed_entity\Fooable) {
    // if the entity not fooable, then we can't foo it
    return;
  }
  $wrapped->fooTheBar($data);
}

This type of implementation could be done for any entity hook.

Is this a good idea? Yes and no.

No, because Typed Entity doesn’t want to replace the hook system. Typed Entity wants to help you write better code that is more efficient to maintain. Reimplementing all of the hooks (thousands of them?) as interfaces doesn’t further this goal.

Yes, because you could do this for your own codebase where it makes sense, keeping it simple and contained. And yes, because Typed Entity does make an exception for hooks related to rendering entities.

Rendering entities

The most common thing we do with entities is to render them. When rendering entities, we already have variants called “view modes” that apply in specific contexts.

This is starting to sound familiar. It sounds like a different type of wrapped object could overlay this system and allow us to organize our code further. This would let us put everything related to rendering an entity type (preprocess logic, view alters, etc.) into its own wrapped object, called a renderer. We don’t have to stuff all of our rendering logic into one Wrapped Entity class.

Typed Entity currently supports three of these hooks:

  • hook_entity_view_alter()
  • hook_preprocess()
  • hook_entity_display_build_alter()

Renderers are declared in the repositories. Taking our repository example from above, we add a “renderers” key:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * The repository for books.
 *
 * @TypedRepository(
 *    entity_type_id = "node",
 *    bundle = "book",
 *    wrappers = @ClassWithVariants(
 *      fallback = "Drupal\my_module\WrappedEntities\Book",
 *      variants = {
 *        "Drupal\my_module\WrappedEntities\SciFiBook",
 *      }
 *    ),
 *    renderers = @ClassWithVariants(
 *      fallback = "Drupal\my_module\Renderers\Base",
 *      variants = {
 *        "Drupal\my_module\Renderers\Teaser",
 *      }
 *    ),
 *   description = @Translation("Repository that holds business logic")
 * )
 */
final class BookRepository extends TypedRepositoryBase {...}

If you understand wrappers, you understand renderers.

The TypedEntityRendererBase has a default ::applies() method to check the view mode being rendered and select the proper variant. See below:

These renderers are much easier to test than individual hook implementations, as you can mock any of the dependencies.

Summary

Typed Entity can help you make your code more testable, discoverable, maintainable, and readable. Specifically, it can help you:

  • Encapsulate your business logic in wrappers
  • Add variants (if needed) for specialized business logic
  • Check for wrapper interfaces when implementing hooks/services
  • Use renderers instead of logic in rendering-specific hooks
  • Add variants per view mode.

All of this leads to a codebase that is easier to expand and cheaper to maintain.

Photo by James Harrison on Unsplash

Apr 30 2021
hw
Apr 30

This DrupalFest series of posts is about to end and I thought that a fitting end would be to talk about the future of Drupal. I have already written a bit about this in my previous post: what I want to see in Drupal 10. However, this post is more aspirational and even dream-like. Some of these may sound really far-fetched and it may not even be clear how to get there. For the purposes of this post, that’s fine. I will not only worry about the how; just the what.

Modular code

Drupal is already modular; in fact, it is rather well designed. As Drupal grows and adds new features, the boundaries need to be redefined. The boundaries that made sense years ago for a set of features may need to be different today. The challenge is in maintaining backwards compatibility for the existing code ecosystem around Drupal. It also means fundamentally rethinking what are Drupal’s constructs. The transition from Drupal 7 to 8 was iterative and in many cases, the systems were just replaced from procedural to object-oriented. We need to rethink this. We should not be afraid to use the newest trends in programming and features from PHP, and rethink what architecture makes sense.

If you’re thinking this sounds too much like rewriting Drupal, you’re right. And maybe the time isn’t right for that, yet. I do believe there will be a time when this will become important. This will also help with testability which was the topic of my previous post about Drupal 10.

Assemblable code

Once we have code that’s modular, we can break it off into packages that can be reused widely. This is already in minds of several core developers and the reason why you see the Drupal\Component namespace. I want to see more systems being moved out not just in a different namespace but in different packages entirely.

The direct upshot of this is that you can use Drupal’s API (or close to it) in other PHP frameworks and applications. But that is not my main interest here. My interest in seeing this happen is that forcing the code to be broken this way will result in extremely simple and replaceable code. It will also result in highly understandable and discoverable code and that is what I want. Drupal core is opaque to most people except those who directly contribute to it or to some of the complex contrib modules. I believe that it doesn’t have to be and I wish we get there soon.

Microservices

Taking this even further, I would like to see some way to break down Drupal’s functions over different servers. I am thinking there could be a server dedicated to authentication and another for content storage. This is a niche use case and therefore a challenge to implement in a general-purpose CMS such as Drupal. This would need kernels that can run in a stateless way and also breaking systems so that they can be run independently using their own kernels. The challenge is that all of this will have to be done in a way that won’t increase the complexity of the existing runtime. This, as you might have guessed, is contradictory.

More themes

I might not have thought about this sometime back. But with a renewed interest in the editor and site-builder, I think it makes sense to improve the theme offerings available to Drupal. There were many times when I build powerful functionalities but then show them in a completely unimpressive look. Olivero and Claro are big steps in this direction and I am hoping for more of the same quality. If there were, I wouldn’t have used Contrib Tracker for over 3 years with the stock bootstrap theme (even the logo was from the theme until recently).

Unstructured Content

Drupal is great at structured content but I see Drupal used more and more for unstructured pages. The way we do this now is using structured bases such as paragraphs to represent components but this method has its shortcomings. Paragraphs and similar concepts quickly get too complicated for the editor. Editing such pages is very painful and managing multiple pages with such content is tricky.

We now have the Layout Builder that is a step forward in addressing this problem. The ecosystem around the Layout Builder modules is scattered right now, in my perception, and I would love to see where the pieces land (pun intended). I would like to see Drupal fundamentally recognize these pages as separate from structured data so that the editing workflows can be separate as well. More in the next section.

Better media and editor experience

I know media is a lot better today than it was before but there’s still a long way to go. When working with pages (not structured content), I would like a filtered editing experience that lets me focus on writing. WordPress does this part well, but WordPress has a specific target audience because of which it can make this decision. This is the reason I previously said I would want Drupal to treat unstructured pages differently.

With a more focused editor experience, I would want better media handling as well. I want to paste images directly into the editor without worrying about generating resized versions. I also want pasted images to be handled somewhat similarly to the current media elements so that we can still deduce some structure. Even tiny things like expanding tweets inline and formatting code correctly could be supported in the editor and that could make a big difference.

Starter kits

We need ways to spin up sites for varied purposes quickly but I don’t think distributions are a good answer, at least not the way they are implemented right now. Once you install a distribution, you are stuck with it and would have to rely on distribution maintainers for updates. I think that’s a waste of effort. I know it’s possible to update parts of distribution without waiting for a release but the process is harder. And if a distribution is going out of support, it is difficult to remove it; it is almost impossible if the distribution authors don’t design for it. We already have challenges with migrations and upgrades, why add the distribution on top of that?

Instead, I would like to see some support for starter kits within Drupal core. Instead of distributions, you would install Drupal from a starter kit which would point to modules and contain configuration. Once installed, it would be as if the site was installed manually. I believe a lot of such solutions are also possible outside Drupal core (using drush, for instance) but it would be nice to have some sort of official interface within the core.

What else?

I know that all of the things I mentioned are possible in part or have challenges that involve tradeoffs. It’s not easy to figure out which tradeoffs we should make considering that Drupal’s user base is massive. For example, what I wrote about today are my wishlist items for Drupal. They may be something completely different for you and that’s okay. I believe the above are already aligned with the vision set for Drupal by Dries and the core team (ambitious experiences, editor-first, site-builder focused, etc). With that as the North Star, we should be able to find a way forward.

That is it for now. I can dream more about the removal of features (such as multisite) but that’s for some other day. Let me know what things you would like to see in Drupal.

Apr 29 2021
hw
Apr 29

The configuration API is one of the major areas of progress made in Drupal 8. It addresses many challenges of managing a site across environments for Drupal 7 and before. It’s not perfect. After all, it’s just version 1 and there is work going on in CMI 2 to fix the problems in the current version. That is not the subject of this blog post, however. In this post, I want to talk about one of the lesser understood features of configuration management: overriding.

Most site builders and developers interact with the Drupal configuration API with “drush config-export” and “drush config-import”. Except for a minor exception, Drupal configuration is an all-or-nothing deal, i.e., you apply the configuration as a whole or not at all. There are modules like config_ignore and config_split to work around all these limitations. These modules allow ignoring parts of configuration or splitting and combining configuration from different locations. Further, Drupal allows overriding specific configuration through settings.php. A combination of all of these makes the Drupal configuration workable for most complex site-building needs.

The Configuration API

The configuration API provides ways to support all of the different scenarios described above. There are very simple constructs that are comparable to Drupal 7’s variable_set and variable_get functions. If you want to write a simple module that needs access to configuration, the documentation is enough to work out all of the details for you. Yet, there are some lesser understood parts of how the configuration handles cases such as overriding and other edge cases. I have seen this often in interviewing several people and even though it is well documented, its lack of visibility explains why people are not aware.

As I said before, I will mainly talk about the overriding system here. You are welcome to read all about the configuration API from the documentation. Specific areas I would recommend reading about are:

The configuration API needs to handle overriding specifically because they could affect exported configuration. If you are overriding configuration in the settings.php file, and if the config system didn’t know that, those values would be exported to the configuration file. This is not what you want. If your intention was to export it, then there was no reason to set it in the settings.php file. That is why the configuration API needs a mechanism to know about this.

Overriding configuration

The configuration API can handle these overridden values separately and also make them available to your code. This is why if you are exporting configuration after setting the values in settings.php, the overridden values won’t be present in the exported YML files. As a site builder, you won’t have to worry about this. But if you are a module developer, it helps to understand how to differentiate between these values.

Before I talk about the code, let’s consider the scenarios why you would need this. As a module developer, you might use the configuration in different ways and for each, you may need either the overridden data or the non-overridden (original) data.

  • For using the configured value in your logic, you would want the overridden data. Since you are using the value in your logic, you want to respect Drupal’s configuration system of overriding configuration.
  • For showing the value in a form, you might want to show the original data. You can choose to show overridden data but Drupal core shows the original data. There is an issue open to change this. Right now, there is a patch to indicate that the data is overridden and changes won’t take effect on the current environment.
  • While saving the values to the configuration, it will always be the original data. As a module developer, you cannot affect the overridden value through the configuration API. In fact, to save the configuration, you would need to call getEditable and that will always return the original data. When you set the new value and save it, you will change the value in the configuration storage. Yet, the override from settings.php will take precedence.

Accessing overridden values

If you have built modules, you might already be aware that you can use a simple get call on the config service to read a value from the configuration (see example). This will return an immutable object which is only useful for reading. To save it, however, you would need to go through the config factory’s getEditable method (example). This will return an object where you can set the value and save it.

While it may seem obvious that this is the only difference between “get” and “getEditable” methods, there is a subtler difference. The “get” method returns the overridden data whereas the “getEditable” method returns the original data. This means, there is a chance that both of these methods might return different values. As a module developer, it is important to understand this difference.

What if you wanted to get an immutable object but with original data? There’s a method for that: getOriginal (see example). Most modules won’t need to worry about the original data in the configuration storage except when saving. For that reason, it is not common to see this method in use. Even if a module were to indicate the differences in original and overridden configuration, it can use getEditable in most cases.

The difference between “get” and “getEditable” has been the trickiest interview question I have ever asked. Out of hundreds of interviews, I have only occasionally seen someone answer this. I hope this post helps you understand the difference and why the subtlety is important to understand.

Apr 28 2021
hw
Apr 28

Just as I published yesterday’s article on the tech stack, I realized that I missed a few important things. I had said that the list was only a start, so I think it is fitting to continue it today. As such, today’s post won’t be as long as yesterday’s or even as long as my usual posts. I should also add a caveat that today’s post won’t make the list complete. With the industry how it is and the requirement of constantly learning, I don’t think such posts stand the test of time; not from a completeness perspective in any case.

Our target persona still remains the same as the last post. We are talking about a Drupal developer building sites and functionality for a complex Drupal website with rich content, workflows, editorial customizations, varying layouts, and more features typically found in a modern content-rich website. Since today’s post focuses on the fundamentals of working on the web, the skills may apply to more than a Drupal developer but we’ll focus on this persona for now.

These are also skills that are often hidden, aka non-functional requirements. It is very easy to forget about this (as was evidenced by my yesterday’s post) but this is probably the most important of any of the skills. Not understanding this sufficiently leads to significantly large problems. Fortunately, Drupal is a robust framework and system and is able to handle all such issues by default. It is still important to understand how to work along with Drupal.

Performance

Performance is a very interesting challenge for a large dynamic website. There are several layers to unravel here and the answer for poor performance could be at any of those layers. This means a developer needs to understand how the web works, how Drupal works, and how does Drupal attempt to optimize for performance.

It is shocking how many people are unable to clearly articulate how the Internet works. To me, the lack of clear articulation is a sign of gaps in understanding in the chain of all systems that make the Internet work. To begin with, understand what is the sequence of events that take place when someone visits a link. Understanding DNS is important too. I know no one really understands DNS fully but you don’t need that. Get familiar with the interactions that take place between the client and the various systems such as DNS. Similarly, get familiar with CDN’s and other caching techniques that you can use.

Scalability is a different problem than performance but still very important to understand. Understand what are load balancers and how do they decide to route traffic. Also, understand how can you configure an application to work in such an environment. For this, you also have to understand the concept of state. Fortunately, PHP is already designed to be stateless and has a natural aptitude for such scalability (and serverless paradigm).

On the application front, understand how JavaScript and other assets can impact the rendering of your page. How would you find out if the front-end code is a bottleneck and if it is, what do you do about it? Same for back-end code. Understand how would you utilize caching at multiple layers to deliver performance to the user. Figure out what scenarios are better served with a reverse proxy cache like Varnish or an application cache such as Redis or memcached.

Accessibility

Accessibility is not an afterthought. Unless you are willing to review each line of code later, start with accessibility in mind from the first day. Again, Drupal meets many of the accessibility standards when you use the themes that ship with Drupal. The framework also supports many of the constructs that make writing accessible interfaces easier. Drupal 7 onwards has committed to meeting WCAG 2.0 and ATAG 2.0. Read the Drupal documentation to know more about how you, as a module developer, can write accessible code.

Security

Again, security is not an afterthought and many people who treat it as such have a fair share of horror stories. And just like before, Drupal provides constructs that make it very easy to write secure code. With Drupal 8 and the introduction of Twig, it became significantly harder for developers to write insecure code. However, it is important to understand what Drupal does for security, otherwise, you will be fighting against the core to make your code work.

Understand Drupal’s philosophy of content filtering of filtering on output, not input. Understand how to use PDO and DBAL to work with databases safely. Learn how to use the Xss helpers to write HTML output safely. Understand how you would use Drupal’s permissions and roles system to provide access control for your code.

Again, these are vast topics but I am only beginning to introduce them here. Do follow the links above to specific Drupal documentation pages to understand the topic better.

Apr 27 2021
Apr 27
[embedded content]

Don’t forget to subscribe to our YouTube channel to stay up-to-date.

File Management Series

Removing files from Drupal is more tricky than you might think. There has been another tutorial about this using the module File Delete.  It requires going through a cycle of minimum 6 hours.  By default, Drupal protects files from removal which are still being used and referenced in other content. Instead of directly deleting a file, the linked usages need to be cleared first, and the files marked as temporary, then finally the system will remove them during cleanup.

This is actually a good policy. However, sometimes it’s annoying to wait for a few hours before these files are being cleaned up. In particular, if we are sure these files are unused or orphaned, there is another module called Fancy File Delete, which solves this problem.

Fancy File Delete allows you to delete files straight away without having to wait.

However, great care must be taken when using this module, because it has a ‘force delete’ option. Use of this module should be restricted to experienced administrators.

Table of Contents

Getting Started

Before we begin, go download and install Fancy File Delete.

Using the following Drush commands:

composer require drupal/fancy_file_delete

NOTE: The module requires the Views Bulk Operations (VBO) module which will be downloaded when you run the above command.

Deleting Files

To follow a proper procedure to delete files, administrators should still go through the proper file handling process by removing them from the nodes and the media library first, even though these processes can be bypassed using this module.

After installing and enabling the modules, go to Admin >> Configuration >>  Content authoring >> Fancy File Delete. In the first tab ‘Info’, it shows a brief description on how to use the module.

Enter the ‘List’ tab, a list of all the files in the system can be found from here.  Select the file(s) to be deleted using the checkbox in front of each file, then select ‘Delete Files’ in the ‘Action’ option on the top of the page, then click the ‘Apply to selected items’ button.

Note that there is another option for Action, which is ‘FORCE Delete Files (No Turning Back!)’.  When a file cannot be deleted, try this option but handle with care.

Can’t See Action Drop-Down

If you can’t see the Action drop-down on the list page that means you’ll need to reconfigure the view.

1. Edit the List view by clicking on the pencil icon.

2. Once you’re editing the view, click on the “Views bulk operations” field.

3. Enable the actions by clicking “Select all”.

Then save the view and you should see the Action drop-down.

Delete Files manually by FID

As can be seen above, there is a File ID for each file.  Files can be deleted using this FID by entering them under the ‘Manual’ tab. Just enter the FIDs of the files to be deleted, one per line, and press the ‘Engage’ button.

Deleting Orphaned and Unmanaged Files

Additional options are available to delete orphaned and unmanaged files if the system detects them.

Deleting Files from the ‘Files’ or ‘Image’ Fields

Note that in the above procedure using ‘Fancy File Delete’ module, it is not a requirement to remove them from the nodes first:

  • It bypasses the default file delete procedure in Drupal, and therefore it should be handled with care.
  • Files deleted will also be removed from previous node revisions too.
  • Files deleted will also be removed from the list of files under Admin >> Content >> Files
  • Files deleted are permanently removed totally from the system, including the physical file in the server.
  • It does not require waiting for the minimum 6 hours requirement.

When the files are uploaded through the media module and deleted without first removing them from the nodes and the media library first, this ‘Fancy File Delete’ module still remove the files same as above, except the following:

  • Files deleted will still be removed both physically from the server and from the list of files under Admin >> Content >> Files, like above.
  • The file will not be shown in node because it is empty, but an empty entity will remain both in the node and in the media library.

Using Drush

If you use Drush, you can delete files straight away using the “drush entity:delete” command.

For example:

drush entity:delete file 1

This command will remove the file from the Files page and delete it from the file system and you won’t have to wait.

Summary

This module offers a more straightforward and efficient way to remove files from a Drupal site permanently. It is powerful and capable of bypassing the default file handling procedures in Drupal. But that also means bypassing the file protection mechanism of Drupal. It handles file deletion in an efficient manner which is an advantage, but it is also a disadvantage at the same time.

On a large site where there are more users and content authors. When deleting files are granted to more people, it is difficult to guarantee that everybody is careful enough to understand the underlying structure and relationships between files and content. There is a higher risk of accidental deletion of files. In such situations, a better protection mechanism might be necessary.

On a small site or in a small team where content is easier to manage and control, efficiency might be preferred.

Editorial Team

About Editorial Team

Web development experts producing the best tutorials on the web. Want to join our team? Get paid to write tutorials.

Apr 27 2021
hw
Apr 27

The title of this post is not really accurate, but I can’t think of another way to say it. This post is related to my earlier one on what a Drupal Developer does day-to-day. Here, I will talk about some of the skills required of a Drupal developer. I am not aiming for completeness in this post (that’s a goal for another time) but I will try to list all skills required to build a regular Drupal site, deploy it, and keep it running. Some of these skills are foundational whereas others may be only needed for specific requirements. Moreover, not all skills are required at a high expertise level. For some roles, even awareness is enough.

This post would be useless without a target persona. Different organizations have different needs and what works at one organization may not work at another at all. Similarly, different roles within an organization have different needs. For example, at Axelerant, we do not have a dedicated site-builder role but this is something that is expected of a Drupal Developer. Such an arrangement may not work at all for your organization nor can I say this arrangement will work forever for Axelereant. In fact, it is even weird to use the word “forever” here.

The target persona for this post is a Drupal Developer building sites and functionality for a complex Drupal website with rich content, workflows, editorial customizations, varying layouts, and more features typically found in a modern content-rich website. Since this is Drupal we are talking about, the above definition is actually quite broad. It includes a web presence for organizations from publishing, healthcare, higher-education, finance, government, and more. With that settled, let’s look at the skills.

Site-building

A Drupal developer would need to have the following skills related to site-building. Even if a developer does not build sites, there is a good chance they would be interfacing with these aspects from code. Hence, most of these are foundational.

  • Content modelling: Understand what makes a good content structure for a site. You should be able to determine if the content structure you are building is the relevant one for the requirements.
  • Content moderation: Most sites need this. I have seen this being used even on simple sites when there is more than one type of user. Understanding how the moderation workflow works and how it ties with the entity-field structure along with its revisions is important.
  • Multiple languages: It is important to understand how Drupal implements multilingual functionality at both interface and content (translation) level. Depending on the requirements, certain aspects of how translated content is stored in fields could be very relevant. At a basic level, you should also be aware of how Drupal determines the language when it renders a page or response.
  • Configuration Management: While this may seem more to do with developers, it is important to understand this from a site building perspective. You need to understand how the content types you create are stored in configuration and how is it different from how, for example, site information is stored. This means you need to understand configuration entities and simple configuration. You also need to understand how configuration can be changed depending on the environment and how it could be overridden.
  • Common solutions like views and webforms: Before you set about developing for some functionality, you have to make sure if there is a solution out there already. You also need to know how to pick modules for your problems.

Development

I don’t think this section needs any explanation as the entire post is about this. So let’s jump in.

  • PHP: This might seem like a no-brainer. Drupal is written in PHP so it is a good idea to be very comfortable with PHP. Understand object-oriented programming, how Drupal uses different constructs such as traits. Also, understand patterns such as dependency injection and observer pattern (hooks and event subscribers are based on this). Then, keep up with what’s new in PHP, if possible, and use it.
  • Composer: Arguably, this is a part of site-building as well but there is a good reason to keep it here. Apart from using composer to download modules, understand how it helps in writing the autoloader. Also, understand how composer works to select a module or a package and what are the reasons it might fail. Most of this comes with experience.
  • Caching: This is probably the most important part to understand about Drupal. Caching is deeply ingrained at multiple levels in Drupal and it is important to understand how it works. Almost all your code will need to interact with it even if you aren’t planning to cache your responses.
  • Other Drupal API’s: There are some common API’s you should be familiar with; for example, Form API and Entity API come to mind. But also be aware of other API such as Batch, Queue, plugins, Field, TypedData, etc. You should know where to look when you need it for a problem.
  • Automated testing: The Drupal core has a very vast collection of test cases and that means you may only have to write functional test cases for your site. You should understand the different tools that you can use to write them.

Deployment

You have to understand where your site is going to live to build it well. We don’t live in that age where you would write code and throw it over a wall to the ops team for them to deploy it. You may not be deploying it but you have to understand the concepts.

  • Servers: Understand how servers work. You don’t need to know enough to configure one securely (unless that’s your job) but you should know enough to understand the terms. For example, you should know what are the common web servers and how they may be configured to run PHP. Also, understand what kind of configuration Drupal needs to run.
  • High Availability: Given Drupal’s market, there is a good chance that the site you are building will need to run in a highly available environment. Understand what it means and what that implies for your Drupal site. Most of these issues may be resolved for you if you are using one of the PaaS providers but if you are building your own server(s), you should understand how to configure Drupal to run on multiple servers. Even if you are using PaaS, you should still understand how running on multiple servers could affect how you write code, e.g., how you work with temporary files.
  • CI/CD: Continuous Integration is very common today and it is important you understand it to be a productive developer. There are dozens of solutions to choose from and most have some kind of a free offering. Pick one and try it out.

And more…

Like I said before, I am not aiming for completeness here but only in making a start. Please let me know if I have missed something obvious. Given the nature of these posts, I can only spend 1-2 hours planning and writing these, so there is a very good chance I have missed something. Let me know.

Apr 26 2021
Apr 26

Now on Drupal 9, the community isn’t slowing down. This month, we continue our interview with Angie Byron, a.k.a Webchick, a Drupal Core committer and product manager, Drupal Association Board Member, author, speaker, mentor, and Mom, and so much more. Currently, she works at Aquia for the Drupal acceleration team, where her primary role is […]

The post Community Corner: Interview with Angie Byron, Part Two appeared first on php[architect].

Apr 26 2021
hw
Apr 26

Over the years, I have significantly lesser time for development and an increasing need to move around. After dealing with back-pain due to the weight of my Dell laptop while travelling for conferences, I bought a 15″ MacBook Pro. More recently, with the issues with Docker performance on Mac, I have been thinking of getting a Linux box. I was further motivated when I bought an iPad last year and wanted to use that for development. Now, with my old MacBook Pro failing because of keyboard and hard disk, I have a new MBP with the M1 chip and just 8 GB RAM. I am more and more interested in making remote development work efficiently for me.

It is not hard to set up a remote machine for development in itself. The problem I want to solve is to make it easy to spin up machines, maintain them, and tear them down. I also want to make it easy to set up a project along with the necessary tooling to get it running as quickly as possible. For now, the only problem I am solving is to set up the tooling quickly. I am calling this project Yakht (after yacht, as I wanted a sea-related metaphor).

Current workflow

While it’s far from the level of automation I am thinking of, it’s not too bad. I was able to set up a machine for use within a few minutes. This is what the process looked like:

  1. Create a 1 GB instance on DigitalOcean in a nearby region (for minimum latency).
  2. Add a wildcard DNS record for one of my domain names so that I can access my projects on ..
  3. Set the domain name and IP address in my Ansible playbook’s variable files and inventories.
  4. Run the Ansible playbook.

These steps had a machine ready for me with all tools required for Drupal development using Docker (Lando in my case). The Ansible playbook installs a bunch of utilities and customizations along with the required software like PHP, Docker, composer, Lando, etc. Only PHP CLI is installed because all development happens within Docker anyway. It also configures Lando for remote serving and sets the base domain to the domain I have configured, which means I can access the URLs generated by Lando (thanks to the wildcard DNS). With the Drupal-specific tooling we have written (some of which I have written before), setting up a new project is fairly quick.

A lot of these tools are somewhat specific to me (such as fish-shell and starship). I need to make it customizable so that someone else using it can pick a different profile. That’s a problem for another day.

Current trials

I have been using this machine for a long time now which is not how I intend for this to be. I am trying out a few tools and customizations before putting them in the Ansible playbook. Most notably, I am trying out cdr and using it as an online IDE which is very similar to vscode. It took a little effort to serve it via Caddy, it works well most of the time. It times out frequently but I think this is because this instance only has 1 GB of RAM. When it times out, the connection breaks and you need to reload which can get frustrating. Fortunately, this happens frequently for a while and then it works fine for long periods of time. In any case, I doubt if this will happen on an instance with a reasonable amount of RAM.

Screenshot of cdr running in Chrome

Screenshot of cdr running in Chrome

I know that VS Code has good support for remote development over SSH but I also want to be able to use the IDE over iPad and a browser-based IDE solves that. I am also considering trying out Theia and Projector but that’s for another day.

It’s also missing a few things I want in my development machines such as my dotfiles and configuration for some of the tools (such as custom fish commands). For now, all of this is set up manually. Of course, my intention is to automate all of these steps (even DNS).

Current problems

The general problem with these kinds of tools is to maintain a balance between flexibility and ease of use. By ease, I mean not having to configure the tool endlessly and frequently to make it do what you want. But that’s exactly what flexibility needs. For now, I am not trying hard to maintain flexibility. Once I have something that works with reasonable customization, I will figure out how to make it much more customizable.

Another problem is accessing remote servers from this machine. Right now, I am using SSH agent forwarding to be able to access remote servers from my development instance without having the SSH key there (and it works). But this doesn’t work if I am using the terminal in cdr. I am still looking for a solution to this problem that doesn’t involve me copying my keys over to the development instance. One idea is, if forwarding is not possible at all, to generate new keys for every instance and give you public keys that you can paste in services you want. This is secure compared to copying the private key but definitely a hurdle to get over.

I am excited by this project and hope to have more updates over time. For now, I hope you find the Ansible playbook useful. Also, I am looking for ideas and suggestions in solving this general problem of remote development. Please let me know via comments or social media what you think.

Apr 25 2021
hw
Apr 25

I thought I was done with the series of posts on object-oriented programming after my last one. Of course, there is a lot we can write about object-oriented programming and Drupal, but that post covers everything noteworthy from the example. There is a way which is old-school but works as it should and another which looks modern but comes with problems. Is there a middle-ground? Tim Plunkett responded on Twitter saying there is.

There's a third way! See https://t.co/cFizL60Loy and https://t.co/so2syXyXZS

— timplunkett (@timplunkett) April 24, 2021

At the end of the last post, I mentioned that the problem is not with object-oriented programming. It is with using something for the sake of using it. If you understand something and use it judiciously, that is more likely to result in a robust solution (also maintainable). Let’s look at the approach mentioned in the tweet in detail.

The fundamental difference

The problem with the version with objects in the last post was not because it used objects. It was because it overrode the entry point of the form callback to change it. Using classes has its advantages, most notably that we can use dependency injection to get our dependencies. For more complex alterations, it is also useful to encapsulate the code in a single class. But the approach with the entry point made the solution unworkable.

On the other hand, the form_alter hook is actually designed for this purpose. Yes, it cannot be used within classes and you have to dump it in a module file along with all the other functions. But it works, and that’s more important. There is no alternative designed for this purpose. So, in a way, the fundamental difference is that this method works whereas the other doesn’t. It doesn’t matter that we can’t use nice things like dependency injection here if it doesn’t even work.

Bringing them together

The two worlds are not so disjoint; PHP handles both brilliantly, after all. If you want to encapsulate your code in objects, the straightforward solution is to write your code in a class and instantiate it from your form_alter hook. Yes, you still have the hook but it is only a couple of lines long at most and all your logic is neatly handled in a class where it is easy to read and test. The class might look something like this.

<?php
 
namespace Drupal\mymodule;
 
use Drupal\Core\Form\FormStateInterface;
 
class MySiteInfoFormAlter {
  public function alterForm(array &$form, FormStateInterface $form_state, $form_id) {
    // Add siteapikey text box to site information group.
    $form['new_element'] = [ '#type' => 'textfield',
      // ... more attributes
    ];
  }
}

And you can simply call it from your hook like so:

function mymodule_form_system_site_information_settings_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $alter = new \Drupal\mymodule\MySiteInfoFormAlter();
  $alter->alterForm($form, $form_state, $form_id);
}

You can save the object instantiation if you make it static but let’s not go there (you lose all advantages of using objects if you do that).

Dependency Injection by Drupal

This is already looking better (and you don’t even need route subscribers). But let’s take it a step further to bring in dependency injection.

We can certainly pass in the dependencies we want from our hook when we create the object, but why not let Drupal do all that work? We have the class resolver service in Drupal that helps us create objects with dependencies. The class needs to implement ContainerInjectionInterface but that is a very common pattern in Drupal code. With such a class, you only need to create the object instance using the class resolver service to build it with dependencies.

function mymodule_form_system_site_information_settings_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  \Drupal::service('class_resolver')
    ->getInstanceFromDefinition(MySiteInfoFormAlter::class)
    ->alterForm($form, $form_state, $form_id);
}

For better examples, look at the links Tim Plunkett mentioned in the tweet: the hook for form_alter and the method.

I hope you found the example useful and a workable middle-ground. Do let me know what you think.

Apr 24 2021
hw
Apr 24

Update: Read the follow-up to this post where I discuss a mixed approach combining both of the approaches here.

I previously wrote about how the object-oriented style of programming can be seen as a solution to all programming problems. There is a saying: if all you have is a hammer, everything looks like a nail. It is not a stretch to say that object-oriented programming is the hammer in this adage. That post was quite abstract and today I want to share a more specific example of what I mean. More specifically, I’ll talk about how using “objects” to alter forms without thinking it through can cause harm.

But first some context: this example comes from my reviews every week of code submitted as part of our interview test. This has happened frequently enough that I think that this is actually a recommendation somewhere. Even if it is the case of people copying each other’s work, it certainly is evidence that this has not been thought out. In fact, this makes for a good interview question: where would this method fail? I am going to answer that in this post.

The traditional method

Let’s look at the traditional method first. Drupal provides hooks to intercept certain actions and events. For example, Drupal might fire hooks in two situations: in response to events like saving a node, or to collect information about something (e.g. hook_help). You will find a lot more examples about the latter and that is what we are going to talk about today.

Drupal fires a few different hooks when a form is built. Specifically, it gives the opportunity to all the enabled modules to alter the form in any way. It does this via a hook_form_alter hook and a specifically named hook_form_FORM_ID_alter. So, for example, to alter a system site information form, either of the functions below would work:

function mymodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form == "system_site_information_settings") {
    $form['new_element'] = [ /* attributes */ ];
  }
}
 
// ... OR ...
 
function mymodule_form_system_site_information_settings_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $form['new_element'] = [ /* attributes */ ];
}

Adding elements or altering the form elements in any way is a simple affair. Just edit the $form array as you want and you can see the changes (with cache clear, of course). This is the old-school method and it still works as of Drupal 9.

The OOPS approach

More often than not, I see the form being altered in a much more involved way. Broadly, this is how it looks:

  1. Create a form using the new object-oriented way but extending from Drupal\system\Form\SiteInformationForm instead of the regular FormBase.
  2. Define an event subscriber that will alter the route using the alterRoutes method.
  3. In the event subscriber, override the form callback to your new form.

This gist contains the entire relevant portion of code.

After doing all this, you might expect that the code should at least work as expected. Many people do. But if you have been paying close attention, you might see the problem. If not, think about what would happen if two modules attempt to alter the same form this way. Only one of them would win out.

If there are two modules altering the same route, the last one to run will win and that module’s form changes will be used, The form controllers from the previous modules will never be executed. You could extend the first module’s form controller in the second module (so that changes from both modules take effect) but that is not reasonable to expect in the real world with varied combinations of modules.

So, we shouldn’t use objects?

I am not saying that. I am saying that we should think how we are applying any programming paradigm to build a solution and where it might fail. In our example, if Drupal supported an object-oriented version of form alters, that would have been safe to use (there is an open issue about this.) In fact, there is discussion to use Symfony forms and also some attempts in contrib space. Until one of those solutions get implemented, the form_alter hook is the best way to alter forms. And there is a good chance that such hooks get replaced in time. After all, the event-based hooks did get replaced by events in most cases.

For now, and always, use the solution that fits your needs. Using objects or using functional programming doesn’t necessarily make a program better. It is using our skills and our judgement that makes a program better.

Update: Read the follow-up to this post where I discuss a mixed approach combining both of the approaches here.

Apr 23 2021
hw
Apr 23

I have been contributing to Drupal in a few different ways for a few years now. I started off by participating in meetups, and then contributing to Drupal core whenever I found time. Eventually, I was even contributing full-time courtesy of Axelerant, my employer. At the same time, I started participating in events outside my city and eventually in other countries as well. I was speaking at most of the events I attended and mentored at sprints in many of these events. I have written about this in detail before in different posts about my Drupal story and a recent update to that.

It was only with the support my wonderful family and also from Axelerant in the early years that enabled me to contribute in this way. As my responsibilities grew, I had to find focus in where to contribute. My kids were growing up and I wanted to spend a lot more time with them. At the same time, I started picking up managerial responsibilities at Axelerant and was responsible not just for my work, but for a team. I was approaching a burnout quickly and something had to go. It was at this time I rethought on how to sustainably contribute to open-source.

Long story, short…

The story is not interesting. Honestly, I barely remember those years myself. I know they were essential for my growth and they came at a significant price. But we know that nothing worth doing is easy. As a mentor to a team and even bordering on a reporting manager, I had the privilege to multiply my efforts through them. I am proud to see how many of them have built their own profiles in the community and continue to do so.

My recommendation to my team and myself is now to stop thinking of contributing as “contribution” but as a part of our work. The word “contribution” implies giving something externally. People are hesitant to make this external action when they already are very busy with bugs, deliveries, and meetings. We all have a limited working area in mind to think about the code and all the complexity. Thinking about something external is very difficult in these circumstances.

Don’t hack core

One reason this feels so external to us is because of how we treat Drupal core and contrib. We drill in the notion in newcomers that we should never hack core. While there is a good reason for this but it results in the perception that the core (and contrib) cannot be touched. It is seen as something external and woe befall anyone who dareth touch that code. It is no surprise that many people are intimidate by the thought of contributing to the Drupal core.

My workflow

The trick is to not think of it as external. I use the word “upstream” instead of contrib projects when talking about Drupal core or modules. I find that some people think of “upstream” as a little closer to themselves than “community contribution”. Thinking about it this way makes the code more real, not something which is a black box that can’t be touched. We realize that this code was written by another team consisting of people who are humans just like us. We realize that they could have made mistakes just the way we do. And we realize that we can talk to them and fix those mistakes. It is no different than working in a large team.

Yes, this means that we don’t have people who are dedicating time to contribute. That is a worthy goal for another day. I am happy with this small victory of getting people familiar with the issue queues and the contribution process on drupal.org. I have seen these small acts bubble up to create contrib modules for use in client work (where relevant). Eventually, I see them having no resistance with the idea of contribution sprints because the most difficult part of the sprint is now easy: the process. They are familiar with the issue queue and how to work with patches (now merge requests); if it is a sprint, the only new thing they are doing is coding, which is not new to them at all.

I realize that this is not a replacement to the idea of a full-time contributor. We need someone who is dedicated to an initiative or a system. These contributors are needed to support the  people who will occasionally come in to fix a bug. But we need to enable everybody to treat the core as just another piece of code across the fence and teach them how to open the gate when necessary.

Apr 22 2021
Apr 22

As DrupalCon comes to a close for the crew at Mediacurrent, we’ve all had a chance to reflect on the experience. Here are the top 10 things we loved and learned at this year’s event.

1. Opening New Doors to ‘Discover Drupal’

Drupal talent is in high demand and The Drupal Association is focused on cultivating that talent with an emphasis on diversity, equity, and inclusion. That’s important to our team at Mediacurrent, too. We love helping young professionals get started in a Drupal career (like our two student interns who experienced their first-ever DrupalCon last week!) and we jumped at the chance to become a training partner for the just-launched Discover Drupal program. We will be mentoring students and providing an opportunity to intern with us after they have finished their scholarship.

Discover Drupal offers a 12-month scholarship and training program for underrepresented individuals in the open source community. Learn more and support the program

Speaking of training, our booth offer this year was a drawing for a free 4-hour training workshop in one of our most popular topics: Front-End Development, Decoupled Drupal with Gatsby, or Drupal Component-Based Theming. We are very excited to be drawing the names of 3 winners this week, who will learn about current technology demands and best practices using active discussion and a hands-on workshop. Watch our Twitter channel to see who wins!

2. Bright Horizons Ahead for Drupal 10 

Dries reinforced that the sun is quickly setting on Drupal 8, with community support ending this fall. Drupal 7’s days are numbered as well. If you haven’t already, it’s time to think about your Drupal 9 action plan.

Key dates for Drupal 7 and 8

The community’s innovation efforts will focus on Drupal 9 while also looking ahead to June 2022 — the target release date for Drupal 10.

Drupal 9 and 10 timeline

3. Going Back to Our Site Builder Roots

Drupal’s roots are about empowering site builders to build ambitious websites with low code. 

-Dries Buytaert, State of Drupal Keynote - DrupalCon North America 2021

What made YOU fall in love with Drupal? 

In his State of Drupal keynote, Dries reflected on Drupal’s core strength to find focus for the year ahead. He reasoned that to help our community grow and become even more successful, we need to give every user a clear reason to adopt Drupal. 

Many Drupal love stories share a common spark; the feeling of being quickly empowered by Drupal’s low code approach. To give site builders that “love at first site” feeling, Dries announced the Project Browser Initiative. That goal is to make site builder basics like installing a module as easy as installing an iPhone app and rise to the competition of Wix, Squarespace, and WordPress. 

Drupal program browser initiative

4. Building a Better Foundation for Future Features

Everyone wants to know what comes next for our favorite digital experience platform. As always, DrupalCon sessions and the Driesnote shed some light on the innovation that lies ahead, highlighting both core and contrib initiatives that the community is working to advance.

Visitors to the Mediacurrent booth saw how Rain CMS speeds up development and gives content creators the authoring experience they crave. (If you missed it, Rain CMS now ships with Layout Builder to make page building a breeze) 

Dries shared a progress update on the core strategic initiatives that are blazing trails for future functionality and improvements in Drupal core. These initiatives shaped the program content, with a different one assigned to each day of the conference. 

  • Easy Out of the Box - This initiative is improving Drupal's ease-of-use remains a top priority.
  • Decoupled Menus - This initiative is positioning Drupal as the go-to for decoupled. Now, non-module Javascript projects have a home on Drupal.org.
  • Automatic Updates - By getting automated security updates into Drupal 9 core, we can help site owners sleep soundly.
  • Drupal 10 Readiness - Drupal 9 is just under a year old but the community is already looking ahead. Dries called for community support to hit the target release date for Drupal 10.

5. Celebrating and Encouraging Community Contributions 

Drupal continues to shine as of the most scalable, robust, and mature development communities in open source. We heard from Heather Rocker, Global Executive Director of the Drupal Association, about some of the initiatives that are making it easier for first-time and non-coding contributors to get involved.

Both individual and company-level contributors were celebrated on the DrupalCon stage. Congratulations are in order for AmyJune Hineline, the recipient of this year’s Aaron Winborn Award. The award honors individuals for their outstanding commitment to the Drupal project and community. (Check out our interview with AmyJune from season one of the Open Waters podcast.) 

Giving back to Drupal remains a core priority for the Mediacurrent team. This year, we’re proud to show our support for the Drupal Association as a Diamond Drupal Certified Partner and excited to maintain our rank as one of the top five organizational contributors. 

top companies sponsoring Drupal

6. The More Sites, The Merrier

How do you manage and maintain dozens or even hundreds of sites effectively?

That’s the question Jay Callicott, VP of Operations at Mediacurrent, set out to answer in his DevOps track session on scaling Drupal with the power of multisite. Drupal’s multisite capabilities are a standout feature, setting it apart from other CMS platforms. Yet there’s a lot to consider - configuration, deployments, site provisioning, and more. 

This session recording is now available to registered attendees with public access coming in a few weeks. Stay tuned!

Drupal multisite presentation slide shows a decision tree

7. Making Sense of Open Source Security 

Mediacurrent’s Drupal security pros took the stage to tackle a timely topic: open source security for marketing and business leaders.

As open source software like Drupal continues to become widely adopted, sticking to security standards is a challenge. The global losses from cybercrime totaled nearly $1 trillion last year (csis.org), raising the stakes on security even higher. 

Be on the lookout for the session recording for a playbook on how to optimize your Drupal security. They covered how to become a security-first organization, embrace process automation, harden Drupal security, and create clear security policies.

these Drupal modules protect from OSWAP

8. Higher Education: The Stage for Ambitious Digital Experiences

DrupalCon’s industry summits are always a great accompaniment to the regular program, and this year was no exception. At the Higher Education Summit, Director of Development Dan Polant was joined by one of Mediacurrent’s ivy league partners  to co-present a case study session. We saw how the university relies on Drupal to model complex data and got a behind-the-scenes look at the decoupled architecture with Gatsby. 

A decoupled approach lets us choose a dedicated solution for a given job

9. Drupal is Powering Hope 

At this year’s DCon, we saw how Drupal is powering some of the most impactful organizations in the world. All but one of the major COVID-19 vaccine-producing companies use Drupal. 

Major nonprofits like Habitat for Humanity also rely on Drupal. Through its website, the organization has helped more than 5.9 million people build or improve the place they call home. Mediacurrent has been honored to support Habitat’s mission and partner with them to build a maintainable platform that thrives on support from the Drupal community. The Drupal Showcase session recording for Habitat for Humanity: Building a foundation for digital success will be publicly available soon. We’re grateful for the opportunity to reflect on the success we achieved through our partnership, and we hope others can learn from it. 

Covid vaccine sites Pfizer, Modern, J&J run on Drupal

10. The Momentum Continues With Drupalfest 

DrupalCon has ended but the celebration continues with Drupalfest. 

Interested in learning more about contributing to Drupal? Let Mediacurrent’s Community Lead Damien McKenna be your guide. Join Damien for Contrib Open Hours through the end of April. 

Watch the State of Drupal Keynote 

Check out the recording of the State of Drupal keynote below.

[embedded content]

Cheers to 20 years, Drupal! We look forward to gathering again next year.

Apr 22 2021
hw
Apr 22

We at Axelerant have been contributing to Drupal in our own ways for a long time. In fact, I worked as a full-time contributor to Drupal a few months after I joined. This was around the time Drupal 8 was almost done and it is thanks to Axelerant I could contribute what I could at that time. At the same time, there was community focus around incentivizing contributions and there were a few websites (like drupalcores) to track contributions.

Sometime later, in one of our internal hackathons, I built a basic mechanism to track contributions by our team (you can see it at contrib.axelerant.com). It was a weekend hackathon and what we built was very basic but it set the groundwork for future work. We adopted it internally and reached a stage where we had processes around it (even our KPI’s for a while). In this time, we expanded the functionality to (manually) track non-code contributions. More recently, we added support to track contributions from Github as well.

Tracking all contributions

Since this was a hackathon demonstrating possibilities using code and technology, we started with only tracking code contributions. Soon, we expanded this to track contributions to events and other non-code means. The latter was manual but this helped us build a central place where we could document all our contributions to the open-source world.

Today, we have tracking from drupal.org and Github and basic checks to determine if code was part of the contribution. On the non-code front, you can track contributions to websites like StackOverflow or Drupal Answers. And for events, you can track contributions such as volunteering, speaking, and even attending (yes, I think participating in an event counts as a contribution).

Now, we have a process for anyone joining Axelerant to set up an account on the contrib tracker. After this, all their contributions to Drupal and Github begin to get tracked at that time. We also remind people frequently to add details of any event they have attended.

Improving contrib-tracker

Contrib Tracker is open source but currently treated as an internal project at Axelerant. We initially set it up as a public repository on our Gitlab server. Now we realize that it was not practical for people to access and help build it. Today, I moved Contrib Tracker to its new location on Github: contrib-tracker/backend. For a while, we had the thought of implementing the website as a decoupled service and that’s why the repository is named “backend”. Right now, we may or may not go that route. If you have an opinion, please do let me know in the comments.

Moving to Github

The move to Github is still in progress. In fact, it just got started. The project is, right now, bespoke to how we host it and one of the lower priority items would be to decouple that. Once that is done, it should be possible for anyone to host their own instance of contrib tracker. But the more important task now is to move the CI and other assets to Github. I will be creating an issue to track this work. Our team at Axelerant has already started moving the CI definitions.

That’s it for today. Do check out the source code at contrib-tracker/backend and let us know there how we can improve it, or better yet, submit a PR. :)

Apr 21 2021
Apr 21

Dealing with constant upgrades and changes to the project requirements is not just the despair of all developers, but also dents the pockets of the clients. When discussing the project development - time and cost go hand in hand. The more the development time, the higher will be the cost. 

Resolving these hurdles is easy with, Drupal distributions as these

(1) make project development less costly to both build and maintain and 

(2) make it more commercially interesting

Leading media and publishing enterprises across the globe are already testifying the positive impact that Drupal has made on their digital business. By enabling a professional editing experience, multi-channel publishing, and personalization distributions are revolutionizing the way media and publishing houses approach Drupal.

media-publishing-drupal-statisticsSource: Drupal.org

But, what is a Drupal Distribution?

Drupal Distribution accelerates website development not just by saving time and cost but it provides quality code with out-of-the-box Industry-standard features. Maintenance of distribution is simpler because updates for all its modules and features can be performed in one shot!

According to Drupal.org “Distributions provide site features and functions for a specific type of site as a single download containing Drupal core, contributed modules, themes, and predefined configuration. They make it possible to quickly set up a complex, use-specific site in fewer steps than installing and configuring elements individually.”

Distributions provide site features and functions for a specific type of site as a single download containing Drupal core, contributed modules, themes, and predefined configuration.

Looking to redesign or start your website using Drupal in 2021? Explore the detailed comparison of the top media publishing distributions that are EzContent, Rain, Varbase, and Thunder to choose the right solution for you.

Top 4 Media & Publishing Drupal Distributions for 2021

Content Listing from EzContent

Content Listing from EzContent


    • Structured content for SEO: With EzContent you can not only easily create structured content but also provides a range of approaches to enable search engine optimization (SEO), including flexible fields, built-in metatags, Schema.org usage, and a large library of available components for rich text, media, and other common content needs.

Component Library EzContentComponent Library EzContent


    • A page builder for landing pages: With EzContent’s page builder, editors can create layouts on the fly without any dependency on developers. They can use the convenient drag-and-drop interface to easily place reusable components onto pages as needed. Similar components can be reused by configuring in different variations.

Drag & Drop Layout Builder EzContentDrag & Drop Layout Builder EzContent


    • An API-ready decoupled CMS: EzContent provides OOB Headless, CMS integration with Gatsby, React, and Angular. Thanks to EzContent distribution, editors are still empowered with legacy CMS features like previewing unpublished content, placing blocks and content using Layout Builder. Ready to use open-sourced Angular and React starter kits are available.

Choice of Frontends, OOB starter LitsChoice of Frontends, OOB starter Lits


    • AI-powered content generation: For content, leverage auto-tagging and auto caption to generate meaningful and contextual tags driven by Google AI and AWS Rekognition.

    • Now you can also manage and perform an intelligent search leveraging image recognition, image detection, and Deep Learning algorithms. Generate auto Podcast out of Article Content on the fly while curating content with help of Google AI.

auto-tagging-ezcontentAuto-tagging for Images

  • Thunder

    Thunder was designed by Hubert Burda Media and released as open-source software under the GNU General Public License in 2016. It consists of the current Drupal functionality, lots of handpicked publisher-centric modules with custom enhancements.

    Key Features & Pros of Thunder

    • Publisher Features: Create articles dynamically with paragraphs. Using paragraphs, you can add text, pictures, videos, Instagram, or Twitter Cardscards to your article with a WYSIWYG editor. — Change the order of elements by dragging and dropping the content wherever you like it.

    • LiveBlog: Cover events in real-time with the liveblog.

    • Google AMP: With the integration to Google AMP, you can deliver not only text but also images, galleries, videos, as well as Instagram and Twitter cards.

    • Improved media handling: With the help of the media browser, it’s very easy to add pictures, galleries, or videos to your article. You can upload new pictures to the media browser by just drag & drop.

    • Mobile-Friendly theme: With the Thunder installation, you get a responsive theme for the frontend and backend.

  • Varbase

    Varbase is an enhanced Drupal distribution launched in Feb 2019. It is packed with adaptive functionalities and essential modules that speed up your development and provides you with standardized configurations. The essence of Varbase lies within the basic concept of DRY (Don’t Repeat Yourself). It removes the need to perform repetitive tasks with the help of its modules, features, configurations that are included in the Drupal project.

    Key Features & Pros of Varbase

    • Publisher Features, Flexible Content Structure & Categorisation: The flexible content architecture allows for custom pages, layouts, and integrations for your special use cases. Content is organized through a predefined and scalable structure for better navigation.

    • Media Management: Full-Feature libraries to provide an appealing way to display media galleries.

    • Multilingual options with localized and translated content, translated interface, date formats, country flags, modern fonts, and more.

    • Mobile-Friendly theme: Fully optimized for mobile.

  • Rain

    Mediacurrent created the Rain Install Profile in May 2019. Rain comes prepackaged and pre-configured with components

    Key Features & Pros of Rain

    • The rain has a strong content model & focuses on editor features. It combines content, administrative & editorial features with a base theme and style guide. It also implements Components based theme, meaning components can be reused, and a build-in style guide.

    • Rain has a preconfigured API for exposing content to other applications in the JSON format. Rain can be paired with frameworks like Gatsby

Metric Comparison:

Screenshot 2021-04-22 at 1.01.06 PM

We did not forget Acquia Lightning!

The list of media publishing distribution is incomplete without mentioning Acquia Lightning. However, Acquia is ending support for the Lightning distribution in November 2021, simultaneously with Drupal 8.

Read the official announcement here

Conclusion

There are a lot of distributions to choose from. Evaluate what your product requires, map it with the vision of the distribution. Do check the roadmap, backlog, compatibility, and maintenance for the distribution.

If you’re looking for a smart distribution, OOB Components, and you want to be flexible on a choice of frontend, EzContent provides a starter kit to save your development time by 30%. 

Apr 21 2021
hw
Apr 21

Drupal 8 was a major revolution for the Drupal community in many ways, not least of which was because of the complete rearchitecting of the codebase. We picked up the modernization of various frameworks and tools in the PHP community and applied it to Drupal. Of course, this makes complete sense because Drupal is written with PHP. One of the things we picked up was the PHP’s shift to the object-oriented programming approach.

The shift to using objects enabled us to collaborate with the rest of the PHP community like never before. On the language front, we had PHP-FIG working on standards such as PSR-4 which was adopted by many libraries. And on the tooling front, we had composer which allows us to use other packages with minimal effort. These developments made it possible for us to build Drupal on top of the work from the larger PHP community. However, this meant that we had to follow the same style of programming as those libraries and thus began a massive re-architecture effort within Drupal.

The refactoring story

Drupal is a product built and maintained by a diverse group of geographically distributed and mostly unpaid people. Further, Drupal’s value is not in just the core system, but also the tens of thousands of modules, themes, and distributions maintained by a similar group of people. All the modules, themes, and distributions depend on the core Drupal’s API which means that making any change to the core is very risky.

Because of this, it is simply not possible to isolate Drupal and refactor. We had to incrementally refactor parts of Drupal while making sure there is sufficient documentation for people to upgrade their modules. This inadvertently, but predictably led to significant overengineering in Drupal’s codebase. There are a lot of parts of Drupal several layers down which may seem messy but there is a reason. The problem is that those reasons are very hard to surface. More importantly, they become a hurdle for more core contributors to simplify the system.

I have to caveat this by pointing out that I am not an expert core developer myself. Not even close. The above is just my observation in working with the core. You may say that this is practically an outsider’s perspective and you are right. But I have learnt that an outsider’s perspective is often the most valuable one.

Objects, objects everywhere

The new structure has brought in dozens of new practices (such as the DIC). This often means that you need to augment the structure to support that. Soon, we have classes with multiple adjectives and nouns everywhere reminiscent of Java. This makes the code even more opaque putting in more hurdles for people who are new to Drupal. Even experienced PHP developers may find trouble navigating the sometimes unintuitive names of various components because of the historical context.

With people managing to work in this new reality, I have found that people’s answer to all problems is simply more objects. Copy-paste solutions from various places (aka StackOverflow) and make it work. At work, I have seen more and more code samples from people who are convinced they are presenting a superior solution simply because they are using classes with names like subscriber and controller while not realising they are breaking functionality that would not have broken in Drupal 7.

This may seem vague at this point and I hope to present more specific examples in future posts. I will leave you with these abstract thoughts for today. I hope you found this interesting even if not useful.

Apr 20 2021
Apr 20

open waters podcast logo

New Year, New Faces, Same Focus

We’re back! Season 2 of Mediacurrent’s Open Waters podcast is officially on its way. We recorded a special trailer episode to celebrate. 

Mark Shropshire and Mario Hernandez are returning as hosts. Just like last season, our purpose is to explore the intersection of open source technology and digital marketing. We’ll share the challenges and solutions we see with our own clients and in the market.

During season 2, we'll be covering topics including:

  • How to optimize your digital strategy
  • Accessibility as a business imperative
  • UX design principles
  • How it all works together using open source technologies like Drupal

Welcome to Season 2

Meet the Hosts 

Mark "Shrop" Shropshire 

Shrop headshot

Role at Mediacurrent: Senior Director of Development 

Podcast creds: Shrop can be found talking about open source security, leadership, mentoring, and more on his two personal podcasts: goServeOthers and SHROPCAST

What are you most excited about for season 2? The opportunity to learn more about what other talented folks are doing in the marketing and tech industries. It is easy to be comfortable with what you know today, but I find that having conversations with others can really challenge you to think differently and learn new niches.

Mario Hernandez
Mario headshot

Role at Mediacurrent: Head of Learning 

Podcast creds: Member of the original cast of Open Waters  - Mario co-hosted the first season of our podcast.

What are you most excited about for season 2? I am looking forward to interviewing industry leaders to discuss all things open source. I am also really excited about teaming up with Shrop. He has vast experience in podcasting and I am ready to learn from him.

Podcast release schedule 

New episodes will be released monthly on the Mediacurrent blog and wherever you follow your favorite podcast. You can also follow us on Twitter for updates.

Subscribe to Open Waters

Visit mediacurrent.com/podcast to hear the latest episode and subscribe to the podcast on your favorite podcast app. Share the podcast or tell a friend about it - tag us @mediacurrent on Twitter. 

How can I support the show?

Subscribe, leave a review, and share about us on social media with the hashtag #openwaterspodcast. Have an idea for a topic? Get in touch with our hosts at [email protected]

Apr 20 2021
hw
Apr 20

Now that we have discussed some of the concerns with career growth, let’s talk about beginning a career in Drupal. I am not aiming for comprehensiveness but I hope to give a broad overview of what a Drupal developer role looks like in the real world. Needless to say, every company or agency is different. You might have a very different set of responsibilities depending on your organization. One of those responsibilities would be to build and develop Drupal websites and we are going to talk about that here.

Working in an organization essentially means working with other people. That is how you multiply your impact. All the roles do have some amount of dealing with people. Initially, you only might have to worry about collaborating with people but as you grow, the scope increases. Eventually, you would have to mentor and maybe even manage people. All along this journey, you would also increase your knowledge and area of impact technically.

Early roles

As someone who has very little experience with programming, you might start off with Drupal by building sites using UI and simple CLI commands (drush or console). Your challenge would be to understand content types, taxonomy terms, users, roles, permissions, etc. You would need to understand how to design a content type that is actually useful for what you want to represent and add fields to it. Moreover, you might know enough PHP to find snippets to alter forms or pages and implement those as per requirements.

At this stage, you might not be expected to solve complex problems or scale websites with heavy traffic. You might be working under the supervision (and mentorship) of someone with more experience with Drupal. It would be expected of you to collaborate with other people on the team such as front-end and QA engineers if any and complete your tasks the best you can.

You would need a strong set of fundamentals here such as git, basic PHP programming skills, and a working knowledge of HTML, CSS, and JavaScript. You would need more of an awareness of your software stack but wouldn’t have to go deep.

Intermediate roles

With around 2-5 years of experience, you will begin to pick up a more complex set of tasks. You would write more complex modules with proper object-oriented code. The site-building requirements also would be more complex. You would have to implement content types with complex relationships with other entities. The code required to tie these things together would also get more complex. You will also have to worry more about how to solve a requirement in the best way rather than just implement something.

At this stage, you would be expected to participate in code reviews and share your feedback. In fact, some organizations (like mine) encourages all levels of engineers to participate in code reviews, so this might not be new. Take this opportunity to also seek mentorship from other folks to go deeper into Drupal and other technologies. While you only had awareness of your stack earlier, you should now have a working knowledge of various elements in the stack. You would also be involved in discussions with other teams to build integrations your system needs. Essentially, you should understand how the pieces fit together and how they participate in making the system work.

You should also begin to question requirements and try to understand the business problem. Your value at this level is not just your technical skills but also solving business problems. In other words, it’s not just about solving the problem right but solving the right problem.

Advanced roles

After about 5-10 years of experience, you will now be responsible for the entirety of a system. You may begin with simpler systems where Drupal plays a major role and then move on to more complex systems where Drupal is just one piece of the puzzle. At this stage, more people will turn to you to solve their problems and you will have to figure out how to solve those problems yourself, guide them, or delegate it to someone else.

You should also be much more familiar with the entire Drupal ecosystem and how it can fit in with other parts of your stack. You are close to approaching what could be called the “architect” role (but we won’t go there today). As an IC, you will have a lot more impact but you would also play a significant glue role in your team (or teams).

This is a vast topic and I might come back to this in a future post (or multiple posts). Like I said before, this is not meant to be a comprehensive guide, but just a broad overview.

Apr 19 2021
hw
Apr 19

As the Director of Drupal services at Axelerant, one of the things I often worry about is the growth of each of the members of my team. We are a Drupal agency, so there are a lot of options for people to choose from. Yet, there are different concerns with working on Drupal for a long time. Today, I’ll talk about some of those concerns and what are the mitigating factors. I can’t claim to present a perfect solution, even less in a post written in less than an hour. But I hope to at least get the topic started.

Concern: Drupal is not cool anymore

When Drupal celebrated its 18th birthday, there were jokes around how Drupal is now old enough to drive (or something like that). This year, Drupal is 20. You might be surprised but a software’s life-cycle is not the same as a person’s life-cycle :). So, while 20 might be the age where a person is cool (I’m showing my age, aren’t I?), that’s not the same for software.

Yes, Drupal is now in the boring technology club. It has been so for years with a definitive transition around the Drupal 8 period. This is not a bad thing. It’s only a bad thing if you want your software stack to be cool and you having to work against deadlines to fix issues for everything that is just a little out of the way. Drupal is mature, predictable, and boring. And that means you should not worry about Drupal going out of style anytime soon.

Fact: Drupal does valuable things; cool, but also valuable

However, the people who have this concern don’t worry about the software living on. They are missing the fun that comes with working with cutting edge technology. They’re right. Fun is important and software development is hard enough without it not being fun. The fact is that Drupal can still be used in cool new ways. For example, Decoupled Drupal is one of the newest trends in the industry to offset Drupal’s limitations in the front-end area. Another subtle way that Drupal is fun by opening it up to the PHP ecosystem with the “get off the island” movement with Drupal 8. You don’t have to be limited by Drupal’s API and libraries to do what you want. The entire PHP ecosystem of packages is available for you for direct use within Drupal.

Further, I encourage people not to code just for the sake of coding. Solve a problem: any problem, even if it is a hypothetical issue or an imaginary challenge. Solve it and put it out to help other people. You make that act of coding about people and in turn, you help yourself. But I am digressing. Drupal solves problems of quickly building a web presence for activities that help people. This tweet comes to my mind again over here. Even if Drupal’s software stack is not cool, what it does is cool and that’s a big deal for me.

Concern: There is not much to do in Drupal

As developers grow and learn more, they find that they are learning less and less in their day-to-day work. This is closely tied with the first concern I talked about (Drupal is not cool). People may not think that Drupal is not cool but the underlying thoughts are the same: all tasks are of the same kind and I am not learning anything anymore. They’re right as well but there are ways around it.

I previously wrote that most requirements of building a website with Drupal can be achieved just by configuring in the UI. You only have to write some glue code to get it all working. Opportunities to develop entirely new functionality in Drupal is now rare unless you are working on the Drupal product. This is when people start looking into other frameworks and languages. Again, I highly encourage that because the learning benefits both the person and the project, but that’s beside the point of this post.

Fact: There is a lot to do around Drupal

The problem is in finding opportunities around Drupal. I have already hinted at one easy way out of this: work on the Drupal product. That is to say, contribute to the Drupal core and contrib space. These are the people solving the hard problems so that we don’t have to. If you want to solve hard problems, we need you there. I am sure your organization will support you if you are interested in contributing to Drupal.

Next, look at what are the integrations where you could help. Very few Drupal sites today work in isolation. Either you have a completely decoupled site, or at least integrations to other complex systems and these are still challenging areas to work in.

You will notice that the solutions here largely depend on the organization where you work. Yes, you would need the support of your organization and there is a good chance you will get that support if you ask. If you don’t, you can tackle this yourselves but that is the subject of another post.

Concern: No one respects Drupal or PHP

PHP (and Drupal) is often the subject of cruel jokes ranging from competence to security issues to just being old. Chances are that you have come across enough of them and so I won’t write more about this.

Fact: PHP and Drupal communities are some of the most respected ones

To be blunt, don’t listen to these people. In my opinion, they are living in a time 20 years back or are influenced by people who lived then. PHP has made a comeback with a robust feature-set and predictable release cycle. So has Drupal. Moreover, Drupal has rearchitected itself to be more compatible with the PHP ecosystem. Finally, code is just about getting the job done and PHP commands a significant share of the web applications market, so you’re in good company.

And it’s not just about code. PHP and Drupal communities are some of the most welcoming communities in the world. They are often talked about in various places (just search for podcasts on the topic) and people cite examples of how they found welcome and support in the communities.

I am going to leave this post here even though there is a lot more I can say. But these are my thoughts for today and I hope you enjoyed them. I hope to come back to this in another post some day.

Apr 18 2021
hw
Apr 18

As of this writing, there are 47,008 modules available on Drupal.org. Even if you filter for Drupal 8 or Drupal 9, there is still an impressive number of modules available (approximately 10,000 and 5,000 respectively). Chances are that you would find just the module you are looking for to build what you want. In fact, chances are that you will find more than one module to do what you want. How do you decide which module to pick or if even a particular module is a good candidate?

Like all things in life, the answer is “it depends”. There are, however, a few checks that you can make to make a better decision. Well, these are the checks I make when trying to pick a module and I hope they can help you too. This is not something you should take strictly; just use this as a guideline to help you decide. Also, if a module fails one of these checks, it doesn’t mean that the module is a bad choice. It only means that you might be making a trade-off. Software is all about making trade-offs and so this is nothing new.

Lastly, I’ll try to focus on modules here in this post but most of this advice is suitable for themes as well.

First-look checks

These are the most basic and easiest checks you can make on a module. Except for the first one, these are not strong indicators but they can quickly give you an initial impression of the module. There might be excellent modules that are perfectly suited to your needs but fail these checks, which is why you should only use these checks to differentiate between two modules. Yeah, the irony of the name is not lost on me.

Version

Is the module even available for your Drupal version? If you’re using Drupal 9, you would need the version that supports Drupal 9. Earlier, just reading the module version would tell you if it is compatible. For example, if the module version is “8.x-3.5”, you know that the module is for Drupal 8, not Drupal 7. You might think that the module is not for Drupal 9 either but that’s not so simple anymore.

Screenshot of version information on Drupal.org

As you can see in the above screenshot from the Chaos Tools module, the 8.x-3.5 version is for both Drupal 8 and Drupal 9. This changed after Drupal.org began supporting semantic versioning for contrib projects. These example release tags show different styles of version numbers you might see and this change record explains how a module may specify different core version requirements.

Module page

Is the module page updated? Does the description make sense considering the Drupal version you are targeting? If you’re looking for the Drupal 9 version of the module and the text hardly talks about that, maybe the module is not completely ready for Drupal 9 or has features missing.

Screenshot of project page on Drupal.org

Another clue you may have is the timestamp when the page was last updated. It may just be that the maintainer has forgotten to update the page even if the module works perfectly fine. For this, we go to the next set of checks.

Recent commits

Has the module been updated recently? If it was last updated years ago, chances are it won’t work with the latest version of Drupal core. Even if it works with your version of Drupal core, would you be able to upgrade once you upgrade to the latest version of Drupal core?

Screenshot of commits block on a project page

The block on the module page gives a quick summary of the recent commits, but don’t rely entirely on this. The block only shows current committers. If there are newer commits by a previous committer or commits made elsewhere pushed here (this would happen if someone were maintaining the module on Github, for example), they won’t show here. To be sure, click on the “View commits” link to see all the commits.

Issues

Is there a discussion going on about improving the module? The issues block on the project page gives a quick summary of what’s happening on the module. Be careful though, some module maintainers choose to maintain the module on Github or elsewhere. In those cases, the issues here would show no activity (or it may be entirely disabled).

Issues block on project pageResources

Are there other resources for the module? Is there external documentation or documentation within the drupal.org guides? The Documentation and Resources block on the project page will point you to such links and other useful links.

Code structure check

These checks take a little more time than just quickly scanning the project page. These indicators are a little more reliable but not the sole determinators of success. For all of these checks, first, go to the code repository by following the “Browse code repository” link from the project page and then, select the branch for the version you want.

README file

In a previous section, I mentioned that the project page may have an outdated or missing description. This happens over time when there are multiple versions and the maintainers find it difficult to keep the page updated. However, chances are that the maintainers would definitely update the README file in the repository. Go to the code repository (see screenshots above) and find the README file. The actual file may be named either README.txt or README.md.

If this file is maintained, there is a good chance the module is well maintained and documented and you would have fewer problems using it.

Code structure

You would need experience with Drupal development to make this check. Look at the module code and see how it’s structured. Are the classes neatly separated from the rest of the code? Does the code make separation of concerns? Are there tests? Is everything dumped in the “.module” file or a bunch of “.inc” files (ignore this if you are checking for Drupal 7 modules)? If the module stores something in the config, is there a config schema?

There are some metrics we can gather to understand this better but not from the code repository browser we see. But an experienced developer would know by looking at how well the module is following Drupal conventions. This is important because following these conventions will make it easier to keep the module updated for future versions of Drupal. You don’t want to start with a module and be stuck on an older version of Drupal because of this.

Test

Here is where we actually test the module and see if it works. These are the strongest indicators but also the most time-consuming to check.

Simplytest.me

The easiest way to check a module is simplytest.me. This excellent community-run service lets you test contrib projects along with patches. Type the name of the module and click “Launch Sandbox”.

SimplyTest screenshotThere is also an “Advanced options” section that lets you add more projects (if you want to test this module along with another module) and patches. Select the module or combination of modules you want, click “Launch Sandbox” and you have a brand new Drupal installation to play with for 24 hours. This actual testing will help you determine if this module fits your need.

Test locally

If you don’t want to test on simplytest.me or you simply want to evaluate code locally, use one of the quick-start Drupal tools to get a Drupal installation with the module. For example, with axl-template, I can type this command to get a Drupal site with smart date module and a few others.

$ init-drupal drupal/test -m smart_date -m admin_toolbar -m gin

You can also use the same code base to evaluate the codebase better, maybe even run some of the code quality checks on it if you’re interested.

I hope this quick post was useful to you. Like I said before, don’t treat this as a complete list but as a guide. In the end, your own experience and actual tests will tell you more. The above guidelines are only here to save you time in reaching there.

Apr 17 2021
hw
Apr 17

I picked up this topic from my ideas list for this #DrupalFest series of posts. I didn’t think I would want to write about this because I don’t think about features that way. One of the strengths of Drupal is its modular architecture and I can put in any feature I want from the contrib space. In fact, I prefer that, but that’s a different topic. I am going to write this very short post anyway because I am now thinking about this from a different point of view.

To write this post, I thought about the various things that bother me in my day-to-day work. I thought of how we could have simpler dependency injection, or lesser (or clearer) hooks, or lesser boilerplate, but then I realized that all of those don’t matter to me very much right now. Those can be improved but they are inconveniences and I can get over them.

Easier testability is what I want from the future versions of Drupal. I have realized that the ease of testability is the strongest indicator of code quality. A system that is easily testable is implicitly modular along the right boundaries. It has to be, otherwise, it is not easy to test. A good test suite comprises of unit tests, integration tests, and feature tests. If it is easy to write unit tests, then the system is composed of components that can be easily reused (à la SOLID principles). Integration and feature tests are easier to write but eventually, they get harder unless the system is built well.

Drupal core testability

Now, Drupal is one of the most well-tested pieces of code out there. Each patch and every commit is accepted only after it passes tens of thousands of tests. Testing is also a formal gate in adding new features (and some bugfixes). That is to say, any new feature needs to have tests before it can be merged into Drupal core. Consequently, testing is common and core contributors are skilled in writing these tests.

This testability is not easily carried forward to most kinds of websites we build using Drupal. Building a typical Drupal website is mostly a site-building job and cross-connecting various elements. This happens either by configuring the site via UI or by using hooks which are essentially magically named functions that react to certain events. With Drupal 8, the hooks-based style of writing custom modules has changed significantly with modern replacements but principally the same. This style of code where you have multiple functions reacting to events and altering small pieces of data is very difficult to unit test. This means that the only possible useful tests are feature tests (or end-to-end tests). Unfortunately, these tests are expensive to run and failures do not always point to an isolated unit.

Testing tools

There have been several attempts to make writing tests easier generally and for Drupal. The package that stands out to me for this is drupal-test-traits. This package provides traits and base classes that make it easy to test sites with content. You would set the configuration to point to an installed site and run the tests. The traits provide methods to create common entities and work with them and the tear-down handlers will clean those entities up at the end. All you have to worry about is providing an installed site.

In fact, the common problem with testing Drupal is testing an installed site. Most Drupal sites I have worked with are not easy to install, despite best efforts. Over time, you need to rely on the database to get a working copy of the site. This is true even if you follow the perfect configuration workflow. It is very common to have certain content required to run a site (common block content, terms, etc) and configuration workflows cannot restore such content. There are other solutions to these problems but they are not worth the pain to maintain. We’ll not go into that here.

Handling the database and assets

Sharing databases turns out to be the simplest way to create copies of a site which shifts the problem to making such databases available to the testing environment (e.g., CI jobs). If you are running a visual regression test, you would also need other assets such as images referenced in blocks and so on. At least for the database, we have prepared a solution involving Docker and implemented as a composer plugin. Read more about it at axelerant/db-docker. This plugin makes it easy for the team to manage the database changes as a Docker image which can be used by the CI job (or another team member).

Handling assets is a more complicated problem. We traditionally solved this with stage_file_proxy and I am planning to work on this more to build a seamless workflow like we did for databases. Any ideas and suggestions are very welcome. :)

The testing workflow

Drupal has long been said to be a solution to build “ambitious digital experiences”. Such systems are built by teams and any team needs a workflow on which everyone is aligned (otherwise it wouldn’t be a team). We have seen many improvements in various aspects of Drupal over time that cater to a team workflow (configuration management comes to mind clearly). In my humble opinion, I feel standard workflows for improving testing should be a priority now.

I will leave my post here as it is already much longer than I intended. I know I didn’t present any comprehensive solutions and that’s because I don’t have one. My interest was in sharing the problem here. There are only pieces of the solution here and I am interested in finding the gel that brings them together.

Apr 16 2021
hw
Apr 16

Drupal is a CMS. One might even say that Drupal is a good CMS and they would be right about that, in my not-so-humble opinion. At its core, Drupal is able to define content really well. Sure, it needs to do better at making the content editor’s experience pleasant, apart from other things. But defining content structures that are malleable to multiple surfaces has always been Drupal’s strengths. This makes Drupal an excellent choice for building a Digital Experience Platform (DXP).

The concept of a DXP has been popular for a few years but it has peaked, not surprisingly, in the last year with organizations now forced to prioritize their digital presence above all else. Companies have now realized that, with the amount of information being thrown at each of us, they have to make sure their presence is felt through all media. Building a coherent content framework that can be used for all of this media is no easy task. Information architects need powerful tools to flexibly define how they would store their content. Drupal has been able to provide such tools for a long time.

Digital Experience is a strategy

You might have realized by now that DXP is not a product, but a collection of tools that can help you execute your strategy. With the proliferation of media, it is important that you convey a consistent message regardless of how someone consumes it. To be able to do that, you have to identify the various ways you would talk to your customers and build a strategy. This is highly subjective and customized for your needs, and I won’t go into much depth here but the output we want is a coherent content architecture. An architecture which can represent your messaging to your customers.

Once you’re able to formulate this strategy, that is when you begin implementing it within your DXP. The content architecture you have identified goes in the CMS within the DXP and it needs to be flexible enough. Drupal is a very capable CMS for such requirements. It supports complex content models with relationships among pieces of content, rich (semantic) fields, and multilingual capabilities. You can also build advanced workflows for content moderation. This enables Drupal to be the single source of truth for all content in an enterprise. This, too, should be important in your content strategy and Drupal makes it easy to implement.

Discovery

A lot of this may sound like a lot of theory and not enough practice. In a way, that’s true. Think of this as a discovery stage for the problem you’re solving. It’s important you spend enough time here so that you identify the problem clearly. Solving a wrong problem may not be very expensive from a technical point of view but frustrating to your content team. Involve various stakeholders within the DXP to determine if the content model you are building will break their systems. For example, your long text field may be good for web and email, but is unusable for a text message. But if you break up your content into a lot of granular pieces, you have to figure out how to  piece it together to build a landing page.

You also have to determine how your content can be served to more diverse channels (e.g., voice assistants or appliances). Depending on your domain, you have to make trade-offs and build a model that is workable for a variety of consumers. But that’s only one side of the story. You also have to make sure that the content is easily discoverable (both internally and externally), easily modifiable, auditable (revisions), trackable (workflows), and reliably stored (security and integrity of the data). Typically, there are an ecosystem of tools to help you achieve this.

Integrations

Drupal already handles some of these things and it can integrate well with other systems in your infrastructure. Drupal 8 began a decoupling movement which became a hype and is now being rationalized. I wrote about it in a separate post. To be clear, decoupling was always possible but Drupal 8 introduced web services in the core that accelerated the pace. Today, you only need to enable the JSON:API module to make all your content immediately discoverable and consumable by a variety of consumers.

Apart from being the content server, Drupal also handles being the consumer very well. As of Drupal 8, developers can easily use any PHP package, library, or SDK to communicate with different systems. Again, this was possible before but Drupal 8 made it very easy by adopting modern PHP programming practices. Even if a library or SDK is not available, most systems expose some sort of API. From Drupal’s point of view, use the in-built Guzzle or another HTTP client of your choice and invoke the API.

Where does Drupal fit in

Drupal is now a very suitable choice for beginning to build your DXP. However, that is not the complete story. All systems evolve, requirements change, and strategies shift. It should be easy for Drupal to shift along with it.

For example, Drupal’s current editing experience was excellent when it came out but that was several years ago. Today, building an intuitive editorial experience with Drupal is the most pressing challenge we face. There are a lot of improvements in this space and there will be more with newer versions of Drupal. It helps that community has picked up a reliable release schedule and that has built the user’s trust in Drupal. Because of the regular release schedule and focused development, we see editorial features such as layout builder and a modern theme as a part of Drupal.

It may seem that this is not important, or at least not as important as “strategy” and “infrastructure”. That’s a dangerous notion to have. Ultimately, your system will only be as effective as your team makes it. An unintuitive UI makes for mistakes and a frustrating experience. And if it is hard to maintain the content, it will not be maintained anymore. If there is anything more dangerous than missing content, it is outdated content.

Customization

Apart from the editorial experience, a flexible system is important for an effective DXP. If the content store cannot keep up with the changes required for new consumers or even existing ones, it will become a bottleneck. In organizations, such problems are solved by hacking on another system within the DXP or running a parallel system. Both of these approaches mark the beginning of demise of your DXP.

That is why it is important for you to be able to easily customize Drupal. Yes, I’m talking about low-code solutions. Drupal has figured out how to modify the content structure with minimum developer involvement, if any. It needs to make this easier for other functionality as well. Various features of Drupal should be able to interact with each other more flexibly and intuitively. For example, it is possible to place a view within a layout but it is not intuitive to do so. We have to identify such common problems and build solutions for site-builders to use. Again, I am not going to go in depth into this.

Building a digital experience platform for your organization is a massive undertaking and I cannot hope to do justice to all the nuances within a single blog post written over a couple of hours. But I hope that this post gave some insights into why Drupal is relevant to this space and how it fits into the picture.

Apr 15 2021
Apr 15

Featuring a video from Acro Media’s YouTube tutorial series Tech Talk, this article will walk you through setting up an awesome Drupal Commerce product catalogue using Search API and Solr, and then adding various ways of filtering the results (product search, sorting options and Facet categories).

Ten steps to creating a product catalogue with Search API, Solr & Facets

These 10 steps will get you a Search API index using Solr, setup a View to display the results of the index, and then implemented 3 different ways to filter the results (search, sorting and Facets).

The end result of this guide will be a catalogue that functions in the same way as our Urban Hipster Drupal Commerce demo site’s catalogue. You can try it here. If you don’t already know why we use Search API, Solr and Facets for catalogues, check out this article to get up to speed.

Even though we’re going to be using products, once you understand how it works you’ll be able to apply the same method for other type of content such as a blog, videos, resources, and more. The datasource can change but the process is the same.

Let's get started! Follow along with this video or skip below for a written guide.

[embedded content]

What you need before starting

  1. A running Solr server (Solr 6.4+)
    This tutorial assumes you have Solr running and can make a new core.
  2. Drupal 8 installed with the following modules:

    TIP: Get most of what you need quickly with Commerce Kickstart. Note that you will still need to install the Facets module after getting your Kickstart package.
    • Commerce
      composer require drupal/commerce
    • Search API
      composer require drupal/search_api
    • Solr
      NOTE: This module requires you're running Solr 6.4+ and PHP 7
      composer require drupal/search_api_solr
    • Facets
      composer require drupal/facets

Getting started

  1. Install/start Solr and add a new core that we’ll use later.
  2. Enable the Commerce, Search API, Solr and Facets modules.

Setup a basic Commerce store

For this tutorial, get your site and basic store set up by doing the following:
  1. Add a product category taxonomy vocabulary that is at least 2 levels deep.
    If we use clothing as an example, we might have Men and Women as the first level, then t-shirts, shorts and shoes as the second level for each.
  2. Setup your basic Commerce store, product types and product variation types.
    If you’re new to Commerce, take a look at their documentation to get up and running quickly.

    NOTE: Make sure to add the taxonomy vocabulary you created as a ‘taxonomy reference’ field to your Product Type.

  3. Add 10 or more simple products for testing the catalogue as we go.

Demo Drupal Commerce today! View our demo site.

Add a Search API server and index

Search API server

Admin: Configuration > Search and metadata > Search API
Admin menu path: /admin/config/search/search-api

  1. Click ‘Add server’.
  2. Configure the server.
    1. Name your server and enable it.
    2. Set ‘Solr’ as the server ‘Backend’.
    3. Configure the Solr connector.
      The defaults are usually fine. The main things to add are:
      • Solr connector = ‘Standard’.
      • Solr core = Whatever you named your core.
    4. Under ‘Advanced’, check ‘Retrieve result data from Solr’.
    5. Look over the remaining settings and update if you need to.
Search API index

Admin:Configuration > Search and metadata > Search API
Admin menu path:/admin/config/search/search-api

The index is where you set what data source is used by Search API. Eventually, you’ll also specify specific fields to be used for filtering the displayed results.

  1. Click ‘Add index’.
  2. Configure the index.
    1. Name your index.
    2. Data source should be ‘Product’
      This can be anything, but we’re creating a Commerce catalogue and so we want to use the store products.
    3. Select the server you just created.
    4. Save. Don’t add any fields for now, we’ll do that later.
    5. Go to the ‘View’ tab and index your results. This will index all of the products you have added so far.

Create a View for the catalogue

Admin:Structure > Views
Admin menu path:/admin/structure/views

The View will use the data source we’ve identified in our index and allow us to create a catalogue with it, and then assign ways of filtering the catalogue results (i.e. a search field and/or facets).

  1. Create a new View.
    1. View Settings, select your index.
    2. Create a page (this will become our catalog).
  2. View Display settings.
    1. Format > Show
      Set as ‘Rendered entity’, then in the settings, set your product types to use a ‘Teaser’ view mode instead of the default.

      NOTE: If you don't see the 'Rendered entity' option, this seems to be a bug with Views and happens when you don't select your index before checking the 'Create a page' checkbox. To fix this, just refresh your page to start over. If that doesn't work, flush your caches.

      NOTE:You may need to create this view mode if it doesn’t already exist.

      NOTE:You could alternately use Fields instead of view modes, but I like to keep my product display settings all within the product type’s display settings. Then you can potentially customize the display per product type if you have more than one.

  3. Save the view .
    These basic settings should give us our overall catalog. You can confirm by previewing the view or visiting the page you just created.

Add Fulltext datasource fields for a catalog search field

Now we’ll start setting up a Fulltext search field to let our users filter results using a product search field. The first thing we need to do is add some datasource fields to our index that the search will use.

  1. Go to your Search API Index and go to the Fields tab.
  2. Add Fulltext fields that you would like to be searchable (such as Title, SKU, Category taxonomy name, etc.).
    Here’s an example for adding the title:
    1. Click ‘Add fields’.
    2. Under the ‘Product’ heading, click ‘Add’ beside the ‘Title’ field.

      NOTE: If you’re adding a different field instead, you may need to drill down further into the field by clicking ( + ) next to the field. For example, to make a taxonomy term a searchable field, you would go to Your Vocabulary > Taxonomy Term > Name .

    3. Click ‘Done’.
    4. Set the field ‘Type’ to ‘Fulltext’.
      This is an important step as only Fulltext fields are searchable with the user-entered text search we are currently setting up.

      NOTE: Under the fields section is a ‘Data Types’ section. You can open that to read information about each available type.

    5. Optionally change the ‘Boost’ setting.
      If you have more than one Fulltext field, the boost setting allows you to give a higher priority to specific fields for when the terms are being searched.

      For example, multiple products could have a similar title, but each product would have an individual SKU. In this case, SKU could be given a higher boost than title to make sure that search results based on the SKU come back first.

  3. Next, add another field for the ‘Published’ status.
  4. Once you’ve added this field, set it’s type as ‘Boolean’.
  5. Reindex your data (from within the index view tab).

Set up the catalogue search field within the catalogue View

We can now set up the actual search field that our customers will use to find products, and use the datasource fields we added to our index to do this.

  1. Go to your catalog View.
  2. Under ‘Filter criteria’.
    1. Add ‘Fulltext search’ and configure its settings.
      • Check ‘Expose this filter to visitors, to allow them to change it’.
        IMPORTANT:This is what gives the user the ability to use this search field.
      • ‘Filter type to expose’, set as ‘Single filter’.
      • ‘Operator’, set as ‘Contains any of these words’.
      • ‘Filter identifier’, optionally adds an identifier into the url to identify a search term filter.
        (i.e. yoursite.com/products?your-filter-identifier=search-term)
      • Apply/save your settings.
    2. Add ‘Published’ and configure it so that it is equal to true.
      This uses the field we added to the index earlier to make sure the product is actually published. Chances are you don’t want unpublished results shown to your customers.
  3. Under ‘Sort criteria’.
    1. Add ‘Relevance’.
    2. Configure so that the order is sorted ascending.
      This will show the more relevant results first (factoring in the boost you may have applied to your index fields).
  4. Now we need to expose the search field to our customers. To do this:
    1. Open the ‘Advanced’ section of your catalog view.
    2. In the ‘Exposed Form’ area.
      • Set ‘Exposed form in block’ to ‘Yes’.
        This creates a block containing a search field that we can place on the site somewhere.
      • Set ‘Exposed form style’ to ‘Basic’ and update the settings. For now, the settings you might change are customizing the submit button text and maybe including a reset button.
  5. Add the search block to your site.
    Admin menu path:/admin/structure/block
    1. In your preferred region, click the ‘Place block’ button.
    2. Find the Views block that starts with ‘Exposed form’ and click ‘Place block’.
      Its full name will be determined by you view’s machine name and page display name (i.e. Exposed form: products-page_1).
    3. Configure the block as you see fit, and save.
  6. Test your search!
    You should now be able to see the search field on your site frontend and try it out.

Add more datasource fields for sorting options

We can optionally sort the catalogue and search results with some additional sorting filters, such as sorting by Title, Price, Date added, etc. Let’s add the ability to sort our products by title with the option to choose ascending or descending order.

  1. Go to your Search API Index fields and add another 'Title' field the same as you did earlier. However, this time you want to change the field ‘Type’ to ‘String’. You should now have two Title fields added, one as ‘Fulltext’ and one as ‘String’.

    NOTE: The field type can be different depending on what field you’re adding. If you’re adding a sorting field such as Price > Number, you might use the ‘Decimal’ field type.

    TIP: I would recommend changing the label for the new Title field to something like ‘Title for sorting’ so that it’s easier to identify later. You could even change the fulltext Title label to ‘Title for search’, just to keep them organized and easy to understand.

  2. Reindex your data (from within the index view tab).
  3. Go to your catalogue View.
    1. Under ‘Sort criteria’.
      • Add the new title datasource and configure it.
        • Check ‘Expose this sort to visitors, to allow them to change it’.
          IMPORTANT: This is what gives the user the ability to use this sorting option.
        • Add a label for the filter
        • Set the initial sorting method.
      • Add any additional sorting fields if you added more.
    2. Open the settings for the ‘Exposed form style’ (within the view’s ‘Advanced’ section).
      • Check ‘Allow people to choose the sort order’.
      • Update the labels as you see fit.
    3. Save your view!
      Refresh your catalogue page and you should now see sorting options available in the search block that you added earlier.

      TIP: If you DO NOT see the sorting options, this is a bug and is easily fixed. All you need to do is remove the search block and then re-add it.

      TIP: You can place this block in multiple regions of your site and hide the elements you don’t want to see with CSS. This way you can have a block with the site search and no filters in your header, and then also have another block on your catalog pages that shows the sorting filters but no search field.

Add Facets to the catalogue

The filters we added earlier can only be used one at a time, however, often we want to filter the results based on a number of different options. For example, if I’m browsing an online store looking for shoes of a certain style and size, I don’t want to see everything else the store has to offer. I want to be able to go to a ‘shoe’ category, then pick the ‘type’ of shoe that I’m after, and finally pick the ‘size’ of shoe that’s relevant to me. I want to see all of the results that fit that criteria. Facets lets you use taxonomy (and other datasources) to achieve this.

Let’s add a Facet that uses the taxonomy vocabulary we created in the initial store setup. This will be our main catalogue menu for narrowing down the product results. Each facet that is created creates a block that we can add into any region of our template.

  1. Add a Search API index field for your taxonomy vocabulary. Set the field ‘Type’ as ‘String’.

    TIP: Like we did earlier, I would recommend renaming the label for this field to something like ‘Categories for Facet’.

  2. Reindex your data (from within the index view tab).
  3. Go to the Facets page.
    Admin: Configuration > Search and metadata > Facets
    Admin menu path: /admin/config/search/facets

    You should see a ‘Facet source’ available to use. When we created a View using our index, this is what added the Facet source here. Now that we have a source, we can create Facets to filter it.

  4. Click ‘Add facet’.
    1. Choose the ‘Facet source’ to use.
    2. Select the index ‘Field’ that this Facet will use (i.e. Categories for Facet, or whatever you labelled your field).
    3. Name your Facet (i.e. Categories).
  5. Configure the Facet.
    This will cover the basic settings that you will need. Start with this and then you can always play around with other settings later. Each setting has a pretty good description to help you understand what it does.
    1. Widget.
      Choose a ‘Widget’ for displaying the categories. For categories, I like to use ‘List of checkboxes’.
    2. Facet Settings.
      Check the following:
      • Transform entity ID to label.
      • Hide facet when facet source is not rendered.
      • URL alias as ‘cat’ (or whatever you like).
      • Empty facet behavior as ‘Do not display facet’.
      • Operator as ‘OR’.
      • Use hierarchy.
      • Enable parent when child gets disabled.
      • NOTE: the Facets Pretty Paths module can be used to give you nicer looking URL paths.
    3. Facet Sorting.
      Configure as you see fit. In this example, I would only check the following.These settings make sure that the taxonomy follows the same order that you have set within the vocabulary itself.
      • Sort by taxonomy term weight.
      • Sort order as ‘Ascending’.
    4. Save.
  6. Add the Facet block to your site.
    Admin: Structure > Block layout
    Admin menu path: /admin/structure/block
    1. In your preferred region, click the ‘Place block’ button.
    2. Find the ‘Categories’ facet block (or whatever you named it) and click ‘Place block’.
    3. Configure the block as you see fit.
    4. Save.
  7. Test your Facet!
    You should now see your Facet on the catalog page. Click the checkboxes and test out how it works!

One last thing...

The sites we've been building use the Facets Pretty Paths module for making nicer looking URLs with our catalog and filters. For a while we were plagued with a problem where, when the user selects a Facet category and then uses the sorting options, the Facets would uncheck and reset. This is obviously not good because the user is trying to sort the filtered down items, not the overall catalog. We need to be able to maintain the active facets when using the filters.

Luckily, a coworker came up with this nice little solutions that you can apply to your theme's .theme file. You just need to replace YOUR_THEME,YOUR-VIEW (i.e. products-page-1), and YOUR-PATH (i.e. products) in the code below. Ideally, this will be fixed within the module itself soon, but this will work while we wait.

/**
* Implements hook_form_alter().
*/
function YOUR_THEME_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Store - Product Listing view exposed form.
if ($form['#id'] == 'views-exposed-form-YOUR-VIEW') {
$current_path = \Drupal::request()->getRequestUri();

// If current path is within your catalog, correct the form action path.
if ((strpos($current_path, '/YOUR-PATH') === 0)) {
// Fix for views using facets with pretty paths enabled.
// Replace form action with current path to maintain active facets.
$form['#action'] = $current_path;
}
}
}

Done!

There you have it! You have now created a Search API index using Solr, setup a View to display the results of the index, and then implemented 3 different ways to filter the results (search, sorting and Facets). This is the start of an awesome product catalogue and you can expand on it with more datasource fields however you want. Cool!

Contact us and learn more about our custom ecommerce solutions

Editor’s note: This article was originally published on July 12, 2018, and has been updated for freshness, accuracy and comprehensiveness.

 
Apr 15 2021
Apr 15
[embedded content]

Don’t forget to subscribe to our YouTube channel to stay up-to-date.

File Management Series

In Drupal, files can be uploaded to the site for users to view or download. This can be easily achieved by creating a file or image field on content types.

In the back end, a list of all the files uploaded can be viewed by the administrator, by going to Administration > Content > Files (admin/content/files).

Files uploaded can be easily removed from the individual content pages (see the image below), but removing them entirely from the system is another story. You might be surprised that you cannot find a button, a link or an option to remove these deleted files entirely from the system.

After deleting files on content, if you go to the Files (admin/content/files) page, you will find the deleted files are still there, and the status still shows ‘Permanent’, even though they are already removed from the nodes. It seems very confusing. Removing files from content and removing files from the system are two different things in Drupal.

To remove files from the system, we need to add the file delete function. This can be achieved by installing the File Delete module.

Table of Contents

Getting Started

The File Delete module adds the ability to delete files from within the administration menu.

To download the module run the following Composer command:

composer require drupal/file_delete

How to Configure

After installing the module, we need to add a ‘Delete link’ to the Files page.  We can do that by going to Administration > Structure > Views and edit the views of the Files list. By default, the name of the views is ‘Files’:

To add the ‘Delete link’, we need to add a field called ‘Link to delete File’ in this views, which appears like the following image:

Select this field.  We can keep everything by default, and then click ‘apply’ and save the views.  Next, go to Administration > Content > Files, and there we shall see the ‘delete’ link there, like the following:

How to Use

With this ‘delete link’, we can remove the delete files from the system by clicking on the ‘delete link’ shown in the above diagram. Note that Drupal will protect all the files, and will not allow files to be deleted when they are being used in any content.  If you try to delete a file which is still being used in a node, you will see this following error message.

The Tricky Part

In some cases, even if you have deleted the files from the nodes, and the files are no longer visible in the nodes, you might still find this error message disallowing you to remove the file from the system.

But that might be correct because these files might still be used in content. The nodes where these files came from might have more than one revision. These files removed from the current revision might still be attached to the previous revisions.

When this happens, check out the nodes again for multiple revisions, like the following example:

Only when all attachments (including the old revisions) are cleared, then these files can really be removed from the system. So in summary, when we delete the files, we need to make sure that these files are not being used in any content, including the old revisions.

The File Status

Even though you can successful remove deleted files from the system using the ‘Delete link”, you will still find the following:

  • The file is still on the list
  • The status of the file is changed from ‘Permanent’ to ‘Temporary’
  • The file is used in 0 places (that means it is not used with any nodes)

Following is an example how it will look like:

But why do these deleted files showing ‘temporarily’ status still appear in the list?  Here is why …

In fact, the files removal process has already been initiated. Drupal will delete the file in the following sequence:

  1. Change the status from ‘Permanent’ to ‘Temporary’
  2. Wait for a minimum of 6 hours
  3. Upon the next cron-run after 6 hours, the system will really remove these temporary files

That is why you still see these deleted files in the list within this 6-hour period.  This is how Drupal manages temporary files.

Temporary File Management

If you go to Administration > Configuration > Media > File system, you will find a configuration and explanation at the bottom of the page:

Here it says temporary files will be deleted in the next cron run after 6 hours. Note that 6 hours is the minimum. This ‘6 hours’ setting can be changed, but 6 hours is already the minimum.  See the following options for the configuration:

With the ‘Media’ module, files can also be added as media documents instead of a ‘File’ field.  These files added as media documents can also be deleted, but it will be a little bit different in the operation. Again, the system will not allow deleting files that are still being used.

To delete such files added as media entities, pay attention to the following:

  1. Confirm that the media is not being used on the site first.
  2. Go to Administration > Content > Media to the list of media entities, and delete the designated items here first.
  3. Next go to Administration > Content > Files, and then delete the designated files here.

It will go through the 6-hour cycle described above, but we should leave it to the system to handle it from here.

The Files list is within the administration area, accessible by the administrator. But if other users will require access to this area to delete the files, user permissions need to be configured specifically to this module.

Using Drush

If you use Drush, you can delete files straight away using the “drush entity:delete” command.

For example:

drush entity:delete file ID

This command will remove the file from the Files page and delete it from the file system and you won’t have to wait.

Summary

The file delete procedure in Drupal is not that user-friendly. The module provides the ability to delete files in Drupal.  The procedure for deleting files is a little bit complicated, due to the fact that files can be used therefore associated with different entities in the system.  Also, for this reason, it is suggested that file delete be handled by an experienced administrator with the right permission and access to the administration area.

Editorial Team

About Editorial Team

Web development experts producing the best tutorials on the web. Want to join our team? Get paid to write tutorials.

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