Upgrade Your Drupal Skills

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

See Advanced Courses NAH, I know Enough
Dec 03 2020
Dec 03
Lebkuchenherz undpaul

We really zeroed for the first time. undpaul had its 10th birthday yesterday - and that was celebrated! With hot wine, delicious food, party hats, and memories of one or the other highlight with the undpaul team - of course all Corona-compliant in a remote meeting.

Ten years it is already... It feels a little bit as if it was only a few moments ago that undpaul was founded on a bitterly cold December day 2010 in Hannover. We have experienced and learned a lot during this time, worked on exciting projects and got together with wonderful colleagues.

"The most wonderful Drupal agency in Germany" - says Stefan about undpaul.

That is true so far, we agree. But not only that is what makes undpaul. Of course there are keywords like Drupal, experience, quality and remote work / new work. But above all, our team, collegiality, flexibility, fun, commitment and integration make us who we are.

Karte 10 Jahre undpaul

We are happy that we have come so far together and wish us another 10 wonderful years with you!

Thanks to all of you who have accompanied us so far - your business partners with the new challenging projects, you undpaul friends and Drupal community with whom we spent so many hours and of course the whole undpaul team for the daily fun.

Danke mit Signaturen

P.S. If you want to know something about our beginnings, you can find more information in our blog post for our 3rd birthday. There you will also find answers to the often asked question "Where does the name undpaul come from and who is Paul?".

Dec 02 2020
Dec 02

You Might Also Like

Many platforms are advertising the ability to manage content in one place while publishing it to multiple channels. They provide a way to model, manage, and create content and then expose that content via an API. 

These are decoupled-only (or headless) back-ends. The only way to present your content is to create an application that consumes the API, interprets it, and renders the content in your desired format.

Contentful is one such platform, and in this article, we’ll be comparing Contentful’s capabilities to Drupal’s capabilities as decoupled content providers. We’ll be using Drupal Core’s JSON: API, which requires no additional configuration to get up and running and is the most popular way for Drupal to serve as a decoupled back-end.

We’ll cover the following:

In the end, we’ll answer the question: can Drupal do anything that Contentful can do? The answer to that is yes, and more, though it takes different paths to get there.

Content Modeling

A good CMS experience starts with content modeling capabilities. Can we accurately represent the data that we need? Can we enable content creation in a well-organized way and defined based on an overarching content strategy?

Like Drupal, Contentful offers a flexible way to create content types and relate them to each other.

Field types

Contentful offers the following field types:

  • Rich text - text formatting with entity embeds.
  • Text - short or long text.
  • Number - integer or decimal.
  • Date and time - can be date only or date with time.
  • Location - latitude and longitude.
  • Media - images, videos, and other files.
  • Boolean
  • JSON object - arbitrary data in JSON format.
  • Reference - reference other content.

How does Drupal compare to this line-up? Drupal Core contains most of these without needing to install other modules.

Drupal includes a few more format-specific field types, like Email and Link. Contentful doesn’t have these extra field types because it has a “Match a specific pattern” validation you can apply to any text field. You can use a regular expression or one of the supplied patterns (Email, URL, Phone number, etc.)

But this is only for immediate validation when creating content. These pattern validations do not change the underlying schema, and there are no distinct data types. As far as any consumer of a Contentful API is concerned, any text field, no matter the pattern validation applied, should be treated as normal text.

You could mimic the same approach in Drupal with the Field Validation module. But there are benefits to how Drupal implements data types (like Email or Link), especially for the back-end. An automated job that checked for broken links, for example, benefits from knowing that something is a link.

Rich text fields include a WYSIWYG editor similar to Drupal, and setting it up is simple and clear. It includes a toggle for most of what you would want to allow: 

  • Headings (H1 through H6)
  • Bold, italic, and underline buttons
  • Basic code formatting
  • Blockquotes
  • Hyperlinks
  • Ordered and unordered lists
  • Embeds of media or other content

What is Drupal Core missing in terms of field types and modeling?

  1. Location - This gap can be filled with the Geofield module.
  2. JSON object - For Contentful, this is the field type you can use to inject whatever data you want into a content type, and there isn’t a corresponding field type that matches what you need. Of course, it’s not very user-friendly for editors. It is very likely the Drupal landscape has the module you need for the data you want to store, but there is also the JSON Field module if you want to mimic the field type itself.

Contentful has one way of doing something, like how to include images and other media. And it works well for the 80%.

With Drupal, there are different ways to do this, even with just what is included in Drupal Core. You have to make a decision upfront, and if you want to switch later, it could be a huge development effort. You could use normal file fields and the basic image embedding offered by the built-in CKEditor.

Or you could enable the Media and Media Library modules, which will use a different type of field and a different way to embed media into rich text. And your entire paradigm changes.

Contentful’s biased approach saves you some brain cycles in figuring out how you want to accomplish some things. It just works. Drupal requires more planning and setup at the beginning. This will be a common theme for other areas of comparison as well.

What is Contentful missing in terms of field types and modeling?

The easiest way to answer this is to just point to the Drupal module ecosystem. Since it is open-source, there are a wide variety of contributions, and since Drupal encourages compatibility, many of these modules work together in interesting ways. 

However, this huge library can also be Drupal’s weakness. It can be hard to find what you are looking for if you don’t already know the correct terminology, and it tends to be less polished. There are sometimes multiple ways of doing something, and unless you have been involved in Drupal for years, you don’t know the “best” way.

Analysis paralysis.

We ran into this same problem while writing this article. What exactly do we include in this section beyond waving our hands in the direction of Drupal’s module directory?

In the end, we landed on some “must-haves” based on common usage, following the 80/20 rule.

  • Multi-value fields - Other than for its Reference and text fields, Contentful does not provide multi-value fields like Drupal. If you want multiple values for a number or location, you need to create multiple fields. That can get cumbersome for both content type setup and the eventual rendering of the content by a consumer. Grouping the related values would require naming all the fields a certain way, which leads to fragility. Drupal’s way of handling this type of data provides clarity and intention.
  • Physical addresses - Drupal’s Address module is a robust modeling of complicated data that differs from one geographic area to the next. Contentful requires you to build up an address field from multiple text fields or write a custom extension.
  • Extensible rich text editor - Drupal uses the mature CKEditor (though you can switch this out if you want), and plugins can be added to extend its functionality. Contentful’s Rich Text editor cannot be modified, though you can take their code for it and modify it to your needs. That means you miss out on any updates and improvements they might push.

Drupal’s Entity structure is also an improvement over Contentful’s entity structure. 

Contentful only has “Content” that you can model. In Drupal, Users, Media, Taxonomy Terms, and much more are entities that can have fields and complex modeling. With Users in particular, this adds some exciting possibilities for things like advanced access control, workflows, and personalization. 

Some of this will simply not be possible in Contentful.

Drupal went through its “everything is content” phase and came out the other side as a mature tool capable of modeling complex domains and requirements. It paid for this maturity with blood, sweat, and tears. Previous versions have the scars to prove it. 

Contentful will also have to learn similar lessons as it matures.

Editorial Experience

How easy is it to find, create, and manage content? Contentful’s default editorial experience looks great and is easy to use. Everything feels fluid and natural. This is one of the natural benefits of a SaaS product, as they have a given feature set and don’t need to be able to solve every editorial problem imaginable.

But this just pertains to the default Contentful Web App. 

If your team is familiar with React, you can customize the editorial experience at the level of a page, content type, field, sidebar, and dialogs. But then you lose some of the benefits of Contentful’s sensible defaults.

With some“locations,” you need to implement your own error handling, rich text data entry, and closely tracking release updates to ensure the underlying data structure has not changed. You are looking at the same development effort as a complex, medium-sized React application. Field and widget customizations have the complexity of writing an individual React component or subcomponent. The good news is that Contentful has released their field editors as open-source, so you have some guidance and/or things you can reuse when writing your own.

This is something you should keep in mind when evaluating Contentful, especially if you feel you will need unique customizations for how you manage content.

Creating content

Each field type has a good selection of widgets to choose from: text fields, drop-downs, radio buttons, URL formatters, and more. Contentful number fields even have the option to enter them as stars to mimic review sites. Long text fields (that are not rich text) have the option for Markdown entry.

You can add existing references or create a piece of content at the same time as referencing it. This can also be done in the context of a rich text field to embed content. It feels intuitive.

Content views

The default content view lists all content in the system, with easy ways to filter that list of content. You can filter by content type and the value of any field, including reference fields. 

You can save any combination of filters as its own view for quick access later. This view can be saved as a “shared view” for everyone or one for your own use. This is incredibly helpful, as it gives editors more autonomy. It’s as easy as typing in a name and clicking “save.”

Translations

Contentful allows you to add locales for content translation. You can then mark fields as translatable. Their default editorial app allows you to switch between locales when creating or editing content, displaying the proper fields.

If you want more than 10 locales, however, you will need their Enterprise tier. In addition, there is no way to translate the default editorial interface. 

If you want a localized experience for your editors, you will need to write your own editorial app.

What is Drupal Core missing in terms of the editorial experience?

  • Duplicating content - This gap can be filled with the Entity Clone module.
  • Entity usage - This gap can be filled with the Entity Usage module, though this can present some scalability issues with some setups.
  • Scheduling content - This gap can be filled with the Scheduler module.
  • Search or create an entity to reference - With a combination of Embed, Entity Embed, Entity Browser, and Inline Entity Form, you can reach functional parity with Contentful’s referencing experience. It takes some effort to set up, but it can be done without any custom code. See images below.
  • Revision comparison and restoration - This gap can be partially filled with the Diff module. However, the out-of-the-box interface is not as nice or intuitive as Contentful’s, which allows for easy field-level restoration. It is straightforward to view differences at a glance and roll back only the fields you want. Drupal has full revision rollback capabilities but is less polished.

The ability for editors to save their own views is useful and not something Drupal can do easily. Any new View, because it is stored in configuration, will require some developer time and a deployment.

What is Contentful missing in terms of the editorial experience?

Drupal has a lot of options for you to craft a good experience for your editors. While many things will not look as sleek or polished as Contentful (a problem being tackled by the Admin UI & Javascript Modernisation Initiative), you can get close. 

Not only are there administration themes looking to fill some gaps, like Gin, there is also plenty you can get done in Drupal through clicking some buttons in the user interface. Doing something similar in Contentful would mean custom development of a React application or component.

  • Form organization - The Field Group module provides custom grouping of fields that allow easy customizations of the editorial experience. This is useful for content types with a lot of fields. With Contentful, you must have a fully custom “Entry Editor.”
  • Multi-value fields - This was also a line-item for content modeling, but it also applies to the editorial experience. There are no multi-value fields for some of their data types in Contentful, so you will not be able to have a widget with checkboxes on many of the field types. Not without heavy customization, at least.
  • User roles and permissions - Drupal gives you unlimited granularity in the roles you define. Contentful limits the roles you can have. The first paid tier gives you some more predefined roles, but you must have an Enterprise-tier account to have custom roles and permissions. 
  • Editorial workflows - Drupal Core includes Content Moderation module and the Workflows module. With them, you can define an unlimited amount of arbitrary publishing states and workflows. No matter how large or varied your team, you can map your ideal workflow and implement it. Because of Contentful’s limited roles, advanced workflows are not possible unless you upgrade to the Enterprise tier.
  • Advanced views - While editors cannot easily create their own content views, Drupal’s View system can create more varied experiences, with the ability to add any field to the view, pull in relationships, and perform bulk operations. If you have a development team working on the back-end anyway, it is effortless to roll out new content views based on particular needs.
  • Translations - Drupal provides unlimited locales. You can also translate the editorial interface without any special customization and without rewriting the whole thing from scratch. Translation workflows can also be combined with more advanced editorial workflows, so Drupal translations can fit within the way your editors want to work.

More on multi-value fields. No doubt Contentful would recommend you create a new content type for anything that needs to be multi-valued. That way, editors can add one to many references to that content, and more, that content can be re-used. It helps things stay organized.

But that seems like overkill for something that just needs a single field of data, and if you need more than 48 content types, you will need the Enterprise tier. You will then be charged accordingly for the number of content types that you need.

Drupal’s flexibility, with unlimited content types and multi-value fields, is something to keep in mind.

The API

Here is the bread and butter of what Contentful offers: the content API. We’ll look at how it measures up to the API included in Drupal Core, JSON: API. For this overview, we will only look at the Content Delivery API, though both Contentful and Drupal have ways to create content through an API and ways to call and preview unpublished content. 

For our comparisons, we have created the same content model in both Contentful and Drupal 8, populated with the same data. This gives us a good sampling of data types and organization to make a good comparison. This is a simple music library.

  • Artist - A Name field, an About field that is rich text so we can include embedded entities, a Latest Album reference field that will reference an Album content type, and a Contact field that will hold an email address.
  • Album - A Title field, a Description field, a Cover Art field so we can look at Media assets and management, a Release Date field for a date/time sample, an Artist field that references an Artist content type, and a Tracks reference that references many entities of the Track content type.
  • Track - only a Title field.

Single Content Queries

This is the API response for the Abbey Road album:

Request format: 

https://cdn.contentful.com/spaces/{space_id}/environments/master/entries/{entry_id}?access_token={access_token}

{
    "sys": {
        "space": {
            "sys": {
                "type": "Link",
                "linkType": "Space",
                "id": "79u36k13bxm5"
            }
        },
        "id": "2oc0DNVizJuFLoXsG7EHwi",
        "type": "Entry",
        "createdAt": "2020-11-12T22:28:11.031Z",
        "updatedAt": "2020-11-12T22:38:16.502Z",
        "environment": {
            "sys": {
                "id": "master",
                "type": "Link",
                "linkType": "Environment"
            }
        },
        "revision": 2,
        "contentType": {
            "sys": {
                "type": "Link",
                "linkType": "ContentType",
                "id": "album"
            }
        },
        "locale": "en-US"
    },
    "fields": {
        "title": "Abbey Road",
        "releaseDate": "1969-09-26",
        "description": "Abbey Road is the eleventh studio album by the English rock band the Beatles",
        "coverArt": {
            "sys": {
                "type": "Link",
                "linkType": "Asset",
                "id": "32z3JMUzfZuUTCv8EtCumB"
            }
        },
        "tracks": [
            {
                "sys": {
                    "type": "Link",
                    "linkType": "Entry",
                    "id": "3TAx53F4EXxz3YVuGJYZql"
                }
            },
            {
                "sys": {
                    "type": "Link",
                    "linkType": "Entry",
                    "id": "26HTJnrAXT3UgQzPuQx5AA"
                }
            },
            {
                "sys": {
                    "type": "Link",
                    "linkType": "Entry",
                    "id": "1F6nqI6J96D7j4KlOQrRvQ"
                }
            },
            {
                "sys": {
                    "type": "Link",
                    "linkType": "Entry",
                    "id": "3veIx6bwvs6EuJz41308Nk"
                }
            },
            {
                "sys": {
                    "type": "Link",
                    "linkType": "Entry",
                    "id": "1Dhy3jECJdyNTYCrQgxQwk"
                }
            }
        ],
        "artist": {
            "sys": {
                "type": "Link",
                "linkType": "Entry",
                "id": "Xm0gwlpQGITlLvcyvTyyM"
            }
        }
    }
}

Here is the same data represented by Drupal’s content API.

Request format: https://example.com/jsonapi/node/{type}/{uuid}

{
    "jsonapi": {
        "version": "1.0",
        "meta": {
            "links": {
                "self": {
                    "href": "http://jsonapi.org/format/1.0/"
                }
            }
        }
    },
    "data": {
        "type": "node--album",
        "id": "df825a90-2fb8-49a1-9fda-022504bc9fb8",
        "links": {
            "self": {
                "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8?resourceVersion=id%3A7"
            }
        },
        "attributes": {
            "drupal_internal__nid": 7,
            "drupal_internal__vid": 7,
            "langcode": "en",
            "revision_timestamp": "2020-11-24T21:00:29+00:00",
            "revision_log": null,
            "status": true,
            "title": "Abbey Road",
            "created": "2020-11-24T20:54:58+00:00",
            "changed": "2020-11-24T21:00:29+00:00",
            "promote": true,
            "sticky": false,
            "default_langcode": true,
            "revision_translation_affected": true,
            "path": {
                "alias": null,
                "pid": null,
                "langcode": "en"
            },
            "field_description": "Abbey Road is the eleventh studio album by the English rock band the Beatles",
            "field_release_date": "1969-09-26T21:49:44+00:00"
        },
        "relationships": {
            "node_type": {
                "data": {
                    "type": "node_type--node_type",
                    "id": "2ba6452d-ac91-48b7-b1a8-a7ffd1ab9cec"
                },
                "links": {
                    "related": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/node_type?resourceVersion=id%3A7"
                    },
                    "self": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/relationships/node_type?resourceVersion=id%3A7"
                    }
                }
            },
            "revision_uid": {
                "data": {
                    "type": "user--user",
                    "id": "441881cb-202d-4804-9832-9f42e32e48c0"
                },
                "links": {
                    "related": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/revision_uid?resourceVersion=id%3A7"
                    },
                    "self": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/relationships/revision_uid?resourceVersion=id%3A7"
                    }
                }
            },
            "uid": {
                "data": {
                    "type": "user--user",
                    "id": "441881cb-202d-4804-9832-9f42e32e48c0"
                },
                "links": {
                    "related": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/uid?resourceVersion=id%3A7"
                    },
                    "self": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/relationships/uid?resourceVersion=id%3A7"
                    }
                }
            },
            "field_artist": {
                "data": {
                    "type": "node--artist",
                    "id": "1e3b51ea-b6b8-417b-89a0-ca14772eb223"
                },
                "links": {
                    "related": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/field_artist?resourceVersion=id%3A7"
                    },
                    "self": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/relationships/field_artist?resourceVersion=id%3A7"
                    }
                }
            },
            "field_cover_art": {
                "data": {
                    "type": "media--image",
                    "id": "f8d292a1-4557-47b0-8f0b-a059f103be24"
                },
                "links": {
                    "related": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/field_cover_art?resourceVersion=id%3A7"
                    },
                    "self": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/relationships/field_cover_art?resourceVersion=id%3A7"
                    }
                }
            },
            "field_tracks": {
                "data": [
                    {
                        "type": "node--track",
                        "id": "922b838c-b63f-42ef-acbb-4e103cf640ac"
                    },
                    {
                        "type": "node--track",
                        "id": "8f15d5d4-1163-4f7b-be98-1b27cf054546"
                    },
                    {
                        "type": "node--track",
                        "id": "6f69fe91-19a7-4a12-92d2-2f0139102072"
                    },
                    {
                        "type": "node--track",
                        "id": "dcc7e5d0-9993-4c57-8a0e-edc9980d6e09"
                    },
                    {
                        "type": "node--track",
                        "id": "923c4da6-b377-4a30-8b81-c980d34f3c92"
                    }
                ],
                "links": {
                    "related": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/field_tracks?resourceVersion=id%3A7"
                    },
                    "self": {
                        "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8/relationships/field_tracks?resourceVersion=id%3A7"
                    }
                }
            }
        }
    },
    "links": {
        "self": {
            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/album/df825a90-2fb8-49a1-9fda-022504bc9fb8"
        }
    }
}

All of the relevant data is easily accessible, though Drupal’s is a little more verbose. This is partly because Drupal’s content entities have more built-in fields by default.

Both list references with their type and their unique ID so that information can be retrieved with subsequent calls.

Contentful:

"sys": {
    "type": "Link",
    "linkType": "Entry",
    "id": "26HTJnrAXT3UgQzPuQx5AA"
}

Drupal:

{
    "type": "node--track",
    "id": "dcc7e5d0-9993-4c57-8a0e-edc9980d6e09"
},

Notice that Contentful’s response has no author or user. This is because its users are purely editorial in context and are not supposed to be part of the model. If you wanted to track authors and pass them via the API, you would need to create an Author content type and another reference field.

Both Contentful and Drupal also allow you to:

  • Resolve the referenced entities' data, so you don’t need to make subsequent API calls for each referenced entity. In our example of an album, we would get terrible performance if we made an API call for every single track. We can add an “include” parameter that puts this information in a separate array.
  • Limit the fields that are returned in a response to limit the verbosity and payload size.

Content Collections

You can pull a collection of entities that match certain criteria, and both have robust filtering mechanisms to find specific content. There are differences in implementation, but you can achieve the same result with both, filtering by any field with a wide range of operators (equal, not equal, greater than, etc.) and ordering the results based on a certain field.

Read about Contentful’s full range of search parameters here and compare them to Drupal’s JSON API filtering capabilities here.

Contentful does include some intriguing full-text search capabilities out-of-the-box that searches across all fields. Typically, a decoupled application will use a dedicated service for search, but if your search needs are rudimentary, Contentful’s default might meet your needs.

On the other hand, because of the way Drupal implements it’s filtering, you can do per-field text searches with pattern operators like 'STARTS_WITH,' 'CONTAINS,' and 'ENDS_WITH.’ This can be useful. 

You can also get a rudimentary full-text search running on Drupal with the JSON: API Search API module.

Here is a Contentful collection example, truncated to the first two results.

Request format: 

