Dec 04 2018
Dec 04

In this article I am going to show you a technique I used recently to mock a relatively simple external service for functional tests in Drupal 8.

Imagine the following scenario: you have an API with one or a few endpoints and you write a service that handles the interaction with it. For example, one of the methods of this service takes an ID and calls the API in order to return the resource for that ID (using the Guzzle service available in Drupal 8). You then cast the Guzzle response stream to a string and return whatever from there to use in your application. How can you test your application with this kind of requirements?

The first thing you can do is unit test your service. In doing so, you can pass to it a mock client that can return whatever you set to it. Guzzle even provides a MockHandler that you can use with the client and specify what you want returned. Fair enough. But what about things like Kernel or Functional tests that need to use your client and make requests to this API? How can you handle this?

It’s not a good idea to use the live API endpoint in your tests for a number of reasons. For example, your testing pipeline would depend on an external, unpredictable service which can go down at any moment. Sure, it’s good to catch when this happens but clearly this is not the way to do it. Or you may have a limited amount of requests you can make to the endpoint. All these test runs will burn through your budget. And let’s not forget you need a network connection to run the tests.

So let’s see an interesting way of doing this using the Guzzle middleware architecture. Before diving into that, however, let’s cover a few theoretical aspects of this process.

Guzzle middlewares

A middleware is a piece of functionality that can be added to the pipeline of a process. For example, the process of turning a request into a response. Check out the StackPHP middlewares for a nice intro to this concept.

In Guzzle, middlewares are used inside the Guzzle handler stack that is responsible for turning a Guzzle request into a response. In this pipeline, middlewares are organised as part of the HandlerStack object which wraps the base handler that does the job, and are used to augment this pipeline. For example, let’s say a Guzzle client uses the base Curl handler to make the request. We can add a middleware to the handler stack to make changes to the outgoing request or to the incoming response. I highly recommend you read the Guzzle documentation on handlers and middlewares for more information.

Guzzle in Drupal 8

Guzzle is the default HTTP client used in Drupal 8 and is exposed as a service (http_client). So whenever we need to make external requests, we just inject that service and we are good to go. This service is instantiated by a ClientFactory that uses the default Guzzle handler stack (with some specific options for Drupal). The handler stack that gets injected into the client is configured by Drupal’s own HandlerStackConfigurator which also registers all the middlewares it finds.

Middlewares can be defined in Drupal as tagged services, with the tag http_client_middleware. There is currently only one available to look at as an example, used for the testing framework: TestHttpClientMiddleware.

Our OMDb (Open Movie Database) Mock

Now that we have an idea about how Guzzle processes a request, let’s see how we can use this to mock requests made to an example API: OMDb.

The client

Let’s assume a module called omdb which has this simple service that interacts with the OMDb API:

<?php

namespace Drupal\omdb;

use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use GuzzleHttp\ClientInterface;

/**
 * Client to interact with the OMDb API.
 */
class OmdbClient {

  /**
   * @var \GuzzleHttp\ClientInterface
   */
  protected $client;

  /**
   * Constructor.
   *
   * @param \GuzzleHttp\ClientInterface $client
   */
  public function __construct(ClientInterface $client) {
    $this->client = $client;
  }

  /**
   * Get a movie by ID.
   *
   * @param \Drupal\omdb\string $id
   *
   * @return \stdClass
   */
  public function getMovie(string $id) {
    $settings = $this->getSettings();
    $url = Url::fromUri($settings['url'], ['query' => ['apiKey' => $settings['key'], 'i' => $id]]);
    $response = $this->client->get($url->toString());
    return json_decode($response->getBody()->__toString());
  }

  /**
   * Returns the OMDb settings.
   *
   * @return array
   */
  protected function getSettings() {
    return Settings::get('omdb');
  }

}

We inject the http_client (Guzzle) and have a single method that retrieves a single movie from the API by its ID. Please disregard the complete lack of validation and error handling, I tried to keep things simple and to the point. To note, however, is that the API endpoint and key is stored in the settings.php file under the omdb key of $settings. That is if you want to play around with this example.

So assuming that we have defined this service inside omdb.services.yml as omdb.client and cleared the cache, we can now use this like so:

$client = \Drupal::service('omdb.client');
$movie = $client->getMovie('tt0068646');

Where $movie would become a stdClass representation of the movie The Godfather from the OMDb.

The mock

Now, let’s assume that we use this client to request movies all over the place in our application and we need to write some Kernel tests that verify that functionality, including the use of this movie data. One option we have is to switch out our OmdbClient client service completely as part of the test, with another one that has the same interface but returns whatever we want. This is ok, but it’s tightly connected to that test. Meaning that we cannot use it elsewhere, such as in Behat tests for example.

So let’s explore an alternative way by which we use middlewares to take over any requests made towards the API endpoint and return our own custom responses.

The first thing we need to do is create a test module where our middleware will live. This module will, of course, only be enabled during test runs or any time we want to play around with the mocked data. So the module can be called omdb_tests and we can place it inside the tests/module directory of the omdb module.

Next, inside the namespace of the test module we can create our middleware which looks like this:

<?php

namespace Drupal\omdb_tests;

use Drupal\Core\Site\Settings;
use GuzzleHttp\Promise\FulfilledPromise;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

/**
 * Guzzle middleware for the OMDb API.
 */
class OmdbMiddleware {

  /**
   * Invoked method that returns a promise.
   */
  public function __invoke() {
    return function ($handler) {
      return function (RequestInterface $request, array $options) use ($handler) {
        $uri = $request->getUri();
        $settings = Settings::get('omdb');

        // API requests to OMDb.
        if ($uri->getScheme() . '://' . $uri->getHost() . $uri->getPath() === $settings['url']) {
          return $this->createPromise($request);
        }

        // Otherwise, no intervention. We defer to the handler stack.
        return $handler($request, $options);
      };
    };
  }


  /**
   * Creates a promise for the OMDb request.
   *
   * @param RequestInterface $request
   *
   * @return \GuzzleHttp\Promise\PromiseInterface
   */
  protected function createPromise(RequestInterface $request) {
    $uri = $request->getUri();
    $params = \GuzzleHttp\Psr7\parse_query($uri->getQuery());
    $id = $params['i'];
    $path = drupal_get_path('module', 'omdb_tests') . '/responses/movies';

    $json = FALSE;
    if (file_exists("$path/$id.json")) {
      $json = file_get_contents("$path/$id.json");
    }

    if ($json === FALSE) {
      $json = file_get_contents("$path/404.json");
    }

    $response = new Response(200, [], $json);
    return new FulfilledPromise($response);
  }

}

Before explaining what all this code does, we need to make sure we register this as a tagged service inside our test module:

services:
  omdb_tests.client_middleware:
    class: Drupal\omdb_tests\OmdbMiddleware
    tags:
      - { name: http_client_middleware }

Guzzle middleware services in Drupal have one single (magic) method called __invoke. This is because the service is treated as a callable. What the middleware needs to do is return a (callable) function which gets as a parameter the next handler from the stack that needs to be called. The returned function then has to return another function that takes the RequestInterface and some options as parameters. At this point, we can modify the request. Lastly, this function needs to make a call to that next handler by passing the RequestInterface and options, which in turn will return a PromiseInterface. Take a look at TestHttpClientMiddleware for an example in which Drupal core tampers with the request headers when Guzzle makes requests during test runs.

So what are we doing here?

We start by defining the first two (callable) functions I mentioned above. In the one which receives the current RequestInterface, we check for the URI of the request to see if it matches the one of our OMDb endpoint. If it doesn’t we simply call the next handler in the stack (which should return a PromiseInterface). If we wanted to alter the response that came back from the next handler(s) in the stack, we could call then() on the PromiseInterface returned by the stack, and pass to it a callback function which receives the ResponseInterface as a parameter. In there we could make the alterations. But alas, we don’t need to do that in our case.

A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled.

Read this for more information on what promises are and how they work.

Now for the good stuff. If the request is made to the OMDb endpoint, we create our own PromiseInterface. And very importantly, we do not call the next handler. Meaning that we break out of the handler stack and skip the other middlewares and the base handler. This way we prevent Guzzle from going to the endpoint and instead have it return our own PromiseInterface.

In this example I decided to store a couple of JSON responses for OMDb movies in files located in the responses/movies folder of the test module. In these JSON files, I store actual JSON responses made by the endpoint for given IDs, as well as a catch-all for whenever a missing ID is being requested. And the createPromise() method is responsible for determining which file to load. Depending on your application, you can choose exactly based on what you would like to build the mocked responses.

The loaded JSON is then added to a new Response object that can be directly added to the FulfilledPromise object we return. This tells Guzzle that the process is done, the promise has been fulfilled, and there is a response to return. And that is pretty much it.

Considerations

This is a very simple implementation. The API has many other ways of querying for data and you could extend this to store also lists of movies based on a title keyword search, for example. Anything that serves the needs of the application. Moreover, you can dispatch an event and allow other modules to provide their own resources in JSON format for various types of requests. There are quite a lot of possibilities.

Finally, this approach is useful for “simple” APIs such as this one. Once you need to implement things like Oauth or need the service to call back to your application, some more complex mocking will be needed such as a dedicated library and/or containerised application that mocks the production one. But for many such cases in which we read data from an endpoint, we can go far with this approach.

Oct 22 2018
Oct 22

Inheriting from Symfony (in principle but not implementation), Drupal 8 allows us to define certain services as lazy. Why? Well why the hell not?!

Sometimes, our services get big. Not necessarily in the number of things they do (hopefully not) but in the time it takes for them to get instantiated. As you know, when we define a service and make it a dependency of something else, the service container will instantiate that service and inject it where it is needed. And this happens whether on that particular request that service is used or not.

For example, let’s imagine you have a Controller with 2 public methods used for 2 distinct routes. Most likely, when one method gets hit for the route, the logic of the second one doesn’t run. And even if only the second one depends on an injected service, the latter gets instantiated in both cases regardless.

Of course, for “popular” services like the EntityTypeManager or form builders this is not a big deal. For one, they are probably going to be instantiated anyway for other parts of the request. And second, they are not expensive to construct. Well, they probably are but anyway, see point 1. However, if we have our custom service as a dependency which is used only for that one route, it doesn’t make sense to have it instantiated for both routes. Especially if it is expensive to do so — heavy on resources. Enter lazy services.

Lazy services basically “tell” the container:

Ok, I need to be injected, sure, but unless I’m not used, please don’t construct me… mkay?

So how does this work in practice? Let’s see an example.

Assume this service:

namespace Drupal\module_name;

class MyHeavyService implements HeavyServiceInterface {

  /**
   * This be slow.
   */
  public function __construct() {
    sleep(4);
  }

  /**
   * Does something, doesn't matter what.
   */
  public function doSomething() {}
}

A few things to note here:

  • It’s important to have an interface. Without one, this won’t work. You’ll see in a moment why.
  • The constructor does, for some reason, take an expensive nap.
  • It’s not important what the API of the service does.

For such a service, the normal service definition would look like this:

module_name.heavy_service:
  class: Drupal\module_name\MyHeavyService

If we inject this into our Controller, any request which uses the latter will instantiate this service as well — which costs us 4 seconds a pop. So to make it lazy we just have this instead:

module_name.heavy_service:
  class: Drupal\module_name\MyHeavyService
  lazy: true

Lazy services work by way of proxy classes. Meaning that for each service that is declared lazy, the container expects a proxy class which is responsible for decorating the original one and only instantiate it if any of the public APIs are requested. But don’t worry, we don’t have to write another class. We have a PHP script provided by Drupal core that does this for us:

php core/scripts/generate-proxy-class.php 'Drupal\module_name\MyHeavyService' 'modules/custom/module_name/src'

The script takes two parameters:

  • The namespace of the service we want to create a proxy for
  • The location where it should be written

Do note that proxy classes are dumped automatically into a ProxyClass folder located at that specified path. So this is what gets generated for our service at modules/custom/module_name/src/ProxyClass/MyHeavyService.php:

// @codingStandardsIgnoreFile

/**
 * This file was generated via php core/scripts/generate-proxy-class.php 'Drupal\module_name\MyHeavyService' "modules/custom/module_name/src".
 */

namespace Drupal\module_name\ProxyClass {

    /**
     * Provides a proxy class for \Drupal\module_name\MyHeavyService.
     *
     * @see \Drupal\Component\ProxyBuilder
     */
    class MyHeavyService implements \Drupal\module_name\HeavyServiceInterface
    {

        use \Drupal\Core\DependencyInjection\DependencySerializationTrait;

        /**
         * The id of the original proxied service.
         *
         * @var string
         */
        protected $drupalProxyOriginalServiceId;

        /**
         * The real proxied service, after it was lazy loaded.
         *
         * @var \Drupal\module_name\MyHeavyService
         */
        protected $service;

        /**
         * The service container.
         *
         * @var \Symfony\Component\DependencyInjection\ContainerInterface
         */
        protected $container;

        /**
         * Constructs a ProxyClass Drupal proxy object.
         *
         * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
         *   The container.
         * @param string $drupal_proxy_original_service_id
         *   The service ID of the original service.
         */
        public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
        {
            $this-&gt;container = $container;
            $this-&gt;drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
        }

        /**
         * Lazy loads the real service from the container.
         *
         * @return object
         *   Returns the constructed real service.
         */
        protected function lazyLoadItself()
        {
            if (!isset($this-&gt;service)) {
                $this-&gt;service = $this-&gt;container-&gt;get($this-&gt;drupalProxyOriginalServiceId);
            }

            return $this-&gt;service;
        }

        /**
         * {@inheritdoc}
         */
        public function doSomething()
        {
            return $this-&gt;lazyLoadItself()-&gt;doSomething();
        }

    }

}

As you can see, we have a simple decorator. It implements the same interface and has the same public methods. The latter, however, are derived automatically from the service class and not the interface. And basically, the container is injected and used to instantiate the underlying service the first time any of the public methods are called. If none are called in that request, it won’t get instantiated.

I mentioned above that having an interface on the service is necessary. The reason is that when we inject it somewhere, we need to type hint the interface. Otherwise, the container would pass an instance of Drupal\module_name\ProxyClass\MyHeavyService which is not the same as the original Drupal\module_name\MyHeavyService.

So now, we can inject it, type hint it with the interface and it would only get instantiated if any of the public methods are called. Neat no?

The responsible for making all this happen is the Drupal\Core\DependencyInjection\Compiler\ProxyServicesPass compiler pass. Looking for service definitions that have been marked as lazy, it creates a new identical service definition (non-lazy) which uses the proxy class and adds that to the container instead. It’s actually not rocket science if you look at the code.

And like many things, just because we have this available, it doesn’t mean we should use it for every service we write. Remember, if you create services used all over the place, this is useless. The criteria for whether to make your service lazy should be:

  • Is it heavy to instantiate (depends on a bunch of other services which in turn are not super popular either)?
  • Is it ever instantiated for no reason?

Hope this helps.

May 22 2018
May 22

In an older article we looked at how to render an entity form programatically using custom form display modes. Fair enough. But did you ever need to combine this form with a few form elements of yours which do not have to be stored with the corresponding entity? In other words, you need to be working in a custom form…

What I used to do in this case was write my own clean form elements in a custom form and on submit, deal with saving them to the entity. This is not a big deal if I am dealing with simple form elements, and of course, only a few of them. If my form is big or complex, using multivalue fields, image uploads and stuff like this, it becomes quite a hassle. And who needs that?

Instead, in our custom form, we can load up and add the field widgets of our entity form. And I know what you are thinking: can we just build an entity form using the EntityFormBuilder service, as we saw in the previous article, and just copy over the form element definitions? Nope. That won’t work. Instead, we need to mimic what it does. So how do we do that?

We start by creating a nice form display in the UI where we can configure all our widgets (the ones we want to show and in the way we want them to show up). If the default form display is good enough, we don’t even need to create this. Then, inside the buildForm() method of our custom form we need to do a few things.

We create an empty entity of the type that concerns us (for example Node) and store that on the form state (for the submission handling that happens later):

    $entity = $this->entityTypeManager->getStorage(‘node’)->create([
      'type' => ‘article’
    ]);
    $form_state->set(‘node’, $node);

Next, we load our newly created form display and store that also on the form state:

     /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
    $form_display = $this->entityTypeManager->getStorage('entity_form_display')->load('node.article.custom_form_display');
    $form_state->set('form_display', $form_display);

You’ll notice that the form display is actually a configuration entity whose ID is made up of the concatenation of the entity type and bundle it’s used on, and its unique machine name.

Then, we loop over all the components of this form display (essentially the field widgets that we configure in the UI or inside the base field definitions) and build their widgets onto the form:

foreach ($form_display->getComponents() as $name => $component) {
  $widget = $form_display->getRenderer($name);
  if (!$widget) {
    continue;
  }

  $items = $entity->get($name);
  $items->filterEmptyItems();
  $form[$name] = $widget->form($items, $form, $form_state);
  $form[$name]['#access'] = $items->access('edit');
}

This happens by loading the renderer for each widget type and asking it for its respective form elements. And in order for it to do this, it needs an instance of the FieldItemListInterface for that field (which at this stage is empty) in order to set any default values. This we just get from our entity.

