PHPackages                             palantirnet/drupal8-rector - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. palantirnet/drupal8-rector

Abandoned → [palantirnet/drupal-rector](/?search=palantirnet%2Fdrupal-rector)Library[Parsing &amp; Serialization](/categories/parsing)

palantirnet/drupal8-rector
==========================

Instant fixes for your Drupal code by using Rector.

0.21.2(1mo ago)15919577[16 PRs](https://github.com/palantirnet/drupal-rector/pulls)MITPHPCI passing

Since Jan 16Pushed 3w ago18 watchersCompare

[ Source](https://github.com/palantirnet/drupal-rector)[ Packagist](https://packagist.org/packages/palantirnet/drupal8-rector)[ RSS](/packages/palantirnet-drupal8-rector/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (10)Dependencies (20)Versions (121)Used By (0)

Drupal Rector
=============

[](#drupal-rector)

Automate fixing deprecated Drupal code.

Status
------

[](#status)

[![Packagist Version](https://camo.githubusercontent.com/4fabe9cce2ea1036215a37e9521dc4c9d074b6eb2ae214d5c366899d842706ba/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f70616c616e7469726e65742f64727570616c2d726563746f72)](https://packagist.org/packages/palantirnet/drupal-rector) [![Functional tests](https://camo.githubusercontent.com/ff0b60abf36ab503d92a0025f080fafa70463b310a733c5e71d978c0930d901b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f70616c616e7469726e65742f64727570616c2d726563746f722f66756e6374696f6e616c5f746573745f5f73696e676c655f726563746f72732e796d6c3f6c6f676f3d676974687562266c6162656c3d46756e6374696f6e616c2532307465737473)](https://camo.githubusercontent.com/ff0b60abf36ab503d92a0025f080fafa70463b310a733c5e71d978c0930d901b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f70616c616e7469726e65742f64727570616c2d726563746f722f66756e6374696f6e616c5f746573745f5f73696e676c655f726563746f72732e796d6c3f6c6f676f3d676974687562266c6162656c3d46756e6374696f6e616c2532307465737473) [![Unit tests](https://camo.githubusercontent.com/6ad4baa8f35aaa31e73ae37a45300bbd6e9d3b5190fb1b37eeef9f7d38cf8159/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f70616c616e7469726e65742f64727570616c2d726563746f722f706870756e69742e796d6c3f6c6f676f3d676974687562266c6162656c3d556e69742532307465737473)](https://camo.githubusercontent.com/6ad4baa8f35aaa31e73ae37a45300bbd6e9d3b5190fb1b37eeef9f7d38cf8159/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f70616c616e7469726e65742f64727570616c2d726563746f722f706870756e69742e796d6c3f6c6f676f3d676974687562266c6162656c3d556e69742532307465737473) [![PHPStan](https://camo.githubusercontent.com/a6735d62aabac6d64f63512c875fead129525a9ebc4299cc17cb99ee79c14f3b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f70616c616e7469726e65742f64727570616c2d726563746f722f7068707374616e2e796d6c3f6c6f676f3d676974687562266c6162656c3d5048505374616e)](https://camo.githubusercontent.com/a6735d62aabac6d64f63512c875fead129525a9ebc4299cc17cb99ee79c14f3b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f70616c616e7469726e65742f64727570616c2d726563746f722f7068707374616e2e796d6c3f6c6f676f3d676974687562266c6162656c3d5048505374616e)

If upgrading from an older version, refresh `rector.php` by copying from the vendor copy: `cp vendor/palantirnet/drupal-rector/rector.php .`

Introduction
------------

[](#introduction)

Originally created to automate Drupal 9 upgrades; Drupal 8 and 9 rules are still included for legacy projects. You can read more details in the following blog post:

Documentation
-------------

[](#documentation)

Development guides and other resources:

Changelog and release history:

Scope and limitations
---------------------

[](#scope-and-limitations)

Drupal 10 and 11 are the primary targets — deprecation coverage spans Drupal 10.0 through 11.4 (Drupal 8/9 rules are included for legacy projects). The development of this tool is prioritized by the perceived impact of the deprecations and updates. There are many deprecations that often involve several components and for each of these there are several ways to address the deprecation.

We've tried to determine impact based on:

- The use of the deprecated functionality in the contributed modules on Drupal.org
- If there are simple to develop ways to fix the deprecation

So, high impact (the code works in newer versions of Drupal for a large number of people), low effort (we can develop the rule based on our knowledge of Rector).

### Common limitations

[](#common-limitations)

Known limitations are listed in the comment documentation for each rule.

Common limitations include:

- Using static calls like `Drupal->service('my_service')->myMethod();` rather than injecting the service into the class
- Skipping complex use cases, such as when optional arguments are passed as variables
- Handling `use` statements in weird ways. Rector has a global option to handle `use` statements and we think the benefits outweigh the drawbacks such as weird placement or lack of handling of less common patterns.
- Handling doc comments in weird ways, particularly around spacing. Rector uses dependencies that sometimes delete empty comments or remove white space. At this point, Drupal Rector does not intend to modify any doc comments, but Rector ends up doing this.

Our hope is that as we learn more about Rector, we may be able to update these rules to add these features.

Issues are managed on [drupal.org](https://www.drupal.org/project/rector)
-------------------------------------------------------------------------

[](#issues-are-managed-on-drupalorg)

For contribution suggestions, please see the later section of this document.

Installation
------------

[](#installation)

**NOTE**: To have the best experience with Drupal Rector, your Drupal site should be running Drupal 10 or higher.

> **On Drupal 10 preparing for Drupal 11?** You can run Drupal Rector against a D10 site to clean up deprecations before upgrading. If your project pins PHPStan 1 (e.g. via `mglaman/phpstan-drupal`) the direct install below will conflict — see [Running against a Drupal 10 project](docs/running-against-drupal-10.md) for the standalone-runner recipe that avoids it.

### Install Drupal Rector inside a Drupal project.

[](#install-drupal-rector-inside-a-drupal-project)

```
$ composer require --dev palantirnet/drupal-rector
```

> **Trying the 1.0 pre-release?** The 1.0.x line is currently published as an alpha. Until a stable `1.0.0` is tagged, the command above resolves to the latest stable release — request the pre-release explicitly instead:
>
> ```
> $ composer require --dev "palantirnet/drupal-rector:^1.0@alpha"
> ```

### Create a configuration file in your project

[](#create-a-configuration-file-in-your-project)

You will need to have a `rector.php` configuration in the root of your repository. This should sit beside your document root such as `web` or `docroot`.

This project uses [`webflo/drupal-finder`](https://packagist.org/packages/webflo/drupal-finder) to find your document root that contains Drupal.

To get started, copy the `rector.php` configuration file provided by this package:

```
cp vendor/palantirnet/drupal-rector/rector.php .
```

By default, Drupal Rector will fix deprecated code for all versions of Drupal. If you want to change this behavior, modify the sets used in the `rector.php` config. For example, if your site is still on Drupal 10.3, and you do not want to fix deprecations made in Drupal 10.4, use the following configuration:

```
$rectorConfig->sets([
    Drupal10SetList::DRUPAL_100,
    Drupal10SetList::DRUPAL_101,
    Drupal10SetList::DRUPAL_102,
    Drupal10SetList::DRUPAL_103,
]);
```

This is more granular than the `Drupal10SetList::DRUPAL_10` set. Since Drupal 10.1 there is not real reason not to include later versions. It will detect the installed Drupal version and supply BC wrappers as needed if you enable it in the config.

### DrupalRectorSettings

[](#drupalrectorsettings)

The copied `rector.php` includes a `DrupalRectorSettings` block that controls two behaviours:

**Backward-compatibility wrapping** — when enabled, rule results are wrapped in `DeprecationHelper::backwardsCompatibleCall()` so the code works on both the old and new Drupal API simultaneously. The default in `rector.php` is **disabled** (recommended for most projects). Enable it when you need the output to run on multiple Drupal versions at the same time:

```
$rectorConfig->singleton(DrupalRectorSettings::class, fn () =>
    (new DrupalRectorSettings())
        ->enableBackwardCompatibility()
);
```

**Minimum supported Drupal version** (contrib modules) — if you are running Rector against a contrib module that must stay compatible with an older Drupal release, set `minimumCoreVersionSupported` so BC wrappers are emitted correctly even when your development environment runs a newer Drupal:

```
$rectorConfig->singleton(DrupalRectorSettings::class, fn () =>
    (new DrupalRectorSettings())
        ->enableBackwardCompatibility()
        ->setMinimumCoreVersionSupported('10.5.0')
);
```

### Cleaning up BC wrappers (contrib modules)

[](#cleaning-up-bc-wrappers-contrib-modules)

If you previously used backward-compatibility wrapping and have since raised your module's minimum supported Drupal version, use `DeprecationHelperRemoveRector` to strip the now-redundant wrappers. It replaces each `DeprecationHelper::backwardsCompatibleCall()` with the new API call directly, for any deprecation introduced before your configured minimum version.

```
use DrupalRector\Rector\Deprecation\DeprecationHelperRemoveRector;
use DrupalRector\Rector\ValueObject\DeprecationHelperRemoveConfiguration;

$rectorConfig->ruleWithConfiguration(DeprecationHelperRemoveRector::class, [
    new DeprecationHelperRemoveConfiguration('10.3.0'),
]);
```

With the above, a wrapper like:

```
DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '9.1.0',
    fn() => \Drupal::service('password_generator')->generate(),
    fn() => user_password()
);
```

becomes:

```
\Drupal::service('password_generator')->generate();
```

Wrappers for deprecations introduced at or after your minimum version are left untouched. The rule is commented out in `rector.php` — uncomment and set the version when you are ready to clean up.

Suggested workflow
------------------

[](#suggested-workflow)

1. Analyze your code with Rector and review suggested changes:

```
$ vendor/bin/rector process web/modules/contrib/[YOUR_MODULE] --dry-run
```

2. Apply suggested changes:

```
$ vendor/bin/rector process web/modules/contrib/[YOUR_MODULE]
```

You can find more information about Rector [here](https://github.com/rectorphp/rector).

Converting hooks to OOP hook classes (run as a separate pass)
-------------------------------------------------------------

[](#converting-hooks-to-oop-hook-classes-run-as-a-separate-pass)

Drupal Rector ships `HookConvertRector`, which converts procedural hook implementations (`mymodule_form_alter()`, …) into a `#[Hook]`-attributed class under `src/Hook/`. **This rule must be run on its own, as a second pass, after your normal deprecation run — never in the same configuration as the deprecation sets.**

To convert hooks, run your deprecation pass first, then point Rector at the dedicated config that registers only `HookConvertRector`:

```
# Pass 1 — fix deprecations in place (your normal config)
$ vendor/bin/rector process web/modules/contrib/[YOUR_MODULE]

# Pass 2 — convert hooks to OOP hook classes
$ vendor/bin/rector process web/modules/contrib/[YOUR_MODULE] \
    --config=vendor/palantirnet/drupal-rector/rector-hook-convert.php
```

**Why two passes?** `HookConvertRector` moves each hook body into a brand-new `src/Hook/*Hooks.php` file that it writes directly to disk. Rector (2.x) cannot feed a newly-created file back through the rule pipeline within the same run, so a deprecated API call that lives inside a hook body would be copied into the new class **unchanged** if hook conversion ran together with the deprecation sets. Running deprecations first means the bodies are already fixed before they are moved. For this reason the example `rector.php` above intentionally does **not**register `HookConvertRector`.

Development and contribution suggestions
----------------------------------------

[](#development-and-contribution-suggestions)

Thanks for your interest in contributing!

Our goal is to make contributing to this project easy for people. While we've made certain architectural decisions here to hopefully achieve that goal, it's a work in progress and feedback is appreciated.

### Adding a Rector rule

[](#adding-a-rector-rule)

If you would like to submit a Rector rule, we are looking for the following:

- A Rector rule class, see `src/Rector/Deprecation` for existing rules. Copy an existing class as a starting point.
- A test class in `tests/src/Drupal{8,9,10,11}/Rector/` and fixture files in `tests/src/Drupal*/Rector/**/fixture/`
- An updated configuration file that registers the Rector rule, see `config/drupal-{8,9,10,11}/`

#### Guides

[](#guides)

A few guides are currently available and we encourage people to create additional guides to provide their perspective and help us better understand this tool together.

##### Additional documentation and links

[](#additional-documentation-and-links)

#### Quick overview

[](#quick-overview)

##### Create a Rector rule class

[](#create-a-rector-rule-class)

Rector rules should be named after the deprecation, including the class name.

`Drupal::url()` -&gt; `DrupalUrlRector.php``drupal_set_message()` -&gt; `DrupalSetMessageRector.php`

We would like one Rector rule per deprecation. Some deprecations include updating multiple things and those would be separate rules.

All drupal-rector rules extend `AbstractDrupalCoreRector` (found in `src/Rector/AbstractDrupalCoreRector.php`) rather than Rector's own `AbstractRector`. This base class provides three things automatically:

- **Version gating** — skips the rule if the installed Drupal version predates the deprecation via `rectorShouldApplyToDrupalVersion()`
- **BC wrapping** — when backward-compatibility mode is enabled, wraps `Expr`→`Expr` results in `DeprecationHelper::backwardsCompatibleCall()` automatically
- **Configuration pattern** — you implement `refactorWithConfiguration(Node $node, VersionedConfigurationInterface $configuration)` instead of `refactor()`

To avoid duplication, we have created base classes for simple repeated patterns where possible. These end in `Base.php` and are located in `src/Rector/Deprecation/Base`. In many of these rules, you will extend the base class, define class properties, add a class comment, and define the definition.

Rector supports passing parameters to rules and you can also define your rules in a variety of ways. To avoid confusion for new developers, we're trying to avoid these advanced features so that someone with limited familiarity with the tool can easily determine where things are located and what they are doing. If the copy &amp; paste challenge isn't worth this trade-off, we can re-evaluate it as we go. Suggestions appreciated.

##### Create / Update a configuration file

[](#create--update-a-configuration-file)

The configuration files in `config/drupal-{8,9,10,11}/` are broken down by Drupal minor versions.

Add your Rector rule to the relevant file. Always add a comment with a link to the issue and change record.

The key is the fully qualified class name of the Rector rule. The key is the yaml null value `~`.

Pinning dev dependencies
------------------------

[](#pinning-dev-dependencies)

If there are conflicts with Rector, the package version can be conflicted with `conflict` on `rector/rector` and `phpstan/phpstan`.

- View the tree for the commit on GitHub and it's `composer/installed.json` file (example )
- Use the reference to pin the `phpstan/phpstan` dependency.

Credits
-------

[](#credits)

Current development is sponsored by [SWIS.nl](https://www.swis.nl).
Current development is sponsored by [Palantir.net](https://www.palantir.net).
Initial development is sponsored by [Pronovix](https://pronovix.com).

###  Health Score

57

—

FairBetter than 98% of packages

Maintenance92

Actively maintained with recent releases

Popularity31

Limited adoption so far

Community33

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~49 days

Recently: every ~93 days

Total

48

Last Release

31d ago

Major Versions

0.21.2 → 1.0.0-alpha12026-06-01

### Community

Maintainers

![](https://www.gravatar.com/avatar/e4d789212d8294371ed2521e511703742071759baf31283c89fd4bec76b869b6?d=identicon)[palantirnet](/maintainers/palantirnet)

![](https://avatars.githubusercontent.com/u/22901?v=4)[Ofer Shaal](/maintainers/shaal)[@shaal](https://github.com/shaal)

![](https://www.gravatar.com/avatar/83bf1351140cdffe8341925a6708101d53da8b48930f325c0e3569e2f73ee18e?d=identicon)[becw](/maintainers/becw)

---

Top Contributors

[![bbrala](https://avatars.githubusercontent.com/u/3294970?v=4)](https://github.com/bbrala "bbrala (616 commits)")[![damontgomery](https://avatars.githubusercontent.com/u/397902?v=4)](https://github.com/damontgomery "damontgomery (273 commits)")[![mglaman](https://avatars.githubusercontent.com/u/3698644?v=4)](https://github.com/mglaman "mglaman (208 commits)")[![agentrickard](https://avatars.githubusercontent.com/u/360988?v=4)](https://github.com/agentrickard "agentrickard (130 commits)")[![mxr576](https://avatars.githubusercontent.com/u/1755573?v=4)](https://github.com/mxr576 "mxr576 (67 commits)")[![goba](https://avatars.githubusercontent.com/u/235185?v=4)](https://github.com/goba "goba (22 commits)")[![Kbentham](https://avatars.githubusercontent.com/u/1236362?v=4)](https://github.com/Kbentham "Kbentham (20 commits)")[![dww](https://avatars.githubusercontent.com/u/203658?v=4)](https://github.com/dww "dww (12 commits)")[![claudiu-cristea](https://avatars.githubusercontent.com/u/473868?v=4)](https://github.com/claudiu-cristea "claudiu-cristea (8 commits)")[![tobiasbaehr](https://avatars.githubusercontent.com/u/105220?v=4)](https://github.com/tobiasbaehr "tobiasbaehr (7 commits)")[![timohuisman](https://avatars.githubusercontent.com/u/22369642?v=4)](https://github.com/timohuisman "timohuisman (6 commits)")[![shaal](https://avatars.githubusercontent.com/u/22901?v=4)](https://github.com/shaal "shaal (5 commits)")[![steveworley](https://avatars.githubusercontent.com/u/1840912?v=4)](https://github.com/steveworley "steveworley (5 commits)")[![CocoaBean5](https://avatars.githubusercontent.com/u/10488517?v=4)](https://github.com/CocoaBean5 "CocoaBean5 (4 commits)")[![TomasVotruba](https://avatars.githubusercontent.com/u/924196?v=4)](https://github.com/TomasVotruba "TomasVotruba (3 commits)")[![nlighteneddesign](https://avatars.githubusercontent.com/u/7533595?v=4)](https://github.com/nlighteneddesign "nlighteneddesign (3 commits)")[![webflo](https://avatars.githubusercontent.com/u/123946?v=4)](https://github.com/webflo "webflo (3 commits)")[![samsonasik](https://avatars.githubusercontent.com/u/459648?v=4)](https://github.com/samsonasik "samsonasik (3 commits)")[![nerdstein](https://avatars.githubusercontent.com/u/966547?v=4)](https://github.com/nerdstein "nerdstein (3 commits)")[![yusufhm](https://avatars.githubusercontent.com/u/1160048?v=4)](https://github.com/yusufhm "yusufhm (2 commits)")

---

Tags

drupalhacktoberfestphprectorCode styledrupalastrector

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/palantirnet-drupal8-rector/health.svg)

```
[![Health](https://phpackages.com/badges/palantirnet-drupal8-rector/health.svg)](https://phpackages.com/packages/palantirnet-drupal8-rector)
```

###  Alternatives

[palantirnet/drupal-rector

Instant fixes for your Drupal code by using Rector.

1584.7M30](/packages/palantirnet-drupal-rector)[driftingly/rector-laravel

Rector upgrades rules for Laravel Framework

1.2k15.4M711](/packages/driftingly-rector-laravel)[drupal/drupal-extension

Drupal extension for Behat

22215.7M172](/packages/drupal-drupal-extension)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k14](/packages/tempest-framework)[ssch/typo3-rector

Instant fixes for your TYPO3 PHP code by using Rector.

2603.2M426](/packages/ssch-typo3-rector)[ajthinking/archetype

Programmatically edit PHP and Laravel files.

2723.9M19](/packages/ajthinking-archetype)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
