Mar 25 2020
Mar 25

The joy of e-commerce is that there are myriads of products that differ in particular details so every customer can find what suits them perfectly.

As an online store owner, you will just need to help them a little — and this will be a win-win! Flexible product management is one of the reasons to choose Drupal Commerce, an e-commerce platform for Drupal websites. Today, we will discuss one of its useful opportunities — the option to set up product attributes in your Drupal online store.

A glimpse at how to increase online sales

In the ocean of recommendations to boost onlines sales on your e-commerce website, you will find anything from providing the smooth and simple checkout process to using cross-selling techniques or offering a choice of payment options. However, every recommendation is focused on usability and engagement.

That’s why, one of the useful ways to increase sales is to provide your customers with a convenient choice between your product variations. Read on to find out how it works on Drupal Commerce websites.

What are product attributes?

Products in online store often come in more than one option. They may differ in size, color, fabric, shape, volume, or whatever other characteristics that customers might need to select when shopping.

These characteristics are called product attributes. Their unique combination makes a product variation in Drupal (e.g. “I love Drudesk” T-shirt of size M and white color). The product is actually the same, but it differs by attributes.

The benefits of using product attributes

Here is what makes the use of product attributes so convenient — especially in the updated and improved system of Drupal Commerce 2.

  • You easily add different product variations within the same product page by specifying their attribute values. No need to create separate products.
  • You easily track items in stock and otherwise manage your products thanks to the fact that every combination of attributes (product variation) is assigned a separate SKU — a machine-readable ID.
  • Your online store customers can easily pick the right product variation according to the desired attributes and add it to cart, with no need to go to a page with a different product.

Setting up product attributes in Drupal

If your e-commerce websits sells products that differ in some characteristics (or this is in your plans), read on. Here is how the process of setting up the Drupal product attributes looks.

Adding a new product attribute

Find the Product Attributes link on your Drupal Commerce store dashboard. Then you click “Add product attribute,” give it a name (e.g. “Dress color”).

Adding product attributes in Drupal Commerce

Adding attribute values

Your online store customers will need to be choosing between some color options (“White,” “Blue,” “Green,” etc.). As soon as you save the form, you will be able to add these as your attribute values. Add them one by one, clicking “Add value” every time. You can reorder them by dragging. If your store is a multilingual Drupal website, don’t forget to check “Enable attribute value translation.”

Adding attribute values in Drupal Commerce

Configuring how the attributes will look

On the same form, configure how it will look on the add-to-cart form (“Select list,” “Radio buttons,” or “Rendered attribute”). For the standard setup, the “Select list” or “Radio buttons” will be ok. Be sure to save the whole thing.

If you want to give your e-commerce website admins and customers a fuller view — for example, with the actual color swatch instead of color names, you should choose the “Rendered attribute” instead and install an additional contrib module such as the Color Field. It will allow you to set the color name and its HEX value when editing the attribute.

Drupal Color Field module

You can add fields to your attribute on the Product Attributes page by clicking “Manage fields” on the attribute editing menu. In this case, it will be the “Color” field.

Managing product attribute fields in Drupal Commerce

When the field is added, you can configure how it should look to your online store admins and your customers on the “Manage form display” and the “Manage display” tabs respectively. You can set the display as “Color swatch” and brush up the shape and size of the colors that will appear on your website.

Attaching the attribute to the product variation type

Attributes need to be added to a particular product variation type that requires them. Product variation types are another important Drupal Commerce concept. You can create or edit them on the Product Variation Type page and also add your attributes to them. Or you can use the “Default” variation type. After that, you will be able to add product variations by specifying their color.

Adding product attributes to product variation types in Drupal Commerce

Let our team help you with the Drupal Commerce setup

The above is just the basic setup. We know from our experience that Drupal Commerce is a powerful platform with plenty of capabilities and plenty of possible settings for your online store. They are able to facilitate the e-commerce website management and boost online sales.

You can make your product selection work exactly as you need. For example, the image and price dynamically without a page reload every time a user clicks on a new attribute — using the decoupled Drupal Commerce approach or a decoupled shopping cart and benefiting from the capabilities of JavaScript frameworks to boost online sales.

Let our Drupal support and maintenance team guide you through the options and help you create the smooth setup depending on your requirements. What cannot be configured by built-in features, we will cover by the use of contributed modules or write custom ones specifically for you. Of course, we can also build an online store from scratch.

Use the best CMS features to boost online sales!

Mar 18 2020
Mar 18

Automatic website updates are incredibly convenient, whatever CMS your site is built on. Unfortunately, the automation of Drupal website updates used to be impossible. But now we have great news for all Drupal 7 and Drupal 8 website owners — automatic website updates are already there! Read on to discover more details.

The most desired Drupal feature: benefits of auto updates

When asked what they would like to see in Drupal, website owners and users have always mentioned automatic updates. In the long-term competition between Drupal and WordPress, the latter had this trump card in its sleeve — even despite certain risks with unattended processes.

Every Drupal website owner or admin often sees a frustrating warning on the dashboard that a new release is available. However, they do not touch it because they know the procedure can be cumbersome. What if all could be done automatically? This would give website owners the unquestionable benefits such as:

  • being able to easily keep up with the Drupal release cycles on their own
  • never having to worry about security updates
  • never having to deal with Composer that is a bit cumbersome for users

The automation was really needed in order to make Drupal more user-friendly, safer thanks to timely security updates, and more competitive on the market. They have become one of the strategic initiatives highlighted by Drupal’s creator Dries Buytaert in the “State of Drupal” presentation. The Automatic Updates initiative now celebrates great success that we can now describe!

Drupal automatic updates as one of strategic priorities

How Drupal automatic updates work

There is a new contributed module that is headed for inclusion into the Drupal core — Automatic Updates. It is meant to auto-update Drupal simply and as cleanly as possible. When you see the update steps, you will notice they really have plenty of measures for cleanliness and safety. Let’s now take a closer look at how it performs both Drupal 7 and Drupal 8 automatic updates.

The key automatic Drupal update steps:

Displaying the security release announcements

The new module will let you know several days in advance about the security announcements (PSAs) for the core and contributed modules. The respective notices will be posted on the admin dashboard. This will be implemented as a PSA.json feed from drupal.org.

Making sure your website is ready for the update

Next, the module checks whether your website is ready for a smooth update and there is nothing to mess with it. These checks are made through the Drupal Cron runs. Upon the check, it displays errors explaining what necessarily needs to be fixed or just warnings. Here are some examples of issues that can be listed:

  • the site uses a read-only filesystem
  • ongoing database updates
  • insufficient disk space

Performing the in-place Drupal update

Here comes the key step in the automatic update process — the actual update. The module downloads a ZIP archive from drupal.org. For security reasons, it is hashed and signed. With the help of the Libsodium library, its signature is verified to make sure this is the official drupal.org archive. Next, all files meant for the update are backed up. Finally, they are overwritten with the new ones using the PHP copy function.

Do automatic website updates need your interference?

The release announcements and website readiness checks are all automatic. The actual update part depends on your choice:

  • you can manually start the update on the module configuration page
  • or you can check the box on the same page that allows automatic updates run with the help of Cron

The current state of automatic Drupal updates

Right now, automatic updates are in active development and their amazing team keeps adding more features. The module is currently focused on automatic Drupal core updates according to security releases. Adding other types of updates, the support for contributed modules, and better work with Composer are in its roadmap.

In order to be added to the Drupal core, the module needs to get a feature called the A/B front-end controller. It will be able to swap between the two codebases and go back to the backed-up one in case something goes wrong during the automatic update, which will add even more safety and reliability to the process.

Apply for any help will automatic website updates

If you are impressed with the news and are ready to try the automatic website update feature, we encourage you to contact our Drupal support and maintenance team.

  • We will help you install and configure the Automatic Updates module and resolve all the update-hampering issues it may discover on your website.
  • As an option, we can inform you when the module gets into the Drupal core and update your website so it is there already.

Enjoy smooth, easy, and safe automatic Drupal updates!

Feb 28 2020
Feb 28
  • Core Modules: These modules are installed in all the Drupal installation packages; you can say that they are the basic (core) modules necessary for the site designing task, like handling the accounts of the users, providing menus for navigation.
  • Contributed Modules: This module can be downloaded from the official Drupal.org site.
  • Custom Modules: Custom modules are pretty self-explanatory – they’re explicitly coded for individual projects.

So here, we try to list out some of the modules from a Pandora of modules that can be used on the go for your web development, in a hassle-free way.

Read More - Move on to Drupal 8, Be Ready for Drupal 9!

Feb 26 2020
Feb 26

New days mean new rules on the web. Having social media integration buttons on your website today is one of the crucial web design tips to ensure your business success.

If you have a website on Drupal, this post will be of special interest to you. We will discuss how social media integration works in Drupal 8, what modules are available, and how to integrate social media on your website using one of them — the Easy Social Drupal module.

The importance of integrating social media

If you want to fully reap the benefits of social media marketing, you need to rely on these small website elements, which can be your huge business boosters:

  • content sharing buttons
  • buttons linking to your social accounts
  • tweetable lines in your content
  • feeds
  • counters

and more.

They help you engage more customers across multiple channels, increase your campaign visibility, improve your communication with your audience, boost your SEO, raise your brand awareness, make your site user-friendly, and much more. Social integration buttons are also indispensable elements of the contact block on every modern website.

Social media integration in Drupal 8

Any kind of third-party integration in Drupal 8 is easy to set up thanks to its API-first principle. Social integration is no exception — on the contrary, it is one of the easiest integrations to perform. This is thanks to helpful contributed modules.

Useful Drupal 8 modules for social media integration

Some of these Drupal 8 modules to integrate social media on your website are cross-network — they help you add blocks of buttons, feeds, links, counters, or social login options for multiple networks at once:

Useful Drupal 8 modules for social media integrationUseful Drupal 8 modules for social media integration

There also are Drupal 8 modules specifically tailored to the integration with particular networks (sharing content, adding feeds, and more):

Useful Drupal 8 modules for social media integrationUseful Drupal 8 modules for social media integration

Social integration via the Easy Social module in Drupal 8

The Easy Social module justifies its name — it allows you to set up your integration buttons with no fuss and no need to add external JavaScript libraries or other modules. The classic set of the most popular buttons is available both as a Drupal block or as a Views field.

Enabling the Easy Social module

When installed, the module offers an additional demonstration module — the Easy Social Example. You can choose whether to enable the latter.

Enabling the Easy Social module in Drupal 8

Enabling the social widgets

At the module’s configuration page (Configuration — Web services — Easy Social) you will see the default widgets that can be enabled:

  • Twitter
  • Facebook
  • LinkedIn
  • Pinterest
  • Google+ (included, but has reached its end-of-life)

There is also the option to load JavaScript asynchronously, which is recommended for performance purposes.

Enabling the social widgets in the Easy Social Drupal 8 module

Configuring the social widgets

Each widget has a tab where it can be configured individually. You can play with their color schemes, fonts, size, screen names, layout styles, types of actions (sharing or sending), the option to show the profile pictures of friends who liked this content, and so on. The available settings vary from widget to widget.

Configuring the social widgets in the Easy Social Drupal 8 module

Adding the social share block

Now that the widgets are selected, we will place our sharing buttons block on the website just like we would do with any other Drupal block. By going to Structure — Place block, we will choose the region to place it in. Next to the necessary region, we will click “Place block” and find the “Easy Social” block on the available list. Another click on the “Place block” and, finally, on the “Save” button is all that's left.

Adding the social share block in Drupal 8

When configuring the block, we can select the content types and pages to display it on, and user roles to display it to. The block title can be renamed to anything we would want users to see when they are supposed to share your content.

Configuring the social share block in Drupal 8

OK, that’s it! So we now see the sharing buttons below our Drupal content items:

Content node with social share buttons in Drupal 8

Let our team do the smooth integration for you!

The above example of how to integrate social media on your website was just a very simple one. Any integrations you wish are possible with the help of our Drupal development team — with any networks and featuring any settings.

If there is no contributed Drupal module that does the integration job, our team can write you a custom one. We can also apply design tweaks in accordance with your branding.

Integrate your website with social media easily — contact us!

Feb 24 2020
Feb 24

24 . February . 2020

Views and Facets modules give you some advanced sorting options for your catalogue of products when building your ecommerce store. But sometimes all those algorithmic options are not what the client wants, they want to custom sort their merchandizing in the way that best promotes their products.

One of our clients has exactly that same need! They want to showcase their bikinis like they would do on their brick and mortar stores, where a professional visual merchandiser would sort the clothing rack in an appealing way that, being pleasant to the customers eye, would bring out the best of each piece.

As everything Drupal-related, there are several ways of accomplishing the same objective. We choose the one that was easier and most intuitive to our client, but also the one that was easier for us to replicate on other projects. The modules that appeared in our radar were DraggableViews, Sortableviews and Weight. We settled on Weight — the oldest of them all (created in 2005!) — mainly because it allows us to add a new weight field to the product entity, and the drag and drop experience was simpler and better when compared to Sortableviews. Initially, DraggableViews was our first choice because it worked so well on Drupal 7, however, on Drupal 8 the module is still very buggy. Both the Sortableviews and the Weight modules are compatible with Search API (which is very important when building Drupal Commerce stores), because they both store weights directly on entity fields, enabling Search API to have them indexed. Sortableviews has the additional advantage of allowing you to choose any integer field to store weights, where Weight only works with its own field type.

We want to change this, into this:

Let’s build that custom sort view!

1. Add a Weight field to the product entity.

2. Create a new view of Products and add the required fields.

3. Save the View and open its page.

As you can see you will have a drag and drop interface to reorder the rows. When settling on the intended order, you should click the Save button and all your products will have its weight field updated to the new value!

And, Voilà!

I hope you enjoyed this small tutorial.

By José Fernandes

Feb 12 2020
Feb 12

If your website has plenty of media files (PDF presentations, price-lists, product images, etc.), you know how cumbersome it can be to replace them. Special attention in file replacement needs to be paid to SEO — because, as every SEO expert knows, every detail matters there.

Luckily, your Drupal 8 website offers more and more ways of easy media management that will also allow you to stay in line with the best practices of SEO.

Discover how to replace Drupal media files easily, with no fuss or extra manual efforts, and with your SEO rankings preserved. This is possible thanks to the new Drupal module — the Media Entity File Replace.

When do you need to Drupal replace media files?

The content never stays unchanged — it needs to keep up with the new business circumstances. Media files are not exception. For example, you may need to:

  • update a PDF presentation for your company/products/services
  • change your price-list
  • update your how-to checklist
  • upload new product images with better quality than before
  • make changes to your corporate video

and many other types of content.

What is the problem with the standard file replacement?

The standard procedure includes removing the old file and uploading another one. When it is replaced, your file gets a different name and path. Drupal appends a number to the end of the new one (_0, _1, etc.), instead of overwriting the original.

Standard file replacement in Drupal 8

File replacement becomes an especially tedious process when the file is used in multiple places throughout your website. This means additional expenses on your or your staff’s manual work. A special point of concern here is the impact on SEO. Read on to find out more about the impact of file replacing on your SEO.

How does media file replacement influence SEO?

File names play a part in your SEO rankings. Human-readable names enriched with keywords and written through a dash is a great way to tell Google what your image is about (in addition to the ALT tag), and this benefits your SEO.

Changing your file name and path can lead to a certain loss in SEO rankings because Google treats the newly uploaded files as new, and needs to recrawl, reprocess, and reindex them. This can take a long time during which it will show old and irrelevant content.

And, of course, if your files are used in content throughout your website and you change them but forget to re-upload them everywhere, they will be unavailable to your users. File path changes have the potential to cause broken links, which is one of the most annoying things both for search engines and users.

Never lose any SERP position to your competitors. Use helpful tools to replace files easily and without losing SEO.

How the Media Entity File Replace module can help

The new Media Entity File Replace module for Drupal 8 offers a smart and SEO-friendly way to replace Drupal media files. The module replaces the source files in Drupal media entities that have a file-based field. It does so by overwriting the old file with the new one. What’s even more important, the name and path are preserved in the process.

The Media Entity File Replace works with Media entities in Drupal 8. If you use the Media system to manage your media files, this module will suit you.

Note: To use the Media module, consider updating your Drupal website to the latest version where it has been greatly improved — our Drupal support team can do it for you.

Installing the Media Entity File Replace module

The module is installed like any other. It depends on a bunch of core modules: Media, File, Field, Image, User, and System.

Installing the Media Entity File Replace module in Drupal 8

Configuring the File Replace widget

The module comes with the File Replace widget, which you need to enable in the media types for which you want your files to be overwritable. Let us remind you: Drupal 8 has 5 default media types: Audio, Document, Image, Remote video, and Video, while others can be created to your liking.

To enable the File Replace widget, we need to go to Structure — Media types — {Our media type} — Manage form display. In our example, we work with the Document Media type.

Let’s drag the Replace File widget to the enabled ones. The perfect place is just below the File field.

Configuring the File Replace widget in Drupal 8

Replacing your Drupal media files

Let’s create a new document entity in Media — Add media — Document. We then upload an “Our services” PDF to it.

Creating a Drupal document Media entityDrupal media file path

The PDF is now saved in our Media Library (Content — Media) where we can go and edit the entity in order to replace the PDF.

Instead of the usual Remove button, we now see the Replace button. If the “Overwrite original filename” is checked, the original name will be kept and the content will be replaced.

Media Entity File Replace Drupal 8 module in action

We click “Choose file” and upload a new one — “Updated services.”

Replacing files with the Media Entity File Replace module

After saving, we see that the filename in this media entity is the same as before.

Drupal document file path

However, the content of the source file available by the same path has been rewritten. It now shows our updated services.

Media file replaced with its path inchanged in Drupal 8

This PDF can be used as an attachment in your content. You just need to add a Media field in your content type, and then you can easily fetch media there from the Media Library. Visit our “Media handling in Drupal 8” to learn how media can serve as building blocks for content.

Adding documents from Media Library to content

In this example, we added a “Document” Media field to the Basic page, and then created a content page with our PDF attached to it.

Content entity with a document Media field

Wherever else we add the file throughout your website, it is going to be rewritten automatically after a replacement, with no need to reupload.

While using the Media Entity File Replace module, special attention needs also to be paid to caching so your users are able to see the updated content sooner.

Entrust your media setup to our Drupal team

The Media capabilities and the ecosystem of Media Library management modules in Drupal 8 keep growing at amazing strides. It offers you more every day for managing your media effortlessly, with joy, and with no SEO losses.

Ask our Drupal support & maintenance team to configure the ideal media management processes on your Drupal 8 website!

Jan 23 2020
Jan 23

Forums are a great way to create a community of people. This is where they can discuss issues, share skills, or talk about your company’s products. Forums are able to keep your visitors on your website. But this is not all — let’s discuss more benefits of forums, see some best forum website examples, and review how to create a forum on your Drupal 8 website.

Benefits of creating a forum for your website

Having a forum, also known as a discussion board or bulletin board, on your site can be useful in many ways:

  • Understanding your customers: A forum is a place to get to know your customers, which is great for market research. Discover their feedback, issues, questions, and needs about your products or services. You can also study their user personas, improve your products, and brush up your marketing strategy.
  • Helping your customers: A forum enables you to resolve your customers’ issues in the form of official customer support or an unofficial advice board.
  • Increasing website traffic: Forums help you engage and retain your website users. They keep coming back to your site, especially if they need an answer to their particular question. The average session duration, just like the visit rate, increase thanks to the activity.
  • Boosting your SEO: If you create a forum on your website, you boost your SEO. Nested discussions built around more general topics and leading to more specific ones work great with search engines. Google also loves exact questions — if a user asks a question that is addressed on your board, the chances are high they will arrive on your website. In addition, you will automatically have fresh content being created.
  • Inspiring purchases: Discussions of products or services are the first stage of the buyer’s journey. When your prospective customer sees other customers’ comments, photos, videos and more, it may bring them a step closer to the buying decision.
  • Monetizing the forum: An additional benefit you can have from creating a discussion board is monetizing it. There are several ways to monetize a discussion board including subscription fees, advertising, donations from users, affiliate programs, sponsorship and more.