And we also check the access on that field to make sure the current user can access it.

Finally, we need to also specify a #parents key on our form definition because that is something the widgets themselves expect. It can stay empty:

    $form['#parents'] = [];

Now we can load our form in the browser and all the configured field widgets should show up nicely. And we can add our own complementary elements as we need. Let’s turn to the submit handler to see how we can easily extract the submitted values and populate the entity. It’s actually very simple:

        /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
        $form_display = $form_state->get('form_display');
        $entity = $form_state->get('entity');
        $extracted = $form_display->extractFormValues($entity, $form, $form_state);

First, we get our hands on the same form display config and the entity object we passed on from the form definition. Then we use the former to “extract” the values that actually belong to the latter, from the form state, into the entity. The $extracted variable simply contains an array of field names which have been submitted and whose values have been added to the entity.

That’s it. We can continue processing our other values and save the entity: basically whatever we want. But we benefited from using the complex field widgets defined on the form display, in our custom form.

Ain't that grand?

Nov 02 2017
Nov 02

If you’ve been wondering where I’ve been and why I haven’t been writing any articles lately, I am here to put your mind at ease: i’ve been working heavily on my first book about Drupal, called Drupal 8 Module Development. And I am happy to announce that it has finally been published and available for purchase.

Released by Packt Publishing, a leading publishing house for technical books in the Open Source world, my book is a comprehensive guide for developers new to Drupal 8. It aims to introduce you to module development starting from scratch but building up to complex functionalities. In doing so, you learn about all the fundamental subsystems and APIs available to work with in your Drupal module.

Drupal 8 Module Development

As you know, my website mainly focuses on Drupal knowledge via articles about tips and techniques, especially in Drupal 8 (most recently). So if you’ve been finding these helpful, I recommend checking out my book as it contains about 500 pages of great content aiming to help you ramp up your Drupal 8 module development skills. I appreciate each and every one who decides to give it a chance and I hope you find it as useful as I intended it to be.

Here is the list of chapters that will take you on the journey from starting a simple module to writing performant functionality using complex subsystems and APIs:

  • Chapter 1,  Developing for Drupal 8 , provides an introduction to module development in Drupal 8. In doing so, it introduces the reader to the various subsystems and outlines the requirements for running a Drupal 8 application.
  • Chapter 2,  Creating Your First Module , gets the ball rolling by creating the first Drupal 8 module of the book. Its main focus is to explore the most common things module developers need to know from the get-go.
  • Chapter 3,  Logging and Mailing , is about the tools available for doing something every web- based application does and/or should be doing, that is, sending emails and logging events.
  • Chapter 4,  Theming , presents the theme system from a module developer's perspective in Drupal 8.
  • Chapter 5,  Menus and Menu Links , explores the world of menus in Drupal 8 and shows how to programmatically create and work with menu links.
  • Chapter 6,  ata Modeling and Storage , looks at the various types of storage available in Drupal 8, from the state system to configuration and entities.
  • Chapter 7,  Your Own Custom Entity and Plugin Types , takes a hands-on approach creating a custom configuration and content entity type, as well as custom plugin type to wire up a practical functional example.
  • Chapter 8,  The Database API , presents the database abstraction layer and how we can work directly with data stored in custom tables.
  • Chapter 9,  Custom Fields , exemplifies the creation of the three plugins necessary for creating a custom field that can be used on a Drupal 8 content entity type.
  • Chapter 10,  Access Control , explores the world of access restrictions in Drupal 8, from roles and permissions to route and entity access checks.
  • Chapter 11,  Caching , looks at the various cache mechanisms available for module developers to improve the performance of their functionality.
  • Chapter 12,  Javascript and the AJAX API , introduces module developers to the specificities of writing JavaScript in Drupal 8, as well as the powerful AJAX system, which can be used to build advanced interactions.
  • Chapter 13,  Internationalization and Languages , deals with the practices Drupal 8 module developers need to observe in order to ensure that the application can be properly translated.
  • Chapter 14,  Batches, Queues, and Cron , explores the various ways module developers can structure their data processing tasks in a reliable way.
  • Chapter 15,  Views , looks at the various ways module developers can programmatically interact with Views and even expose their own data to them.
  • Chapter 16,  Working with Files and Images , explores the various file and image APIs that allow module developers to store, track, and manage files in Drupal 8.
  • Chapter 17,  Automated Testing , explores the various types of automated test module developers can write for their Drupal 8 applications to ensure stable and resilient code.
  • Annex, Drupal 8 Security , recaps some of the main things module developers need to pay attention to for writing secure code in Drupal 8.

If you find something incorrect or out of place, please use the appropriate errata submission form mentioned in the book. And as always, feel free to drop comments below about the your thoughts on the book. Enjoy and thank you very much for purchasing my book!

Jun 05 2017
Jun 05

Drupal 8 has become much more flexible for doing pretty much everything. In this article I want to talk a bit about menu links and show you how powerful the new system is compared to Drupal 7.

In Drupal 7, menu links were a thing of their own with an API that you can use to create them programatically and put them in a menu. So if you wanted to deploy a menu link in code, you’d have to write an update hook and create the link programatically. All in a day’s…

We have much more control in Drupal 8. First, it has become significantly easier to do the same thing. Menu links are now plugins discovered from YAML files. So for example, to define a link in code, all you need is place the following inside a my_module.links.menu.yml file:

    my_module.link_name:
      title: 'This is my link'
      description: 'See some stuff on this page.'
      route_name: my_module.route_it_points_to
      parent: my_module.optional_parent_link_name_it_belongs_under
      menu_name: the_menu_name_we_want_it_in
      weight: -1

And that’s it. If you specify a parent link which is in a menu, you no longer even need to specify the menu name. So clearing the cache will get this menu link created and added to your menu. And even more, removing this code will remove your menu link from the menu. With D7 you need another update hook to clear that link.

Second, you can do far more powerful things than this. In the example above, we know the route name and have hardcoded it there. But what if we don’t yet and have to grab it from somewhere dynamically. That is where plugin derivatives come into play. For more information about what these are and how they work, do check out my previous article on the matter.

So let’s see an example of how we can define menu links dynamically. First, let’s head back to our *.links.menu.yml file and add our derivative declaration and then explain what we are doing:

    my_module.product_link:
      class: Drupal\my_module\Plugin\Menu\ProductMenuLink
      deriver: Drupal\my_module\Plugin\Derivative\ProductMenuLink
      menu_name: product

First of all, we want to create dynamically a menu link inside the product menu for all the products on our site. Let’s say those are entities.

There are two main things we need to define for our dynamic menu links: the class they use and the deriver class responsible for creating a menu link derivative for each product. Additionally, we can add here in the YAML file all the static information that will be common for all these links. In this case, the menu name they’ll be in is the same for all we might as well just add it here.

Next, we need to write those two classes. The first would typically go in the Plugin/Menu namespace of our module and can look as simple as this:

    namespace Drupal\my_module\Plugin\Menu;

    use Drupal\Core\Menu\MenuLinkDefault;

    /**
     * Represents a menu link for a single Product.
     */
    class ProductMenuLink extends MenuLinkDefault {}

We don’t even need to have any specific functionality in our class if we don’t need it. We can extend the MenuLinkDefault class which will contain all that is needed for the default interaction with menu links — and more important, implement the MenuLinkInterface which is required. But if we need to work with these programatically a lot, we can add some helper methods to access plugin information.

Next, we can write our deriver class that goes in the Plugin/Derivative namespace of our module:

    <?php

    namespace Drupal\my_module\Plugin\Derivative;

    use Drupal\Component\Plugin\Derivative\DeriverBase;
    use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
    use Drupal\Core\Entity\EntityTypeManagerInterface;
    use Symfony\Component\DependencyInjection\ContainerInterface;

    /**
     * Derivative class that provides the menu links for the Products.
     */
    class ProductMenuLink extends DeriverBase implements ContainerDeriverInterface {

       /**
       * @var EntityTypeManagerInterface $entityTypeManager.
       */
      protected $entityTypeManager;

      /**
       * Creates a ProductMenuLink instance.
       *
       * @param $base_plugin_id
       * @param EntityTypeManagerInterface $entity_type_manager
       */
      public function __construct($base_plugin_id, EntityTypeManagerInterface $entity_type_manager) {
        $this->entityTypeManager = $entity_type_manager;
      }

      /**
       * {@inheritdoc}
       */
      public static function create(ContainerInterface $container, $base_plugin_id) {
        return new static(
          $base_plugin_id,
          $container->get('entity_type.manager')
        );
      }

      /**
       * {@inheritdoc}
       */
      public function getDerivativeDefinitions($base_plugin_definition) {
        $links = [];

        // We assume we don't have too many...
        $products = $this->entityTypeManager->getStorage('product')->loadMultiple();
        foreach ($products as $id => $product) {
          $links[$id] = [
            'title' => $product->label(),
            'route_name' => $product->toUrl()->getRouteName(),
            'route_parameters' => ['product' => $product->id()]
          ] + $base_plugin_definition;
        }

        return $links;
      }
    }

This is where most of the logic happens. First, we implement the ContainerDeriverInterface so that we can expose this class to the container and inject the Entity Type Manager. You can see the create() method signature is a bit different than you are used to. Second, we implement the getDerivativeDefinitions() method to return an array of plugin definitions based on the master definition (the one found in the YAML file). To this end, we load all our products and create the array of definitions.

Some things to note about this array of definitions. The keys of this array are the ID of the derivative, which in our case will match the Product IDs. However, the menu link IDs themselves will be made up of the following construct [my_module].product_link:[product-id]. That is the name of the link we set in the YAML file + the derivative ID, separated by a colon.

The route name we add to the derivative is the canonical route of the product entity. And because this route is dynamic (has arguments) we absolutely must also have the route_parameters key where we add the necessary parameters for building this route. Had the route been static, no route params would have been necessary.

Finally, each definition is made up of what we specify here + the base plugin definition for the link (which actually includes also all the things we added in the YAML file). If we need to interact programatically with these links and read some basic information about the products themselves, we can use the options key and store that data. This can then be read by helper methods in the Drupal\my_module\Plugin\Menu\ProductMenuLink class.

And that’s it. Now if we clear the cache, all our products are in the menu. If we create another product, it’s getting added to the menu (once the caches are cleared).

Bonus

You know how you can define action links and local tasks (tabs) in the same way as menu link? In their respective YAML files? Well the same applies for the derivatives. So using this same technique, you can define local actions and tasks dynamically. The difference is that you will have a different class to extend for representing the links. For local tasks it is LocalTaskDefault and for local actions it is LocalActionDefault.

Summary

In this article we saw how we can dynamically create menu links in Drupal 8 using derivatives. In doing so, we also got a brief refresher on how derivatives work. This is a very powerful subsystem of the Plugin API which hides a lot of powerful functionality. You just gotta dig it out and use it.

May 08 2017
May 08

One of the great things about the taxonomy terms in Drupal has always been their hierarchical readiness. That is, how they can easily be organised in a parent-child relationship via a simple drag-and-drop interface. This feature becomes even more important in Drupal 8 where creating entities for anything you want has become easy so we no longer have to (ab)use taxonomy term entities for everything. Unless, of course, we need this kind of behaviour.

However, I recently noticed a shortcoming in the way we are able to load taxonomy terms programatically. I needed to load a tree of terms as represented by their hierarchy. But there is no API (for the moment) that allows me to do so. At least none that I could find.

What I needed was similar to the menu system where if you load a tree, you get an array of MenuLinkTreeElement objects that wrap the links and which can each contain an array of MenuLinkTreeElement objects that represent the children (subtree) of that link. So one big multidimensional array of objects.

For terms, I imaged there would be something similar, but I was wrong. The Drupal\taxonomy\TermStorage::loadTree() method basically does half the job I want. It returns all the terms in the vocabulary, each represented as a stdClass object (why?) that contains some basic info. And in this object we get a parents array that contains the IDs of the terms which are its parents (as you know, terms can have multiple parents).

This may be enough in certain cases. However, I wanted to go one step further. So I created a simple service that loads the tree of a vocabulary in a multidimensional array, similar to what the menu system does:

    <?php

    namespace Drupal\taxonomy_tree;

    use Drupal\Core\Entity\EntityTypeManager;

    /**
     * Loads taxonomy terms in a tree
     */
    class TaxonomyTermTree {

      /**
       * @var \Drupal\Core\Entity\EntityTypeManager
       */
      protected $entityTypeManager;

      /**
       * TaxonomyTermTree constructor.
       *
       * @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager
       */
      public function __construct(EntityTypeManager $entityTypeManager) {
        $this->entityTypeManager = $entityTypeManager;
      }

      /**
       * Loads the tree of a vocabulary.
       *
       * @param string $vocabulary
       *   Machine name
       *
       * @return array
       */
      public function load($vocabulary) {
        $terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadTree($vocabulary);
        $tree = [];
        foreach ($terms as $tree_object) {
          $this->buildTree($tree, $tree_object, $vocabulary);
        }

        return $tree;
      }

      /**
       * Populates a tree array given a taxonomy term tree object.
       *
       * @param $tree
       * @param $object
       * @param $vocabulary
       */
      protected function buildTree(&$tree, $object, $vocabulary) {
        if ($object->depth != 0) {
          return;
        }
        $tree[$object->tid] = $object;
        $tree[$object->tid]->children = [];
        $object_children = &$tree[$object->tid]->children;

        $children = $this->entityTypeManager->getStorage('taxonomy_term')->loadChildren($object->tid);
        if (!$children) {
          return;
        }

        $child_tree_objects = $this->entityTypeManager->getStorage('taxonomy_term')->loadTree($vocabulary, $object->tid);

        foreach ($children as $child) {
          foreach ($child_tree_objects as $child_tree_object) {
            if ($child_tree_object->tid == $child->id()) {
             $this->buildTree($object_children, $child_tree_object, $vocabulary);
            }
          }
        }
      }
    }

No need to copy it from here, you can find it in this repository inside a simple module called taxonomy_tree.

So what I basically do here is load the default tree and iterate through all the objects. If any of them are not already at the bottom of the tree, I populate a children key with their children. This happens by using the TermStorage::loadChildren() method and recursing through that list as well.

So let me know what you think and if this helps you out.

Mar 21 2017
Mar 21

Have you ever needed to persist some irregular data relating with a user account? Things like user preferences or settings that are kinda configuration but not really? Storing them as configuration means having to export them, and that’s no option. Storing them in State is an option, but not a good one as you’d have to maintain a State value map with each of your users and who wants to deal with that…

In Drupal 7, if you remember way back when, we had this data column in the user table which meant that we could add to the $user->data array whatever we wanted and it would get serialised and saved in that column (if we saved the user object). So what is the equivalent of this in Drupal 8?

I’m happy to say we have the exact same thing, but of course much more flexible and properly handled. So not exactly the same. But close. We have the user.data service provided by the User module and the users_data table for storage. So how does this work?

First of all, it’s a service. So whenever we need to work with it, we have to get an instance like so:

/** @var UserDataInterface $userData */
$userData = \Drupal::service('user.data');

Of course, you should inject it wherever possible.

The resulting object (by default) will be UserData which implements UserDataInterface. And using this object we can store as many pieces of data or information for a given user as we want. Let’s explore this a bit to learn more.

The interface has 3 methods or handling data: get(), set(), delete(). But the power comes in the method arguments. This is how we can store some data for User 1:

$userData->set('my_module', 1, 'my_preference', 'this is my preference');

So as you can see, we have 4 arguments:

  • The module name we want this piece of data to be findable by
  • The user ID
  • The name of the piece of data
  • The value of the piece of data

This is very flexible. First, we can have module specific data. No more colluding with other modules for storing user preferences. Stay in your lane. Second, we can have multiple pieces of data per user, per module. And third, the value is automatically serialised for us so we are not restricted to simple strings.

Retrieving data can be done like so:

$data = $userData->get('my_module', 1, 'my_preference');

This will return exactly this is my preference (in our case). And deserialisation also happens automatically if your data got serialised on input.

Deleting data is just as easy:

$userData->delete('my_module', 1, 'my_preference');

Moreover, most of the arguments of the get() and delete() methods are optional. Meaning you can load/delete multiple pieces of data at once. Check out UserDataInterface to see how omitting some arguments can return/delete sets of records rather than individual ones.

And that is pretty much it. And in true Drupal 8 form, there’s nobody stopping you from overriding the service and using your own UserDataInterface implementation that has that little extra something you are missing. So no, you probably don’t have to create that custom table after all.

Mar 13 2017
Mar 13

The Symfony service container that Drupal 8 ships with allows us to define a large number of services (dependency objects) that we can inject in our controllers, forms, plugins, other services, etc. If you don't know about dependency injection yet, you can read more about it here. In this article we will look at how we can use our own factory class to instantiate a service via the Symfony - Drupal 8 service container.

The typical (barebones) service definition consists of a class name to be instantiated and an array of arguments to be passed to its constructor as it gets created (other service definitions or static parameters). For more information, check out the documentation on services.

In some cases, though, we would like our service to be built dynamically based on certain contextual conditions, such as the current user. The implication is also that we don’t rely on the service container for the actual object instantiation, but our own factory class. We do still want to benefit from most of what the container offers us, such as caching.