https://cdn.contentful.com/spaces/{space_id}/environments/master/entries?access_token={access_token}&content_type={type}


{
    "sys": {
        "type": "Array"
    },
    "total": 9,
    "skip": 0,
    "limit": 100,
    "items": [
        {
            "sys": {
                "space": {
                    "sys": {
                        "type": "Link",
                        "linkType": "Space",
                        "id": "79u36k13bxm5"
                    }
                },
                "id": "7w2rXd9fQfTOXuAEPcqmqB",
                "type": "Entry",
                "createdAt": "2020-11-17T19:38:08.569Z",
                "updatedAt": "2020-11-17T19:38:08.569Z",
                "environment": {
                    "sys": {
                        "id": "master",
                        "type": "Link",
                        "linkType": "Environment"
                    }
                },
                "revision": 1,
                "contentType": {
                    "sys": {
                        "type": "Link",
                        "linkType": "ContentType",
                        "id": "song"
                    }
                },
                "locale": "en-US"
            },
            "fields": {
                "title": "Please Please Me"
            }
        },
        {
            "sys": {
                "space": {
                    "sys": {
                        "type": "Link",
                        "linkType": "Space",
                        "id": "79u36k13bxm5"
                    }
                },
                "id": "7uFcbd7Q3vyG3kpibaPWfp",
                "type": "Entry",
                "createdAt": "2020-11-17T19:37:58.370Z",
                "updatedAt": "2020-11-17T19:37:58.370Z",
                "environment": {
                    "sys": {
                        "id": "master",
                        "type": "Link",
                        "linkType": "Environment"
                    }
                },
                "revision": 1,
                "contentType": {
                    "sys": {
                        "type": "Link",
                        "linkType": "ContentType",
                        "id": "song"
                    }
                },
                "locale": "en-US"
            },
            "fields": {
                "title": "Ask Me Why"
            }
        },
        ..
        .
    ]
}

And here is the Drupal JSON API example, also truncated to the first two results. 

Request format: https://example.com/jsonapi/node/{type}


{
    "jsonapi": {
        "version": "1.0",
        "meta": {
            "links": {
                "self": {
                    "href": "http://jsonapi.org/format/1.0/"
                }
            }
        }
    },
    "data": [
        {
            "type": "node--track",
            "id": "922b838c-b63f-42ef-acbb-4e103cf640ac",
            "links": {
                "self": {
                    "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/922b838c-b63f-42ef-acbb-4e103cf640ac?resourceVersion=id%3A2"
                }
            },
            "attributes": {
                "drupal_internal__nid": 2,
                "drupal_internal__vid": 2,
                "langcode": "en",
                "revision_timestamp": "2020-11-24T20:58:56+00:00",
                "revision_log": null,
                "status": true,
                "title": "Come Together",
                "created": "2020-11-24T20:58:56+00:00",
                "changed": "2020-11-24T20:58:56+00:00",
                "promote": true,
                "sticky": false,
                "default_langcode": true,
                "revision_translation_affected": true,
                "path": {
                    "alias": null,
                    "pid": null,
                    "langcode": "en"
                }
            },
            "relationships": {
                "node_type": {
                    "data": {
                        "type": "node_type--node_type",
                        "id": "d773d9e2-9c75-4547-98af-47cc41f5b28e"
                    },
                    "links": {
                        "related": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/922b838c-b63f-42ef-acbb-4e103cf640ac/node_type?resourceVersion=id%3A2"
                        },
                        "self": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/922b838c-b63f-42ef-acbb-4e103cf640ac/relationships/node_type?resourceVersion=id%3A2"
                        }
                    }
                },
                "revision_uid": {
                    "data": {
                        "type": "user--user",
                        "id": "441881cb-202d-4804-9832-9f42e32e48c0"
                    },
                    "links": {
                        "related": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/922b838c-b63f-42ef-acbb-4e103cf640ac/revision_uid?resourceVersion=id%3A2"
                        },
                        "self": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/922b838c-b63f-42ef-acbb-4e103cf640ac/relationships/revision_uid?resourceVersion=id%3A2"
                        }
                    }
                },
                "uid": {
                    "data": {
                        "type": "user--user",
                        "id": "441881cb-202d-4804-9832-9f42e32e48c0"
                    },
                    "links": {
                        "related": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/922b838c-b63f-42ef-acbb-4e103cf640ac/uid?resourceVersion=id%3A2"
                        },
                        "self": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/922b838c-b63f-42ef-acbb-4e103cf640ac/relationships/uid?resourceVersion=id%3A2"
                        }
                    }
                }
            }
        },
        {
            "type": "node--track",
            "id": "8f15d5d4-1163-4f7b-be98-1b27cf054546",
            "links": {
                "self": {
                    "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/8f15d5d4-1163-4f7b-be98-1b27cf054546?resourceVersion=id%3A3"
                }
            },
            "attributes": {
                "drupal_internal__nid": 3,
                "drupal_internal__vid": 3,
                "langcode": "en",
                "revision_timestamp": "2020-11-24T20:59:01+00:00",
                "revision_log": null,
                "status": true,
                "title": "Something",
                "created": "2020-11-24T20:59:01+00:00",
                "changed": "2020-11-24T20:59:01+00:00",
                "promote": true,
                "sticky": false,
                "default_langcode": true,
                "revision_translation_affected": true,
                "path": {
                    "alias": null,
                    "pid": null,
                    "langcode": "en"
                }
            },
            "relationships": {
                "node_type": {
                    "data": {
                        "type": "node_type--node_type",
                        "id": "d773d9e2-9c75-4547-98af-47cc41f5b28e"
                    },
                    "links": {
                        "related": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/8f15d5d4-1163-4f7b-be98-1b27cf054546/node_type?resourceVersion=id%3A3"
                        },
                        "self": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/8f15d5d4-1163-4f7b-be98-1b27cf054546/relationships/node_type?resourceVersion=id%3A3"
                        }
                    }
                },
                "revision_uid": {
                    "data": {
                        "type": "user--user",
                        "id": "441881cb-202d-4804-9832-9f42e32e48c0"
                    },
                    "links": {
                        "related": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/8f15d5d4-1163-4f7b-be98-1b27cf054546/revision_uid?resourceVersion=id%3A3"
                        },
                        "self": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/8f15d5d4-1163-4f7b-be98-1b27cf054546/relationships/revision_uid?resourceVersion=id%3A3"
                        }
                    }
                },
                "uid": {
                    "data": {
                        "type": "user--user",
                        "id": "441881cb-202d-4804-9832-9f42e32e48c0"
                    },
                    "links": {
                        "related": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/8f15d5d4-1163-4f7b-be98-1b27cf054546/uid?resourceVersion=id%3A3"
                        },
                        "self": {
                            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track/8f15d5d4-1163-4f7b-be98-1b27cf054546/relationships/uid?resourceVersion=id%3A3"
                        }
                    }
                }
            }
        },
        ..
        .
    ],
    "links": {
        "self": {
            "href": "https://dev-music-library-demo.pantheonsite.io/jsonapi/node/track"
        }
    }
}

Rich Text and Embeds

Each system handles rich text and embeds in different ways. First, let’s look at how Contentful returns content with embedded assets.

For this example, we’ll pull our Artist content titled “The Beatles.” This is how the About field is represented:

"about": {
            "data": {},
            "content": [
                {
                    "data": {},
                    "content": [
                        {
                            "data": {},
                            "marks": [],
                            "value": "The Beatles were an English rock band formed in Liverpool in 1960. The group, whose best-known line-up comprised John Lennon, Paul McCartney, George Harrison and Ringo Starr, are regarded as the most influential band of all time.",
                            "nodeType": "text"
                        }
                    ],
                    "nodeType": "paragraph"
                },
                {
                    "data": {},
                    "content": [
                        {
                            "data": {},
                            "marks": [],
                            "value": "They were integral to the development of 1960s counterculture and popular music's recognition as an art form.Rooted in skiffle, beat and 1950s rock and roll, their sound incorporated elements of classical music and traditional pop in innovative ways; the band later explored music styles ranging from ballads and Indian music to psychedelia and hard rock. ",
                            "nodeType": "text"
                        }
                    ],
                    "nodeType": "paragraph"
                },
                {
                    "data": {
                        "target": {
                            "sys": {
                                "id": "6NwAnNO3L14TjyfCpvrf0l",
                                "type": "Link",
                                "linkType": "Asset"
                            }
                        }
                    },
                    "content": [],
                    "nodeType": "embedded-asset-block"
                },
                {
                    "data": {},
                    "content": [
                        {
                            "data": {},
                            "marks": [],
                            "value": "As pioneers in recording, songwriting and artistic presentation, the Beatles revolutionised many aspects of the music industry and were often publicised as leaders of the era's youth and sociocultural movements.",
                            "nodeType": "text"
                        }
                    ],
                    "nodeType": "paragraph"
                },
                {
                    "data": {
                        "target": {
                            "sys": {
                                "id": "XLrFYAYIhAMh7thYq2gxs",
                                "type": "Link",
                                "linkType": "Entry"
                            }
                        }
                    },
                    "content": [],
                    "nodeType": "embedded-entry-block"
                },
                {
                    "data": {},
                    "content": [
                        {
                            "data": {},
                            "marks": [],
                            "value": "Nationwide interest in the Beatles had been piqued with the success of their second UK single and ",
                            "nodeType": "text"
                        },
                        {
                            "data": {
                                "uri": "https://en.wikipedia.org/wiki/Parlophone"
                            },
                            "content": [
                                {
                                    "data": {},
                                    "marks": [],
                                    "value": "Parlophone",
                                    "nodeType": "text"
                                }
                            ],
                            "nodeType": "hyperlink"
                        },
                        {
                            "data": {},
                            "marks": [],
                            "value": ", hoping to take advantage of this, promptly decided to follow it up with an album.",
                            "nodeType": "text"
                        }
                    ],
                    "nodeType": "paragraph"
                },
                {
                    "data": {},
                    "content": [
                        {
                            "data": {},
                            "marks": [],
                            "value": "",
                            "nodeType": "text"
                        }
                    ],
                    "nodeType": "paragraph"
                },
                {
                    "data": {},
                    "content": [
                        {
                            "data": {},
                            "marks": [],
                            "value": "",
                            "nodeType": "text"
                        }
                    ],
                    "nodeType": "paragraph"
                }
            ],
            "nodeType": "document"
        },

It contains no HTML markup. Each paragraph is its own “node” with a nodeType of “paragraph,” each with its own content array of “nodes.” Even links are represented as a different “node.”

Embedded content like images is represented as “embedded-asset-block” or “embedded-entry-block,” with all the data you need to get the information for those items.

If the query is built right, you can also include all of the data for embedded entities in the same API call.

This means you need to build up a page yourself on the front-end. This is like a LEGO brick set that comes with clear instructions. It’s very flexible and makes no assumptions about where this data is going to be rendered.

To compare, here is how Drupal handles a call for the same content.