Famous forum website examples

There are plenty of famous examples out there to see what a good discussion board looks like. Let’s look at a few.

Reddit

Reddit — famous forum website example

Ubuntu forums

Ubuntu forums — famous forum website example

Stack Overflow

Stack Overflow — famous forum website example

Boards

Boards — famous forum website example

MoneySavingExpert

MoneySavingExpert — famous forum website example

Ars Technica

Ars Technica — famous forum website example

How to create a forum on your Drupal 8 website

If you have a website created with Drupal (or plan to get one), there is great news for you — the forum functionality is already built-in!

The core Forum module

There is a core module responsible for creating forums. It is turned off by default and needs to be enabled for those who want it.

the core Forum module in Drupal 8

Creating categories and subcategories

You decide what hierarchy structure your discussion board will have. In “Structure,” there now is a “Forums” tab that enables you to add forums and containers. Containers can be used to group related forums together.

The module also provides a ready-made forum “General discussion” that we can rename or delete.

Adding a forum in Drupal 8

Your discussions can have categories and subcategories, aka parent and child forums. For example, let’s create a forum called “Drudesk services.” It is going to be the main one and, in its settings, the “Parent” is set as “root.”

Creating forum categories in Drupal 8

Let’s add a couple of subforums (e.g. “Drupal development” and “Drupal support.” The procedure is the same (the “Add forum” button). The only difference is that we need to set the “Parent” as “Drudesk services.” Next, we can add more detailed subcategories to our subcategories by setting the right “Parent” every time.

Forum categories and subcategories in Drupal 8

We can see what it looks like on the default page created by Drupal by checking the address /forum, or simply by clicking the right category link. However, we see that the number of topics and posts is null because we still need to create topics.

Simple forum page in Drupal 8

Adding forum topics

Forum topics will be posted like any other content nodes. The module has created a content type “Forum topics” for this. For the user’s convenience, there is also the “Add the forum topic” button on the Forums page.

When creating a topic, we need to select which category or subcategory we want to post it.

Adding forum topics in Drupal 8

The answers to each topic will be posted like comments to each node. In our example, after we have posted one topic and one comment (or reply), we see that the count of topics has changed to 1 and the post count to 2.

A forum topic in Drupal 8Simple forum with posts in Drupal 8

Forum participant permissions

Now it’s time to determine who can view, add, edit, and delete the topic and comments. A common option is allowing authenticated Drupal users in “People — Permissions.” Alternatively, it’s possible to create a separate Drupal role if you want to make a membership forum for subscribers only.

Check out our video tutorial about how to create a forum on your Drupal 8 website.

[embedded content]

Entrust our Drupal experts with creating your board

Inspired to create a forum on your Drupal website? The above example has been a rough sketch. Your discussion board will look exactly as you wish.

If you want to change the style or position on your website, add a feed with the latest discussions on other pages, or explore the many other options, our Drupal development experts can configure it out. Contact us and enjoy an attractive and user-friendly forum!

Jan 20 2020
Jan 20

In this tutorial I will explain how I accomplished taking a listing of nodes that came from a View and created a Parallax effect using the Bootstrap theme from Drupal 8.

The code in this tutorial can be found on GitLab. 

To use the code in the repos, you can:

  1. Clone the repos locally
  2. Run composer install from the root folder
  3. Run drush config:import -y 

I would like to refer to this article which explains how to Add Parallax Blocks to Drupal 8 With ScrollMagic. I got my ideas and most of the code from there.

You will need to have Drupal 8 installed with Views and a Bootstrap subtheme set up.

For this tutorial, I am using a simple Page content type that I created with 3 fields: Title, Body and Background Image.

You should then create a View that lists this Page content type. I am listing the Body field and Background Image field in my example. I am keeping my Page content type and View very simple for explanation purposes. But you can set up more complex Views and content types as you wish. You just need at least an image field (or you can place a background image to an existing content type field via CSS as well).

Step #1 - Configure the Bootstrap theme

Because Parallax effects are usually full width, you should turn on the Fluid container option in the Bootstrap theme menu.

  • Enter your subtheme Boothstrap theme settings.
  • Under General >> Container check the Fluid container boxFluid checkbox

Step #2 - Set up your Content Type and Views.

Here is my Page content type with 3 fields: Title (not show in in screenshot), Body and Background image

Page content type fields

Here is my View. It's a pretty much standard View which just lists the Page content type and creates a page out of it. I am using the image field here as the background image for the Parallax. You can also use another field (text or whatever) and set a CSS background as the image.

View listing page content types

Now create some Page content and go to the View page to see the listing of your content.

Step #3 - Style the View using CSS

Here is my CSS:

.view-homepage {

  .views-row { text-align: center; position: relative; overflow: hidden; height: 500px; }

  .views-field-field-background-image { position: absolute; width: 100%; height: 140%; }

  .views-field-body {

    position: relative; top: 50%;
    -webkit-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    transform: translateY(-50%);
    color: #fff;
  }
}

Step #4 - Get the ScrollMagic files

Go to Github and download/extract library.

Now go to your theme folder and create a folder called /js/ and move these files into the folder

  • animation.gsap.min.js
  • ScrollMagic.min.js
  • TweenMax.min.js
  • and also manually create a blank parallax.js

You now need to tell the theme to load the js libraries. To do that, open your_theme/your_theme.libraries.yml:

global-styling:
  css:
    theme:
     css/style.css: {}

  js:
    js/ScrollMagic.min.js: {}
    js/animation.gsap.min.js: {}
    js/TweenMax.min.js: {}
    js/parallax.js: {}
  dependencies:
    - core/drupal
    - core/jquery

Step #5 Add the Parallax JS code to parallax.js

(function ($) {
    'use strict';
    Drupal.behaviors.myBehavior = {
        attach: function (context, settings) {

            var controller = new ScrollMagic.Controller();

            $('.views-row').each(function (index) {

                var $bg = $(this).find('.views-field-field-background-image');
                var $content = $(this).find('.views-field-body');

                var tl = new TimelineMax();
                tl
                    .from($bg, 2, {y: '-40%', ease: Power0.easeNone}, 0)
                    .from($content, 1, {autoAlpha: 0, ease: Power0.easeNone}, 0.4)
                ;

                var scene = new ScrollMagic.Scene({
                    triggerElement: this,
                    triggerHook: 1,
                    duration: "100%"
                })
                .setTween(tl)
                .addTo(controller);
            });
        }
    }
}(jQuery));

Make sure the images you are using are big enough for the max width you want to display.

You should now have a nice parallax scrolling effect for each node in the View list.

Parallax example

Jan 11 2020
Jan 11

The large business world knows no compromise. Your website should stand out from the competitors and keep up with all the business requirements. And not just keep up — a site can move your business forward by offering advanced digital experiences to customers.

Whether the website is capable of doing this, largely depends on the choice of the platform you build it with. In this post, we discuss why it’s worth choosing Drupal for large business website development.

How large business website development can benefit from Drupal

If you have an idea to create a large business website, it may have some specific needs. For example, this site needs to be content-heavy, complex in architecture, high in traffic, unique and robust in functionality, and so on. See how Drupal, an enterprise-level CMS and CMF in one, can help you build a big website for your big idea.

Exceptional and unlimited functionality

Provide your large business website users with any functionality desired. Drupal empowers developers with creating even the most complex and specific site features.

It has 44+ thousand free contributed modules for various spheres of your site’s work — content display, search, security, third-party integration, SEO, access control, e-commerce functionality, etc. And, of course, any custom features can be created by a development team to match your business scenarios exactly.

The Tesla’s site (Drupal + Adobe Experience Manager):

Tesla website

Modern technology inside

Efficient development workflows, clean code, and fast performance of your large website also depend on what is “under the hood” of a CMS. Drupal 8 uses OOP (object-oriented programming), the Twig theming engine, the modern PHP 7, Symfony components, and more.

Your brand’s multichannel reach

Your large business website can be part of a whole multichannel ecosystem for your brand. It can share its content to iOS or Android applications, JavaScript-based web apps, various Internet-of-Things devices, and so on. The “Create Once, Publish Everywhere” (COPE) method will speed up your content management.

Make use of the API-first principle and the exceptional support of third-party integration in Drupal 8! There also are plenty of add-on modules, helpful development kits for third-party frameworks, etc.

Going global with a multilingual site

Large business website development can also let you go global. Having a multilingual site means multiplying your audience and profits as well.

D8 has strong multilingual features that are among its “visiting cards.” To help you create a big website that speaks different languages, it offers an extremely easy setup, a hundred languages supported out-of-the-box, flexible options as to what website elements should be translatable, RTL support, and much more.

Multisite support

If you want to create a complex website, here is another idea that might be interesting. Large organizations and businesses often need more than one site — they need a collection of related sites that are easy to manage.

Drupal offers a multisite feature that allows you to run multiple sites from the same Drupal installation. They are created, managed, and updated from one place.

Powerful search even on complex sites

Large and complex sites especially need ways for users to quickly find things. Drupal allows you to create the most advanced search features.

They include faceted search, alternate spellings, content suggestions, result highlighting, search in attachments, multilingual and multisite search, and much more. This is thanks to such modules as Search API, Search API Solr Search, Elasticsearch Connector, Facets, etc.

The General Electric’s site:

General Electric site on Drupal

Easy content workflows

If your large business website is content-heavy, Drupal can save your editorial team’s time a lot. Drupal 8 has a user-friendly CKEditor for content publishing. The Media system provides for the easy media handling in Drupal 8 and enriching the content with various videos, audios, remote videos, etc.

There are strong built-in capabilities to have flexible editorial workflows thanks to the Content Moderation and Workflows modules. Another novelty for large websites is the Workspaces module that allows you to quickly deploy tons of content from a stage to a live environment.

Outrunning your competitors in SEO

Let your large business website be better found through search engines thanks to such a SEO-friendly CMS as Drupal.

It has plenty of built-in and add-on modules for SEO that take care of its every aspect. For example, SEO-friendly URLs (including automatic, pattern-based URL creation on large sites), keyword optimization, meta tags, XML sitemap, broken link fixing, and much more.

A high level of security

Cybercriminals never sleep and are always trying to find vulnerabilities in sites that they could exploit for malicious purposes. A large business website faces more risks than smaller ones because it has more to lose.

When it comes to security, Drupal has a very good reputation. It stands against the most critical security vulnerabilities of the web. This is thanks to the vigilant security team, strong coding standards, a watchful community, a flexible system of site roles and permissions, and more. Here is why governments trust Drupal across many countries of the world.

The Pfizer’s site:

Pfizer site on Drupal

High website speed

Creating a big website that loads fast is easy with Drupal. D8 uses flexible approaches to caching and has robust built-in caching modules. One of them is the BigPipe that loads the unchanged parts of the page instantly to not keep your users waiting.

There are also plenty of add-on performance modules to speed up Drupal sites. Finally, it’s a hot trend to combine Drupal 8 with JavaScript frameworks like React, Vue, or Angular to reach exceptional speed and interactivity.

Hire experts to create a large business website

We have outlined the key reasons why choose Drupal for a big website. Let’s discuss more details in a conversation. Entrust your large business website development to our professional Drupal team and let your large site help your large business flourish!

Jan 03 2020
Jan 03

Ok, the problem is clear:

  • Your composer based Drupal site put code base to the /web folder
  • You are using a shared hosting which maps your primary domain to /public_html, and you can't change that

Now your users will have to browse your site as http://example.com/web . And it is not cool.

So how to serve your site from the subfolder /public_html/web but removing the /web suffix so it becomes transparent to users?

Here are the steps, as I learned from this thread on Drupal.org

1. Open your settings.php file and add the following code:

if ( isset($GLOBALS['request']) && '/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME') ) {
    $GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

2. Create a .htaccess file on the /public_html folder with:

<IfModule mod_rewrite.c>
RewriteEngine on
# Redirect to the subdirectory because that's where Drupal is installed
RewriteRule (.*) web/$1 [L]
</IfModule>

3. Update .htaccess under /public_html/web folder

Uncomment the line RewriteBase and set it to:

RewriteBase /web

4. Clear the cache and run update.php

Your site should work by browsing http://example.com now (without the /web suffix). Your menu items may still have the /web part, but it will be gone after some hard refresh.

5. (Bonus) If you want to redirect http/https and wwww/non-www:

On the .htaccess file under /public_html/web, please add those lines between the <IfModule mod_rewrite.c> tag:

This is to redirect non-https + www to https + non-www:

  RewriteCond %{HTTPS} off [OR]
  RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
  RewriteRule (.*) https://example.com/$1 [L,R=301]

And this is to redirect non-https + non-www to https + www"

  RewriteCond %{HTTPS} off [OR]
  RewriteCond %{HTTP_HOST} !^www\. [NC]
  RewriteCond %{HTTP_HOST} ^(.*)$  [NC]
  RewriteRule (.*) https://www.%1/$1 [R=301,L]

You can see those examples on Htaccess guide.

Dec 07 2019
Dec 07

Services Module is a standardized solution for building API's so that external clients can communicate with Drupal. It provide Drupal plug-ins that allow others to create their own authentication mechanisms, request formats, and response formats. Some of the existing users of this module may have faced the service registration issues while implementing it, I have worked out some solutions for various registry issues you might come across.

Technical details of the tools used.

  • Drupal 7.41
  • Module: Service [ Version:- 7.x-3.13 ]
  • Chrome Extension: Advanced REST client - 4.12.8-stable.0

Register Users through service API module:

CASE 1 – Using default registration parameters

{

"name" : "testuser",

"mail" : "[email protected]",

"pass" :{ "pass1" : "123456", "pass2" : "123456" }

}

This should get you going!

CASE 2 – Custom registration parameters

{

"name" : "testuser",

"mail" : "[email protected]",

"pass" : { "pass1" : "123456", "pass2" : "123456" }, "field_voucher_number" : { "und": [{ "value": "1234" }] }

}

you need to add one more line of code mentioned here in the bold.

If the response is 200 OK then, everything's alright and user has registered successfully.

EXCEPTION No. 1.

If you are getting 500 internal server error as shown in the screen-shot below, you need to follow below mentioned procedure to make user register.

Services Module - Registration 

First of all check error report logs. If you have same error as shown in below screen-shot then you need to apply patch #6.

Link to the patch - https://www.drupal.org/node/2543010

Services Module - Registration 

After that again try to register. if you haven't implemented captcha you will get a response as shown in the screen-shot below.

Services Module - Registration 

Captcha Exception

If you have captcha validations on registration page then you will get error named “406: Not Acceptable: What code is in the image? field is required.” as shown in the screen-shot below

Services Module - Registration 

Solution

To rectify this issue we will need to apply one form alter hook which will be applied only when registration will be performed through API.

function MYMODULE_form_alter(&$form, &$form_state, $form_id) {

if($form_id == 'user_register_form'){

if (arg(0) == 'api') {

// You might have to update this line depending on the path to your API unset($form['captcha']);

}

}

}

After this user registration will work properly for the given fields as shown in the screen-shot below.

Services Module - Registration 

Custom field with text

If you are adding new custom field involving “text”, you can use below mentioned method.

{ "name" : "testuser", "mail" : "[email protected]", "pass" : { "pass1" : "123456", "pass2" : "123456" }, "field_test_text" : { "und": [{ "value": "1234" }] } }

Also there's one more thing that you need to be careful about:

Suppose you have added “field_test” as per shown in the image and have added its list value for radio button list are as described below:

a|A

b|B

c|C

and add field value to store while registration is

{ "name" : "testuser", "mail" : "[email protected]", "pass" : { "pass1" : "123456", "pass2" : "123456" }, "field_test" : { "und": "a" } }

this will throw an error as per shown in the below image.

Services Module - Registration 

Now, let's try something else!

Lets create new field “field_test2” and set its field type and widget as shown in the image, I have set its value as described below:

1|a

2|b

3|c

now add field parameter in the registration api:

{ "name" : "testuser", "mail" : "[email protected]", "pass" : { "pass1" : "123456", "pass2" : "123456" }, "field_test2" : { "und": 1 } }

this works perfectly as shown in the below image

Field type “List(text)” generates some issue to store values and it is not added in the error logs either.

So, basically if you are using “String” to store its value, it will throw an error, so instead use “integer” value and it will work perfectly!

Difference between “field_test” and “field_test2” is shown in the below image

Services Module - Registration 

Stay connected for more technical blogs. You can even drop us your any Drupal Web Development queries, we provide optimal solutions.

Dec 07 2019
Dec 07
<?php
function MYMODULE_drush_command() {
  $items  = array();
  $items['nodecreate'] = array(
    'callback'    => 'custom_drush_create_node',
    'description' => dt('Triggers a node-save'),
    'aliases' => array('nc'),
    'arguments'   => array(
      'title'     => "Title of node",
    ),
    'options' => array(
      'repeat' => 'Number nodes to create.',
    ),
    'examples' => array(
      'drush nc error' => 'Prints error as node title is blank.',
      'drush nc Test --repeat=5' => 'Creates 5 nodes with title Test.',
    ),
  );
  return $items;
}

Running the Drush help command for our own command drush help nc will list some useful information about this command (arguments, options, description, aliases, examples etc)

Callback Function

As we have written callback function, Drush expects a function to be declared called drush_create_node(). This default naming structure starts with drush followed by the name of the command all connected with underscores.

function MYMODULE_create_node($title) {
  $repeat = drush_get_option('repeat', 1);
  for ($i=0; $i < $repeat; $i++) {
    $node = new stdClass();
    $node->type = "page";
    $node->title = $title;
    $node->language = LANGUAGE_NONE;
    $node->uid = 1;
    $node = node_submit($node);
    node_save($node);
  }
  drupal_set_message(t('Created ' . $repeat . ' node with title ' . $title));
}

Now clear the drush cache: drush cc drush

And run command: drush nc OR drush nodecreate

Arguments and options

-> Arguments are mandatory whereas options are not.

-> Arguments are passed as function parameters (in order) while options are retrieved in the callback using a special helper function (drush_get_option).

We declared 1 argument (called title) and one option called repeat.

-> The argument type will be the first string that gets written after the command name in the terminal (drush nodecreate or drush nc).

-> The option will be an integer value that gets assigned to the --repeat flag in the command.

Ex. drush nc Test --repeat=2

This will create 5 nodes, with title “Test”

User input

Let’s make it so that if a user doesn’t pass an argument, we ask them what argument they’d like to pass and use the value they provide interactively.

This goes to the top of the command callback function before checking whether the correct argument was passed.

// Check for existence of argument
if (!$title) {
  $options = array(
    'Test' => t('Test'),
    '0' => t('Error'),
  );
  $title = drush_choice($options, t('Please choose a option.'));
}
…
  1. Everything happens only if the user has not passed an argument.
  2. We create an array of key-value pairs that will represent the choices we give the user. The array keys represent the machine name of the choice while the values, the human readable name.
  3. We pass this array along side a question string to the drush_choice() function that will return the machine name of the choice the user makes. And that becomes our new $title variable (the argument).

If the title is not set or error is returned, we can add code to print error in terminal.

…
  if(!$title || $title='error') {
    drupal_set_message(t('Error! No title set.'));
  }
…

Full Code will look something like this:

<?php
 
function MYMODULE_drush_command() {
  $items  = array();
  $items['nodecreate'] = array(
    'callback'    => 'custom_drush_create_node',
    'description' => dt('Triggers a node-save'),
    'aliases' => array('nc'),
    'arguments'   => array(
      'title'     => "Title of node",
    ),
    'options' => array(
      'repeat' => 'Number nodes to create.',
    ),
    'examples' => array(
      'drush nc error' => 'Prints error as node title is blank.',
      'drush nc Test --repeat=5' => 'Creates 5 nodes with title Test.',
    ),
  );
  return $items;
}
 
function MYMODULE_create_node($title) {
  if (!$title) {
    $options = array(
      'Test' => t('Test'),
      '0' => t('Error'),
    );
    $title = drush_choice($options, t('Please choose a option.'));
  }
  if(!$title || $title='error') {
    drupal_set_message(t('Error! No title set.'));
  }
  else {
    $repeat = drush_get_option('repeat', 1);
    for ($i=0; $i < $repeat; $i++) {
      $node = new stdClass();
      $node->type = "page";
      $node->title = $title;
      $node->language = LANGUAGE_NONE;
      $node->uid = 1;
      $node = node_submit($node);
      node_save($node);
    }
    drupal_set_message(t('Created ' . $repeat . ' node with title ' . $title));
  }
}

Feel free to drop your any queries/concern related to this blog. For Drupal Web Development we are always ready to help :) Stay tuned! 

