سیاره دروپال

Drupal.org - aggregated feeds in category Planet Drupal
Subscribe to خوراک سیاره دروپال

I presented Just Keep Swimming! Or, how not to drown in your open source project at DrupalCon Baltimore 2017, as part of the Being Human track. Below is a text summary of the presentation (along with the associated slides).

(I will also add a link to the video of the presentation once it's finished uploading.)

Hi, I'm Jeff Geerling, known most places around the Internet as geerlingguy. I've been involved with the Drupal community for almost nine years, and the Ansible community for four. I work for a company named Acquia, one of the largest Drupal service providers, and I write a lot (mostly about open source software), and automate a lot of things (mostly using Ansible).

DrupalVM is a tool created by Jeff Geerling that “makes building local Drupal development environments quick and easy” for Drupal. It is built using Vagrant and provisioned with Ansible. Since it uses Ansible, it also provides a means to support a production environment deployment. This allows for a repeatable and determinable environment when developing and deploying to remote servers.

In fact, I currently use DrupalVM to power a Drupal Commerce 2 environment that I run locally and in production. The production environment is updated using continuous deployment via CircleCI. The wonderful roles created by Jeff Geerling and his playbook in DrupalVM handle my production deployment.

Want the tl;dr, skip to bottom for the example.

Setting up DrupalVM within your project

First things first, you’ll need to use DrupalVM. In this example we will add DrupalVM as a project dependency, using Composer. This is important. It ensures that any developer using this project, the CI/CD environment, and the final destination all have the same version of files. It also makes it easier to manage and receive upstream fixes.

For my project I followed Jeff’s blog post Soup to Nuts to configure DrupalVM and setup my DigitalOcean droplet to be my production target. You might want to read that over if you have yet to see how DrupalVM can go to production. I won’t copy those steps here, I’ll show how you can get CircleCI to deploy your DrupalVM configuration to a remote host.

See the article for full details, or my example linked later. For now I’ll do a quick review of some basic config.

The inventory file:

[drupalvm] ansible_ssh_user=drupalvm

The config.yml file:

drupal_domain: "example.com" vagrant_hostname: "{{ drupal_domain }}" apache_vhosts: - servername: "{{ drupal_domain }}" documentroot: "{{ drupal_core_path }}" extra_parameters: "{{ apache_vhost_php_fpm_parameters }}"

The vagrant.config.yml file:

# Note, {{ drupal_domain }} overridden for Vagrant to use local.* prefix. drupal_domain: "local.example.com" The prod.config.yml file: drupal_deploy: true drupal_deploy_repo: "git@bitbucket.org:organization/repo.git" drupal_deploy_dir: "/var/www/drupal"

Those are the only tidbits in my production configuration. I treat the config.yml as primary with specific non-production overrides in vagrant.config.yml.

Adding Circle CI

NOTE! You’ll need to be able to deploy from CircleCI to a remote server, which means adding SSH permissions. With CircleCI you must create a key on your server and give the private key to project configuration.

Okay! So DrupalVM is running, you have accessed your site. Now, let’s run this sucker with CircleCI to do testing and deployment. Create a circle.yml file and let us walk through writing it.

First, we need to specify what language we’re using. In this case, I am using a PHP 7.0 image.

machine: php: version: 7.0.7 Defining dependencies

Next we want to set up our dependencies. Dependencies are things that we will need to actually run our tests, and they can be cached to speed up future runs. I’ll annotate specific steps using comments within the YAML.

  # Cache the caches for Composer and PIP, because package download is always a PITA and time eater.
    - ~/.composer/cache
    - ~/.cache/pip
    # Install Ansible
    - pip install ansible
    - pip install --upgrade setuptools
    - echo $ANSIBLE_VAULT_PASSWORD > ~/.vault.txt
    # Disable xdebug (performance) and set timezzone.
    - echo "date.timezone = 'America/Chicago'"  > /opt/circleci/php/7.0.7/etc/conf.d/xdebug.ini
    # I save a GitHub personal OAuth token for when Composer beats down GitHub's API limits
    - git config --global github.accesstoken $GITHUB_OAUTH_TOKEN
    - composer config -g github-oauth.github.com $GITHUB_OAUTH_TOKEN
    - composer install --prefer-dist --no-interaction

Running tests

Before deploying anything to production or staging, we should make sure it does not deploy broken code.

test: pre: # Containers come with PhantomJS, so let's use it for JavaScript testing. # We specify it to run in background so that Circle CI saves output as build artifacts for later review. - phantomjs --webdriver=4444: background: true # Sometimes the test script can get cranky when this directory is missing, so make it. - mkdir web/sites/simpletest # User the PHP built-in webserver for tests, also run in background for log artifacts. - php -S localhost:8080 -t web: background: true override: # Run some tests - ./bin/phpunit --testsuite unit --group commerce - ./bin/phpunit --testsuite kernel --group commerce - ./bin/behat -f junit -o $CIRCLE_TEST_REPORTS -f pretty -o std Saving artifacts

In the event that our tests do fail, it would be great to see additional artifacts. Any process that had background: true defined will have its logs available. Adding the following lines will let us access HTML output from the PHPUnit Functional tests and any Behat tests.

general: # Expose test output folders as artifacts so we can review when failures happen. artifacts: # Folder where Functional/FunctionalJavascript dump HTML output - "web/sites/simpletest/browser_output" # Folder where Behat generates HTML/PNG output for step failures - "tests/failures" Setting up deployment

Now, it is time to tell CircleCI about our deployment process. Nothing too magical here. We are simplify defining that when the master branch passes to run a specific command. This command will load our production config and run the DrupalVM provisioning playbook on our production server. We specify the drupal tags to limit the scope of deployment.

deployment: prod: branch: master commands: # Specify DrupalVM environment and fire off provisioning. # DRUPALVM_ENV specifies which *.config.yml to load. - DRUPALVM_ENV=prod ansible-playbook \ -i vm/inventory \ vendor/geerlingguy/drupal-vm/provisioning/playbook.yml \ # Points to directory containing your config.yml files. -e "config_dir=$(pwd)/vm" \ --sudo --tags=drupal # I exported my Ansible user sudo password to environment variables to make provisioning work. --extra-vars "ansible_become_pass=${ANSIBLE_VAULT_PASSWORD}"

If your tests fail then the deployment will not run.


Want to see an example of the full config? See my

I have been working with Turner for the past twelve months as part of the Draco team (Drupal Application Core), who maintains Drupal 8 modules used by TV channels such as NBA, PGA, or TBS. Once brands started to use our modules, it was mandatory for us to improve testing coverage and monitoring. By that time, we had unit tests, but there was still a long way to go to get to a point where we could feel safe to merge a given pull request by looking at the code and the test results in Jenkins. This article explains our journey, including both the frustrations and successes implementing testing coverage in Drupal 8.

General structure of a test

A test tests something. Yes, it may sound trivial, but I want to use this triviality to explain why there are different types of tests in Drupal 8 and how they achieve this goal. Every test has a first step where you prepare the context and then a second step where you run assertions against that context. Here are some examples:

Context Tests I am an editor who has created a page node. When I open the full display view, I should see the title, the body, and an image I am visiting the homepage. There should be a menu with links to navigate to the different sections of the site, plus a few blocks promoting the main sections. I am an authenticated user who has opened the contact form. Some of the fields such as the name and email should be automatically set. Form submission should pass validation. A confirmation message is shown on success.

The assertions in the Tests column verify that the code that you have written works as expected under a given Context. To me, the end goals of tests are:

  • They save me from having to test things manually when I am peer reviewing code.
  • They prove that a new feature or bug fix works as expected.
  • They check that the new code does not cause regressions in other areas.

Having said that, let’s dive into how we can accomplish the above in Drupal 8.

Types of tests available

Depending on what you want to test, there are a few options available in Drupal 8:

  • If you want to test class methods, then you can write Unit tests.
  • If you want to test module APIs, then your best option is to write Kernel tests.
  • If you want to test web interfaces (I call these UI tests), then you have a few options:

In the following sections we will see how to write and run each of the above, plus a few things to take into account in order to avoid frustration.

Unit tests

Unit tests in Drupal 8 are awesome. They use the well known PHPUnit testing framework and they run blazingly fast. Here is a clip where we show one of our unit tests and then we run the module’s unit test suite:

Videos require iframe browser support.

The downside of Unit tests is that if the class has many dependencies, then there is a lot that you need to mock in order to prepare the context for your test to work, which complicates understanding and maintaining the test logic. Here is what I do to overcome that: whenever I see that I am spending too much time writing the code to set up the context of a Unit test, I end up converting the test to a Kernel test, which we explore in the next section.

Kernel tests

Kernel tests are Unit tests on steroids. They are great when you want to test your module’s APIs. In a Kernel test, Drupal is installed with a limited set of features so you specify what you need in order to prepare the context of your test. These tests are written in PHPUnit, so you also have all the goodness of this framework such as mocking and data providers.

Here is a Kernel test in action. Notice that it is very similar to the clip above about Unit tests:

Videos require iframe browser support.

Kernel tests fetch the database information from core/phpunit.xml where you need to set the database connection details. You may have noticed that these tests are slightly slower than Unit tests—they need to install Drupal—yet they are extremely powerful. There are many good examples of Kernel tests in Drupal core and contributed modules like Token.

UI tests

I am grouping together Browser tests, JavaScript tests, and Behat tests as UI tests because they all test the user interface through different methods. I want to save you the hassle of going through each of them by suggesting that if you need to test the user interface, then install and use Drupal Behat Extension. Here is why:

Browser tests don’t support JavaScript. Unless you are testing an administration form, chances are that you will need JavaScript to run on a page. They are solid, but I don’t see a reason to write a Browser test when I could write a Behat one.

JavaScript tests only support PhantomJS as the browser. PhantomJS is headless, meaning that there is no visual interface. It is tedious and at times frustrating to write tests using PhantomJS because you need to type and execute commands on a debugger in order to figure out what the test “sees” at a given point, while with Behat you can use full-featured Chrome or Firefox (I laugh at myself every time I call this a "bodymore" browser) so debugging becomes way more fun. Moreover, these kind of tests get randomly stuck both in my local development environment and in Jenkins.

Discovering Behat tests

Andrew Berry and myself spent a lot of time trying to get JavaScript tests working locally and in Jenkins without luck, which is why we decided to give Behat tests a go. It felt like salvation because:

  • The setup process of the Drupal Behat Extension module is straightforward.
  • We found no bugs in the module while writing tests.
  • We can use Chrome or Firefox locally, while Jenkins uses PhantomJS and does not get stuck like it did with JavaScript tests.

Here is a sample test run:

Videos require iframe browser support.

On top of the above, I discovered the usefulness of feature files. A feature file contains human readable steps to test something. As a developer, I thought that I did not need this, but then I discovered how easy it was for the whole team to read the feature file of a module to understand what is tested, and then dive into the step implementations of that feature file to extend them.

Here is a sample feature file:


Each of the above steps matches with a class method that implements its logic. For example, here is the step implementation of the step “When I create a Runsheet”:


Behat tests can access Drupal’s APIs so, if needed, you can prepare the context of a test programmatically. All that Behat needs in its "behat.yml" file is the URL of your site and the Drupal’s root path:

undefined Now look at your project

Does your project or module have any tests? Does it need them? If so, which type of tests? I hope that now you have the answers to some of these questions thanks to this article. Go ahead and make your project more robust by writing tests.

If you are willing to improve how testing works in Drupal 8 core, here are a few interesting open issues:

In the next article, I will share with you how do we run Unit, Kernel, and Behat tests automatically when a developer creates a pull request and report their results.


I want to thank the following folks for their help while writing this article:

  • Matt Oliveira, for proofreading.
  • Marcos Cano, for his tips and his time spent doing research on this topic.
  • Seth Brown, for helping me to become a better writer.
  • The Draco team at Turner, for giving me the chance to experiment and implement testing as part of our development workflow.

Working with external APIs in Drupal has always been possible. Using PHP’s curl function or drupal_http_request is simple enough, but in Drupal 8 you can build in a lot more flexibility using Drupal::httpClient. Drupal::httpClient leverages Guzzle, a PHP HTTP client. If your project requires more than a single interaction with an external API a few steps can be taken to make those interactions much more reusable.

Make a Drupal Service for your API Connection

In Drupal 8, you can turn reusable functionality into a Service that you can easily reuse in your other custom code. Services can be called in module hooks and added to things like controllers using Dependency Injection. Defining a service in Drupal 8 requires a services.yml file in your custom module. For example, let's create a module called my_api:

The code from this example is based on a couple real-world API clients we’ve created recently.

  1. Watson API - IBM’s Watson API allows interacting with powerful utilities like speech to text. Rather than using Drupal’s httpClient in this case, we found a PHP class that already did the heavy lifting for us and we created a Drupal Service to extend that PHP class. In this case, we only needed to use Watson’s text-to-speech functionality to save text to audio files in Drupal, but ended up creating a flexible solution to interact with more than just the text-to-speech endpoint. You can check that code out on Drupal.org or GitHub.
  2. PCO API - Planning Center Online (PCO) is a CRM that is popular with faith-based institutions. PCO has a well documented RESTful API. In this case, I was building an application that needed to access the people stored in Planning Center in a Drupal 8 application. You can check that code out on Drupal.org or GitHub.
my_api.services.yml services: my_api.client: class: '\Drupal\my_api\Client\MyClient' arguments: ['@http_client', '@key.repository', '@config.factory']

The class indication references the PHP class for your service; arguments references the other Services being utilized in the Class.

Now MyClient can be referenced throughout our code base. In a Drupal hook (example hook_cron) it might look something like this:

$client = Drupal::service('my_api.client'); $client->request();

In a Controller (example MyController.php) it might look like this:

<?php   namespace Drupal\my_custom_module\Controller;   use Drupal\Core\Controller\ControllerBase; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\my_api\MyClient;   /** * Class MyController. * * @package Drupal\my_custom_module\Controller */ class MyController extends ControllerBase {   /** * Drupal\my_api\MyClient definition. * * @var \Drupal\my_api\MyClient */ protected $myClient;   /** * {@inheritdoc} */ public function __construct(MyClient $my_client) { $this->myClient = $my_client; }   /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('my_api.client') ); }   /** * Content. * * @return array * Return array. */ public function content() { $this->myClient->request()); return []; } }