"field_about": {
        "value": "

The Beatles were an English rock band formed in Liverpool in 1960. The group, whose best-known line-up comprised John Lennon, Paul McCartney, George Harrison and Ringo Starr, are regarded as the most influential band of all time.

\r\n\r\n

They were integral to the development of 1960s counterculture and popular music's recognition as an art form.Rooted in skiffle, beat and 1950s rock and roll, their sound incorporated elements of classical music and traditional pop in innovative ways; the band later explored music styles ranging from ballads and Indian music to psychedelia and hard rock.

\r\n\r\n\r\n\r\n

As pioneers in recording, songwriting and artistic presentation, the Beatles revolutionised many aspects of the music industry and were often publicised as leaders of the era's youth and sociocultural movements.

\r\n\r\n\r\n\r\n

 

\r\n\r\n

Nationwide interest in the Beatles had been piqued with the success of their second UK single and Parlophone, hoping to take advantage of this, promptly decided to follow it up with an album.

\r\n", "format": "basic_html", "processed": "

The Beatles were an English rock band formed in Liverpool in 1960. The group, whose best-known line-up comprised John Lennon, Paul McCartney, George Harrison and Ringo Starr, are regarded as the most influential band of all time.

\n\n

They were integral to the development of 1960s counterculture and popular music's recognition as an art form.Rooted in skiffle, beat and 1950s rock and roll, their sound incorporated elements of classical music and traditional pop in innovative ways; the band later explored music styles ranging from ballads and Indian music to psychedelia and hard rock.

..." },

This is a different approach. Drupal includes both the unfiltered markup and the processed markup for the field, based on the selected format. For simple content, you can just take what is returned in the “processed” key and render it. If you set things up on the back-end properly, this even works with embeds.

For some sites, that’s all you need.

This is the isolated embed code for a media asset and a content entity:

If you want to handle rendering in a more ad-hoc manner, with more flexibility, you will need some way to save embedded entities into an entity reference field on the node. This will let you include their data in the same API request. 

It requires some additional processing on the back-end, as you need to parse the rich text field and grab the entities embedded there. We did something similar on Edutopia with great success.

Conclusion

We could compare a lot more, like previews and image derivatives, but this gives you a good introduction to the differences.

Bottom line: anything Contentful does, Drupal can do as well. You can treat Drupal as a hub for your content, and it will perform admirably. Most gaps in Drupal Core have been filled with stable, secure, and reliable modules.

Contentful is a true API-first platform. It was designed with front-end consumers in mind, and it is very robust in that regard.

Drupal’s focus has been on managing large amounts of content and the editorial workflows that can come with that, as well as modeling diverse types of content. Its API capabilities are good and stable, but they have not been its sole focus. As a result, sometimes there are additional hoops you need to jump through to get your desired result.

Back-end customizations can be done for both Contentful and Drupal. For Contentful, you will want deep React experience. With Drupal, deep PHP experience. 

What does your team look like? If you are hiring an agency to help, what is their expertise? These should be considered while weighing the decision.

Since Contentful is a SaaS product, it has a very polished feature set. But this comes with limited extensibility. Your business will need to adapt to Contentful’s capabilities. Smaller companies will have no problem with this, but larger companies, or companies that are growing fast, might reach the bars of the cage sooner than they thought, finding themselves unable to flex or maneuver.

Drupal, by contrast, cannot be as polished since it doesn’t require you to go down a limited number of predetermined paths. As a result, Drupal places no arbitrary roadblocks to implementing what you need.

If you have a large editorial team with complicated workflow requirements, Drupal is ready to change for your needs. To even start with custom roles on Contentful, you will need the Enterprise tier.

In fact, for most companies with a large web presence, if you go with Contentful, you will need to go with their Enterprise tier. There are too many limitations with the Team tier. This means long-term contracts and big licensing fees. You get a lot in return, like uptime and support SLAs, but you need to take that into consideration.

What are the key advantages of Drupal compared to Contentful?

  • Unlimited users, roles, and permissions with unlimited workflow possibilities.
  • Full translatable content with unlimited locales, including built-in translations for the editorial interface.
  • Large contrib module ecosystem, providing more ways to customize the editorial experience.
  • Granular customizations of API responses.
  • Mature content modeling with unlimited content types.
  • Open-source with no licensing fees and no long-term contracts.

Do you have a decoupled project you are considering? We have helped solve some of the hardest decoupled problems with Drupal, and we would love to help you. Our experience is concrete and practical, not theoretical.

Contact us today.

Dec 02 2020
Dec 02

What’s new in Drupal 9.1.0?

The first feature release of Drupal 9 includes the new experimental Olivero frontend theme and various additions to the Claro administration theme. Installer performance is improved 20% and full Composer 2 and PHP 8 support is available. Images with known dimensions are set to lazy-load by default to improve frontend performance.

Download Drupal 9.1.0

New experimental Olivero theme

A new beta experimental frontend theme has been added to Drupal core called Olivero. This is a new modern and clear theme that is planned to become the new default Drupal theme later (replacing Bartik). Subtheming Olivero is currently not supported, but formal support may be included in the future.

The theme is named after Rachel Olivero (1982-2019). She was the head of the organizational technology group at the National Federation of the Blind, a well-known accessibility expert, a Drupal community contributor, and a friend to many.

Key additions to the Claro theme

The experimental Claro administration theme introduces designs for various key pages: the extensions administration page, views administration, status report and media library received Claro styled designs.

Composer 2 and PHP 8 support

Drupal 9.1 is fully compatible with Composer 2. If you are using Composer 1, now would be a great time to update. Most plugins used on Drupal sites are compatible and/or obsolete with the new version. The memory and performance requirements reduced dramatically, which should improve your experience.

PHP 8 is also supported in Drupal 9.1, including all of Drupal's dependencies. There may be contributed projects that are not fully compatible though. Drupal 9 is still compatible with PHP 7.3 and older. There are various exciting new features in PHP 8, but the JIT compiler and performance improvements are not likely to affect Drupal. Drupal 10 is planned to require PHP 8 in 2022. It is worth examining the support timelines of PHP versions to schedule your platform updates.

Other improvements

Installer performance is improved 20%, so getting a new Drupal site set up will be faster.

Images rendered by Drupal with known dimensions will be set to lazy-load automatically. This means browsers will only load them when they should appear in the viewport of the user, improving the user experience by making content appear faster.

Drupal 10 is planned for mid-2022. While Drupal 9 keeps requiring Symfony 4, Drupal 9.1 includes adjustments required to support Symfony 5 already.

What does this mean for me?

Drupal 8 site owners

Update at least to 8.9.x to continue receiving bug fixes until the end of life of Drupal 8 in November 2021. The next bug-fix release (8.9.11) is scheduled for January 6, 2021. (See the release schedule overview for more information.) As of this release, sites on Drupal 8.8 will no longer receive security coverage.

We suggest that you update from Drupal 8 to Drupal 9 though. Updating is supported directly from 8.8.x and 8.9.x. Of the top 1000 most used drupal.org projects, 85% are updated for Drupal 9, so there is a high likeliness that most of the modules and themes you rely on are compatible.

Drupal 7 site owners

Drupal 7 support was extended to November 28, 2022, and will continue to receive bug and security fixes throughout this time. From November 2022 until at least November 2025, the Drupal 7 Vendor Extended Support program will be offered by vendors.

On the other hand, the migration path for Drupal 7 sites to Drupal 9 is stable. Read more about the migration to Drupal 9.

Translation, module, and theme contributors

Minor releases like Drupal 9.1.0 include backwards-compatible API additions for developers as well as new features.

Since minor releases are backwards-compatible, modules, themes, and translations that supported Drupal 9.0.x and earlier will be compatible with 9.1.x as well. However, the new version does include some changes to strings, user interfaces, internal APIs and API deprecations. This means that some small updates may be required for your translations, modules, and themes. Read the 9.1.0 release notes for a full list of changes that may affect your modules and themes.

This release has advanced the Drupal project significantly and represents the efforts of hundreds of volunteers and contributors from various organizations. Thank you to everyone who contributed to Drupal 9.1.0!

Dec 02 2020
Dec 02

Some minor tweaks were made in Webform 6.x to improve settings, options, behaviors, and features. For example, URL aliases on the Webform module's General setting form are now prefixed with a forward slash. This approach is more consistent with how Drupal core handles URLs/paths.

One of the biggest changes, which does not impact any existing installation of the Webform module, is the Webform module's default 'gender' options are more now inclusive. Personally, I like ensuring that the Webform module user experience reflects the diversity and inclusivity of the Drupal community.

Dec 02 2020
Dec 02

I joined Axelerant with the thrilling purpose of cultivating and fostering their participation and contribution to the Drupal community. And I did, with a defying obstacle: I don’t code and until then I had only heard a few things about Drupal.

As soon as I began this journey, I verified that Drupal (the technology) is completely interlinked with the community that sustains it. To understand one you must know the other. Though you can get a kick out of reading about the advantages of headless Drupal or the improvements that will come with the release of D10, it is obvious that what holds the project together is the willingness of its members to advance, connect, and share knowledge. Hence, the motto “Come for the code, stay for the community.”

Everybody has their first time

In every community, face-to-face encounters are essential to solidify our personal and professional bonds. They are mandatory to get the true sense of a community. Therefore, as soon as I embarked on this endeavor I knew I needed to add an event experience to my Drupal immersion.

Yet, the global crisis unleashed by the COVID-19 pandemic is forbidding us all to attend large and exciting live events. Was I supposed to meet this need online, while surfing a context of widespread virtual fatigue? The truth is that, although we are all a little tired of facing our screens, technology has proven its capability of bringing us close, even eliminating borders. As a result, I decided to sign up for free for my first Drupal Camp, and I was lucky to have debuted with my attendance at the Bay Area Drupal Camp, or BADCamp, which describes itself as the world’s raddest Drupal camp.

Pierina at BAD Camp 2020

Travelling from Buenos Aires to the world’s raddest Drupal camp

The Bay Area Drupal Camp is “An annual celebration of open-source software normally based in Berkeley, California” that has already trained over 3,000 Drupalers. This year, for their very first time, they went the extra mile and went fully virtual from October 14th to 17th.

From day one, the organizers ensured the attendees were aware of the Drupal Code of Conduct, and indeed all the interactions I had and the overall environment were imbued with respect and collaboration.

The first couple of days were exclusively for summits and training. I joined for the last two days of the event to attend sessions. The schedule offered a wide variety of topics for all levels of experience, which allowed me to achieve my goal: understanding the full range of knowledge-sharing and learning that happens in these events, without feeling like an outsider. I was able to participate in meetings related to non-code contributions from which I earned valuable resources.

Thank you for making it happen!

Thanks to the organizers and volunteers who made it happen. Surely it would have been easier to suspend the event until next year, but you took the time and effort to carry it through and the result was impeccable.

609

Registrations

515

Attendees

32

Countries

Congratulations!

What I experienced at BADCamp 2020

Two experienced Drupal contributors from Axelerant participated at BADCamp as speakers: Mohit Aghera and Kunal Kursija. Obviously, I wanted to watch them in action. Their sessions were tagged as “Drupal for beginners”, and they both had over 20 attendees to their meetings. It was very compelling to see how they interacted with the audience, covering concepts as well as practical tips and showcasing live-demos. They answered all questions and provided further examples when needed, and of course, in an open-source collaborative spirit, shared their slides and links to the sample code repositories.

Go ahead, relive the sessions, and check out the resources.

 

 
This will be helpful both for site builders and developers. 

  

Learn about the very tiny, mighty and hidden gems of Drupal, "filters", that process and display the user-submitted content. 

As I was planning my schedule, I literally felt this session title was talking to me. Baddy did a great job explaining specific ways you can contribute to Drupal beyond code. And she managed to make it appealing, sharing her own journey choosing non-code contributions even though she has the needed technical skills. Thanks to her inspiring talk, I realized I can offer valuable support by pitching in with these kinds of contributions. So, if you like to design, you’re good at organizing projects or events, you enjoy writing, reviewing, or translating content, find out how you can help here

This session offered valuable insights towards building the marketing arm of an open-source project, highlighting the importance of storytelling, both within the community and towards external audiences. Suzanne stressed the need to pinpoint whom the Drupal community is talking to, and how to adapt marketing efforts to different personas (from developers encountering Drupal for the first time, but also to marketers and evaluators that won’t ever install Drupal but occupy decision-making positions in organizations). I personally engaged with the idea of telling better stories around code contributions within the community. Good stories are easier to amplify, and knowing the people behind the code makes it straightforward to relate and is always inspiring. Stories boost empathy, motivation and sense of belonging; all things that foster a healthy culture in any community.

The Promote Drupal Initiative already produced valuable resources in this direction: the Drupal brand book (setting design elements but also the tone of voice and the brand personality) and marketing materials such as press releases, pitch decks, and one-pagers. Visit the Promote Drupal page to download the resources and/or if you want to contribute to the Drupal brand.


Overall, I had a rich experience, I witnessed first-hand the power of innovation and knowledge-sharing behind Open Source and I now have proof that the Drupal community is guided by a culture of openness, respect, and collaboration.

P.S 1: If you’re interested in web content accessibility, I recommend you watch this session to learn interesting insights, tools, and distinctions between accessibility, usability, and authentic digital inclusion. Check out the video here.

P.S 2: Thanks again to the BADCamp organizers for including the farm tour and the pet meet & greet, it was a creative and conscious way to mitigate virtual fatigue.

Check out all the recorded sessions of BADCamp 2020 here.

Dec 02 2020
Dec 02

PHP 8 beta 4 is out. In fact, the chances are that by the time you read this, we might even have the first RC.

PHP 8 adds a lot of exciting new features, but at the same time, being a major version, it breaks a lot of previous behaviors and functionalities.

Getting Drupal to work on PHP 8 is not as simple as getting it to work on a new minor release such as PHP 7.4.

The Drupal community began planning to fix the compatibility issues early on. And as releases started rolling out, there were individual issues to address each deprecation, changed method signatures, and other breaking changes. These fixes went into a single issue so that we could run a single test against PHP 8. That is the patch I started with when I wanted to test Drupal 9 with PHP 8. To make it even more fun, I also used Composer 2 for all of these steps.

Why am I writing this?

It’s clear that this article may not have any value at all in some time when Drupal 9 officially supports PHP 8, along with all of its dependencies. Why am I writing this then? For one, I believe writing down things helps clarify the ideas and goals. It serves as documentation that can help throughout the process of experimentation. Secondly, I hope that parts of this article will be useful to people who are trying to upgrade their own complex applications to work with PHP 8.

The challenges I describe here are more relevant to applications that need to support a spectrum of PHP versions, not just one or two.

Drupal 8 supports PHP 7.0 to 7.4 right now and the issue I mentioned earlier also tries to add support for PHP 8 to Drupal 8.9 as well (it looks like it might just happen as well). This makes the challenge of supporting PHP 8 in Drupal even bigger as we have to support several breaking changes simultaneously.

Also, many of the problems may not be relevant to applications that need to run on one version of PHP as they just have to change code to match the changes in PHP 8.

I will also not try to explain all the changes that have gone in to support PHP 8. I’ll just talk about the parts that I analysed, reviewed, or changed myself. With all that said, let’s begin.

Problem 1: Environment and initial setup

Docker is great for setting up quick environments for testing and development. At Axelerant, we usually use Lando for setting up a project (in fact, our project template tool supports generating a default scaffold for Lando). But that wouldn’t fit my needs here because Lando doesn’t support PHP 8 yet. Anyway, docker-compose is much simpler for something like this. I only need two services to begin with–a web server container (with PHP) and a database.

The Docker and PHP community maintain a great starting point in the form of official PHP Docker images in a variety of flavors: CLI, FPM, and with Apache on Buster. We use the last one here and add various PHP extensions and settings optimized for Drupal. I already maintain a collection of Drupal optimized PHP images and I only adapted that to work with the PHP 8 beta 4 image. The only difference is that as pecl is no longer included with PHP (as of PHP 8), I just removed those lines. That meant that the common PHP extensions such as APCu and YAML wouldn’t be available, but that’s okay for the first attempt. (I eventually added them in the image anyway.)

The other service in the docker-compose file is for MariaDB and I use Bitnami’s Docker version here. There’s an official one, but I am more used to the Bitnami one as Lando uses it. I don’t do any fancy setup with MariaDB as this is just for experimentation. You can see the docker-compose.yml and Dockerfile on Github. Apart from the Docker environment, we also need a Drupal site setup. Fortunately, this was very easy with the templating tool I mentioned earlier. Once the axl-template tool is installed, I just run this command:

init-drupal hussainweb/test-d9p8c2 --core-version "^[email protected]"

Typically, this would have been enough for a good starting point, but the template is optimized for composer 1. It includes certain packages that improve the composer’s performance with Drupal. However, I want to use composer 2 and those packages are not required. In fact, they don’t even work. So, after the init-drupal command above, I remove that package before upgrading the composer to version 2. I also update composer-patches to the latest dev release, which has the updated “require” statements to work with composer 2.

composer remove zaporylie/composer-drupal-optimizations
composer require cweagans/composer-patches:"^[email protected]"

Now, I’m good to update composer to the latest version (2.0 RC1 as of this writing):

composer self-update --2

At the time of this writing, the composer-patches plugin doesn’t work with composer 2. I have a PR open for the final fix (as of now) and I just used my fork as the repository for the package. Normally, in the Drupal world, I would have tried to apply a patch, but the plugin responsible for applying patches is broken here. Anyway, using forks is better. This commit shows how I used my fork, which works properly with composer 2. By the time you’re reading this, you might not have to do this at all.

Another thing to note is that my local machine is still running PHP 7.4. This is important because many of Drupal’s dependencies do not support PHP 8 and cannot be installed (unless we use the --ignore-platform-requirements flag).

This is good enough to get a basic environment running. Spin up the docker containers and find the port that the container exposes (look at docker ps -a). Access the site, and you might see an error message.

Problem with dependencies

Drupal is built on top of many packages and components in the PHP world and they have to support PHP 8 as well. As of right now, most of these components are not easily installable on PHP 8 due to the requirements in their composer.json. However, I ran composer on my local machine, which still runs PHP 7.4 and accordingly, it didn’t complain about PHP 8. This was obviously a risk and we should never do this on a production site (you shouldn’t be using PHP 8 beta on production right now anyway). But for this experiment, I wanted to try running those components on PHP 8 despite their composer.json restrictions. The good news is that none of those components caused any problems in my tests so far.

Of course, this is a blocker to add PHP 8 support for Drupal and is being tracked in this issue.

Problem 2: Fix Drupal errors

First, I faced problems with incompatible method declarations in doctrine/reflection. The problems were in methods getConstants and newInstance and I manually fixed both those instances (it was trivial) and it moved ahead. It turned out that they had already been fixed in the patch and I need not have worried but I moved on.

This fix at least got Drupal’s installation pages loaded and I went as far as the page where we enter the database details. (I eventually configured the .env file and never saw that page again, but that’s beside the point.) At this step, I saw an error related to an invalid method signature for a PDO method. In PHP 8, the method signatures of PDOStatement::fetchAll and PDOStatement::fetch have changed. Unfortunately, Drupal 8 and 9 have a wrapper on this method with the old signature. This now needs to change for PHP 8. But changing it will break support for PHP 7 and this creates our complication.

The solution is a rather brilliant hackery by Alex Pott where we introduce two interfaces–one for PHP 7 and the other for PHP 8. Depending on the PHP version, we alias the relevant interface which gets used by the actual class. Then, to handle both method signatures, we have two different traits–again one for PHP 7 and the other for PHP 8. We again alias the relevant trait depending on the PHP version, which gets used in the class. This looks something like this:

if (PHP_VERSION_ID >= 80000) {
  class_alias('\Drupal\Core\Database\Php8StatementInterface',  '\Drupal\Core\Database\StatementInterfaceBase');
}
else {
  class_alias('\Drupal\Core\Database\Php7StatementInterface',   '\Drupal\Core\Database\StatementInterfaceBase');
}
interface StatementInterface extends StatementInterfaceBase, \Traversable {
  // ..
}

Similarly, the traits are aliased and each of the traits call a new helper method in the actual Statement class (they are just renamed from the previous method). For example, the erstwhile fetchAll method would now become doFetchAll and since it is a different name, it doesn’t matter what signature it has. The fetchAll method would now reside in the relevant trait with the appropriate signature depending on the PHP version and would just call the doFetchAll method. This way, we have two different method signatures in the interfaces and traits depending on the PHP version!

The above changes can be reviewed in the patch at the issue where this is being worked at the time of this writing. When I tested, the patch only contained support for the differing signatures for the fetch method. Subsequently, the signature for the fetchAll method had changed as well and I added support for that in the patch. This solved the problem with installing Drupal. I was surprised and happy that there were no more errors during the rest of the installation and even when I was greeted with my new site’s homepage running Drupal 9.1 and PHP 8!

Before I go on to the next problem, I should note that the issue here with PDOStatement is really because of a mistake in the design.

As a developer, we should never directly depend on the API of something we can’t directly control. PHP version is something that we, as Drupal core developers, can’t control. We can certainly require a minimum version of PHP but we can’t control PHP to control other dependencies.

Intertwining our business logic with PHP’s API brings risks such as this. Like Alex Pott says in a comment in that issue, “These are not our methods. These are from \PDOStatement and their signature is owned by PHP and not by Drupal.”

Fortunately, Drupal boasts a high code coverage in the automated tests and refactoring could be as safe as we can hope. There might still be problems with contributed modules that might have extended this method and rely on Drupal’s implementation on top of the PHP wrapper. In a complex product like Drupal, it is precarious to refactor code like this.

Problem 3: Dynamic routes

I was elated with a working install on PHP 8 and wanted to test further, all the while keeping an eye on the error log. I found a few niche errors in how Drupal behaved on dynamic routes but that turned out to be a problem with the changes in PDOStatement::fetchAll and how it behaves with optional parameters. It was very messy and I am glad that PHP 8 changed the method signature to use variadics. The problem here was how the traits wrapped the call to the relevant Statement class's actual method. I had to use an ugly switch..case block to account for the number of parameters similar to how it was already handled in Drupal core. You can see the changes in this patch.

Problem 4: CKEditor warnings

I noticed multiple warnings being logged by CKEditor when I opened the node add/edit form. The warnings from a method called CKEditorPluginManager::getEnabledButtons and it was due to how a certain parameter was passed into the callback for array_reduce. Fortunately, this turned out to be an easy fix because there was no need at all to pass that parameter by reference and the patch was quickly committed. The issue contains more details and sample code for reproducing the issue.

Next steps

If you want to test this yourself, find my code here and set it up yourself locally. You would need composer and Docker and hope it is self-explanatory, but I will soon add documentation to the repository.

I was able to run Drupal 9 and perform many actions on PHP 8. But not many people need just the Drupal core. To test complex sites, I needed to test as many features as possible in core and also contrib modules. I will write about this in a subsequent post and maybe even do a simple benchmark comparing PHP 7.4 and 8.0 performance.

Dec 02 2020
Dec 02

The CKEditor integration in Drupal 8 is available out of the box along with the APIs, which can be used to integrate custom/contributed CKEditor plugins into Drupal. In this post, we will be exploring all such possibilities in-depth and learning them practically.

This blog will talk about a very famous WYSIWYG editor - CKEditor, and it’s usage in a very powerful web content management system - Drupal.

What is CKEditor?

CKEditor is a WYSIWYG rich text editor that enables web applications to offer an easy-peasy process of writing and formatting content in text area fields by providing many features like adding images, tables, styles, links, e.t.c. Below screen grab shows how a CKEditor enabled text area looks like:

Information on Content Accessibility Matters

Drupal 8 and CKEditor Integration

Drupal core’s editor module provides a framework that can be extended by the core and contributed modules to create or integrate any WYSIWYG editor(TinyMCE, CKEditor, e.c.t) with Drupal. This framework is used by the core CKEditor module to integrate CKEditor with Drupal. This helps Drupal core in providing the integration out of the box.

Text Formats Configuration

Drupal entity fields that allow the user to add HTML input in them Can show the CKEditor toolbar. However, It doesn’t always mean for such fields to always have the CKEditor enabled. To enable CKEditor on the field, You will have to observe the text formats your fields allow, and depending on the same, The associated text formats on your Drupal instance will need to be configured. The text editor can be configured by the following steps:

  • Log in as a site administrator on your Drupal instance.
  • Go to the path admin/config/content/formats.
  • Edit the text format of your concern(In our case, we wanted to have CKEditor visible on Basic HTML text format).
  • Change the Text editor select option to CKEditor and save the settings. See screenshot for reference:
Basic HTML in Drupal backend
  • Now when you view the entity form with fields allowing to use Basic HTML text format, You will see the CKEditor toolbar visible on the fields as shown in the screenshot below:
Highlighed CKEditor toolbar in Basic HTML

The CKEditor Plugins

CKEditor follows plugin-based architecture, and the CKEditor toolbar is nothing but a collection of plugins where the plugin is nothing but a piece of code that provides some features (Ex: Adding Images, Adding Links, etc).
 

Icons on the CKEditor toolbar as plugin highlighted with arrows

CKEditor Plugins: The Approach

  • Any CKEditor plugin in Drupal is made up of two important components, as mentioned below:
    • Drupal module: A custom or contributed Drupal module is required to define and register the plugin.
    • CKEditor plugin: A custom or contributed CKEditor plugin is required to provide the actual functionality.
  • Depending on your requirement, you can refer to the below image and decide your approach for the type of components to use. CKEditor Plugin in contributed and custom Drupal modules showcased

CKEditor Plugins: The Integration Methods

  • Based on the image of the previous section, There are three methods by which we can achieve the functionality in Drupal.
    • Contributed Modules & Contributed Plugins
    • Custom Modules & Contributed Plugins
    • Custom Modules & Custom Plugins
       
  • Let’s see each method in detail:

Method 1: Contributed Modules & Contributed Plugins

There are many contributed modules out there that integrate the contributed CKEditor plugins and allow you to add them to Drupal.

The installation and usage method for this type can be best explained in the individual module’s documentation (Example: See the README.txt file for the integration of the CKEditor CodeSnippet module).

Method 2: Custom Modules & Contributed Plugins

Sometimes a contributed plugin might be available for use from the CKEditor plugin repository, but there might not be a contributed module out there to integrate the plugin with Drupal. In such cases, we write custom modules.

For Example: For the Preview CKEditor plugin, there is no contributed module out there, and in such a case, we create a custom module to register the plugin with Drupal and use it. Let’s get into it and see how we can integrate the Preview plugin with Drupal.

  • Step 1: We will download the Preview plugin using the composer. Since the CKEditor plugins don't have composer packages of their own, we manually define packages for each plugin we want to use.

For each plugin, add an entry to the repositories section of your composer.json file. This will tell the composer about the package and tell it where to get it from. 

For example: We added an entry for Preview plugin and run ‘composer require ckeditor-plugin/preview’

Composer will extract the plugin here ‘web/libraries/preview’(Note: We have our Drupal installation in the ‘web’ directory).

  • Step 2: We will create a custom module called mysite_ckeditor_preview at path ‘web/modules/custom/mysite_ckeditor_preview’(Note: We have our Drupal installation in the ‘web’ directory). Below image shows how our module directory structure looks like:
Files under mystite ckeditor preview
  • Step 3: We have created a mysite_ckeditor_preview.info.yml which will help Drupal to register the package mysite_ckeditor_preview as a custom module, and it contains below code:
  • Step 4: We have created a plugin PreviewCKEditorButton.php in the namespace Drupal\mysite_ckeditor_preview\Plugin\CKEditorPlugin, and its purpose is to register our CKEditor plugin. This file will consist of the following code:

Let’s understand some of the essential pointers about the above class:

Annotation: Our CKEditor plugin needs to annotate @CKEditorPlugin() and the id = "preview" in it tells Drupal about the registered CKEditor plugin name, In our case, it’s called preview. The vital point to note here is the name & casing of the id value should match the first argument of CKEDITOR.plugins.add() in plugin.js, which is the main file of any CKEditor plugin.

Functions: The plugin class consist of the following methods:

getButtons(): Returns the icon path and icon label of the plugin, which will appear on the CKEditor toolbar. We will be using the icon provided by the preview plugin, which we have kept in the ‘libraries’ directory, and hence our icon path is ‘/libraries/preview/icons/preview.png’.

getFile(): Returns the plugin.js path of the actual CKEditor plugin. In our case, the plugin.js is present at this path ‘/libraries/preview/plugin.js’.

getConfig(): Allows you to set additional configurations that can be accessed in plugin.js under the CKEDITOR.config.

  • Step 5: Enable the custom module.
  • Step 6: Edit your desired text format, which has CKEditor enabled(In our case, it’s ‘Basic Html’), and you should see our preview button is present in the available buttons toolbar. Drag the preview button to the Active toolbar area. Finally, save the configuration.
view of the CKEditor highlighting the preview plugin icon
  • Step 7: Now, when you create any content with fields allowing to use ‘Basic Html’ text format, You will see the preview button is present on the CKEditor toolbar.
Preview icon can be seen on CKEditor toolbar

So this is how we can create a custom module in Drupal to integrate any contributed CKEditor plugin.

Method 3: Custom Modules & Custom Plugins

If you want to create any custom functionality for which you neither have a CKEditor plugin nor the Drupal contributed module, You will have to create a custom Drupal module and a custom CKEditor plugin.

For Example: If we want to add some text mentioning current ‘day, month, date, and time’ in the textarea field on the click of the CKEditor toolbar icon, then it becomes a very specific project requirement which can be achieved using a custom module and a custom CKEditor plugin. Let’s get into the code and see how we can achieve this:

  • Step 1: We have created an mysite_ckeditor_timestamp.info.yml which will help Drupal to register the package mysite_ckeditor_timestamp as a custom module, and it contains below code:
  • Step 2: We will create a custom CKEditor plugin called ‘timestamp’ in a custom module and add a directory called ‘timestamp’ at the path ‘web/modules/custom/mysite_ckeditor_timestamp/libraries/plugins/timestamp’.
  • Step 3: We need to add a ‘timestamp.png’ icon to our plugin such that it is present at this path ‘web/modules/custom/mysite_ckeditor_timestamp/libraries/plugins/timestamp/icons/timestamp.png
  • Step 4: Let’s add a plugin.js file in the timestamp directory such that it's present at this path ‘web/modules/custom/mysite_ckeditor_timestamp/libraries/plugins/timestamp/plugin.js’. The purpose of this file is to register a CKEditor plugin called ‘timestamp’ and the code of this file looks like below:

We will not go in the detail of how to write a custom CKEditor plugin, but let’s just understand that the above code will register the ‘timestamp’ plugin with CKEditor. And whenever a user clicks on the icon from the CKEditor toolbar, then our plugin.js will insert the current ‘day, month, date, and time’ as HTML in the textarea. For more information on how to write CKEditor plugin - Refer to this documentation.

After this step, This is how our timestamp plugin inside the custom Drupal module will look like:

mysite ckeditor timestamp
  • Step 5: Adding the timestamp CKEditor plugin is not enough for Drupal to recognize it. We will create a plugin called  TimestampCKEditorButton.php in the namespace Drupal\mysite_ckeditor_timestamp\Plugin\CKEditorPlugin and register a ‘timestamp’ plugin into Drupal. This file will consist of the following code:

Since we have already covered the anatomy of the CKEditor plugin class in this post, The above code should be self-explanatory. 

  • Step 6: Edit your desired text format, which has CKEditor enabled(In our case, it’s ‘Basic Html’), and you should see our timestamp button is present in the available buttons toolbar. Drag the timestamp button to the active toolbar area and save the configuration.
we need to drag the timestamp to the active toolbar
  • Step 7: Now, when you create any content with fields allowing to use ‘Basic Html’ text format, You will see the timestamp button is present on the CKEditor toolbar.
Timestamp button can be seen on the CKEditor toolbar

And that’s how we can integrate a custom CKEditor plugin in Drupal using a custom Drupal module.

Conclusion

Drupal has been highly successful in providing a good editorial experience via the highly scalable, feature-rich, and robust CKEditor Ecosystem. This, in turn, helps content editors focus on the things they are good at - “Content.”

Summary

Every web application in the world is backed by a content team whose expectations have evolved with the evolution of technologies used in these applications. Content editors wish for many features like WYSIWYG editors, scheduling, smoother workflows, intuitive UI, etc., from a web application as their content quality and the productivity is directly proportional to the whole editorial experience provided by the web application.

Dec 02 2020
Dec 02

Outsourcing certain aspects of your business, such as design or development, through staff augmentation or another method is becoming more and more popular. And with good reason - there are many benefits of outsourcing which make it a viable and cost-effective choice for businesses.

Just like with any type of work arrangement, however, there are going to be certain challenges or concerns that come with outsourcing. In this article, we’ll take a more detailed look at one of them: keeping control of your project, specifically when you’re outsourcing software development.

What it means and why is it important

You can be the owner of the product that needs to be built, or a consulting business that provides implementation services to clients. In either case, you’ll of course want to make sure that the development aligns with the goals and mission of your company. At the same time, you’ll also definitely want to keep control of the resulting intellectual property.

By keeping control of the project’s management throughout its development, you’ll guarantee that all its requirements and goals are met. Trust is a key element here, especially with larger teams or when outsourcing larger parts or entire projects. 

Trust enables you to relinquish some of the control because you know your outsourced developers are aligned on your needs and objectives. You’ll be able to keep control without having to micromanage, which will be a win-win for both you and the development partner as you’ll be left to do what you do best.

As for keeping control of your IP - this is just a no-brainer. With fewer people augmenting your in-house team, you won’t need to worry about this. When outsourcing an entire project, however, look for a partner that provides white-label development so you can rest assured that you will remain in charge of the resulting IP. 

Different outsourcing strategies mean different degrees of control

How much control of your project you keep is directly tied to the type of outsourcing strategy you go with - this means that it’s wise to choose the type of outsourcing based on what degree of control you want to keep.

Infographic of differently structured outsourced teams

Managed services

If you don’t have in-house development and you’re happy leaving the project’s development up to the partner, then managed services is probably your best bet. With managed services, the partner will take care of the entire development, both the management and the execution, and you won’t need to get involved during the process.

These types of projects are very often fixed in scope, also called turnkey projects. Make sure that the partner offers white-label services, so that you’re guaranteed to remain the owner of the intellectual property once it’s delivered.

Dedicated teams

This type of outsourcing strategy is a kind of middle-ground - you aren’t just augmenting your team with one or a few people, but rather outsource a whole section of the development, or even the entire development. In contrast with managed services, though, with dedicated teams it is your project management that is in charge rather than that of the partner agency.

This way, you retain control of the overall progress of the project while leaving the technical nitty-gritty to the experts whom you’ve hired for this specific expertise. 

It is ideal both for companies with no in-house development as well as those that do have in-house developers, but lack certain skill-sets, aren’t familiar with a new technology that’s required or would like to form a new team rather than augmenting an existing one.

Staff augmentation / team augmentation

The option where you keep the highest level of control is staff or team augmentation. In this case you only need a few people to boost your in-house development capacity, either to fill a skill gap or because a project needs a large amount of a specific expertise. 

If you only need a single developer, hiring a freelancer is a viable option. As soon as you need two people or more, however, it makes more sense to contact an agency specializing in staff augmentation, so you don’t spend extra resources on several hiring and vetting processes. 

The partner agency will guarantee the quality of their staff and will be able to provide adequate replacements if something unexpected happens with the original hires. 

By augmenting your team this way, you’ll keep control of both the organizational and the technical aspects of the project, and will consequently automatically be the sole owner of the resulting product or service.

What to look for with outsourced development

Here are some of the qualities you should look for in an outsourced development partner that will help you to be satisfied with the level of control you have over your project, no matter what kind of outsourcing strategy you ultimately decide on.

  • Technical expertise: this is another no-brainer. By selecting a partner with verifiable expertise in whatever you’re looking for, you’ll be able to leave even more complex tasks and processes to them without worrying about a low-quality outcome. 
  • Good communication: transparent communication is the number one thing for ensuring trust right from the get-go. If your development partner proves to be a good communicator, you can feel safer leaving certain aspects of your project in their hands.
  • Company culture: if the agency you work with has a company culture that’s similar to yours, it’s easier to determine if they share the same values and will see things the way you do and thus execute them the way you want them to. Again, similar values will result in better alignment and no need for you to manage everything. 
  • Compliance with standards and best practices: by working with an agency or freelancer that has demonstrated their commitment to following standards, you’ll feel safer about their respect of your intellectual property and any potential NDAs involved. Furthermore, it will be another indicator of the final result’s quality.

Looking for a development agency?

We hope this article will help you in selecting the best outsourcing strategy for your needs as well as the right partner to entrust your development with. If you’re currently looking for a development agency to partner with and Agiledrop seems like the perfect choice, reach out to us or learn more about how we can ensure the success of your project:

Dec 02 2020
Dec 02

(Available as freelancer)

Joris Snoek

Business Consultant
/ Drupal Developer

So we wanted to implement the great Bootstrap Toasts feature in our social productivity Drupal distro OpenLucius. HTML framework Bootstrap provides Toasts out of the box. After some trial and error, the end result seems fairly easy to use for everybody. So here is how:

  1. Override status-messages.html.twig in your (custom) theme with the code underneath;
  2. Initiate Toasts in Javascript.

1. Override status-messages.html.twig in your (custom) theme

So place the Twig template override file with this code in your theme. For example in YOURTHEME/templates/misc/status-messages.html.twig. Clear your cache and Drupal should take this file for generating messages, instead of the core one with the same filename. More on Twig template naming conventions here.

2. Initiate Toasts in Javascript

In your (custom) Javascript make sure to initiate the Toasts

$('.toast').toast('show');

3. Et Voilá

The messages will also stack nicely in case of multiple messages, with multiple types (status, warning, error). Ánd have a nicely coloured header depending on message type (green, orange, red).

Additional info from the Bootstrap documentation

Things to know when using the toast plugin:

If you’re building our JavaScript from source, it requires util.js.

  • Toasts are opt-in for performance reasons, so you must initialize them yourself.
  • Please note that you are responsible for positioning toasts.
  • Toasts will automatically hide if you do not specify autohide: false.

On the Toasts documentation page, you'll find the configuration options, for placements, autohide, etc.

Bonus

For all you 80ies babies, here is the other Toasty! He scared the crap out of me when here appeared out of nowhere somewhere in the 90ies, especially with the high singing lady that accompanied him :)