Dec 04 2019
Dec 04

In the first days of December, the great news makes our hearts feel warm! We are happy to see the sparkling fresh release — and to show all our readers what’s new in Drupal 8.8.0.

This is, in fact, the last minor release of Drupal 8 before another big day — June 3, 2020. This is when Drupal 8.9 and Drupal 9 should arrive together. All D8 sites that are regularly updated and free from deprecated code will be instantly ready for Drupal 9.

However, an even bigger reason why you should update to Drupal 8.8.0 right now is its absolutely irresistible features. It looks like the Drupal creators have put their hearts into this release. Our Drupal support team is ready to help you with the update — now let’s take a closer look at all the secrets of D8.8.0.

What's new in Drupal 8.8

Stable Media Library & integration with CKEditor

One of the most anticipated new features of D8.8 is the Media Library and WYSIWYG integration. Content editors will be especially happy with the new handy Media Library icon that can be easily added to the active CKEditor toolbar. This allows you to use the images, videos, and other multimedia assets that you keep in the Media Library and embed them into content with a few clicks.

And, as the community is focused on website accessibility for all users, the whole media embedding process has been made available via the keyboard only!

Other improvements include Media Library’s integration with the Content Moderation module, its better support for multilingual sites, UI updates, and more. After all the amazing work, the Media Library is officially stable in Drupal 8.8 core and absolutely ready to be used on live sites. Hurray!

Media Library in Drupal 8.8Media Library and CKEditor integration in Drupal 8.8Media Library stable in Drupal 8.8

The new and user-friendly admin theme Claro

The Drupal admin UI needed a good brush-up, decided the community. No sooner said than done, and a fresh, clean, concise, and modern experimental theme has arrived in the D8.8 core.

The new Drupal admin theme Claro is responsive and has a big focus on readability and accessibility. It will make the admin dashboard more convenient and enjoyable to work with, and Drupal itself more competitive among CMSs. This is another reason why you should update to Drupal 8.8 (you will definitely want to!).

According to Dries Buytaert’s feedback in his “State of Drupal” presentation, Drupal has never looked better or been more accessible as it is with the new Claro theme.

New experimental admin theme Claro

Native Composer support in Drupal core

Updating and installing Drupal has become easier than ever. Composer, the famous PHP dependency management tool, helps developers do it with one command, and takes care of the right third-party libraries.

Thanks to the Composer Support in Core Initiative, Composer is now officially supported by Drupal out-of-box. There is also an easy transition path for sites that have not used Composer before.

The helpful Help Topics experimental module

In order to make Drupal easier for all users, a new experimental module called Help Topics has just arrived in Drupal core. Module and theme developers can now provide helpful instructions in Twig files. They will be listed on every website’s admin/help page.

The topics can be single or grouped, according to the complexity and the number of tasks needed to work with a particular module. An additional contributed module should allow adding help topics from the browser.

New Help Topic experimental module in Drupal 8.8New Help Topics experimental module in Drupal 8.8

Great JSON:API module improvements

One of the greatest sensations in Drupal 8.7 was the arrival of the new JSON:API module in the core even without any experimental phase. It created an even better API-first future for Drupal websites and enhanced their capabilities to share data with third-party apps.

In Drupal 8.8, JSON:APi module has received a number of improvements to make it work more efficiently. This is related to resource normalization, omission links, HTTP error codes, security hardening, and more.

The ecosystem of contributed modules also grows — for example, there is the new JSON:API Explorer module that is an interactive web app to help developers explore their JSON:API server.

Final end of PHP 5.5 and 5.6 support

While the PHP 5.5 and PHP 5.6 were officially removed in D8.7, websites were still allowed to perform security updates.

D8.8 finally puts an end to this. These actions will fail unless servers are updated at least to PHP 7.0.8. However, PHP 7.0 and 7.1 will no longer receive security support from the PHP team, so it’s better to choose the newer PHP 7.2 or 7.3. You can contact our support experts with checking your PHP version and performing the update.

Significant Workspaces module improvements

We have all admired two new and amazing core modules that handle content workflows — Content Moderation (D8.3) and Workspaces (D8.6).

  • Content Moderation in a duet with Workflows provides convenient content workflows out-of-box, as well as allowing you to create custom ones.
Content Moderation in Drupal 8
  • Workspaces allows editors to quickly deploy tons of content from the “Stage” to the “Live” environment.
Experimental module Workpaces in Drupal 8

However, the two could not work together on the same website. This is solved in the new Drupal 8.8 release! In addition, the creators of the Workspaces module have rolled out the interesting capability to create hierarchical workspaces (i.e. sub-workspaces and parent workspaces).

Hierarchical workspaces in Drupal 8.8

More Drupal 9 readiness with the new core versioning

Indeed, Drupal 9 is coming! Developers are getting their modules and themes ready by cleaning up the deprecated code.

Now they can declare their project compatibility with multiple Drupal versions — D8 and D9. They just need to add the new core version requirement key to the project’s info.yml file.

This new core versioning system landed yet in 8.7.7 this September. It allows great precision so compatibility with minor and patch versions can also be declared.

Goodbye to jQuery UI

jQuery UI, the famous collection of widgets and effects for user interfaces, has reached its end-of-life. Most of its libraries are deprecated from Drupal 8.8 core and will be removed in the 9th version. “The big drop” is moving in the direction of using pure JavaScript in this area.

The modules and themes that depend on the jQuery UI libraries can find them in the replacement contributed projects, but it is better to find a more future-proof solution.

Multiple dependency updates

To support newer PHP and achieve better website efficiency, D8.8 uses new versions of multiple third-party dependencies. Among them:

  • D8.8 requires version 6.3 or newer of the HTTP client library for PHP — Guzzle.
  • It no longer supports version 4 of the PHPUnit unit testing framework. D8.8 can support PHPUnit 6.5+ and PHPUnit 7, while using version 6 by default.
  • Components of the Symfony framework have been updated to 3.4.5.
  • Drupal 8’s default content editor, CKEditor, has been updated to 4.13.0.
  • The Diactoros PHP package is up to 1.8.7.
  • The Twig template engine is up to 1.42.3.

Changes to browser support

Websites can only work well with modern browsers that support CSS and JavaScript. Some browsers are getting outdated. So the new Drupal 8.8 is changing the browser support policy.

It supports the latest release of the two latest supported major versions of these desktop and mobile browsers:

  • Firefox
  • Google Chrome
  • Opera
  • Safari
  • Microsoft Edge
  • Safari for iOS

As well as the latest supported release of the latest major version of these desktop and mobile browsers:

  • DFirefox ESR
  • Internet Explorer
  • Chrome for iOS
  • Chrome for Android
  • Samsung Internet
  • UC Browser
  • Opera Mini

And more

D8.8 also features improvements to configuration management, multilingual migrations, the work of Views, and so on. Developers should pay special attention to considerable changes to path alias handling and a critical note about using the latest version of the Pathauto module — more about this can be found in the technical release notes.

Update to Drupal 8.8 with us!

This has been a brief overview of what’s new in Drupal 8.8 released today. All of these and many more improvements can arrive on your website right now if you update to Drupal 8.8

All you need is to contact the Drudesk Drupal support team — we are ready to:

  • perform a smooth update to Drupal 8.8
  • configure the new modules
  • help you prepare for Drupal 9
  • update your PHP

Upgrade from Drupal 7 to Drupal 8

You see Drupal 8 offers more and more amazing features. To use them all, upgrade from Drupal 7 to Drupal 8 now if you haven't yet. And, of course, this, will be your best preparation for Drupal 9!

Stay up-to-date with the latest and greatest!

Nov 27 2019
Nov 27

Emerging from test-driven development practices, Behavior-Driven Development is an Agile software development process that supports collaboration among developers and non-technical and business contributors to help formulate and standardize a concrete understanding of how the application should operate.

In our latest webinar, we demonstrated how to use Cypress (and the respective integration module for Drupal) for Behaviour Driven Development (BDD) to elevate the quality of your code and project.
The webinar covered a brief introduction to BDD and testing in general, an introduction to Cypress, how to install and use the Cypress module for Drupal, adding E2E tests to a custom module, and testing a full Drupal project. 

If you’re curious about how Behavior-Driven Development and Test-Driven Development with Drupal & Cypress.io could improve your next project, watch the full Webinar below.

[embedded content]

Nov 18 2019
Nov 18

21 . November . 2019

The Portuguese use the payment instruments offered by the Multibanco network in their online purchases for various reasons. The Multibanco reference, the MB Net cards, and, recently, the MB Way service, are simple, convenient and safe instruments.

The familiarity of the Portuguese with the Multibanco network, together with demographic characteristics of the population, lead to a natural preference for these methods over other options such as Paypal or credit card.

The online shops that operate for the Portuguese market are aware of this preference of the consumers, providing a Multibanco reference in their payment options. Recently, several of these brands have also making the MB Way option available.

As it had happened in the past, BloomIdea contributed to the Drupal community and for the e-commerce in Portugal developing a module for Drupal Commerce 2.x that allows to automatically generate Multibanco references on this e-commerce platform. This module for Drupal 8 uses Ifthenpay and it will soon include the MB Way payment method.

Integrate the Ifthenpay Commerce module into your online store.

If you don't already have an online store and need expert advice contact our team.

By Cláudia Freitas.

Nov 18 2019
Nov 18

21 . November . 2019

Hosted by the Associação Drupal Portugal, Drupal Day Lisboa is the biggest even of the year for the Drupal community in Portugal... and we’ll be there!

Bloomidea in DrupalDay Lisboa a 22 november 2019.

In 2019 and with a free entry (by ticket reservation), the event takes place November 22nd, Friday, between 9.45 a.m. and 5.30 p.m., at Diamond by Bold (Avenida Dom João II).

The goal of Drupal Day Lisboa is to share experiences and raise awareness of one of the most amazing open source content management tools, used by institutions and programmers all over the world. We couldn’t miss the chance!

We take pride in frequently contributing to the growth and evolution of the Drupal community, and the event of November 22nd will include a workshop by our CTO, José Fernandes. Over two hours, José will address the subject of the development of an e-commerce using Drupal Commerce 2.0. To participate in the workshop, those who are interested just need to have previous knowledge concerning PHP7.x, Composer, Mysql&Apache or Lando.

The workshop is scheduled to 2 p.m. and will last two hours. See you there?

The complete Schedule can be found here.

Nov 10 2019
Nov 10

19 . November . 2019

It’s no secret we’re big supporters of Drupal, a development modular framework with an integrated content management system. However, we’ve noticed that there are several doubts about Drupal’s stability and security, given that it’s an open-source system, which makes some people apprehensive.

As such, we decided that it was time to put an end to your doubts and clarify, once and for all, the security (or lack thereof) of Drupal’s framework. By the end of this article you should know everything you need about this- and if you still have any doubts, you can always contact us for further clarification.

Open-source software is a software whose source code- the original code written by the developers what will then be compiled to be readable by computer, thus making it software- is publicly available.

The big difference of open-source software is that anyone can contribute to its development, unlike closed-source software, in which the original team of programmers is the one who handles all the software’s development. Therefore, open-source software is more interactive, being constantly under development by several users.

With that in mind, it’s understandable that you have some suspicions of this type of software: if anyone can modify the code, does this not mean that there are greater risks?

The truth is that open-source software is as safe- sometimes even safer- than other types of software. There are several reasons for this, but one of the main ones is the fact that the community developed around the creation of this software is actively searching for vulnerabilities in its code and correcting them. This means that while “closed” software sometimes has uncorrected vulnerabilities that the responsible team, due to lapse or lack of time, doesn’t correct, open-source software is constantly being viewed, reviewed and analyzed by several people. More importantly, as vulnerabilities are exposed, they are more easily detected by the community and quickly corrected.

On the other hand, to believe that a closed system is inherently safer simply because the code isn’t visible is a common mistake, known as “security through obscurity”- is the same that assuming that having hidden money under the mattress, where no one knows where it is, makes it more protected than in a bank, where, even though several people know where it is, there are several security measures so that only authorized people can access it. What really brings security to any system are its protections, so the source code being publicly available doesn’t make it any less protected.

We’ve established that open-source software is safe, but what about Drupal specifically? Since we realize that the security measures are what really makes the difference, which one does Drupal put into practice?

In order to ensure platform security, Drupal has a security team that constantly works with the community to detect and correct any vulnerabilities in the framework, as well as providing extensive documentation on how to create a secure Drupal website. As a rule, this team focuses on supporting the latest version of Drupal and the previous version- currently version 8.x and 7.x, respectively-, releasing and announcing new security updates almost monthly.

In addition to vulnerabilities in the infrastructure itself, this team also focuses on detecting and helps to correct security breaches in the various modules and projects. All this continuous work results in Drupal meeting the requirements of the Open Web Application Security Project (OWASP), a nonprofit organization focused on improving the software’s security, that created a guide of the top 10 security risks, to help guide the development of online software security.

With this, Drupal has several working measures to ensure that not only the framework, but all the projects as well, are always properly protected against attacks- in fact, 90% of the security flaws detected in Drupal websites are due to themes or modules developed by less experienced teams in their own websites, which is why you should only trust an experienced in Drupal team to develop and update your platform.

It’s also important to note that these security updates are not automatic, that is, they must be installed manually, and sometimes they create conflicts with some outdated modules. This is another reason why you need an experienced and fully dedicated team in your project, to ensure that you’re always safe and functioning at 100%.

In addition to this continuous protection, the framework itself is structured with the user’s safety in mind, offering various features such as advanced password encryption (which can still be improved with modules developed thinking about the protection of authentication), perfected access controls, a variety of options for database encryption that allows you to meet the requirements of PCI, HIPPA and other privacy requirements, and a functionality that is installed from the root to report security flaws.

The definitive answer to this article’s title is: yes, Drupal is safe, provided that you have a team that ensures the system’s always up to date with the new implementation of Drupal’s security team, and whose custom code is professional to the point of not creating new security flaws.

If you’re still not convinced that Drupal is safe, here’s a last fact that can make you change your mind: even the White House chose Drupal, in 2009, precisely due to its safety, and many other large entities rely on it- to name a few, UNESCO, the American Red Cross, NBC, Harvard and Oxford Universities, Twitter and NBA, among many others. If it was safe enough for Barack Obama, why wouldn’t it be for you?

Nov 07 2019
Nov 07

All beautiful websites have one thing in common — a good theme. It should be not only beautiful but also mobile responsive, accessible, and ready to support modern website functionality.

This is all true of Olivero — the future main front-end theme for Drupal 9. And this future is just around the corner because Drupal 9 is coming! With it is coming the era of beautiful websites.

Why is a website theme important?

A website theme defines what the site looks like to visitors, which includes layout, styles, color schemes, typography, buttons, and much more. Beautiful themes make beautiful websites, creating visual appeal and your brand’s identity. But this is not all.

The theme’s responsibility goes beyond being beautiful. It can also greatly contribute to the smooth user’s interaction with the website, including on various mobile devices. So if beautiful website design goes hand-in-hand with the best usability practices, this eventually translates into more conversions.

The new Olivero theme in Drupal 9

The new theme’s official overviews say “Drupal 9: The Most Beautiful CMS Ever!” And you immediately know it’s true when you see Olivero.

New main front-end theme in Drupal 9 — Olivero

Olivero is a beautiful implementation of the community’s idea to create a new default front-end theme. The current default theme, Bartik, is ten years old already and was initially created for D7.

Bartik has served us as an amazing and very adaptable theme. In addition, it is mobile responsive out-of-the-box to meet D8’s mobile-first philosophy. However, Bartik’s design looks a bit outdated. So Drupal needed a new main front-end theme that would better showcase Drupal’s strength.

Olivero is expected to come in Drupal 9.1. The community keeps working on it, and anyone who wants to contribute to it is welcome.

Theme named in honor of Rachel Olivero

There is a nice tradition in Drupal to name main themes after outstanding programmers. For example, Bartik got its name after Jean Bartik who was among the original ENIAC computer creators.

The tradition goes on with Olivero — it is named after a female programmer Rachel Olivero who was an outstanding advocate of website accessibility. Sadly, Rachel passed away in 2019. To honor her, the community kept her beautiful name alive in a beautiful theme. Patient, generous, and inclusive — these were Rachel Olivero’s qualities that they wanted the theme to embody.

Key features of Olivero theme in Drupal 9

Beautiful web design, simplicity with no clutter, a professional look, accessibility, flexibility in options, responsiveness on mobile devices — the list of its virtues could go on. Let’s outline at least a few of its numerous features for websites.

WCAG AA compliance

One of the top priorities for the theme’s creators was to make Olivero compliant with Web Content Accessibility Guidelines (WCAG), so they worked with website accessibility experts. All users, including those with various impairments, should find it easy to use websites with Olivero.

Support for the latest Drupal functionality

The Olivero creators have prioritized making it supportive of the recent Drupal features for websites such as Layout Builder, media embeds, second-level navigation, and more.

A modern and bright color palette

Websites will look beautiful with Olivero’s color scheme, with a base color of bright blue. In addition to being attractive, it supports Drupal’s branding. Combinations of darker and lighter colors help provide website accessibility.

Color palette of the new Olivero theme in Drupal 9

Simple but modern forms and buttons

Forms and buttons in Olivero are user-friendly, recognizable, and accessible. Forms have a left color bar, and their labels are placed above the fields to meet website accessibility requirements. Buttons are presented in two types: primary and secondary.

Buttons in the new OIivero theme for Drupal 9Forms and buttons in the new Drupal 9's front-end theme Olivero

A convenient sidebar region

Olivero features a beautiful sidebar to the right of the website’s main content area that allows you, for example, to add related content. The region proportions allow the content area to look more prominent, while the sidebar gives it good support.

Sidebar regions in new main Drupal 9 theme Olivero

Flexible header and navigation options

Navigation options can accommodate any website’s needs. The header is able to collapse into a hamburger-button menu when scrolling, which allows the menu to be accessible on long pages. The secondary dropdown menus are also supported by Olivero.

Navigation in new main Drupal 9 theme Olivero

RTL (right-to-left) text direction support

Drupal 8 has already raised the bar of multilingual support very high. See why Drupal 8 is the best choice for multilingual websites, including those with RTL languages. It will be even better with the new theme in Drupal 9 — just take a look at the beautiful RTL implementation.

RTL support in new main Drupal 9 theme Olivero

Time for beautiful websites and other Drupal 9’s benefits!

It looks like Olivero is one of the beautiful answers to the question of what’s new in Drupal 9, coming in June 2020!