Now we can use a common method in my_api.client like “request” to make calls to our external API. Connect then serves as a nice wrapper for the httpClient service.

public function request($method, $endpoint, $query, $body) { $response = $this->httpClient->{$method}( $this->base_uri . $endpoint, $this->buildOptions($query, $body) ); }

The request method accepts: A method (GET, POST, PATCH, DELETE, etc.) Endpoint (the API being used) Query (querystring parameters) Body

You can adjust your method parameters to best fit the API you are working with. In this example, the parameters defined covered the needed functionality.

$request = $this->myClient->request('post', 'people/v2/people', [], $body);

Using httpClient directly would look something like:

$response = $this->httpClient->post( 'http://someapi.com/people/v2/people', [ 'auth' => ['token', 'secret'], 'body' => json_encode($body), ] );

Using httpClient instead of a service directly could litter hard coded values throughout your code base and insecurely expose authentication credentials.

Next time your project requires integrating with a 3rd party API, consider turning it into a service to set yourself up well for the future.

Tips for Setting up a Booth at DrupalCon

For DrupalCon Baltimore I was volunteered to help with the lounge for Amazee Labs. This was my first year helping to set up a booth for any conference event and I learned a lot in the process. Fortunately, we have seasoned boothers which made the whole process look easy, but I realized there must be a lot of learned knowledge locked away. In the spirit of open source, I asked six of the vendors here to answer a few questions about their experiences and all were happy to contribute.