Let’s see a very simple example. Imagine a UserContextInterface which can have multiple implementations. These implementations depend on some value on the current user account (such as role for instance). And we want to have a service we can inject into our other objects which implements this interface but which is also the representation of the current user. Meaning it is an implementation specific to it (not always the same class).

We can go about achieving this in two ways:

  • We can have a Factory class we define as a simple service (with the current user as an argument), use this as our dependency and then always ask it to give us the correct UserContextInterface.
  • We can have a Factory class we define as a service (with the current user as an argument) but use it in the definition of another service as a factory and rely on the container for asking it for the UserContextInterface.

The first option is pretty self-explanatory and not necessary in our case. Why should we keep asking the user context at runtime (the process to determine the context can be quite complex) when we can have that cached for the duration of the request. So let’s instead see how the second option would work:

my_module.user_context_factory:
    class: Drupal\my_module\UserContextFactory
    arguments: ['@current_user']
my_module.user_context:
    class:  Drupal\my_module\UserContextFactory
    factory: 'my_module.user_context_factory:getUserContext'

So these would be our service definitions. We have the factory which takes the current user as an argument, and the user context service which we will be injecting as our dependency wherever we need. The latter uses our factory’s getUserContext() method to return the relevant UserContextInterface implementation. It is not so important what class we set on this latter service because the resulting object will always be the result of the factory.

The rest is boilerplate and we won’t be going into it. However, what needs to happen next is create our UserContextFactory class which takes in the AccountProxyInterface representing the current user and which implements the getUserContext() method tasked with building the UserContextInterface implementation. The latter method is not bound to any return type by the service per se, however, we must ensure that we return a UserContextInterface  in every case to preserve the integrity of our application. One good practice to ensure this is creating a UserContextNone implementation of UserContextInterface which would be returned by the factory in those edge cases when the context cannot be determined or values are missing, etc.

So that is pretty much it on how and why you would or can use a factory instantiation of services from your container. There is nothing new here, in fact the Symfony documentation has an entry specifically about this. However, I believe it’s a neat little trick we should all be aware of.

Feb 27 2017
Feb 27

Dates have always been a tricky thing to manage in Drupal. Even in PHP. PHP 5.2 introduced the DateTimeInterface which makes handling dates, date ranges, intervals, comparisons etc much easier. However, we always still have the complication of data storage, formatting and different timezones management.

In this article we are going to look at how we can run some entity queries in Drupal 8 using the Date field in our conditions. The requirement for returning entities which have a date field with a value between certain hours is definitely not an edge case, and although seems like an easy task, it can be tricky.

Query for entities using dates in Drupal 8

Imagine a simple date field on the Node entity which stores date and time. By default in Drupal 8, the storage for this date is in the format Y-m-d\TH:i:s and the timezone is UTC. However, the site timezone is rarely UTC and we very well may have users choosing their own timezones. So we need to construct our node queries carefully if we want reliable results.

Running a db_query() type of query for returning nodes with the date in a certain range would be a pain at best and impossible at worst. Luckily though, we can, and should always in Drupal 8 try to rely on the entity.query service when looking for entities.

So let's see a couple of examples.

First, an easy one: how do we query for all the nodes which have the field_date value in the future.

$now = new DrupalDateTime('now');
$query = \Drupal::entityQuery('node');
$query->condition('field_date', $now->format(DATETIME_DATETIME_STORAGE_FORMAT), '>=');
$results = $query->execute();

A few things to notice. First, we are using the Drupal wrapper of \DateTime and constructing an object to represent our current time. Then we create our entity query and for the date field condition we pass the storage format so that it can be compared to what is being stored. And the regular operators here allow us to find the right entities.

There is one problem with this though. When creating the DrupalDateTime, the site default timezone is used. So if our timezone is not UTC, the query will suffer because we are essentially comparing apples with oranges. And the further away from UTC we are, the more apples start to become compared to cars and airplanes.

To fix this, we need to set the timezone to UTC before running the query.

$now = new DrupalDateTime('now');
$now->setTimezone(new \DateTimeZone(DATETIME_STORAGE_TIMEZONE));

And then use $now in the query. The subtle difference to understand is that we are creating $now totally relative to where we are (the site timezone) because we are interested in finding nodes in the future from us, not from from another timezone. However, we then convert it so that we can have them compared properly in the query.

A more complex example could be a range of times. Let's say we want all the nodes with the time of today between 16:00 and 18:00 (a 2 hour span).

I prefer to work directly with \DateTime and then wrap it into the Drupal wrapper just because i can have all the native methods highlighted by my IDE. So we can do something like this:

$timezone = drupal_get_user_timezone();
$start = new \DateTime('now', new \DateTimezone($timezone));
$start->setTime(16,0);
$start->setTimezone(new \DateTimeZone(DATETIME_STORAGE_TIMEZONE));
$start = DrupalDateTime::createFromDateTime($start);

$end = new \DateTime('now', new \DateTimezone($timezone));
$end->setTime(18, 0);
$end->setTimezone(new \DateTimeZone(DATETIME_STORAGE_TIMEZONE));
$end = DrupalDateTime::createFromDateTime($end);

$query = \Drupal::entityQuery('node');
$query
  ->condition('field_date', $start->format(DATETIME_DATETIME_STORAGE_FORMAT), '>=')
  ->condition('field_date', $end->format(DATETIME_DATETIME_STORAGE_FORMAT), '<=');
$results = $query->execute();

So first, we get the user timezone. drupal_get_user_timezone() returns for us the string representation of the timezone the current user has selected, or if they haven't, the site default timezone. Based on that, we create our native date object that represents the current point in time but set the actual time to 16:00. After that we set the storage timezone and create our Drupal wrapper so that we can format it for the query.

For the end date we do the same thing but we set a different time. Then we expectedly write our query conditions and ask for the entities which have a date between those 2 times.

The order of setting the time and timezone on the date object is important. We want to set the time before we set the timezone because the times we are looking for are relative to the current user, not to the storage timezone.

So that is pretty much it. Now you can query for entities and play with date fields without issues (hopefully).

Feb 20 2017
Feb 20

In this article we are going to look at how we can render images using image styles in Drupal 8.

In Drupal 7, rendering images with a particular style (say the default "thumbnail") was by calling the theme_image_style() theme and passing the image uri and image style you want to render (+ some other optional parameters):

$image = theme('image_style', array('style_name' => 'thumbnail', 'path' => 'public://my-image.png'));

You'll see this pattern all over the place in Drupal 7 codebases.

The theme prepares the URL for the image, runs the image through the style processors and returns a themed image (via theme_image()). The function it uses internally for preparing the url of the image is image_style_url() which returns the URL of the location where the image is stored after being prepared. It may not yet exist, but on the first request, it would get generated.

So how do we do it in Drupal 8?

First of all, image styles in Drupal 8 are configuration entities. This means they are created and exported like many other things. Second of all, in Drupal 8 we no longer (should) call theme functions like above directly. What we should do is always return render arrays and expect them to be rendered somewhere down the line. This helps with things like caching etc.

So to render an image with a particular image style, we need to do the following:

$render = [
    '#theme' => 'image_style',
    '#style_name' => 'thumbnail',
    '#uri' => 'public://my-image.png',
    // optional parameters
];

This would render the image tag with the image having been processed by the style.

Finally, if we just want the URL of an image with the image style applied, we need to load the image style config entity and ask it for the URL:

$style = \Drupal::entityTypeManager()->getStorage('image_style')->load('thumbnail');
$url = $style->buildUrl('public://my-image.png');

So that is it. You now have the image URL which will generate the image upon the first request.

Remember though to inject the entity type manager if you are in such a context that you can.

Jan 31 2017
Jan 31

Drupal 8 is very flexible when it comes to controlling access to your routes. It inherits quite a bit from the Symfony routing system, but adds its own flavour on top of that. In this article we are going to look at an example of a complex access requirement. In doing so, we won't cover the simpler use cases which are already described in the Drupal.org docs, but we will sure make use of some of them.

The requirement

So let's imagine this scenario: we have two types of users (employees and managers) whose persona is not determined by a user role. Let's say their "role" is determined on the fly as a result of an API call or some dynamic thing.

Now, let's say we have 3 routes: Route A (accessible for employees only), Route B (accessible for managers only) and Route C (accessible for both).

Finally, imagine we have a service called UserType which we can ask what type of person the current user is.

Implementation

One of the cool things about the Route access control in Drupal 8 is the ability, as the docs show, to delegate the access checking to a service. So a basic implementation for Route A and Route C can be something like this.

my_module.route_a:
  path: 'route-a'
  defaults:
    _controller: '\Drupal\my_module\Controller\DefaultController::buildRouteA'
    _title: 'Route A'
  requirements:
    _company_access_check_employee: 'true'

This is the route definition. As you can see, as per the docs, we have a requirement for the company_access_check access service to return the access result. So let's quickly see that service:

my_module.company_access_check:
    class:  Drupal\my_module\Access\CompanyAccessCheck
    arguments: ['@user_type']
    tags:
      - { name: access_check, applies_to: _company_access_check_employee }

A simple tagged service definition with a dependency to our fictitious UserType service that tells us the type of person the current user is. Additionally, we specify that this access checking service should be applied to all routes with the requirement _company_access_check_employee.

I am not going to show you this class because an example is already covered in the docs. However, it has one method called access() which by default gets passed the AccountInterface of the current user. So with the help of our UserType service we can determine whether the current user is an employee. Then we can return either AccessResult::forbidden() or AccessResult::allowed().

For managers, we do the same: create a new service and apply it to Route C.

So where does the complication come? Well, you guessed it: Route B which requires both. If we add two requirements to the route, let's say something like this:

my_module.route_b:
  path: 'route-b'
  defaults:
    _controller: '\Drupal\my_module\Controller\DefaultController::buildRouteB'
    _title: 'Route B'
  requirements:
    _company_access_check_employee: 'true'
    _company_access_check_manager: 'true'

It will check for both but grant access only if both return positive. So in our case this won't be very helpful since we need to check if the user is either. For the purposes of this article, please forgive the implication that managers are not also employees.

The solution

What we can do is create another access service called something like company_access_check_both which is responsible for determining if the current user is of one of the user roles. This is fine if our requirements are as simple as we described them. But what happens when we have multiple user types and a bunch of different routes where we have to mix and match the user types which have access to them? Creating a service for all these different types of combinations is not very efficient.

So instead, let's create a generic service called company_access_check_multiple AND specify in the route the type of user that has access to it in the form of a custom option. For example, the route definition can be something like this:

my_module.route_b:
  path: 'route-b'
  defaults:
    _controller: '\Drupal\my_module\Controller\DefaultController::buildRouteB'
    _title: 'Route B'
  requirements:
    _company_access_check_multiple: 'true'
  options:
    _company_access_users:
      - Employee
      - Manager

In this route we created a custom option called _company_access_users in which we list the types of users that should have access to it.

But how can we make use of this inside our service? Well, the Route object can be inspected and the list of allowed user types can be retrieved:

$types = $route->getOption('_company_access_users');

So if the route has that option, $types will tell us what type the current user needs to be in order to have access.

However, where do we get the Route object? As we know, the access() method of the service only receives the user account as a parameter. We might be tempted to inject the current route match service into our own. This does the trick, but only when the route in question is being checked upon a user actually going to it. It will miserably fail when a given route is being checked for access from another one (for example when building menu links).

If we dig deep and look closely, before our access() method is called, an arguments resolver is employed via the AccessArgumentsResolverFactory. This allows for the current user account to be passed to the access() method. But what not many people know is that if we type hint our access() method with either Route, RouteMatchInterface or Request, we will be getting those parameters as well. And in this case, the Route object is that of the route being checked for access rather than the current route.

So something like this:

public function access(AccountInterface $account, Route $route) {
  $types = $route->getOption('_company_access_users');
  // etc
}

So there you have it. A neat little trick that opens the door to some complex access restriction rules on your routes.

Jan 24 2017
Jan 24

Drupal 8 comes with a funky new feature that allows admins and editors to customize entity forms in more than one variant. That means they can have, for different purposes, different form modes that feature different fields, with different form display configuration, etc. Nice, right?

Although you can do this in Drupal 8, not much use has yet been made of these form modes. So if you create a form mode, you cannot easily render it. Even more so, Drupal core doesn't actually make use of them.

In this article we will, however, look at how we can programatically render entity forms which use a form mode that had been created by an admin in the UI. First though, how do we render a regular entity form in Drupal 8?

Regular entity forms

$form = \Drupal::service('entity.form_builder')->getForm($entity);

$form is now a renderable array for the entity passed to the getForm() method of the EntityFormBuilder service. The entity itself can be an existing one (which will show you the edit form with values pre-filled) or a new one you just created programatically.

It's that simple.

The EntityFormBuilder::getForm() method takes a second parameter though, namely $operation. Apart from the variable name, this reminds me of how an entity itself is rendered, the second parameter to the build method being a view mode. So you'd expect in this case $operation to be a form mode, right? Well, wrong. Ish.

When an entity is defined, for example Node, under the handlers key of the annotation we have some form handlers defined. Those are what the $operation parameter expects. So for example, if we want the delete form of the Node entity, we pass delete and we get a different form. Otherwise, we fallback to the default one which is used for create/edit (although we can also specify edit but it maps to the same class anyway).

Custom form modes

Continuing with the Node example, the entity type defines three handlers (operations): default, delete, edit. That is not a lot. Other entity types can define more or less and can be differently named.

So if we create a form mode in the UI, whose machine name ends up being create_editors (for example), how do we go about rendering the entity form for nodes using that form mode? Passing that machine name as the second parameter by itself won't do the trick because the Node entity has not defined that handler, and more importantly, it doesn't map to an actual form class.

To fix this, we can alter the entity definition and add our own form handler named as our custom form mode, mapped to the default Form class of the Node entity. Here is a snippet of code, sprinkled with explanatory comments, that takes care of our Node entity for a custom form mode called create_editors:

/**
 * Implements hook_entity_type_alter().
 */
function example_module_entity_type_alter(array &$entity_types) {
  // We get all form modes, for all entities, and loop through them.
  $form_modes = \Drupal::service('entity_display.repository')->getAllFormModes();
  foreach ($form_modes as $entity_type => $display_modes) {
    if ($entity_type !== 'node') {
      // We are only interested in adding a handler to the Node entity.
      continue;
    }

    $node_type = $entity_types[$entity_type];
    foreach ($display_modes as $machine_name => $form_display) {
      if ($machine_name !== 'create_editors') {
        // We are only interested in adding this form mode to the definition.
        continue;
      }
      // We get the default handler class. It will be enough for us.
      $default_handler_class = $node_type->getHandlerClasses()['form']['default'];
      // We set the form class, keyed by the machine name of our custom form mode.
      $node_type->setFormClass($machine_name, $default_handler_class);
    }
  }
}

So basically, we are supplementing the Node form handlers with a new one called create_editors which maps to the default form class, in this case Drupal\node\NodeForm. The form class itself is not so important because after it is built, if there is a form mode with that name, it will be used to override the default form with all the configuration of that form mode. So building our node form with our custom form mode would now go like this:

$form = \Drupal::service('entity.form_builder')->getForm($entity, 'create_editors');

And that is pretty much it. Of course you can loop through all the entity types and add all form modes if you want. But I always like to inject my custom functionality only to the extent I need, touching as little as possible.

Let me know how this works for you.

Jan 17 2017
Jan 17

The Drupal node access grants system has always been a powerful and flexible way to control access to your nodes. It's been there from Drupal 5 (if not earlier) and it continues to exist in Drupal 8 as we move forward. In this article, I want to quickly highlight this system from a D8 perspective and how I propose to use it in a OOP architecture.

What is it?

The node access grant system is a way by which you can control programatically and very granularly access to all four operations on your Drupal nodes (view, create, edit, delete). It allows to define certain realms of functionality (related to your access requirements) and a set of grants that are required for any of the four mentioned operations, within that realm. Users will then need to posses the grants in the respective realms in order to be granted access.

The two main components of this system are therefore:

  • The implementation of hook_node_access_records() which is called whenever a node is saved (or site-wide permissions rebuilt). It is responsible for storing the access requirements for that given node.
  • The implementation of hook_node_grants() which is called whenever a user is trying to access a node (or a query is being performed in the name of that user). It is responsible for presenting the grants for the current user, which if match the access requirements of the node, allows them access.

The great thing about this node access grants is that it's system-wide in the sense of who checks for the access. In contrast to implementing hook_node_access() which only is called when viewing a node on its canonical URL, the access grants are checked almost everywhere such as views or even custom queries with much ease.

Drupal 8

In Drupal 8 these 2 hooks remain the foundation of the node access grants system, albeit with type hinted parameters. This means that we need to place their implementation inside our .module files.

Node access grants are not used on every site because they serve relatively complex access rules. Complex access rules usually also require a fair bit of calculating what grants a particular node must have for a given realm, as well as whether a given user possesses them. For this very reason I am not so fond of having to put all this logic in my .module file.