Wrap up

So there you have it for great toast instead of boring Drupal messages, no offence :) Want to see it in live action? Try OpenLucius and see for yourself! Or you can download and install it yourself via our drupal.org project page. More info on Toasts here on getbootstrap.com.

Dec 01 2020
Dec 01

Every major release calls for updating the Drupal core. 

New improvements or additions are released as patches and website administrators are required to update the site on a regular basis. And keeping your Drupal site updated is one of the best ways of ensuring its security and stability. 

Thus, it’s a good idea to update your site with the current release, i.e., Drupal 9. 

Why Update Your Drupal Core?

Along with adding new features, the Drupal core release also updates the modules to make them compatible with the latest version. Therefore, updating the core becomes crucial in case you employ these modules for your website. 

It is good to update your Drupal core to the latest version as and when required. 

Secondly, with every release, bugs are removed from the core code of the CMS. This ensures your site’s security and uninterrupted functioning. 

What Are My Options? 

Now that you have decided to update your Drupal core, let’s explore the options in detail.

Manually

The official Drupal site gives us a standard manual update procedure to update the core manually. 

Via Drush

Drush has already removed the support for updating the Core. In Drush 9 and Drush 10 (the current version), all the up commands pm-update, pm-updatecode and pm-updatestatus are deprecated, and thus, it no longer supports updating Drupal. 

Now, you need to use Composer (see below) along with Drush to update your website. 

Via Composer

Composer, the dependency manager for PHP, is used for updating and installing packages (modules) in Drupal. It helps declare and manage libraries and core dependencies such as Symfony components and certain packages.

First, install Composer. Make sure all your modules are secure and supported, and compatible with the Drupal 9 version. 

Here’s a video to guide you through the process:
 

Challenges With Upgrading Drupal Core

Any major release will pose some challenges. Being cautious and prepared in advance can save you a lot of time and effort. 

Here are a few considerations you can keep in mind during the process:

  • Always look out for error messages.
  • Use the file and database backups to restore your site to its previous state if needed.
  • If you are not sure, you can consult one of the support options listed here. 

How to begin the upgrade process?

Let’s initiate the process with some pre-requisites considered:

  • Backing up all files, directories, and the database is a must before starting. 
  • Keep a test copy of your site before putting it on your live site. 
  • The release notes that come with new Drupal releases (explaining the changes made since the previous version or any special instructions) come in handy.

The standard process of updating as per Drupal’s official site is as follows:

  • Take backups of all files and the database.
  • Put the site in Maintenance Mode (under Configuration / Development)
  • Find your webroot folder. If it is called www, rename it to www_old.
  • Download the latest version of Drupal 7 core. Unzip the files and delete the site’s folder locally.
  • Upload all the files to the server into a new directory www. (Make sure this www folder has the same permissions as the previous folder www_old).
  • Move the site’s folder from www_old/sites to www/sites. (This assumes any contributed modules, custom themes, etc. that you use are in the site’s directory)
  • If changes have been made to robots.txt or .htaccess in the new version, ensure these are incorporated into your version. The release notes should tell you whether this is required. Otherwise, copy your previous versions from www_old to www.
  • Run Update.php by visiting yourdomain.com/update.php.
  • While Update.php runs, if you get any errors, use the Module missing message fixer to fix these (7.5x versions only).

I hope this helps you with updating your Drupal Core. For more, get in touch with our Drupal experts! 

Dec 01 2020
Dec 01

The creation of dynamic routes has changed as compared to the past versions of Drupal. Precisely when the routing layer now (in D8 and above) is Symfony based.

In my case, I had to display the basic details of any entity (either existing one or the one that will be created) dynamically. 

How do we create dynamic routes in Drupal 8?

This tutorial assumes you are already familiar with the routing system in Drupal. The routing system overview is an excellent place to start.

Step 1: Create an entry in Routing.yml

In order to provide a dynamic route, you will need to create an entry in your modules routing.yml file.

You can achieve the same using a service as well.

Step 2: Create a routing class

Now you will have to create your routing class and put your logic there. The dynamic routing method either returns an array of \Symfony\Component\Routing\Route objects or a \Symfony\Component\Routing\RouteCollection object. You have to define that in src/Routing/EntityOverview.php.

Step 3: Create a controller

The final step is to create a controller for your route callback. You’ve to define that in src/Controller/EntityDetails.php.

How do we upcast a parameter of a route?

You have created the dynamic route. But did you see the controller? How did the parameter all_entity provide a loaded entity? That is where the parameter upcasting/converter comes into the picture. Let's see how we can do that! 

Step 1: Define a service in services.yml

To upcast a parameter, you need to create a service defined in your modules my_module.services.yml.

Note: you’ll have to tag the service as paramconverter.

Step 2: Create a parameter converter class

Finally, we need to create the class for the parameter converter.

The class MyModuleParamConverter implements ParamConverterInterface, which provides two abstract methods:

  • convert: That’s where you need to write the logic to process your parameters. In my case, I’ve fetched the entity type from the route object and loaded the entity using the entityTypeManager.
  • applies: It is a basic validation of where the conversion is applicable. In my case, it is appropriate where the parameter is of type all_entity.

Note: the variable name in the route and the controller should match.

Cheers! Now your dynamic route with the upcasted parameter is ready to roll. 

Though this required more effort to create it as compared to Drupal 7, it has it's own advantages associated with it, too. I hope this post will help you create your dynamic routes without any hassle. For more on routes in Drupal 8, check our blog here

Dec 01 2020
Dec 01

Node Package Manager (NPM) is an open-source software library that has over 800,000 code packages. In simple terms, we can say that NPM is a command-line tool that installs, updates, or uninstalls node.js packages of an application.

NPM Install

Installation

Inside the project theme folder, directly run the npm install command. It will install all the packages that are there in the package.json file.
Once done, you can verify the NPM installation by writing the following command in the command prompt. This will show you the version of the NPM.

  
npm -v

If you have older version of NPM then you can update it to the latest version using this command:

  
npm install npm -g

We can use NPM in two different modes: Global and Local mode.
Global mode - It performs operations which affects all the Node.js applications on the computer.
Local mode - It performs operations for a particular local directory which affects an application in that directory only.

How to add Dependency into package.json

NPM packages are all defined in one file called package.json. The content inside package.json must be written in JSON format. The two necessary fields in that file are ‘name’ and ‘version’.
The main goal of this is automated dependency and package management. Here, you can specify all your project/application dependencies within the package.json file.

Node Package Manager (NPM) in Drupal

Here “test” is the name of the Project and version number is given as “1.0.0”.

The dependency packages that are required for “test” project are : Bootstrap, gulp and gulp-sass along with their versions.

Run the below command in the terminal to install the node modules inside your project theme folder.  

  
npm install

Once you run this command, all the dependency modules will get installed.

Node Package Manager (NPM) in Drupal

Inside the node_modules folder you will see the dependency modules that get installed.

the gulpfile

Gulp is a task runner. It can do many things. It uses the JavaScript code and helps run front-end tasks for large scale web applications. It also builds system automated tasks like CSS preprocessing, HTML minification, concatenating library files, compiling the SASS files, and more. Here we are using Gulp to convert .scss files into .css.

Inside the gulpfile.js we are going to assign the tasks that can be done by Gulp.

Node Package Manager (NPM) in Drupal

When using functionalities that are not Drupal, we need to import the CSS or JS files with respect to that module as a library in theme_name.libraries.yml. Next, we need to call the library with respect to that particular twig file to see the required changes. 

This way we can use other NPM packages like slick-carousel, responsive tabs etc. to your project using this command:

  
npm install 

Use this command to update the packages:

  
C:\MyNodeProj> npm update 


To uninstall the package, use this command:

  
C:\>npm uninstall 
Dec 01 2020
Dec 01

What happens if no one updates PHP: lack of security

Mostly, it’s a security and data leak that happens on outdated websites, and a hacker doesn’t have to be a CIA computer security consultant like Edward Snowden.

Here are two cases from our practice.

A WordPress content website was hacked because of PHP vulnerabilities: and attackers managed to insert the malicious code on pages

A high-load Drupal website that stores many users' data (their personal information, the records of their actions and purchases) runs on PHP 5.6 - this is partly caused by business logic restrictions and budgeting. Soon the hosting will stop the support of this version and part of the functionality will be broken, so for some time, there can be troubles with getting new leads and clients, and receiving payments on the website. So when this happens, we will have to upgrade in a very tight timeline which doesn’t leave us room for testing changes.

You see, the further you put off the PHP upgrade, the more it will cost: at some point in time, incompatibility between your website and hosting requirements, security requirements, etc. will become dramatic and expensive to fix.

Updating PHP is suggested to be as important for website security as a strong password, secure connection, and trustworthy hosting provider.

Upgrade PHP and get better performance for your website

We’re working with Drupal a lot, so let us provide some examples based on this CMS. 

We have already written the article about performance improvement, and the relevant PHP version was one of the required conditions.

Read Drupal 7 Performance Tips.

In a nutshell, such CMSs as Drupal and WordPress want users to use particular PHP versions for the websites built on those CMSs. Drupal has 3 supported major versions right now: Drupal 7, 8, 9, and the recommendation is to run those websites on PHP 7.3 or higher. It’s worth mentioning that PHP 7.3 is not the newest version, so website owners have a so-called release window and time to upgrade.

What happens if a website runs on an older version? First of all, its overall performance is noticeably lower than it could be if it was running on a newer version.

Dec 01 2020
Dec 01

The much-awaited Drupal 9 has been out and about for over a month now. Introduced amid a global pandemic, it wasn’t as big a launch as Drupal 8 in 2015.

Like Dries said, “The big deal about Drupal 9 is that... it shouldn’t be a big deal.”

So far, we don’t have much to dissect in the Drupal 9 update, so we’ll take a peek into Drupal 8’s transition over the years, and how it gave way to Drupal 9. Considering how every minor update in Drupal 8 has improved the CMS, we‘ll try to foresee the trajectory of Drupal 9.

Drupal 8 So Far

Drupal 8.0.0 was the first fully supported release of Drupal 8, released in 2015 as the biggest update ever to the Open Source CMS, Drupal. 

Note on semantic versioning

  • A MAJOR version is when incompatible API changes are made, e.g. the launch of Drupal 9 and complete removal of the deprecated code.
  • A MINOR version is when functionality is added in a backward-compatible manner. e.g. Drupal 8.2 to Drupal 8.3. 
  • A PATCH version is when backward-compatible bug fixes are done.

Drupal 8.1 - Drupal 8.4

20 April 2016 to 4 Oct 2017

The BigPipe module was included in Drupal 8 core with the Drupal 8.1 update, and it became stable in Drupal 8.3. We also saw Drupal 8.2.0 adopting coding standards changes.

Drupal 8.4 included major version updates for Symfony, jQuery and jQuery UI, and was no longer compatible with older versions of Drush. Drupal 8.4 also introduced media in the core.

Drupal 8.5 - Drupal 8.7

7 Mar 2018- 1 May 2019

Drupal 8.5 and 8.6 provided new improvements and functionality without breaking backward compatibility (BC) for public APIs.

The in-demand layout builder was launched with Drupal 8.7 and it changed the structure for Drupal editors significantly. 

Note: If you are still on version 8.6.x or older, you can skip directly to 8.8.x and have the upgrade path bug fixes applied.  

Drupal 8.8 and Drupal 8.9

Drupal8.8 launched on 4 Dec 2019

These last two updates paved the way for Drupal 9 to be built within Drupal 8. Drupal 8.8.0 declared a conflict with modules like Pathauto 8.x-1.5 or lower.

Drupal 8.8.0 ends the PHP 5.5 and 5.6 support and updates will now fail if servers are not updated to at least PHP 7.0.8.

Thus, Drupal 8.9, as the final minor release of the 8.x series, is a long-term support (LTS) version and will be supported until November 2021. Though Drupal 8.9 runs on all PHP 7 versions, it is recommended to update to at least PHP 7.3. 

Introducing Drupal 9

A cleaned-up version of Drupal 8, we saw the launch of Drupal 9 with updated dependencies and the removal of deprecated code. Though the vast majority of Drupal 8 migration tutorials will apply to your Drupal 9 sites, there's no one-size-fits-all process for upgrading/migrating. 

Initiatives We Look Forward to in the Drupal 9 Release Cycle

We can expect the theme Olivero, being built in the contributed project for inclusion in Drupal core, to be added as an experimental theme in the impending Drupal 9.1 update. Similarly, the theme Claro could be marked stable as it is already experimental in Drupal 8.8.

Apart from this, we expect to see automated updates in the core, CMI 2.0, and JavaScript modernization.

Here’s a list of various other strategic initiatives:

  1. API-First
  2. Automatic Updates
  3. Composer support in Core
  4. Configuration Management
  5. Documentation and Help
  6. Drupal 10 Readiness
  7. Media 
  8. New frontend theme
  9. Workflow

Migration Pre-requisites

Check out the tasks to be completed before you begin the migration process: 

  • Ensure your hosting environment matches the platform requirements of Drupal 9.
  • Update to the latest release, i.e. Drupal 8.8.x or 8.9.x 
  • Ensure Drupal 9 compatibility by updating contributed projects.
  • Make your custom code Drupal 9 compatible too.
  • Update core codebase to the major version, Drupal 9.
  • Lastly, run update.php.

Should You Migrate Your Drupal 8 Site? 

Migrating to Drupal 9 requires fully updating the Drupal 8 site to the most recent version of both the core and contributed modules and themes. This will ensure your database is Drupal 9-ready and only the code will change with some smaller database updates.

If your site is at any version below Drupal 8.8, then it’s a good time to start investing in upgrading. 

In case you are at either the Drupal 8.8 or Drupal 8.9 versions, then upgrading to Drupal 9 shouldn’t be that big a hassle for your team. Ensure your contributed modules are compatible with the latest release and your site is good to go. 

Conclusion

As a significant introduction, Drupal 8 embarked on a long and exciting journey with the Drupal community. Each minor update brought newer experiences, power-packed features, greater flexibility, and improved the overall outlook of the Open Source CMS. Today, the Drupal 9 version is entirely based on the workings of Drupal 8 itself. And it is only the hard work of the community and all their contributions that have helped Drupal reach this level of scalability and efficiency. 