The following interviews have been edited heavily (due to my poor journalistic skills). Any and all mistakes are mine.

Brandon Williams Thu, 04/27/2017 - 16:42 myDropWizard

How long have you been setting up booths?
This is our second DrupalCon booth, but we've also had a presence at Drupal camps.

Do you develop it in-house or work with a third party?
The concept, design and setup was all us, but we used third parties to help us create videos and print signs.

How long did it take you, from concept to completion?
It's hard to say, we've re-used some materials and ordered others new this year. Overall we've been planning for the last two months.

Any general tips you'd like to share, or things you'd do differently?
This is DrupalCon, it's a big deal for us. Work hard to get it right, start as early as possible. Try to avoid ordering things last minute, maybe even try to setup as practice before the event. I wish we would have taped out a ten by ten square in our office to better experiment with the booth size. I didn't realize how many things were required to be bought from the official convention center vendor, so look into that as well.

Thank you David!

New Valley Media

How long have you been setting up booths?
This is our second Drupalcon.

Do you develop it in-house or work with a third party?
We do all our designs and builds in-house.

How long did it take you, from concept to completion?
At least four weeks.

Any general tips you'd like to share, or things you'd do differently?
Make sure things are lightweight because you'll be carrying them. Start planning early, at least six months out. Try to stick out from the crowd. We did recon at previous DrupalCons to develop something unique.