As a web agency that creates beautiful websites with great functionality and optimizes existing ones, we would like to offer you our assistance in:

  • getting ready for Drupal 9, which involves a good clean-up from deprecated code
  • moving your website to Drupal that becomes “The Most Beautiful CMS Ever!” (and it’s just a tiny part of Drupal’s strength)
  • creating a custom theme, or otherwise improving your website’s design to make it more beautiful, user-friendly, and accessible

Drop a line to our Drupal development team!

Oct 30 2019
Oct 30

Working with databases can be challenging and cumbersome. Luckily, there are useful Drupal modules that make complicated tasks easy (or even possible at all). Of course, the best way to get the results you want is to rely on Drupal development and DevOps services by Drudesk. In the meantime, we are sharing great modules for working with databases in Drupal with you.

Some challenges with databases in Drupal

When you are working with databases, you may need to:

  • store your data in a database that Drupal does not support by default (i.e. other than MySQL, PostgreSQL, and SQLite)
  • connect to multiple external databases
  • quickly back up, restore, or migrate your database between the environments
  • set up the database search

and much more.    

Modules for working with databases in Drupal

MongoDB

The MongoDB module allows you to store your Drupal data not in the “classic” SQL database but in MongoDB — a popular, document-based distributed database. 

The module offers website administrators a user-friendly interface with database logs. It provides fast database logging and easily handles external logging mechanisms (for example, Elastic Stack). 

MongoDB takes the load off your SQL database server and does not require complicated settings or coding from site admins. However, it is also a joy for developers to work with thanks to a Drupal-standard API, handy Drush and Drupal Console commands, PSR-3 implementation, detailed documentation, and much more.

MongoDB Drupal module

Drupal driver for SQL Server and SQL Azure

Here is a Drupal driver for working with the database engines of Microsoft SQL Server — a famous relational database management system. The module supports:

  • SQL Server of version 2008 and newer
  • Azure SQL of version 12 and newer

The Drupal driver module is modern in everything — including the fact that it only supports PHP7 or later versions, with older ones to be used at your own risk. The MSSQL PDO extension is compatible with Windows and Linux.

The module’s Drupal 8 version is fresh and new, with the latest update in September. The 8.2’s branch of the SQL Server driver is tested by means of the AppVeyor service.

Drupal Driver for SQL Server and SQL AzureDrupal Driver for SQL Server and SQL Azure

Oracle Driver

Another popular relational database management system, Oracle, can become the primary backend of your Drupal website thanks to the Oracle Driver Drupal module. 

The module allows you to create Drupal nodes from Oracle tables, store your website’s files in Oracle, and more. 

It should be noted that the module is minimally maintained and its Drupal 8 version is a release candidate. However, it can be a nice example of a module connecting Drupal to a particular third-party database system.

Oracle Driver Drupal module

Search API Database Search

The drupal.org website itself uses the Search API Database Search module, which is the best “promo” possible. However, please note that the module is only ready for Drupal 7.

The module provides a backend for the Search API module known as a great foundation for creating the search setup on Drupal websites. Search API Database Search uses a classic database for data indexing. 

This is a simple and cheap option for websites that are not so large and/or do not need a super-powerful search backend — for example, the Solr engine.

Views Database Connector

It can be incredibly useful to be able to pull data from external databases and display it to your users as a Drupal view. It is possible with the Views Database Connector module.

Drupal Views get full access to the external database tables that are found in your Drupal installation’s settings. To provide effective data pulling, the module needs an information_schema table for MySQL or PostgreSQL and sqlite_master for SQLite.

Thanks to this module, you get a new view type on the “Show” menu to select. All items generated by the module have a [VDC] prefix.

Views Database Connector Drupal module

Backup and Migrate

Everyone knows about the importance of regular backups. Restoring your Drupal database from a backup can become a rescue in critical situations. 

Luckily, there is the Backup and Migrate module that backups and restores databases, files, and code. The module downloads your database as a file or saves it on the server. It supports various compression types (zip, gzip, and bzip). 

It can back up all the database tables or the ones you select. Automatic scheduled backups are also supported.

Backup and Migrate Drupal moduleBackup and Migrate Drupal module

Let us help you manage your databases in Drupal

The modules described above — and others — can be helpful for working with databases in Drupal. However, this area requires a technical background from the person who performs the tasks. 

Contact our Drupal development and support team for any help in managing your databases in Drupal. If this requires add-on modules, we will select and configure them for you, or create custom modules that will match your requirements more exactly. 

We want to make sure your databases in Drupal are perfect and serve you well

Oct 28 2019
Oct 28

21 . November . 2019

InvoiceXpress is an invoicing program - certified by the Tax Authority - that allows the emission of invoices in a matter of seconds through a customer file system.

The user (in this case, the seller) enters the customer data, the items to be invoiced and the payment terms, and if the customer is already registered in the program filling becomes automatic with all the data and associated conditions. On the other hand, in the case of a new customer, a contact sheet is automatically created to optimize the time spent in the process.

It is now possible to integrate the Drupal module with InvoiceXpress so that the billing issue is faster.

This module was developed by BloomIdea, which has been part of the Drupal community for several years and is proud to frequently contribute to the growth and evolution of this platform.

Integrate the Commerce InvoiceXpress module now into your online store!

Oct 28 2019
Oct 28

Lazy load images in Drupal with BLazy

Recently, we involved in a local project with Ecoparker.com. It is a directory of restaurants, cafes, entertainments, services, real properties ... in Ecopark Hanoi, Vietnam. This site is based on our best selling directory theme BizReview.

On this site, there is a page which lists all kindergartens around the area. It has 20 listings and will continue to grow. It is a very typical page built with Drupal views.

Kindergartens at Ecopark

By curious, we ran a PageSpeed Insight test, a Goolge provided test for accessing how fast your page is loading, to see how it performs.

The score on Desktop was 75, which is quite good. But let's see how we can improve it.

Page speed test - before

Scroll down to the Opportunities section which suggests how to help your page load faster, we see an interesting point "Defer offscreen images" with the suggestion:

"Consider lazy-loading offscreen and hidden images after critical resources have finished loading to lower time to interative

Page speed test - suggestions

Lazy loading is a technique that only serve content when it becomes visible to users, ie, when users scroll to it. If it is off screen, we don't load it to save bandwidth. It will be much useful when your sites contain a lot of images, so we don't have to load them all everytime an user browse the page. Only when the user scroll, images load and become visible.

It brought me to a question that how to lazy load on Drupal.

We had a look a the Blazy module, because it was a prerequisite of another module on our site. Previously we haven't been curious to know what it does. It turns out to be a very popular module with 30K+ sites reporting using this module.

Looking in more details, this module is very promising:

On private benchmarks, Blazy saves a page with lots of images from 14MB to 3MB, 200 http requests to 20, loading time 30s to 3s. Elevating performance grade from F/E to A/B via gtmetrix. Overall ~5-10x better.

On the description page, Blazy offers:

  1. Blazy as field formatter
  2. Blazy filter as HTML filter (on your CKEditor)
  3. Blazy Grid as Views style

That's all we need, so we started to get our hands dirty.

1. Install module:

Install and enable the module as usual, via the admin interface or composer: https://www.drupal.org/docs/8/extending-drupal-8/installing-drupal-8-mod...

Note: if you use Slick module for slideshows, it requires Blazy 1.0. But to get Blazy as a HTML filter, you need the 2.0 version.

2. Blazy configuration:

Blazy configuration is available at /admin/config/media/blazy. There are a bunch of options, like custom placeholder image, offscreen view port etc ... You are good to go with default settings.

Drupal Blazy UI configuration

3. HTML filter

Just go to /admin/config/content/formats, edit the Full HTML format, and enable the Blazy filter.

Drupal Blazy filter as HTML filter

Your HTML content will be automatically applied Blazy filter, ie, images and iframes will be lazy loaded. On our project, we found that images lazy loading works properly, but iframes do not. Not sure why, but we will come back for it at a later time.

4. Views

We editted the view page, on the Image field, there is a new Image format. Choose Blazy and set the image style, Save it.

Drupal Blazy on Views

All images on this view based page are now lazy loaded. If you scroll fast enough, you will see the placeholder are blinking first, then your images will show. Awesome!

After that, we ran the PageSpeed Insight test again.

Page Speed test - after

As you can see, the issue with "Defer offscreen images" is gone. The point have raised to 81, which is slightly better. That's what we need.

In conclusion, please consider to apply the lazy load technique to all of your Drupal sites, as it is highly recommended for a high performance site.

Oct 24 2019
Oct 24

In the world of PCs, smartphones are much smaller than their desktop siblings but their significance keeps growing bigger and bigger. More and more users prefer to interact with brands using mobile devices.

Website owners need to hurry up to make their website mobile-friendly, in light of the mobile boom, as well as Google’s mobile-first indexing that shows the search giant primarily takes into account the website’s mobile display.

In addition to this, many go further and also build a mobile application to give an extra boost to their business.

Drupal is a great choice for both of the above:

1. Making websites mobile-friendly is a breeze with Drupal 8 thanks to its mobile-first principle. Responsive web design allows page elements to adapt to the current device and provides the user with the most convenient experiences.

Responsive web design in Drupal 8 example

2. Drupal can also be the base for creating fast, lightweight, and effective mobile applications — and that's what we will focus on in this post. Let’s see why you should build a mobile app with Drupal.

Some benefits of mobile apps for business

Mobile apps vary in architecture, but most of them include the following benefits:

  • Mobile apps significantly expand your mobile reach.
  • You can add more avenues of communication with your users and offer them more interesting features.
  • Mobile apps build a multichannel presence and promote your brand.
  • With them, you are closer to your audience even when their smartphone is offline.
  • You can benefit from in-app advertising.
  • You have access to the device’s hardware (i.e. using camera to make images).
  • They allow you to use the specific capabilities of iOS and Android devices.
  • You will get additional profits from being able to sell your mobile app in app stores.

and much more.

Mobile app example

Drupal as a platform to build a mobile app with

Speaking about mobile app development, you might be surprised to hear Drupal among the possible solutions. After all, Drupal is a PHP-based, enterprise-class content management framework known primarily in the arena of website creation.

Now let Drupal pleasantly surprise you in the mobile app area! Drupal works as a robust data source and shares its data to your mobile app, responding to requests and events on it. The data includes your content, business logic, functionality, user base, and so on.

This works both ways:

  1. If you already have a Drupal website, you can create a mobile app on its basis.
  2. If you are thinking about a strong backend platform for your mobile app, Drupal is your reliable choice.

Drupal is becoming an increasingly lucrative option for mobile development thanks to the following:

  • Drupal 8 adopted an amazing API-first principle and has 5 powerful modules for web services in the core. They provide Drupal’s smooth “communication” with any apps. Drupal REST APIs send data in the JSON format that is easy for applications to consume.
  • There are plenty of Drupal modules, development kits, libraries, and sample mobile apps to boost mobile development and integration.
Mobile app example

Native mobile apps with Drupal

Native mobile applications are written in the programming languages that are native to their device operating systems. For example:

  • Java and Kotlin for Android mobile apps
  • Swift and Objective-C for iOS mobile apps

Native apps are characterized by amazing productivity, the availability of device-specific features, user experiences tailored to the device, and more.

Drupal developers’ skill sets usually include PHP, MySQL, HTML, CSS, and JavaScript, which may sound far from the native mobile app programming languages. However, this is easily solved by using helpful software development kits, frameworks, and base apps.

Among them are PhoneGap, Waterwheel Swift, Drupal 8 iOS SDK, Example iOS app for Drupal 8, One Drupal Android, and others. They help in building native mobile apps and connecting Drupal to them.

Web-based mobile apps with Drupal

Unlike native mobile apps that use device-specific programming languages, web-based mobile apps rely on standard web technologies like HTML, CSS, and JavaScript. Web-based apps run in mobile device browsers.

They may be limited in their device-based capabilities, but they are versatile and have a faster time to market. Connected to Drupal via a REST API, these apps look native to the Android or iOS users while sharing Drupal data with them.

Today, there are plenty of JavaScript frameworks and tools that are characterized by amazing speed and interactivity. They include Vue, React, Angular, GatsbyJS based on React and GraphQL, Ionic based on Angular and Apache Cordoba, and so on. They pair perfectly with Drupal. Helpful SDKs, modules, plugins, and libraries help developers build faster and speed up the integration.

Build a mobile app with Drupal!

It’s time to let your business fully embrace all the benefits of mobile development. Our web development agency can help you with this. Ask our developers to build a mobile app for your specific business case, or perform a smooth integration between your existing software.

And, of course, also don’t forget that your website needs responsive web design.

The mobile future is here!

Oct 03 2019
Oct 03

The proper use of internal linking can turn any website into a powerful marketing tool. It is a vital part of effective content writing strategies. In this post, we explore why it is so, as well as review a helpful module for smart content linking in Drupal 8 — D8 Editor Advanced Link. Let’s go.

What is internal linking on websites?

Internal linking is known as the practice of placing hyperlinks inside content leading to the other relevant pages within the same domain. Internal links to content often use the keyword-rich anchor phrases. 

Why is internal linking important?

  • It boosts SEO rankings by helping the search engines understand what your pages are about, offering them multiple entry points to crawl your websites, as well as increasing page authority.
  • Session duration grows — users visit more pages per session, which, among other things, is an important search ranking factor.
  • Internal linking enhances user engagement by offering them more and more relevant content. They simply cannot leave!
  • The conversion rate potentially grows because users remain interested. They get closer and closer to making the desired conversion.

Internal linking in Drupal 8

Content links should be handy both for content editors to create and for website readers to navigate through. Of course, it’s possible with Drupal 8! 

First, creating links in Drupal 8 is handy for anyone by default — thanks to the built-in CKEditor with a link icon on its dashboard.

Standard link creation in Drupal 8's CKEditor

Second, there are also tools for creating links in Drupal 8 CKEditor that further extend the standard functionality. They are meant for more advanced internal and, of course, external linking as well. Let’s look at how this job is performed by one of them — the D8 Editor Advanced Link module.

The D8 Editor Advanced Link module

The Drupal module D8 Editor Advanced Link increases the website’s usability both for the content creators and readers in the following ways:

  • Content editors and SEO managers can control more precisely from the CKEditor panel how the content links are displayed. 
  • Content readers can enjoy rich links and more convenient navigation.

These content linking capabilities include:

  • linking directly to exact phrases or even words on the page
  • adding CSS classes
  • making links open in a new or in the same window
  • displaying the link’s title on mouseover
  • adding relationships between the linked and the source page

“This is a super simple module that serves a very cool little purpose,” said Thomas Shean, a famous Drupal contributor, in the video tutorial about the D8 Editor Advanced Link.

The principle of the D8 Editor Advanced Link module’s work

The module provides advanced link creation by offering more attributes to be added to them. Let’s compare. The classic Drupal CKEditor has just one field for the URL during content linking:

Standard link adding form in Drupal 8's CKEditor

Everything is different with the D8 Editor Advanced Link module installed. It enriches the Drupal 
CKEditor’s content linking menu with advanced attributes such as: 

  • title
  • class
  • id 
  • target 
  • rel
     
D8 Editor Advanced Link module's capabilities

The difference is amazing. More details will be discussed in the “Installation and configuration” part.

Installation and configuration of the D8 Editor Advanced Link

  • Installing and enabling the module

First, we need to install and enable the D8 Editor Advanced Link module on the Drupal 8 website. 

Enabling D8 Editor Advanced Link module in Drupal 8
  • Preparing the text formats

Next, we go to Administration — Configuration — Content authoring — Text formats and editors and open the “Full HTML” format.

Text formats in Drupal 8

We make sure we have the “link” buttons on the active toolbar. If not, we need to drag them there. We will need them, as well as the “source” button.

Configuring Drupal 8's CKEditor dashboard for adding links

We should also look at the "Limit allowed HTML tags and correct faulty HTML" filter. 

  1. If it is unchecked, there is nothing else to do, since there are no restrictions in tags. 
  2. If it is checked, you can add more allowed HTML tags manually (such as "title," "class," "id," "target," and "rel")
  • Using the content linking attributes

When we have prepared everything, we can go ahead with our Drupal content linking. When selecting the part of the text that needs to be linked and clicking on the “link” button, we will see a form with advanced attributes that just need to be unfolded. 
 

Advanced link attributes in CKEditor Advanced Link module for Drupal 8
  • URL. This is the URL of the destination page.
  • Title: This is the text that is shown as a tooltip when the mouse hovers over the link.

Advanced section:

  • CSS classes. This is the place to add CSS classes. Multiple ones are supported, which should be separated by spaces.
  • ID. This allows you to use URL fragments and lead users to a specific portion of the page. For example, you list “ID2” at the end of the URL tag after the “#” symbol. Then you should mark where the “ID2” fragment begins inside in the source code of the destination page. Like this: <p id="ID2">.
Using URL fragments in Drupal 8
  • Target. This is a simple check/uncheck option as to whether the links should open in a new window or not.
  • Relation (rel). This is for adding relationships between the source and the destination document (e.g. “nofollow,” “noreferrer,” etc.).

Make your internal linking in Drupal 8 more advanced!

With Drupal, there are always more opportunities than you could imagine. Make your content workflows much smarter by installing the D8 Editor Advanced Link module or other modules for internal linking in Drupal. 

Our Drupal team is always there for module selection, installation, configuration, or creation from scratch!

Sep 18 2019
Sep 18

It’s great to live at a time when a robust CMS can share its content with an ultrafast JavaScript front-end. One of the best examples of this is combining Drupal and GatsbyJS. We are happy to see a new tool for it that is fresh from the oven — Gatsby Live Preview module for Drupal 8. 

It provides Drupal editors with easy content creation workflows, making Drupal and Gatsby integration a more lucrative idea for developers and website owners.

GatsbyJS: a great companion for Drupal

The GatsbyJS modern site generator inspires the Drupal community more and more for many reasons. Here are at least a few:

  • It is based on the hottest technologies such as the ReactJS front-end framework, the GraphQL query language, and the Webpack JavaScript module bundler. 
  • It is amazingly fast and provides real-time content updates. Every static Gatsby site is, in fact, a full-fledged React app. 
  • It comes packed with 1250+ source plugins to retrieve data from particular data sources. This includes the Drupal source plugin that connects your Drupal site as a data source to your Gatsby site.
  • It has 250+ starter kits to quickly set up a Gatsby website that will display your Drupal 8 data.
GatsbyJS starter kit exampleGatsbyJS starter kit example 2

The Gatsby Live Preview module in Drupal 8

The contributed module called Gatsby Live Preview allows Drupal content editors to make content updates and immediately see how it will look on the Gatsby site before deployment. 

This easy content creation is provided by showing Drupal on the left and Gatsby on the right:

Gatsby Live Preview module in Drupal 8

The maintainer of the module, Shean Thomas, gave a talk and showed slides of the Gatsby Live Preview module at Decoupled Days in New York on July 18, 2019. 

Thomas explained the problem that the module solved. Previously, there was no easy way to see during content creation how changes would look like before you click “save.” Among the available options was to run the Gatsby development server before deploying the changes to live, which required the entire site regeneration. 

According to Shean Thomas, among the plans for the future is integrating the module with the Drupal 8’s Content Moderation module. The core Content Moderation and Workflows modules take content creation to a new level through handy editorial workflows in Drupal 8

The module is very new with its alpha release out on August 14, 2019. It is based on the tool introduced by the Gatsby team — the Gatsby Preview Beta

Steps to install and configure the module 

This part comes when the main setup is complete. So we assume you are done with:

  • Gatsby site creation
  • Gatsby Source Drupal plugin installation (version 3.2.3 or later)
  • configuring the gatsby-config.js file to list your Drupal website’s address
  • building up your Gatsby pages to display Drupal content