So I came up with a basic developer module that defines an interface that has two methods: accessRecords() and grants(). Other modules which want to implement the access grants hooks can instead now create a service which implements this interface and tag it with node_access_grants. My module will do the rest and you won't have to touch any .module file. You can inject whatever dependencies from the container you need and perform whatever logic is needed for determining your grants and access records.

Let me what you think down in the comments. Would love your feedback.

Jan 09 2017
Jan 09

Have you ever needed to render certain pages (or groups of pages) with a different theme than the default one configured for the site? I did. And in this article I'm going to show you how it's done in Drupal 8. And like usual, I will illustrate the technique using a simple use case.

The requirement

Let's say we have a second theme on our site called gianduja since we just love the chocolate from Torino so much. And we want to apply this theme to a few custom routes (the content rendered by the respective controllers is not so important for this article). How would we go about implementing this in a custom module called Gianduja?

The solution

First, we need a route option to distinguish these routes as needing a different theme. We can call this option _custom_theme and its value can be the machine name of the theme we want to render with it. This is how a route using this option would look like:

gianduja.info:
  path: '/gianduja/info'
  defaults:
    _controller: '\Drupal\gianduja\Controller\GiandujaController::info'
    _title: 'About Gianduja'
  requirements:
    _permission: 'access content'
  options:
    _custom_theme: 'gianduja'

Just a simple route for our first info page. You can see our custom option at the bottom which indicates the theme this route should use to render its content in. The Controller implementation is outside the scope of this article.

However, just adding an option there won't actually do anything. We need to implement a ThemeNegotiator that looks at the routes as they are requested and switches the theme if needed. We do this by creating a tagged service.

So let's create a simple class for this service inside the src/Theme folder (directory/namespace not so important):

namespace Drupal\gianduja\Theme;

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Theme\ThemeNegotiatorInterface;

/**
 * Our Gianduja Theme Negotiator
 */
class ThemeNegotiator implements ThemeNegotiatorInterface {

  /**
   * {@inheritdoc}
   */
  public function applies(RouteMatchInterface $route_match) {
    $route = $route_match->getRouteObject();
    if (!$route instanceof Route) {
      return FALSE;
    }
    $option = $route->getOption('_custom_theme');
    if (!$option) {
      return FALSE;
    }

    return $option == 'gianduja';
  }

  /**
   * {@inheritdoc}
   */
  public function determineActiveTheme(RouteMatchInterface $route_match) {
    return 'gianduja';
  }
}

As you can see, all we need to do is implement the ThemeNegotiatorInterface which comes with two methods. The first, applies(), is the most important. It is run on each route to determine if this negotiator provides the theme for it. So in our example we examine the Route object and see if it has the option we set in our route. The second, determineActiveTheme() is responsible for providing the theme name to be used in case applies() has returned TRUE for this route. So here we just return our theme name. All pretty straightforward.

Lastly though, we need to register this class as a service in our gianduja.services.yml file:

services:
    theme.negotiator.gianduja:
        class: Drupal\gianduja\Theme\ThemeNegotiator
        tags:
          - { name: theme_negotiator, priority: -50 }

This is a normal definition of a service, except for the fact that we are applying the theme_negotiator tag to it to inform the relevant container compiler pass that we are talking about a theme negotiator instance. Additionally, we are also setting a priority for it so that it runs early on in the theme negotiation process.

And that is pretty much it. Clearing the cache and hitting our new route should use the gianduja theme if one exists and is enabled.

Using this example, we can create more complex scenarios as well. For one, the theme negotiator class can receive services from the container if we just name them in the service definition. Using these we can then run complex logics to determine whether and which theme should be used on a certain route. For example, we can look at a canonical route of an entity and render it with a different theme if it has a certain taxonomy tag applied to it. There is quite a lot of flexibility here.

Jul 26 2016
Jul 26

The content_type ctools plugin is the most used type of ctools plugin in Drupal 7. It allows us to quickly build complex (and configurable) components that can be used in the Panels interface. They are quick to set up, the easiest start being the definition of the $plugin array and the implementation of the plugin render function in a .inc file. Have you ever wondered though what the $subtype parameter of this render function is and what it serves?

Most of the time our content_type plugins only have one type so the $subtype argument is the same name as the plugin (and file name). However, it's possible to have multiple subtypes that have slight (but critical) differences while sharing common functionalities. Not many people are familiar with that. Intrigued? Let's see how they work.

When content_type plugins are being processed (loaded, prepared for use and cached), ctools asks them whether there are any subtypes it would like to define or they are single. By default the latter is true but in order to define variations we can either populate an array of subtype definitions in the main $plugin array or implement a function with a specific naming convention: module_name_plugin_name_content_type_content_types. This callback then needs to return the plugin information for all the subtypes of this plugin.

But since it's easier to show than explain, let's take a look at an example. Imagine you need a simple content_type plugin that outputs data which depends on a certain ctools context. You can define your plugin as such:

$plugin = array(
  'title' => t('My plugin'),
  'description' => t('My plugin description'),
  'category' => t('My category'),
  'required context' => new ctools_context_required(t('Node'), 'node'),
);

This is a simple example of a plugin that depends on the Node context. But what if you want it to depend on the Node context OR the current User context? In other words, it should work on the node_view page manager template or the user_view one. Or whatever page these contexts are on but nowhere else.

Instead of required context you could use 'all contexts' => true. But this would then pass in to your render function all the available contexts. And this is neither elegant nor a statement of dependency on one of those two contexts. In other words, it will be available on all page manager pages but maybe won't do anything on most and it's up to the render function to handle extra logic for checking the contexts.

This is where plugin subtypes come to help out. Since your render function does the exact same regardless of context (or very similar), you can have a subtype for each. So let's see how that's done.

First, we simplify the main plugin array:

$plugin = array(
  'title' => t('My plugin'),
  'description' => t('My plugin description'),
  'category' => t('My category'),
);

Then we implement the function that returns the subtypes (following this naming convention):

function my_module_my_plugin_content_type_content_types() {
  return array(
    'node' => array(
      'title' => 'My plugin for nodes',
      'required context' => new ctools_context_required(t('Node'), 'node'),
    ),
    'user' => array(
      'title' => 'My plugin for users',
      'required context' => new ctools_context_required(t('User'), 'user'),
    ),
  );
}

The subtype machine name is the key in the array and the rest is regular plugin definition as we are used to. In our case we define two, each for their respective dependencies. And with this in place we achieve a number of things.

First, we can add the My plugin for nodes content_type plugin whenever the Node context is available and the My plugin for users when the User context is present. They cannot be used in other cases. Second, we ensure that whatever context is passed to the render function is either a Node or a User (nothing else). This can come in really handy when your context is custom and wraps an object that implements a common interface. Third, the $subtype argument to the render function now will be either node or user which is helpful to maybe slightly fork the functionality depending on the subtype.

Clear the caches and give it a go. Let me know how it works out.

May 10 2016
May 10

Have you ever needed to run a custom query that returns all the nodes which reference two or more taxonomy terms? I have, and most of the time it was very simple because the requirement was for nodes which reference either term, rather than ALL the terms.

When we are dealing with an OR type of select query, it couldn't be easier:

$query = db_select('node', 'n');
$query->join('taxonomy_index', 'ti', 'ti.nid = n.nid');
$query->condition('ti.tid', array(1, 2));
$query->fields('n', array('nid'));
$result = $query->execute();

The above example keeps things simple by assuming the term reference maintains an index in the taxonomy_index table and that we already have our term IDs.

Things get a bit more complicated when we are trying to query the nodes which reference both term 1 AND term 2. After banging my head against the wall for a bit, I came up with a solution inspired by how Views generates its query:

$tids = array(1, 2);
$query = db_select('node', 'n');
foreach ($tids as $key => $tid) {
  $query->innerJoin('taxonomy_index', 'ti_' . $key, 'ti_' . $key . '.nid = n.nid AND ti_' . $key . '.tid = ' . $tid);
}
foreach ($tids as $key => $tid) {
  $query->condition('ti_' . $key . '.tid', $tid);
}
$query->fields('n', array('nid'));
$result = $query->execute();

So basically the solution is to create a join for each term ID we want to filter by. A crucial part of this is that the join needs to happen on the node ID between the two tables (as expected) but also on the term ID we are using for the filter matching the record in the taxonomy_index table. This will ensure that the two joins are not the same but that they reflect the relation between the node record and each individual term ID. Are you still following? Then, we just add our conditions on the newly created joins.

Caveats

This should work, and depending on the size of your dataset, it should not have too much of a performance impact. However, as no joins should be done if not absolutely necessary, investigate the possibility of querying for the nodes that reference the first term and then filtering the rest out using PHP. This can be a viable option if you know that usual result sets are not too big so you are not running array_filter() on 2000 terms. And of course, when possible, cache the query appropriately.

Dec 08 2015
Dec 08

Behat is a great testing framework for running behaviour driven testing (in BDD) against your site. The Drupal extention for Behat allows a tighter integration with Drupal that makes propping up tests for a Drupal site that much faster.

In this article we are going to look at a solution for having dummy content available on a Drupal 7 installation that allows Behat to run its tests against. We are not going to cover the basics of Behat or test driven development so I suggest you check out the resources I mentioned above and others for getting up to speed with those issues if you are not already.

The problem

Unlike testing frameworks like Simpletest, Behat runs your tests against the current site (Drupal environment in our case). You may use a CI tool that replicates your production site somewhere on another server and then runs the tests against that instance. However, in many cases you will need to have some dummy content configured in a specific way that validates the functionalities you've built for the site. This is especially true during development. Moreover, you need to also ensure that all cases of your tests can be tested (not just the ones that happen to be triggered by the content of your current production db).

A handy solution

One solution is to write scenarios or backgrounds that create said content and remove it after the tests. This is the approach of Simpletest-like integration tests. However, a better (and faster) way is to use the Migrate module and create migrations for the dummy content that just needs to be there. With a CSV source for your data, you can very quickly set up some node or other kind of migrations that you can run and rollback whenever you want.

The great part of this approach is that you can then leverage Behat hooks to run your migrations before the test suite starts and roll them back when it ends. Or at any step you want. This allows you to leave the site in a clean state after tests have run and you avoid having to manually run the migrations before and roll them back after.

A Fixture trait

Since you may have more than one method related to fixturizing your environment for the tests, you can define a Trait that you can use inside the FeatureContext class of your Behat testing setup. In there you can put all the related methods, such as the ones tagged with the @BeforeSuite and @AfterSuite Behat tags.

Let's see a quick example setup:

/**
 * @BeforeSuite
 */
public static function enableFixtureModules(\Behat\Testwork\Hook\Scope\BeforeSuiteScope $scope) {
  module_enable(array('migrate', 'my_example_migration_module'));
}

This method is run whenever the Behat testing suite is started and all it does is enable the relevant modules. The my_example_migration_module module contains our migrations.

It's counterpart that runs at the end of the suite would be this:

/**
 * @AfterSuite
 */
public static function disableFixtureModules(\Behat\Testwork\Hook\Scope\AfterSuiteScope $scope) {
  module_disable(array('migrate', 'my_example_migration_module'));
}

The method names are not important as Behat looks at the docblock for the tags that start with the @ sign.

Now we have Migrate and our migration module enabled while the test is running. Let's also set up the methods responsible for actually running the migrations.

/**
 * @BeforeFeature @fixtures
 */
public static function runAllMigrations(BeforeFeatureScope $scope) {
  $machine_names = self::getAllFixtureMigrations(true);
  foreach ($machine_names as $machine_name) {
    self::runMigration($machine_name);
  }
}

This method is called by Behat before each testing Feature that has the @fixtures tag on it. Its counterpart for when the Feature is done would be this:

/**
 * @AfterFeature @fixtures
 */
public static function revertAllMigrations(AfterFeatureScope $scope) {
  $machine_names = self::getAllFixtureMigrations();
  self::revertMigrations($machine_names);
}

Let's take a quick look at getAllFixtureMigrations():

protected static function getAllFixtureMigrations($register = false) {
  if (!module_exists('my_example_migration_module')) {
    return array();
  }

  module_load_include('inc', 'my_example_migration_module', 'my_example_migration_module.migrate');
  $migrations = my_example_migration_module_migrate_api();
  $machine_names = array();
  foreach ($migrations['migrations'] as $name => $migration) {
    $machine_names[] = $name;
  }

  if ($register) {
    migrate_static_registration($machine_names);
  }

  return $machine_names;
}

In this method we return all the migrations defined in our my_example_migration_module module. Depending on the $register parameter, we also statically register them so they can be run.

Now let's see what runMigration is all about:

protected static function runMigration($machine_name) {
  $migration = Migration::getInstance($machine_name);
  $dependencies = $migration->getHardDependencies();
  if ($dependencies) {
    foreach ($dependencies as $name) {
      self::runMigration($name);
    }
  }
  $migration->processImport();
}

This method simply loads a migration, runs the import on its dependencies and then on the original migration. This way we ensure that the migration has its dependencies already met.

Finally, let's see what the revertMigrations is all about:

protected static function revertMigrations($machine_names) {
  $dependencies = array();
  foreach ($machine_names as $machine_name) {
    $migration = Migration::getInstance($machine_name);
    $dependencies += $migration->getDependencies();
  }

  foreach ($dependencies as $dependency) {
    $dependencies[$dependency] = $dependency;
  }

  // First revert top level migrations (no dependencies)
  foreach ($machine_names as $machine_name) {
    if (in_array($machine_name, $dependencies)) {
      continue;
    }
    self::revertMigration($machine_name);
  }

  if ($dependencies) {
    self::revertMigrations($dependencies);
  }
}

This is is a bit more complex, but not really. First, it loads each migration and creates an array of migrations which are dependencies of others (these need to be reverted last). Then it reverts all the migrations which are not a dependency of any other migration. The method for actually reverting the migration is simple:

protected static function revertMigration($machine_name) {
  $migration = Migration::getInstance($machine_name);
  $migration->processRollback(array('force' => true));
}

Lastly, though, the revertMigrations() method runs itself again passing the array of migrations which were a dependency. This way they get re-processed and reverted in the right order (migrations that are not a dependency first) until no migrations are left.

And this is pretty much it. We have a rudimentary run-all-migrations-on-this-feature kind of content fixture solution.

You can take it way further though to increase performance and flexibility. You can group your migrations depending on whatever criteria you want, and create various tags that only import and rollback the right migrations (depending on the actual feature being run).

Hope this helps.

Nov 09 2015
Nov 09

Have you ever needed to override a Queue in Drupal 7? For example, the reliable database SystemQueue? It's actually quite easy and very flexible as well. Let me first tell you the use case we are going to work with in this article.

Let's say that we want to make sure that when adding items to a queue, those items don't already exist in the queue table. That's actually a fair request in my opinion. An option would be to make a query and see if the item already exists before delegating its creation to the responsible Queue class. However, we'd have to deal with querying for serialised data and is just not performant.

A better way is to use our own DrupalQueueInterface implementation:

/**
 * Custom implementation of the DrupalQueueInterface
 */
class MyCustomQueue extends SystemQueue {

  /**
   * Overriding the method to make sure no duplicate queue items get created
   * but that the items are updated if the exist.
   */
  public function createItem($data) {

    $serialized = serialize($data);

    $query = db_merge('queue')
      ->key(array('name' => $this->name, 'data' => $serialized))
      ->fields(array(
        'name' => $this->name,
        'data' => $serialized,
        'created' => time(),
      ));
    return (bool) $query->execute();
  }
}

As you can see, we are extending from the good ol' SystemQueue but overriding it's createItem() method. Instead of the db_insert() statement with which items were persisted, we are using a db_merge() statement to UPSERT the items. This means that if the items already exit, they get updated. If not, they get created. Which is exactly what we want.

Lastly, we need to make sure this class is being used for our queue. Again the solution is simple. Let's say our queue name is my_custom_queue. When requesting it like so:

DrupalQueue::get('my_custom_queue');

... Drupal looks in the variables table for a variable called queue_class_my_custom_queue. If it finds it, it will try to instantiate a class that has the name specified as the variable value (if it also implements DrupalQueueInterface). If there is no such variable, it falls back to the default one which is SystemQueue.

So this means that our module needs to create that variable so that when we are requesting this particular queue, we get an instance of our own class. We can do this inside install and uninstall hooks:

/**
 * Implements hook_install().
 */
function my_module_install() {
  variable_set('queue_class_my_custom_queue', 'MyCustomQueue');
}

/**
 * Implements hook_uninstall().
 */
function my_module_uninstall() {
  variable_del('queue_class_my_custom_queue');
}

And that is pretty much it. Now our queue will use the custom class we wrote and we can make sure no items are duplicated.

Hope this helps.

Oct 20 2015
Oct 20

Have you ever needed to perform an action after a node has been inserted or updated? In this article we are going to see how we can trigger functionality after nodes have been inserted or updated. And no, it's probably not what you think.

By default, there is no hook that provides this in Drupal core. Sure, you have hook_node_insert(), hook_node_update() and hook_node_presave() but all of these are called within the scope of node_save(). This is important because, at this point, we cannot rely on the database for any data that may have been affected by the node save process. As the documentation for hook_node_insert() says:

when this hook is invoked, the changes have not yet been written to the database, because a database transaction is still in progress.