Dec 01 2020
Dec 01

At the time of this writing, it’s over a month since Drupal 9 was released. While the Drupal community has grown over the last decade, thanks to the innovative release cycle and building bridges to other communities, Drupal 9 release festivities were not as grand as I remember for Drupal 8. A significant reason for this is the COVID-19 pandemic that we all are facing right now (I hope you’re okay reading this in the future). But there’s a bigger point here. Drupal upgrades are not exciting anymore. 

Stay with me for a minute. Drupal 8 will remain the most exciting Drupal release for the foreseeable future. It was an interesting time while we rewrote Drupal (almost) from the ground up. We did that using years of learned best practices and PHP community support. As a result, Drupal is more reliable and dependable now than ever before in its two decades of existence. On the other hand, Drupal 9 release was almost boring. The only thing we did was remove the deprecated code.

Understanding the Drupal release cycle

That’s a big deal here. As a community, we are approaching our tweens and deciding how best to lay our foundations for the long haul ahead. This is reflected in how we release Drupal. Drupal 1 through 4 were the only supported major versions throughout their lifetime. Drupal 5 support lasted well into the Drupal 6 lifecycle and this repeated for Drupal 7, 8, and 9. Due to an interesting combination of circumstances, Drupal 7’s support exceeds even Drupal 8.
Image Source


We are innovating by introducing new features on a schedule. Read more about the release cycle here. At the same time, we are keeping Drupal maintainable for the long-term. It’s of little consequence that not all Drupal 8 code will run on Drupal 9. The important thing is that most of the code will. In fact, with the predictable release schedule of deprecations and new features, a well-maintained site might have had nothing to do when upgrading to Drupal 9. We saw this with a flurry of tweets and other social media updates announcing that people have upgraded their sites to Drupal 9 within hours of release.
Image Source

Understanding major releases

Starting with Drupal 9, all major releases will be the same as the last minor release in the previous version, except for the absence of deprecated code. This means Drupal 9 is identical to Drupal 8.9 to everyone–editors, site builders, and developers (as long as they don’t use deprecated functionality). That will also be the case for Drupal 10 and Drupal 11. And this will go on until we see a significant shift in the PHP programming paradigm that warrants another Drupal 8 style rewrite (will it be generics or async programming or something else we haven’t yet imagined?)

Enough theory, what does this mean for you?

Based on everything we talked about above, let’s get down to business.

  • Are you running Drupal 6 or earlier?
    • Migrate right now.
  • Are you running Drupal 7?
    • You have until Nov 28, 2022, to migrate to Drupal 9. Yes, it would be best if you don’t plan to migrate to Drupal 8 right now*.
  • Are you running Drupal 8.8 or earlier?
    • Upgrade to Drupal 8.9 right now.
  • Are you running Drupal 8.9?
    • You’re good until November 2021. Evaluate your site’s contrib and custom code to plan for Drupal 9 upgrade when possible.
  • Are you running Drupal 9?
    • You have reached your destination.

* There are caveats to every situation. I always try to make sure that I never generalize.

Planning the upgrade to Drupal 9

You are on Drupal 8 and want to upgrade to Drupal 9? There are lots of resources to help, but I suggest you start by installing the Upgrade Status and Upgrade Rector modules. Chances are you won’t need to look elsewhere.

Upgrade Status module can check for Drupal 9 compatibility information for each of the modules you use (including custom modules) and, along with Upgrade Rector, generate patches that you can use on Contrib and custom modules. As we see here, many Contrib modules already have Drupal 9 compatible releases. Most of the remaining modules only need minimal changes to become compatible.

Personally, I have only upgraded one site to Drupal 9 so far. There are a few more sites I can upgrade to Drupal 9 right now if I switched to dev releases of certain modules I use. But there’s no good reason for me to hurry. My Drupal 8.9 site is as good as Drupal 9 in every way, except the amount of code, PHP has to load (and that’s not a major problem thanks to Opcache). We will only see new features in Drupal 9.1 in December 2020, and I can wait until then for the Contrib modules to have proper releases.

Understanding Drupal versioning

If you have used Drupal for some time, you might know that you recognize compatible Contrib modules by their version. For example, Pathauto 7.x-1.0 is for Drupal 7 only. It won’t work on Drupal 6, nor Drupal 8. Similarly, token 8.x-1.2 would not work on Drupal 7.

With Drupal 8, the community adopted semantic versioning for the core. This has now rolled out to even Contrib modules. This means that we would be dropping the familiar versioning system that we have used for over a decade in favor of semantic versioning. Don’t worry, existing major releases are fine. That means you would still see new releases coming out for Pathauto 8.x-1.x branch, but if it were ever to create a new major release, we would probably see Pathauto 2.0. Actually, we might see Pathauto in Core (I hope), but that’s a different story.

Some of the modules have adopted this and see new releases in semantic versioning style (devel comes to mind). Other modules are still on their existing 8.x-y.z release scheme because they don’t need to change anything. And that’s another sign of maturity in how we write code for Drupal.

Conclusion

Drupal has long since moved from being adventurous and made efforts to become more reliable and robust in serving the people, as it should. The Drupal community has long stood by its slogan: Come for the code, stay for the community. This shift in thinking about Drupal’s release cycle is a testament to that fact: Drupal is not built in a vacuum. It is built, foremost, to serve the people who would use it.

Nov 30 2020
Nov 30
77 of us are going | Wunderkraut

Drupalcon 2015

People from across the globe who use, develop, design and support the Drupal platform will be brought together during a full week dedicated to networking, Drupal 8 and sharing and growing Drupal skills.

As we have active hiring plans we’ve decided that this year’s approach should have a focus on meeting people who might want to work for Wunderkraut and getting Drupal 8 out into the world.
As Signature Supporting Partner we wanted as much people as possible to attend the event. We managed to get 77 Wunderkrauts on the plane to Barcelona!  From Belgium alone we have an attendance of 17 people.
The majority of our developers will be participating in sprints (a get-together for focused development work on a Drupal project) giving all they got together with all other contributors at DrupalCon.

We look forward to an active DrupalCon week.  
If you're at DrupalCon and feel like talking to us. Just look for the folks with Wunderkraut carrot t-shirts or give Jo a call at his cell phone +32 476 945 176.

Share

Related Blog Posts

Want to know more?

Contact us today

or call us +32 (0)3 298 69 98

© 2015 Wunderkraut Benelux

Nov 30 2020
Nov 30
Watch our epic Drupal 8 promo video | Wunderkraut

How Wunderkraut feels about Drupal 8

Drupal 8 is coming and everyone is sprinting hard to get it over the finish line. To boost contributor morale we’ve made a motivational Drupal 8 video that will get them into the zone and tackling those last critical issues in no time.

[embedded content]

Share

Related Blog Posts

Want to know more?

Contact us today

or call us +32 (0)3 298 69 98

© 2015 Wunderkraut Benelux

Nov 30 2020
Nov 30

Once again Heritage day was a huge succes.

About 400 000 visitors visited Flanders monuments and heritage sites last Sunday.  The Open Monumentendag website received more than double the amount of last year's visitors.

Visitors to the website organised their day out by using the powerful search tool we built that allowed them to search for activities and sights at their desired location.  Not only could they search by location (province, zip code, city name, km range) but also by activity type, keywords, category and accessibility.  Each search request being added as a (removable) filter for finding the perfect activity.

By clicking on the heart icon, next to each activity, a favorite list was drawn up.  Ready for printing and taking along as route map.

Our support team monitored the website making sure visitors had a great digital experience for a good start to the day's activities.

Did you experience the ease of use of the Open Monumentendag website?  Are you curious about the know-how we applied for this project?  Read our Open Monumentendag case.

Nov 30 2020
Nov 30
Very proud to be a part of it | Wunderkraut

Breaking ground as Drupal's first Signature Supporting Partner

Drupal Association Executive Director Holly Ross is thrilled that Wunderkraut is joining as first and says: "Their support for the Association and the project is, and has always been, top-notch. This is another great expression of how much Wunderkraut believes in the incredible work our community does."

As Drupal Signature Supporting Partner we commit ourselves to advancing the Drupal project and empowering the Drupal community.  We're very proud to be a part of it as we enjoy contributing to the Drupal ecosystem (especially when we can be quircky and fun as CEO Vesa Palmu states).

Our contribution allowed the Drupal Association to:

  • Complete Drupal.org's D7 upgrade - now they can enhance new features
  • Hired a full engineering team committed to improving Drupal.org infrastructure
  • Set the roadmap for Drupal.org success.

First signaturepartner announcement in Drupal Newsletter

By

Michèle Weisz

Share

Related Blog Posts

Want to know more?

Contact us today

or call us +32 (0)3 298 69 98

© 2015 Wunderkraut Benelux

Nov 30 2020
Nov 30

But in this post I'd like to talk about one of the disadvantages that here at Wunderkraut we pay close attention to.

A consequence of the ability to build features in more than one way is that it's difficult to predict how different people interact (or want to interact) with them. As a result, companies end up delivering solutions to their clients that although seem perfect, turn out, in time, to be less than ideal and sometimes outright counterproductive. 

Great communication with the client and interest in their problems goes a long way towards minimising this effect. But sometimes clients realise that certain implementations are not perfect and could be made better. And when that happens, we are there to listen, adapt and reshape future solutions by taking into account these experiences. 

One such recent example involved the use of a certain WYSIWYG library from our toolkit on a client website. Content editors were initially happy with the implementation before they actually started using it to the full extent. Problems began to emerge, leading to editors spending way more time than they should have performing editing tasks. The client signalled this problem to us which we then proceed to correct by replacing said library. This resulted in our client becoming happier with the solution, much more productive and less frustrated with their experience on their site. 

We learned an important lesson in this process and we started using that new library on other sites as well. Polling our other clients on the performance of the new library revealed that indeed it was a good change to make. 

Nov 30 2020
Nov 30

A few years ago most of the requests started with : "Dear Wunderkraut, we want to build a new website and ... "  - nowadays we are addressed as "Dear Wunderkraut, we have x websites in Drupal and are very happy with that, but we are now looking for a reliable partner to support & host ... ".

By the year 2011 Drupal had been around for just about 10 years. It was growing and changing at a fast pace. More and more websites were being built with it. Increasing numbers of people were requesting help and support with their website. And though there were a number of companies flourishing in Drupal business, few considered specific Drupal support an interesting market segment. Throughout 2011 Wunderkraut Benelux (formerly known as Krimson) was tinkering with the idea of offering support, but it was only when Drupal newbie Jurgen Verhasselt arrived at the company in 2012 that the idea really took shape.

Before his arrival, six different people, all with different profiles, were handling customer support in a weekly rotation system. This worked poorly. A developer trying to get his own job done plus deal with a customer issue at the same time was getting neither job done properly. Tickets got lost or forgotten, customers felt frustrated and problems were not always fixed. We knew we could do better. The job required uninterrupted dedication and constant follow-up.

That’s where Jurgen came in the picture. After years of day job experience in the graphic sector and nights spent on Drupal he came to work at Wunderkraut and seized the opportunity to dedicate himself entirely to Drupal support. Within a couple of weeks his coworkers had handed over all their cases. They were relieved, he was excited! And most importantly, our customers were being assisted on a constant and reliable basis.

By the end of 2012 the first important change was brought about, i.e. to have Jurgen work closely with colleague Stijn Vanden Brande, our Sys Admin. This team of two ensured that many of the problems that arose could be solved extremely efficiently. Wunderkraut being the hosting party as well as the Drupal party means that no needless discussions with the hosting took place and moreover, the hosting environment was well-known. This meant we could find solutions with little loss of time, as we know that time is an important factor when a customer is under pressure to deliver.

In the course of 2013 our support system went from a well-meaning but improvised attempt to help customers in need to a fully qualified division within our company. What changed? We decided to classify customer support issues into: questions, incidents/problems and change requests and incorporated ITIL based best practices. In this way we created a dedicated Service Desk which acts as a Single Point of Contact after Warranty. This enabled us to offer clearly differing support models based on the diverse needs of our customers (more details about this here). In addition, we adopted customer support software and industry standard monitoring tools. We’ve been improving ever since, thanks to the large amount of input we receive from our trusted customers. Since 2013, Danny and Tim have joined our superb support squad and we’re looking to grow more in the months to come.

When customers call us for support we do quite a bit more than just fix the problem at hand. Foremostly, we listen carefully and double check everything to ensure that we understand him or her correctly. This helps to take the edge off the huge pressure our customer may be experiencing. After which, we have a list of do’s and don’t for valuable support.

  • Do a quick scan of possible causes by getting a clear understanding of the symptoms
  • Do look for the cause of course, but also assess possible quick-fixes and workarounds to give yourself time to solve the underlying issue
  • Do check if it’s a pebkac
  • and finally, do test everything within the realm of reason.

The most basic don’t that we swear by is:

  • never, ever apply changes to the foundation of a project.
  • Support never covers a problem that takes more than two days to fix. At that point we escalate to development.

We are so dedicated to offering superior support to customers that on explicit request, we cater to our customers’ customers. Needless to say, our commitment in support has yielded remarkable  results and plenty of customer satisfaction (which makes us happy, too)

Nov 30 2020
Nov 30

If your website is running Drupal 6, chances are it’s between 3 and 6 years old now, and once Drupal 8 comes out. Support for Drupal 6 will drop. Luckily the support window has recently been prolonged for another 3 months after Drupal 8 comes out. But still,  that leaves you only a small window of time to migrate to the latest and greatest. But why would you? 

There are many great things about Drupal 8 that will have something for everyone to love, but that should not be the only reason why you would need an upgrade. It is not the tool itself that will magically improve the traffic to your site, neither convert its users to start buying more stuff, it’s how you use the tool.  

So if your site is running Drupal 6 and hasn’t had large improvements in the last years it might be time to investigate if it needs a major overhaul to be up to par with the competition. If that’s the case, think about brand, concept, design, UX and all of that first to understand how your site should work and what it should look like, only then we can understand if a choice needs to be made to go for Drupal 7 or Drupal 8.  

If your site is still running well you might not even need to upgrade! Although community support for Drupal 6 will end a few months after Drupal 8 release, we will continue to support Drupal 6 sites and work with you to fix any security issues we encounter and collaborate with the Drupal Security Team to provide patches.

My rule of thumb is that if your site uses only core Drupal and a small set of contributed modules, it’s ok to build a new website on Drupal 8 once it comes out. But if you have a complex website running on many contributed and custom modules it might be better to wait a few months maybe a year until all becomes stable. 

Nov 30 2020
Nov 30

So how does customer journey mapping work?

In this somewhat simplified example, we map the customer journey of somebody signing up for an online course. If you want to follow along with your own use case, pick an important target audience and a customer journey that you know is problematic for the customer.

1. Plot the customer steps in the journey

customer journey map 1

Write down the series of steps a client takes to complete this journey. For example “requests brochure”, “receives brochure”, “visits the website for more information”, etc. Put each step on a coloured sticky note.

2. Define the interactions with your organisation

customer journey map 2

Next, for each step, determine which people and groups the customer interacts with, like the marketing department, copywriter and designer, customer service agent, etc. Do the same for all objects and systems that the client encounters, like the brochure, website and email messages. You’ve now mapped out all people, groups, systems and objects that the customer interacts with during this particular journey.

3. Draw the line

customer journey map 3

Draw a line under the sticky notes. Everything above the line is “on stage”, visible to your customers.

4. Map what happens behind the curtains

customer journey map 4

Now we’ll plot the backstage parts. Use sticky notes of a different color and collect the persons, groups, actions, objects and systems that support the on stage part of the journey. In this example these would be the marketing team that produces the prod brochure, the printer, the mail delivery partner, web site content team, IT departments, etc. This backstage part is usually more complex than the on stage part.

5. How do people feel about this?

Customer journey map 5

Now we get to the crucial part. Mark the parts that work well from the perspective of the person interacting with it with green dots. Mark the parts where people start to feel unhappy with yellow dots. Mark the parts where people get really frustrated with red. What you’ll probably see now is that your client starts to feel unhappy much sooner than employees or partners. It could well be that on the inside people are perfectly happy with how things work while the customer gets frustrated.

What does this give you?

Through this process you can immediately start discovering and solving customer experience issues because you now have:

  • A user centred perspective on your entire service/product offering
  • A good view on opportunities for innovation and improvement
  • Clarity about which parts of the organisation can be made responsible to produce those improvements
  • In a shareable format that is easy to understand

Mapping your customer journey is an important first step towards customer centred thinking and acting. The challenge is learning to see things from your customers perspective and that's exactly what a customer journey map enables you to do. Based on the opportunities you identified from the customer journey map, you’ll want to start integrating the multitude of digital channels, tools and technology already in use into a cohesive platform. In short: A platform for digital experience management! That's our topic for our next post.

Nov 30 2020
Nov 30

In combination with the FacetAPI module, which allows you to easily configure a block or a pane with facet links, we created a page displaying search results containing contact type content and a facets block on the left hand side to narrow down those results.

One of the struggles with FacetAPI are the URLs of the individual facets. While Drupal turns the ugly GET 'q' parameter into a clean URLs, FacetAPI just concatenates any extra query parameters which leads to Real Ugly Paths. The FacetAPI Pretty Paths module tries to change that by rewriting those into human friendly URLs.

Our challenge involved altering the paths generated by the facets, but with a slight twist.

Due to the projects architecture, we were forced to replace the full view mode of a node of the bundle type "contact" with a single search result based on the nid of the visited node. This was a cheap way to avoid duplicating functionality and wasting precious time. We used the CTools custom page manager to take over the node/% page and added a variant which is triggered by a selection rule based on the bundle type. The variant itself doesn't use the panels renderer but redirects the visitor to the Solr page passing the nid as an extra argument with the URL. This resulted in a path like this: /contacts?contact=1234.

With this snippet, the contact query parameter is passed to Solr which yields the exact result we need.

/**
 * Implements hook_apachesolr_query_alter().
 */
function myproject_apachesolr_query_alter($query) {
  if (!empty($_GET['contact'])) {
    $query->addFilter('entity_id', $_GET['contact']);
  }
}

The result page with our single search result still contains facets in a sidebar. Moreover, the URLs of those facets looked like this: /contacts?contact=1234&f[0]=im_field_myfield..... Now we faced a new problem. The ?contact=1234 part was conflicting with the rest of the search query. This resulted in an empty result page, whenever our single search result, node 1234, didn't match with the rest of the search query! So, we had to alter the paths of the individual facets, to make them look like this: /contacts?f[0]=im_field_myfield.

This is how I approached the problem.

If you look carefully in the API documentation, you won't find any hooks that allow you to directly alter the URLs of the facets. Gutting the FacetAPI module is quite daunting. I started looking for undocumented hooks, but quickly abandoned that approach. Then, I realised that FacetAPI Pretty Paths actually does what we wanted: alter the paths of the facets to make them look, well, pretty! I just had to figure out how it worked and emulate its behaviour in our own module.

Turns out that most of the facet generating functionality is contained in a set of adaptable, loosely coupled, extensible classes registered as CTools plugin handlers. Great! This means that I just had to find the relevant class and override those methods with our custom logic while extending.

Facet URLs are generated by classes extending the abstract FacetapiUrlProcessor class. The FacetapiUrlProcessorStandard extends and implements the base class and already does all of the heavy lifting, so I decided to take it from there. I just had to create a new class, implement the right methods and register it as a plugin. In the folder of my custom module, I created a new folder plugins/facetapi containing a new file called url_processor_myproject.inc. This is my class:

/**
 * @file
 * A custom URL processor for cancer.
 */

/**
 * Extension of FacetapiUrlProcessor.
 */
class FacetapiUrlProcessorMyProject extends FacetapiUrlProcessorStandard {

  /**
   * Overrides FacetapiUrlProcessorStandard::normalizeParams().
   *
   * Strips the "q" and "page" variables from the params array.
   * Custom: Strips the 'contact' variable from the params array too
   */
  public function normalizeParams(array $params, $filter_key = 'f') {
    return drupal_get_query_parameters($params, array('q', 'page', 'contact'));
  }

}

I registered my new URL Processor by implementing hook_facetapi_url_processors in the myproject.module file.

**
 * Implements hook_facetapi_url_processors().
 */
function myproject_facetapi_url_processors() {
  return array(
    'myproject' => array(
      'handler' => array(
        'label' => t('MyProject'),
        'class' => 'FacetapiUrlProcessorMyProject',
      ),
    ),
  );
}

I also included the .inc file in the myproject.info file:

files[] = plugins/facetapi/url_processor_myproject.inc

Now I had a new registered URL Processor handler. But I still needed to hook it up with the correct Solr searcher on which the FacetAPI relies to generate facets. hook_facetapi_searcher_info_alter allows you to override the searcher definition and tell the searcher to use your new custom URL processor rather than the standard URL processor. This is the implementation in myproject.module:

/**
 * Implements hook_facetapi_search_info().
 */
function myproject_facetapi_searcher_info_alter(array &$searcher_info) {
  foreach ($searcher_info as &$info) {
    $info['url processor'] = 'myproject';
  }
}