So the live preview setup steps are as follows:

  • install and enable the Gatsby Live Preview Drupal module the way you prefer
  • set up a Gatsby cloud preview account
  • set the “preview” flag to “true” in the “options” (the Gatsby Source Drupal plugin’s file)
  • Gatsby is now ready to follow the content changes at a particular URL
  • copy the preview URL from the Gatsby cloud to the “Gatsby Preview Server URL” (Configuration — System — Gatsby Live Preview Settings of your Drupal admin dashboard)

Examples of easy content creation & preview with the module 

The Decoupled Days' speech about the Gatsby Live Preview module greatly inspired the Drupal community. In order to make it easy for people to get started with Drupal and Gatsby integration. 

Drupal contributor Jesus Manuel Olivas decided to improve some features in the module.

The developer also added this setup to projects based on the Drupal Boina Distribution and shared his impressions about the module in the blog post with the video. Let’s have a look at this easy content creation process:

  • On the left side, we see the Drupal site where some content is added via the admin interface. 
Gatsby Live Preview module in Drupal 8 exampleGatsby Live Preview module in Drupal 8 example
  • On the right side, we see the Gatsby site update immediately after the “Save” button is clicked in Drupal.
Gatsby Live Preview module in Drupal 8 example

 

Get the most of Drupal and Gatsby integration!

Our developers will help you enjoy the incredible speed that GatsbyJS is able to give to your Drupal website! They can:

  • set up a Gatsby website and establish content retrieval from Drupal
  • build your Gatsby pages exactly according to your wishes thanks to GraphQL
  • install and configure the module for Drupal and Gatsby live preview for easy content creation

Our Drupal team are masters of modern JavaScript technologies. You can entrust this integration to us!

Sep 07 2019
Sep 07

In the previous article we’ve shown how to get data with useQuery from a Drupal powered GraphQL API. Fetching data is fun, but even more fun is to be able to send data to an API as part of interactivity features that our user might need to enjoy when using our apps. To do so in a more modern way Apollo now provides us with the useMutation()-hook. Let’s see how to make use of it.

Apollo Client React Hooks with Drupal GraphQL

Published on 2019-09-07 at 18:45

Drupal decoupled React.js GraphQL Apollo

Updating our Drupal GraphQL API to support mutations

First thing needed is to make Drupal aware of the fact that we want it to receive and store data via the GraphQL implementation. In the first part of this article series we already made the preparations so that Drupal knows how to handle GraphQL-queries. Let’s extend these so that players can be created via mutations as well. The first change needs to happen in the graphql/players.graphqls file of our custom module:

schema {
  query: Query
  mutation: Mutation
}

...

type Mutation {
  createPlayer(data: PlayerInput): Player
}

input PlayerInput {
  first_name: String!
  last_name: String!
}

The schema block receives the command mutation, which points to the new type “Mutation”. Inside of it we define the command and the input/data it needs, in order to be successful. We need two more changes, first update the resolvers in our Drupal schema - see changes src/Plugin/GraphQL/Schema/PlayersSchema.php:

<?php

...

  /**
   * {@inheritdoc}
   */
  public function getResolverRegistry() {
    $registry = new ResolverRegistry();
    $builder = new ResolverBuilder();

    $this->addQueryFields($registry, $builder);
    $this->addMutationFields($registry, $builder);
    $this->addPlayerFields($registry, $builder);

    // Re-usable connection type fields.
    $this->addConnectionFields('PlayerConnection', $registry, $builder);

    return $registry;
  }

  ...

  /**
   * @param \Drupal\graphql\GraphQL\ResolverRegistry $registry
   * @param \Drupal\graphql\GraphQL\ResolverBuilder $builder
   */
  protected function addMutationFields(ResolverRegistry $registry, ResolverBuilder $builder) {
    // Create player mutation.
    $registry->addFieldResolver('Mutation', 'createPlayer',
      $builder->produce('create_player')
        ->map('data', $builder->fromArgument('data'))
    );
  }

  ...

}

We create a new addMutationFields()-method where we assign the create_player producer to the mutation and set the data needed. The producer receives this data as an argument it its’ resolve method and handles the logic for manipulating and saving it, see src/Plugin/GraphQL/DataProducer/CreatePlayer.php:

<?php

namespace Drupal\drupov_apollo_react_hooks\Plugin\GraphQL\DataProducer;

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
use Drupal\node\Entity\Node;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Creates a new player entity.
 *
 * @DataProducer(
 *   id = "create_player",
 *   name = @Translation("Create Player"),
 *   description = @Translation("Creates a new player."),
 *   produces = @ContextDefinition("any",
 *     label = @Translation("Player")
 *   ),
 *   consumes = {
 *     "data" = @ContextDefinition("any",
 *       label = @Translation("Player data")
 *     )
 *   }
 * )
 */
class CreatePlayer extends DataProducerPluginBase implements ContainerFactoryPluginInterface {

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('current_user')
    );
  }

  /**
   * CreatePlayer constructor.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param array $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   */
  public function __construct(array $configuration, $plugin_id, array $plugin_definition, AccountInterface $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->currentUser = $current_user;
  }

  /**
   * Creates a player.
   *
   * @param array $data
   *   The title of the job.
   *
   * @return \Drupal\node\NodeInterface
   *   The newly created player.
   *
   * @throws \Exception
   */
  public function resolve(array $data) {
    if ($this->currentUser->hasPermission('create player content')) {
      $first_name = $data['first_name'];
      $last_name = $data['last_name'];

      $values = [
        'type' => 'player',
        'title' => $first_name . ' ' . $last_name,
        'field_first_name' => $first_name,
        'field_last_name' => $last_name,
      ];
      $node = Node::create($values);
      $node->save();

      return $node;
    }

    return NULL;
  }

}

Visit the GraphiQL explorer and make sure the mutation is working as here:

Create player mutation in GraphiQL explorer Create player mutation in GraphiQL explorer

Make the mutations from the React.js-app with useMutation()

Something important first. As this article does not handle authentication etc. make sure to loosen up Drupals’ permission system appropriately, so that anonymous users also have the permission “Player: Create new content” - something you probably must reconsider in production.

Let’s start by adding our new GraphQL-query to src/gql/common.js:

export const CREATE_PLAYER = gql`
mutation CreatePlayer ($first_name: String!, $last_name: String!) {
  createPlayer (data: {first_name: $first_name, last_name: $last_name}) {
    id
  }
}
`;

With that in place, we can turn our attention to the new component itself - create a src/components/CreatePlayer.js-file:

import React from 'react';
import { useMutation } from '@apollo/react-hooks';
import { CREATE_PLAYER, PLAYERS } from '../gql/common';

const CreatePlayer = () => {
  const [createPlayer, { loading }] = useMutation(CREATE_PLAYER);

  return (
    <React.Fragment>
      <h1>Create new player</h1>
      {loading ? <p>Saving player...</p> : ''} 
      <form
        onSubmit={event => {
          event.preventDefault();
          const firstName = event.target.first_name.value;
          const lastName = event.target.last_name.value;
          
          if (!firstName || !lastName) {
            alert('First or last name must be filled out.');
            return;
          }

          createPlayer({
            variables: {first_name: firstName, last_name: lastName},
            refetchQueries: [{ query: PLAYERS }]
          }).then((res) => {
            console.log(`Player with id ${res.data.createPlayer.id} added successfully.`);
          });

          event.target.first_name.value = '';
          event.target.last_name.value = '';
        }}
      >
        <label htmlFor="first_name">First name</label>
        <input type="text" name="first_name" />
        <br />
        <label htmlFor="last_name">Last name</label>
        <input type="text" name="last_name" />
        <br />
        <button type="submit">Create player</button>
      </form>
    </React.Fragment>
  );
}

export default CreatePlayer;

Right at the beginning of the component we call the useMutation()-hook and pass it the new query. The hook is fired, when the appropriate function is called, as defined by the hook, in this case createPlayer(). This function get passed an object as an argument with the variables for the query, but also an array of queries that need to be re-fetched, so that Apollo gets the most recent data. At the end, we create a new player here and the players data would need to be updated and therefore the Players-component re-rendered.

Last but not least, let’s add this new component to the Overview.js:

import React from 'react';
import Players from './Players';
import CreatePlayer from './CreatePlayer';

const Overview = () => {
  return (
    <React.Fragment>
      <Players />
      <CreatePlayer />
    </React.Fragment>
  );
}

export default Overview;

Let’s try out or new code:

Create new player Create new player

The code using useMutation() looks pretty slick and well isolated. One of the main advantages of this hook is that it can be reused multiple times in a single component, e.g. to update and delete an entity, something not possible prior with the HOC-approach. Check out the code for backend and frontend in the respective repositories.

Find me on LinkedIn or Twitter with any questions you have on this topic, looking forward to get in touch with you.

Sep 07 2019
Sep 07

In the previous article we successfully set up a GraphQL server in Drupal 8 with the 4.x-version of the module. Our goal this time is to fetch data from the API by using the recently introduced useQuery()-hook and display the players data we have in the CMS in our frontend app.

Apollo Client React Hooks with Drupal GraphQL

Published on 2019-09-07 at 18:45

Drupal decoupled React.js GraphQL Apollo

Create the app, add our dependencies and modify the entry point

Something important first. As this article does not handle authentication etc. make sure to loosen up Drupals’ permission system appropriately, so that anonymous users have the permission “Players: Execute arbitrary requests” - something you probably must reconsider in production.

Let’s create a new React.js app as usual. As the article title says, we need some additional packages in addition to what is provided by the boilerplate command:

npm install apollo-boost @apollo/react-hooks graphql react-apollo

With that out of the way let’s edt the src/App.js file in the app to look like this:

import React, { useState } from 'react';
import Overview from './components/Overview';
import Player from './components/Player';
import PlayerContext from './context/PlayerContext';
import ApolloClient from "apollo-boost";
import { ApolloProvider } from 'react-apollo';

const client = new ApolloClient({
  uri: 'https://apollo-react-hooks-drupal-graphql.lndo.site/graphql'
});

const App = () => {
  const [activePlayerId, setActivePlayerId] = useState(0);

  return (
    <ApolloProvider client={client}>
      <PlayerContext.Provider value={
        {
          activePlayerId: activePlayerId,
          setActivePlayerId: setActivePlayerId
        }
      }>
        {activePlayerId ? <Player /> : <Overview /> }
      </PlayerContext.Provider>
    </ApolloProvider>
  )
}

export default App;

A few things to note here: we initialize the ApolloClient and pass it the uri of our Drupal installation. I use Lando, so this is the URL I get from it. You can see also that I chose /graphql as the endpoint in my GraphQL server. Furthermore in the App-component I set activePlayerId as state and assign it 0 initially. The idea here is that if the value differs than 0, then a detailed view of a player would be displayed, otherwise we should get a list of all players.

Creating the components needed

The Overview-component is a pretty simple one:

import React from 'react';
import Players from './Players';
import CreatePlayer from './CreatePlayer';

const Overview = () => {
  return (
    <React.Fragment>
      <Players />
    </React.Fragment>
  );
}

export default Overview;

At the moment it simply renders the Players-component. The reason to not render the Players-component itself directly here, it that later the Overview will get an additional component, the CreatePlayer. There we’ll show how to implement the useMutation()-hook. Let’s see how this Players-component looks like, but first of all let’s put our GraphQL-queries in a separate file, so that they can be imported where needed. For that let’s create a file src/gql/common.js:

import gql from "graphql-tag";

export const PLAYER = gql`
query Player ($id: Int!) {
  player(id: $id) {
    first_name
    last_name
  }
}
`;

export const PLAYERS = gql`
{
  players {
    items {
      id
      first_name
      last_name
    }
  }
}
`;

We now have all the ingredients needed to create our Players-component:

import React, { useContext } from 'react';
import PlayerContext from '../context/PlayerContext';
import { useQuery } from '@apollo/react-hooks';
import { PLAYERS } from '../gql/common';

const Players = () => {
  const context = useContext(PlayerContext);
  const { data, loading, error } = useQuery(PLAYERS);
  
  if (error) {
    return error.message;
  }

  return (
    <React.Fragment>
      <h1>Players</h1>
      {
        loading
        ?
        <p>Loading...</p>
        :
        data.players.items.map((item) => (
          <button key={item.id} onClick={() => context.setActivePlayerId(item.id)}>
            {item.first_name} {item.last_name} ({item.id})
          </button>
        ))
      }
    </React.Fragment>
  );
}

export default Players;

OK, we’re getting there. useQuery() receives the GraphQL-query as a parameter and this is really all it needs in order to connect to the API endpoint and receive data. The rest is pretty straightforward React.js-code - we render a loading indicator during loading and after that a list of buttons for each record. Clicking on the button would make use of the Context API and set the active player id to the current one in question, so that the detailed component Player.js would render.

import React, { useContext } from 'react';
import PlayerContext from '../context/PlayerContext';
import { useQuery } from '@apollo/react-hooks';
import { PLAYER } from '../gql/common';

const Player = () => {
  const context = useContext(PlayerContext);

  const { data, loading, error } = useQuery(PLAYER, {variables: {id: context.activePlayerId}});

  if (error) {
    return error.message;
  }

  return (
    <React.Fragment>
      <h1>Player data</h1>
      {
        loading
        ?
        <p>Loading...</p>
        :
        <React.Fragment>
          <p>First name: {data.player.first_name}</p>
          <button onClick={() => context.setActivePlayerId(0)}>Return to players list</button>
        </React.Fragment>
      }
    </React.Fragment>
  );
}

export default Player;

The thing to note in that component is that we provide useQuery with an additional parameter, an object that contains the id of the player node, which is passed into the query, in order to return the date for the one player in question.

Player data in Drupal and frontend Player data in Drupal and frontend

That’s really it. useQuery() makes the component where it is used extremely easy understandable and more importantly also makes sure that the data requirements are in one place with the code responsible for rendering that data. This is one of the huge advantages of the new Apollo hooks. You can check out the code we wrote here over at this repository. In the next article we’ll take a look at another hook provided by Apollo - the useMutation().

Find me on LinkedIn or Twitter with any questions you have on this topic, looking forward to get in touch with you.

Sep 07 2019
Sep 07

With version 16.8 React.js made the breaking change of introducing hooks as a new way to write your functional components. If you have used the Apollo Client to connect your GraphQL server to your React application - which you should, there are now more good news - Apollo Client has adopted the hooks-concept, making fetching and updating data a lot easier. Let’s see how we can do that with Drupal’s GraphQL implementation.

Apollo Client React Hooks with Drupal GraphQL

Published on 2019-09-07 at 18:44

Drupal decoupled React.js GraphQL Apollo

Set up Drupal’s GraphQL module for queries

Create content type

For this article we’ll create a new content type in Drupal and serve its’ data from the 4.x-version of the GraphQL module. The content type would be player, containing two custom fields - the first and last name of the player. Let’s remove the body field and just use two fields of type “Text (plain)” for the names. At the end we the “Manage fields”-screen ot the “Players” content type should look like this:

Fields on player content type Fields on player content type

Create custom schema

Great! Now let’s create the custom schema for GraphQL in a custom module. In contrast to version 3 of the module, where we were provided with an almost full schema of the entities available in Drupal, version 4 of the module allows you to tailor your GraphQL-schema exactly to the data requirements of the frontend, taking only the data that is needed with you and also removing Drupalisms along the way, that would not make any sense to frontend developers not familiar with Drupal.

Disclaimer: big thanks to Joao Garin for the excellent documentation on the GraphQL module, that helped me a lot to figure out the best way to set up the schema in Drupal.

In order to create the schema we need to make sure to download and install the 4.x-version of GraphQL:

composer require drupal/graphql:4.x-dev
drush en graphql

We also need a custom module where to define our schema and data producers. First step is to define the schema definition, based on the data we want to make available in our API. For this we need to create a file graphql/players.graphqls in our module, where players is what the machine name of our resolver (the connector between the schema and Drupals’ data model) will be.

schema {
  query: Query
}

type Query {
  player(id: Int!): Player
  players(
    offset: Int = 0
    limit: Int = 10
  ): PlayerConnection!
}

type Player {
  id: Int!
  first_name: String!
  last_name: String!
}

type PlayerConnection {
  total: Int!
  items: [Player!]
}

We want two types of queries. One that would return all currently available player nodes in Drupal and one that would fetch a single one, identified by the node id. Note that the id-parameter is not defined as nid, as node identifiers are called in Drupal, as this makes no sense outside of the Drupal community. Same with the first_name and last_name fields, they are not prefixed with field_ as Drupal would do. This schema is what our frontend requirements might very well look like and GraphQL 4.x in Drupal 8 allows us to mimic it as close as possible.

Create resolvers and data producers

Let’s hook up the schema to a resolver and data producer in Drupal. We need to extend SdlSchemaPluginBase, done in a file src/Plugin/GraphQL/Schema/PlayersSchema.php in our module:

<?php

namespace Drupal\drupov_apollo_react_hooks\Plugin\GraphQL\Schema;

use Drupal\graphql\GraphQL\ResolverBuilder;
use Drupal\graphql\GraphQL\ResolverRegistry;
use Drupal\graphql\Plugin\GraphQL\Schema\SdlSchemaPluginBase;
use Drupal\drupov_apollo_react_hooks\Wrappers\PlayerConnection;

/**
 * @Schema(
 *   id = "players",
 *   name = "Players schema"
 * )
 */
class PlayersSchema extends SdlSchemaPluginBase {

  /**
   * {@inheritdoc}
   */
  public function getResolverRegistry() {
    $registry = new ResolverRegistry();
    $builder = new ResolverBuilder();

    $this->addQueryFields($registry, $builder);
    $this->addPlayerFields($registry, $builder);

    // Re-usable connection type fields.
    $this->addConnectionFields('PlayerConnection', $registry, $builder);

    return $registry;
  }

  /**
   * @param \Drupal\graphql\GraphQL\ResolverRegistry $registry
   * @param \Drupal\graphql\GraphQL\ResolverBuilder $builder
   */
  protected function addQueryFields(ResolverRegistry $registry, ResolverBuilder $builder) {
    $registry->addFieldResolver('Query', 'player',
      $builder->produce('entity_load')
        ->map('type', $builder->fromValue('node'))
        ->map('bundles', $builder->fromValue(['player']))
        ->map('id', $builder->fromArgument('id'))
    );

    $registry->addFieldResolver('Query', 'players',
      $builder->produce('query_players')
        ->map('offset', $builder->fromArgument('offset'))
        ->map('limit', $builder->fromArgument('limit'))
    );
  }

  /**
   * @param \Drupal\graphql\GraphQL\ResolverRegistry $registry
   * @param \Drupal\graphql\GraphQL\ResolverBuilder $builder
   */
  protected function addPlayerFields(ResolverRegistry $registry, ResolverBuilder $builder) {
    $registry->addFieldResolver('Player', 'id',
      $builder->produce('entity_id')
        ->map('entity', $builder->fromParent())
    );

    $registry->addFieldResolver('Player', 'first_name',
      $builder->produce('property_path')
        ->map('type', $builder->fromValue('entity:node'))
        ->map('value', $builder->fromParent())
        ->map('path', $builder->fromValue('field_first_name.value'))
    );

    $registry->addFieldResolver('Player', 'last_name',
      $builder->produce('property_path')
        ->map('type', $builder->fromValue('entity:node'))
        ->map('value', $builder->fromParent())
        ->map('path', $builder->fromValue('field_last_name.value'))
    );
  }

  /**
   * @param string $type
   * @param \Drupal\graphql\GraphQL\ResolverRegistry $registry
   * @param \Drupal\graphql\GraphQL\ResolverBuilder $builder
   */
  protected function addConnectionFields($type, ResolverRegistry $registry, ResolverBuilder $builder) {
    $registry->addFieldResolver($type, 'total',
      $builder->callback(function (PlayerConnection $connection) {
        return $connection->total();
      })
    );

    $registry->addFieldResolver($type, 'items',
      $builder->callback(function (PlayerConnection $connection) {
        return $connection->items();
      })
    );
  }

}