When you have to deal with something totally external to the node in question, this may not be a problem. Heck, you might not even need the database. But there are those one or two cases in which you do need data that has been affected by the process.

For example, when inserting a new node, various actions take place. One of them can be Pathauto doing some magic with the node title and saving a path alias for this node. So if you need to alter this final alias in the scope of hook_node_insert(), you cannot rely on something like path_load() to get the node alias data because it might have not yet been written. I've actually seen it return different things in different cases.

What you can do then is register a function with Drupal that will get called just about when Drupal is finished with the request. It's actually very simple. You just call drupal_register_shutdown_function() with the name of the function you want to be called. Additionally, you can pass as further arguments whatever it is in your context you want passed to it. It's kinda like subscribing a function to an event.

So now when the request is finishing, we know the node_save() database transaction has completed and we can rely on the data from the database. Using path_load() now will guarantee that the latest path for that node is being loaded.

Hope this helps.

Sep 30 2015
Sep 30

If you are a reader of Webomelette.com you probably know it's been a while since any love has been given to this website. I decided recently to right this wrong and release a refreshed version. Lo and behold, the new version of Web Omelette!

I think it looks a bit fresher, crisper and should be a bit more performant as well. Additionally, I fixed some of the problems we had with copying code fragments by using the SyntaxHighlighter plugin for displaying code fences. This should also make them a bit more readable.

Moreover, you'll notice in the listing also external articles I've written for other websites. Feel free to check out those write-ups as well.

Please let me know if you encounter any bugs or issues with the website. I'd very much appreciate that.

Aug 10 2015
Aug 10

Today I would like to introduce a new module that I released for the Drupal (developer) community to use and share: Info Plugins. This is for developers who are tired of implementing a bunch of messy _info hooks (and their corresponding callbacks), lumping together functionality that frankly shouldn't even touch. I'm talking about those ugly switch statements in which we have cases for the various extensions we provide. Don't get me wrong Drupal, I love your hook system.

With Info Plugins, much (and progressively more and more) of this becomes cleaner by exposing all those extension points to the cTools plugin system. What I mean by this is that using this module you will be able to declare things like Drupal blocks, filters, field formatters and more, as cTools plugins. This way, all the logic related to one plugin (block, filter or field formatter to continue with the above examples) resides neatly within one single plugin include file.

Let us look at an example a bit more in depth: the Drupal block. Instead of implementing up to 4 hooks (_info, _view, _configure and _save) to manage your blocks, you can now define a new core_block plugin within your cTools plugins folder like so:

$plugin = array(
  'title' => t('Example block'),
  // Your own callback for building the display of the block (called by `hook_block_view()`)
  // Leaving this empty, the function name would default to `my_module_example_block_view()`
  'view' => 'my_module_render_example_block',
  // Your own callback for building the config form for the block (called by `hook_block_configure()`)
  // Leaving this empty, the function name would default to `my_module_example_block_configure()`
  'configure' => 'my_module_configure_example_block',
  // Your own callback for saving the config for the block (called by `hook_block_saved()`)
  // Leaving this empty, the function name would default to `my_module_example_block_save()`
  'save' => 'my_module_save_example_block',
  // ... all other options you may want to pass to `hook_block_info()`
);

/**
 * Returns a renderable array that represents the block content, i.e. 
 * the same as you would return from `hook_block_view()`.
 *
 * @param $delta
 *   The block delta
 */
function my_module_render_example_block($delta) {
  return array(
    '#type' => 'markup',
    '#markup' => 'My custom example block'
  );
}

/**
 * Returns a form to be used as the block configuration form, i.e. the same
 * as you would return from `hook_block_configure()`
 *
 * @param $delta
 *   The block delta
 */
function my_module_configure_example_block($delta) {
  $form = array();
  $form['my_custom_field'] = array(
    '#type' => 'textfield',
    '#title' => t('My custom block field'),
    '#default_value' => variable_get($delta, '')
  );

  return $form;
}

/**
 * Saves the block configuration, i.e. the same as you would do inside
 * `hook_block_save()`
 *
 * @param $block
 *   An array of values representing the block with it's configuration, i.e. the
 *   `$edit` array passed to `hook_block_save()`
 */
function my_module_save_example_block($block) {
  variable_set($block['delta'], $block['my_custom_field']);
}

So as you can see, your block definition, render and configuration resides in one file. If you need more blocks, you just define more plugins and you are good to go. There is such a documentation oriented example inside the plugin_examples folder of the module for each available plugin type. Plus, don't forget the README.md file.

Once you install the module, you will have only one administration screen at admin/config/info-plugins where you'll be able to select which plugin types you need. For example, if you need to define a custom block, enable the Core Block plugin type. If you need others, enable them as well. But I recommend you keep them disabled if you don't use them so that their logic doesn't get included in memory (all the relevant hooks and what not). My goal here is to keep a very low foot print.

To see which plugin types are available to use, please consult the project page. And keep checking back because I will add more. And if you want to contribute, please don't hesitate. Take it out for a spin, give it a test and please open issues to let me know of any bugs you find. I will be active on this for a while and want to hammer out all the potential problems before creating a stable release.

Cheers!

Aug 03 2015
Aug 03

Views Bulk Operations (VBO) is a powerful module that leverages Views to allow site administrators to perform bulk operations on multiple entities at once. It does so efficiently by processing the items in batches over multiple requests to avoid timeouts.

Installing the module will already provide you with a host of various actions you can perform in bulk on various entities. You can publish 1000 nodes at once, delete them or even change their author. And these are just a few examples of what you can do.

In this article we are going to look at programatically creating our own action that we can trigger with VBO to affect multiple node entities. Sometimes you need to write your own because the use case does not quite fit in the extensive list of actions the module provides.

For our example, let's assume we have an entity reference field called field_users on both the article and basic page content types. This field can reference whatever user it wants. And the requirement is to be able to bulk update the value of this field on a bunch of nodes of both these node types at once.

Out of the box, VBO provides us with an action to change the value of a field but this doesn't help us in this case. When adding a value to this field via VBO, we are presented with as many instances of the field as different node types are in the selection. And this is not ideal if we want to scale the functionality to more than one content type. What we want is to select a number of nodes and then only once provide a value to this field. So let's see how we can define a custom VBO action for this use case.

The action

To define a new action we need to implement hook_action_info():

/**
 * Implements hook_action_info().
 */
function my_module_action_info() {
  return array(
    'my_module_my_custom_action' => array(
      'type' => 'entity',
      'label' => t('Add a user to Users field'),
      'behavior' => array('changes_property'),
      'configurable' => TRUE,
      'vbo_configurable' => FALSE,
      'triggers' => array('any'),
    ),
  );
}

With this hook implementation we are defining our own action called my_module_my_custom_action which is available to be triggered on all entity types (because we specified entity for the type) and it acts as a property changer. It is configurable using the default Action API but we don't need any kind of VBO specific configuration. For more information on all the values that you can pass here, feel free to consult the documentation page for VBO.

Next, it's time to create the configuration form for this action, namely the form that will be presented to us to select the user we want to add to the field_users reference field:

function my_module_my_custom_action_form() {
  $form = array();
  $form['user'] = array(
    '#type' => 'textfield',
    '#title' => t('User'),
    '#maxlength' => 60,
    '#autocomplete_path' => 'user/autocomplete',
    '#weight' => -1,
  );

  return $form;
}

The function name takes from the machine name of the action suffixed by _form and is responsible for creating and returning a form array. All we need is one field which uses the core user/autocomplete path to load users via Ajax. Simple enough.

So now after we make a bulk selection and choose our action, we'll be prompted with this form to choose the user we want to add to the reference field. It follows to couple it with a submit handler that will save the value into the context of the operation:

function my_module_my_custom_action_submit($form, &$form_state) {
  $uid = db_query('SELECT uid from {users} WHERE name = :name', array(':name' => $form_state['values']['user']))->fetchField();
  return array(
    'uid' => $uid,
  );
}

The naming of this function is similar to the previous one except for the suffix being _submit this time around. In it, we load from the database the uid of the user that was referenced in the form field by name and return that inside an array. The latter will then be merged into the $context variable available in the next step.

So it's now time to write the final function which represents this step by adding the selected user to the existing ones in that field across all the selected nodes, regardless of their type:

function my_module_my_custom_action(&$entity, $context) {
  if (!isset($entity->field_users)) {
    return;
  }

  if (!isset($context['uid'])) {
    return;
  }

  if (!empty($entity->field_users)) {
    foreach ($entity->field_users[LANGUAGE_NONE] as $ref) {
      if ($ref['target_id'] === $context['uid']) {
        return;
      }
    }
  }

  $user =  array(
    'target_id' => $context['uid'],
  );

  if (!empty($entity->field_users)) {
    $entity->field_users[LANGUAGE_NONE][] = $user;
    return;
  }

  $entity->field_users[LANGUAGE_NONE] = array($user);
}

The name of this function is exactly the same as the machine name of the action, the reason for which we prefixed the latter with the module name. As arguments, this function gets the entity object that is being changed (by reference) and the context of the operation.

We start by returning early if the current entity doesn't have our field_users field or if by any chance the uid key is not available inside $context. Then we loop through all the values of the field and return if the selected uid already exists (we don't want to add it twice). And last, we add the selected uid to the list of existing users in the field by taking into account the possibilities that the field can be empty or it can already contain values. After passing through this action, VBO will automatically save the node with the changes for us.

And that is pretty much it. Clearing the cache will make the new action available in the VBO configuration of your view. Adding it will then allow you to select as many nodes as you want, specify a user via the autocomplete field and have that user be added to the field_users field of all those nodes. And the cool thing is that you can select any node you want: if the field doesn't exist on that content type, it will just be skipped gracefully because we are checking for this inside the action logic.

Hope this helps.

Jun 29 2015
Jun 29

That is the main question. If you came here looking for a definitive answer, I'm afraid you won't find one. What you maybe will find is a discussion I propose on this topic and my two cents on the matter.

Why am I talking about this?

I've been working on a big Drupal website recently which has many contributed and custom modules. One of my recent tasks has been enabling validation of an existent text field used for inputting phone numbers. The client needed this number in a specific format. No problem, a quick regex inside hook_node_validate() should do the trick nicely. But then it got me thinking? Isn't there a module I can use for this instead? Well yes there is: Field validation.

I installed this module which comes with a plethora of validation rules and possibilities. The default phone validation for my country was not matching the client expectation so I had to use a custom expression for that. No problem, achieved basically the same result. But was this the better option under the circumstances? You might say yes because people have been working on this module a long time to perfect it, keep it secure and provide all sorts of goodies under the hood. Not to mention that it's used on over 10.000 websites.

However, the Field Validation module is big. It has a bunch of functionality that allows you to perform all sorts of validation on fields. This is not a bad thing, don't get me wrong. But does my little validation need warrant the installation and loading into memory of so much code? My custom solution was very targeted and took no more than 10 or so lines of code.

One argument would be that yes, because I may need other kinds of validation rules in the future so you can use this module also for those. But I think that being already very far in the lifetime of this website the odds are quite low of that. And even if this is the case, will an extra 2-3 validation needs warrant the use of this module?

On the other hand, you can argue that your custom code is not vetted, is difficult to maintain, can be insecure if you make mistakes and basically represents some non-configurable magic on your site. These can all be true but can also all be false depending on the developer, how they document code and the functionality itself.

I ended up with the custom solution in this case because on this site I really want to introduce new modules only if they bring something major to the table (performance being my concern here). So of course, the choice heavily depends on the actual module you are considering, the website it would go on and the custom code you'd write as an alternative.

Moreover, please do not focus on the actual Field Validation module in this discussion. I am not here to discuss its merits but the whether or not installing any such module that serves a tiny purpose is the right way to go. This is mostly a Drupal 7 problem as in D8 we use object oriented practices by which we can have as much code as we want because we only load the necessary parts when needed.

So what do you think? Do you have a general rule when it comes to this decision or you also take it case by case basis? If the latter, what are your criteria for informing your choice? If the former, why is this? I'd love to hear what you have to say.

Jun 15 2015
Jun 15

In this article we are going to look at how to use the ThirdPartySettingsInterface to add some extra data to existing configuration entities. For example, if you ever need to store some config together with a node type or a taxonomy vocabulary, there is a great way to do so using this interface. Today we are going to see an example of this and add an extra field to the menu definition and store the value in this way.

There are a number of steps involved in this process. First, we need to alter the form with which the entity configuration data is added and saved. In the case of the menu entity there are two forms (one for adding and one for editing) so we need to alter them both. We can do something like this:

/**
 * Implements hook_form_alter().
 */
function my_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id === 'menu_add_form' || $form_id === 'menu_edit_form') {
    my_module_alter_menu_forms($form, $form_state, $form_id);
  }
}

Inside this general hook_form_alter() implementation we delegate the logic to a custom function if the form is one of the two we need. Alternatively you can also implement hook_form_FORM_ID_alter() for both those forms and delegate from each. That would limit a bit on the function calls. But let's see our custom function:

/**
 * Handles the form alter for the menu_add_form and menu_edit_form forms.
 */
function my_module_alter_menu_forms(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $menu = $form_state->getFormObject()->getEntity();
  $form['my_text_field'] = array(
    '#type' => 'textfield',
    '#title' => t('My text field'),
    '#description' => t('This is some extra data'),
    '#default_value' => $menu->getThirdPartySetting('my_module', 'my_text_field'),
    '#weight' => 1
  );

  if (isset($form['links'])) {
    $form['links']['#weight'] = 2;
  }

  $form['#entity_builders'][] = 'my_module_form_menu_add_form_builder';
}

In here we do a couple of things. First, we retrieve the configuration entity object which the form is currently editing. Then, we define a new textfield and add it to the form. Next, we check if the form has menu links on it (meaning that it's probably the edit form) in which case we make its weight higher than one of our new field (just so that the form looks nicer). And last, we add a new #entity_builder to the form which will be triggered when the form is submitted.

The getThirdPartySetting() method on the entity object is provided by the ThirdPartySettingsInterface which all configuration entities have by default if they extend from the ConfigEntityBase class. With this method we simply retrieve a value that is stored as third party for a given module (my_module in this case). It will return NULL if none is set so we don't even need to provide a default in this case.

Let us now turn to our #entity_builder which gets called when the form is submitted and is responsible for mapping data to the entity:

/**
 * Entity builder for the menu configuration entity.
 */
function my_module_form_menu_add_form_builder($entity_type, \Drupal\system\Entity\Menu $menu, &$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  if ($form_state->getValue('my_text_field')) {
    $menu->setThirdPartySetting('my_module', 'my_text_field', $form_state->getValue('my_text_field'));
    return;
  }

  $menu->unsetThirdPartySetting('my_module', 'my_text_field');
}

Inside we check if our textfield was filled in and set it to the third party setting we can access from the config entity object that is passed as an argument. If the form value is empty we reset the third party setting to remove lingering data in case there is something there.

And that's pretty much it for the business logic. We can clear the cache and try this out by creating/editing a menu and storing new data with it. However, our job is not quite finished. We need to add our configuration schema so that it becomes translatable. Inside the /config/schema/my_module.schema.yml file of our module we need to add this:

system.menu.*.third_party.my_module:
  type: mapping
  label: 'My module textfield'
  mapping:
    my_text_field:
      type: text
      label: 'My textfield'

With this schema definition we are basically appending to the schema of the system.menu config entity by specifying some metadata about the third party settings our module provides. For more information on config schemas be sure to check out the docs on Drupal.org.

Now if we reinstall our module and turn on configuration translation, we can translate the values users add to my_text_field. You go to admin/config/regional/config-translation/menu, select a menu and when translating in a different language you see a new Third Party Settings fieldset containing all the translatable values defined in the schema.

Hope this helps.

Jun 02 2015
Jun 02

In this article we are going to look at how we can create and use pseudo-fields in Drupal 8.

What are pseudo-fields?

Pseudo-fields are simple display fields that you can control from the display settings of a particular entity type. An example of such a field is the core Links field on the node or comment entities.

Why are they useful?

Pseudo-fields are great if you have some content or data that you need to render together with that of a particular entity. And since you don't want to be hacky and hardcode all of this inside a template or preprocessor, you can use pseudo-fields to expose some control over this to the UI. This means that you can use the core drag-and-drop functionality to control their visibility and position relative to regular entity fields.

Pseudo-fields are a great way to display data that is tightly coupled to the entities but is not part of them or their fields.

So how do they work?

There are 2 main steps we need to take in order to create a pseudo-field. First, we need to implement hook_entity_extra_field_info() which is similar to Drupal 7.

/**
 * Implements hook_entity_extra_field_info().
 */
function my_module_entity_extra_field_info() {
  $extra = array();

  foreach (NodeType::loadMultiple() as $bundle) {
    $extra['node'][$bundle->Id()]['display']['my_own_pseudo_field'] = array(
      'label' => t('My own field'),
      'description' => t('This is my own pseudo-field'),
      'weight' => 100,
      'visible' => TRUE,
    );
  }

  return $extra;
}

We mustn't forget to use the NodeType class at the top of the file:

use Drupal\node\Entity\NodeType;

With this implementation we are creating one pseudo-field called My own field that will show up on the display settings of all the node bundles. After clearing the cache, you can already see it if you go to the display settings of any node bundle you have.

drupal 8 pseudo fields

The second step is making this field actually render something when the node is being viewed. For this we need to implement hook_entity_view() or any of its variants:

/**
 * Implements hook_ENTITY_TYPE_view().
 */
function my_module_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode, $langcode) {
  if ($display->getComponent('my_own_pseudo_field')) {
      $build['my_own_pseudo_field'] = [
        '#type' => 'markup',
        '#markup' => 'This is my custom content', 
    ];
  }
}

