Porting Drupal 7 module to Drupal 8 on the example of Cookiec

13.12.2016

Time has already passed since the premiere of Drupal 8. New projects and modules are released all the time, and there is an ever-increasing number of projects compatible with version 8.x at drupal.org. Sadly, these versions are often still unstable and filled with various bugs. As of today, the number of additional modules available for Drupal 8 is around 2,250, compared to 12,400 Drupal 7 modules. It is immediately visible that the range of ready-made solutions is far more narrow in the case of the new generation, compared to the older one. However, even though in the case of advanced projects, writing them from scratch might be pointless, in the case of smaller add-ons, we can try to port the entire module or its interesting functionalities to version 8.x. In this guide, we are going to port a module used by us to display the cookies disclaimer on our website to be used with Drupal 8.

This is what the file structure of v. 7.x looks like. The module is fairly simple, as it contains a custom CSS file, a JavaScript, two templates, one included .inc and the standard .info and. module files.
In order for the script to be visible by Drupal 8, we are going to need an .info.yml file. Let us start with this one. In D8, it is the only file required for the module to be seen by the system.

1. Info files:

Drupal 7

cookiec.info

name = CookieC
description = This module aims at making the website compliant with the new EU cookie regulation
core = 7.x

Drupal 8

The files are fairly similar – as you can see, the main difference here is the file format. Since Drupal 8 uses YML files, the file needs to have an .info.yml extension. Additionally, we also have to add type: because skins are using similar syntax, in our case this is going to be type: module. Additionally, in this file, we can add ‘configure:’ – a routing hook to the configuration page. However, we are going to discuss routing in the next part. It is worth mentioning that – just like in Python – indentations in the code are crucial. After purging the cache, the module should be already visible on the list.

2. .module file and hooks

Let’s now see what can be found in a D7. module file. Our module uses the following hooks/functions:

The *.routing.yml file contains the name of the routing – cookiec.render_cookiec.Path: URL address, allowing us to access a given functionality; as in D7 we can also use dynamic paths, such as for example: path: 'example/{user}', in this case it won’t be needed, since our module displays only a static page.defaults: _controller: '\Drupal\cookiec\Controller\Cookiec::renderPage’ at /cookiec content will be displayed, returned by Cookiec class using renderPage() method. We will write about this in detail while creating /cookiec. static page.Requirements: We are going to add access permissions in _permission: access content.
We should create all the classes and methods assigned to our routings at once in order to avoid displaying errors.
We are going to create a simple “Hello World” example. Let’s start by creating a Cookiec.php file in /src/Controller:

The name of the cookiec.settings routing is going to be placed in the info.yml file (configure: cookiec.settings), thanks to which the module configuration button will redirect us to this form.

5. Hook_init migration

Hook_init, which in D7 started every time the page loaded was removed in D8. In order to get a similar functionality, we are going to use Events, specifically EventSubscriber.
In order to create EventSubscriber in Drupal 8 we are going to need a service. We create service just like other .yml files:
Add the following to cookiec.service.yml:

In order for our service to be an Event Subscriber, we need to create a class implementing the interface – EventSubscriberInterface. In order for it to work correctly, we are going to create three methods:
in src/EventSubscriber/CookiecSubscriber.php

Load the module settings in our constructor, which will be later passed to the JavaScript.
In order for our event to work, we have to add the getSubscribedEvents() method, put in the name of the method (showCookiecMessage) which will be called and the weight (20). We can use weight to set up the order of the events.

6. Adding JS and CSS files

Our next step will be transferring over our JS and CSS files – in our case they are going to be left almost without any significant changes. Instead, we are going to focus on loading them while executing our code.
If we want to add external JS or CSS files to our module, we can create a file named module.libraries.yml, in our case this is going to be cookiec.libraries.yml

Our module does the majority of its magic client-side. To work properly, our script requires sending several parameters. Settings such as height, width, the displayed text or position are sent to drupalSettings array in JS.