The protected methods in the class are very much aligned with the schema we defined previously - we have

  • addQueryFields - which differentiates between the two queries we want to have - player and players

  • addPlayerFields - here we resolve the 3 values we want to have returned by our Player type: id, first_name and last_name. Nothing more, nothing less.

  • addConnectionFields - here we return specific values for our PlayerConnection needed in the players-query, as these are not entity API specific and need to be provided specifically.

The data producer for the players query should live in src/Plugin/GraphQL/DataProducer/QueryPlayers.php and contain the following code:

<?php

namespace Drupal\drupov_apollo_react_hooks\Plugin\GraphQL\DataProducer;

use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\drupov_apollo_react_hooks\Wrappers\PlayerConnection;
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
use GraphQL\Error\UserError;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * @DataProducer(
 *   id = "query_players",
 *   name = @Translation("Load players"),
 *   description = @Translation("Loads a list of players."),
 *   produces = @ContextDefinition("any",
 *     label = @Translation("Player connection")
 *   ),
 *   consumes = {
 *     "offset" = @ContextDefinition("integer",
 *       label = @Translation("Offset"),
 *       required = FALSE
 *     ),
 *     "limit" = @ContextDefinition("integer",
 *       label = @Translation("Limit"),
 *       required = FALSE
 *     )
 *   }
 * )
 */
class QueryPlayers extends DataProducerPluginBase implements ContainerFactoryPluginInterface {

  const MAX_LIMIT = 100;

  /**
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function __construct(
    array $configuration,
    $pluginId,
    $pluginDefinition,
    EntityTypeManagerInterface $entityManager
  ) {
    parent::__construct($configuration, $pluginId, $pluginDefinition);
    $this->entityManager = $entityManager;
  }

  /**
   * @param $offset
   * @param $limit
   * @param \Drupal\Core\Cache\RefinableCacheableDependencyInterface $metadata
   *
   * @return \Drupal\drupov_apollo_react_hooks\Wrappers\PlayerConnection
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function resolve($offset, $limit, RefinableCacheableDependencyInterface $metadata) {
    if (!$limit > static::MAX_LIMIT) {
      throw new UserError(sprintf('Exceeded maximum query limit: %s.', static::MAX_LIMIT));
    }

    $storage = $this->entityManager->getStorage('node');
    $type = $storage->getEntityType();
    $query = $storage->getQuery()
      ->currentRevision()
      ->accessCheck();

    $query->condition($type->getKey('bundle'), 'player');
    $query->range($offset, $limit);

    $metadata->addCacheTags($type->getListCacheTags());
    $metadata->addCacheContexts($type->getListCacheContexts());

    return new PlayerConnection($query);
  }

}

Take a look at the resolve-method here. Here we prepare all query parameters for the Drupal query and pass it into the player connection class. Let’s create this one in src/Wrappers/PlayerConnection.php too, to wrap things up:

<?php

namespace Drupal\drupov_apollo_react_hooks\Wrappers;

use Drupal\Core\Entity\Query\QueryInterface;
use GraphQL\Deferred;

class PlayerConnection {

  /**
   * @var \Drupal\Core\Entity\Query\Sql\Query
   */
  protected $query;

  /**
   * QueryConnection constructor.
   *
   * @param \Drupal\Core\Entity\Query\QueryInterface $query
   */
  public function __construct(QueryInterface $query) {
    $this->query = $query;
  }

  /**
   * @return int
   */
  public function total() {
    $query = clone $this->query;
    $query->range(NULL, NULL)->count();
    return $query->execute();
  }

  /**
   * @return array|\GraphQL\Deferred
   */
  public function items() {
    $result = $this->query->execute();
    if (empty($result)) {
      return [];
    }

    $buffer = \Drupal::service('graphql.buffer.entity');
    $callback = $buffer->add($this->query->getEntityTypeId(), array_values($result));
    return new Deferred(function () use ($callback) {
      return $callback();
    });
  }

}

The PlayerConnection is simply a helper class, that has the two methods total() and items(), corresponding to what we have defined as requirements in our schema.

Now that was a lot of code we created, but we’re ready with our API! What’s left is very clicks in Drupal. Go to /admin/config/graphql and create a new server. Give it some meaningful label and choose the just created “Players schema”. The endpoints can be anything that makes sense, usually /graphql is chosen. Click save and visit /node/add/player in your Drupal installation to create a new Player-node. Save it and choose the GraphiQL-explorer from the drop-down menu of your new server. Here is my result :)

Drupal GraphQL player query Drupal GraphQL player query

You can get the full code at this repository. This is it for now. Having our API finished we can now see how to fetch data from a React.js application with the new Apollo Client React hook useQuery() in the next article.

Find me on LinkedIn or Twitter with any questions you have on this topic, looking forward to get in touch with you.

Sep 04 2019
Sep 04

Drupal 8 makes it easier and easier to create rich, interesting, and beautiful content pages. Among the new features of the Drupal 8.7 release, we saw the stable Layout Builder and the new Media Library user interface. 

Another great piece of news is coming now! The Media Library in Drupal 8 has an embed button added to the CKEditor panel, and media embedding without a mouse is possible. This Media Library and CKEditor integration is now in the dev branch and will be officially available with the Drupal 8.8 stable release in December 2019. 

Consider scheduling your Drupal website update to 8.8 with our team. Meanwhile, let’s learn more about the new features.

The Media Library in Drupal 8 and rich content creation

Thanks to the Media Library and Media modules being part of the Drupal core, media handling in Drupal 8 is very convenient. It’s possible to add various types of media, store them in the Library, and reuse the content whenever you need it. 

You can display the items in a grid or table view, select and insert them, sort and filter them by various criteria, bulk upload, and so on. With the new Library user interface introduced in Drupal 8.7, everything looks and works especially well. Here are our screenshots from this version.

Media Library in Drupal 8

Media Library in Drupal 8: adding or selecting images

The default Drupal 8 media types are:

  • Audio
  • File
  • Image
  • Remote video (with links from YouTube, Vimeo, etc.)
  • Video

Using items from Media Library in content

Content editors appreciate the ability to select items from the Library and insert it directly into the content. To achieve this, it is necessary to add the Media field of the relevant type to a content type (or other fieldable entities like user account). 

Media Library in Drupal 8: oEmbed videosMedia Library in Drupal 8: adding or selecting videos

Great news: media button in the CKEditor panel

To make media selection and embedding experiences even smoother, the embed button has now been added to the CKEditor dashboard in Drupal 8.8x-dev release. This Media Library and WYSIWYG integration was announced in a tweet by “The Drop is Always moving.”

Media Library and CKEditor integration tweet

As we see, the Media Library button has an icon that looks attractive and clearly shows its purpose to users. 

The Media subsystem maintainer Phenaproxima shows nice screenshots and writes that the icon design is agreed by all, usability tests are successfully passed, and the button is well-tested. Congrats and thanks to the team of amazing experts for their job!

The work is successfully committed to the Drupal 8.8.x dev branch, waiting for the official release on December 4, 2019.

Media Library button added to Drupal 8.8 CKEditor

Users can click on the button, see the Media Library, select media, and click “ Insert Selected.”

Media Library button added to Drupal 8.8 CKeditor

The button can be enabled or disabled by drag-and-dropping, which is a great capability of the CKEditor in Drupal 8.

CKEditor panel now with Media Library button

Breaking news: final patch for Media Library and WYSIWYG integration

As we were preparing this article for publication, another awesome news arrived about the final feature patch for the Media Library. It allows for media embedding in WYSIWYG with no mouse needed. Wim Leers, one of the gurus who make such things happen, posted a video on his blog post.

Media embedding without mouse in Drupal 8.8 CKEditor

Enjoy the Media library’s new features!

Start producing richer content in a snap of a finger — use the Media Library in Drupal 8. Our Drupal support and development team can assist you in every step of your way. For example, we can:

  • update you to Drupal 8.7 so you can use new Media Library’s user interface
  • upgrade your website to Drupal 8 if you are still on Drupal 7
  • adjust your website’s settings for easy media handling workflows
  • advise you and set up other attractive ways to display content in Drupal 8
  • and, of course, update you to the upcoming Drupal 8.8 as soon as it arrives in December

Follow our news about Drupal support services and always feel free to contact us!

Aug 28 2019
Aug 28

To always work smoothly and be up-to-date, your Drupal website needs support and maintenance. It’s nice to know you can rely on experts for things like Drupal updates, website performance audit, bug fixes, or anything else. However, you need to choose them carefully. 

First of all, there are plenty of reasons to choose a support company over a freelancer. But there are also the must-have characteristics of a good Drupal support agency. Let them help you with your choice. 

Good Drupal support agency’s features 

  • Decent time on the market

All companies were once startups. However, if a Drupal support agency popped up a week ago, it might be risky to immediately entrust it with major website tasks. After a little while, the agency is able to prove its stability on the market. 

Drudesk support agency has celebrated its 4th birthday and its parent company InternetDevels is preparing to have its 12th anniversary. They have gained a lot of solid experience in challenging Drupal support projects and complex cases.

  • Positive customer feedback

No one says that 100% trust in online feedback is a panacea. Still, it’s important to know what experiences other people have had with a Drupal support agency, so it definitely should have positive reviews.

Drudesk’s customers speak warmly about the agency, call it a forward-thinking and conscientious team, communicative and organized, quick to respond to queries, a reliable partner, and more. Drudesk reviews on Clutch, testimonials on the company’s main page, and other feedback will give you a better picture. 


positive customer feedback

  • A wide range of support services

Website support embraces a wealth of various aspects. It’s convenient and effective to have the same agency working with all of them. So your ideal Drupal supporting partner needs to have broad expertise. 

Drudesk offers all kinds of support and related services. Among them:

and many more.

But this is not all — Drudesk has a strong web development background that allows it to develop websites from scratch. 

In addition, the agency employs quality assurance engineers, DevOps experts, SEO specialists, and others whose expertise may be needed for your case. 

a wide range of support services

  • Warranty for the work performed

Drupal support services, like any others, need to have a warranty. This means that the agency is responsible for their work. 

It should be noted that website support services have their peculiarities. Websites often have old bugs and legacy code that may interfere with the website’s work, making it harder to give a warranty for particular tasks. 

Still, Drudesk cares about customers and offers a warranty for the tasks performed. The standard acceptance period lasts 31 calendar days. During this time, you can check the results. If you find any bugs, everything is fixed free of charge.

  • Transparent task tracking

A good Drupal support agency will give you full control over the tasks performed. Its workflows will be transparent and open to you.

With Drudesk, all customers can see the working progress in real-time. All tasks are managed in Drudesk’s CRM. You can leave your comments on tasks and approve the results. You can also be notified about the team’s new comments in any way convenient to you. 

Since Drudesk relies on the Agile methodology, it has an iterative approach to projects. Large ones are broken into sprints and your feedback is considered at every stage in order to make the result more suited to your needs.

transparent task tracking

  • Openness to communication

When working with a decent Drupal support agency, you should feel they are ready to answer your questions and hear your feedback.

Effective communication is one of Drudesk’s priorities. The agency has English-speaking customer service managers and project managers. 

They make sure your ideas are brought to the developers in the right ways, and they are always open to communication and ready to schedule a Skype call with you or reply by email.  

  • Drupal.org profile & community engagement

Every agency working with the Drupal open-source CMS is part of the Drupal community. Its engagement into Drupal life is directly connected to its attitude and expertise. 

Drudesk is listed on drupal.org and its developers make their contribution to various Drupal projects. They help newbies understand Drupal through discussion forums and willingly mentor new talents. Drudesk developers also actively participate in Drupal events like code sprints, Drupal Camps, etc.

Drupal community engagement

Your Drupal support agency is here

When all these characteristics are met, this means you have found a perfect Drupal support services partner. Contact our Drupal support agency and let’s discuss how we can make your website’s work better. This is where good website support starts!

Aug 15 2019
Aug 15

Once, the Drupal community had Mollom, and everything was good. It was a web service that would let you use an API to scan comments and other user-submitted content and it would let your site know whether it thought it was spam, or not, so it could safely publish the content. Or not. It was created by our very own Dries Buytaert and obviously had a Drupal module. It was the service of choice for Drupal sites struggling with comment spam. Unfortunately, Mollom no longer exists. But there is an alternative, from the WordPress world: Akismet.

Akismet is very similar to Mollom. It too is a web service that lets you use an API to judge if some submitted content is spam. The name is derived from the Turkish word kismet, which means fate or destiny. The A simply stands for automatic (or Automattic, the company behind both WordPress and Akismet). It was created for WordPress, and like Mollom was once for Drupal, it is the service of choice for WordPress sites. However, nothing is keeping any other software from making use of it, so when you download the Akismet module, you can use it with your Drupal site as well. Incidentally, the module is actually based on the code of the Mollom module.

There is no stable release of the module, currently. In fact, there is no release at all, not even an alpha release. Except for development releases, that is. This means that for now it might not be an option for you to deploy the module. Hopefully, this changes soon, although the last commit is over a year ago at the time of writing. A mitigating circumstance, though, is that Drupal.org itself seems to be using this module as well, albeit in the Drupal 7 version (this article will be discussing the D8 version).

Adding Akismet to your Drupal site

How to add the module will depend on your workflow. Either download a development release, or - when you use a composer-based workflow - add the module like so:

$ composer require drupal/akismet:^[email protected]

Then, enable the module through the Extend admin screen (/admin/modules).

Basic configuration

In order to configure the module, you will first need an Akismet API key. To get this, register at https://akismet.com. If you have a wordpress.com account (which you might have from either wordpress.com itself, or e.g. because you also have Gravatar) you can sign in with it.

Once you've obtained an API key, you can go to /admin/config/content/akismet/settings to configure Akismet.

The choice what to do when Akismet is not available is probably dependent on how busy your site is. If it is very busy, and you do not get tons of spam, you probably want to accept all submissions. If you get a lot of spam and not very many actual contributions, you might want to block everything. If you both have a high traffic site and get a lot of spam, good luck. Of course, you can always look at a second line of defense, like the Honeypot module

The second two settings - Show a link to the privacy policy and Enable testing mode - seem to be left-overs from the Mollom module, because neither of them seem to do anything. I created issues for both the privacy policy and the testing mode.

While Mollom had a requirement to either show a link to its terms of use on protected forms, or have your own terms of use that made it clear you make use of the Mollom service, Akismet doesn't seem to have such a requirement. (Of course, it is a good idea to add something about your use of Akismet in your terms of use or your privacy policy).

Testing with Akismet is possible to either pass "viagra-test-123" as the body of the message, or "[email protected]" as the email address; these will always result in a spam classification. This seems to trigger the "unsure" scenario, eventhough that doesn't actually fully work, currently (see further). Forcing a ham (the opposite of spam - I didn't make this up) response is a bit trickier, because it would involve setting some parameters to the web service you do not have control over from the outside. Especially the testing mode might be a nice feature request for the Akismet module. Ideally, the module would work similar to the Mollom module, where you could simply send in a comment with "ham", "unsure" and "spam" to test. As said, I created an issue to flesh out this functionality.

The advanced configuration hides settings to control whether to only log errors and warnings, or all Akismet messages, and a timeout for contacting the Akismet server. Especially in the beginning you might want to log all messages to monitor whether things are working as they should. 

Configuring which forms to protect

When having finished the basic configuration for the module, it is time to configure the forms you want to protect. This happens on the path /admin/config/content/akismet. Here, click the "Add form" button to start configuring a form.

When clicking the button, the module will ask you which form you wish to configure. Out of the box, the module will offer to protect node, comment user and contact forms. A hook is offered to add additional forms, although either a module will need to implement the hook itself, or it will have to be done for it. Here, I'm choosing to just protect the comment form, as I am suffering from quite a lot of comment spam. Once you've chosen a form, it will show the form fields you might want to pass to the Akismet web server for analysis.

You'll basically want to select anything that is directly controlled by the user. The obvious candidate is the body, but also the subject, user name, email address, website and hostname will contain clues whether something is spam or not.

Next, you get to select what happens when Akismet decides content is or might be spam. Akismet may report back that it is sure something is spam. If it says something is spam, but does not pass back this certainty flag, the Drupal module says Akismet is "unsure", which is actually a term that can be traced back to the Mollom roots of this module. You may tell the module it should then retain the submission for manual moderation, although this doesn't seem to work correctly, at the moment. I created an issue in the issue queue for that. What I'm seeing happening is that the post is discarded, just like when Akismet is sure.

Click Create Protected Akismet Form to save the protection configuration. You're now ready to catch some spam. You can look at the watchdog log (/admin/reports/dblog) to see the module reporting on what it is doing. Akismet itself also has a nice dashboard with some graphs showing you how much ham and spam it detected on your site.

Reporting spam to Akismet

Sometimes, Akismet might wrongly accept some piece of content that is actually spam. Or, when the moderation queue mechanism actually works properly, you probably want to let Akismet know that yes, something is in fact spam (you might also want to let Akismet know it didn't correctly identify spam, i.e. report false positives. This is a feature of the web service, but is currently not in the module; another feature request, it seems. I've submitted one in the issue queue).

The module comes with action plugins for comments and nodes that let you unpublish the content and report it as spam to Akismet at the same time. You can add it to your comment views by changing their configuration at /admin/structure/views/view/comment (you will need the Views UI module enabled to be able to configure views). Unfortunately, it seems that also with this functionality there is an issue, the action doesn't actually unpublish. A patch is available in the linked issue and of course the workaround is to first use the Akismet action, and then use the standard unpublish action.

Find the configure link for the Comment operations form. Click the link and, in the modal that opens, find the list of checkboxes for the available actions. Enable Report to Akismet and unpublish and save the configuration. Repeat for the Unapproved comments display. This will mean you will now have the action available in the actions dropdown on the comments overviews at /admin/content/comment.

Adding this to a node view will be similar, although chances are that when you have end users submitting nodes, you likely also have some dedicated views for your specific use case, such as Forum posts.

Issues created as a result of this blog post

Please note that I did not intend to "set anyone to work" with creating these. I simply wanted to record some findings and ideas from writing up this blog post.

Aug 14 2019
Aug 14

It‘s easy and enjoyable to create marketing campaigns, drive leads, and tell your brand’s story to the world if your website is on the right CMS. Drupal 8’s benefits will definitely impress any marketer. So let’s take a closer look at the greatness of Drupal 8 for marketers, see what makes it so valuable, and name a few useful modules.

The benefits of Drupal 8 for marketers

Drupal 8 has cutting-edge marketing features built into the core and a myriad of contributed modules helpful in every aspect of your successful marketing. 

Easy integration with marketing automation tools 

Marketers love the various marketing automation and CRM tools. They effectively streamline their workflows, as well as give them valuable analytics. 

Thanks to its built-in support for RESTFul web services, Drupal 8 integrates with marketing tools or any others at a snap of a finger. 

Drupal 8 modules to integrate marketing tools

and many more.

Multilingual Drupal 8 campaigns

Marketers can produce more powerful and convincing campaigns in their users’ native languages. Without a doubt, Drupal 8 is a great choice for multilingual websites.

A hundred languages are supported out-of-box, including those with the RTL text direction. The four built-in multilingual modules make it easy to add languages to your site and translate everything — interface, configuration, and content. Most interface translations are already prepared by the community.

Admin interfaces to add translations are very handy and editor-friendly. As D8’s third-party integration capabilities are among its key benefits, it’s also easy to integrate any translation software.

Drupal 8 modules for translation tool integration

and more.

There also are contributed Drupal 8 modules for multilingual features for every aspect of a multilingual website.

Some Drupal 8 multilingual modules

and many more.

Multilingual Drupal 8 website example

 

Multi-channel marketing in Drupal 8

Marketers can engage customers with their Drupal 8 campaigns on their preferred devices. D8 websites are ready to share their data to any web or mobile applications. 