After clearing the cache, the correct path was generated per facet. Great! Of course, the paths still don't look pretty and contain those way too visible and way too ugly query parameters. We could enable the FacetAPI Pretty Path module, but by implementing our own URL processor, FacetAPI Pretty Paths will cause a conflict since the searcher uses either one or the other class. Not both. One way to solve this problem would be to extend the FacetapiUrlProcessorPrettyPaths class, since it is derived from the same FacetapiUrlProcessorStandard base class, and override its normalizeParams() method.

But that's another story.

Nov 30 2020
Nov 30

We are currently planning for Drupal core to drop support for Internet Explorer 11 in Drupal 10 (scheduled to be released in June 2022). Drupal 9 will be supported until late 2023, which means that sites that want to support Internet Explorer 11 can continue using Drupal 9 until then.

Feedback needed from assistive technology stakeholders

WebAIM's survey of screen reader users shows Internet Explorer 11 usage dropping from 23.3% in October 2017 to 10.9% in September 2019. The next edition of their survey is likely to be released at the end of 2021, but we need to finalize our browser support within the next month in order to develop and release Drupal 10 on schedule.

We need feedback from assistive technology users and accessibility stakeholders. Do you or your users still use Internet Explorer 11 with screen readers? Do their screen readers support browsers other than Internet Explorer 11? How feasible is it to upgrade to a different browser for use with your screen reader? We are requesting feedback until December 18th, 2020.

Why would we drop support for Internet Explorer 11?

  • Microsoft stopped developing Internet Explorer 11 in 2015. For that reason it is significantly behind modern browsers that have continued development. Because more and more libraries are adopting the use of those features, there is a significant cost associated with maintaining Internet Explorer 11. For example, the latest major release of CKEditor has dropped support for Internet Explorer 11, which means that Drupal 10 cannot securely support both CKEditor5 and Internet Explorer 11.

  • Microsoft itself has dropped support for Internet Explorer 11 in many of its services, and the rest will drop support in mid-2021.

  • Usage of Internet Explorer 11 has decreased significantly. Drupal doesn’t collect analytics on browser usage from its end users, so we rely on data provided by other projects such as Wikimedia, WebAIM, and Statcounter. For example, in October 2019, Wikimedia had 4.4% of its traffic using Internet Explorer 11. At the same time this year the number had dropped to 1.4%. We assume that the number of Internet Explorer 11 users will continue decreasing before the release of Drupal 10.

  • Supporting Internet Explorer 11 degrades the experience for everyone. We currently supply all users extra code to make Internet Explorer 11 work. This increases the request size and makes page load time slower for everyone.

  • The additional requirements of Internet Explorer 11 demand additional development time that far exceeds the browser's market share. These efforts come at the expense of new features and bug fixes.

What if I need to support Internet Explorer 11?

Even if Drupal 10 drops support for Internet Explorer 11, you can continue using Drupal 9 until late 2023. We recommend advising your users to move to another browser before that. If you believe your users have specific requirements as to why they cannot move from Internet Explorer 11, post them on the Internet Explorer 11 policy discussion.

Would this affect Drupal 7?

No. Drupal 7 remains compatible with Internet Explorer 11. A separate announcement will be issued if that changes.

Nov 30 2020
Nov 30

We are currently planning for Drupal core to drop support for Internet Explorer 11 in Drupal 10 (scheduled to be released in June 2022). Drupal 9 will be supported until late 2023, which means that sites that want to support Internet Explorer 11 can continue using Drupal 9 until then.

Feedback needed from assistive technology stakeholders

WebAIM's survey of screen reader users shows Internet Explorer 11 usage dropping from 23.3% in October 2017 to 10.9% in September 2019. The next edition of their survey is likely to be released at the end of 2021, but we need to finalize our browser support within the next month in order to develop and release Drupal 10 on schedule.

We need feedback from assistive technology users and accessibility stakeholders. Do you or your users still use Internet Explorer 11 with screen readers? Do their screen readers support browsers other than Internet Explorer 11? How feasible is it to upgrade to a different browser for use with your screen reader? We are requesting feedback until December 18th, 2020.

Why would we drop support for Internet Explorer 11?

  • Microsoft stopped developing Internet Explorer 11 in 2015. For that reason it is significantly behind modern browsers that have continued development. Because more and more libraries are adopting the use of those features, there is a significant cost associated with maintaining Internet Explorer 11. For example, the latest major release of CKEditor has dropped support for Internet Explorer 11, which means that Drupal 10 cannot securely support both CKEditor5 and Internet Explorer 11.

  • Microsoft itself has dropped support for Internet Explorer 11 in many of its services, and the rest will drop support in mid-2021.

  • Usage of Internet Explorer 11 has decreased significantly. Drupal doesn’t collect analytics on browser usage from its end users, so we rely on data provided by other projects such as Wikimedia, WebAIM, and Statcounter. For example, in October 2019, Wikimedia had 4.4% of its traffic using Internet Explorer 11. At the same time this year the number had dropped to 1.4%. We assume that the number of Internet Explorer 11 users will continue decreasing before the release of Drupal 10.

  • Supporting Internet Explorer 11 degrades the experience for everyone. We currently supply all users extra code to make Internet Explorer 11 work. This increases the request size and makes page load time slower for everyone.

  • The additional requirements of Internet Explorer 11 demand additional development time that far exceeds the browser's market share. These efforts come at the expense of new features and bug fixes.

What if I need to support Internet Explorer 11?

Even if Drupal 10 drops support for Internet Explorer 11, you can continue using Drupal 9 until late 2023. We recommend advising your users to move to another browser before that. If you believe your users have specific requirements as to why they cannot move from Internet Explorer 11, post them on the Internet Explorer 11 policy discussion.

Would this affect Drupal 7?

No. Drupal 7 remains compatible with Internet Explorer 11. A separate announcement will be issued if that changes.

Nov 30 2020
Nov 30

In this short article I want to introduce you to a new module we recently released on Drupal.org, namely Multi-value form element.

drupal multi value form elements

This small module provides a form element that allows you to easily define multi-value elements in your custom forms. Much like what field widgets provide with the Add another item Ajax button.

So how does it work? Easy, really. All you have to do is define a form element of the '#type' => 'multivalue' with one or more children, defined like you normally would. So for example:

$form['names'] = [
  '#type' => 'multivalue',
  '#title' => $this->t('Names'),
  'name' => [
    '#type' => 'textfield',
    '#title' => $this->t('Name'),
  ],
];

Would give you this:

drupal multi value form elements example

And you can also use multiple form element children if you want:

$form['contacts'] = [
  '#type' => 'multivalue',
  '#title' => $this->t('Contacts'),
  'name' => [
    '#type' => 'textfield',
    '#title' => $this->t('Name'),
  ],
  'mail' => [
    '#type' => 'email',
    '#title' => $this->t('E-mail'),
  ],
];

So as you can see, no big deal to use. But all the complex Ajax logic of adding extra values is out of your hands now and can easily build nice forms.

Check out some more examples of how to use this element and what options it has above the Drupal\multivalue_form_element\Element\MultiValue class.

This module is sponsored by the European Commission as part of the OpenEuropa initiative and all the work my colleagues and myself are doing there.

Nov 27 2020
Nov 27

Drupal is being chosen as a platform for building websites, among other things, due to its flexibility. If you want a system ideally suited to your business model and better than the competition's systems, Drupal will prove to be perfect. One of the areas you can customise in Drupal is the user permissions system. Take a few minutes to learn about the permission management abilities of Drupal.

General information

Drupal allows you to manage access from the admin panel and from the code level. In this post, I will present these two possibilities and the most common examples of their use.

Roles and permissions in the Drupal core

If this is your first time dealing with Drupal and its permission system, you should know that there are three elements used for granting permissions:

  1. User
  2. Role
  3. Permission

When installing Drupal, you create a root administrator account in the system (identifier 1 in the database). It can be compared to the root user in Unix systems. This user has access to all subpages and settings in the system.

You can add more users to the system. These could be, e.g. the editors responsible for creating the content, or the moderators deciding whether to post the added comments.

If you want to assign a permission to a given user, you do it indirectly by assigning a role to them. There is no association between a user and permissions in Drupal. There is a user-role association and a role-permission association.

schema

How to add an editor role and assign the appropriate permissions to it

This is probably the most common issue encountered in Drupal. You need to let users into your system, but you want to limit their rights to the content management only. You do not want to give the rights to change the system configuration or to add new users.

In order to achieve this, follow these steps:

  1. Add a new role on the page "/admin/people/roles/add/".
  2. Assign the selected permissions to the role on the page "/admin/people/permissions/". For the content-related ones, check out the "Node" section. Below you can find more information on the permission list.
  3. Assign the selected user to the new role on the page "/admin/people/".

Then log-in into the account of the selected user and check out whether they have the appropriate permissions. Maybe you need to extend them or take them away. If you are unfamiliar with the Drupal's permission system, such a test with logging-in into the user account is always worth carrying out.

You do not need to know the password to the user account you want to log-in into. You just need to install the module Masquerade. Thanks to it, you can log-in into the account of any user.

Drupal core permissions overview

When entering the page "/admin/people/permissions/" for the first time, one can get a little scared. This is probably the longest configuration page in Drupal.

Let us start with the table header. You will always see the word "PERMISSION" in the first column. In the next cells of the first row, there will be the names of the roles. The more roles you add (you can add them on the page /admin/people/roles/add/), the more of them you will see in this table.

Then, looking at the first column in its entirety, you will see a long list of permissions. The permissions are divided into sections. The sections are the names of modules. The "Node" section mentioned earlier is named so because the permissions in this section are defined in the "node" module (you will find it on your disk in the core/modules/node directory).

Some sections have only one permission, e.g. the "Block" section has the "Administer blocks" permission only. Others have many more of them.

If this is your first time dealing with Drupal permission settings, I suggest that you read the names of all permissions. The names themselves explain what a given permission is for.

Anonymous & Authenticated

There are two system roles in Drupal that cannot be removed:

  1. Anonymous User
  2. Authenticated User

The first of these roles is responsible for all non-logged-in users. For example: if you want to add the ability to view user profiles for all non-logged-in for the "View user information" permission, tick the checkbox in the "Anonymous User" column.

"Authenticated User" is the role assigned to all logged-in users. It is important here to understand the permission inheritance. If you assign a permission to "Authenticated User", then all other roles (except anonymous) will be given this permission immediately.

Example: You have the "Editor" role in the system. You assign the "View user information" permission to the "Authenticated User" role. Everyone with the "Editor" role will also be given the permission because they are also considered to be logged-in users.

Moreover, keep in mind that if you select any permission for the Anonymous role (e.g. "View user information" again), but do not select it for the "Authenticated User", the logged-in users will not be able to access the selected section ("View user information" – they will not have access to user profiles).

Worth remembering

  • In Drupal, you can add an unlimited number of roles.
  • The list of permissions is defined by modules in modulename.permissions.yml files (more on this can be found further in the text). 
  • The "Authenticated" and "Anonymous" roles are separate – if you select something for "Anonymous" only, the logged-in users will not be given this permission.
  • To test permissions, it is good to use the Masquerade module.

Own permissions in the code

Sometimes there is a need to define your own permissions, e.g. to administration pages defined by new modules or to modify access to the pages defined by the Drupal core.

How to define a permission

You just need to add the modulename.permissions.yml file in the new module (or in the existing one, if you already have your own modules created). If you do not know how to create your own modules, I encourage you to visit the website.

The permission file is a file in the YML format. A simple example can be found in the Popup Message module, right here.

skrin

Being defined in the file is a unique name for the permission (e.g. "popup message administration"), and then – the names being displayed on the page "/admin/people/permissions/". You can provide a title in the "title" parameter and additionally – a more detailed description in the "description" parameter.

This is enough to define new permissions. After creating the file and clearing the cache, you will see the new permissions on the "/admin/people/permissions/" page.

How to use a permission

Most often, permissions are being used when defining routing. Take a look at the file.

In the "requirements" section, you can add the "permission" parameter. In this way, you can define the users (or rather roles) with what permission can display the page defined in routing.

The second method is to check out the permissions in your code. User object in Drupal has the "hasPermission" method. In this way, you can check out whether a given user has the selected permission.

// Get the current user
$user = \Drupal::currentUser();
// Check for permission
if ($user->hasPermission('display popup message')) {
// Do something.
}

It is worth to take a look at the hasPermission method here. As you can see, the user ID is being checked there. If the id equals 1, the user gets access without further checking if they have selected roles.

How to check whether the user has a role

Drupal also offers a ready-made method to check whether a given user has a role with a specific name. Provided below is an example of how you can do it in the code.

// Get the current user
$user = \Drupal::currentUser();
// Check for permission
if ($user->hasRole('editor')) {
// Do something.
}

Additionally, there are also methods related to the Authenticated and Anonymous roles:

  • $user-> isAuthenticated();
  • $user-> isAnonymous();

How to check permissions for operations on an entity

In the application code, you can also check the permissions to operate on selected entities (e.g. Node or User). You can perform certain operations, e.g. depending on whether the user has the right to edit a given entity or to display an entity.

Entities in Drupal have the method access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE). A simple example of use is provided below:

$nid = 545;
$node = \Drupal\node\Entity\Node::load($nid);
$user = \Drupal::currentUser();
if ($node->access('edit', $user)) {
// Do something
}

Defining content permissions

Drupal allows you to manage access to display and edit at the level of a single entry (node). This topic was thoroughly described in our other blog post. Grzegorz Pietrzak described it in the article Drupal Node grants.

Ready-made modules for Drupal related to permissions

There are already many ready-made modules extending the capabilities of the Drupal core. You should check them out before you start writing your own permission-related modules.

Below is a list of a few selected modules that are worth checking out and testing:

Also, check the page and take a look at other modules. Maybe some of them you will find useful.

Summary

Drupal is a very flexible system. Just looking at the possibilities regarding permissions, you can see the multitude of configuration possibilities. If you are building a large website with many editor levels or an internal application (e.g. an intranet system) where the users must have limited permissions, Drupal will do the job very well.

If you need support from Drupal specialists on permissions or other issues, use the services of our Drupal developers.

Nov 27 2020
Nov 27

We just launched a new free demo on try.dxpr.com that lets you test drive the DXPR Drupal experience. Thanks to our 60+ new demo pages you will be guided to explore the many exciting elements and features that are offered in our DXPR Builder and DXPR Builder Enterprise modules for Drupal 9.

The new demo takes it to the next level: our demo site is based on Acquia Lightning and shows you the extent of Drupal integration of our front-end layout building application. Learn how our state-of-the-art visual authoring experience seamlessly integrates with Drupal’s multilingual features, workflow processes, and views.

New minor release for DXPR Builder

Today we release a new minor version update for both our Drupal 7 and Drupal 9 branches of DXPR Builder. Most notably we now have improved native support for media entities in DXPR Builder.

Whether you are on Acquia Lightning or a completely custom Drupal 9 platform, if you upload or re-use images in the DXPR Builder editor our software will automatically detect if your site supports media entities or just file entities, and create media entities when this is supported.

What's next? Bootstrap 4 support!

The DXPR team is working hard to bring our products up to date with Bootstrap 4. This is a large migration for us since our Drupal layout builder is based on and built around Bootstrap 3.

We aim to have a release out that takes full advantage of Bootstrap 4's new features. We will also be able to improve the layout building experience by taking advantage of CSS flexbox technology, which is fully supported in Bootstrap 4.

Nov 25 2020
Nov 25

The Drupal project uses the PEAR Archive_Tar library. The PEAR Archive_Tar library has released a security update that impacts Drupal. For more information please see:

Multiple vulnerabilities are possible if Drupal is configured to allow .tar, .tar.gz, .bz2, or .tlz file uploads and processes them.

To mitigate this issue, prevent untrusted users from uploading .tar, .tar.gz, .bz2, or .tlz files.

This is a different issue than SA-CORE-2019-012. Similar configuration changes may mitigate the problem until you are able to patch.

Nov 25 2020
Nov 25

In my first blog post, I introduced the Custom Elements module: A solution for soft-decoupled Drupal! Following that, I want to put more emphasize on the frontend side of the stack in this blog post:

Selecting a frontend framework

With the backend producing custom elements markup, we need a frontend framework that is able to work with that. While there are many frameworks that play nice with custom elements, we want to pick a well-established solution with a large user base. That way, it's more likely that the framework stays relevant and well maintained on the long term. Also, finding more integrated libraries, learning materials or developers knowing the framework becomes much easier.

According to The State of JavaScript 2019: Front End Frameworks the top 3 frameworks developers have used are React, Vue.js and Angular:

  • Angular has been not liked much by developers that used it and won't be used again by the majority of them (see survey). Besides that, it's provided as a whole MVC framework with lots of things potentially not needed here. So not the best fit.

  • React has a very strong user base, but does not play that well with custom elements. While there are solutions like react-slot, they are not as common and well maintained. Finally, personally I don't like the "Everything is Javascript" approach so much.

  • Vue.js on the other hand, comes with template parsing built-in that is able to render custom elements data easily. Like React, it utilizes a virtual DOM and is well adopted and continuously growing. Finally, the Vue.js single file components are following a template based, web-standard oriented approach.

  • Since web components build upon custom elements, they seem to be the perfect fit. However, they are not, since they are not well adopted and server-side rendering web components is not a well solved issue (yet?).

Vue.js

Thus, Vue.js turns out to be the ideal candidate for our decoupled Drupal stack built upon custom elements. Moreover, I like it for the following:

  • It's approachable and easy to use. It has great documentation and sticks to web standard oriented notations.

  • It comes with a set of incrementable adoptable companion libraries for further needs, like routing or state management.

  • It's fast! It only weighs 20kB gzipped and scores well in rendering benchmarks.

  • Just like Drupal, it's a community backed open-source project, not depending on a single large corporation. Check out the Vue.js team and its sponsors.

Nuxt.js

Once one decides for Vue.js, one quickly stumbles over Nuxt.js - the intuitive Vue framework. It comes with a set of useful conventions - inspirated by Next.js - that make it very easy and enjoyable to get started with development. It provides all necessary setup for Javascript transpilation, CSS processing and improves performance by handling route-based automatic code-spliting or link prefetching. Thankfully, it's following Vue.js principles, thus it emphasizes the ease of use and provides great documentation.

Finally, it's built upon a powerful, modular architecture and allows providing features as re-usable Nuxt.js modules - what makes it a great addition to Drupal. While the number of modules is nowhere comparable to Drupal, there are many useful modules available, like PWA generation, Google Analytics or Tag manager integration, or the usual frontend/CSS framework integrations with Bootstrap, Material UI or Tailwind CSS. Check out the module directory at modules.nuxtjs.org for more.

Nuxt.js deployment options

One of the nice features of Nuxt.js is that it's really easy to deploy your project using various ways, all from the same code-base - just by a different deployment configuration. The options are:

  • Static generation
    Generate a static site and leverage the Jamstack approach for dynamic functionality and content previews.

  • Server Side Rendering
    Render the markup using a Node.js server or Serverless functions.

  • Single Page Application

    Just serve a pre-built Javascript application to users and let the user's browser take over rendering.

That way, one can choose the best suiting deployment target per project. Small sites without a large number of pages could be very easily statically generated and benefit from fast, cheap and secure hosting; e.g. via providers like Netlify, Amazon S3 or Github pages. If SEO is not required, running as a Single Page application does away the need for re-building after content changes and allows for highly dynamic, user-specific content and app-like UIs.

More demanding projects, requiring SEO and having a large number of content, can use server side rendering with any Node.js compatible hosting provider like Platform.sh or Heroku. Alternative options would be specialized hosting providers like Vercel, AWS amplify or deploying via the Serverless framework to various serverless cloud providers.

The frontproxy approach

Finally, I'd like to mention we also developed a custom, more advanced approach that becomes possible with custom elements markup: The lupus-frontproxy is a small PHP-based script that serves content as custom element markup combined with a pre-generated app shell (site header and footer). That way, large, content-heavy sites can easily run without a node.js server driving the frontend, while still providing decent SEO based upon the custom element markup delivered (Google just ignores custom elements and indexes the contained markup). However, with the rise of easy and affordable hosting options for server side rendering, such a custom built, uncommon solution seems unnecessary and not really worth the efforts.

Summing up

Nuxt.js is a great framework that makes it really easy to build a Vue.js based frontend application that renders the custom elements markup provided by the Drupal backend. Since each custom element is mapped to a Vue.js component, it's the perfect fit for building up component-based frontends, while keeping the editorial controls in the backend.

Thanks to its flexible deployments options, we can leverage static generation for smaller sites and use server-side rendering for larger, more content-heavy sites.

Following up

Since there are so many details more to talk about, I'll be following up with further blog posts in the coming weeks, covering the following topics:

  • Authentication & related architecture variants. Custom Elements markup & json formats.

  • A developer introduction: Creating components, adding Custom Element processors, the relationship to Drupal's render API, Custom routes and optimizing cache metadata.

  • Handling blocks & layout builder, content previews, forms, caching & performance optimizations.

Finally, I'm going to talk more about this stack at the Drupalcon Europe 2020 in my session "Custom Elements: An alternate Render API for decoupled Drupal" at December 08 - 09:15 - so mark your calendars!