And again, let's use the necessary classes at the top:

use \Drupal\Core\Entity\EntityInterface;
use \Drupal\Core\Entity\Display\EntityViewDisplayInterface;

Above we went with the hook_ENTITY_TYPE_view() variant that applies to the node entity. Inside, we are being passed an EntityViewDisplayInterface display object which we can use to check whether or not our own component (the one we defined earlier) exists in this display. If it does, we add our custom data to the $build render array that is passed by reference. This check allows the user interface to determine the visibility of this component on each view mode, as well as the weight (position relative to the other components which can be either entity fields or other such pseudo-fields).

And that's about it. You can save, edit the display settings of your nodes, create view modes and specify exactly for which one and where this custom content should show up.

Hope this helps.

May 25 2015
May 25

I was working on a big website with many contrib and custom modules. And I had to debug a very annoying redirect that started happening sometime in the recent past, not sure when. Some pages simply just redirected to other URLs.

I figured out that the problem was one of a 301 redirect. My browser told me that at least. But good luck figuring out where in the code I can find the culprit. Xdebug breakpoints everywhere but to no avail. A search for drupal_goto in the custom modules directory didn't help either, and God be with anyone trying to search through a contrib folder of that size.

Then it hit me. Isn't there a hook invoked inside drupal_goto? At this point I was assuming (and hoping really) that the redirect was happening somehow with a drupal_goto. And it turns out there is one: hook_drupal_goto_alter.

Armed with a new dose of hope, I implemented the hook and cleared the cache. Inside, I added the obligatory $test = ''; statement and put a breakpoint on it. Let's see what happens. After loading one of the offending pages, the breakpoint halted the execution and the Xdebug call stack in my PHPStorm immediately pointed out the problem: Global Redirect. There was some URL rewriting happening on the site so GR got a bit confused and was redirecting back to the original path. The details of the issue are however not important.

My point is that using this hook, I could see exactly who and why was calling drupal_goto. I didn't use it for anything else, apart from learning why the redirect is happening which in turn allowed me to write some code that prevented that.

Awesome. I learned about a new hook. And maybe now you as well.

May 18 2015
May 18

In a previous article I've shown you how you can add new html elements to the <head> of your Drupal 7 site. Recently, however, I was working on a Drupal 8 project and encountered the need to do this in D8. And it took me a while to figure it out so I thought I'd share the process with you.

As you know, in Drupal 7 we use drupal_add_html_head() from anywhere in the code to add a rendered element into the <head>. This is done by passing a render array and most of the time you'll use the type #tag. In Drupal 8, however, we no longer have this procedural function so it can be a bit tricky to find out how this is done.

Although existing in Drupal 7 as well, the #attached key in render arrays really becomes important in D8. We can no longer add any scripts or stylesheets to any page without such proper attachment to render arrays. In my last article I've shown you how to add core scripts to pages in case they were missing (which can happen for anonymous users). In essence, it is all about libraries now that get attached to render arrays. So that is most of what you'll hear about.

But libraries are not the only thing you can attach to render arrays. You can also add elements to the head of the page in a similar way you'd attach libraries. So if we wanted to add a description meta tag to all of the pages on our site, we could implement hook_page_attachments() like so:

/**
 * Implements hook_page_attachments().
 */
function module_name_page_attachments(array &$page) {
  $description = [
    '#tag' => 'meta',
    '#attributes' => [
      'name' => 'description',
      'content' => 'This is my website.',
    ],
  ];
  $page['#attached']['html_head'][] = [$description, 'description'];
}

In the example above we are just adding a dummy description meta tag to all the pages. You probably won't want to apply that to all the pages though and rather have the content of the description tag read the title of the current node. In this case you can implement hook_entity_view() like so:

/**
 * Implements hook_entity_view().
 */
function demo_entity_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode, $langcode) {
  if ($entity->getEntityTypeId() !== 'node') {
    return;
  }

  $description = [
    '#tag' => 'meta',
    '#attributes' => [
      'name' => 'description',
      'content' => \Drupal\Component\Utility\SafeMarkup::checkPlain($entity->title->value),
    ],
  ];
  $build['#attached']['html_head'][] = [$description, 'description'];
}

Now you targeting the node entities and using their titles as the content for the description meta tag. And that is pretty much it.

Hope this helps.

Apr 20 2015
Apr 20

Drupal 8 comes with many performance improvements, one of which being that javascript is no longer indiscriminately loaded on every page. This means that for anonymous users, there are many pages where there is no jQuery or even javascript loaded.

Although this is a good thing, sometimes you do need jQuery (for example to use Ajax, in which case you'd also need other scripts). So how do you load these files? One way is to use hook_page_attachments() to #attach your own library to the page. However, this is only recommended if the assets you need to attach do not apply to something specific, but to the entire page. The recommended way is to attach the library to a render array because then it will only get loaded if necessary.

And if we look at the documentation page for assets, we'll see how we can add our own library. We need to create a my_module.libraries.yml or my_theme.libraries.yml file. And inside, we can add the following:

my_scripts:
  version: VERSION
  js:
    js/scripts.js: {}
  dependencies:
    - core/jquery
    - core/drupal.ajax
    - core/drupal
    - core/drupalSettings
    - core/jquery.once

Where my_scripts will be the name of the library we will reference when attaching.

As you can see, we are not including any javascript or css of our own, we are just making use of the dependency scripts provided by core. So then what is left to do is to attach this library to a render array (or to the entire page if that is your use case):

$render_array['#attached']['library'][] = 'my_module/my_scripts';

Hope this helps.

Mar 23 2015
Mar 23

Have you ever used hook_node_access() to control access to various node operations on your site? Have you found this hook unbelievably awesome? Thought to yourself, boy, I'm unstoppable now? Well, I sure did.

The problem is that Drupal 7 entities do not start and end with nodes and you may want to control access to other entities in the same way. However, there is no hook_taxonomy_term_access() or hook_fieldable_panels_pane_access() that you can use to apply this tactic. So what can you do in these cases?

The first thing is to understand that each entity implementation is different. Some have a centralised access callback for all the operations while others simply define permissions or access callbacks to be used directly inside the hook_menu() definition. And I'm sure there are also other ways of handling this but these I think are the most common.

In this article we are going to look at two entity examples: taxonomy terms (from core) and fieldable panels panes (from contrib). We will trace the access pipeline from request to response and see what we can do to intervene in this process and add our own logic. So let's begin.

Taxonomy terms

The first entity type we are going to look at is the regular taxonomy term introduced by core. It's actually pretty easy to understand how this entity type is built and what we can do in order to hook into the access pipeline.

If we take a look at taxonomy_menu(), we can quickly figure out which paths it creates to add and edit terms and what access callback and arguments are defined:

Adding terms to a vocabulary

$items['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/add'] = array(
   'title' => 'Add term',
   'page callback' => 'drupal_get_form',
   'page arguments' => array('taxonomy_form_term', array(), 3),
   'access arguments' => array('administer taxonomy'),
   'type' => MENU_LOCAL_ACTION,
   'file' => 'taxonomy.admin.inc',
);

Editing a particular term

$items['taxonomy/term/%taxonomy_term/edit'] = array(
   'title' => 'Edit',
   'page callback' => 'drupal_get_form',
   // Pass a NULL argument to ensure that additional path components are not
   // passed to taxonomy_form_term() as the vocabulary machine name argument.
   'page arguments' => array('taxonomy_form_term', 2, NULL),
   'access callback' => 'taxonomy_term_edit_access',
   'access arguments' => array(2),
   'type' => MENU_LOCAL_TASK,
   'weight' => 10,
   'file' => 'taxonomy.admin.inc',
);

By nature, viewing taxonomy term pages has to do with node access since they show a list of nodes so we will skip this aspect here and stick with just the add/edit operations.

So let's change the access callbacks and potential passed arguments inside a hook_menu_alter() implementation.

/**
 * Implements hook_menu_alter().
 */
function demo_menu_alter(&$items) {
  $items['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/add']['access callback'] = 'demo_taxonomy_term_access';
  $items['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/add']['access arguments'] = array(3, 'add');

  $items['taxonomy/term/%taxonomy_term/edit']['access callback'] = 'demo_taxonomy_term_access';
  $items['taxonomy/term/%taxonomy_term/edit']['access arguments'][] = 'edit';
}

So what happens here? We are simply replacing the access callback definition for these two menu items with our own custom function demo_taxonomy_term_access(). Additionally, we standardise a bit the arguments this function gets: $entity (either term or vocabulary object) and $op (add or edit). This covers both cases.

Now let's write our callback function:

/**
 * Access callback for taxonomy term add/edit operations
 *
 * @param null $entity
 * @param null $op
 * @return bool
 */
function demo_taxonomy_term_access($entity = null, $op = null) {
  if ($op === 'add') {
    return user_access('administer taxonomy');
  }

  if ($op === 'edit') {
    return taxonomy_term_edit_access($entity);
  }
}

Inside the function we run a check on $op and perform the access logic we want. In doing so, we make use of the $entity object that can be either the term being edited or the vocabulary to which a new term is added. In this example we are replicating exactly the intended access checks of the Taxonomy module. To add a term, a user needs to have the administer taxonomy permission while to edit one it needs either the same permission or a vocabulary specific permission (as seen inside taxonomy_term_edit_access()). Now it's up to you to include inside this logic whatever else you need. And you end up with something not so dissimilar to hook_node_access() but for taxonomy terms.

Fieldable Panels Panes (FPP)

FPP is a contributed module that creates an entity type that is primarily used inside a Panels context. Regardless of any of this though, it too exposes CRUD operations on the entities of this type. And consequently, there are access implications. So let's see how we can hook into this pipeline by starting where we did with the Taxonomy module: at fieldable_panels_panes_menu().

By looking inside this hook implementation we can find many defined paths which relate to these CRUD operations. And we also see that many of them have fieldable_panels_panes_access() as the access callback with some specific arguments passed to it.

But what does this function actually do? Nothing but taking the parameters and deferring to the controller class responsible for this entity type and its access() method. And by checking fieldable_panels_panes_entity_info(), the principle function responsible for defining the entity type, we find that this is the PanelsPaneController class. In there, we find all the logic for determining access rights for various operations.

Now that we know all this, what can we do to hook into this pipeline? We could do like before and override the hook_menu() implementation. But since there are so many menu items and the FPP class controller is already doing such a nice job, that may be counter productive. So let's instead override the entity definition and replace the class controller with one of ours that extends PanelsPaneController. In there, we then do what we want.

First, we implement hook_entity_info_alter():

/**
 * Implements hook_entity_info_alter().
 */
function demo_entity_info_alter(&$entity_info) {
  $entity_info['fieldable_panels_pane']['controller class'] = 'DemoPanelsPaneController';
}

Right after this, we create a file inside our module called DemoPanelsPaneController.inc which contains the following to start with:

<?php

/**
 * Overrides fieldable panels panes controller functionality
 */
class DemoPanelsPaneController extends PanelsPaneController {

}

Finally, we edit the module's .info file and make sure it loads this file:

files[] = DemoPanelsPaneController.inc

Then we clear the cache. If all went well, nothing really has changed on the site in terms of functionality. However, the DemoPanelsPaneController class is being used for controlling the fieldable_panels_pane entity type. And since this one extends PanelsPaneController, all previous functionality remains. It follows to now override the access() method and include our own logic to it:

public function access($op, $entity = NULL, $account = NULL) {
   // $account not always full (defaults to current user)
   return parent::access($op, $entity, $account);
}

In the example above, nothing is really changed because the logic is deferred back to the parent class. But you could add some logic in addition or instead of that depending on various contextual factors.

However, I strongly recommend/warn you to stick to the minimum amount of deviation from default is needed, and for all rest, defer back to the original logic. This is to prevent the opening of any security holes. For example, if your access() method looks like this:

public function access($op, $entity = NULL, $account = NULL) {
   if ($op === 'update') {
     return false;
   }   
}

You are indeed denying access to the edit form but now anybody can create and delete entities because there is no more check on those operations. So make sure you understand this and do not leave any loopholes. The fix in this case would be:

public function access($op, $entity = NULL, $account = NULL) {
   if ($op === 'update') {
     return false;
   }   
   return parent::access($op, $entity, $account);
}

If the operation is edit, the access is denied for everybody (probably not a good idea but suitable for this demo purpose). However, if the operation is delete, create or view, we defer to the logic of the parent class to handle those cases. In which case the default FPP permissions will be used.

Conclusion

In this article we've seen two ways we can hook into the access checking pipeline of entities in Drupal 7. We've learned that there is more than just one way of going about it depending on how the entity type in question has been defined. The purpose was to illustrate how you can approach the matter and where you need to look in order to find a solution. Hope this helps.

Mar 02 2015
Mar 02

In a previous article I showed you how to use the usort() and uasort() PHP functions to sort some more complex data using a comparator callback function. How cool was that?

Although powerful, this technique is quite restricting though because all the logic for the sorting happens inside the comparator function. In other words, you cannot pass parameters to this callback except for the actual default values that are being compared. So what's the problem with this?

Say you have an array of objects that have a name property that can be retrieved by a getName() getter method. And let's say they also have an address property retrieved by getAddress(). And you have a listing of this data and you need to allow for sorting by any of these properties both ASC and DESC. And forget for one second about the possibility of ordering them as they come out of your data store.

Implementing this with just the default usort() function means you will need 4 different comparer functions (one for each combination of property and sort direction). And what if you want to add more columns to the listing? Oh no..

As you can imagine, the solution to this problem is having a dynamic sorting function (or method in a class) to which you can pass the items to be sorted, the property by which to sort and the direction of sort. And then not have to worry about creating all these ridiculous comparer functions. So how might this look like?

function sortByObjectProps(&$items, $method, $order) {
  if ( ! is_array($items)) {
    return false;
  }

  return usort($items, function($a, $b) use ($method, $order){
    $cmp = strcmp($a->$method(), $b->$method());
    return $order === 'asc' ? $cmp : -$cmp;
  });
}

So what happens here? First of all, $items is passed by reference so we don't need to return it. The return value will just be a boolean indicating the success or failure of the sort. Additionally, we pass the method name that retrieves the property value ($method) and the direction of the sort ($order).

Then we run usort() on the items but - and here is the kicker - with an anonymous function that can use the passed in method and order values. Then it's just a matter of comparing the return values of the getter methods and negate the integer if the order is DESC. Pretty cool no?

So now you can have as many columns as you need and get them sorted in both directions. And obviously even more complex stuff.

Hope this helps.

Feb 02 2015
Feb 02

So you are taking the plunge into learning Drupal 8 for the purpose of developing sites, modules, themes, etc. You're a great Drupal 7 developer, familiar with many drupalisms but you don't have tons of experience with modern PHP frameworks, principles and practices. Well, Drupal 8 still includes many of the old drupalisms but still attempts to keep in line with times and modernise itself.

In this article I want to outline 6 steps I believe you should take to get started learning how to develop custom modules and/or themes in Drupal 8. On top of these 6 builds everything else.

The first three are PHP related in a more general fashion, while the last three target aspects of Drupal 8 itself.

1. Learn Object Oriented Programming

One of the biggest difference between Drupal 7 and 8 for developers is the way code is written. It's still PHP but it's now much more object oriented. Global procedural functions are still in place but most of the logic happens in classes.

In case you don't have much experience with Object Oriented Programming in PHP, this is the first thing you need to learn, brush upon or revise (depending on your level). There are many resources available out there, all scattered as hyperlinks in this section. There are also courses you can take, both free and paid.

Without quite a solid OOP foundation, you won't be able to understand much of how Drupal 8 modules are built.

2. Learn how to use Composer

One of the consequences of modernizing PHP has been the introduction of the Composer package manager. Projects are no longer built without it as it does a great job of installing, updating and managing in general the external libraries and dependencies of your project. Not to mention its very helpful autoloader.

Drupal 8 uses Composer to manage external PHP libraries and dependencies (such as Symfony components, Guzzle, etc) and there is talk about the ability to handle also contrib modules. So make sure you know how Composer works and even start using it in non-Drupal projects.

3. Get familiar with Symfony

One of the main points of contention (back then) in the Drupal 8 development cycle was the introduction of Symfony components. Some people didn't really agree with this great shift from the Drupal way, but others embraced it wholeheartedly. I am in the latter group as I love Symfony and used it even before developing anything in Drupal 8.

Drupal 7 developers are often being told that knowing Symfony is not required in order to develop in Drupal 8. While technically true, you still end up learning a lot of it through the Drupal experience. That being said, I strongly recommend learning some Symfony before. It is a great modular framework and knowing its concepts will really help you out in understanding how Drupal 8 is built (for the components it uses I mean). Once you can build a small website in Symfony, you'll enjoy developing in Drupal 8 that much more because concepts will be similar a lot of the time. Not too mention that you can use Symfony to build apps on its own.

4. Routing and controllers

Just like with Drupal 7, when starting to learn Drupal 8 you need to create the obligatory hello world module (creating a page with a parameter in the URL( usually world) that displays the text Hello + parameter). This example introduces you to many important things:

  • Module folder structure
  • Routing (no more hook_menu) through routing.yml files that map to Controller methods
  • Controller classes which have various methods that can be mapped to routes
  • Access arguments for these routes
  • Rendering markup to the page inside the Controller methods
  • etc

So I really recommend giving this a go.

5. Plugins

Another important concept you'll need to get familiar with is Plugins. Admittedly, this is not the easiest to grasp, but it is super important because it's everywhere. Not to worry though, it's not rocket science.

Many old Drupal 7 implementations of various concepts have been transformed to plugins: info hooks, blocks, field formatters, views handlers, etc. Understanding plugins is therefore very important for being able to extend default Drupal functionality.

6. Dependency injection and the service container

The last step I am going to mention here is dependency injection. Drupal 8 uses the Symfony dependency injection container to manage service instantiation and injection into classes that need them. This helps decouple functionality and increases testability.

However, many people are scared of this concept, mainly because they don't grasp it. I wasn't super comfortable either before understanding it. But you should definitely learn what it means, why we use it and how we use it. Because it is a very simple concept that is used all the time in procedural code as well.

You can already find many tutorials out there on Drupal 8 that load services statically through the \Drupal class. It is much faster to write so people (me included) prefer it when writing about D8. I usually also tend to make a note that using dependency injection is preferred in theses cases.

Not understanding what the service container and dependency injection is will easily let you fall into the habit of just statically requesting services and coupling your code like it was procedural. Once you are clear on this point, this will hopefully not happen any more and the sight of a \Drupal::get('some_service') will make you think twice.

Conclusion

There you have it. What I think are the first 6 steps you should take when learning Drupal 8 for the first time. Of course there are many other important things to learn and do but I believe they build on top of this foundation. Of course, this is me writing so others may have different opinions (very much welcomed in the comments). So let's discuss.

Jan 26 2015
Jan 26

In the previous article we've seen how we can interact programatically with Views in Drupal 8 in order to create a custom field in our Views results. Today, we will be looking a bit at how we can create a custom filter you can then add to the View in the UI and influence the results based on that.

Filters in Views have to do with the query being run by Views on the base table. Every filter plugin is responsible with adding various clauses in this query in an attempt to limit the results. Some (probably most) take on configuration parameters so you can specify in the UI how the filtering should be done.

If you remember from the last article, to create our field we extended the FieldPluginBase class. Similarly, for filters, there is a FilterPluginBase class that we can extend to create our own custom filter. Luckily though, Views also provides a bunch of plugins that extend the base one and which we can use or extend to make our lives even easier. For example, there is a BooleanOperator class that provides a lot of the functionality needed for this type of filter. Similarly, there is an InOperator class, a String class, etc. You can find them all inside the views/src/Plugin/views/filter directory of the Views core module or here.

In this tutorial, we will create 2 custom filters. One will be a very simple one that won't even require creating a new class. The second one will be slightly more complex and for which we will create our own plugin.

The code we write will go in the same module we started in the previous article and that can be found in this repository.

Node type filter

The first filter we will write is very simple. We want to be able to filter our node results by the machine name of the node type. By default, we can use a filter in which we select which node types to be included. Let's say, for the sake of argument, we want a more complex one, such as the one available for a regular text value like the title. The String class will be perfect for this and will provide actually 100% of our needs.

So let's go to our hook_views_data_alter() implementation and add a new filter:

...

$data['node_field_data']['node_type_filter'] = array(
  'title' => t('Enhanced node type filter'),
  'filter' => array(
    'title' => t('Enhanced node type filter'),
    'help' => t('Provides a custom filter for nodes by their type.'),
    'field' => 'type',
    'id' => 'string'
  ),
);

...

Since the table that we are interested in altering the query for is the node_field_data table, that is what we are extending with our new filter. Under the filter key we have some basic info + the id of the plugin used to perform this task. Since our needs are very simple, we can directly use the String plugin without us having to extend it. The most important thing here though is the field key (under filter). This is where we specify that our node_type_filter field (which is obviously a non-existent table column) should be treated as being the type column on the node_field_data table. So, by default, the query alter happens on that column. And this way we don't have to worry about anything else, the String plugin will take care of everything. If we didn't specify that, we would have to extend the plugin and make sure the query happens on the right column.

And that's it. You can clear your cache, create a View with nodes of multiple types and add the Enhanced node type filter to it. In its configuration you'll have many matching options such as equals, contains, does not contain etc you can use. For example, you can use contains and specify the letters art in order to return results whose node type machine name contain these letters.

Node title filter

The second custom filter we build will allow Views UI users to filter the node results by their title from a list of possibilities. In other words, they will have a list of checkboxes which will make it possible to include/exclude various node titles from the result set.

Like before, we need to declare our filter inside the hook_views_data_alter() implementation:

...

$data['node_field_data']['nodes_titles'] = array(
  'title' => t('Node titles'),
  'filter' => array(
    'title' => t('Node titles'),
    'help' => t('Specify a list of titles a node can have.'),
    'field' => 'title',
    'id' => 'd8views_node_titles'
  ),
);

...

Since we are filtering on the title column, we are extending again on the node_field_data table but with the title column as the real field to be used. Additionally, this time we are creating a plugin to handle the filtering identified as d8views_node_titles. Now it follows to create this class:

src/Plugin/views/filter/NodeTitles.php:

<?php

/**
 * @file
 * Definition of Drupal\d8views\Plugin\views\filter\NodeTitles.
 */

namespace Drupal\d8views\Plugin\views\filter;

use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\filter\InOperator;
use Drupal\views\ViewExecutable;

/**
 * Filters by given list of node title options.
 *
 * @ingroup views_filter_handlers
 *
 * @ViewsFilter("d8views_node_titles")
 */
class NodeTitles extends InOperator {

  /**
   * {@inheritdoc}
   */
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);
    $this->valueTitle = t('Allowed node titles');
    $this->definition['options callback'] = array($this, 'generateOptions');
  }

  /**
   * Override the query so that no filtering takes place if the user doesn't
   * select any options.
   */
  public function query() {
    if (!empty($this->value)) {
      parent::query();
    }
  }

  /**
   * Skip validation if no options have been chosen so we can use it as a
   * non-filter.
   */
  public function validate() {
    if (!empty($this->value)) {
      parent::validate();
    }
  }

  /**
   * Helper function that generates the options.
   * @return array
   */
  public function generateOptions() {
    // Array keys are used to compare with the table field values.
    return array(
      'my title' => 'my title',
      'another title' => 'another title',
    );
  }

}