7. Configs

Another big change in Drupal 8 is the use of config files. These are also YML files, the goal of which is to facilitate synchronisation of settings, variables, and other data saved in the database between environments.
You can read more about this subject here: https://www.drupal.org/docs/8/configuration-management/managing-your-sites-configuration
The D8-compatible version of our module uses configs to store the settings of our window and to load the default settings during installation. After placing the config file in config/install folder, it is going to be automatically loaded on module installation, so we are not going to use hook_install anymore.
Our config/install/cookiec.settings.yml file”

8. TWIG templates

One of the most significant changes after moving from D7 to D8 is the fact that D8 did away with PHP templates in favour of TWIG (http://twig.sensiolabs.org/). This is quite an extensive topic in itself, so we are probably going to write a separate article just about it. Right now, the main takeaway for us is that we cannot use PHP functions anymore, and the logic is limited to simple loops and conditions.
Our Drupal 7 module has two templates:cookiec-agreed.tpl.php
cookiec-info.tpl.php

We are going to start with changing the names by replacing the extension with xxx.html.twig.
PHP tags are not parsed in .twig files, so we will have to adapt all functions and comments to the TWIG format.

Comments:

If we want to preserve old or add new comments, we have to replace the PHP tags with {# .... #}.

<#
/**
* @file
* This is a template file for a pop-up informing a user that he has already
* agreed to cookies.
*
* When overriding this template, it is important to note that jQuery will use
* the following classes to assign actions to buttons:
*
*
* Variables available:
* message Contains the text that will be display within the pop-up
* hide – destroy the pop-up
* more – link to an information page
*/
#>

Printing the variable values

We can print the variable by placing our variable in brackets like this: {{ variable }}. Our module has three variables:
message, hide, more – they contain translated strings. Adding {{ message | raw }} will cause the html to be rendered in its pure form, without for example replacing . < > into &lt; &gt; .

Sending data to TWIG

As you can see, TWIG offers great capabilities. However, in order for our variables to be seen in our TWIG, we have to get them there.
In our example, we have to save the content of the parsed TWIG to the variable and send it to the JS array. We can do this like that:
First, we collect the variables to be used in our TWIG:

However, you will rarely use this method while working with Drupal 8. Most often you will use other methods, like overwriting the standard templates using Twig Template naming conventions.
Blocks:
1. block--module--delta.html.twig
2. block--module.html.twig
3. block.html.twig
Nodes:
1. node--nodeid--viewmode.html.twig
2. node--nodeid.html.twig
3. node--type--viewmode.html.twig
4. node--type.html.twig
5. node--viewmode.html.twig
6. node.html.twig
etc.
Then put the custom templates to our theme/templates folder.
There is also a more advanced method to do the same thing – adding files directly to the modules using hook_theme,

9. Summary

All functionalities were ported and are now fully compatible with Drupal 8.x. The module works perfectly and is used by us in several projects.
You can download the project from GitHub:https://github.com/droptica/cookiec/
Leave a comment below if you have any questions or issues.
Summing up our short article: The changes between D7 and D8 are significant, and this is only a small part of the vast scope of innovations and new capabilities offered by our new CMS. If you want to further expand your knowledge about D8 and other tools useful for designing web applications, give us a like on Facebook, where we share our tutorials, guides, and various interesting stuff from the industry. You can also take part in Drupal Day and the Drupal Camp! New content is also coming soon to our blog!

Get blog updates in your inbox!

Sign up for out newsletter and get e-mails of stories like this.

Your name

Your e-mail address

By Subscribing to our newsletter you agree for terms and conditions

By sending the form You consent to process Your personal data by DROPTICA Sp. z o.o. based in Wrocław ul. Duńska 9 and to entrust data to subjects cooperating with DROPTICA Sp. z o.o. for processing purposes. Submission of data is voluntary, however, lack of consent for personal data processing makes it impossible to answer your question. You have the right to access your personal data and correct it.