Skip to Main Content
Menu
Close Menu

Creating a Drupal Rector rule

Overview

Creating a Rector rule in Drupal Rector requires three steps:

  • Create an example file that shows deprecated code
  • Create a Rector class
  • Register the Rector class in a configuration file

We have recorded a video demonstrating how to create a simple rule.

Code used in the video example is provided below.

For additional examples and base classes, please refer to the Drupal Rector repository, https://github.com/palantirnet/drupal-rector/tree/master/src/Rector/Deprecation.

Video example

Updates

$this->getName() changes

Replace:

$this->getName($node)

With:

$this->getName($node->name)

This video was recorded using Rector 0.6. The new pattern works in both versions.

Rector class name changes

Rector has changed the class names used for its classes.

Replace:

use Rector\RectorDefinition\CodeSample;

With:

use Rector\Core\RectorDefinition\CodeSample;

Identifying classes to use in Rector

In the video, we used the Rector documentation to find class names. You can also use Php Parse to help.

Thanks to Adam Bergstein for suggesting the Php Parse tool and helping us understand how to use it.

For example:

vendor/bin/php-parse drupal-rector/rector_examples/drupal_url.php

The line in the example file:

\Drupal

This will produce output in Php Parse which includes:

class: Name_FullyQualified(

Which translates to this class in Rector:

Node\Name\FullyQualified

Code used in this example

These examples have been updated to work with Rector 0.7.* and are slightly different than the video.

drupal-rector/rector_examples/format_date.php.

First, we create an example file that shows the deprecated code that we need to update. Place that in a stand-alone PHP file. The example file is used to test the Rector rule we will write.

<?php

/**
 * This demonstrates the deprecated static calls that might be called from procedural code like '.module' files.
 */

/**
 * A simple example using the minimum number of arguments.
 */
function simple_example() {
  $formatted_date = format_date(123456);
}

/**
 * An example using all of the arguments.
 */
function using_all_arguments() {
  $formatted_date = format_date(time(), 'custom', 'Y M D', 'America/Los_Angeles', 'en-us');
}

drupal-rector/src/Rector/Deprecation/FormatDateRector.php

Next, we create the Rector file that replaces the deprecated code.

<?php

namespace DrupalRector\Rector\Deprecation;

use PhpParser\Node;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;

/**
 * Replaces deprecated format_date() calls.
 *
 * See https://www.drupal.org/node/1876852 for change record.
 *
 * What is covered:
 * - Static replacement
 *
 * Improvement opportunities
 * - Dependency injection
 */
 final class FormatDateRector extends FunctionToServiceBase
 {

    /**
     * @inheritdoc
     */
    public function getDefinition(): RectorDefinition
    {
        return new RectorDefinition('Fixes deprecated format_date() calls', [
            new CodeSample("$formatted_date = format_date(123456);", "\Drupal::service('date.formatter')->format(123456);")
        ]);
    }

  /**
   * @inheritdoc
   */
  public function getNodeTypes(): array
  {
    return [
      Node\Expr\FuncCall::class,
    ];
  }

  /**
   * @inheritdoc
   */
  public function refactor(Node $node): ?Node
  {
    /* @var Node\Expr\FuncCall $node */
    if ($this->getName($node->name) === 'format_date') {

      $var = new Node\Expr\StaticCall(new Node\Name\FullyQualified('Drupal'), new Node\Identifier('service'), [new Node\Arg(new Node\Scalar\String_('date.formatter'))]);

      $name = new Node\Identifier('format');

      $args = $node->args;

      $node = new Node\Expr\MethodCall($var, $name, $args);

      return $node;
    }

    return null;
  }

}

drupal-rector/config/drupal-8/drupal-8.0-deprecations.yml

Finally, we add the working rule to the list of deprecations in the YML file.

# Contains automatic fixes for some deprecations introduced in Drupal 8.0.
services:
  DrupalRector\Rector\Deprecation\FormatDateRector: ~

References

For more in-depth coverage of how to write rector rules, see the following documentation:

Drupal Rector repository rules and base classes

https://github.com/palantirnet/drupal-rector/tree/master/src/Rector/Deprecation

Rector node overview documentation

https://github.com/rectorphp/rector/blob/master/docs/NodesOverview.md

Thanks

Thanks to everyone who has provided feedback on Drupal Rector and on the existing project documentation!

We greatly appreciate hearing about what worked, what didn't work, and what bugs you encountered. We are working to incorporate that feedback into the project documentation and supporting resources like this page.

We also want to thank everyone who has and who will contribute resources around using Drupal Rector and the tools that it is built on. These additional perspectives are invaluable as we collectively build our knowledge of the capabilities and best practices for using these tools.

Let's work together.

Have an exceptional idea? Let's talk and see how we can help.
New Call-to-action