Thank you Christina!


How long have you been setting up booths?
At EY we've been doing them for two years, but we have five years of previous DrupalCon experience.

Do you develop it in-house or work with a third party?
We work with local talent for each Drupalcon to build our booth. We also source beer and swag from local suppliers. At the end of DrupalCon we'll work with local charities to donate anything of value.

How long did it take you, from concept to completion?
It took 2-3 months from concept to design, source the local talent, and build the final booth.

Any general tips you'd like to share, or things you'd do differently?
Get here early so you'll have time if anything goes wrong. Plan for the worst, hope for the best.

Thank you Liz!

Third and Grove

How long have you been setting up booths?
This is our first Drupalcon.

Do you develop it in-house or work with a third party?
All in-house.

How long did it take you, from concept to completion?
About 25 hours in total, but we started two months out.

Any general tips you'd like to share, or things you'd do differently?
Ask the conference vendors about options early. We wish we had a bigger backdrop and carpet for our booth. We decided to spend more on giveaways than atmosphere. I'm happy to see there are more design focused companies here, and hope to talk and learn from them.

Thank you Dan!


How long have you been setting up booths?
Six years.

Do you develop it in-house or work with a third party?

How long did it take you, from concept to completion?
We put some extra time into our booth because we use it throughout the year. We probably spent 80 hours over the course of many months. We also start planning early, at least a year in advance.