This is thanks to the API-first architecture — one of D8’s key benefits. The core now has 5 robust modules that effectively expose your Drupal entities as a RESTful web API. In the Drupal 8.7 release, the JSON:API module joined this “team” to make multi-channel experiences even more ambitious.

Marketers will appreciate the “create once, publish everywhere” philosophy adopted by the API-first Drupal 8. It significantly increases their reach with minimum publishing expenses. 

Quick and handy content creation with advanced features

Content is the heart and soul of marketing campaigns. A new level of its creation is among the greatest benefits prepared by Drupal 8 for marketers. Editorial workflows are both very user-friendly and advanced in their capabilities. 

At least a few of Drupal 8 content creation benefits

  • You can make edits on the fly with the inline editing feature.
  • The handy drag-and-drop CKEditor is the default D8’s WYSIWYG editor. 
  • Drupal 8 has a Media Library that lets you save and reuse videos, audios, images, and other media.
  • You can add media directly into articles or news, including remote videos from YouTube or Vimeo via the oEmbed feature in Drupal 8.
  • Configurable editorial workflows are available to your marketing team with the new Content Moderation and Workflows modules.
  • The Views in D8 core lets you add highly configurable content collections to your pages. 
  • It’s easy to create beautiful slideshows and carousels with the help of contributed tools such as Views Slideshow, Juicebox, jCarousel, Owl Carousel, and so on.

Media Library in Drupal 8

Smart content personalization

Individualized, or targeted, content delivery helps marketers reach their audience. You just give the right offer at the right moment to the right person. Drupal 8 offers awesome opportunities to marketers in this field. 

Some great Drupal 8 personalization modules

  • Smart Content allows you to offer a different display based on browser conditions.
  • Smart Content Segments helps you manage groups of these conditions in a handy UI.
  • Acquia Lift Connector unites your content and customer in a drag-and-drop interface so marketers can effectively manage your campaigns in real-time using behavioral factors.
  • Cloudwords for Multilingual Drupal is your assistant in multilingual campaigns with the features of workflow automation and project management.

Acquia Lift Connector Drupal 8 personalization module

Social media campaigns

Marketers know that social networks are amazing campaign boosters. Your SM page and your website can be an invincible marketing team. With D8, their integration is a breeze. 

Marketers will be amazed by a myriad of contributed Drupal 8 modules that will help them to:

  • auto-publish content to social networks
  • invite users to join your social media pages
  • add their icons to the website
  • add sharing buttons
  • analyze the statistics 
  • embed feeds 

These Drupal 8 social integration modules include

and many more. 

Social integration modules in Drupal 8

Let your marketing boost with Drupal 8!

These have been just a few glances at the greatness of Drupal 8 for marketers. Contact our Drupal team to discuss in what other ways D8 can be helpful to your marketing campaigns and your business. 


Our Drupal developers are ready to:

  • build you a Drupal 8 website from scratch
  • migrate your Drupal 7 website to Drupal 8
  • update your minor Drupal 8 version (since some features mentioned above only start from Drupal 8.7)
  • install the needed modules and configure them properly based on your needs
  • customize the existing solutions to add the desired marketing features to your site

Enjoy the benefits of Drupal 8 for marketers!

Aug 07 2019
Aug 07

You've probably heard recently that Drupal 9 is coming. Drupal 8.7 was released in May and Drupal 8.8 is planned for December 2019. At the same time, D9 is becoming a hotly discussed topic in the Drupal world. 

Drupal 9’s arrival perfectly fits into the Game of Thrones’ quote — “Brace yourself, winter is coming.” But do you need to brace for D9? It is promised to arrive easily and smoothly. Still, some important preparations are needed. Let’s review them in this post.

Drupal 9 is coming in June 2020

The year of the D9 release became known back in September 2018. Drupal creator Dries Buytaert announced it at Drupal Europe in Darmstadt. Later on, in December, the exact date arrived — Drupal 9 is coming on June 3, 2020!

What will happen to Drupal 7 and Drupal 8? Both D7 and D8 will reach their end-of-life in November 2021. This means the end of official support and no more updates in the functional and security areas. Some companies will come up with extended commercial support, but it’s far better to keep up with the times and upgrade. All the development ideas and innovations will be focused on “the great nine.”

The Drupal creator explained the planned release and end-of-life dates. In a nutshell, D8’s major dependency is the Symfony 3 framework that is reaching end-of-life in November 2021. Drupal 9 will ship with Symfony 4/5. So the Drupal team has to end-of-life Drupal 8 at that time, but they want to give website owners and developers enough time to prepare for Drupal 9 — hence the June 2020 release decision. 

According to the timing, you need to be on Drupal 9 by By November 2021. In the meantime, you should prepare. 

Preparations for Drupal 9 in the coming

1. How to prepare for Drupal 9 if you are on Drupal 8

Hearing that Drupal 9 is coming, many D8 website owners may say “Hey, we just had an epic upgrade from Drupal 7 to Drupal 8, and here we go again!”.

Keep calm — everything is on the right track. Your upgrade from Drupal 8 to Drupal 9 should be instantaneous. D9 will look like the latest version of D8, but without deprecated code and with third-party dependencies updated (Symfony 4/5, Twig 2, and so on).

Dries Buytaert's quote: we are building Drupal 9 in Drupal 8

There are two rules of thumb regarding the Drupal 9 preparations:

1) Using the latest versions of everything

To have a quick upgrade from Drupal 8 to Drupal 9, you need to stick to the newest versions of the core, modules, and themes. According to Gábor Hojtsy, Drupal Initiative Coordinator, you are gradually becoming a D9 user by keeping your D8 website up-to-date.

Gabor Hojtsy's quote: you become a Drupal 9 user by keeping up to date with Drupal 8.

“The great eight” has adopted a continuous innovation model, which means a new minor version every half a year. Our Drupal team is ready to help you with regular and smooth updates.

2) Getting rid of deprecated code

It is also necessary to keep your website clean from the deprecated code. Deprecated code means APIs and functions that have newer alternatives and are marked as deprecated, or obsolete. 

Any module that does not use deprecated code will just continue working in Drupal 9, Dries said.

Dries Buytaert's quote: without deprecated code websites will be ready for Drupal 9

How can you find deprecated code? Here are a few tools that check everything including custom modules:

  • The command-line tool Drupal Check that checks your code for deprecations
  • The Upgrade Status contributed module that offers a graphical interface to check the modules and theme and get the summary

Many deprecations are very easy to replace. You can always rely on our development team to have a thorough check and cleanup from deprecations. 

2. How to prepare for Drupal 9 if you are on Drupal 7

The best way to prepare for Drupal 9 is to upgrade to Drupal 8 now. Even if this might sound like a marketing mantra to you, it has very practical grounds.

There are plenty of reasons to upgrade and no reason to skip Drupal 8. These are words from Dries Buytaert's presentation

Dries Buytaert's presentation: there are many reasons to upgrade to Drupal 8 now

You will enjoy a wealth of Drupal 8’s benefits for business all the time before 2021. And when Drupal 9 arrives, you will just click and move ahead to it!

Gabor Hojtsy's quote: skipping Drupal 8 does not bring benefits

Don’t worry, despite the immense difference between D7 and D8, the 7-to-8 upgrades are getting easier every day. Developers have studied the D7-to-D8 upgrade path well. In addition, very helpful migration modules have recently reached stability in the D8 core.

Your upgrade to Drupal 8 will depend on your website’s custom functionality and overall complexity. In any case, our Drupal developers will take care of making it smooth. 

So make up your mind and upgrade now — welcome to the innovative path that will lead you further to “the great 9.”

Plan for Drupal 9 with us!

Yes, Drupal 9 is coming. No matter which version of Drupal you are using now, we can help you make the right Drupal 9 preparation plan — and fulfill it, of course. Just contact our Drupal experts!

Aug 05 2019
Aug 05

When deploying changes to a Drupal environment, you should be running database updates (e.g. drush updb, or through update.php) first, and only then import new configuration (which itself is supposedly the result of running the same update hooks on a development environment). The reason for this is that update hooks may want to update configuration, which will fail if that configuration is already structured in the new format (you can't do without updates either; update hooks don't just deal with configuration, but may also need to change the database schema and do associated data migrations). So, there really is no discussion; updates first, config import second. But sometimes, you need some configuration to be available before executing an update hook.

For example, you may want to configure a pathauto pattern, and then generate all aliases for the affected content. Or, you need to do some content restructuring, for which you need to add a new field, and then migrate data from an old field into the new field (bonus tip: you should be using post update hooks for such changes). So, that's a catch-22, right?

Well, no. The answer is actually pretty simple, at least in principle: make sure you import that particular configuration you need within your update hook. For importing some configuration from your configuration sync directory, you can add this function to your module's .install file:

/**
 * Synchronize a configuration entity.
 * 
 * Don't use this to create a new field, use 
 * my_custom_module_create_field_from_sync().
 *
 * @param string $id
 *   The config ID.
 *
 * @see https://blt.readthedocs.io/en/9.x/readme/configuration-management/#using-update-hooks-to-importing-individual-config-files
 */
function my_custom_module_read_config_from_sync($id) {
  // Statically cache storage objects.
  static $fileStorage, $activeStorage;

  if (empty($fileStorage)) {
    global $config_directories;
    $fileStorage = new FileStorage($config_directories[CONFIG_SYNC_DIRECTORY]);
  }
  if (empty($activeStorage)) {
    $activeStorage = \Drupal::service('config.storage');
  }

  $config_data = $fileStorage->read($id);
  $activeStorage->write($id, $config_data);
}

Use it like this:

my_custom_module_read_config_from_sync('pathauto.pattern.landing_page_url_alias');

As you might have seen in the docblock above that function, it is not actually suitable for creating fields. This is because just importing the configuration will not create the field storage in the database. When you need to create a field, use the following code:

/**
 * Creates a field from configuration in the sync directory.
 *
 * For fields the method used in kankernl_custom_read_config_from_sync() does
 * not work properly.
 *
 * @param string $entityTypeId
 *   The ID of the entity type the field should be created for.
 * @param string[] $bundles
 *   An array of IDs of the bundles the field should be added to.
 * @param string $field
 *   The name of the field to add.
 *
 * @throws \Drupal\Core\Entity\EntityStorageException
 */
function my_custom_module_create_field_from_sync($entityTypeId, array $bundles, $field) {
  // Statically cache storage objects.
  static $fileStorage;

  // Create the file storage to read from.
  if (empty($fileStorage)) {
    global $config_directories;
    $fileStorage = new FileStorage($config_directories[CONFIG_SYNC_DIRECTORY]);
  }

  /** @var \Drupal\Core\Entity\EntityStorageInterface $fieldConfigStorage */
  $fieldStorage = \Drupal::service('entity_type.manager')
    ->getStorage('field_storage_config');

  // If the storage does not yet exit, create it first.
  if (empty($fieldStorage->load("$entityTypeId.$field"))) {
    $fieldStorage
      ->create($fileStorage->read("field.storage.$entityTypeId.$field"))
      ->save();
  }

  /** @var \Drupal\Core\Entity\EntityStorageInterface $fieldConfigStorage */
  $fieldConfigStorage = \Drupal::service('entity_type.manager')
    ->getStorage('field_config');

  // Create the field instances.
  foreach ($bundles as $bundleId) {
    $config = $fieldConfigStorage->load("$entityTypeId.$bundleId.$field");
    if (empty($config)) {
      $fieldConfigStorage->create($fileStorage->read("field.field.$entityTypeId.$bundleId.$field"))
        ->save();
    }
  }
}

And, once again, a usage example:

my_custom_module_create_field_from_sync('node', ['basic_page', 'article'], 'field_category');

The function will check whether the field already exists, so it is safe to run again, or to run it for a field that already exists on another bundle of the same entity type.

Note that when using post update hooks, it will be important to create a single hook implementation that applies all required actions for what should be considered a single change, because there are no guarantees about the order of post update hooks. So that would for example constitute:

  1. Create a new field.
  2. Migrate data from the old field to the new field.
  3. Remove the old field.

Hopefully, this helps someone get out of that catch 22. Whatever you do, don't run your config import before your database updates.

Jul 17 2019
Jul 17

What is the latest business forecast for the media and publishing industry? The thunder and lightning of success! This is because Drupal has very useful web solutions for this industry.

In addition to easy content editing in Drupal 8 and other niceties, there are Drupal distributions for media and publishing. They are called Thunder and Lightning, and we will now discuss what they can give you.

What are Drupal distributions?

Distributions are meant to start a website with significant time and cost savings. This is because Drupal distributions are installation kits suited to specific business use cases.

These packages include the Drupal core, a set of contributed modules, specific configuration, and more. Distributions are free and ready to go. They can be customized and extended by development teams to meet your business needs.

Drupal distributions for media and publishing

Thunder and Lightning are very famous Drupal distributions for media and publishing. They sound like a pair of related projects, but they are actually from different creators. Let’s review the details of each of them.

Lightning — Drupal distribution for media and publishing

Lightning is a framework and a distribution in one. It empowers developers to build great authoring experiences. And it allows content editors and publishers to enjoy smooth, handy, and consistent workflows.

The Lightning distribution was developed by Acquia in 2016. It is a lightweight and extensible product provided with detailed documentation and recommendations. Lightning inherits the best Drupal practices and offers a set of modules without being overloaded by extraneous ones.

about lightning drupal distribution

The distribution’s reliability is guaranteed by 60+ automated tests and by Drupal Security Team’s close attention. This makes it much safer to use than a selection of standalone modules.

The project is actively maintained and has seen its 8.x-4.001 version released in June 2019. Lightning is the most downloadable Drupal 8 distribution on drupal.org in general, not only among Drupal 8 distributions for media and publishing.

Distributions Drupal.org Lightning

Key Lightning features for publishers

  • Easy media management

Lightning includes the media management feature with the media library. Content publishers can upload images and videos from a PC or from a URL, save them to the library, or embed them into the content.

  • Flexible editorial workflows

With Lightning, it is easy to streamline content workflows between different user roles in the team. Publishers can manage the existing ones, or create new content approval states.

  • Handy content preview

Editors can enjoy a comprehensive content preview, including images and videos, before submitting it to the public.

  • Drag-and-drop layouts

The handy drag-and-drop tools allow editors to shape their page layouts for different occasions. The layouts are responsive to mobile devices. 

  • API for content sharing

 Lightning has a preconfigured API for exposing content to other applications in the JSON format, so your media website can go multichannel.

  • Headless Lightning subprofile

The subprofile has the same features but also offers an interface for decoupled Drupal setup, which is a hot trend. According to Dane Powell, Senior Technical Architect at Acquia, both Lightning and Headless Lightning are a great choice for this architecture.

key features of lightning drupal distribution

Thunder — Drupal distribution for media and publishing

The Thunder distribution is an out-of-the-box product to be used by professional media websites. On its official page, Thunder positions itself as a CMS (content management system) for professional publishing.

It includes a set of specific modules tailored to the needs of publishers. Similarly to Lightning, Thunder is free and open-source.

about thunder drupal distribution

Thunder was created in 2016 by Hubert Burda Media. In addition to the Thunder Core Team, the project is maintained by partners from the Thunder Coalition such as Nexxt.tv, Acquia, Valiton, Facebook etc. that add their own custom features to it. The distribution’s creation was great news for the Drupal world.

about thunder drupal distribution

And just like Lightning, Thunder is actively supported and has released it 8.x-2.4 version in June 2019.

Key Thunder features for publishers

  • Flexible content creation

Publishers can create more than simple articles by adding elements like images, videos, galleries, Twitter cards, and more with a drag-and-drop tool. Media can be saved for further reuse.

  • Content scheduling

Your content can be scheduled to show on the website at a given date and time or, on the contrary, to stop showing at a given time.

  • Nexx.tv video player

Thunder features a high-performance Nexx.tv video player that allows publishers to control their videos across platforms and devices.

  • Riddle tool for interactive content

There is a Riddle that allows you to create interactive content like quizzes, tests, and so on. This keeps users engaged and drives your traffic.

  • Instant Articles by Facebook

With the Instant Articles feature by Facebook, publishers can create articles that will load instantly on mobile devices of Facebook app users. 

  • The Infinity theme

This is a special theme created for media and publishing websites by InStyle. It allows website to present content and increase user engagement with infinite scrolling.

  • Mobile-friendliness

The distribution allows publishers to work in the admin dashboard from any device. Users can enjoy a modern and flexible front-end design.

key features of thunder drupal distribution

Get the best from Drupal distributions for media and publishing

These have been just a very brief rundown of the Lightning and Thunder capabilities. They both are built according to the best development practices and both can be a great base for your website.

Contact our Drupal development team and we will help you quickly setup a website upon one of these distributions. Let your media and publishing business flourish with a website that reflects its demands!

Jul 12 2019
Jul 12

JSON-RPC is a great Drupal module filling when from a decoupled application you e.g. need to extract or manipulate data in a custom way or more importantly run code in your content providing Drupal installation.

Drupal JSON-RPC

Published on 2019-07-12 at 18:43

Drupal JSON-RPC decoupled

Oftentimes when you design a decoupled application with Drupal as your data provider, you run into some cases, where the data available to you from your e.g. JSON:API is not full. E.g. you want your app user to fetch or manipulate some of the configuration on the backend like the site name. Or even allow your consumer to do administrative tasks such as clearing the cache, adding a permission to a role?

The JSON-RPC module allows you to do just that. Let's have a look on how to use it and create a custom plugin.

What is JSON-RPC and how does it work in Drupal

Wikipedia has a very good first sentence on what JSON-RPC is:

JSON-RPC is a remote procedure call protocol encoded in JSON. It is a very simple protocol (and very similar to XML-RPC), defining only a few data types and commands. JSON-RPC allows for notifications (data sent to the server that does not require a response) and for multiple calls to be sent to the server which may be answered out of order.

The consumer is able to send a request to your Drupal site, which is implementing the JSON-RPC protocol. The consumer passes a JSON-object to the server, specifying

  • the version of the protocol, should be "2.0"
  • which method will be called on the remote machine
  • which parameter should be passed, if any
  • an id, so that the response can be matched properly

Here is an example of such a request from the jsonrpc_core-module:

{
        "jsonrpc": "2.0",
        "method": "plugins.list",
        "params": {
                "service": "plugin.manager.link_relation_type",
                "page": {"limit": 15, "offset": 1}
        },
        "id": "relation-types"
}

The request will be handled by a plugin provided by the Drupal JSON-RPC module, which has to annotate an id (corresponding to the "method"-key in the request), parameters (mapped to the "params"-key), access restriction (a Drupal permission) and a description.

The discovered class will call its' execute-method, where the provided parameters will be passed. Each parameter can be annotated with a key of schema (where it will be passed as is) or factory (which allows the parameter to be processed and transformed through a class defined by the factory key). Finally the output of the "execute" is being handled by the outputSchema-method, so that the JSON-schema of the response is defined correctly.

The project page of the module has a Postman collection with some examples for requests for the plugins provided by the jsonrpc_core module, definitely with checking these out.

The response of the request above would look something like this (in this example it is cut-off for simplicity):

{
    "jsonrpc": "2.0",
    "id": "relation-types",
    "result": {
        "add-page": {
            "class": "Drupal\\Core\\Http\\LinkRelationType",
            "uri": "https:\/\/drupal.org\/link-relations\/add-page",
            "description": "A page where a resource of this type and related types can be created.",
            "provider": "core",
            "id": "add-page"
        },
        ...
        "alternate": {
            "class": "Drupal\\Core\\Http\\LinkRelationType",
            "description": "Refers to a substitute for this context",
            "reference": "[http:\/\/www.w3.org\/TR\/html5\/links.html#link-type-alternate]",
            "provider": "core",
            "id": "alternate"
        }
    }
}

Create own plugin - allow configuration to be imported via a JSON-RPC call