Wolfgang Ziegler

On drupal.org:

fago

Drupal evangelist since 2005, Drupal Core contributor & contrib maintainer, TU-Vienna graduate (Information & Knowledge Management)

Nov 25 2020
Nov 25

DrupalCon Europe 2020 is just around the corner and we’re super excited to attend, speak and contribute to this year's virtual event for all things Drupal.

This year's event is chockablock with great ways to expand your skills, network with the community and contribute your talents to making Drupal even better. Everyone is welcome and all experience levels are encouraged to contribute. 

Here’s what our developers are sharing this year. 

Tuesday, December 08


Check out Nick O'Sullivan’s talk Decoupled Translations with Drupal and learn how to utilise Drupal’s exceptional multilingual features to produce a fully localised Gatsby site — 13:30 to 13:50 CET

Wednesday, December 09


Join Dan Lemon for his panel discussion and workshop – Retrospective: How did the COVID-19 Crisis Affect Client Relationships and What Can We Take Out of It?. This interactive workshop facilitated by a team of agile coaches will use the retrospective format so we can share and learn from our experiences with the COVID-19 crisis. We will celebrate achievements and collect insights on what we can learn and improve for the future – 16:15 to 17:15 CET

Thursday, December 10
 

These days, more and more often digital web solutions face the challenge of becoming out of date and suffering technical debt that stymies innovation. Break the cycle and catch Philipp Melab in the panel discussion on Sustainable Practices for Building and Maintaining the Open Web — 09:15 to 09:55 CET

Learn how to take an already existing Drupal site and quickly add CypressIO and start writing end to end tests in Fran Garcia-Linares’ talk Add End to End Tests to Your Drupal Site in one hour with CypressIO — 10:35 to 10:55 CET

Then join Dan Lemon’s Building a Platform to Bring People Together to Celebrate Drupal for the story of how CelebrateDrupal.org came to be — 11:30 to 12:10 CET

Friday, December 11
 

Make sure to set aside some time and join us for Friday’s Contribution Day, an open-source get-together for focused collaborative work. Contributions range from organizing events and designing a user interface, to translating text and verifying bugs. There will be opportunities to help out all throughout the conference, but Friday is a dedicated contribution day. 

Don’t forget to check out the full schedule of 119 sessions, four in-depth interactive workshops, four keynotes, 42 BoFs, a myriad of contribution topics, fun social events and more.  

Register today! We’ll see you there!
 

Nov 25 2020
Nov 25

Building websites that are completely mistake proof is often considered to be a massive undertaking, which many-many times is not properly executed. Since there are so many parameters to fulfil and so many corners to oversee, mistakes tend to happen. You may not even realise that you have done something wrong in the development process, it could be much much later when you actually undergo a website audit that you come across the mistake that has been made.

Drupal websites are equally prone to mistakes. Despite the CMS being one of the best, there are still occurrences when things go wrong and the impact is felt on the engagement, conversions and consequently, the sales.

To not let that happen, I have compiled a list of mistakes that you need to steer clear of when building or working on a Drupal website. These are errors and oversights that many developers and content authors have experienced first-hand and you can certainly try to learn from their mistakes.

So here are the most common mistakes witnessed on Drupal websites.

A pencil is shown after having erased an error on the extreme left and the mistakes to avoid in Drupal are written in bullets in the rest of the space on a white background.


Where can you go wrong with the content? 

A good website is often considered to be the one with outstanding content, since that is what keeps the audience engaged and leads to conversion. Therefore, content is crucial for a website, both for the front-end and the back-end, so content should be one of the priorities in the website designing process. Due to this fact, there are a number of areas where the developers can go wrong with the content. 

The first common mistake witnesses with the architecture of content is using too many content types that you actually do not use. The unused content types are just going to burden your database and I am certain, you would not want an additional table in your database for three content types that you do not even use. Having content types with no nodes will have the same effect. Performing an inventory will help you get the mistake resolved.

Moving on from the unused to the used, content structures are extremely valuable for your editors who are going to fill them up and if they end up confused, what will be the point of it all? Standardising your content types is going to help you a great deal. 

  • Strike off the content types that are similar to each other, like news and articles;
  • Do not add new fields for every content type;
  • And most importantly, plan a structure prior to it, winging it may not work with your website content.

Content types have an effect on the performance of your website as well. So, if you do not want to drain the performance of your site by adding unnecessary complexity, you would be wise to avoid these mistakes.

What about your display mismanagement?

After content comes its display and Drupal is best in that game. With many different features available for use, Drupal can make your display game strong as well, you capitalise it wisely.

Creating a view for every list is both impractical and a waste of time. Focus on reusing Views as much as possible along with parameter based rendering.

Do you use PHP code in your database? If so, avoid doing that, instead you must write all the codes in the modules or themes itself.

Planning, optimisation and segregation are essentially the building blocks of a great website display. 

  • Planning to render the content types you need;
  • Optimising the Views you already have;
  • And segregating logic from presentation.

These three would have a visible effect on the display architecture.

What aspects of functionality can make your site lag behind?

The functionality of a Drupal site depends on the number of modules used and the way they interact with each other. Your code and how much of it you use is a major contributor in that. 

The most common mistake in this sense is the ignorance of code standards. This becomes more of a problem when there are more than one developers and everyone is using a different type of code. In such a situation, not only would the standard be lost,  but it would also become difficult for a developer to understand the other’s code. Therefore, the adherence to Drupal’s Coding Standards becomes a great help to uniformalise the code and make the functionality a breeze. 

Another obstacle in functionality are unorganised patches. Code modifications and bug fixes mandates the implementation of patches, however, they become a problem whenever there is an update. You can forget all about re-apply the patch or forget to change it in accordance with the new version. This can very well affect the functionality of your website, so organising them is essential. 

Having too many modules, too many roles and too much custom code, despite there being contrib modules for the same is bound to affect the functionality as well. Evaluate and re-evaluate your site for its needs to overcome these functionality hindrances.

Is your performance and scalability not up to the bar?

User Experience is directly proportional to the performance of your website; the more streamlined the performance is, the richer would the UX be. 

Here are three scenarios that can impact your performance in all the wrong ways.

  • The foremost is improper JS/CSS aggregation settings. This is supposed to combine and compress JS and CSS files from the modules in the HTML, leading to lesser load times and higher performance. And you will be saying goodbye to that with the improper aggregation.
  • The next mistake is that of inundating your site with too many modules. Drupal may have numerous modules to offer, but you can’t be using too many of them. Doing so would only slow you down and hamper your security as well. Only keep the modules that you would be using, messing up your code, performance, overheads and security is simply not worth it.
  • A sound cache strategy also goes a long way in performance enhancement. Caching too soon, caching at lower levels and not knowing what and when to cache all contribute in a lowered performance.

Drupal websites can be scaled by millions of users within seconds and that is what makes these sites great. Drupal offers many modules to enhance the performance and scalability, Blazy, Content Delivery Network and Server Scaling, being just a few of them. Not installing these could be deemed as a mistake.

Are you facing possible security breaches?

Security has become one of the major concerns amongst website builders. Therefore, protecting your business from the menace of hackers and all the havoc they can cause is paramount. 

You must have your security measures in place, however, there still may be certain areas where you may have become complacent and that just gives the break the hackers need. 

  • Primarily, you need to keep your website updated, all the core and contrib modules, despite you using or not using them. Updating a module would mean that Drupal’s security protocols are being updated with them and you make yourself secure with that. You cannot have your projects falling behind on various levels of Drupal’s security advisories.
  • Now, you can install the “ Update Manager” module to keep yourself updated. The “Available Updates” will give you a friendly reminder of applying the available security updates.
  • Next on the list of security blunders is not giving the Input Filters in Drupal their due importance. You might have configured the full HTML Input Format to every user or you might have completely disabled the HTML filtering. Both of these instances can give malicious code to enter your website and you know what happens then.
  • Continuing on similar lines, many sites also configure their servers improperly leading to unwanted access to them. On some occasions, servers are seen displaying their version numbers, which is like giving an open invitation to hackers. Server configuration and permissions should be a priority for every site builder.
  • It is also important to ensure that all the users accessing your site by logging into it are the ones you want. By implementing a password policy, removing old users and updating staff roles, you will be taking a step towards better security.
  • User roles are quite important in running a website, however, they can become overused quite quickly too, which not only slows down your website, but if they are misconfigured, it can lead to major security breaches.

Drupal has proven to be one of the best CMSs in terms of its security measures, it has you covered from every corner, but only if you let it. From granting secure access to providing granular user access control along with database encryption and preventing malicious data entry, Drupal will keep your site protected, provided you let it.

Have you made any infrastructural oversights?

The infrastructure of your website is decided by the stacks you have, which includes the server, database and the software layers like Varnish. Going into development with a firm plan for your infrastructure is the only way to go, an oversight in this area can be quite damaging. 

The common mistakes in this area are;

  • The size of the website’s stack is extremely large or extremely small.
  • Not preparing for growth by consistently checking the logs for error and the identification of the weaklings.
  • Having an ideal sized server, but not configuring it properly, which can make the traffic forego Varnish.
  • Allowing remote connections to the server can make the website more vulnerable.

Misconfiguration can be avoided by simply using the right tools for it. MySQLTuner is one amongst many, its performance suggestions help in improving the infrastructure as well.

Are you following your maintenance goals?

Maintenance of a website starts after the development is done and continues for the entirety of the life of the website. Considering this fact, you have to be very diligent with the maintenance process as making the wrong moves can be brutal.

Here are some of these wrong moves.

  • Not following Drupal updates is a more common mistake than you would think. By doing this, you are going to be hampering security and making your site vulnerable to Drupalgeddon attacks.
  • On the contrary, there are also times when we update the modules, but we forget to remove the older versions. This too happens a lot of the time and can cause many problems.
  • It is not just the modules that need to be updated, the development environment should also be up-to-date and friendly for testing.
  • Then there is the code, which is not using the Version Control System like Git, even the deployment of files should come directly from there. Also, using it, but not leaving messages for other developers related to the changes made can lead to chaos. It is, thereby important to always keep the VCS repository clean.

The crucial aspects of maintenance is time and consistency. When you do it timely, only then would it become a worthy practice. The review and assessment of your architecture in timely intervals along with all the logs, be it Apache or Drupal is a great headstart for the maintenance process.

Are you universally accessible?

Websites today need to transcend the parameters that used to confine them and their audience in the past. The sites and applications need to be built on a foundation that would make them fit for each and every user. Drupal has worked for the same, it aims to make websites accessible to all, including people with disabilities, by making itself an all-accessible tool. 

Web accessibility has become of the essence today, and persons with disabilities are at the core of it. Websites need to be designed keeping in mind their needs, be it a broken hand or a temporary sight loss. It isn't just me who believes this, World Wide Web Consortium’s guidelines agree with me as well. W3C two sets of guidelines are ardently followed by Drupal and your website should do the same, thus, support and foster inclusion. 

Despite its importance, many developers tend to overlook the accessibility features and that is where they go so very wrong. 

  • Not focusing on balanced contrast levels that can work under sunlight;
  • Not incorporating a form validation error verbiage to aid the visually impaired; 
  • Not using buttons over CTAs.

These may seem like minor errors to you, but they can go a long way in making your Drupal site accessible to everyone.

Is your site SEO friendly?

Being SEO friendly is almost as important as building a website. Search engines bring in big numbers of traffic, so optimising them is crucial; yet we tend to forget to fine-tune the SEO details and focus on all the other aspects. At the end of the day, a website is an online business and business cannot survive without its clients and being SEO friendly is the way to go. Going wrong in this area can be extremely detrimental.

Look at the following aspects of a website and see how many you are and aren’t doing. 

Are your URLs user friendly?
Are your images small in size, with filled out alt texts?
Are you making your paragraphs short to make the text easy to scan through?
Are you using robots.txt for pages that you do not want crawled?
Are you creating an XML roadmap to help Google easily understand the structure of your website?
Are you researching your keywords?
Are you adding internal links to make your less popular pages gain attention through the more popular ones?

A positive answer to all of these means that your SEO game is strong and a contrary answer would let you know your mistakes.

To avoid the contrary from happening, Drupal provides a number of modules to help you capitalise on the SEO front. The SEO checklist module is a proof of that as it helps you by ensuring that you are following through on the latest SEO practices. Then there are the modules that aid your URL precision, like Redirect, Pathauo and Easy Breadcrumbs.From easing the process tags to helping in communication with search engines to providing the essentials for editing, Drupal has all the right SEO modules in its corner and not using these would be a colossal mistake on your part. Read our blog, The Ultimate Drupal SEO Guide 2020, to know more about these. 

Can being multilingual pose a problem for you? 

Today, languages that are regionally spoken have started getting more prominence than ever before, especially in the international community. A french website would not be successful in India, if it is in French, not many people speak that language, so it would have to be in a locally accepted language. Being multilingual also opens the doors for many mistakes to occur. 

  • Using the same URL for all of your multilingual websites; 
  • Not giving the user a chance to avoid a redirect to the international website;
  • Using an automated translator, instead of actually hiring content authors fluent in the language;
  • Foregoing to translate the imbedded parts of the site like meta tags and descriptions;
  • Not focusing on the foreign market trends and the keywords appropriate to it;
  • And lastly, not writing the content in accordance with the local language and dialects. You can’t be calling ice lollies popsicles sticks in India.

You have to be totally attuned with the language of the region that you have followed for the multilingual project to work.

Is having a multisite presence worth it?

Depending on your business and its needs, having multiple sites can be a good solution for you. However, managing then can become a bit of a hassle and often lead to big blunders. 

Some examples of such blunders are;

  • Traffic is one of the major concerns here. Running multiple sites means you have one codebase and many sites on it, so if one is inundated with traffic, all of them could slow down as a result.
  • A mistake in the syntax of one site could mean a mistake in the syntax of all.
  • Updates become a headache as well. For Drupal sites, you have to run an update.php in order to update the site and doing that on multiple sites is going to bring on the headache.
  • And finally, if you do not use Aegir, you are going to regret going multisite.

Is your Decoupled Drupal approach the right one?

Drupal offers an impressive front-end technology to make your presentation layer as good as you want, yet it does not include all the front end technologies there are on the market. Taking advantage of JavaScript and Static Site Generator would mean to decouple Drupal and separating the front-end from it. Even if you want to take on decoupling, it may not want to take on. The decoupled Drupal can bring more drawbacks then. 

  • If you wish to capitalise Drupal’s in-built features, Decoupling would be a mistake, since you would end up parting with them.
  • If your front-end requirements and Drupal’s front-end capabilities are aligned, taking on Decoupling would only be an unnecessary effort on your part.
  • If you do not have either the budget or resources to tap into the hottest technologies, then even if you want them it is not going to be fruitful.
  • If you are only publishing content at one place, you would have no need for decoupling.

For a detailed explanation, read our blog, When to Move From Monolithic to Decoupled Drupal Architecture.

Finally, what about web hosting, are you doing it the right way?

Web hosting services that provide your website its own space on the internet are pretty common. There are far too many web hosts to count, yet the decision to choose one is not easy at all, since there are too many considerations to keep in mind. 

Some of the common mistakes to avoid which signing on a web host are;

  • Testing web hosts is not uncommon, it is the right way to know whether they are valuable. However, testing on your website that is primarily bringing in the traffic could be unwise, especially if you are using a free service. Therefore, not registering with a different party can be colossal.
  • Another mistake is trusting too easily without knowing the host for too long. Therefore, not partnering with one that has a long trial could be a mistake. The longer the trial period on offer is, the more reliable the host is going to be.
  • Taking on a web host is a huge commitment, so you have to be sure that you are in the good. Not doing your due diligence before the commitment is not the right way, comparing the pricing and features along with checking if they have blacklisted IPs.
  • Not tracking your hosting uptime and speed can also be a problem. Also not checking what guarantees for uptime are provided by the hosts for the same would not be wise. If there is a lapse between the guaranteed and actual uptime, keeping a track would give you the opportunity to ask for compensation.
  • Lastly, you cannot afford to not have a backup of your site and that too regularly. You will only have the recent version of your files and assets, if you back them up.

The Bottom Line 

Every aspect of your website is important, consequently, you have to be mindful of them all. If you are not, mistakes will happen and they will cost you your site’s performance, its security and your potential customers and sales. In order to keep that from happening, you have to avoid all of the aforementioned mistakes and ensure that your website is impeccably built and maintained on all platforms. 

Nov 24 2020
Nov 24

Thanksgiving this year will be different from any we’ve ever experienced, but then again, the same could be said for pretty much every aspect of 2020.

At Promet Source, we attract talent from all over North America and the world, so we had a bit of a head start navigating remote work requirements. We were still mindful though, every day, of the many ways that Covid-19 was having an impact on our teams and our clients. 

During a normal year, we look forward to the opportunity to connect during conferences, events, and client engagements, but as was the case for all of you, we had to count on Zoom calls and technology to do a lot of the heavy lifting. 

We made a point, whenever possible to fill in the gaps, show appreciation, and exercise empathy. More so than ever before, we worked on cultivating the best that is within us, emphasizing truths such as this one: 

Doing good holds the power to transform us on the inside, and then ripple out in ever-expanding circles that positively impact the world at large.  
--Shari Arison

Little surprises and humor went a long way this year. During the height of the pandemic, we designed a t-shirt to encapsulate how we were all feeling about being stuck at home during quarantine while continuing to work remotely. The shirt simulated a concert t-shirt boasting on the front: “Promet Source World Tour - Remote Edition”. The joke, of course, is the location for every tour date listed was “HOME.” We sent this t-shirt out to our staff and what happened, as a result, was quite unexpected.
 

Promet 2020 t-shirt

Promet's 2020 Company t-shirt to commemorate remote working during the pandemic and resulting quarantine.

Promet team Zoom photo

Our team members who received their shirts started taking selfies of themselves and Slacking them to the greater team. So we called a quick Zoom meeting and snapped a screenshot of our North American team to suffice for our pandemic team picture during a time we couldn't get together for an actual group photo. 

Promet Philipeans team

Before we knew it, our worldwide teams started taking pictures of themselves at their desks and in scenic locations and created a new image of them and sent it to our headquarters located in Chicago to share with the rest of Promet.

Something that started out as a generic company t-shirt sent smiles across the world and back during a time when it was most needed to bring teams together and unite everyone during trying times.

As we plan for a Thanksgiving holiday that’s likely to have a lot of empty seats, our commitment to each other and to you is that we will continue to do good, stay connected, and practice the power of gratitude.

A happy and healthy Thanksgiving to you, from all of us at Promet Source


 

Nov 24 2020
Nov 24

Do you know the version number of the browser you’re using? What about the operating system version you’re using? Chances are, you have no idea what the current version you’re using of any major software is. And that’s the way it should be.

Tips for upgrading to Drupal 9

  • Make sure your version of Drupal is up-to-date.

  • Use Upgrade Status to see if your website is ready for upgrading

  • If you have custom code, use Drupal Rector to identify code that needs to be updated

Throughout the software industry, there is a movement to more frequent, easier, updates. The reason behind more frequent updates is that everyone tends to keep software up to date and more secure, the easier and more frequent those updates come. Soon, you may not know the major or minor version of your website software, just that it is up-to-date and secure, which is the ultimate goal of any update, upgrade or version release.

What version of Drupal am I running?

Chances are if you’re using Drupal, you are using version 7 or 8. In June 2020, version 9 of Drupal was released and the last minor version of Drupal 8 was released. Both version 8 and 9 contain the same features and code. The only difference is that Drupal 9, or D9 as it is referred to in the industry, removed deprecated code and updated third-party dependencies.

(Source: Drupal.org - How to prepare for Drupal 9)

The image above shows the timeline for Drupal 8 and its version releases since 2019. The upgrade cycle in version 8 for minor releases was established to be a single release roughly twice a year. Now that Drupal 9 has been released, there will be an end-date for support for Drupal 8, but that is not scheduled until November 2, 2021. In fact, the upgrade from 8 to 9 is so painless, version 10 will be released in 2022, likely to even less fanfare, as it will also be the same as the most recent version 9.

Time to upgrade? Let our Drupal experts help!Upgrading between all minor versions of Drupal, including the jump to version 9 is advised, but is a much simpler process than version upgrades have been in the past. See what Drupal.org has to say about it here. However, if your website was recently created or released since 2016, it’s likely that you’re on Drupal 8, and the upgrade should be extremely straightforward and relatively painless.

If you find yourself on version 7 of Drupal, you can absolutely upgrade straight to D9 and skip D8 altogether. The rebuild would likely take the form of an entirely new website, but the benefits of going right to D9 are two-fold: avoiding end of life issues for D8 in 2022 and jumping on a platform that will enable to you go headless, adopt the best media, personalization, translation, and content creation tool that open source has to offer.

Why migrate to Drupal 9?

Running end-of-life platforms come with a set of problems that over time, will end up costing your company time and money. When official support for D7 runs out in 2022 (the same time as D8), security updates, bug fixes and creation of new modules for those versions will also go away. This opens your system to being more vulnerable to cyber attacks, potential downtime and a lack of up-to-date features that your customers would expect from your web presence.