Since we want our filter to be of a type that allows users to select from a list of options to be included in the results, we are extending from the InOperator plugin. The class is identified with the @ViewsFilter("d8views_node_titles") annotation (the id we specified in the hook_views_data_alter() implementation).

Inside our plugin, we override three methods:

Inside init(), we specify the title of the set of filter options and the callback that generates the values for options. This callback has to be a callable and in this case we opted for the generateOptions() method on this class. The latter just returns an array of options to be presented for the users, the keys of which being used in the query alteration. Alternatively, we could have also directly created the options inside the init() method by filling up the $this->valueOptions property with our available titles. Using a callback is cleaner though as you can perform various logic in there responsible for delivering the necessary node titles.

The point of overriding the query() and validate() methods was to prevent a query and validation from happening in case the user created the filter without selecting any title. This way the filter has no effect on the results rather than returning 0 results. It's a simple preference meant to illustrate how you can override various functionality to tailor your plugins to fit your needs.

And that's it. You can add the Node titles filter and check the box next to the titles you want to allow in the results.

Conclusion

In this article we've looked at how we can create custom filters in Drupal 8 Views. We've seen what are the steps to achieve this and looked at a couple of the existing plugins that are used across the framework and which you can use as is or extend from.

The best way to learn how all these work is by studying the code in those plugin classes. You will see if they are enough for what you want to build or extending them makes sense. In the next article we are going to look at some other Views plugins, so stay tuned.

Jan 19 2015
Jan 19

In this article I am going to show you how to create a custom Views field in Drupal 8. At the end of this tutorial, you will be able to add a new field to any node based View which will flag (by displaying a specific message) the nodes of a particular type (configurable in the field configuration). Although I will use nodes, you can use this example to create custom fields for other entities as well.

So let's get started by creating a small module called d8views (which you can also find in this repository):

d8views.info.yml:

name: Drupal 8 Views Demo
description: 'Demo module that illustrates working with the Drupal 8 Views API'
type: module
core: 8.x

In Drupal 7, whenever we want to create a custom field, filter, relationship, etc for Views, we need to implement hook_views_api() and declare the version of Views we are using. That is no longer necessary in Drupal 8. What we do now is create a file called module_name.views.inc in the root of our module and implement the views related hooks there.

To create a custom field for the node entity, we need to implement hook_views_data_alter():

d8views.views.inc:

/**
 * Implements hook_views_data_alter().
 */
function d8views_views_data_alter(array &$data) {
  $data['node']['node_type_flagger'] = array(
    'title' => t('Node type flagger'),
    'field' => array(
      'title' => t('Node type flagger'),
      'help' => t('Flags a specific node type.'),
      'id' => 'node_type_flagger',
    ),
  );
}

In this implementation we extend the node table definition by adding a new field called node_type_flagger. Although there are many more options you can specify here, these will be enough for our purpose. The most important thing to remember is the id key (under field) which marks the id of the views plugin that will be used to handle this field. In Drupal 7 we have instead a handler key in which we specify the class name.

In Drupal 8 we have something called plugins and many things have now been converted to plugins, including views handlers. So let's define ours inside the src/Plugin/views/field folder of our module:

src/Plugin/views/field/NodeTypeFlagger.php

<?php

/**
 * @file
 * Definition of Drupal\d8views\Plugin\views\field\NodeTypeFlagger
 */

namespace Drupal\d8views\Plugin\views\field;

use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\NodeType;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;

/**
 * Field handler to flag the node type.
 *
 * @ingroup views_field_handlers
 *
 * @ViewsField("node_type_flagger")
 */
class NodeTypeFlagger extends FieldPluginBase {

  /**
   * @{inheritdoc}
   */
  public function query() {
    // Leave empty to avoid a query on this field.
  }

  /**
   * Define the available options
   * @return array
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['node_type'] = array('default' => 'article');

    return $options;
  }

  /**
   * Provide the options form.
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    $types = NodeType::loadMultiple();
    $options = [];
    foreach ($types as $key => $type) {
      $options[$key] = $type->label();
    }
    $form['node_type'] = array(
      '#title' => $this->t('Which node type should be flagged?'),
      '#type' => 'select',
      '#default_value' => $this->options['node_type'],
      '#options' => $options,
    );

    parent::buildOptionsForm($form, $form_state);
  }

  /**
   * @{inheritdoc}
   */
  public function render(ResultRow $values) {
    $node = $values->_entity;
    if ($node->bundle() == $this->options['node_type']) {
      return $this->t('Hey, I\'m of the type: @type', array('@type' => $this->options['node_type']));
    }
    else {
      return $this->t('Hey, I\'m something else.');
    }
  }
}

We are defining our NodeTypeFlagger class that extends FieldPluginBase (which is the base plugin abstract class for the views field many plugins extend from). Just above the class declaration we use the @ViewsField annotation to specify the id of this plugin (the same one we declared in the hook_views_data_alter() implementation). We also use the @ingroup annotation to mark that this is a views field handler.

In our example class, we have 4 methods (all overriding the parent class ones).

Query

First, we override the query() method but leave it empty. This is so that views does not try to include this field in the regular node table query (since the field is not backed by a table column).

DefineOptions

The second method is the defineOptions() method through which we specify what configuration options we need for this field. In our case one is enough: we need to specify the node type which we want flagged in the Views results. We set a sensible default as the article node type.

BuildOptionsForm

The third method, buildOptionsForm() is responsible for creating the form for the configuration options we declared earlier. In our case we just have a select list with which we can choose from the existing node types.

Render

Lastly, the render() method which is the most important and which deals with output. We use it to actually render the content of the field for each result. Here is where we perform some business logic based on the currently set node type option and flag with a message whether or not the current result is in fact of the type specified in the configuration.

The $resultRow object is an instance of Drupal\views\ResultRow which contains data returned for the current row by Views and the entity object at the base of the query (in our case the node). Based on this information we can perform our logic.

Keep in mind you can use depedency injection to inject all sorts of services into this class and make use of them in your logic. Additionally, you can override various other methods of the parent class in order to further customize your field.

Conclusion

There you have it. A small custom module that demonstrates how to create a custom Views field (plugin). Relationships, filters, sorters and others work in similar way. I will be covering those in later articles. Stay tuned.

Nov 24 2014
Nov 24

If you do a lot of Drupal development and need to deploy configuration I am sure that you are using update hooks to some extent at least. If you don't use Features and want to create a taxonomy vocabulary or something in code, the hook_update_N() hook is the way to go.

But have you ever needed to perform an update the size of which would exceed PHP's maximum execution time? If you need to create 1000 entities (let's just say as an example), it's not a good idea to trust that the production server will not max out and leave you hanging in the middle of a deploy. So what's the solution?

You can use the batch capability of the update hook. If you were wondering what the &$sandbox argument is for, it's just for that. You use it for two things mainly:

  • store data required for your operations across multiple passes (since it is passed by reference the values remain)
  • tell Drupal when it should stop the process by setting the $sandbox['#finished'] value to 1.

Let me show you how this works. Let's say we want to create a vocabulary and a bunch of taxonomy terms with names from a big array. We want to break this array into chunks and create the terms one chunk at the time so as to avoid the load on the server.

So here is how you do it:

/**
 * Create all the terms
 */
function my_module_update_7001(&$sandbox) {

  $names = array(
    'Fiona',
    'Jesse',
    'Michael',
    ...
    'Sam',
    'Nate',
  );

  if (!isset($sandbox['progress'])) {
    $sandbox['progress'] = 0;
    $sandbox['limit'] = 5;
    $sandbox['max'] = count($names);

    // Create the vocabulary
    $vocab = (object) array(
      'name' => 'Names',
      'description' => 'My name vocabulary.',
      'machine_name' => 'names_vocabulary',
    );

    taxonomy_vocabulary_save($vocab);
    $sandbox['vocab'] = taxonomy_vocabulary_machine_name_load('names_vocabulary');
  }

  // Create the terms
  $chunk = array_slice($names, $sandbox['progress'], $sandbox['limit']);
  if (!empty($chunk)) {
    foreach ($chunk as $key => $name) {
      $term = (object) array(
        'name' => $name,
        'description' => 'The name is: ' . $name,
        'vid' => $sandbox['vocab']->vid,
      );

      taxonomy_term_save($term);
      $sandbox['progress']++;
    }
  }

  $sandbox['#finished'] = ($sandbox['progress'] / $sandbox['max']);


}

So what happens here? First, we are dealing with an array of names (can anybody recognise them by the way?) Then we basically see if we are at the first pass by checking if we had set already the progress key in $sandbox. If we are at the first pass, we set some defaults: a limit of 5 terms per pass out of a total of count($names). Additionally, we create the vocabulary and store it as a loaded object in the sandbox as well (because we need its id for creating the terms).

Then, regardless of the pass we are on, we take a chunk out of the names always offset by the progress of the operation. And with each term created, we increment this progress by one (so with each chunk, the progress increases by 5) and of course create the terms. At the very end, we keep setting the value of $sandbox['#finished'] to the ratio of progress per total. Meaning that with each pass, this value increases from an original of 0 to a maximum of 1 (at which point Drupal knows it needs to stop calling the hook).

And like this, we save a bunch of terms without worrying that PHP will time out or the server will be overloaded. Drupal will keep calling the hook as many times as needed. And depending on the operation, you can set your own sensible chunk sizes.

Hope this helps.

Sep 08 2014
Sep 08

Have you ever needed to remove in bulk a bunch of voting results for, let's say, a given content type? There is no option in the UI but you can find in the votingapi.module some handy functions that will allow you to write a customized update hook.

So let's say that we need to remove all the results for the article content type. If we look in the votingapi_vote table, we don't see any bundle or content type column, but we see an entity_id. So we need to get all the ids of our article nodes:

  $query = db_query("SELECT nid FROM node WHERE type = 'article'");
  foreach ($query as $res) {
    $nids[] = $res->nid;
  }

Now we have the $nids array containing all of our node IDs. Next, let's load all the votes for these IDs:

  module_load_include('module', 'votingapi', 'votingapi.module');

  $votes = votingapi_select_votes(array('entity_id' => $nids));

First we include the right module file and then we use one of its functions to select all the votes that match some criteria (in our case an array of IDs). Next, we need to worry also about the votingapi_cache table which contains the results of the voting per entity. We need to remove that as well. So we'll use another helper function from Voting API:

$results = votingapi_select_results(array('entity_id' => $nids));

Now we have also the result objects we need to delete so we can proceed with the actual removal. For this, we can use two more handy methods from the Voting API module:

votingapi_delete_votes($votes);
votingapi_delete_results($results);

And that's it. This will remove all the votes and their aggregated results from both tables. It may take some time so make sure you have enough server resources to perform this task.

To use this code, I recommend creating an update hook in a custom module that you run once. But make sure you properly test it on your test environment before deploying and running the code on production servers. Always keep in mind the possibility of the server running out of resources depending on how many votes you have in the database.

Do you have any better way of batch deleting votes/results? This is what I found and I'm curious if you know of any better ways. Let me know.

Sep 01 2014
Sep 01

Have you ever had to sort an array in PHP? There are a bunch of functions available, the most common being sort(). This function does a default sorting of the values in your array. So if you have numbers or want to do alphabetical sorting, sort() will get the job done.

But what if you require a more complex sorting logic? Let's say you have an array of names that need to be sorted in a specific order. I don't know, because your client says so. Let me show you how.

Let's say your DB returns a list of names in an array:

$names = array("Christian", "Daniel", "Adrian");

And your client says they need to be arranged in the following order: Adrian, Christian, Daniel. You can use the usort() function together with a comparator function you write yourself. How does this system work?

As a second argument of the usort() function, we pass in the name of our custom comparator function. The way this gets processed is that all the values in the array that needs sorting are passed to this function 2 at the time (usually you'll see them as $a and $b). This is done to determine which one takes precedence over which. The comparator has to return 0 if the 2 values are considered equal, a negative integer if the first value is less than the second value or a positive integer if the second value is less than the first. What less means is up to you to determine. So let's put this in practice with our example:

function _name_comparer($a, $b) {
    $correct_order = array("Adrian", "Christian", "Daniel");

    $a_key = array_search($a, $correct_order);
    $b_key = array_search($b, $correct_order);

    if ($a_key == $b_key) {
        return 0;
    }

    return ($a_key < $b_key) ? -1 : 1;
}

usort($names, "_name_comparer");

So what happens in my comparator function? First, I create an array that contains the proper order of the names. This means that each value has an integer key that can be easily compared (and that I store in the $a_key and $b_key variables). After comparing these, I return 0, a negative or positive integer. The result is that the $names array gets resorted in the order they appear in the $correct_order local variable I created. And that's it.

If the $names variable is associative and you need to maintain the keys as they were, you can use the uasort() function:

$names = array(
    "christian" => "Christian", 
    "daniel" => "Daniel", 
    "adrian" => "Adrian",
);
uasort($names, "_name_comparer");

The comparator function can stay the same, but the uasort() function will take into account and maintain the index association of your values.

And that's it. Hope this helps.

Jun 16 2014
Jun 16

With the move from a mostly procedural to a mostly OOP based architecture in Drupal 8, many Drupal developers have been introduced to new concepts we don't fully understand. I myself was terrified of notions such as dependency injection and service container, making me worry about the future of my Drupal development.

So I took it to Symfony (from where many components have been borrowed) and then Drupal 8 alpha releases and turns out it's not a big deal. All you need in order to understand them is to know basic OOP principles. Check out Larry Garfield's timeless introductory article to Object Oriented Programming on Drupal Watchdog for a good start.

In this article I am going to talk a bit about what dependency injection is and why one would use a container for managing these dependencies. In Symfony and Drupal 8 this is called a service container (because we refer to these global objects as services). Then, we will take a look at how these are applied in Drupal 8. Briefly, because you don't need much to understand them.

So what is dependency injection?

Take the following simple class:

class Car {

  protected $engine;

  public function __construct() {
    $this->engine = new Engine();
  }

  /* ... */

}

When you instantiate a new class Car you go like this:

$car = new Car();

And now you have an object handler ($car) that has an $engine property containing the handler of another object. But what if this car class needs to work with another engine? You'd have to extend the class and overwrite its constructor for each new car with a different engine. Does that make sense? No.

Now consider the following:

class Car {

  protected $engine;

  public function __construct($engine) {
    $this->engine = $engine;
  }

  /* ... */

}

To instantiate an object of this class, you go like this:

$engine = new Engine();
$car = new Car($engine);

Much better. So now if you need to create another car using another engine, you can do so easily without caring about the Car class too much since it is supposedly equipped to work with all the engines in your application.

$turbo = new TurboEngine();
$car2 = new Car($turbo);

And that is dependency injection. The Car class depends on an engine to run (dooh), so we inject one into its constructor which then does what it needs to do. Rather than hardcoding the engine into the Car class which would not make the engine swappable. Such constructor injections are the most common but you'll also find other types such as the setter injection by which we would pass in the engine through a setter method.

So what is this container business?

So far we've seen a very simple class example. But imagine (rightfully) that the Car has many other potentially swappable components (dependencies), like a type of gear shift, breaks or wheels. You have to manually instantiate all these dependent objects just so you can pass them to the one you actually need. This is what the container is for, to do all that for you.

Basically it works like this. You first register with the container your classes and their dependencies. And then at various points of your application, you can access the container and request an instance of a particular class (or service as we call them in Symfony and Drupal 8). The container instantiates an object of that class as well as one of each of its dependencies, then returns you that service object. But what is the difference between services that we usually access through the container and other PHP classes?

A very good definition that makes this distinction comes from the Symfony book:

As a rule, a PHP object is a service if it is used globally in your application. A single Mailer service is used globally to send email messages whereas the many Message objects that it delivers are not services. Similarly, a Product object is not a service, but an object that persists Product objects to a database is a service.

Understanding how the container works under the hood is I believe not crucial for using it. It's enough to know how to register classes and how to access them later. There are multiple ways to register services but in Drupal 8 we use YAML files. In Symfony, you can use directly PHP, YAML or even XML. To know more about how to do this in Drupal 8, check out this documentation page. Accessing the services in Drupal 8, on the other hand, is done in one of two ways: statically and using, yet again, dependency injection.

Statically, it's very simple. We use the global \Drupal namespace to access its service() method that returns the service with the name we pass to it.

$service = \Drupal::service('my service');

This approach is mostly used for when we need a service in our .module files where we are still working with procedural code. If we are in a class (such as a form, controller, entity, etc), we should always inject the service as a dependency to the class. Since I covered it elsewhere and the Drupal documentation mentioned provides a good starting point, I won't go into the exact steps you need to take in order to inject dependent services into your Drupal 8 classes. However, you can check out my introductory series on Drupal 8 module development, on Sitepoint.com, where I covered the process of creating services and injecting them as dependencies (in the third part, published soon if not already).

Conclusion

So there you go. Dependency injection is a very simple concept that has to do with the practice of decoupling functionality between classes. By passing dependencies to objects we can isolate their purpose and easily swap them with others. Additionally, it make is much easier to unit test the classes individually by passing mock objects.

The service container is basically there to manage some classes when things get overwhelming. That is, when the number grows and the number of their dependencies also increases. It keeps track of what a certain service needs before getting instantiated, does it for you and all you have to do is access the container to request that service.

Hope its clear.

Jun 10 2014
Jun 10

Developing Drupal sites can be quite a challenge and adventure. And this comes from those who call themselves Drupal developers. Men and women of PHP who work with other frameworks and applications most likely find it even more cumbersome to understand. However, Drupal is fostered by a big community of enthusiastic people who love it, myself included. But in all honesty, the more you work with it, the more you develop this love/hate relationship with all the quirks of Drupal development.

But one thing is certain, and this is applicable to other areas of web development as well: the tools you use for the job can make a big difference in the experience you have. And Drupal makes no exception. I mean, remember when we were writing PHP in Notepad and that one missing semicolon added 2 hours of debugging that day?

In this article I would like to share with you 4 tools that I use for Drupal development. I heavily rely on them to minimise frustration, increase productivity and lower development time. And I can guarantee you that if you are serious about Drupal development and you are not using them, you are missing out. But if you are, kudos, do share some of your experiences that further demonstrate their power.

So here we are, I guess in order of complexity, the 4 tools in my belt when I run vagrant up to spin up a project on my local environment. I will say a few words about each, but I can't go into all of their features. That's for you to explore after I give you a taste of what they can offer.

Devel and Search Krumo modules

Devel is the most used Drupal development module built for aiding with debugging code, generating content and all sorts of other dev tasks. Search Krumo is yet another cool module that plugs into it in order to give us a hand with navigating through huge array structures. And if you know Drupal 7, it is all about big arrays.

These modules are probably the first solution for debugging variables in Drupal. Using Devel's dsm(), dpm(), and krumo() functions in your code you can print out arrays, objects and whatever you need for a great overview of what you have in scope at that moment of execution. And they are not the only ones...

Another great use for the Devel module is content generation. It has a series of submodules that can generate nodes, taxonomy terms, users and more. Sometimes you need 500 nodes on the site to test something out. Additionally, you can use it to execute PHP code in the Drupal environment, switch between users on the site and other awesome functionality. So it's a must have on any Drupal development environment.

Drush

Drush is an awesome command line tool for Drupal that speeds up many tasks. Some people call it the swiss army knife of Drupal and you can't really argue the opposite.

Drush allows you to perform a host of Drupal tasks from the command line. You can download and enable/disable/uninstall/update modules or Drupal core and all sorts of other helpful jobs. This great list of core commands can give you an overview of what you can do with Drush. And if you are looking for some help with setting Drush up on your server, you can read this article I wrote on the subject.

Another great thing about Drush is that aside from all the awesome core commands, you can declare your own. This way, you can expose some of your custom functionality to the command line. This goes behind development and can help with maintenance or even production jobs that need to run with cron. So it truly is versatile.

A good IDE like PHPStorm

I mentioned before the good ol' times (not really) when Notepad was the editor of choice for many developers. Luckily nowadays we don't have to suffer through that as we can use IDEs for coding. I myself use PHPStorm and is of great help.

An IDE can speed up your development time by preventing code mistakes, highlighting syntax for great readability, code hinting for classes and functions in your project and many others. And with Drupal, all of these are important. Since Drupal 7 is mostly procedural you need to be aware of many functions and parameters. The IDE great reduces the time you spend online researching these APIs. And not to mention the integrations you can create with these API documentation resources.

Another great use of IDEs (which for me is the most important) is debugging. Integrating PHPStorm with XDebug on my local server really changed things around. But more on that in the next point.

Xdebug

As great as the Devel module is for printing out variables to the screen, it does not come close to Xdebug when we talk about debugging. After setting it up, all you have to do is place a breakpoint in your code and load your site page. The execution stops at the breakpoint (that was hopefully supposed to be executed) and you have access to a wealth of contextual information. You get all the global and scope variables that you can navigate through, a great callstack of what functions/methods have been triggered so far and many others.

Another cool feature is that you can play forward the execution line by line and jump inside of to be called functions to see where the code is heading. This is great for debugging where your code fails, at which point does that exception get thrown, or why that variable is null. So I do recommend checking it out.

Conclusion

And there you have it: 4 tools you can start using today to make you Drupal development experience more efficient. Using Drush and the Devel module are really only specifically for Drupal, but the use of a good IDE and XDebug is applicable to all other PHP projects as well. And I can guarantee you they are all worth using.

Jun 03 2014
Jun 03

This is a guest post from Kate Marshalkina, a Russian Drupal developer who works for Licel LLC. Enjoy the read and check out some of her other work.

Drush Make is well-known as an advanced tool for Drupal distribution building. But it also can be very useful for those who have never dealt with distributions. One great example is applying patches like a boss.

In this article I’ll show you how I use Drush Make to automate some of my routine tasks and help me to discover great Drupal stuff.

Drush Make commands

Drush Make includes 2 commands which are already built in Drush itself:

  1. make — Turns a .makefile into a Drupal codebase.
  2. make-generate — Generates a .makefile from the current Drupal site.

Both commands are related to a .makefile — flat text file with Drush Make instructions. You can read more about .makefile syntax here.

But for now, let's go deeper and see Drush Make in action.

Rebuild your development environment

How often do you install a new and clean Drupal site for development, testing or demonstration purposes? Additionally to Drupal core, developers usually have a predefined list of favorite modules like Administration Menu, Views or something more special. With Drush Make you can automate this process greatly by combining all the projects you need into one file and lettting Drush Make build it for you.

Here is an example .makefile for a multilingual testing site:

; Drush Make API version.
api = 2
; Drupal core.
core = 7.x

;Common modules.
projects[admin_menu][subdir] = "contrib"
projects[ctools][subdir] = "contrib"
projects[token][subdir] = "contrib"
projects[views][subdir] = "contrib"

; Development modules.
projects[devel][subdir] = "development"

; Multilingual modules.
projects[fallback_language_negotation][subdir] = "contrib"
projects[variable][subdir] = "contrib"
projects[i18n][subdir] = "contrib"
projects[i18nviews][subdir] = "contrib"

; Load some translations.
translations[] = de
translations[] = ru

This file can be saved locally (in ~/.drush/make-files/d7_i18n.make for example) or hosted on a remote server like GitHub.

To use it, let’s run the make command to prepare our custom build on our server (in /var/www/drupal_test.local for example):

$ drush make d7_i18n.make /var/www/drupal_test.local

The first run can be quite long, but the next time Drush will take most of projects from its cache.

As a result, the latest Drupal core, contrib modules and translations from the .makefile will be downloaded and placed in appropriate folders. Now you can go to your site's URL and run the install.php or run the installation process directly with Drush:

$ drush si --db-url="mysql://user:[email protected]/databasename" --site-name="Drupal Multilingual"

Additionally, you can also generate a tarball from the .makefile with --tar option:

$ drush make d7_i18n.make drupal_multilingual --tar

Add to that a couple of features (based on Features module) and you’ll end up with your own distro.

Download dependencies

Have you ever noticed that some contrib modules provide .make or .make.example file? These usually contain a list of specific external libraries (like the jQuery Colorbox plugin for the Colorbox module). These file can be built inside existing Drupal codebases using the --no-core flag. As an example, let’s say you want to download the Chosen module:

$ drush dl chosen
Project chosen (7.x-2.0-beta4) downloaded to sites/all/modules/contrib/chosen.

$ drush make sites/all/modules/contrib/chosen/chosen.make.example --no-core
chosen downloaded from https://github.com/harvesthq/chosen/releases/download/v1.1.0/chosen_v1.1.0.zip

In this case, the proper jQuery plugin was downloaded and unzipped into the proper directory inside the libraries/ folder. Isn’t that handy?

Module developers, please, add a .make.example file into your Drupal.org projects if you are using any external libraries. Instead of building custom Drush commands like chosen-plugin, we can use Drush Make. Just compare 117 lines to 7.

Generate makefile from existing site

You can easily share a custom Drupal build with Drush Make. First run generate-makefile command from Drupal root to generate a skeleton:

$ drush generate-makefile drupal_custom_build.make

The generated file drupal_custom_build.make will contain instructions for all enabled projects with specific versions. If a project has .git folder, Drush Make will automatically set appropriate properties:

projects[redirect][type] = "module"
projects[redirect][download][type] = "git"
projects[redirect][download][url] = "http://git.drupal.org/project/redirect.git"
projects[redirect][download][branch] = "7.x-1.x"
projects[redirect][download][revision] = "0b7b8dc2d58cb277874d87c91c45f0a361e148f7"

This file still needs a quick manual review. For example, you can add patch references. In my project, 2 patches are applied to the Redirect module:

projects[redirect][patch][] = "https://drupal.org/files/issues/redirect-global-905914-145.patch"
projects[redirect][patch][] = "https://drupal.org/files/issues/redirect.circular-loops.1796596-146.patch"

The resulting .makefile may be very useful if you want to share your working environment with a colleague or to provide definitive info for troubleshooting.

Bonus! Explore Drupal world!

Finally, the Drush Make file itself is a good read for discovering new cool contrib projects. Check out well-tested Commerce Kickstart or OpenScholar .makefiles with plenty of interesting projects inside.

I hope this article will help you use Drush more widely, to automate some of your tasks or to even build your first distribution!

About the Author

Kate is a passionate web developer from Russia who fell in love with Drupal in 2011.

She cares about multilingual stuff, usability and performance.

Connect with Kate:
Twitter | drupal.org | Google +

May 26 2014
May 26

I've worked recently on some new features for my contrib module Block Inject and I thought I'd share with you what's new.

Based on some feature requests from the community, I've implemented two new things that make this module more flexible. They are available in the 7.x-1.2alpha5 release onwards.

Theming

First, the injected region is now wrapped in a with some default classes on it for easy styling. I've also created an alter hook for this so you can add easily your own classes there depending on the $node object the region is injected in.

An example implementation of this hook:

function hook_block_inject_attributes_alter($attributes) {
  if ($attributes['node']->type == 'article') {
    $attributes['attributes']['class'][] = 'article-block-inject';
  }
}

The $attributes parameter is an array with two values: the node object and another attributes array that gets transformed into HTML attributes by the drupal_attributes() function.

Site building

The second new feature of the module is the possibility to specify default paragraph offsets for an inject region depending on some conditions related to the node body field.

For example, when creating the inject region you can set it so that the region gets injected 5 paragraphs lower than the middle if the total number of paragraphs is over 20. Or move the region higher by 2 paragraphs if the total number of paragraphs equals 6.

Feel free to check it out and let me know what you think.

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