# uname -a

mercredi 27 juillet 2016

Drupal 8 : create a custom Rule Action

Warning : the Rule plugin for Drupal 8 was not considered stable when I wrote this post.

1. Drupal 8: the new modules paradigm

Drupal 8 modules structure changed, and many modules are now using the new API.

No more plain old functions name like hook_something, no more obscurous PHP for menu entries. Instead, Object Oriented programming, YAML configuration files, magic comments, and Symfony routing.

Let's give it a try, let's make our first simplest module.

2. Base module configuration

If you already know how to do this, jumb to next section.

Create a directory for your module, for instance mymodule.

Create an info file in YAML format : mymodule/mymodule.info.yaml:

name: 'My Module'
type: module
core: 8.x
package: Custom

You don't need more! You don't need routing as you will plug into Rules.

3. File names and Namespaces

Creates the RulesAction directory and its parents: mymodule/src/Plugin/RulesAction/

Creates a PHP file for your class: MyAction.php. The class will be loaded with the autoload system.

Edit the file you just created, and specify the namespace at the beginning of the file:

 * @file
 * Contains \Drupal\mymodule\Plugin\RulesAction\MyAction.
namespace Drupal\mymodule\Plugin\RulesAction;
use Drupal\rules\Core\RulesActionBase;

The namespace must correspond to your module name and class name!

4. Rule Action specifications and parameters

Comments are very important as they are also specifications. You will define your Action id, description, and parameters. For instance, here is a copied sample from the predefined action DataSet:

 * Provides a 'My action' action.
 * @RulesAction(
 *   id = "rules_myaction",
 *   label = @Translation("Set a data value"),
 *   category = @Translation("Data"),
 *   context = {
 *     "data" = @ContextDefinition("any",
 *       label = @Translation("Data"),
 *       description = @Translation("Specifies the data to be modified using a data selector, e.g. 'node:author:name'."),
 *       allow_null = TRUE,
 *       assignment_restriction = "selector"
 *     ),
 *     "value" = @ContextDefinition("any",
 *       label = @Translation("Value"),
 *       description = @Translation("The new value to set for the specified data."),
 *       default_value = NULL,
 *       required = FALSE
 *     )
 *   }
 * )

The Rule id is rules_myaction.

The category of the action in the dropdown menu is Data and it will be labeled Set a data value.

The current action will have two parameters : the data that will be changed, and the corresponding value.

5. Rule Action callback

Again, no more plain callback, the function doExecute will be called to execute your Action:

class MyAction extends RulesActionBase {

   * Executes the Plugin.
   * @param mixed $data
   *   Original value of an element which is being updated.
   * @param mixed $value
   *   A new value which is being set to an element identified by data selector.
  protected function doExecute($data, $value) {
    $typed_data = $this->getContext('data')->getContextData();

   * {@inheritdoc}
  public function autoSaveContext() {
    // Saving is done at the root of the typed data tree, for example on the
    // entity level.
    $typed_data = $this->getContext('data')->getContextData();
    $root = $typed_data->getRoot();
    $value = $root->getValue();
    // Only save things that are objects and have a save() method.
    if (is_object($value) && method_exists($value, 'save')) {
      return ['data'];
    return [];


The class name has to correspond to your file name.

In this sample, the parameter $value will be set to $data.

6. Troubleshooting

Uncaught PHP Exception Drupal\\Component\\Plugin\\Exception\\PluginException: "Plugin (rules_myaction) instance class "Drupal\\tbh_system\\Plugin\\RulesAction\\MyAction" does not exist."

Your namespace/classname/filename/directoryname is probably wrong.


Drupal 8 Rules Action documentation

jeudi 1 octobre 2015

About ToBeHost : the last of my student's projects

Hello there, this is not your ordinary reading on this blog. This post is a sort of introduction for a series of posts about the making of a free web hosting provider, implementing a web panel from scratch using Drupal for front-end and Puppet as back-end.

But first, let me introduce you the reason why we started the project. I said “we” because I am not the only one in the boat, but it’s me who will make all the technical choices, and implement it. I am also the one who was saying “give up” to my colleague a few months ago, before going back with this new and exciting crazy idea.

Lire la suite...

mercredi 25 février 2015

Drupal 7 : create your own image effect for use in image styles

Drupal comes with many predefined effects, you can combine them in image styles to get the picture you want. But what if you have to make your own effect ? Here is how.

Lire la suite...

vendredi 5 décembre 2014

Drupal 7 : integrate a simple payment workflow with Payment module

Payment forms are common these days, and Drupal has already many out-of-the-box modules to implement a web shop.

But these modules are often very cumbersome, complicated, and not-so-easy to tweak for your own needs.

So, let’s (re)start from the beginning: let’s implement our own Payment form with Payment, and throw Ubercart, Commerce, and all his friends away.

Note that the use of Payment is compatible with Ubercart and Commerce, but please let me make it simpler.

Lire la suite...

lundi 10 novembre 2014

Drupal 7 : change page title on node form

Every rule has its exceptions, setting drupal_set_title directly on form_alter doesn’t work for node form title. To customize pages like “Add node”, or “Edit node” :

  • Make a module

  • Add a function to implement hook_form_alter

  • Add a form afterbuild in your hook_form_alter implementation: $form['#after_build'][] = '_my_callback_form_set_title'

  • In '_my_callback_form_set_title', use drupal_set_title to change the form title: drupal_set_title(...)

  • Update system table to have the weight of your module greater than Node module (on a default install, core modules are weighted 0, so set your module weight to 1).

  • Rebuild registry, clear caches.