Jumping right into a new build with D9, you benefit from having the long-term official support from the Drupal community including security releases that help protect your website from various vulnerabilities. D9 also removes outdated code and uses the new version of PHP, which is important in terms of security.

Other reasons to upgrade to D9, from Drupal.org:

  • Easiest upgrade in a decade, and a commitment to easy upgrades in the future. Never replatform again.
  • Continuous innovation, cutting-edge new features, reaching new digital channels while strengthening our foundation in content management.
  • Dramatically easier tools, intuitive solutions that empower business users to take advantage of the power of Drupal.

Currently, we are on the cusp of the first minor release of Drupal 9, which is planned before the end of the year. Most large ecosystem modules in Drupal have complete support for Drupal 9, including Drupal Commerce version 2.

Tips for Upgrading to Drupal 9

  • Make sure your version of Drupal is up-to-date.
  • Use Upgrade Status to see if your website is ready for upgrading (this module will flag modules that need to be upgraded to Drupal 9).
  • If you have custom code, you can use Drupal Rector to identify code that needs to be updated and, in many cases, can be automatically upgraded.

Still not sure that the upgrade to Drupal 9 is right for your organization? Have questions about the best way to handle upgrading your Drupal site? Our team is here to help you answer those kinds of questions. Check out our Drupal and Drupal Commerce Development page for more details on our services, or contact our experts to get started on your Drupal upgrade today.

Need more information on upgrading to Drupal 9? Contact our Drupal experts today to get your project started >

Josh has been creating websites since 2000, has been a Drupal community member since 2008, and is currently the Team Lead of the Investment Division at Acro Media. He spends most of his free time playing board games and yelling at his cat with his wife.

Nov 24 2020
Nov 24

Much has been spoken about the importance and benefits of migrating to Drupal 8. Drupal migration is the most significant part of a development workflow. We need to ensure that content gets transferred seamlessly without losing out on any critical user information and data. Check this complete guide for a successful Drupal 7 to Drupal 8 migration.  

There are several ways to migrate to Drupal 8 using various sources. We have already written about how to migrate from CSV to Drupal 8. Other sources include SQL, XML, JSON, etc. In this blog, we will be discussing about migrating to Drupal 8 using SQL as a source.

Migratiom

Why SQL?

While choosing the data source largely depends on the source of the existing data required to be migrated, some of the other common reasons for choosing SQL source for a Drupal 8 migration are:  

  • It is easy to write queries to get the required data by connecting to the database.
  • Migrating the data from one server to another will be quicker than any other method.
  • Reduces the usage of many contributed modules.
  • No need of views data export which is used for exporting views CSV data from Drupal 7 sites.
  • We will not need the Views password field which is used for migrating sensitive information (passwords in hash), since we are using DB query.
  • Migrate source CSV module is also not needed since we are using SQL source.

Let the Migration Process begin!

In this blog, we will be migrating users to a Drupal 8 site. Following are the steps we will take to migrate to Drupal 8 -
1.    Create a custom module for the migration.
2.    Reference the source database.
3.    Define the migration YML and map the identified Drupal fields.
4.    Create a source plugin for migration.
5.    Process single value, multi-value and address fields.
6.    Run migration using the drush command line tool.

Step 1: Create a custom module for the Drupal 8 migration.

First, let’s create a custom module as you create in Drupal 8. Check this detailed blog for creating custom modules in Drupal 8. Here we are creating a module called “company employee migrate”. The module structure is as follows:

custom module

company_employee_migrate.info.yml : Consists of basic information regarding the module and its dependencies.

company_employee_migrate.install : This will be used for writing PHP scripts that should trigger while installing and uninstalling the module. In our case, we are deleting the migration configuration when the module is uninstalled. See the below screenshot for the script.

Source database

company_employee_migrate.module : This will be used for defining the general hooks for the site. These are the initial things needed for the module. We will be explaining the remaining in the next steps.

Step 2: Reference the source database 

Next, we need to set up the source database from where we are extracting the data. Update the settings.php file for your Drupal site by moving to webroot -> sites -> default - > settings.php. 

Add the new database connection below the default connection as shown in the below screenshot. “migrate” is key for the source database. 

Drupal Module

Step 3: Define the migration YML and map the Drupal fields.

Now, we need to identify the fields which we want to migrate and map those fields in the migration yml. In this example we are migrating User Id, User Name, Password, Email, Status, Created Timestamp, First Name, Last Name, Job Role, Mailing Address etc.

After the identification of fields, we need to define the migration at migrate_plus.migration.company_employee.yml. Now let’s have a closer look at migration yml and their mappings.
 

Migration YML and Map

id: Unique id for the migration yml.

label: Display name for the migration.

migration_group: Migration group name.

source:  Annotation Name of the migration source plugin. This will be defined in the @MigrateSource annotation in src/Plugin/migrate/source/CompanyEmployee.php.

destination: Name of migration destination plugin. In this case, it's entity:user since we are migrating user entity.

process: In process, we will be mapping the Drupal fields with the source fields. The left-side values are field machine names and the right-side values are the field names which we pass from the source plugin.

migration_dependencies: This is an optional key. This will be used only if there is any dependency on other migrations.

Step 4: Create a source plugin for migration

Migration source plugin is the heart of the SQL migration. Below is the detailed explanation for the source plugin. 

  • The source plugin can be created at src/Plugin/migrate/source/CompanyEmployee.php 
  • The namespace will be Drupal\company_employee_migrate\Plugin\migrate\source.
  • The @MigrateSource annotations include the source plugin id that we map in the migration definition.
  • Here we are extending the Abstract SqlBase class provided by the core migrate module.

See the below screenshot for reference.

source plugin for migration

The source plugin must implement the following three methods –

query() : This will return the source fields data by connecting to the source database. See the below screenshot which will return the field data where the user id is greater than 0 and user mail is ending with “@phyins.com”.

source plugin for migration


fields() : This method will return the available fields in the source. Below, I have added the code snippet for the list of available fields along with the baseFields().

basefields

getIds() : This method will return a unique ID for the source row. The below code will return a user ID of type integer since uid will be unique for each user.
 

Drupal Module

Apart from these above-mentioned methods we also have:

prepareRow() : This method will be called once for each row. We are loading the data here from different tables and processes according to the requirement. Any property we create using $row->setSourceProperty will be available in the process step. We will be using the Drupal 8 DB query to get the data in prepareRow().

baseFields() : This will contain an array of basic fields from “users_field_data” that can be used by the query() method. Find the code in the below image.

drupal 8 migrate

Step 5: Process single value, multi-value and address fields.

In Drupal, we have different types of fields and processing some fields can get a little tricky for developers while migrating content. I have added the code snippets for some fields below:

Single value fields : These fields include text fields, boolean fields, email, etc. Find the code snippet below for getting a single value field; here the field_first_name can be set as below.

Process single value


Multi Value fields: These fields include user roles, job roles, multi value select fields, checkboxes, etc. For a multi value field we need to return an associative array. Find below the code snippet for the “roles” field.

Migration


Address Fields: Migrating the address field provided by the address module will be little different from migrating other fields. We need to preprocess the queried data into an associative array with the proper keys as shown below for field_mailing_address.

Migration


Now all set to run the migration by installing the company_employee_migrate module in the Drupal 8 site.

Step 6: Run the migration using drush command line tool

Finally, we are ready for our SQL migration. To run the migration, we need to install drush (if you are not already using it).

List of useful drush commands for Drupal migration:

drush migrate-status : This will return the status of migration with details.

migrtion using drush

drush migrate-import migration_id : This will import the data from source to the site.

drush migration

drush migrate-reset-status migration_id : If the execution of the script has stopped or paused, the migration status will display as “Importing”. This command will reset the migration status to “Idle” so that we can proceed with the migration import.

drush migration

drush migrate-rollback migration_id : This will be used for rolling back to its previous state.

drush migration
Nov 24 2020
Nov 24

(Available as freelancer)

Joris Snoek

Business Consultant
/ Drupal Developer

Last months we had more than 300 people testing the alpha-3 version of OpenLucius: a social productivity platform -build into a Drupal distro. We interviewed them and soon came to the conclusion that the base layouts needed big improvements. It was received as 'mhew..', we agreed. So we went to work and released alpha-4 today. We implemented a complete new base theme from scratch: clean, lean, fast and Bootstrap 4 based. Goal is to leave all the room for custom branding and other design needs.

Below you'll find some screenshots and short explanation of the alpha-4 version, I intentionally kept the screens quite low resolution: it's best to experience the real deal in the live test environment, or go to the project page on drupal.org and install it yourself.

Below you'll find some screenshots and short explanation of the alpha-4 version, I intentionally kept the screens quite low resolution: it's best to experience the real deal / try it for yourself.

So yeah, we revamped everything:

  1. Overall layout and navigation;
  2. Activity streams;
  3. Social posts;
  4. Messages;
  5. Document management (files and folders);
  6. Likes;
  7. Comments;
  8. Chatrooms (where are they?).

1. Overall layout and navigation

  • All markup was rebuild from the ground up, based on Bootstrap 4. This way we got rid of all the cluttery html and designs, it's now as Bootstrap-native as humanly possible.
  • The main navigation went from the left sidebar to the top of the page, this also leaves room for extensions / extra menu items and new goodies in the future.
  • The basic color scheme is now minimalistic: black and white with primary and secondary 'action colors'.
  • Also, the platform is much more responsive now: easy of use on mobile devices improved beyond compare.

  1. Main navigation, including a 'Groups' drop-down (with activity badges);
  2. Quick add button;
  3. User area;
  4. Group name / page title;
  5. Sections within groups (including activity badges);
  6. Action buttons.

2. Activity streams

  • This is the default homepage, where you'll find all activity from all your groups in one stream;
  • All activity is now clearly bundled per day, per group. Instead of one big blurred stream of everything together as in previous versions the case was;
  • In the right sidebar you'll find all your groups, including activity badges;
  • (Every group now has a dedicated activity stream);
  • (Every user now has a dedicated activity stream).

3. Social posts

  • Clean new design, with great new image experience;
  • Comments and likes (AJAX based) build into freshly styled components.

4. Messages

  • The new screens for message lists -and message detail pages;
  • With comments and likes;
  • And likes on comments :) ;
  • The message as well as the comments can be enriched with file attachments.

5. Document management (files and folders)

  • The layout for 'Docs & Files' is also completely rebuild;
  • It's now based on DataTables, that brings all goodies like: instant search, sorting and a paging.
  • The table is responsive now;
  • It's still possible to manage folders to organise your files.

6. Likes

  • Inline with other UI improvements, the like area is now also nice and clean.

7. Comments

  • Also inline with other UI improvements, the comment area including attachments is improved.

8. What about the chatrooms / channels per group?

Well, in previous versions this was integrated in the activity streams. That wasn't received very good, so we split them up. In this alpha-4 release the activity stream is fully working and restyled as you can see above.

The realtime chat will be back in a future release within a dedicated section for it. For now it's 1 step back, a next release it will be 2 steps forward for the chatrooms / channels. The activity streams already made that 2 steps forward because of this approach.

Wrap up

Alright, there you have it for a major design update for OpenLucius: a social productivity platform -built into a Drupal distro. You can download and install it yourself open source: check out the project page on Drupal.org. If you'd like to try it this instant, go to the product page and hit the 'try now' button.

Always looking forward to new feedback.

Nov 24 2020
Nov 24

Maybe you have banged your head against the wall trying to figure out why if you add an Ajax button (or any other element) inside a table, it just doesn’t work. I have.

drupal ajax form tables

I was building a complex form that needed to render some table rows, nicely formatted and have some operations buttons to the right to edit/delete the rows. All this via Ajax. You know when you estimate things and you go like: yeah, simple form, we render table, add buttons, Ajax, replace with text fields, Save, done. Right? Wrong. You render the table, put the Ajax buttons in the last column and BAM! Hours later, you wanna punch someone. When Drupal renders tables, it doesn’t process the #ajax definition if you pass an element in the column data key.

Well, here’s a neat little trick to help you out in this case: #pre_render.

What we can do is add our buttons outside the table and use a #pre_render callback to move the buttons back into the table where we want them. Because by that time, the form is processed and Drupal doesn’t really care where the buttons are. As long as everything else is correct as well.

So here’s what a very basic buildForm() method can look like. Remember, it doesn’t do anything just ensures we can get our Ajax callback triggered.

 /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['#id'] = $form['#id'] ?? Html::getId('test');

    $rows = [];

    $row = [
      $this->t('Row label'),
      []
    ];

    $rows[] = $row;

    $form['buttons'] = [
      [
        '#type' => 'button',
        '#value' => $this->t('Edit'),
        '#submit' => [
          [$this, 'editButtonSubmit'],
        ],
        '#executes_submit_callback' => TRUE,
        // Hardcoding for now as we have only one row.
        '#edit' => 0,
        '#ajax' => [
          'callback' => [$this, 'ajaxCallback'],
          'wrapper' => $form['#id'],
        ]
      ],
    ];

    $form['table'] = [
      '#type' => 'table',
      '#rows' => $rows,
      '#header' => [$this->t('Title'), $this->t('Operations')],
    ];

    $form['#pre_render'] = [
      [$this, 'preRenderForm'],
    ];

    return $form;
  }

First, we ensure we have an ID on our form so we have something to replace via Ajax. Then we create a row with two columns: a simple text and an empty column (where the button should go, in fact).

Outside the form, we create a series of buttons (1 in this case), matching literally the rows in the table. So here I hardcode the crap out of things but you’d probably loop the same loop as for generating the rows. On top of the regular Ajax shizzle, we also add a submit callback just so we can properly capture which button gets pressed. This is so that on form rebuild, we can do something with it (up to you to do that).

Finally, we have the table element and a general form pre_render callback defined.

And here are the two referenced callback methods:

 /**
   * {@inheritdoc}
   */
  public function editButtonSubmit(array &$form, FormStateInterface $form_state) {
    $element = $form_state->getTriggeringElement();
    $form_state->set('edit', $element['#edit']);
    $form_state->setRebuild();
  }

  /**
   * Prerender callback for the form.
   *
   * Moves the buttons into the table.
   *
   * @param array $form
   *   The form.
   *
   * @return array
   *   The form.
   */
  public function preRenderForm(array $form) {
    foreach (Element::children($form['buttons']) as $child) {
      // The 1 is the cell number where we insert the button.
      $form['table']['#rows'][$child][1] = [
        'data' => $form['buttons'][$child]
      ];
      unset($form['buttons'][$child]);
    }

    return $form;
  }

First we have the submit callback which stores information about the button that was pressed, as well as rebuilds the form. This allows us to manipulate the form however we want in the rebuild. And second, we have a very simple loop of the declared buttons which we move into the table. And that’s it.

Of course, our form should implement Drupal\Core\Security\TrustedCallbackInterface and its method trustedCallbacks() so Drupal knows our pre_render callback is secure:

 /**
   * {@inheritdoc}
   */
  public static function trustedCallbacks() {
    return ['preRenderForm'];
  }

And that’s pretty much it. Now the Edit button will trigger the Ajax, rebuild the form and you are able to repurpose the row to show something else: perhaps a textfield to change the hardcoded label we did? Up to you.

Hope this helps.

Nov 24 2020
Nov 24

Acquia Engage is over, but its great lessons and content live on. You can access all of the Engage session recordings on the event site. Here are our top six can’t-miss sessions to catch up on if you couldn’t make it to Engage:

General Session #1

Hear from the leadership of Acquia about all of the new product announcements, features, and strategies for the Acquia Open DXP today and what is planned for the next year. If you are invested in Acquia or are looking to move to the Acquia platform, this session will help you skate to where the puck will be.

Exciting stuff!

General Session #3: King Arthur Baking Company

It was great to see our client and everyone’s favorite flour brand King Arthur featured in General Session #3 (around minute 39). Hear brand web and marketing leads talk about how they worked with Acquia and Third and Grove to fuel 2,000% increase in sales.

Black Girls Code

You need to hear the remarkable story of Black Girls Code directly from founder Kimberly Bryant in General Session #4 (starting around minute 36). It’s an inspiring story, and it makes us quite proud that our partner, Acquia, supports this program.

We also have serious eyeglass envy over Kimberly’s lenses.

DXP Track Session: Leveraging Drupal 8 and Acquia to Boost B2B Lead Generation and Marketing Velocity

Ahem, we might be a little biased, but this session by our CEO and Acquia Engage award winner CloudHealth Tech by VMware has a bunch of actionable insights to turn your site into a B2b lead generation machine. No good deed goes unpunished in B2B demand generation: Next quarter will always require more.

It’s a must-watch for any marketing leader at a B2B tech company.

COVID Has Redefined Scale. Learn How to Adapt, and Prepare for What’s Next

Learn from a real Acquia Drupal organization user at scale: Charles Schawb. Terrific lessons for dealing with scale and developer agility during the global COVID-19 pandemic.

Building it Better: Best Practices for Site Studio Architecture

On the workshop front, we wanted to call out this session on Site Studio (formerly called Acquia Cohesion). Site Studio is a major differentiator for using Drupal on Acquia, and a leading platform in the rise of the low-code CMS page editors. Attend this workshop to learn best practices on using Site Studio.

Nov 24 2020
Nov 24

I have several local development environments in my machine. I would like to use HTTPS on them without much hustle. That is why I decided to create my own custom Certificate Authority to simplify the process.

First I want to disclose that I am not an expert in this matter. I did some research and stapled together several articles that I found. My main source of inspiration was this article.

Please note that I am fully aware there are local development toolkits that may handle this for me. I have never found a need to virtualize and or containerize my local development environment. I like running things in my metal because they run faster, I have more control over them, and debugging them is simpler. If I ever need to work on several sites in parallel requiring conflicting setups in my local, I will likely jump into that wagon. However, this article is not about that.

I did the whole process in three steps:

  1. I created the Certificate Authority (CA). This is a one time setup.
  2. I installed the CA into Linux and Firefox. This is also a one time setup.
  3. I generated one certificate per site, signed by the CA, and added it to nginx. You need to do this once per site.

Creating a custom Certificate Authority

Since I have a directory in my local with all my sites I decided to put all the files in a directory there: /home/e0ipso/Sites/certs. Please change the path to the one you use. Run the commands in that directory.

To create the CA you need to type:

1
openssl genrsa -des3 -out myCA.key 2048

During the execution of that command you will need to provide a passphrase. I recommend using your password manager to generate and store such password. You will need the password in the last step.

After you generate the key, generate the root certificate.

1
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem

Openssl will prompt you with questions. You can leave the questions on their defaults, provide silly answers, or give it truthful values. It doesn’t matter.

Making your system accept the new authority

If you use Linux you need to install the ca-certificate on the system. This is useful if you are not using Firefox to make the HTTP requests. Think of curl, Insomnia (which is amazing), a PHP program, etc. I learned how to do this in this post.

1
2
3
4
5
6
# First transform the .pem into a .crt.
openssl crl2pkcs7 -nocrl -certfile myCA.pem | openssl pkcs7 -print_certs -out myCA.crt
# Copy the ca-certificate where the OS expects it.
sudo cp myCA.crt /usr/local/share/ca-certificates
# Update the certificates to pick it up.
sudo update-ca-certificates

In addition to that you will need to install it into Firefox. Yes, even if you installed it system wide.

Firefox preferences pane

In the firefox preferences access the Privacy and Security section. After that under the Certificates heading select View Certificates…. This will open a dialog with an Authorities tab. There you will be able to import myCA.pem.

Creating the site certificate

This step is necessary every time you need to enable SSL for a new site in your local environment. This is why I wanted to simplify the process as much as possible, because next time I need to do this I will not remember how to do it. This is the shell script (you can also download it).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/sh

if [ "$#" -ne 1 ]
then
  echo "Usage: Must supply a domain"
  exit 1
fi

DOMAIN=$1

openssl genrsa -out ./certs/$DOMAIN.key 2048
openssl req -new -key ./certs/$DOMAIN.key -out ./certs/$DOMAIN.csr

cat > ./certs/$DOMAIN.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
EOF

openssl x509 -req -in ./certs/$DOMAIN.csr -CA ./certs/myCA.pem -CAkey ./certs/myCA.key -CAcreateserial \
-out ./certs/$DOMAIN.crt -days 825 -sha256 -extfile ./certs/$DOMAIN.ext

I have this script in /home/e0ipso/Sites/generate-certificate.sh, one level above /home/e0ipso/Sites/certs/myCA.key. Then I can run it with the domain name I want the certificate for:

1
./generate-certificate.sh local.contrib.com

Once again this will prompt you with some questions, you can skip them if you like. At some point it will require the password we saved in our password manager earlier (hopefully not a napkin). This will generate the local.contrib.com.key and local.contrib.com.crt files. The last step is to add it you your local webserver.

I use nginx, so I add:

1
2
3
4
5
6
server {
    # ...
    listen 443 ssl;
    ssl_certificate /home/e0ipso/Sites/certs/local.contrib.com.crt;
    ssl_certificate_key /home/e0ipso/Sites/certs/local.contrib.com.key;
    # ...

If you are curious, this is the nginx configuration file I use for my local development in a Drupal project.

Photo by Mauro Sbicego on Unsplash

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