Any general tips you'd like to share, or things you'd do differently?
Be flexible and able to accept mistakes, adapt. We had a problem with our stickers, for example, which means I had to overnight a whole batch, so they aren't available on day one. Take every problem with a grain of salt, it's not the end of the world.

Thank you Calvin!

Amazee Labs

How long have you been setting up booths?
Four years.

Do you develop it in-house or work with a third party?
We do everything in-house.

How long did it take you, from concept to completion?
About 20 hours, over the course of two months.

Any general tips you'd like to share, or things you'd do differently?
Cool swag is the easiest way to make an impression. You want people to come by and say, "I heard you have (fill in the blank), how do I get one?" Then just make sure you have enough supply for the demand.

Thank you Andrew!

Thanks to all who took the time to take the poll. The participation was great! Over 350 respondents, which is a number in excess of 10% of the DrupalCon attendance. There were couple comments that I'd like to address:

A few felt that the questions were biased, or that the choices given were biased. I strove to make each of the questions a current topic, without having any imply a leaning in either direction. For example: "How do you feel about Drupal's Leadership" is meant to present a current topic in the community, but is designed to not imply a positive or negative spin. As for the options, it will never be possible in a poll with static response choices to cover all nuances, unless you just give three: positive, negative or neutral. I did try to ensure that each question had a fully positive response, a clearly negative response, and some options in between. I suppose it could have been set up to be a 1-10 scale, but I defy you to qualify the difference between 6 and 7 on such a scale. I also offered to account for comments that included a question number and a custom response when presenting the results, and have done that on questions 1 and 6, for which custom answers were given. 

There was also a concern that question 6 only offered negative or neutral options, and the suggestion was that the question should be removed from the poll as a result. I disagree, feeling that the first option, "The matter was handled properly" is certainly an option that indicates an opinion that is neither negative nor on the fence.

Should I do another poll? Let me know. 

And now, the results:

The average time in Drupal for all respondents was 7.1 years.

Tags: Drupal PlanetDrupalpoll

My blog post from last week was very well received and sparked a conversation in the Drupal community about the future of Drupal. That conversation has continued this week at DrupalCon Baltimore.

Yesterday during the opening keynote, Dries touched on some of the issues raised in my blog post. Later in the day we held an unofficial BoF. The turn out was smaller than I expected, but we had a great discussion.

Drupal moving from a hobbyist and business tool to being an enterprise CMS for creating "ambitious digital experiences" was raised in the Driesnote and in other conversations including the BoF. We need to acknowledge that this has happened and consider it an achievement. Some people have been left behind as Drupal has grown up. There is probably more we can do to help these people. Do we need more resources to help them skill up? Should we direct them towards WordPress, backdrop, squarespace, wix etc? Is it is possible to build smaller sites that eventually grow into larger sites?

In my original blog post I talked about "peak Drupal" and used metrics that supported this assertion. One metric missing from that post is dollars spent on Drupal. It is clear that the picture is very different when measuring success using budgets. There is a general sense that a lot of money is being spent on high end Drupal sites. This has resulted in less sites doing more with Drupal 8.