Let's make our hands dirty and create our own plugin that will make Drupal import the active configuration, basically the same as running drush cim -y from the command line. We need a custom module for that, let's call it drupov_jsonrpc. Add the basic drupov_jsonrpc.info.yaml file:

name: Drupov JSON-RPC
description: Drupal 8 JSON-RPC plugin demo module.
package: Custom
core: 8.x
type: module

With that the module can be enabled. Let's create our plugin - for that we need a file src/Plugin/jsonrpc/Method/ConfigImport.php. The ConfigImport class will need to extend JsonRpcMethodBase and provide its' annotation - no params needed to be provided for our action:

/**
 * Import config.
 *
 * @JsonRpcMethod(
 *   id = "config.import",
 *   usage = @Translation("Config import."),
 *   access = {"administer site configuration"},
 * ),
 */
class ConfigImport extends JsonRpcMethodBase {

The outputSchema is simple as we return only a message to the consumer. Our execute() method will look like this (logic is borrowed from core/lib/Drupal/Core/Config/Importer/ConfigImporterBatch.php)

  /**
   * {@inheritdoc}
   */
  public function execute(ParameterBag $params) {
    $storage_comparer = new StorageComparer($this->syncStorage, $this->activeStorage);

    $config_importer = new ConfigImporter(
      $storage_comparer,
      $this->eventDispatcher,
      $this->configManager,
      $this->lock,
      $this->typedConfigManager,
      $this->moduleHandler,
      $this->moduleInstaller,
      $this->themeHandler,
      $this->getStringTranslation()
    );
    if ($config_importer->alreadyImporting()) {
      $this->message .= $this->t('Another request may be synchronizing configuration already.');
    }
    else {
      try {
        $sync_steps = $config_importer->initialize();
        foreach ($sync_steps as $sync_step) {
          $config_importer->doSyncStep($sync_step, $context);
        }
        $this->message = $this->t( 'The configuration was imported successfully');
      } catch (ConfigImporterException $e) {
        $this->message .= $this->t('The configuration cannot be imported because it failed validation for the following reasons: ');

        foreach ($config_importer->getErrors() as $message) {
          $this->message .= $message;
        }
      }

    }

    return $this->message;
  }

  /**
   * {@inheritdoc}
   */
  public static function outputSchema() {
    return ['type' => 'string'];
  }

You can find the full code at this GitHub-repository. Enable the module in your Drupal installation, make some changes to the config (e.g. change the site name) and send a POST-request to /jsonrpc-route of your Drupal site.

{
        "jsonrpc": "2.0",
        "method": "config.import",
        "id": "config.import"
}

That's it. Hopefully this will be useful when you need to make your decoupled Drupal backend perform a task that is not tied to the entity eco-system.

You can find the full module in this GitHub repo.

Jul 10 2019
Jul 10

At last month's DrupalJam XL in Utrecht, the Netherlands, I gave Gabor Hojtsy's presentation on the state of Drupal 9. It was recorded - thanks DrupalJam organization! - so here is the video. You might also want to view Gabor's own presentation from DrupalCamp Belarus.

You'll need to turn up the audio, because it seems that it was recorded using the camera, not the fancy microphone I'm wearing.

[embedded content]

Jul 04 2019
Jul 04

Developing a website for a higher education institution may be tough, as universities have plenty of departments and branches. Despite the fact that each department has its own site with specific content, all of them have to function under the same CMS and be closely connected. How do you know which CMS is right for your university website? Let’s sort things out!

Drupal vs WordPress for higher education institutions

The most popular choices for higher education institutions websites are Drupal and WordPress. However, WP lacks functionality, security, and accessibility necessary for a complicated higher education institution platform.

Did you know that 71 out of the top 100 universities, including Harvard University, University of Oxford, and Yale, use Drupal for their websites? It’s not surprising if you are familiar with all of Drupal benefits.

Today, the team at Drudesk explores the benefits of Drupal for university website development.

Drupal’s benefits for university websites

Drupal offers a bunch of tools and features necessary for a complicated university website development. Here are the main ones:

  • Accessibility

Caring about accessibility for users with physical disabilities is a must. Drupal 8 possess a number of features that support website accessibility standards. They help screen readers understand web pages, add alt text for images, take care of fonts and colors, and much more.

Note that you can always contact Drudesk for a website accessibility audit to see if your website is optimized for people with impairments.

  • Information security

University websites contain a lot of valuable content that should be kept safe. Luckily, Drupal is one of the most secure CMS, as it offers regular core, modules, and security updates. With Drupal you can be sure that your platform maintains the highest level of security.

  • User roles and permissions

University websites are visited by professors, students, administration staff, and much more. All of them need different permissions for creating and editing website content based on their roles at the university. Drupal offers out-of-the-box user roles, as well as a number of contributed user access modules that will help you easily configure roles and permissions on the site.

  • Multilingual functionality

Drupal 8 possess a multilingual feature out-of-the-box. This is extremely useful for higher education institutions, as students all over the globe will access the website. Drupal translates all information available, from content to interface, and offers a choice of 100+ languages to install on websites.

  • A multisite approach

Multisiting is usual for higher education institutions, as they have different departments that require sister domains. Things become easy with the Drupal multisite feature that lets you have as many websites as you need on the same Drupal installation. It provides unlimited opportunities for sharing content, managing the settings, and giving access between multiple sites.

  • Easy content creation and editing

Higher education websites update and add content regularly. Drupal 8 is a solution for content creators, as it possesses a number of built-in features for easy content creation, from posting to editing.

  • Hundreds of themes and templates

Drupal offers various design templates that are pretty much effortless to use while ensuring consistency across an entire institution.

Great examples of higher education websites built in Drupal

Harvard University

Harvard university website on Drupal

Rutgers University

Rutgers University website on Drupal

Stanford Graduate School of Business

Stanford Graduate School of Business website on Drupal

University of Oxford

University of Oxford website on Drupal

University of Colorado 

University of Colorado website on Drupal

Develop a website for a higher education institution on Drupal!

Take a look at the Maryland Global University, a website created by our web development partners: InternetDevels agency. It is supplied by the eCommerce functionality for buying online courses, as well as Moodle integration — a well-known LMS (learning management system).

Maryland Global University website on Drupal by InternetDevels

Don’t hesitate over the choice of CMS for university website development anymore — Drupal is definitely the solution! Drop us a line regarding your project and we’ll immediately get back to you to discuss all the details of the project.

Jun 26 2019
Jun 26

Since React 16.6 we have the possibility to load components on demand. This new feature is provided by the new method React.lazy(), which is part of the new Suspense API (WIP) of React.

Feeling lazy

Published on 2019-06-26 at 17:52

React.js Drupal decoupled React.lazy() Suspense API

Why would this be important?

Modern bundling tools like webpack are great, but there is a small caveat when using them, especially in big React applications - which most of them in the end are - the code packaged and loaded in the browser is synchronous. So on an initial page load your browser ends up loading a lot of code, which might never get executed at all. A very simple example with React is a component, which should be rendered only when a certain action on the frontend happens - up until now the code for that component is packaged and served to the browser initially. Components can be very different though - some of them are small, e.g. an <li>-item that receives its content via a prop - not a big deal. But imagine you have one that makes a call to an API and that query is quite long - on top of that a component can also have several methods in it that are needed to modify its’ output based on changing state. But that might never happen?

React.lazy() and Suspense API

Part of the new features shipped by the React.js team with the 16.6. Update allows us to optimize this loading process. We’ll create a very simple example with a React app and a Drupal backend to illustrate that.

Preparations for frontend and backend

Let’s make a folder for our frontend and backend apps:

mkdir react-lazy-suspense-with-drupal
cd react-lazy-suspense-with-drupal

Once inside the main folder, create the frontend (use create-react-app) and backend (use the composer template for Drupal projects) apps. I normally put them in separate “frontend” and “backend” folders in the top-level-folder (in this case the just created “react-lazy-suspense-with-drupal”).

Frontend preparations

Make sure to have at least React version 16.6 in the package.json file of the frontend app. As we’ll use React hooks in our example, it’s actually 16.7 (hooks came with 16.7), but the same demo can be done with normal class-based components:

  "dependencies": {
...
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
...
  },

We’ll be doing some data fetching from out Drupal backend, so let’s also get axios for that:

npm install axios

Backend preparations

Our backend will consist of Drupal core and let’s grab the graphql module to provide data from Drupal. Install the just created site as usual first. We’ll use the 3.x version of it for simplicity, as it’s shipping with full Drupal entity schema and we’ll show Drupal articles in our frontend in the example. Download and enable the module:

composer require drupal/graphql:3.x
drush en graphql_core

Note - you’ll need to setup the CORS settings for Drupal, so that the frontend can receive data for it on it’s own URL, see https://drupal.stackexchange.com/questions/245903/how-do-i-set-up-cors for more information on that.

We can now create some articles in Drupal. I am lazy (sometimes and it fits the current context of this article) and let devel_generate do that for me.

Creating our to-be-lazy-loaded-component in the React app

Let’s start with the component that will get loaded on demand. Create a file frontend/src/components/Articles.js. It can look something like this:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function Articles() {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const result = await axios(
        'https://react-lazy-suspense-with-drupal.lndo.site/graphql?query={nodeQuery(limit:5){entities{entityId,entityLabel}}}',
      );

      setData(result.data.data.nodeQuery.entities);
    };

    fetchData();
  }, []);

  return (
      <ul>
        {data.map(item => (
            <li key={item.entityId}>{item.entityLabel}</li>
        ))}
      </ul>
  );
}

export default Articles;

First things first: you’ll probably use ApolloProvider to wrap your GraphQL query instead of passing it as a parameter, if done properly. But we want to focus on something else here.

OK, nothing too fancy with this component. We use useState to define out data constant and setData-callback (React hooks are really great!) and fetch data from Drupal with axios in the useEffect-hook (yes React hooks are indeed great!). In the end we return a list of the fetched data. At the end this is the component we want to load lazily.This is admittedly not a huge component, but in the real world a component can easily grow into such that loads/imports other components, each with its own logic queries etc.

Let’s jump to the main part of this demo now. We’ll put the code that will lazy-load our just created component in the App.js file of the React-app:

import React, { useState, Suspense } from 'react';
const Articles = React.lazy(() => import('./components/Articles'));

function App() {
  const [articlesVisible, setArticlesVisible] = useState(false);

  return (
    <React.Fragment>
      {articlesVisible ? (
        <Suspense fallback={<div>Loading...</div>}>
          <Articles />
        </Suspense>
      ) : (
        <button onClick={() => setArticlesVisible(true)}>Show articles</button>
      )}
    </React.Fragment>
  );
}

export default App;

Note that we load Suspense from the react-package at the top. Right after that we tell React that our Articles component will be lazy-loaded. For that to happen we return an import statement for the component in the lazy()-function. Up until now we would have imported it as we do with all our components in React normally, e.g. import Articles from './components/Articles'; and webpack would’ve bundled the components’ code together with all the rest.

With that we’re ready with our demo. To visualize the difference in the loading process check out the full filesize of the code without

without-lazy-suspese Network tab showing component loaded WITHOUT React.lazy()

and with the React.lazy() implementation:

with-lazy-suspense Network tab showing component loaded WITH React.lazy()

With lazy-loading you’ll notice that we have a smaller initial file-size - equal to the size of the bundle.js, produced by webpack - but now without the additional code included in our Article.js-component. This code get shipped to the browser only after the condition to show it is triggered by the user, exactly as expected.

This is pretty neat. If you want to play around with this, you can get a copy of the code over at this repository. Thanks for sticking until the end!

Jun 26 2019
Jun 26

Drupal 9 is coming — its arrival is planned for June 2020. So while the world continues enjoying Drupal 8’s benefits, it’s also time to start getting ready for Drupal 9. What does it mean and how should you prepare? We are discussing this today in our blog post.

Easy upgrades to Drupal 9 as a huge bonus

All website owners and developers can enjoy an amazing bonus related to Drupal 9. Thanks to efforts from the Drupal community, upgrades from Drupal 8 to Drupal 9 are made easy! They shouldn’t take more time than trivial updates between minor versions (for example, from Drupal 8.6 to Drupal 8.7).

As Dries Buytaert wrote in his State of Drupal presentation, when sites move from Drupal 8 to Drupal 9, content is already ready and the code continues to work. Amazing!

Excerpt from Dries Buytaert's State of Drupal presentation

But, as you might have noticed, there is one remark in this illustration by Dries. Easy upgrades to Drupal 9 will be available if websites are not using deprecated code. Let’s see in more detail what this means and how to fulfill this condition.

Getting ready for Drupal 9: cleaning up deprecated code

To be ready for Drupal 9, all websites should cleaned up from deprecated Drupal APIs and functions (outdated ones that have more modern alternatives).

Since Drupal core and contributed modules are maintained by their developers, there is a big chance they will take care of the cleanup. So it is necessary to keep the core and contributed modules up-to-date as part of preparation for Drupal 9. However, a good deprecation check is also highly recommended.

When it comes to custom modules and themes developed specifically for your website, they should be properly checked for deprecations and updated.

To discover deprecated code, there are useful tools in Drupal. Among them:

What to expect from the module readiness and the amount of work needed? Dwayne McDaniel of Pantheon checked almost 7,000 of the most popular contributed Drupal 8 modules with the Drupal-check tool. He found that almost half of the modules had no Drupal 9 compatibility issues, while 35% had 5 issues or less.

At MidCamp 2019, issues for 300 modules were additionally opened, so the work is already being done on them. Most modules just need an easy fix. All this is stated in the Drupal 9 slides by famous Drupal contributor Gábor Hojtsy.

How Drupal contributed modules are ready for Drupal 9

Dries Buytaert also says that many deprecations are just a matter of “find and replace” and he tried this on his own website.

So don’t worry — the cleanup work as part of getting ready for Drupal 9 shouldn’t take much time. Our Drupal team is always ready to help you check and clean your website from deprecated code.

What about Drupal 7?

Drupal 7 website owners can upgrade to Drupal 8 now or wait for Drupal 9. However, the first option looks much more beneficial. See why.

If they upgrade from Drupal 7 to Drupal 8 now, they can start enjoying what Drupal 8 has to offer (and that’s a huge piece of pie — just check out the basic Drupal 8’s benefits for business). And then they will just switch to Drupal 9 in a snap of a finger. Only one big move will ever be needed.

“Once you are on the Drupal 8 track, you will never have to change tracks again,” Dries writes in the presentation, comparing migration to changing railway tracks.

As you can see from his great illustrations, the Drupal 8 track leads to Drupal 9 and then to Drupal 10 stations. At the same time, Drupal 7 and especially Drupal 6 tracks have no future.

Dries Buytaert illustrating the future of Drupal versions

Dries Buytaert illustrating the future of Drupal versions

In addition, the upgrade path from Drupal 7 to Drupal 8 is very well documented, tried by most developers, and has been improved a lot recently. Useful migration modules have become stable in Drupal 8 core, so it is much easier to migrate content and configuration.

You will definitely benefit from moving to Drupal 8, and Drudesk team is ready to help you. Change the track if you are still with Drupal 7 and get on the train to the future!

Drupal 9 is coming — entrust us with getting your site ready

Entrust our Drupal support team with preparing your website for the future. Both cleanups and migrations are Drudesk’s area of expertise. We strive to make websites better, cleaner, more modern — and ready for Drupal 9!

Jun 12 2019
Jun 12

There are many beautiful words you can use to tell your customers that your website is trustworthy, reliable, and transparent. But one small widget can say it better that a thousand words.

So let us introduce the UpTime Widget Drupal module. See how it could help you always stay aware of your website uptime, build customer trust, and stand out from competitors.

Module maintained by our developers

Before we move on, we are especially happy to mention that the UpTime Widget Drupal module is maintained by our guys.

Knyshuk.vova is the owner of the module. Its creator Lolandese transferred the ownership to him in accordance with Open Ownership Pledge. Vladimirrem and ApacheEx are maintainers of the module who also make important commits.

These are Drupal developers from Drudesk and Drudesk’s parent company — InternetDevels, which is also listed as supporting organization on the module’s page.

What UpTime Widget Drupal module does

The UpTime Widget module connects your website to the popular free uptime monitoring service — UpTimeRobot.com.

It shows your website uptime (the percentage of time that your website is available to visitors online). Ideally, it should be 100%, although this figure may be a little bit lower in reality.

Your website uptime figure appears in the form of a handy widget to be placed anywhere on your website as a Drupal block. It can also optionally show a configurable copyright notice.

Uptime widget for Drupal website

Uptime widget for Drupal website

The UpTimeRobot service is able to monitor your website uptime every 5 minutes or at an interval you choose. You can get notifications about it by:

  • email
  • SMS
  • Twitter
  • RSS
  • push notifications for iPhone or iPad.

How the UpTime Widget module works in more detail

Getting your keys on the UptimeRobot service

First, we will need to register our website from the UptimeRobot.com service and get the API key and the monitor ID. We need to make a few easy steps:

  • sign up, activate your account, and log in at UptimeRobot.com
  • add a new monitor of the HTTP(s) type, give our website a name, and submit its URL

Register website at UpTime Robot service

The UptimeRobot service has plenty of interesting things like informative dashboards or detailed notification settings. We can come back here any time, but now let’s grab the API key and monitor ID and move on to our Drupal 8 website.

Installing and configuring the UpTime Widget module

The UpTime Widget module can be installed on the Drupal 8 website in any way you prefer. Although it is using a third-party service, installation with Composer is not obligatory.

When the module is installed and enabled, its settings appear at admin/config/system/uptime_widget. Let’s run through some of them.

  • There are two key required fields where we need to enter the previously received API key and monitor ID.
  • The “decimal separator” and “scale” fields have nice defaults, but we can play with the ways our website uptime digits are displayed.
  • The monitoring interval and the refresh interval fields also have sensible defaults. But we can choose how often the website uptime should be checked and how often Drupal should receive this information.

Configuring UpTime Widget Drupal module

Configuring the copyright notice

The website uptime widget by default comes with the copyright widget, which can optionally be disabled. Hiding or showing the copyright is also available in the block configuration, which will be described in the “Configuring the Uptime block” part.

The module’s settings page at admin/config/system/uptime_widget lets us configure how the copyright will look. It offers:

  • several options for the copyright notice
  • the option to specify the year that our domain was first online
  • the option to write a custom “Prepend text” instead of “All rights reserved.”

Configuring copyright notice of Drupal uptime widget

Placing and configuring the Uptime block on the website

It’s now time to place the uptime widget block on our Drupal website. In Structure — Block Layout, we choose the theme region (for example, Footer first), click on it, find the Uptime block in the list of blocks, place block, and save the blocks.

Placing UpTime Widget as block on Drupal website

We can configure the block to our liking — either on the Block Layout page or by clicking the “quick edit” pencil near the block on the website.

We can leave or hide its title by checking or unchecking “Display title,” configure visibility for specific roles, specific pages or content types, and so on.

Configuring UpTime Widget as Drupal block

We can also choose to show both the uptime and copyright widgets, or only one of them.

UpTime and copyright widgets Drupal

More features to come in the future

Our guys have many plans about the module’s improvements in version 8.2. Here are at least some of them:

  • Uptime check notifications should be configurable directly from the Drupal website, which is for now only possible on the UpTimeRobot service.
  • The Uptime information should be included into the “Reports” page on the Drupal dashboard.
  • Public Status Pages, or detailed boards about uptime information, should be integrated into Drupal.

UpTime Robot service dashboard

Get yourself a website uptime widget

Show your visitors they can rely on you all the time! And you can always rely on our Drupal support team if you need any help in:

  • installing and configuring the UpTime Widget Drupal module
  • customizing its look on your website
  • creating another custom Drupal module in accordance with the customer’s requirements

Stay reliable and build your customer trust!

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