As often happens when trying to solve problems with Drupal during the BoF descended into talking technical solutions. Technical solutions and implementation detail have a place. I think it is important for the community to move beyond this and start talking about Drupal as a product.

In my mind Drupal core should be a content management framework and content hub service for building compelling digital experiences. For the record, I am not arguing Drupal should become API only. Larger users will take this and build their digital stack on top of this platform. This same platform should support an ecosystem of Drupal "distros". These product focused projects target specific use cases. Great examples of such distros include Lightning, Thunder, Open Social, aGov and Drupal Commerce. For smaller agencies and sites a distro can provide a great starting point for building new Drupal 8 sites.

The biggest challenge I see is continuing this conversation as a community. The majority of the community toolkit is focused on facilitating technical discussions and implementations. These tools will be valuable as we move from talking to doing, but right now we need tools and processes for engaging in silver discussions so we can build platinum level products.

According to SAQ A-EP an e-commerce website should not receive cardholder data but should control how consumers, or their cardholder data, are redirected to a PCI DSS validated third-party payment processor.

Drupal Planet, Drupal modules, Drupal security

In this tutorial, I will explain how to use custom block types to create a Parallax effect in a Drupal 8 subtheme.

It would be preferable but not required for you to have a good understanding of Drupal 8 theming. You can click here to take the Drupal 8 Theming Class.

To be able to follow this tutorial, you need to install Bootstrap and create a subtheme from the CDN folder. You can follow our guide here in our earlier post.

Using the Bootstrap CDN allows you to quickly add custom code that overrides the Bootstrap defaults. By doing so you can quickly make your own Drupal theme based on Bootstrap.

In this tutorial, we will demonstrate how to create a Drupal 8, Bootstrap subtheme that uses the "Bootstrap CDN".

This weekend (29th-30th April 2017) the Drupal, Joomla, and WordPress communities will get together in London for two days of sprints that enable anyone working with Open Source to get involved with the communities that create it and take part in improving it.



This weekend (29th-30th April 2017) the Drupal, Joomla, and WordPress communities will get together in London for two days of sprints that enable anyone working with Open Source to get involved with the communities that create it and take part in improving it.



We are heading towards the end of our "Druplicon marathon". Besides this post, we have only one left for you. It will be hard for us not to search for any Druplicons. But until then, let’s enjoy them a little bit more. After Humans and Superhumans, Fruits and Vegetables, Animals, Outdoor activities, National Identities, Emotions, Human Professions and Hats, it’s time for Drupal Logos covered with Art.   Aztec Druplicon (Drupal Camp Mexico 2013)     China art Druplicon (Drupal Camp China 2015)     Druplicon in Mesquerade costum (Drupal Camp New Orleans 2015)     Indian art Druplicon (… READ MORE

This is a story of why we have migrated from Phing to Make.

Periodic Table of Drupal 8 Modules

Thanks to you, the Drupal Community, our Periodic Table of Drupal 8 Modules is a smash hit! So much so that the 100 prints we brought to Baltimore are gone. By popular demand, however, we're providing the PDF for download—perfect for a desktop or a print of your very own.

Andrew McClintock Wed, 04/26/2017 - 21:23

Modular architecture of the Drupal 8 media ecosystem has become a standard. If you want to build media related editorial experience modules like Entity browser, DropzoneJS and Media entity are the way to go. They can effectively handle locally hosted media, but they are not limited to that. Recently we implemented a module that integrates with the Bynder DAM and lets you use its assets directly in a Drupal 8 site.

Drupal and the Drupal community are driven by volunteer contributions. There are many great ways to contribute that don't involve writing a single line of code. You could report a bug, edit a documentation page, test a new Drupal 8 feature, help a beginner on a forum, or help organize a meetup. Despite this, many Drupalers are shy about diving in.

After some reflection, the Evolving Web team realized that there's one way to contribute to the community that's really simple: thanking someone who has helped you. Someone who built a module you used, helped you in the issue queue, or has done a presentation you liked. It doesn't matter if you do it privately, publicly on Twitter, or whether you're Dries or a total beginner. 

As part of Evolving Web's "Drupal Love" sponsorship at DrupalCon Baltimore, we're hoping to encourage spontaneous expressions of gratitude by handing out 1,000 flowers, with a simple request: Give this flower to someone at DrupalCon Baltimore who helped you in some way. Spread #DrupalThanks.

It will make both you and them feel great, encourage contributions, prevent burnout, and maybe even start a virtuous cycle. Thanking somebody costs nothing, yet can mean so much.

Evolving Web will be handing out several prizes to both givers and receivers of public thanks, which include a day of free Drupal Training, a subsidized trip to attend DrupalCamp Montréal this June 15-18, and flower bouquets delivered to your home or office.

To participate, just thank someone publicly on Twitter, like this:

or like this:

or like this:

Or if you'd prefer to do it offline, come by our Evolving Web's booth and tell us who you are thanking.


+ more awesome articles by Evolving Web

If you’ve been working with Drupal long enough you probably know that it has jQuery out of the box since the 5th version.

If you’ve been working with Drupal long enough you probably have already tried to find something instead of jQuery.

jQuery doesn’t solve the problems that developers face nowadays. But Vue.js does. Besides having many stars and downloads, a large and friendly community, it is supported by Laravel (PHP framework) out of the box.

Those were the reasons to start using Vue.js for enhancing  Drupal user elements without jQuery. If you feel like learning how to work with Vue.js components, integrate Vue.js with third-party libraries and you want to create a simple SPA on your own - keep on reading here.

26 Apr Drupal 8 migration strategies Kevin VB

Content is always one of the most important parts of a website. After all, the internet was designed for information sharing. As a result, upgrading to a new CMS implies the migration of content in some form or another. Taking this into account in the early stages is crucial when considering and preparing a CMS upgrade.
The Drupal community is very aware of content migration as a key success factor. Therefore, Drupal’s latest version (D8) has the
migrate module included in its core. This key functionality allows you to upgrade from an older Drupal version to Drupal 8, using a few simple configuration steps. Below, I will explain how this works and put forward a few alternatives for custom migrations.


Why should you migrate to Drupal 8?

Site speed is not only important for SEO; it also affects your visitors’ browsing time and exit rate. Drupal 8 comes with an improved caching system that makes Drupal fly - all while taking into account content modification. There are no more endless waits for caches to invalidate, thanks to the real-time cache invalidation using cache tags.
Another reason for migration is the Drupal community. Plenty of features are available to integrate in your own site for free, which in turn enables you to spend time and money on other things. The community also keeps an eye on continuous improvements to the existing code. Drupal 8 is a great example of this, with its foundations in the Symfony2 framework. Everything in D8 has been standardised in such a way that maintenance is a lot easier and time-effective.
Let there be no doubt that migrating to Drupal 8 is an excellent long-term move!


How exactly should I migrate to Drupal 8?

You can use the Drupal migrate module that is included in core to upgrade from an older Drupal version to Drupal 8. Make sure to install and enable required modules first.
An example: if your site uses special field types, those modules should also be installed in your new Drupal 8 website. When you’re done configuring your site, you just need to enable the following modules:

  • Migrate
  • Migrate Drupal
  • Migrate Drupal UI

This last module will direct you to a configuration page, where you can start the actual migration. Simply enter the database information from your existing Drupal site and let Drupal review the upgrade.

The review will give you a list of available upgrade paths, next to a list of modules that are currently missing. If you’re happy about the review, you can choose to start the upgrade. Drupal will start importing content, users and taxonomies into your Drupal 8 website. Be aware that a rollback mechanism through the UI of Drupal is not available at this time. Since the Drupal core migrate is built to support a certain number of cases, it is possible that your site is too complicated to import correctly with the Migrate Drupal module. Sometimes, writing a customised migration is a better approach.

How to write a customized migration?

In most cases, the Migrate Drupal module will result in a reinstall of your Drupal website because some parts have been imported in the wrong way. You can opt to play things safe and write the migration yourself.
Writing a migration in Drupal 8 is done with the Migrate Plus module. This module allows you to create a new Migration entity. Those entities are created in YAML.

# Migration configuration for News content. id: news_node label: News Content Type migration_group: demo_news source: plugin: news_node destination: plugin: entity:node process: type: plugin: default_value default_value: news langcode: plugin: default_value source: language_code default_value: nl title: post_title field_title: post_title path: path field_tags: plugin: migration migration: - news_terms source: tags_terms migration_dependencies: required: - news_terms

Example of a Migration entity: migrate_plus.migration.news_node.yml

Each migration entity can belong to a Migration Group entity and is defined in YAML with the key ‘migrate_group’. A whole group of migrations can be imported or rolled back at once with drush by installing the Migrate Tools module.

  • drush mi --group=”demo_news” Import all migration in group demo_news
  • drush mr --group=”demo_news” Rollback all migrations in group demo_news


The main key of a migration is a Drupal 8 plugin that tells the migration where the source information comes from. There are plenty of base source plugins available for Drupal 8.

  • SqlBase - in Drupal Core: lets you migrate from an SQL source.
  • URL - in Migrate Plus: lets you migrate from a URL which can return JSON, XML, SOAP.
  • CSV - in Migrate Source CSV: lets you migrate from a CSV source file.
  • Spreadsheet - in Migrate Spreadsheet: lets you migrate from a csv, xls or xlsx source file.

If this does not suffice, you can start from your own source that extends from the SourcePluginBase class.

We extended the SqlBase source for our news_node source plugin.

public function query() { $query = $this->select('post', 'p'); $query->fields('p', [ 'ID', 'post_title', 'post_name', 'post_date', ]); $query->condition('p.type', 'news'); return $query; }

Query function in news_node source.

The query function returns a Select object with the information needed during the migration. This object will be the source for our migration.
Next we need to tell the migration which fields we want to map to the migration. This is done with the fields method.

public function fields() { $fields = [ 'post_title' => $this->t('The Post Node title'), 'post_date' => $this->t('The Post creation time'), // ... ]; return $fields; }

In Drupal 7 we used prepareRow to provide field information that couldn’t be selected with a single query. In Drupal 8 this can be done with the prepareRow method. In our example we fetch a teaser image and then add the file ID and file alt to the migration source.

public function prepareRow(Row $row) { // Find related teaser attachment image. $file = $this->getTeaserImage($content_id); // Set a new property file_id. $row->setSourceProperty('file_id', $file['id']); $row->setSourceProperty('file_alt', $file['alt']); return parent::prepareRow($row); }

Add extra information to the migration in preparerow.

When we go back to the YAML confirmation of our migration entity, we see that there is also a destination key configured. In most cases this will be an entity:entity_type destination plugin. Migrate will then automatically create entities of the configured type. In our example, new nodes will be created. If needed, you can also simply create a new destination plugin, which performs extra actions during the import function.


The progress key in our configuration defines the field value mapping. It contains a mapping of keys and values where the key is the Drupal field name and the value is the source field name. In some cases, like ‘type’ or ‘language’, we use a default_value plugin which allows us to set the value of the field to a fixed value. In our example, we are creating new nodes of type news in Dutch.

In some cases, the source value comes from another migration. In our example the value of ‘field_tags’ comes from another migration, this is defined by using the ‘migration’ plugin and then specify the migration(s) in which the value is migrated. Whenever such migration dependent fields are presents an extra key ‘migration dependencies’ is necessary. This is an array of migrations which needs to run first.

I hope this post has helped you to provide some insight in migrating your website from D7 to D8! As always, you can reach out to me and the rest of the team via our website.

Tomorrow (Wednesday, April 25), I'm leading a Birds of a Feather (BoF) at DrupalCon Baltimore titled Managing Drupal sites with Composer (3:45 - 4:45 p.m. in room 305).

I've built four Drupal 8 websites now, and for each site, I have battle scars from working with Composer (read my Tips for Managing Drupal 8 projects with Composer). Even some of the tools that I use alongside composer—for project scaffolding, managing dependencies, patching things, etc.—have changed quite a bit over the past year.

As more and more Drupal developers adopt a Composer workflow for Drupal, we are solving some of the most painful problems.

For example:

آخرین ارسال ها

محتواهای محبوب

درباره ما

اینجا دروپال یعنی همه چیز. در مورد دروپال صحبت میکنیم. ماژول هامون رو به اشتراک میزاریم در مورد قالب دروپال ، فروشگاه دروپال، دروپال فارسی و تاریخ شمسی دروپال صحبت میکنیم و هرچیزی که در مورد طراحی سایت با دروپال میدونیم به هم انتقال میدیم. دروپالیون یک سایت شخصی نیست. ما دست همه کسانی که برای پیشرفت دروپال تلاش میکنند رو میفشاریم و با آغوش باز اونها رو در این سایت میپذیریم.

تماس با ما

با ما تماس بگیرید.