palantirnet/drupal-rector
Instant fixes for your Drupal code by using Rector.
1.1.2
5.0M downloads/mo
#1984 most downloaded on Packagist
palantirnet/drupal-rector
What this package is like to depend on
Last release 23 days ago
31 Jul 2026
Ships unpredictably
gaps range from 8 days to 12 months
Nearly every release is documented
notes for 48 of 51 stable releases
Nothing withdrawn
no release was ever pulled
7 years old
59 releases · first in 2020
15 releases in the last 12 months
see the full history below
Release timeline
59 releases · Jan 2020 to Jul 2026Releases
latest 59-
1.1.231 Jul 2026Release notes
Open source →What's Changed
- docs: Add rule interface so we can publish docs on getrector.com by @bbrala in #408
- Don't make converted hook methods static by @bbrala in #410
- Fix comment typo in rector.php by @mbomb007 in #413
- docs: update naming of the composer sets so documentation on rectorph… by @bbrala in #416
- feat: populate phpstan-drupal ServiceMap in bootstrap when Rector injects the PHPStan container [#3600964] by @bbrala in #412
- fix: drop Drupal 11.4 search plugin renames from DRUPAL_114_BREAKING by @bbrala in #417
- feat: remove RemoveAliasManagerCacheMethodCallsRector by @bbrala in #418
New Contributors
Full Changelog: 1.1.0...1.1.2
-
1.1.111 Jul 2026Release notes
Open source →What's Changed
- docs: Add rule interface so we can publish docs on getrector.com by @bbrala in #408
- Don't make converted hook methods static by @bbrala in #410
Full Changelog: 1.1.0...1.1.1
-
1.1.009 Jul 2026Release notes
Open source →What's Changed
- Add contrib-search skill; delegate rector-live-test module discovery to it by @bbrala in #406
- Add AddSymfonyConstraintValidatorTypeDeclarationsRector (Symfony 8 / Drupal 12 validator type declarations) by @bbrala in #407
- fix: conditional (BC) removal in RemoveAliasManagerCacheMethodCallsRector by @bbrala in #405
- docs: prepare 1.1.0 release and backfill 1.0.1 changelog by @bbrala in #409
Full Changelog: 1.0.1...1.1.0
Release notes
Open source →Added
AddSymfonyConstraintValidatorTypeDeclarationsRector— adds the Symfony 8 / Drupal 12 type declarations (mixed $valueand: voidonvalidate(),: voidoninitialize()) toSymfony\Component\Validator\ConstraintValidatorInterfaceimplementers. Backward compatible on all supported Drupal versions, so no version gate. (#3600790)
Fixed
- Composer-based sets bootstrap — the Drupal bootstrap now loads correctly when rector is run through the composer-based sets, so rules that rely on the Drupal container / class map resolve as expected in that scenario (#404).
RemoveAliasManagerCacheMethodCallsRector— no longer removes calls toAliasManager::setCacheKey()/writeCache()unconditionally, which broke backward compatibility on Drupal < 11.3. These methods only became no-ops in 11.3.0 (when the path alias preload cache was replaced by a Fiber-based bulk-lookup strategy); before 11.3.0 they performed real caching work. The rector now extendsAbstractDrupalCoreRectorand, when BC support is enabled, wraps the call in aDeprecationHelper::backwardsCompatibleCall()with a no-op current callable so the caching still runs on Drupal < 11.3 and is skipped on 11.3+. When BC support is disabled the call is removed as before. Reported by Berdir (#3600789).
-
1.0.102 Jul 2026Release notes
Open source →Fixed
- Composer-based sets bootstrap — the Drupal bootstrap now loads correctly when rector is run through the composer-based sets, so rules that rely on the Drupal container / class map resolve as expected in that scenario (#404).
-
1.0.002 Jul 2026Release notes
Open source →Overview
The first stable release of the 1.0 line. It ships full Drupal 11 deprecation
coverage (11.0–11.4), Drupal 10.3 additions, the container-managed
DrupalRectorSettingsservice, and Composer-based sets — Rector now pins the
active rule set to the exact Drupal version Composer installed, so you get clean,
single-version rewrites with noDeprecationHelperwrappers to clean up later.
See the Drupal.org post Use Rector on your Drupal site: easier than ever with
new Composer-based sets
for a walkthrough.Everything in the
1.0.0-alpha1/-beta*series is rolled up here. The betas
hardened the release against contrib-wide validation (whole-of-contrib runs via
project_analysis); nothing
below changes the public API since alpha1.Changes since 1.0.0-alpha1
- Composer-based sets (
beta2/beta3) —DrupalSetProviderloads only the
deprecation sets live on the installed Drupal version, and registers
DrupalRectorSettingswith BC wrapping disabled by default. Projects that must
target multiple Drupal minors can re-enable it in their ownrector.php. - PHPUnit metadata attributes (
beta3) —PhpUnitTestAnnotationToAttributeRector
andPhpUnitAddRunTestsInSeparateProcessesAttributeRector;@group legacy→
#[IgnoreDeprecations]folded into the former. - By-reference BC wrappers (
beta7) —DeprecationHelper::backwardsCompatibleCall()
now wraps calls that pass a variable to a by-reference parameter
(&$variables,&$form, …) in a long closure that captures by reference, so
mutations are no longer silently dropped. MethodToMethodWithCheckRector(beta6) — only rewrites on a definite
receiver-type match, dropping false positives on unrelated classes.AnnotationToAttributeRector(beta5) — preserves the positional/keyless
annotation value (e.g.#[FormElement('foo')]) and is idempotent across name
importing (beta3).- BC-wrapper simplifications —
RemoveConfigSaveTrustedDataArgRectorand
FileSystemBasenameToNativeRectornow emit plain$config->save()/
basename(...)calls, since both rewrites are behaviourally equivalent on every
supported version.
For the complete feature list — every shipped rector, the
DrupalRectorSettings
service, the Claude Code skills, upgrade notes, and compatibility matrix — see the
1.0.0-alpha1notes below.1.0.0-alpha1 - 2026-06-01
Overview
The first alpha of the 1.0 line. It adds full Drupal 11 deprecation coverage (11.0
through 11.4), a container-managed settings service that gives you explicit control
over backward-compatibility wrapping, and a documented set of Claude Code skills for
building further rectors. It also drops support for Rector 1.Validated end-to-end against real code:
- Applied to Drupal Canvas on the
canvas-3589155branch; the full Canvas test suite passed
(pipeline 825601). - Run across the whole of Drupal contrib via
project_analysis: code
branchmaster-next,
generated patches under
results-next.
Spot-checking those patches drove several of the late fixes below: the PDO
receiver guard, the BC-wrapper mutation bug, theConstantToClassConstantRector
generalisation, and the extraMethodToMethodWithCheckRectorpatterns.
Highlights
- Drupal 11.0–11.4 coverage. 72 rectors wired across five per-minor-version
deprecation set lists, covering function → service / function → static / function
→ method-on-first-arg / class-constant → enum / class rename / argument removal
/ property → method / and configuration-key rewrites. - Drupal 10.3 additions. 4 new D10 rectors covering
REQUEST_TIME,
ThemeHandlerInterface::rebuildThemeData(),ModuleHandlerInterface::getName(),
andFileSystemInterface::EXISTS_*→FileExistsenum. DrupalRectorSettingsservice. Three knobs for tuning runtime behaviour:
toggle BC wrapping on/off, set aminimumCoreVersionSupported(contrib modules),
and override the detected Drupal version (tests). Registered via
$rectorConfig->singleton(DrupalRectorSettings::class, …)in the shipped
rector.php.- Generic data-driven rectors. A new shared rector
(FunctionCallRemovalRector) and two extracted from per-version folders
(DrupalServiceRenameRector,FunctionToFirstArgMethodRector) now live in
src/Rector/Deprecation/alongside the established shared rectors, so each
Drupal version can register them via config-only entries rather than
per-version subclasses. See the Generic shared rectors subsection below
for a labelled list of what's new vs. refactored vs. unchanged. - BC wrapping covers all expression rewrites. Previously
AbstractDrupalCoreRector::createBcCallOnExpr()only wrapped CallLike → CallLike
rewrites; it now wraps anyNode\Expr→Node\Exprtransformation
(ClassConstFetch,PropertyFetch, etc.), so mixed-type rewrites get
DeprecationHelper::backwardsCompatibleCall()automatically. - Claude Code skills. Four
.claude/skills/entries (/rector-discover,
/rector-implement,/rector-qa,/rector-live-test) drive the conversion
pipeline from dbuytaert/drupal-digests
rules into shipped rector classes with tests. Includes the 700-line canonical
conversion prompt and three reusable recipes.
Added
Infrastructure
rector-hook-convert.php: dedicated configuration that registers
onlyHookConvertRector, for running hook conversion as a separate second
pass.HookConvertRectorwrites the generatedsrc/Hook/*Hooks.phpto disk
outside Rector's file pipeline, so bundling it with the deprecation sets would
copy un-fixed hook bodies into the new class. Documented in the README
("Converting hooks to OOP hook classes"): run deprecations first, then this
config.DrupalRectorSettings(src/Services/DrupalRectorSettings.php): container-
managed settings object withenableBackwardCompatibility()/
disableBackwardCompatibility()/setMinimumCoreVersionSupported(string)/
setDrupalVersion(?string)methods. Resolved via
static::getContainer()->make(DrupalRectorSettings::class)in tests.AbstractDrupalRectorTestCase(tests/src/AbstractDrupalRectorTestCase.php):
replaces the prior namespaced-class\Drupalhack with a proper
setUp/tearDownpattern that resets the sharedDrupalRectorSettings
singleton between tests, preventing version-override leaks.createBcCallOnExpr()widened toNode\Exprin
src/Rector/AbstractDrupalCoreRector.php, so non-CallLike rewrites are
BC-wrapped too..gitattributesadded withexport-ignoreentries for.claude/,
.github/,tests/,fixtures/,docs/,scripts/,phpstan*.neon,
phpunit.xml,rector.php, etc. Keeps the Composer dist archive small and
clean. (Verify withgit archive HEAD | tar t | grep -c .claude; expect 0.)- 25 PHPStan stubs under
stubs/covering core classes the rectors type-guard
against (ModuleHandlerInterface,EntityInterface,ConfigEntityInterface,
StatementPrefetchIterator,CachePluginBase,ThemeHandlerInterface,
SessionManagerInterface, …).
Drupal 11 deprecation rules
Every rule wired across
config/drupal-11/drupal-11.{0,1,2,3,4}-deprecations.php
is listed below. Each row links to the Drupal.org change record (or, if no
dedicated change record exists, the parent issue). Configurable generic rectors
(FunctionToServiceRector,FunctionToStaticRector,FunctionCallRemovalRector,
ConstantToClassConstantRector,ClassConstantToClassConstantRector,
MethodToMethodWithCheckRector,FunctionToFirstArgMethodRector,
RenameClassRector) may appear in multiple rows when they handle several
distinct deprecations in the same minor.Drupal 11.0
Rule What it does Change record GetNameToNameRectorTestCase::getName()→name()node/3217904 RemoveStateCacheSettingRectorRemove $settings['state_cache']; state caching is permanently enablednode/2575105 ReplaceRequestTimeConstantRectorREQUEST_TIME→\Drupal::time()->getRequestTime()node/3395986 StripMigrationDependenciesExpandArgRectorgetMigrationDependencies($expand)→ drop the boolean argnode/3442785 MigrateSqlGetMigrationPluginManagerRectorSql::getMigrationPluginManager()→$this->migrationPluginManagerpropertynode/3282894 Drupal 11.1
Rule What it does Change record PluginBaseIsConfigurableRectorPluginBase::isConfigurable()→instanceof ConfigurableInterfacechecknode/2946122 RenameClassRectorAliasWhitelist[Interface]→AliasPrefixList[Interface];MatchingRouteNotFoundException→ResourceNotFoundExceptionnode/3467559 MethodToMethodWithCheckRectorAliasManager::pathAliasWhitelistRebuild()→pathAliasPrefixListRebuild()node/3467559 RemoveModuleHandlerDeprecatedMethodsRectorModuleHandler::writeCache()removed;getHookInfo()returns[]node/3368812 ReplaceLocaleConfigBatchFunctionsRectorRename locale_config_batch_set_config_langcodes()andlocale_config_batch_refresh_name()node/3575254 RemoveUpdaterPostInstallMethodsRectorRemove Updater::postInstall*()methods (no replacement)node/3461934 BlockContentTestBaseStringToArrayRectorBlockContentTestBase::createBlockContentType($string)→ array argnode/3473739 MovePointerToMouseOverRectormovePointerTo($css)→getSession()->getDriver()->mouseOver($xpath)node/3460567 ReplaceAddCachedDiscoveryMethodCallRectoraddMethodCall('addCachedDiscovery', …)onplugin.cache_clearerremovednode/3442229 FunctionToStaticRectordrupal_common_theme()→ThemeCommonElements::commonElements()node/3488176 Drupal 11.2
Rule What it does Change record StatementPrefetchIteratorFetchColumnRectorStatementPrefetchIterator::fetchColumn()→fetchField()node/3490312 MethodToMethodWithCheckRectorCacheBackendInterface::invalidateAll()→deleteAll()node/3500622 FunctionToServiceRectortemplate_preprocess_{html,page,container,links,time,datetime_form,datetime_wrapper}()→ThemePreprocess/DatePreprocessservice methodsnode/3504125 FunctionCallRemovalRectorRemove template_preprocess(),update_clear_update_disk_cache(),update_delete_file_if_stale(),_update_manager_{cache_directory,extract_directory,unique_identifier}()node/3501136 RemoveModuleHandlerAddModuleCallsRectorRemove ModuleHandler::addModule()/addProfile()(no-ops)node/3550193 RemoveHandlerBaseDefineExtraOptionsRectorRemove HandlerBase::defineExtraOptions()overrides (dead code)node/3486781 FunctionToStaticRectordrupal_requirements_severity()→RequirementSeverity::maxSeverityFromRequirements()node/3497049 FunctionToServiceRectorviews_field_default_views_data()and_views_field_get_entity_type_storage()→ servicesnode/3489415 ConstantToClassConstantRectorGlobal REQUIREMENT_INFO/OK/WARNING/ERROR→RequirementSeverity::*node/3575841 RemoveTwigNodeTransTagArgumentRectorDrop the 6th $tagargument fromTwigNodeTransconstructor callsnode/3474692 ReplaceAlphadecimalToIntNullRectorNumber::alphadecimalToInt(null|'')→0node/3494472 ReplaceFieldgroupToFieldsetRectorRender-array '#type' => 'fieldgroup'→'fieldset'node/3515272 ReplacePdoFetchConstantsRector\PDO::FETCH_*→\Drupal\Core\Database\Statement\FetchAs::*(StatementInterface receiver only)node/3488338 ReplaceDateTimeRangeConstantsRectorDateTimeRangeConstantsInterface::{BOTH,START_DATE,END_DATE}→ enum->value;datetime_type_field_views_data_helper()→ servicenode/3574901 FunctionToFirstArgMethodRectorfile_get_content_headers($file)→$file->getDownloadHeaders()node/3494172 ReplaceSessionWritesWithRequestSessionRector$_SESSION['key'] = $value→\Drupal::request()->getSession()->set(...)node/3518914 ReplaceEditorLoadRectoreditor_load($format_id)→entityTypeManager()->getStorage('editor')->load($format_id)node/3509245 ReplaceEntityOriginalPropertyRector$entity->originalmagic property →$entity->getOriginal()/setOriginal(); nullsafe-awarenode/3571065 RenameStopProceduralHookScanRector#[StopProceduralHookScan]→#[ProceduralHookScanStop]node/3495943 RenameClassRectorDrupal\Core\Entity\Query\Sql\pgsql\*→Drupal\pgsql\Entity\Query\*;jsonapiResourceResponseValidator movenode/3488572 RemoveCacheTagChecksumAssertionsRectorRemove CacheTagChecksumCount/CacheTagIsValidCountperformance-trait assertionsnode/3511149 RemoveRootFromCreateConnectionOptionsFromUrlRectorConnection::createConnectionOptionsFromUrl(); drop$rootparameternode/3511287 ClassConstantToClassConstantRectorSystemManager::REQUIREMENT_*→RequirementSeverity::*node/3410939 Drupal 11.3
Rule What it does Change record ReplaceCommentManagerGetCountNewCommentsRectorCommentManager::getCountNewComments()→HistoryManager::getCountNewComments()node/3551729 LoadAllIncludesRectorModuleHandler::loadAllIncludes()→ explicitforeach (getModuleList() …) loadInclude()node/3536432 NodeStorageDeprecatedMethodsRectorNodeStorage::revisionIds()/userRevisionIds()→ entity query chains;countDefaultLanguageRevisions()removednode/3519187 FunctionToServiceRectornode_mass_update()→NodeBulkUpdate::process()node/3533083 FunctionToServiceRectortemplate_preprocess_layout()→LayoutDiscoveryThemeHooks::preprocessLayout()node/3504125 ReplaceTwigExtensionRectortwig_extension()→'.html.twig'string literalnode/1685492 ReplaceNodeModuleProceduralFunctionsRectornode_type_get_names()→entity_type.bundle.infoservice;node_get_type_label($node)→$node->getBundleEntity()->label()node/3516778 FunctionCallRemovalRectorRemove block_content_add_body_field()calls (replaced by config)node/3535528 FunctionToFirstArgMethodRectorcomment_uri($comment)→$comment->permalink()node/2010202 ReplaceNodeAccessViewAllNodesRectornode_access_view_all_nodes()→ entity-type-manager access-control chainnode/3038909 FunctionToServiceRectorresponsive_image_*()helpers →responsive_image.builderservicenode/3548329 ReplaceNodeAddBodyFieldRectornode_add_body_field()→$this->createBodyField()(BodyFieldCreationTrait)node/3516778 ReplaceUserSessionNamePropertyRector$userSession->nameread →getAccountName()node/3513877 FunctionToStaticRectorfile_system_settings_submit()→FileSystemSettingsForm::submit()node/3534091 FileManagedFileSubmitRector'file_managed_file_submit'string callback →[ManagedFile::class, 'submit']array callablenode/3534091 ConstantToClassConstantRectorGlobal JSONAPI_FILTER_AMONG_*→\Drupal\jsonapi\JsonApiFilter::AMONG_*node/3495601 ReplaceNodeSetPreviewModeRectorDRUPAL_DISABLED/OPTIONAL/REQUIRED(and integers) insetPreviewMode()→NodePreviewModeenumnode/3538666 FileSystemBasenameToNativeRectorFileSystem::basename()→ PHP nativebasename()node/3530869 ErrorCurrentErrorHandlerRectorError::currentErrorHandler()→ PHPget_error_handler()node/3529500 ReplaceThemeGetSettingRectortheme_get_setting()→ThemeSettingsProviderservice;_system_default_theme_features()→ThemeSettingsProvider::DEFAULT_THEME_FEATURESnode/3573896 RemoveRootFromConvertDbUrlRectorDatabase::convertDbUrlToConnectionInfo($url, $root, …); drop the$rootargnode/3511287 RenameClassRectorworkspaces.associationservice /WorkspaceAssociation*→workspaces.tracker/WorkspaceTracker*node/3551450 Drupal 11.4
Rule What it does Change record ViewsPluginHandlerManagerRectorViews::pluginManager()/handlerManager()→plugin.manager.views.*servicesnode/3566982 FunctionToServiceRectornode_access_grants()→NodeGrantsHelper::nodeAccessGrants()node/3578055 NodeAccessRebuildFunctionsRectornode_access_rebuild()/node_access_needs_rebuild()→NodeAccessRebuildservicenode/3534610 FilterFormatFunctionsToServiceRectorfilter_formats(),filter_get_roles_by_format(),filter_get_formats_by_role(),filter_default_format(),filter_fallback_format()→FilterFormatRepositoryInterfaceservicenode/3035368 MediaFilterFormatEditFormValidateRectormedia_filter_format_edit_form_validate()→MediaHooks::formatEditFormValidate()node/3566774 DeprecatedFilterFunctionsRector_filter_autop()/_filter_html_escape()/_filter_html_image_secure_process()→plugin.manager.filtercreateInstance chainnode/3566774 ReplaceSessionManagerDeleteRectorSessionManager::delete($uid)→UserSessionRepositoryInterface::deleteAll($uid)node/3570851 ClassConstantToClassConstantRectorCommentItemInterface::{FORM_BELOW,FORM_SEPARATE_PAGE,HIDDEN,CLOSED,OPEN}andCommentInterface::ANONYMOUS_*→FormLocation/CommentingStatus/AnonymousContactenumsnode/3550054 FunctionToServiceRectorlanguage_configuration_element_submit()→LanguageConfiguration::submit()node/3574727 FunctionCallRemovalRectorRemove field_ui_form_manage_field_form_submit(),automated_cron_settings_submit(),syslog_facility_list(),syslog_logging_settings_submit(),taxonomy_build_node_index(),taxonomy_delete_node_index(), views_ui contextual-suppress functionsnode/3566774 RemoveSetUriCallbackRectorRemove EntityTypeInterface::setUriCallback()calls; uselink_templatesinsteadnode/3575062 ReplaceRecipeRunnerInstallModuleRectorRecipeRunner::installModule($module)→installModules([$module])node/3579527 ReplaceSystemPerformanceGzipKeyRectorsystem.performancecss.gzip/js.gzipconfig keys →css.compress/js.compressnode/3526344 RemoveViewsRowCacheKeysRectorRemove CachePluginBase::getRowCacheKeys()/getRowId()overridesnode/3564958 RemoveCacheExpireOverrideRectorRemove CachePluginBase::cacheExpire()subclass overridesnode/3576855 RemoveTrustDataCallRectorStrip ->trustData()fromConfigfluent chainsnode/3348180 RemoveConfigSaveTrustedDataArgRectorConfig::save($has_trusted_data); drop the boolean argnode/3348180 RemoveLinkWidgetValidateTitleElementRectorRemove LinkWidget::validateTitleElement(); now handled byLinkTitleRequiredConstraintnode/3554139 RemoveAutomatedCronSubmitHandlerRectorDrop 'automated_cron_settings_submit'from$form['#submit'];#config_targetnow handles config savenode/3566774 ReplaceViewsProceduralFunctionsRectorviews_view_is_{enabled,disabled}(),views_{enable,disable}_view(),views_get_view*()→ entity-storage /Views::*static callsnode/3572594 GetOriginalClassToGetDecoratedClassesRectorEntityTypeInterface::getOriginalClass()→getDecoratedClasses()array accessnode/3557464 UseEntityTypeHasIntegerIdRectorgetEntityTypeIdKeyType() === 'integer',entityTypeSupportsComments(),hasIntegerId($entityType)→EntityTypeInterface::hasIntegerId()node/3566814 FunctionToServiceRectoreditor_filter_xss()→EditorXssFilterInterfaceservicenode/3568144 FunctionToStaticRector_media_library_configure_form_display()/_media_library_configure_view_display()→ static helpersnode/3566774 FunctionToStaticRectorlanguage_configuration_element_submit()static-call form →LanguageConfiguration::submit()node/3574727 FunctionToServiceRectorcontextual_links_to_id()/contextual_id_to_links()→ContextualLinksSerializernode/3568087 FunctionToServiceRectorviews_add_contextual_links()→views.contextual_linksservicenode/3382344 ConstantToClassConstantRectorIMAGE_DERIVATIVE_TOKEN→ImageStyleInterface::TOKENnode/3567619 ReplaceEntityReferenceRecursiveLimitRectorEntityReferenceEntityFormatter::RECURSIVE_RENDER_LIMIT→ literal20node/2940605 SystemRegionFunctionsRectorsystem_region_list()/system_default_region()→theme.region.managerservicenode/3015812 CheckMarkupToProcessedTextRectorcheck_markup()→ processed-text render arraynode/3588040 RemoveFilterTipsLongParamRectorFilterInterface::tips(); drop the$longparameternode/3567879 SystemSortThemesRector'system_sort_themes'string callback →Closure(closure callable)node/3566774 LocaleCompareIncToServiceRectorlocale_translation_flush_projects()/locale_translation_build_projects()/locale_translation_check_projects*()etc. →locale.projectandLocaleSourceservicesnode/3037031 Drupal 10.3 deprecation rules
Wired in
config/drupal-10/drupal-10.3-deprecations.php.Rule What it does Change record MethodToMethodWithCheckRectorRendererInterface::renderPlain()→renderInIsolation()node/3407994 FunctionToStaticRectorfile_icon_class()→IconMimeTypes::getIconClass();file_icon_map()→IconMimeTypes::getGenericMimeType()node/3411269 ReplaceRebuildThemeDataRectorThemeHandlerInterface::rebuildThemeData()→extension.list.themeservicenode/3413196 ReplaceModuleHandlerGetNameRectorModuleHandlerInterface::getName()→extension.list.moduleservicenode/3310017 ClassConstantToClassConstantRectorFileSystemInterface::EXISTS_*→\Drupal\Core\File\FileExistsenumnode/3426517 Generic shared rectors
All eight live under
src/Rector/Deprecation/. Each row labels what changed in
this release:(new)introduced in this PR,(refactored)existing class
restructured,(enhanced)new feature added,(moved)relocated from a
per-version folder,(pre-existing)unchanged but used by new D10.3 / D11
configs.Rector Status in this release Notes FunctionCallRemovalRector(new) Removes deprecated function-call statements that have no direct replacement. Supports an accumulating configuration so per-version config files each contribute their own function list. ConstantToClassConstantRector(refactored) Now extends AbstractDrupalCoreRectorso it participates in BC wrapping when aVersionedConfigurationis supplied. Three previously-bespoke rectors (ReplaceRequirementSeverityConstantsRector,ReplaceJsonApiFilterConstantsRector,ReplaceLocaleTranslationDefaultServerPatternRector) were collapsed into config entries against this class.FunctionToServiceRector(enhanced) New useClassSyntaxoption onFunctionToServiceConfigurationemits\Drupal::service(ClassName::class)instead of a string service ID.MethodToMethodWithCheckRector(enhanced) Additional patterns matched (statement-level, assignment, fluent-chain) so it covers more configurations found during contrib-wide analysis. DrupalServiceRenameRector(moved + bugfix) Lifted from src/Drupal8/intosrc/Rector/Deprecation/. The previous in-place$nodemutation that broke the BC wrapper fallback is fixed: now clones before mutating, with a regression fixture. The legacyDrupal8\Rector\Deprecation\DrupalServiceRenameRectoris kept as a thin subclass that re-validates the D8 configuration value object.FunctionToFirstArgMethodRector(moved) Lifted from src/Drupal9/intosrc/Rector/Deprecation/. The legacyDrupal9\Rector\Deprecation\FunctionToFirstArgMethodRectoris kept as a thin subclass.FunctionToStaticRector(pre-existing) Unchanged class; new configurations added in D10.3 and D11.{1,2,3,4} configs. ClassConstantToClassConstantRector(pre-existing) Unchanged class (introduced in PR #282); new configurations added in D10.3 ( FileSystemInterface::EXISTS_*→FileExistsenum) and D11.4 (CommentItemInterface::*enums).Tooling and scripts
.claude/skills/rector-discover/SKILL.md: lists unimplemented
drupal-digests rules by implementation phase; regenerates
docs/rector-index.ymlwhen stale..claude/skills/rector-implement/SKILL.md: 14-step canonical conversion
workflow from a digest rule to a finished rector class + test + fixture +
config entry, with type-guard and version-gating quality gates..claude/skills/rector-qa/SKILL.md: five-pass quality review (type
guards, fixture coverage, BC decision correctness,@seeURL accuracy,
registration audit). Supportsallmode for branch-wide scans..claude/skills/rector-live-test/SKILL.md+setup-rector-test.sh:
finds real contrib modules that use the deprecated API a rector targets and
runs the rector against them to validate end-to-end. Uses
search.tresbien.tech as primary source with
GitLab API fallback..claude/scripts/generate-rector-index.php: regenerates
docs/rector-index.ymlfrom the digests source..claude/scripts/setup-repos.sh: clonesrepos/drupal-digestsand
repos/drupal-corefor local development of new rectors.scripts/check-rector-coverage.php: evaluates real-world coverage by
matching shipped rectors against real contrib patches.scripts/generate-deprecation-map.php: extracts@trigger_error
deprecations from Drupal core into a structured YAML map.
Changed
-
ClassConstantToClassConstantRectorandMethodToMethodWithCheckRectornow
extendAbstractDrupalCoreRectorand auto-wrap theirExpr → Exprrewrites
viaDeprecationHelper::backwardsCompatibleCall(). Their configuration value
objects (ClassConstantToClassConstantConfiguration,
MethodToMethodWithCheckConfiguration) gain a requiredintroducedVersion
constructor argument and now implementVersionedConfigurationInterface.
This closes three D11 → D10 runtime regressions (Comment* enums in 11.4,
RequirementSeverityin 11.2,AliasManagermethod rename in 11.1) without
moving anything to a-breaking.phpset. -
MethodToMethodWithCheckRectorno longer attaches a "please confirm the
receiver type" TODO comment for themaybetype-inference case. The
comment-on-parent-statement mechanism relied on parent-node tracking that
Rector 2.x removed; the BC wrap makes both code paths runtime-safe by
selecting the right call based on\Drupal::VERSION, which addresses the
underlying concern. -
Shipped
rector.phpdisables BC wrapping by default. New users get clean
one-version rewrites out of the box. Contrib modules and projects that need to
run on multiple Drupal versions should call->enableBackwardCompatibility()
and optionally->setMinimumCoreVersionSupported(...)on the
DrupalRectorSettingssingleton.The
DrupalRectorSettingsclass default forbackwardCompatibilityEnabled
remainstrue(avoids silently changing behaviour for existing users who do
not call either method on the service); the shippedrector.phpinvokes
disableBackwardCompatibility()explicitly to surface the project-level
recommended default. -
PHPUnit test setup: tests now extend
AbstractDrupalRectorTestCase
instead ofAbstractRectorTestCasedirectly soDrupalRectorSettings
mutations don't leak between tests. -
composer.jsondev-dependency bumps:phpunit/phpunit^10.0→^12.5.24phpstan/phpstan^1.12 || ^2.0→^2.1.54phpstan/phpstan-deprecation-rules^1.2 || ^2.0→^2.0.4friendsofphp/php-cs-fixer^3.58→^3.95.1symplify/vendor-patches^11.0→^12.0.6cweagans/composer-patches^1.7.2→^2.0symfony/yaml^5 || ^6 || ^7→^5 || ^6 || ^7.4.8
-
CI matrix simplified to PHP 8.3 + Rector 2 (previously also tested PHP 8.2
- Rector 1).
-
Drupal stub
VERSIONbumped from10.99.x-devto11.99.x-devso D11
rules fire in tests by default; D11 tests opt out via
DrupalRectorSettings::setDrupalVersion('1.0.0')for below-version cases. -
Composer autoload
exclude-from-classmapentries added for
**/fixture/**,**/fixture-*/**,**/Fixture/**so fixtures don't pollute
consuming projects' class maps.
Removed
- Rector 1 support.
composer.jsonnow requiresrector/rector:^2. Drupal
10 EOL is August 2026; Rector 1 was already EOL upstream. docs/rules_overview.md(1,210 lines, auto-generated). Replaced by
on-demand generation via.claude/scripts/generate-rector-index.php→
docs/rector-index.yml. The composerdocsscript that produced the file
is also removed.- Three single-purpose constant rectors collapsed into
ConstantToClassConstantRectorconfig entries:
ReplaceRequirementSeverityConstantsRector,
ReplaceJsonApiFilterConstantsRector,
ReplaceLocaleTranslationDefaultServerPatternRector.
Fixed
DrupalServiceRenameRectorBC wrapper fallback.refactorWithConfiguration
used to mutate the input$nodein place; the parent'screateBcCallOnExpr
reused that same already-mutated node as the deprecated branch of the
DeprecationHelper::backwardsCompatibleCall(...), so both branches ended
up calling the renamed service and the legacy fallback was silently lost. Now
clones before mutating; a regression fixture exercises the BC wrapping.ReplacePdoFetchConstantsRectornative-PDO receiver guard. The original
matcher rewrotesetFetchMode/fetch*calls on any object whose
argument was\PDO::FETCH_*, which would break native PDO statements. Now
guards the receiver with
isObjectType($node->var, new ObjectType('Drupal\Core\Database\StatementInterface')).NodeStorageDeprecatedMethodsRectormissingcountDefaultLanguageRevisions:
the statement-level REMOVE_NODE case was missing entirely; now covered.ReplaceEntityOriginalPropertyRectornullsafe support: added
NullsafePropertyFetchto the node types and refactor logic so
$entity?->originalis rewritten to$entity?->getOriginal().ReplaceEditorLoadRectorargument count: added an arg-count guard so
editor_load()(no args) andeditor_load($a, $b)(two args) are not
incorrectly transformed.RemoveCacheExpireOverrideRector: handles Time/Tag/None cache plugin
subclasses, FQCN imports, aliased imports, and ignores side-effects in the
method body.- 8 unregistered rectors wired into deprecation configs: eight new D11
rector classes shipped with tests but noconfig/references in earlier
drafts; now all wired into the matchingdrupal-11.X-deprecations.php. AbstractDrupalCoreRector::createBcCallOnExprvisibility: changed from
private to protected so subclasses can call it directly when they have to
build manual BC wraps for non-Expr top-level nodes (e.g.,
ReplacePdoFetchConstantsRector::refactor()'sArrayItembranch).
Compatibility
Dimension Supported PHP ^8.2(CI runs 8.3)Rector ^2only; Rector 1 is droppedDrupal core 8, 9, 10, 11 (10 and 11 are the primary targets; 8 and 9 rules retained for legacy projects) Upgrade notes
Refresh
rector.phpThe shipped
rector.phpwas rewritten to register theDrupalRectorSettings
singleton. Refresh your project's copy:cp vendor/palantirnet/drupal-rector/rector.php .If you have local customisations, merge them by hand. The notable new block is:
$rectorConfig->singleton(DrupalRectorSettings::class, fn () => (new DrupalRectorSettings()) ->disableBackwardCompatibility() );
Contrib modules running against an older minimum Drupal version
If your module must keep running on (e.g.) Drupal 10.5 while the development
environment runs 11.x, enable BC wrapping and tell the settings the minimum core
version you support so the wrappers are emitted correctly:$rectorConfig->singleton(DrupalRectorSettings::class, fn () => (new DrupalRectorSettings()) ->enableBackwardCompatibility() ->setMinimumCoreVersionSupported('10.5.0') );
Cleaning up old BC wrappers
Once you raise your module's minimum supported Drupal version, the existing
DeprecationHelper::backwardsCompatibleCall()wrappers in your code become
redundant. Strip them withDeprecationHelperRemoveRector(commented example in
the shippedrector.php):$rectorConfig->ruleWithConfiguration(DeprecationHelperRemoveRector::class, [ new DeprecationHelperRemoveConfiguration('10.3.0'), ]);
This rewrites every wrapper whose
introducedVersionis below10.3.0back to
the new API call directly.Drupal 8 / 9 legacy rectors
Still included for legacy projects. The classes
Drupal8\Rector\Deprecation\DrupalServiceRenameRectorand
Drupal9\Rector\Deprecation\FunctionToFirstArgMethodRectorare thin subclasses
re-validating their D8/D9 configuration value objects; behaviour is unchanged.Release notes
Open source →Changed
RemoveConfigSaveTrustedDataArgRector— no longer wraps the rewrite in aDeprecationHelper::backwardsCompatibleCall(). The deprecated$has_trusted_dataargument toConfig::save()is only a performance hint (skip re-casting data already typed to its schema); re-casting is idempotent, so dropping the argument is behaviourally equivalent on every Drupal version that shipsConfig::save()and the rector now emits a plain$config->save(). Confirmed with berdir. Code already converted while the rector still emitted a BC wrapper is left untouched — the deprecated call sits in thedeprecatedCallablearm and is skipped by the existingisInBackwardsCompatibleCall()guard.FileSystemBasenameToNativeRector— no longer wraps the replacement in aDeprecationHelper::backwardsCompatibleCall(). PHP's nativebasename()is identical toFileSystemInterface::basename()on every PHP version Drupal 11 supports (the wrapper only worked around a pre-PHP-8.0 bug), so the rewrite is always safe and emits a plainbasename(…)call. Code already converted while the rector still emitted a BC wrapper is left untouched — the deprecated call sits in thedeprecatedCallablearm and is skipped by the existingisInBackwardsCompatibleCall()guard.
- Composer-based sets (
-
1.0.0-beta724 Jun 2026 pre-releaseRelease notes
Open source →Fixed
- Backward-compatible call wrapping — when a deprecation replacement passes a
variable to a by-reference parameter (
template_preprocess_html(&$variables), form*_process/*_validate/*_buildercallbacks with&$form,views_add_contextual_links(&$render_element), …), the generatedDeprecationHelper::backwardsCompatibleCall()now wraps the call in a long closure that captures the variable by reference (function () use (&$var) { … }) instead of an arrow function. Arrow functions capture by value, so a mutation made through the reference was silently dropped — breaking, for example, webform render and form-handling tests. By-reference parameters are detected by reflecting the replacement service method, so the fix is automatic for every affected deprecation. Closures wrapping avoidtarget emit a bare expression statement instead ofreturn <expr>;, avoiding PHPStan'sfunction.void.
- Backward-compatible call wrapping — when a deprecation replacement passes a
variable to a by-reference parameter (
-
1.0.0-beta624 Jun 2026 pre-releaseRelease notes
Open source →What's Changed
- hotfix: MethodToMethodWithCheckRector triggers on
maybeby @bbrala in #396 - docs: prepare 1.0.0-beta6 by @bbrala in #397
Full Changelog: 1.0.0-beta5...1.0.0-beta6
Release notes
Open source →Fixed
MethodToMethodWithCheckRector— only rewrite a call when the receiver type definitely matches the configured class. The guard previously also fired on a maybe match (isSuperTypeOf()returningMAYBE), so a method call on an unrelated class that merely could implement the target interface was rewritten. In webform this turnedWebformThemeManagerInterface::renderPlain()intorenderInIsolation(), which does not exist there and breaks on older Drupal. Requiring a definite (YES) match drops these false positives. (#396)
- hotfix: MethodToMethodWithCheckRector triggers on
-
1.0.0-beta523 Jun 2026 pre-releaseRelease notes
Open source →Fixed
AnnotationToAttributeRector— preserve the positional (keyless) value when converting a plugin annotation to an attribute. Previously a bare positional value such as the id in@FormElement("foo")or@ViewsField("id")was silently dropped, producing#[FormElement]with no constructor argument. The value is now emitted as the attribute's first positional argument, with positional arguments ordered before named ones as PHP requires (e.g.#[FormElement('foo')]and#[FormElement('id', label: ...)]). (#3579141, #3470861)
-
1.0.0-beta422 Jun 2026 pre-release -
1.0.0-beta322 Jun 2026 pre-releaseRelease notes
Open source →What's Changed
- feat: disable BC wrapping by default for composer-based sets by @bbrala in #373
- chore: remove unmatched PHPStan errors by @bbrala in #377
- feat: add ReplaceUserOneTimeAuthFunctionsRector for #3581056 by @bbrala in #363
- feat: add ReplaceLocaleBatchProceduralFunctionsRector for #3581303 by @bbrala in #364
- feat(11.4): add NodeSearch → SearchNode rename to DRUPAL_114_BREAKING (#3587564) by @bbrala in #367
- feat: add UserLoadByNameAndMailRector for #3555936 by @bbrala in #368
- feat: PHPUnit annotations-to-attributes Rector rules (Drupal 12 readiness) [#3552124] by @bbrala in #375
- docs: prepare 1.0.0-beta3 by @bbrala in #378
Full Changelog: 1.0.0-beta2...1.0.0-beta3
Release notes
Open source →Added
PhpUnitTestAnnotationToAttributeRector— converts PHPUnit test-metadata doc-block annotations (@group, with@group legacy → #[IgnoreDeprecations]as a special case) to PHP attributes. Backward-compatible by default: the annotation is kept alongside the new attribute while the configuredremoveVersionhas not been reached (or while BC mode is on), so the rewritten code stays compatible with older PHPUnit/Drupal versions that tolerate unknown attribute classes. ImplementsMinPhpVersionInterface(PHP 8.1+). The already-present check compares the attribute's short name, so it stays idempotent after Rector's name-importing pass reprints the attribute as ause-imported short name (a fully-qualified comparison would miss the imported form and re-append the attribute on every pass). (#3535662, #3417066)PhpUnitAddRunTestsInSeparateProcessesAttributeRector— additively stamps#[RunTestsInSeparateProcesses]onto Kernel and Browser (Functional) test classes; skips Unit tests, anonymous classes, abstract classes, and already-attributed classes. The already-attributed check compares the attribute's short name so the rule stays idempotent across name-importing passes (see Rector A above). Registered in the Drupal 11.4 deprecation set.UserLoadByNameAndMailRector(Drupal 11.4, #3555936) — rewrites the deprecateduser_load_by_name()anduser_load_by_mail()functions (deprecated in drupal:11.4.0, removed in drupal:13.0.0) to the equivalent entity-storage lookup\Drupal::entityTypeManager()->getStorage('user')->loadByProperties([...]). BecauseloadByProperties()returns an array keyed by user ID while the old functions returned a single user object orFALSE, the result is normalised witharray_values(...)[0] ?? FALSEto preserve the original return contract. The replacement uses only long-standing entity APIs and pure PHP, so it runs on every supported Drupal version and is not BC-wrapped.DRUPAL_114_BREAKING:NodeSearch→SearchNodeclass rename.Drupal\node\Plugin\Search\NodeSearchwas moved out of thenodemodule and renamed toDrupal\search_node\Plugin\Search\SearchNodein the newsearch_nodecore sub-module (drupal:11.4.0). Added as aRenameClassRectorentry todrupal-11.4-breaking.php. Unlike theHelpSearchmove, the oldNodeSearchclass is not removed in 11.4 — it survives as a@deprecatedsubclass ofSearchNodeuntil removal in drupal:12.0.0. It is still in the breaking set becauseSearchNodedoes not exist on any Drupal minor below 11.4, and ause/extends/::classrename is structural and cannot be BC-wrapped, so applying it against code that must still run on an older minor would fatal there. Known D11 contrib subclasses affected:trash(TrashNodeSearch) andsearch_exclude(SearchExcludeNodeSearch). Opt in viaDrupal11SetList::DRUPAL_114_BREAKINGonly after dropping support for Drupal < 11.4 (#3587564 / change record).- Locale batch procedural functions (Drupal 11.4, #3581303) —
added
ReplaceLocaleBatchProceduralFunctionsRector, which rewrites the 17 deprecated batch callbacks fromlocale.batch.inc,locale.bulk.inc, andlocale.compare.inc(deprecated in drupal:11.4.0, removed in drupal:13.0.0) to the equivalent methods on theLocaleFetch,LocaleImportBatch,LocaleConfigBatch, andLocaleProjectCheckerservices. BC-wrapped viaDeprecationHelperbecause the new services do not exist on Drupal < 11.4.locale_config_batch_build()andlocale_translation_batch_status_build()are intentionally left for manual migration (changed signature/behavior). ReplaceUserOneTimeAuthFunctionsRector(Drupal 11.4, #3581056) — replaces the deprecated user one-time authentication functionsuser_pass_rehash(),user_pass_reset_url()anduser_cancel_url()(deprecated in drupal:11.4.0, removed in drupal:13.0.0) with the new\Drupal\user\OneTimeAuthenticationservice methodsgenerateHmac(),generateOneTimeLoginUrl()andgenerateCancelConfirmUrl(). BC-wrapped viaDeprecationHelperbecause the service does not exist on Drupal < 11.4. The two URL methods return aUrlobject, so the rewrite chains->toString().user_mail_tokens()(deprecated in the same issue) is intentionally not handled — it is used as a string callback and its replacement needs aBubbleableMetadataargument that cannot be synthesised.
Removed
- Removed
GroupLegacyToIgnoreDeprecationsRector— its@group legacy→#[IgnoreDeprecations]conversion is now handled by the newPhpUnitTestAnnotationToAttributeRector(registered in the Drupal 11.0 set).
Fixed
AnnotationToAttributeRectoris now idempotent across name-importing. Its already-present check compared the existing attribute's fully-qualified name against the configured attribute class. After Rector'simportNames()pass reprints the attribute as a shortuse-imported name (#[Action]) — or the import is dropped across passes and the short name resolves to the current namespace — that comparison missed and a duplicate attribute was appended on every pass, stacking unboundedly. It now compares the short (last) name segment, which is stable regardless of import state.
Changed
- Composer-based sets now disable backward-compatibility wrapping by default.
Composer-based selection pins the rules to the exact installed Drupal version
and only loads sets for deprecations live on it, so the rewritten code only ever
runs against that one version — there is no older minor to stay compatible with,
which makes the
DeprecationHelperBC wrappers pure noise. TheDrupalRectorSettingssingleton is now registered with BC disabled inconfig/drupal-bootstrap.php(the set matched once per Drupal major byDrupalSetProvider). A project that does need the wrappers can re-register the singleton in its ownrector.php. (Still inert until a Rector release ships the composer-based set support — see beta2.)
-
1.0.0-beta218 Jun 2026 pre-releaseRelease notes
Open source →Added
- Infrastructure for composer-based sets (rectorphp/rector#9778) —
ships
DrupalRector\Set\DrupalSetProvider, which will let Rector pick the Drupal deprecation sets automatically from the installeddrupal/coreversion. This is groundwork only: it is inert until a Rector release ships theSetGroup::DRUPALgroup and thewithComposerBased(drupal: ...)toggle, which has not landed yet.
Changed
RemoveFilterTipsLongParamRectormoved from the default deprecation set into the opt-inDRUPAL_114_BREAKINGset (#371). Removing$longfrom atips()override is non-BC:FilterInterfaceandFilterBasestill declaretips($long = FALSE)on every Drupal minor below 11.4, and PHP rejects a child that drops a parameter the parent declares with a fatal at class-declaration time (Declaration of …::tips() must be compatible with …FilterInterface::tips($long = false)). In beta1 the rule ran in the default set and so fired against contrib still supporting Drupal < 11.4, producing a signature-mismatch fatal there. It now only runs once the consumer's minimum supported Drupal is ≥ 11.4; it must not block Drupal 12 compatibility (on Drupal 12 the parent no longer declares$long, so an un-rewritten subclass keeps a harmless extra optional param — phpstan grumbles but it runs). Surfaced by a rejected non-BC change totoken_filter(#3603786).
- Infrastructure for composer-based sets (rectorphp/rector#9778) —
ships
-
1.0.0-beta111 Jun 2026 pre-releaseRelease notes
Open source →Added
-
template_preprocess_*()family (Drupal 11.3, #3504125) — extendedFunctionToServiceRectorcoverage with 14 moretemplate_preprocess_*()functions deprecated in drupal:11.3.0 and removed in drupal:12.0.0. Each is rewritten (BC-wrapped viaDeprecationHelper) to the equivalent*Preprocessservice method:table,tablesort_indicator,item_list,region,maintenance_page,maintenance_task_list,install_page→ThemePreprocess;image→ImagePreprocess;breadcrumb→BreadcrumbPreprocess;pager→PagerPreprocess;field,field_multiple_value_form→FieldPreprocess;menu_local_task,menu_local_action→MenuPreprocess. (template_preprocess_authorize_report()has no replacement and is intentionally excluded.) -
RemoveSourceModuleFromMigrateSourceAttributeRector— removes thesource_modulenamed argument from#[MigrateSource]attribute usages. Only theDrupal\migrate\Attribute\MigrateSourceattribute is targeted (an attribute of the same short name from another namespace is left untouched). Thesource_moduleconstructor parameter was removed from the attribute in drupal:11.2.0; passing#[MigrateSource(source_module: '...')]now raises an "Unknown named parameter" error at plugin discovery time. The rewrite cannot be BC-wrapped (an attribute is not anExpr → Exprtransformation) and the argument is mutually exclusive across minors, so the rule lives in the opt-inDrupal11SetList::DRUPAL_112_BREAKINGset, not the default deprecation set. For plugins extendingDrupalSqlBasethesource_modulevalue must be re-declared via the@MigrateSourceannotation or the migration YAML after removal — a manual follow-up this rule does not automate. Apply only after dropping support for Drupal minors that predate 11.2.0. #3009349 / change record -
UploadedFileConstraintArrayOptionsToNamedArgsRector— replaces the deprecated options-array argument ofUploadedFileConstraintwith explicit named constructor arguments (e.g.new UploadedFileConstraint(['maxSize' => 1024000])→new UploadedFileConstraint(maxSize: 1024000)). Passing an options array is deprecated in drupal:11.4.0 and removed in drupal:12.0.0. The transformation is BC-wrapped: the named-argument constructor was introduced alongside the deprecation, so the new form would fatal (Unknown named parameter) on Drupal < 11.4. The rector therefore wraps thenewexpression inDeprecationHelper::backwardsCompatibleCall(), using named arguments on Drupal ≥ 11.4 and the original options array on older versions. See #3561135 and the change record. -
DRUPAL_114_BREAKING:HelpSearch→SearchHelpSearchclass rename.Drupal\help\Plugin\Search\HelpSearchwas moved out of thehelpmodule and renamed toDrupal\search_help\Plugin\Search\SearchHelpSearchin the newsearch_helpcore sub-module (system_update_11400(), drupal:11.4.0). Added as aRenameClassRectorentry todrupal-11.4-breaking.php: theSearchHelpSearchclass does not exist on any Drupal minor below 11.4, and ause/::classrename is structural and cannot be BC-wrapped, so applying it against code that still needs to run on an older minor would fatal there. Opt in viaDrupal11SetList::DRUPAL_114_BREAKINGonly after dropping support for Drupal < 11.4 (#3581109). -
CommentLinkBuilderConstructorRector— rewrites the deprecated 5-argumentnew \Drupal\comment\CommentLinkBuilder(...)constructor call to the new 3-argument form, dropping the$module_handlerand$entity_type_managerarguments (deprecated in drupal:11.3.0, removed in drupal:12.0.0). Because the 3-argument signature only exists on Drupal >= 11.3.0, the rewrite is BC-wrapped withDeprecationHelper::backwardsCompatibleCall()so the original 5-argument call still runs on older Drupal. Only calls with exactly 5 positional arguments are rewritten. -
ReplaceItemAttributesWithAttributesRector— replaces the deprecated#item_attributeskey with#attributesin render arrays whose#themeisimage_formatterorresponsive_image_formatter. The#item_attributesproperty is deprecated in drupal:11.4.0 and removed in drupal:12.0.0. The transformation is BC-wrapped: the#attributesvariable was only added to these theme hooks in 11.4.0, so a plain rename would silently drop the attributes on Drupal < 11.4. The rector therefore wraps the array literal inDeprecationHelper::backwardsCompatibleCall(), using#attributeson Drupal ≥ 11.4 and the original#item_attributeson older versions. Arrays with an unrelated (or absent)#theme, and arrays already using#attributes, are left untouched. #3554447 / CR. -
HookRequirementsAlterRenameRector— renames procedural{module}_requirements_alter()hook implementations to{module}_runtime_requirements_alter(), deprecated in drupal:11.3.0 and removed in drupal:13.0.0. The runtime hook is only invoked on Drupal minors where it exists, so the renamed function is a silent no-op on older Drupal; this is a non-BC rewrite and ships in the opt-inDRUPAL_113_BREAKINGset, not the default deprecation set. The rule only renames functions with a single by-reference parameter, skips thehook_requirements_alter()API-doc function, and is idempotent — the_runtime_/_update_requirements_alter()hooks are left untouched. -
ReplaceDrupalStaticResetFileReferencesRector— rewritesdrupal_static_reset('file_get_file_references')anddrupal_static_reset('file_get_file_references:field_columns')to\Drupal::service('cache.memory')->invalidateTags(['file_references']). Both static-cache keys were deprecated in drupal:11.4.0 (removed in drupal:13.0.0) when the file-reference lookup moved to the newFileReferenceResolverservice, which uses thefile_referencesmemory-cache tag instead ofdrupal_static(). Only those two literal keys are matched; otherdrupal_static_reset()calls, calls tofile_get_file_references()itself, and named/unpacked argument forms are intentionally left for manual review. BC-wrapped viaDeprecationHelper: thefile_referencescache tag does not exist before drupal:11.4.0, so the new call would be a silent no-op there — the wrapper keeps the originaldrupal_static_reset()on older versions and only switches to thecache.memoryinvalidation on drupal:11.4.0 and above. -
ReplaceNodeViewControllerRector(+ a companionRenameClassRectorentry) — migrates the deprecatedDrupal\node\Controller\NodeViewControllertoDrupal\Core\Entity\Controller\EntityViewController(deprecated in drupal:11.4.0, removed in drupal:13.0.0). The custom rector rewritesnew NodeViewController($etm, $renderer, $currentUser, $entityRepository)tonew EntityViewController($etm, $renderer), dropping the two extra constructor arguments thatEntityViewControllerdoes not accept; it matches both the old and new class names so the argument trim is order-independent w.r.t. the rename pass. TheRenameClassRectorentry handles the structural references (use/extends/::class/ type hints). Ships in the opt-inDRUPAL_114_BREAKINGset: unlike the other entries there, the replacement class exists on every supported minor (so it never fatals on a missing symbol), but reparentingextends NodeViewControllertoextends EntityViewControlleris behaviorally breaking on every minor — subclasses lose the node-specificcreate()/currentUser/entityRepository/title()/view()members and can throw anArgumentCountErroror call an undefinedtitle(), so it needs manual review. A subclass's ownparent::__construct($a, $b, $c, $d)is not rewritten (PHP silently discards the extra arguments). #3589630 / CR. -
RenameHookRankingRector— renames the deprecated OOP hook attribute#[Hook('ranking')]to#[Hook('node_search_ranking')]. Only theDrupal\Core\Hook\Attribute\Hookattribute is targeted (an attribute of the same short name from another namespace is left untouched), and only the'ranking'argument is rewritten — the implementing method name and any docblocks are unchanged.hook_ranking()is deprecated in drupal:11.3.0 and removed in drupal:12.0.0; usehook_node_search_ranking()instead. Because thenode_search_rankinghook is only invoked on Drupal minors where it exists, a plain rename is a silent no-op on older Drupal, and an attribute is not anExpr → Exprtransformation so it cannot be BC-wrapped. The rule therefore lives in the opt-inDrupal11SetList::DRUPAL_113_BREAKINGset, not the default deprecation set. #1019966 / change record -
BlockContentSelectionExtendsRector— reparents entity reference selection plugins for theblock_contententity type fromDrupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelectiontoDrupal\block_content\Plugin\EntityReferenceSelection\BlockContentSelection. The hook that automatically filtered non-reusable blocks out of those selections (block_content_query_entity_reference_alter()) is deprecated and removed in drupal:12.0.0;BlockContentSelectionperforms that filtering itself. The rewrite is gated on theEntityReferenceSelectionattribute carryingentity_types: ["block_content"], soDefaultSelectionsubclasses for other entity types are left untouched, and the canonical coreBlockContentSelectionis skipped so it is not made to extend itself. Ships in the opt-inDRUPAL_114_BREAKINGset:BlockContentSelectionwas added to core alongside the deprecation (a new class, so 11.4.0) and does not exist on any minor below 11.4, so reparenting onto it would fatal there, and aclass … extends …declaration cannot be BC-wrapped. #2987159 / CR. -
RemoveFilterTipsLongParamRector— drops the deprecated$longparameter from a filter plugin'stips()override and the second argument from_filter_tips()calls. The$longparameter and the long-format "filter tips" page are deprecated in drupal:11.4.0 and removed in drupal:12.0.0. (Reclassified into the opt-in breaking set in 1.0.0-beta2 — see below.) #3505370 / CR. -
RemoveRouteBuilderDeprecatedArgsRector— rewrites the deprecated 6-argumentnew \Drupal\Core\Routing\RouteBuilder(...)instantiation to the new 4-argument form (deprecated in drupal:11.4.0, removed in drupal:12.0.0). The$module_handler(arg 3) and$controller_resolver(arg 4) arguments were removed and$check_providershifted from position 5 to position 3; YAML route discovery moved to the newYamlRouteDiscoveryservice. Only 6-argument positional calls toRouteBuilderare matched; the new signature only exists on Drupal ≥ 11.4, so the change is BC-wrapped viaDeprecationHelper::backwardsCompatibleCall(). -
RemoveDrupalToStringTraitRector— removesuse Drupal\Component\Utility\ToStringTrait;from a class body and inserts an inlinepublic function __toString(): string { return (string) $this->render(); }in its place. The trait was a PHP 7.x workaround for fatal errors thrown from__toString(); on PHP 8+ exceptions inside__toString()propagate normally, so the trait is deprecated in drupal:11.4.0 and removed in drupal:13.0.0. The rector preserves an existing__toString()if the class already defines one (only the composition is removed) and keeps any sibling traits in a comma-separateduselist. The file-leveluse Drupal\Component\Utility\ToStringTrait;import is intentionally left in place — Rector's generic unused-import cleanup is a separate concern. The replacement body is pure PHP, so the transformed code runs on every Drupal version — no BC wrapping needed. #3548957 / CR. -
RemoveInstallSchemaSystemSequencesRector— removes deprecatedKernelTestBase::installSchema('system', 'sequences')calls in test classes. Thesequencestable was deprecated in drupal:10.2.0 and fully removed in drupal:12.0.0 via #3335756; the call now throws aLogicExceptionon Drupal 12. The rule removes the entire statement when the second argument is the string'sequences'or an array containing only'sequences'; when the array also lists other tables, only the'sequences'entry is stripped. Receiver is type-guarded toDrupal\KernelTests\KernelTestBase, so unrelatedinstallSchema()methods on other classes are left untouched. See change record #3349345. -
GroupLegacyToIgnoreDeprecationsRector— replaces the@group legacyPHPDoc annotation with PHPUnit 10's native#[\PHPUnit\Framework\Attributes\IgnoreDeprecations]attribute on both method- and class-level test declarations. Drupal 11 dropped thesymfony/phpunit-bridgedependency and adopted PHPUnit 10, whose attribute supersedes the bridge's docblock annotation. A Drupal shim preserves the annotation form for BC, so the rewrite is purely a forward-compatibility cleanup rather than a hard requirement, but test classes that already declare the attribute are skipped so the rule is idempotent. The rector strips just the@group legacyline from the docblock — surrounding annotations (@covers,@dataProvider, description text) are preserved — and inserts the attribute immediately above the method or class declaration. PHPStan cannot surface this deprecation because@group legacyis a docblock convention, not a code-level@deprecatedsymbol; this rule must be applied proactively as part of a PHPUnit 10 migration. #3417066 / related: #3365413. -
RemoveAliasManagerCacheMethodCallsRector— deletes calls toAliasManager::setCacheKey()andAliasManager::writeCache(). Both methods were deprecated in drupal:11.3.0 and are removed in drupal:13.0.0 with no replacement — they became no-ops when the path alias preload cache was replaced by a Fiber-based bulk-lookup strategy. The receiver must be typed as\Drupal\path_alias\AliasManagerorAliasManagerInterface; this guard prevents accidentally removing unrelated methods that share the name (notablyModuleHandler::writeCache()). Removes the entire expression statement, leaving surrounding code intact. No BC wrapping is needed since dropping a no-op call is safe on every Drupal version. #3496369 / CR. -
EntityFormModeEmptyDescriptionToNullRector— rewritesEntityFormMode::create([..., 'description' => '', ...])to useNULLinstead of the empty string. Setting the description property of anEntityFormModeto''was deprecated in drupal:11.2.0 and must beNULLin drupal:12.0.0. Matches both the short class name (use-imported) and the fully-qualified\Drupal\Core\Entity\Entity\EntityFormMode::create()form, and leaves unrelated classes (e.g.EntityViewMode), non-empty descriptions, and already-migrated NULL values untouched. The replacement is plain PHP, so no BC wrapping is needed. #3448457 / CR. -
ViewsBlockItemsPerPageNoneToNullRector— rewritesViewsBlockBase::setConfigurationValue('items_per_page', 'none')tosetConfigurationValue('items_per_page', NULL). The string'none'was deprecated in drupal:11.2.0 and is removed in drupal:12.0.0;NULLis the canonical value for inheriting the items-per-page setting from the underlying view. The receiver is type-guarded toViewsBlockBase(or any subclass), so unrelatedsetConfigurationValue()calls on other plugin types are left untouched. The replacement is plain PHP, so no BC wrapping is needed. #3520946 / CR. -
TaxonomyTermPageVariableToViewModeRector— replaces reads of$variables['page']with$variables['view_mode'] === 'full'inside taxonomy term preprocess hooks (procedural*_preprocess_taxonomy_term()functions and class-basedpreprocessTaxonomyTerm()methods). The$variables['page']template variable for taxonomy terms was deprecated in drupal:11.3.0 and is removed in drupal:13.0.0. Assignment targets ($variables['page'] = …) are intentionally left untouched so legacy initialisation continues to work, and unrelated preprocess hooks are not scanned. The replacement is a pure-PHP===comparison, so the transformed code runs on every Drupal version — no BC wrapping needed. #3535439 / CR. -
ReplaceNonBoolAccessRector— rewrites integer-literal#accessvalues inside render arrays to proper booleans:1(or any non-zero integer) becomestrue, and0becomesfalse. Passing non-boolean, non-AccessResultInterfacevalues to#accesswas deprecated in drupal:11.4.0 and will be removed in drupal:13.0.0. The rule matches onArrayItemnodes whose key is the string literal'#access'and whose value is an integer literal — it deliberately ignores booleans, variables, function/method calls, and any other expression, because the correct boolean replacement for those cannot be determined statically. The replacement is pure PHP (true/false), so no BC wrapping is needed; the transformed code runs on every Drupal version. #3526250. -
ReplaceDialogClassOptionRector— rewrites the removed$dialog_options['dialogClass']key to$dialog_options['classes']['ui-dialog']innew OpenDialogCommand(...),new OpenModalDialogCommand(...), andnew OpenOffCanvasDialogCommand(...)calls.dialogClasswas deprecated in drupal:11.3.0 and removed in drupal:12.0.0. Receiver narrowing is by FQCN match on the resolvedNew_->class(Drupal\Core\Ajax\OpenDialogCommand,Drupal\Core\Ajax\OpenModalDialogCommand, orDrupal\Core\Ajax\OpenOffCanvasDialogCommand), and the$dialog_optionsargument is located per-class (4th argument forOpenDialogCommand, 3rd for the modal/off-canvas commands), so unrelated constructors with similarly-shaped option arrays are left alone. Handles three array shapes: (a) no existingclasseskey → adds'classes' => ['ui-dialog' => $value]; (b)classesexists withoutui-dialog→ adds'ui-dialog' => $valueinside it; (c)classes['ui-dialog']already present and both old/new values are string literals → concatenates with a space. Non-literal values (variables, function calls, dynamic arrays) at any position cause the rule to skip rather than guess. The replacement formclasses['ui-dialog']has existed in core since 10.3.x, so the transformed output runs on every drupal-rector–supported Drupal minor (D10.3+) — no BC wrapping needed. #3571054 / CR. -
RemoveToolkitArgFromImageToolkitOperationConstructorRector— removes the deprecatedImageToolkitInterface $toolkit4th argument fromImageToolkitOperationBasesubclass constructors and strips it from the matchingparent::__construct()call. The parameter was deprecated in drupal:11.4.0 and will be removed in drupal:13.0.0; the plugin manager now injects the toolkit viasetToolkit()after instantiation, enabling constructor autowiring. The rector only fires when the subclass directly extendsImageToolkitOperationBase, the constructor has at least five parameters, the 4th is typed exactly as\Drupal\Core\ImageToolkit\ImageToolkitInterface, and$toolkitappears exactly once in the constructor body (as the 4th argument ofparent::__construct()). The usage-count walk skips nested closures and arrow-functions so a$toolkit-shadowing inner scope cannot inflate the count. No BC wrapping is needed: the parent signature accepts the unionLoggerInterface|ImageToolkitInterface, so the transformed code runs on every drupal:11.4.x+ version. #3559481 / CR. -
RemoveRendererAddCacheableDependencyNonObjectRector— deletes calls toRendererInterface::addCacheableDependency($elements, $dependency)whose second argument is statically provable to be a non-object (bool,int,float,string,null, orarray). Passing such values was deprecated in drupal:11.3.0 and will throw in drupal:13.0.0; at runtime it silently setsmax-age = 0on the render array, making the page uncacheable for no useful gain. The rector matches at statement level so the entire expression is removed, never partially rewritten. The receiver is type-guarded to\Drupal\Core\Render\RendererInterface(catching the concreteRendererand any other implementer), and the argument count must be exactly two — this distinguishes the call from the single-argumentaddCacheableDependency()defined onBubbleableMetadataandRefinableCacheableDependencyInterface. The PHPStan type of the dependency must satisfyisObject()->no(), so any call where the argument might be an object at runtime (variables typed as configs, entities, ormixed) is left untouched — the rector targets only the unambiguous primitive-passing mistake the deprecation was added to flag. No BC wrapping is needed because the removed call is a silent uncacheability bug on every Drupal version. #3525388 / CR. -
DrupalGetHeadersAssocArrayRector— converts the two deprecatedUiHelperTrait::drupalGet()$headersargument shapes to the documented associative format: integer-keyed colon-separated strings (['X-Requested-With: XMLHttpRequest']) are split to['X-Requested-With' => 'XMLHttpRequest'], andnullvalues (['Accept-Language' => NULL]) become empty strings (['Accept-Language' => '']). The integer-keyed path requires the conventionalName: value(colon-space) form and a name part matching[A-Za-z][A-Za-z0-9-]*, so incidental colon-containing strings (URLs, paths) are not silently split. Guarded againstDrupal\Tests\BrowserTestBasesoKernelTestBase(which usesHttpKernelUiHelperTraitand does not emit this deprecation) is left alone. Deprecated in drupal:11.1.0, removed in drupal:12.0.0; replacement is plain PHP so no BC wrapping is needed. Live-tested againstpager_serializer. #3440169 / CR (indexed headers) / CR (null values). -
ReplaceHideShowWithPrintedRector— replaces statement-level calls to the deprecated globalhide()andshow()functions (deprecated in drupal:11.4.0, removed in drupal:13.0.0) with direct$element['#printed'] = TRUE/FALSEassignment. Expression-context uses (where the return value is captured) are intentionally skipped because the original returns the element while the rewrite would not. Live-tested againstfpa,saml_sp,vertical_tabs_config, andfield_group_background_image. #2258355 / CR. -
GetDrupalRootToRootPropertyRector— rewrites calls toDrupalKernelInterface::getDrupalRoot()to direct access of the$this->rootproperty on Drupal base test classes (BrowserTestBase, KernelTestBase, UnitTestCase).getDrupalRoot()was deprecated in drupal:11.4.0 and removed in drupal:13.0.0. The receiver is type-guarded to the listed base classes (and their subclasses), so unrelatedgetDrupalRoot()methods on other classes are left alone. No BC wrapping is needed — the$rootproperty has existed on the trait since Drupal 10.x. #3589047 / CR. -
ReplaceLocaleTranslationPathConfigRector— rewrites chained\Drupal::config('locale.settings')->get('translation.path')(and equivalents viaconfigFactory()->get('locale.settings')->get(...),$this->config('locale.settings')->get(...), and similar) to\Drupal\Core\Site\Settings::get('locale_translation_path', 'public://translations'). Thelocale.settings:translation.pathconfig key was deprecated in drupal:11.4.0 and is removed in drupal:13.0.0; the interface translations directory path must now be set as$settings['locale_translation_path']insettings.php. On older Drupal the value still lives in config, so the replacement is BC-wrapped withDeprecationHelper::backwardsCompatibleCall(). Matching is purely structural — two literal keys ('locale.settings'and'translation.path') must both appear in the expected positions, so unrelated config reads and standalone$config->get('translation.path')calls are left untouched. Caveat: the BC wrapper gates on\Drupal::VERSION, not on where the value is stored. Before running this rule, confirm that any customised translation path has been moved to$settings['locale_translation_path']insettings.php; otherwise the new branch silently returns the default'public://translations'even when the config still holds the customised value. PHPStan / upgrade_status cannot detect this deprecation — the deprecated symbol is the config key, not a PHP API with@deprecatedortrigger_error(), so this rule must be applied proactively as part of an 11.4 → 13 migration plan. #3571593 / CR. -
ViewsConfigUpdaterClassResolverToServiceRector— rewrites\Drupal::classResolver(\Drupal\views\ViewsConfigUpdater::class)to\Drupal::service(\Drupal\views\ViewsConfigUpdater::class). In drupal:11.3.0ViewsConfigUpdaterwas registered as a service;classResolver()returns a fresh instance on each call, so state set viasetDeprecationsEnabled(FALSE)was lost across hook invocations. The new call only resolves on Drupal ≥ 11.3.0 (the service isn't registered on older versions), so the replacement is BC-wrapped withDeprecationHelper::backwardsCompatibleCall(). Three layered guards ensure only the targeted call shape is touched: receiver must be\Drupal, method must beclassResolver, and the single argument must be\Drupal\views\ViewsConfigUpdater::class. #3529274 / CR. -
ReplaceExpectDeprecationRector— migrates removed test framework methods to their PHPUnit 11+ replacements. Renames are BC-wrapped withDeprecationHelper::backwardsCompatibleCall()so tests keep passing on both pre-11.4 (old methods) and 11.4+ (new methods). Covers:$this->expectDeprecation($msg)and$this->expectDeprecationMessage($msg)→$this->expectUserDeprecationMessage($msg);$this->expectDeprecationMessageMatches($p)→$this->expectUserDeprecationMessageMatches($p); bare$this->expectDeprecation()(no-arg PHPUnit form) → removed.ExpectDeprecationTraitis deprecated in drupal:11.4.0 and removed in drupal:12.0.0. #3550268 / CR. -
ReplaceCommentPreviewConstantsRector— rewrites the legacyDRUPAL_DISABLED/DRUPAL_OPTIONAL/DRUPAL_REQUIREDconstant arguments toCommentTestBase::setCommentPreview()to the correspondingDrupal\comment\CommentPreviewModeenum case. Only these named constants are matched (ConstFetchnodes) — a bare integer literal such assetCommentPreview(0)is left untouched. Passing the constants was deprecated in drupal:11.3.0 and is removed in drupal:13.0.0. BC-wrapped viaDeprecationHelper::backwardsCompatibleCall()so the rewrite still runs on pre-11.3 Drupal where the enum doesn't yet exist. #3538660 / CR. -
RemovePhpUnitCompatibilityTraitRector— removesuse Drupal\Tests\PhpUnitCompatibilityTrait;from test class declarations. The trait was a forward-compatibility shim for PHPUnit API differences across versions; it is deleted from Drupal core in Drupal 12 via #3582118, at which point any test class still composing the trait fatal-errors at autoload time because the trait class no longer exists.Gated to Drupal 12 only — and deliberately off by default. The trait still exists on Drupal 10 (and may still hold shim methods that tests depend on) and is an empty no-op on Drupal 11. Because the trait composition is a structural
Class_change, not an Expr → Expr rewrite, it cannot be BC-wrapped withDeprecationHelper. Running the rule prematurely on a D10-only codebase risks silently stripping a composition that the tests still rely on. It is registered in the defaultdrupal-11.4-deprecations.phpset but gated withDrupalIntroducedVersionConfiguration('12.0.0'), so it never fires unless the consumer explicitly sets the target Drupal version to12.0.0or higher viaDrupalRectorSettings::setDrupalVersion('12.0.0'). The orphan top-of-fileuse Drupal\Tests\PhpUnitCompatibilityTrait;import is left in place — PHP never resolves an unused alias, so it remains harmless on D12; cleanup is optional and out of scope. #3582118. -
New opt-in "breaking" sets, one per Drupal 11 minor:
Drupal11SetList::DRUPAL_111_BREAKING,DRUPAL_112_BREAKING,DRUPAL_113_BREAKING,DRUPAL_114_BREAKING. Each is loaded fromconfig/drupal-11/drupal-11.X-breaking.php. Rules in these sets rewrite code into a form that does NOT run on every drupal-rector-supported minor — typically because the replacement symbol was introduced together with the deprecation and does not exist on older minors, and the rewrite (class rename, trait composition, etc.) is structural and cannot be BC-wrapped. None of the breaking sets is included inDRUPAL_11XorDRUPAL_11; consumers must load each one explicitly after committing to drop the older minor(s) named in that file's docblock. -
Reclassified existing
RenameClassRectorentries as breaking, moved out of the defaultdrupal-11.X-deprecations.phpfiles and into the new per-minor breaking sets. Targets verified missing on Drupal 10.6.x:DRUPAL_111_BREAKING:path_alias\AliasWhitelist[Interface]→path_alias\AliasPrefixList[Interface](#3151086 / CR).DRUPAL_112_BREAKING:Core\Entity\Query\Sql\pgsql\{QueryFactory,Condition}→pgsql\EntityQuery\*(#3488572 / CR);migrate_drupal\Plugin\migrate\source\{ContentEntity,ContentEntityDeriver}→migrate\Plugin\migrate\source\*(#3498915 / CR).DRUPAL_113_BREAKING:workspaces\WorkspaceAssociation[Interface]→workspaces\WorkspaceTracker[Interface](#3551446 / CR); the fourblock_content\Access\*aliases (AccessGroupAnd,DependentAccessInterface,RefinableDependentAccessInterface,RefinableDependentAccessTrait) → their canonicalCore\Access\*homes. The canonical classes were introduced in drupal:11.3.0 (not earlier) and do not exist on any Drupal 10 branch, andRenameClassRectorrewrites structuraluse/extends/implements/::classnodes that cannot be BC-wrapped, so the rewrite fatals on Drupal 10 (#3571874 / CR).DRUPAL_114_BREAKING:menu_link_content\Plugin\migrate\process\{LinkOptions,LinkUri}→migrate\Plugin\migrate\process\*(#3560075 / CR).
-
Dropped: the planned
Drupal\jsonapi\EventSubscriber\ResourceResponseValidator→Drupal\jsonapi_response_validator\…rename (#3472008) is not shipped in any set. The replacement lives incore/modules/jsonapi/tests/modules/, i.e. a core test module that production code cannot rely on being loaded; rewriting the production FQCN to that test-module FQCN would fatal on D10 AND on any production D11 site that does not enable that test module. -
Class-rename entry for
LibraryDiscovery:Drupal\Core\Asset\LibraryDiscovery→Drupal\Core\Asset\LibraryDiscoveryInterface. The concrete class was deprecated in drupal:11.1.0 and removed in drupal:12.0.0; thelibrary.discoveryservice is now backed byLibraryDiscoveryCollector, so consumer code should type-hint the interface. Registered via Rector's built-inRenameClassRectorindrupal-11.1-deprecations.php.LibraryDiscoveryInterfacehas existed since Drupal 10.0.x, so the rewrite is safe across all supported Drupal 10 and 11 minors. #3462871 (deprecation) / #3571057 (removal) / CR. -
Class-rename entry for
EntityPermissionsRouteProviderWithCheck:Drupal\user\Entity\EntityPermissionsRouteProviderWithCheck→Drupal\user\Entity\EntityPermissionsRouteProvider. TheWithCheckvariant was deprecated in drupal:11.1.0 and removed in drupal:12.0.0; the base provider has existed since Drupal 10.0.x, so the rewrite is safe across all supported Drupal 10 and 11 minors. Registered via Rector's built-inRenameClassRectorindrupal-11.1-deprecations.php. Access-check semantics: theWithCheckvariant layered a_custom_accessrequirement (EntityPermissionsForm::access, also removed) on top of the base route to deny access when an entity type had no entity-specific permissions; the base provider already enforces_permission: administer permissions, so the security boundary is preserved and only the "no permissions defined → deny" convenience check is dropped. Subclass overrides that re-added the custom check are NOT rewritten —RenameClassRectoronly updates the parent class reference, so owners of such subclasses must port any remaining access logic into the route definition (the new model adds permission requirements directly on the route). Limitation — doctrine annotation strings are not rewritten. Real-world contrib usage is almost exclusively the entity-annotation form ("permissions" = "Drupal\user\Entity\EntityPermissionsRouteProviderWithCheck"inside a@ContentEntityType/@ConfigEntityTypedocblock).RenameClassRectoronly touches PHPNamenodes (use,extends,implements,::class, typehints,instanceof) — it does not scan string literals inside doctrine annotations. Audited against Drupal contrib (api.tresbien.tech, 2026-05-27): three modules reference the class — all via the annotation form — and zero contrib modules use it in PHP code. Owners of those modules must hand-edit the annotation string; this rector is a safety net foruse/extendspatterns and for entity types that switch to PHP-attribute syntax. #3573870 / CR.
Changed
-
Migration note for existing consumers of
Drupal11SetList::DRUPAL_111/DRUPAL_112/DRUPAL_113: the class-rename entries listed above have been moved out of the per-minorDRUPAL_11Xaggregates into new opt-in*_BREAKINGsets. If you currently rely on rector rewriting any of these symbols, add the matching*_BREAKINGset to your rector config alongside your existingDRUPAL_11Xinclude — otherwise the rewrites silently stop:DRUPAL_111:AliasWhitelist[Interface]→AliasPrefixList[Interface]now requiresDRUPAL_111_BREAKING.DRUPAL_112:Core\Entity\Query\Sql\pgsql\{QueryFactory,Condition}→pgsql\EntityQuery\*and themigrate_drupal→migratesource-plugin moves now requireDRUPAL_112_BREAKING.DRUPAL_113:WorkspaceAssociation[Interface]→WorkspaceTracker[Interface]now requiresDRUPAL_113_BREAKING.
The breaking sets are not transitively included by
DRUPAL_11XorDRUPAL_11; consumers must load each one explicitly after committing to drop the older minor(s) named in that file's docblock. -
Guide: Running against a Drupal 10 project — covers the direct install and a standalone-runner recipe for sites whose PHPStan 1 tooling conflicts with Rector 2's PHPStan 2 requirement.
-
HookConvertRectornow produces lint-clean hook classes:- Methods whose body never references
$thisare declaredstatic(satisfies thecanvas.requireStaticMethods/ "method does not use$thisand should be declared static" check). The body originates from a procedural function, so this is safe by construction. - Global
t()calls are rewritten to$this->t()and the generated class gainsuse Drupal\Core\StringTranslation\StringTranslationTrait;(clears theDrupalPractice.Objects.GlobalFunction.GlobalFunctionwarning). Because$this->t()introduces$this, those methods correctly remain non-static — the two rules compose rather than conflict.
- Methods whose body never references
Fixed
-
ReplaceEntityOriginalPropertyRectornow handlesisset()andunset()correctly instead of producing a parse-time fatal. Those constructs accept only a variable, so blindly rewriting$entity->originalto the$entity->getOriginal()method call (e.g.isset($entity->getOriginal())) was invalid PHP. MirroringEntityBase's magic methods:isset($entity->original)→$entity->getOriginal() !== NULL(__isset()returnsgetOriginal()), BC-wrapped inDeprecationHelper.unset($entity->original)→$entity->setOriginal(NULL)(__unset()callssetOriginal(NULL)), BC-wrapped with$entity->original = NULLas the pre-11.2 path. In a multi-operandunset(), only the->originaloperand is rewritten; the rest stay in a residualunset().
Only the direct/outermost operand is fatal as a method call, so nested fetches are rewritten normally:
isset($entity->original->field)→isset($entity->getOriginal()->field)and likewise forunset()(both parse fine — only a bare method call as the outermost operand is fatal). A fetch used as an array key, e.g.isset($map[$entity->original]), andempty()(which accepts arbitrary expressions) are also rewritten. The only form left untouched is the direct operand of a multi-operandisset()—isset($entity->original, $other)— where rewriting->originalwould produce the fatalisset($entity->getOriginal(), $other). -
Loading the Drupal 9 and Drupal 11 sets together no longer crashes at container-build time. The Drupal 9
FunctionToFirstArgMethodRector(and the Drupal 8DrupalServiceRenameRector) subclass the generic rule, so Rector delivered the generic rule's configuration to the subclass instance as well (afterResolvingcallbacks match byinstanceof); the subclass' strict type guard then threw. The subclasses now ignore configuration that is not their own. This unblocks running the full, bundled rule set — including the D10-era deprecations that live in the Drupal 11 set — against Drupal 10 sites.
-
-
1.0.0-alpha101 Jun 2026 pre-releaseRelease notes
Open source →Changed
This will be the first alpha of the 1.0 line. Adds full Drupal 11 deprecation coverage (versions 11.0 through 11.4), a new container-managed settings service that gives users explicit control over backward-compatibility wrapping, a documented set of Claude Code skills for building further rectors, and drops support for Rector 1.
Real-world validated end-to-end:
- Applied to Drupal Canvas on the
canvas-3589155branch — the full Canvas test suite passed (pipeline 825601). - Run across the whole of Drupal contrib via
project_analysis — code
branch
master-next, generated patches underresults-next. Spot-checking those patches surfaced and drove the late-PR fixes (PDO receiver guard, BC-wrapper mutation,ConstantToClassConstantRectorgeneralisation, extraMethodToMethodWithCheckRectorpatterns).
Highlights
- Drupal 11.0–11.4 coverage. 72 rectors wired across five per-minor-version deprecation set lists, covering function → service / function → static / function → method-on-first-arg / class-constant → enum / class rename / argument removal / property → method / and configuration-key rewrites.
- Drupal 10.3 additions. 4 new D10 rectors covering
REQUEST_TIME,ThemeHandlerInterface::rebuildThemeData(),ModuleHandlerInterface::getName(), andFileSystemInterface::EXISTS_*→FileExistsenum. DrupalRectorSettingsservice. Three knobs for tuning runtime behaviour: toggle BC wrapping on/off, set aminimumCoreVersionSupported(contrib modules), and override the detected Drupal version (tests). Registered via$rectorConfig->singleton(DrupalRectorSettings::class, …)in the shippedrector.php.- Generic data-driven rectors. A new shared rector
(
FunctionCallRemovalRector) and two extracted from per-version folders (DrupalServiceRenameRector,FunctionToFirstArgMethodRector) now live insrc/Rector/Deprecation/alongside the established shared rectors, so each Drupal version can register them via config-only entries rather than per-version subclasses. See the Generic shared rectors subsection below for a labelled list of what's new vs. refactored vs. unchanged. - BC wrapping covers all expression rewrites. Previously
AbstractDrupalCoreRector::createBcCallOnExpr()only wrapped CallLike → CallLike rewrites; it now wraps anyNode\Expr→Node\Exprtransformation (ClassConstFetch,PropertyFetch, etc.), so mixed-type rewrites getDeprecationHelper::backwardsCompatibleCall()automatically. - Claude Code skills. Four
.claude/skills/entries —/rector-discover,/rector-implement,/rector-qa,/rector-live-test— drive the conversion pipeline from dbuytaert/drupal-digests rules into shipped rector classes with tests. Includes the 700-line canonical conversion prompt and three reusable recipes.
Added
Infrastructure
rector-hook-convert.php— dedicated configuration that registers onlyHookConvertRector, for running hook conversion as a separate second pass.HookConvertRectorwrites the generatedsrc/Hook/*Hooks.phpto disk outside Rector's file pipeline, so bundling it with the deprecation sets would copy un-fixed hook bodies into the new class. Documented in the README ("Converting hooks to OOP hook classes"): run deprecations first, then this config.DrupalRectorSettings(src/Services/DrupalRectorSettings.php) — container- managed settings object withenableBackwardCompatibility()/disableBackwardCompatibility()/setMinimumCoreVersionSupported(string)/setDrupalVersion(?string)methods. Resolved viastatic::getContainer()->make(DrupalRectorSettings::class)in tests.AbstractDrupalRectorTestCase(tests/src/AbstractDrupalRectorTestCase.php) — replaces the prior namespaced-class\Drupalhack with a propersetUp/tearDownpattern that resets the sharedDrupalRectorSettingssingleton between tests, preventing version-override leaks.createBcCallOnExpr()widened toNode\Exprinsrc/Rector/AbstractDrupalCoreRector.php, so non-CallLike rewrites are BC-wrapped too..gitattributesadded withexport-ignoreentries for.claude/,.github/,tests/,fixtures/,docs/,scripts/,phpstan*.neon,phpunit.xml,rector.php, etc. — keeps the Composer dist archive small and clean. (Verify withgit archive HEAD | tar t | grep -c .claude— expect 0.)- 25 PHPStan stubs under
stubs/covering core classes the rectors type-guard against (ModuleHandlerInterface,EntityInterface,ConfigEntityInterface,StatementPrefetchIterator,CachePluginBase,ThemeHandlerInterface,SessionManagerInterface, …).
Drupal 11 deprecation rules
Every rule wired across
config/drupal-11/drupal-11.{0,1,2,3,4}-deprecations.phpis listed below. Each row links to the Drupal.org change record (or, if no dedicated change record exists, the parent issue). Configurable generic rectors (FunctionToServiceRector,FunctionToStaticRector,FunctionCallRemovalRector,ConstantToClassConstantRector,ClassConstantToClassConstantRector,MethodToMethodWithCheckRector,FunctionToFirstArgMethodRector,RenameClassRector) may appear in multiple rows when they handle several distinct deprecations in the same minor.Drupal 11.0
Rule What it does Change record GetNameToNameRectorTestCase::getName()→name()node/3217904 RemoveStateCacheSettingRectorRemove $settings['state_cache']— state caching is permanently enablednode/2575105 ReplaceRequestTimeConstantRectorREQUEST_TIME→\Drupal::time()->getRequestTime()node/3395986 StripMigrationDependenciesExpandArgRectorgetMigrationDependencies($expand)→ drop the boolean argnode/3442785 MigrateSqlGetMigrationPluginManagerRectorSql::getMigrationPluginManager()→$this->migrationPluginManagerpropertynode/3282894 Drupal 11.1
Rule What it does Change record PluginBaseIsConfigurableRectorPluginBase::isConfigurable()→instanceof ConfigurableInterfacechecknode/2946122 RenameClassRectorAliasWhitelist[Interface]→AliasPrefixList[Interface];MatchingRouteNotFoundException→ResourceNotFoundExceptionnode/3467559 MethodToMethodWithCheckRectorAliasManager::pathAliasWhitelistRebuild()→pathAliasPrefixListRebuild()node/3467559 RemoveModuleHandlerDeprecatedMethodsRectorModuleHandler::writeCache()removed;getHookInfo()returns[]node/3368812 ReplaceLocaleConfigBatchFunctionsRectorRename locale_config_batch_set_config_langcodes()andlocale_config_batch_refresh_name()node/3575254 RemoveUpdaterPostInstallMethodsRectorRemove Updater::postInstall*()methods (no replacement)node/3461934 BlockContentTestBaseStringToArrayRectorBlockContentTestBase::createBlockContentType($string)→ array argnode/3473739 MovePointerToMouseOverRectormovePointerTo($css)→getSession()->getDriver()->mouseOver($xpath)node/3460567 ReplaceAddCachedDiscoveryMethodCallRectoraddMethodCall('addCachedDiscovery', …)onplugin.cache_clearerremovednode/3442229 FunctionToStaticRectordrupal_common_theme()→ThemeCommonElements::commonElements()node/3488176 Drupal 11.2
Rule What it does Change record StatementPrefetchIteratorFetchColumnRectorStatementPrefetchIterator::fetchColumn()→fetchField()node/3490312 MethodToMethodWithCheckRectorCacheBackendInterface::invalidateAll()→deleteAll()node/3500622 FunctionToServiceRectortemplate_preprocess_{html,page,container,links,time,datetime_form,datetime_wrapper}()→ThemePreprocess/DatePreprocessservice methodsnode/3504125 FunctionCallRemovalRectorRemove template_preprocess(),update_clear_update_disk_cache(),update_delete_file_if_stale(),_update_manager_{cache_directory,extract_directory,unique_identifier}()node/3501136 RemoveModuleHandlerAddModuleCallsRectorRemove ModuleHandler::addModule()/addProfile()(no-ops)node/3550193 RemoveHandlerBaseDefineExtraOptionsRectorRemove HandlerBase::defineExtraOptions()overrides (dead code)node/3486781 FunctionToStaticRectordrupal_requirements_severity()→RequirementSeverity::maxSeverityFromRequirements()node/3497049 FunctionToServiceRectorviews_field_default_views_data()and_views_field_get_entity_type_storage()→ servicesnode/3489415 ConstantToClassConstantRectorGlobal REQUIREMENT_INFO/OK/WARNING/ERROR→RequirementSeverity::*node/3575841 RemoveTwigNodeTransTagArgumentRectorDrop the 6th $tagargument fromTwigNodeTransconstructor callsnode/3474692 ReplaceAlphadecimalToIntNullRectorNumber::alphadecimalToInt(null|'')→0node/3494472 ReplaceFieldgroupToFieldsetRectorRender-array '#type' => 'fieldgroup'→'fieldset'node/3515272 ReplacePdoFetchConstantsRector\PDO::FETCH_*→\Drupal\Core\Database\Statement\FetchAs::*(StatementInterface receiver only)node/3488338 ReplaceDateTimeRangeConstantsRectorDateTimeRangeConstantsInterface::{BOTH,START_DATE,END_DATE}→ enum->value;datetime_type_field_views_data_helper()→ servicenode/3574901 FunctionToFirstArgMethodRectorfile_get_content_headers($file)→$file->getDownloadHeaders()node/3494172 ReplaceSessionWritesWithRequestSessionRector$_SESSION['key'] = $value→\Drupal::request()->getSession()->set(...)node/3518914 ReplaceEditorLoadRectoreditor_load($format_id)→entityTypeManager()->getStorage('editor')->load($format_id)node/3509245 ReplaceEntityOriginalPropertyRector$entity->originalmagic property →$entity->getOriginal()/setOriginal(); nullsafe-awarenode/3571065 RenameStopProceduralHookScanRector#[StopProceduralHookScan]→#[ProceduralHookScanStop]node/3495943 RenameClassRectorDrupal\Core\Entity\Query\Sql\pgsql\*→Drupal\pgsql\Entity\Query\*;jsonapiResourceResponseValidator movenode/3488572 RemoveCacheTagChecksumAssertionsRectorRemove CacheTagChecksumCount/CacheTagIsValidCountperformance-trait assertionsnode/3511149 RemoveRootFromCreateConnectionOptionsFromUrlRectorConnection::createConnectionOptionsFromUrl()— drop$rootparameternode/3511287 ClassConstantToClassConstantRectorSystemManager::REQUIREMENT_*→RequirementSeverity::*node/3410939 Drupal 11.3
Rule What it does Change record ReplaceCommentManagerGetCountNewCommentsRectorCommentManager::getCountNewComments()→HistoryManager::getCountNewComments()node/3551729 LoadAllIncludesRectorModuleHandler::loadAllIncludes()→ explicitforeach (getModuleList() …) loadInclude()node/3536432 NodeStorageDeprecatedMethodsRectorNodeStorage::revisionIds()/userRevisionIds()→ entity query chains;countDefaultLanguageRevisions()removednode/3519187 FunctionToServiceRectornode_mass_update()→NodeBulkUpdate::process()node/3533083 FunctionToServiceRectortemplate_preprocess_layout()→LayoutDiscoveryThemeHooks::preprocessLayout()node/3504125 ReplaceTwigExtensionRectortwig_extension()→'.html.twig'string literalnode/1685492 ReplaceNodeModuleProceduralFunctionsRectornode_type_get_names()→entity_type.bundle.infoservice;node_get_type_label($node)→$node->getBundleEntity()->label()node/3516778 FunctionCallRemovalRectorRemove block_content_add_body_field()calls (replaced by config)node/3535528 FunctionToFirstArgMethodRectorcomment_uri($comment)→$comment->permalink()node/2010202 ReplaceNodeAccessViewAllNodesRectornode_access_view_all_nodes()→ entity-type-manager access-control chainnode/3038909 FunctionToServiceRectorresponsive_image_*()helpers →responsive_image.builderservicenode/3548329 ReplaceNodeAddBodyFieldRectornode_add_body_field()→$this->createBodyField()(BodyFieldCreationTrait)node/3516778 ReplaceUserSessionNamePropertyRector$userSession->nameread →getAccountName()node/3513877 FunctionToStaticRectorfile_system_settings_submit()→FileSystemSettingsForm::submit()node/3534091 FileManagedFileSubmitRector'file_managed_file_submit'string callback →[ManagedFile::class, 'submit']array callablenode/3534091 ConstantToClassConstantRectorGlobal JSONAPI_FILTER_AMONG_*→\Drupal\jsonapi\JsonApiFilter::AMONG_*node/3495601 ReplaceNodeSetPreviewModeRectorDRUPAL_DISABLED/OPTIONAL/REQUIRED(and integers) insetPreviewMode()→NodePreviewModeenumnode/3538666 FileSystemBasenameToNativeRectorFileSystem::basename()→ PHP nativebasename()node/3530869 ErrorCurrentErrorHandlerRectorError::currentErrorHandler()→ PHPget_error_handler()node/3529500 ReplaceThemeGetSettingRectortheme_get_setting()→ThemeSettingsProviderservice;_system_default_theme_features()→ThemeSettingsProvider::DEFAULT_THEME_FEATURESnode/3573896 RemoveRootFromConvertDbUrlRectorDatabase::convertDbUrlToConnectionInfo($url, $root, …)— drop the$rootargnode/3511287 RenameClassRectorworkspaces.associationservice /WorkspaceAssociation*→workspaces.tracker/WorkspaceTracker*node/3551450 Drupal 11.4
Rule What it does Change record ViewsPluginHandlerManagerRectorViews::pluginManager()/handlerManager()→plugin.manager.views.*servicesnode/3566982 FunctionToServiceRectornode_access_grants()→NodeGrantsHelper::nodeAccessGrants()node/3578055 NodeAccessRebuildFunctionsRectornode_access_rebuild()/node_access_needs_rebuild()→NodeAccessRebuildservicenode/3534610 FilterFormatFunctionsToServiceRectorfilter_formats(),filter_get_roles_by_format(),filter_get_formats_by_role(),filter_default_format(),filter_fallback_format()→FilterFormatRepositoryInterfaceservicenode/3035368 MediaFilterFormatEditFormValidateRectormedia_filter_format_edit_form_validate()→MediaHooks::formatEditFormValidate()node/3566774 DeprecatedFilterFunctionsRector_filter_autop()/_filter_html_escape()/_filter_html_image_secure_process()→plugin.manager.filtercreateInstance chainnode/3566774 ReplaceSessionManagerDeleteRectorSessionManager::delete($uid)→UserSessionRepositoryInterface::deleteAll($uid)node/3570851 ClassConstantToClassConstantRectorCommentItemInterface::{FORM_BELOW,FORM_SEPARATE_PAGE,HIDDEN,CLOSED,OPEN}andCommentInterface::ANONYMOUS_*→FormLocation/CommentingStatus/AnonymousContactenumsnode/3550054 FunctionToServiceRectorlanguage_configuration_element_submit()→LanguageConfiguration::submit()node/3574727 FunctionCallRemovalRectorRemove field_ui_form_manage_field_form_submit(),automated_cron_settings_submit(),syslog_facility_list(),syslog_logging_settings_submit(),taxonomy_build_node_index(),taxonomy_delete_node_index(), views_ui contextual-suppress functionsnode/3566774 RemoveSetUriCallbackRectorRemove EntityTypeInterface::setUriCallback()calls — uselink_templatesinsteadnode/3575062 ReplaceRecipeRunnerInstallModuleRectorRecipeRunner::installModule($module)→installModules([$module])node/3579527 ReplaceSystemPerformanceGzipKeyRectorsystem.performancecss.gzip/js.gzipconfig keys →css.compress/js.compressnode/3526344 RemoveViewsRowCacheKeysRectorRemove CachePluginBase::getRowCacheKeys()/getRowId()overridesnode/3564958 RemoveCacheExpireOverrideRectorRemove CachePluginBase::cacheExpire()subclass overridesnode/3576855 RemoveTrustDataCallRectorStrip ->trustData()fromConfigfluent chainsnode/3348180 RemoveConfigSaveTrustedDataArgRectorConfig::save($has_trusted_data)— drop the boolean argnode/3348180 RemoveLinkWidgetValidateTitleElementRectorRemove LinkWidget::validateTitleElement()— now handled byLinkTitleRequiredConstraintnode/3554139 RemoveAutomatedCronSubmitHandlerRectorDrop 'automated_cron_settings_submit'from$form['#submit']—#config_targetnow handles config savenode/3566774 ReplaceViewsProceduralFunctionsRectorviews_view_is_{enabled,disabled}(),views_{enable,disable}_view(),views_get_view*()→ entity-storage /Views::*static callsnode/3572594 GetOriginalClassToGetDecoratedClassesRectorEntityTypeInterface::getOriginalClass()→getDecoratedClasses()array accessnode/3557464 UseEntityTypeHasIntegerIdRectorgetEntityTypeIdKeyType() === 'integer',entityTypeSupportsComments(),hasIntegerId($entityType)→EntityTypeInterface::hasIntegerId()node/3566814 FunctionToServiceRectoreditor_filter_xss()→EditorXssFilterInterfaceservicenode/3568144 FunctionToStaticRector_media_library_configure_form_display()/_media_library_configure_view_display()→ static helpersnode/3566774 FunctionToStaticRectorlanguage_configuration_element_submit()static-call form →LanguageConfiguration::submit()node/3574727 FunctionToServiceRectorcontextual_links_to_id()/contextual_id_to_links()→ContextualLinksSerializernode/3568087 FunctionToServiceRectorviews_add_contextual_links()→views.contextual_linksservicenode/3382344 ConstantToClassConstantRectorIMAGE_DERIVATIVE_TOKEN→ImageStyleInterface::TOKENnode/3567619 ReplaceEntityReferenceRecursiveLimitRectorEntityReferenceEntityFormatter::RECURSIVE_RENDER_LIMIT→ literal20node/2940605 SystemRegionFunctionsRectorsystem_region_list()/system_default_region()→theme.region.managerservicenode/3015812 CheckMarkupToProcessedTextRectorcheck_markup()→ processed-text render arraynode/3588040 SystemSortThemesRector'system_sort_themes'string callback →Closure(closure callable)node/3566774 LocaleCompareIncToServiceRectorlocale_translation_flush_projects()/locale_translation_build_projects()/locale_translation_check_projects*()etc. →locale.projectandLocaleSourceservicesnode/3037031 Drupal 10.3 deprecation rules
Wired in
config/drupal-10/drupal-10.3-deprecations.php.Rule What it does Change record MethodToMethodWithCheckRectorRendererInterface::renderPlain()→renderInIsolation()node/3407994 FunctionToStaticRectorfile_icon_class()→IconMimeTypes::getIconClass();file_icon_map()→IconMimeTypes::getGenericMimeType()node/3411269 ReplaceRebuildThemeDataRectorThemeHandlerInterface::rebuildThemeData()→extension.list.themeservicenode/3413196 ReplaceModuleHandlerGetNameRectorModuleHandlerInterface::getName()→extension.list.moduleservicenode/3310017 ClassConstantToClassConstantRectorFileSystemInterface::EXISTS_*→\Drupal\Core\File\FileExistsenumnode/3426517 Generic shared rectors
All eight live under
src/Rector/Deprecation/. Each row labels what changed in this release:(new)introduced in this PR,(refactored)existing class restructured,(enhanced)new feature added,(moved)relocated from a per-version folder,(pre-existing)unchanged but used by new D10.3 / D11 configs.Rector Status in this release Notes FunctionCallRemovalRector(new) Removes deprecated function-call statements that have no direct replacement. Supports an accumulating configuration so per-version config files each contribute their own function list. ConstantToClassConstantRector(refactored) Now extends AbstractDrupalCoreRectorso it participates in BC wrapping when aVersionedConfigurationis supplied. Three previously-bespoke rectors (ReplaceRequirementSeverityConstantsRector,ReplaceJsonApiFilterConstantsRector,ReplaceLocaleTranslationDefaultServerPatternRector) were collapsed into config entries against this class.FunctionToServiceRector(enhanced) New useClassSyntaxoption onFunctionToServiceConfigurationemits\Drupal::service(ClassName::class)instead of a string service ID.MethodToMethodWithCheckRector(enhanced) Additional patterns matched (statement-level, assignment, fluent-chain) so it covers more configurations found during contrib-wide analysis. DrupalServiceRenameRector(moved + bugfix) Lifted from src/Drupal8/intosrc/Rector/Deprecation/. The previous in-place$nodemutation that broke the BC wrapper fallback is fixed — now clones before mutating, with a regression fixture. The legacyDrupal8\Rector\Deprecation\DrupalServiceRenameRectoris kept as a thin subclass that re-validates the D8 configuration value object.FunctionToFirstArgMethodRector(moved) Lifted from src/Drupal9/intosrc/Rector/Deprecation/. The legacyDrupal9\Rector\Deprecation\FunctionToFirstArgMethodRectoris kept as a thin subclass.FunctionToStaticRector(pre-existing) Unchanged class; new configurations added in D10.3 and D11.{1,2,3,4} configs. ClassConstantToClassConstantRector(pre-existing) Unchanged class (introduced in PR #282); new configurations added in D10.3 ( FileSystemInterface::EXISTS_*→FileExistsenum) and D11.4 (CommentItemInterface::*enums).Tooling and scripts
.claude/skills/rector-discover/SKILL.md— lists unimplemented drupal-digests rules by implementation phase; regeneratesdocs/rector-index.ymlwhen stale..claude/skills/rector-implement/SKILL.md— 14-step canonical conversion workflow from a digest rule to a finished rector class + test + fixture + config entry, with type-guard and version-gating quality gates..claude/skills/rector-qa/SKILL.md— five-pass quality review (type guards, fixture coverage, BC decision correctness,@seeURL accuracy, registration audit). Supportsallmode for branch-wide scans..claude/skills/rector-live-test/SKILL.md+setup-rector-test.sh— finds real contrib modules that use the deprecated API a rector targets and runs the rector against them to validate end-to-end. Uses search.tresbien.tech as primary source with GitLab API fallback..claude/scripts/generate-rector-index.php— regeneratesdocs/rector-index.ymlfrom the digests source..claude/scripts/setup-repos.sh— clonesrepos/drupal-digestsandrepos/drupal-corefor local development of new rectors.scripts/check-rector-coverage.php— evaluates real-world coverage by matching shipped rectors against real contrib patches.scripts/generate-deprecation-map.php— extracts@trigger_errordeprecations from Drupal core into a structured YAML map.
Changed
-
ClassConstantToClassConstantRectorandMethodToMethodWithCheckRectornow extendAbstractDrupalCoreRectorand auto-wrap theirExpr → Exprrewrites viaDeprecationHelper::backwardsCompatibleCall(). Their configuration value objects (ClassConstantToClassConstantConfiguration,MethodToMethodWithCheckConfiguration) gain an optionalintroducedVersionconstructor argument (default'0.0.0') and now implementVersionedConfigurationInterface. The default falls outside the BC-wrap gate (< 10.0.0), so consumers that instantiate these value objects without passing the new argument keep pre-refactor behaviour (no wrapping). This closes three D11 → D10 runtime regressions (Comment* enums in 11.4,RequirementSeverityin 11.2,AliasManagermethod rename in 11.1) without moving anything to a-breaking.phpset. -
MethodToMethodWithCheckRectorno longer attaches a "please confirm the receiver type" TODO comment for themaybetype-inference case. The comment-on-parent-statement mechanism relied on parent-node tracking that Rector 2.x removed. For configurations whoseintroducedVersion ≥ 10.0.0, the BC wrap selects the right call at runtime via\Drupal::VERSIONand fully addresses the underlying concern. Configurations with an older introduced version (e.g.urlInfo→toUrl@ 8.0.0,getLowercaseLabel→getSingularLabel@ 8.8.0,clearCsrfTokenSeed→stampNew@ 9.2.0) fall outside the BC-wrap gate and rewrite unconditionally on amaybe-typed receiver. Contrib audit (api.tresbien.tech, 2026-05-28) found zero live callers of those three methods on receivers PHPStan cannot resolve to a concrete type, so the residual risk is theoretical. -
Shipped
rector.phpdisables BC wrapping by default. New users get clean one-version rewrites out of the box. Contrib modules and projects that need to run on multiple Drupal versions should call->enableBackwardCompatibility()and optionally->setMinimumCoreVersionSupported(...)on theDrupalRectorSettingssingleton.The
DrupalRectorSettingsclass default forbackwardCompatibilityEnabledremainstrue(avoids silently changing behaviour for existing users who do not call either method on the service); the shippedrector.phpinvokesdisableBackwardCompatibility()explicitly to surface the project-level recommended default. -
PHPUnit test setup — tests now extend
AbstractDrupalRectorTestCaseinstead ofAbstractRectorTestCasedirectly soDrupalRectorSettingsmutations don't leak between tests. -
composer.jsondev-dependency bumps:phpunit/phpunit^10.0→^12.5.24phpstan/phpstan^1.12 || ^2.0→^2.1.54phpstan/phpstan-deprecation-rules^1.2 || ^2.0→^2.0.4friendsofphp/php-cs-fixer^3.58→^3.95.1symplify/vendor-patches^11.0→^12.0.6cweagans/composer-patches^1.7.2→^2.0symfony/yaml^5 || ^6 || ^7→^5 || ^6 || ^7.4.8
-
CI matrix simplified to PHP 8.3 + Rector 2 (previously also tested PHP 8.2
- Rector 1).
-
Drupal stub
VERSIONbumped from10.99.x-devto11.99.x-devso D11 rules fire in tests by default; D11 tests opt out viaDrupalRectorSettings::setDrupalVersion('1.0.0')for below-version cases. -
Composer autoload
exclude-from-classmapentries added for**/fixture/**,**/fixture-*/**,**/Fixture/**so fixtures don't pollute consuming projects' class maps.
Removed
- Rector 1 support.
composer.jsonnow requiresrector/rector:^2. Drupal 10 EOL is August 2026; Rector 1 was already EOL upstream. docs/rules_overview.md(1,210 lines, auto-generated). Replaced by on-demand generation via.claude/scripts/generate-rector-index.php→docs/rector-index.yml. The composerdocsscript that produced the file is also removed.- Three single-purpose constant rectors collapsed into
ConstantToClassConstantRectorconfig entries:ReplaceRequirementSeverityConstantsRector,ReplaceJsonApiFilterConstantsRector,ReplaceLocaleTranslationDefaultServerPatternRector.
Fixed
DrupalServiceRenameRectorBC wrapper fallback.refactorWithConfigurationused to mutate the input$nodein place; the parent'screateBcCallOnExprreused that same already-mutated node as the deprecated branch of theDeprecationHelper::backwardsCompatibleCall(...), so both branches ended up calling the renamed service and the legacy fallback was silently lost. Now clones before mutating; a regression fixture exercises the BC wrapping.ReplacePdoFetchConstantsRectornative-PDO receiver guard. The original matcher rewrotesetFetchMode/fetch*calls on any object whose argument was\PDO::FETCH_*, which would break native PDO statements. Now guards the receiver withisObjectType($node->var, new ObjectType('Drupal\Core\Database\StatementInterface')).NodeStorageDeprecatedMethodsRectormissingcountDefaultLanguageRevisions— the statement-level REMOVE_NODE case was missing entirely; now covered.ReplaceEntityOriginalPropertyRectornullsafe support — addedNullsafePropertyFetchto the node types and refactor logic so$entity?->originalis rewritten to$entity?->getOriginal().ReplaceEditorLoadRectorargument count — added an arg-count guard soeditor_load()(no args) andeditor_load($a, $b)(two args) are not incorrectly transformed.RemoveCacheExpireOverrideRector— handles Time/Tag/None cache plugin subclasses, FQCN imports, aliased imports, and ignores side-effects in the method body.- 8 unregistered rectors wired into deprecation configs — eight new D11
rector classes shipped with tests but no
config/references in earlier drafts; now all wired into the matchingdrupal-11.X-deprecations.php. AbstractDrupalCoreRector::createBcCallOnExprvisibility — changed from private to protected so subclasses can call it directly when they have to build manual BC wraps for non-Expr top-level nodes (e.g.,ReplacePdoFetchConstantsRector::refactor()'sArrayItembranch).
Compatibility
Dimension Supported PHP ^8.2(CI runs 8.3)Rector ^2only — Rector 1 is droppedDrupal core 8, 9, 10, 11 (10 and 11 are the primary targets; 8 and 9 rules retained for legacy projects) Upgrade notes
Refresh
rector.phpThe shipped
rector.phpwas rewritten to register theDrupalRectorSettingssingleton. Refresh your project's copy:cp vendor/palantirnet/drupal-rector/rector.php .If you have local customisations, merge them by hand. The notable new block is:
$rectorConfig->singleton(DrupalRectorSettings::class, fn () => (new DrupalRectorSettings()) ->disableBackwardCompatibility() );Contrib modules running against an older minimum Drupal version
If your module must keep running on (e.g.) Drupal 10.5 while the development environment runs 11.x, enable BC wrapping and tell the settings the minimum core version you support so the wrappers are emitted correctly:
$rectorConfig->singleton(DrupalRectorSettings::class, fn () => (new DrupalRectorSettings()) ->enableBackwardCompatibility() ->setMinimumCoreVersionSupported('10.5.0') );Cleaning up old BC wrappers
Once you raise your module's minimum supported Drupal version, the existing
DeprecationHelper::backwardsCompatibleCall()wrappers in your code become redundant. Strip them withDeprecationHelperRemoveRector(commented example in the shippedrector.php):$rectorConfig->ruleWithConfiguration(DeprecationHelperRemoveRector::class, [ new DeprecationHelperRemoveConfiguration('10.3.0'), ]);This rewrites every wrapper whose
introducedVersionis below10.3.0back to the new API call directly.Drupal 8 / 9 legacy rectors
Still included for legacy projects. The classes
Drupal8\Rector\Deprecation\DrupalServiceRenameRectorandDrupal9\Rector\Deprecation\FunctionToFirstArgMethodRectorare thin subclasses re-validating their D8/D9 configuration value objects; behaviour is unchanged.Release notes
Open source →Overview
The first alpha of the 1.0 line. It adds full Drupal 11 deprecation coverage (11.0 through 11.4), a container-managed settings service that gives you explicit control over backward-compatibility wrapping, and a documented set of Claude Code skills for building further rectors. It also drops support for Rector 1.
Validated end-to-end against real code:
-
Applied to Drupal Canvas on the canvas-3589155 branch; the full Canvas test suite passed ( pipeline 825601 ).
-
Run across the whole of Drupal contrib via project_analysis : code branch master-next , generated patches under results-next . Spot-checking those patches drove several of the late fixes below: the PDO receiver guard, the BC-wrapper mutation bug, the ConstantToClassConstantRector generalisation, and the extra MethodToMethodWithCheckRector patterns.
Highlights
-
Drupal 11.0–11.4 coverage. 72 rectors wired across five per-minor-version deprecation set lists, covering function → service / function → static / function → method-on-first-arg / class-constant → enum / class rename / argument removal / property → method / and configuration-key rewrites.
-
Drupal 10.3 additions. 4 new D10 rectors covering REQUEST_TIME , ThemeHandlerInterface::rebuildThemeData() , ModuleHandlerInterface::getName() , and FileSystemInterface::EXISTS_* → FileExists enum.
-
DrupalRectorSettings service. Three knobs for tuning runtime behaviour: toggle BC wrapping on/off, set a minimumCoreVersionSupported (contrib modules), and override the detected Drupal version (tests). Registered via $rectorConfig->singleton(DrupalRectorSettings::class, …) in the shipped rector.php .
-
Generic data-driven rectors. A new shared rector ( FunctionCallRemovalRector ) and two extracted from per-version folders ( DrupalServiceRenameRector , FunctionToFirstArgMethodRector ) now live in src/Rector/Deprecation/ alongside the established shared rectors, so each Drupal version can register them via config-only entries rather than per-version subclasses. See the Generic shared rectors subsection below for a labelled list of what's new vs. refactored vs. unchanged.
-
BC wrapping covers all expression rewrites. Previously AbstractDrupalCoreRector::createBcCallOnExpr() only wrapped CallLike → CallLike rewrites; it now wraps any Node\Expr → Node\Expr transformation ( ClassConstFetch , PropertyFetch , etc.), so mixed-type rewrites get DeprecationHelper::backwardsCompatibleCall() automatically.
-
Claude Code skills. Four .claude/skills/ entries ( /rector-discover , /rector-implement , /rector-qa , /rector-live-test ) drive the conversion pipeline from dbuytaert/drupal-digests rules into shipped rector classes with tests. Includes the 700-line canonical conversion prompt and three reusable recipes.
Added
Infrastructure
-
rector-hook-convert.php : dedicated configuration that registers only HookConvertRector , for running hook conversion as a separate second pass. HookConvertRector writes the generated src/Hook/*Hooks.php to disk outside Rector's file pipeline, so bundling it with the deprecation sets would copy un-fixed hook bodies into the new class. Documented in the README ("Converting hooks to OOP hook classes"): run deprecations first, then this config.
-
DrupalRectorSettings ( src/Services/DrupalRectorSettings.php ): container- managed settings object with enableBackwardCompatibility() / disableBackwardCompatibility() / setMinimumCoreVersionSupported(string) / setDrupalVersion(?string) methods. Resolved via static::getContainer()->make(DrupalRectorSettings::class) in tests.
-
AbstractDrupalRectorTestCase ( tests/src/AbstractDrupalRectorTestCase.php ): replaces the prior namespaced-class \Drupal hack with a proper setUp / tearDown pattern that resets the shared DrupalRectorSettings singleton between tests, preventing version-override leaks.
-
createBcCallOnExpr() widened to Node\Expr in src/Rector/AbstractDrupalCoreRector.php , so non-CallLike rewrites are BC-wrapped too.
-
.gitattributes added with export-ignore entries for .claude/ , .github/ , tests/ , fixtures/ , docs/ , scripts/ , phpstan*.neon , phpunit.xml , rector.php , etc. Keeps the Composer dist archive small and clean. (Verify with git archive HEAD | tar t | grep -c .claude ; expect 0.)
-
25 PHPStan stubs under stubs/ covering core classes the rectors type-guard against ( ModuleHandlerInterface , EntityInterface , ConfigEntityInterface , StatementPrefetchIterator , CachePluginBase , ThemeHandlerInterface , SessionManagerInterface , …).
Drupal 11 deprecation rules
Every rule wired across config/drupal-11/drupal-11.{0,1,2,3,4}-deprecations.php is listed below. Each row links to the Drupal.org change record (or, if no dedicated change record exists, the parent issue). Configurable generic rectors ( FunctionToServiceRector , FunctionToStaticRector , FunctionCallRemovalRector , ConstantToClassConstantRector , ClassConstantToClassConstantRector , MethodToMethodWithCheckRector , FunctionToFirstArgMethodRector , RenameClassRector ) may appear in multiple rows when they handle several distinct deprecations in the same minor.
Drupal 11.0
Rule What it does Change record
GetNameToNameRector TestCase::getName() → name() node/3217904
RemoveStateCacheSettingRector Remove $settings['state_cache'] ; state caching is permanently enabled node/2575105
ReplaceRequestTimeConstantRector REQUEST_TIME → \Drupal::time()->getRequestTime() node/3395986
StripMigrationDependenciesExpandArgRector getMigrationDependencies($expand) → drop the boolean arg node/3442785
MigrateSqlGetMigrationPluginManagerRector Sql::getMigrationPluginManager() → $this->migrationPluginManager property node/3282894
Drupal 11.1
Rule What it does Change record
PluginBaseIsConfigurableRector PluginBase::isConfigurable() → instanceof ConfigurableInterface check node/2946122
RenameClassRector AliasWhitelist[Interface] → AliasPrefixList[Interface] ; MatchingRouteNotFoundException → ResourceNotFoundException node/3467559
MethodToMethodWithCheckRector AliasManager::pathAliasWhitelistRebuild() → pathAliasPrefixListRebuild() node/3467559
`RemoveModuleHandlerDeprecatedM...
Read more
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
🎉 2 maks-oleksyuk and sjerdo reacted with hooray emoji All reactions
- 🎉 2 reactions
2 people reacted
- Applied to Drupal Canvas on the
-
0.21.208 May 2026Release notes
Open source →What's Changed
- build: fix codestyle by @bbrala in https://github.com/palantirnet/drupal-rector/pull/322
- fix: Fix phpstan issues and update pipeline actions to current versions by @bbrala in https://github.com/palantirnet/drupal-rector/pull/324
- Allow rector ^2.4.1 and replace file with getFile() if method exists by @samsonasik in https://github.com/palantirnet/drupal-rector/pull/326
- Add theme extension by @nlighteneddesign in https://github.com/palantirnet/drupal-rector/pull/325
- fix: fix theme hook test by @bbrala in https://github.com/palantirnet/drupal-rector/pull/328
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.21.1...0.21.2
-
0.21.107 Nov 2025Release notes
Open source →What's Changed
- Fix method not found on GetDeclaringSourceTrait::getDeclaringSource() by @samsonasik in https://github.com/palantirnet/drupal-rector/pull/317
- Update Deny list to include to missing hooks and remove preprocess by @nlighteneddesign in https://github.com/palantirnet/drupal-rector/pull/318
- Better replacement for dynamic uppercase parts in Implements hook_xy by @Berdir in https://github.com/palantirnet/drupal-rector/pull/320
New Contributors
- @Berdir made their first contribution in https://github.com/palantirnet/drupal-rector/pull/320
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.21.0...0.21.1
-
0.21.023 May 2025Release notes
Open source →This release adds Rector 2 support. FOr now we support both 1 and 2, for now this seems like a reasonable goal. If we start running into to many issues we will split the repo into a 1 and 2 release.
What's Changed
- feat: Drop Drupal 8 support by @bbrala in https://github.com/palantirnet/drupal-rector/pull/311
- feat: Add support for PHPstan 2 and Rector 2 by @ptmkenny in https://github.com/palantirnet/drupal-rector/pull/312
- feat: Add new HookConvert rector to convert legacy hooks to new OOP hooks. by @nlighteneddesign in https://github.com/palantirnet/drupal-rector/pull/308
- chore: Remove use of protected property NodeNameResolver on HookConvertRector by @samsonasik in https://github.com/palantirnet/drupal-rector/pull/316
New Contributors
- @ptmkenny made their first contribution in https://github.com/palantirnet/drupal-rector/pull/312
- @nlighteneddesign made their first contribution in https://github.com/palantirnet/drupal-rector/pull/308
- @samsonasik made their first contribution in https://github.com/palantirnet/drupal-rector/pull/316
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.20.3...0.21.0
-
0.20.310 Jun 2024Release notes
Open source →New rectors
- New rector (10.3): Add rule for file_icon_class() and file_icon_map() by @timohuisman in https://github.com/palantirnet/drupal-rector/pull/304
- Add common PHPUnit 10 deprecations by @bbrala in https://github.com/palantirnet/drupal-rector/pull/307
Bugfixes
- symplify/rule-doc-generator doesnt like cs-fixer a lot of times. Adju… by @bbrala in https://github.com/palantirnet/drupal-rector/pull/306
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.20.2...0.20.3
-
0.20.226 Apr 2024Release notes
Open source →New rectors
- New rector (10.1): drupal_theme_rebuild is deprecated by @bbrala in https://github.com/palantirnet/drupal-rector/pull/297
- New rector (10.2): Rector for _drupal_flush_css_js through new VersionedFunctionToServiceRector by @bbrala in https://github.com/palantirnet/drupal-rector/pull/302
Bugfixes
- bugfix: remove extra \ from Drupal\Core\StringTranslation\ByteSizeMarkup rector by @bbrala in https://github.com/palantirnet/drupal-rector/pull/301
What's Changed
- Update core_plugin_conversion.md by @bbrala in https://github.com/palantirnet/drupal-rector/pull/298
- doc: Fix doc for AnnotationToAttributeRector and generate new docs. by @bbrala in https://github.com/palantirnet/drupal-rector/pull/299
- Upgrade project tooling to PHP 8.2 by @agentrickard in https://github.com/palantirnet/drupal-rector/pull/300
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.20.1...0.20.2
-
0.20.109 Mar 2024Release notes
Open source →This release adds the code to move from annotations to attributes which currently is being done in core. For now this code is not added by default until things settle down. If you want to use the rector check out AnnotationToAttributeRector.
If you want to contribute to core in the migration, check out these docs or go help out in #3396165.
New rectors
- New rector: Rule to convert action to attributes by @andypost in https://github.com/palantirnet/drupal-rector/pull/257
- New rector (9.1): ClassConstantToClassConstantRector to rename class constants to a new class. by @bbrala in https://github.com/palantirnet/drupal-rector/pull/282
- feat: Optimize AnnotationToAttributeRector by @bbrala in https://github.com/palantirnet/drupal-rector/pull/296
What's Changed
- Add bbrala to authors by @bbrala in https://github.com/palantirnet/drupal-rector/pull/294
- Add agentrickard to authors. by @agentrickard in https://github.com/palantirnet/drupal-rector/pull/295
New Contributors
- @andypost made their first contribution in https://github.com/palantirnet/drupal-rector/pull/257
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.20.0...0.20.1
-
0.20.005 Mar 2024Release notes
Open source →New Rector
- feat: add rector rule for deprecated GDToolkit by @timohuisman in https://github.com/palantirnet/drupal-rector/pull/289
What's Changed
- refactor: Replace deprecated LevelSetLists for version specific PHPUnit, Symfony and Twig sets by @timohuisman in https://github.com/palantirnet/drupal-rector/pull/290
- feat: upgrade to rector 1.0 by @bbrala in https://github.com/palantirnet/drupal-rector/pull/292
- fix: Add proper levels for all symfony versions deprecated in the different versions of Drupal by @bbrala in https://github.com/palantirnet/drupal-rector/pull/293
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.19.2...0.20.0
-
0.19.217 Jan 2024Release notes
Open source →Fixed
- Fix: Double deprecated calls when already refactored by @bbrala in https://github.com/palantirnet/drupal-rector/pull/288
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.19.1...0.19.2
-
0.19.112 Jan 2024Release notes
Open source →What's Changed
- bugfix: switch arguments of AbstractDrupalCoreRector by @timohuisman in https://github.com/palantirnet/drupal-rector/pull/287
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.19.0...0.19.1
-
0.19.011 Jan 2024Release notes
Open source →New rector
- feat: Add rector rule for format_size in 10.2 by @timohuisman in https://github.com/palantirnet/drupal-rector/pull/286
What's Changed
- feat: Upgrade rector to 0.19 and fix phpstan incompatiblities by @bbrala in https://github.com/palantirnet/drupal-rector/pull/284
New Contributors
- @timohuisman made their first contribution in https://github.com/palantirnet/drupal-rector/pull/286
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.18.6...0.19.
-
0.18.628 Dec 2023Release notes
Open source →What's Changed
- Hotfix: New rector FILE_STATUS_PERMANENT was not added to deprecation list. … by @bbrala in https://github.com/palantirnet/drupal-rector/pull/280
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.18.5...0.18.6
-
0.18.527 Dec 2023Release notes
Open source →New rector
- New rector (9.3): Support FILE_STATUS_PERMANENT deprecation by @bbrala in https://github.com/palantirnet/drupal-rector/pull/278
- New rector (9.1): \Drupal\Component\Utility\Bytes::toInt() is deprecated by @bbrala in https://github.com/palantirnet/drupal-rector/pull/279
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.18.4...0.18.5
-
0.18.418 Dec 2023Release notes
Open source →New rector
- New rector: Support for module_load_include deprecation (Drupal 9) by @bbrala in https://github.com/palantirnet/drupal-rector/pull/277
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.18.3...0.18.4
-
0.18.305 Dec 2023Release notes
Open source →New rector
- PHPUnit: Rector to fix missing parent::setUp and parent::tearDown methods by @bbrala in https://github.com/palantirnet/drupal-rector/pull/273
Bugfix
- Fix EntityManagerRector based on project_analysis results by @bbrala in https://github.com/palantirnet/drupal-rector/pull/274
Other changes
- Remove latest release from readme, unneeded maintainance, its already… by @bbrala in https://github.com/palantirnet/drupal-rector/pull/270
- Better workflows by @bbrala in https://github.com/palantirnet/drupal-rector/pull/275
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.18.2...0.18.3
-
0.18.224 Nov 2023Release notes
Open source →New rector
- Add rector for system_time_zones by @bbrala in https://github.com/palantirnet/drupal-rector/pull/271
What's Changed
- Link packagist version shield to package on packagist.org by @kasperg in https://github.com/palantirnet/drupal-rector/pull/269
New Contributors
- @kasperg made their first contribution in https://github.com/palantirnet/drupal-rector/pull/269
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.18.1...0.18.2
-
0.18.121 Nov 2023Release notes
Open source →New rector
- Add $defaultTheme property if missing on BrowserTestBase by @mglaman in https://github.com/palantirnet/drupal-rector/pull/211
What's Changed
- Update README.md by @bbrala in https://github.com/palantirnet/drupal-rector/pull/264
- Restructure rules by major and generate rule list (docs) by @bbrala in https://github.com/palantirnet/drupal-rector/pull/267
- Fix db_query.php expected test. by @bbrala in https://github.com/palantirnet/drupal-rector/pull/268
- Update README-automated-testing.md by @bbrala in https://github.com/palantirnet/drupal-rector/pull/266
- Add php-cs-fixer by @bbrala in https://github.com/palantirnet/drupal-rector/pull/265
- Add $defaultTheme property if missing on BrowserTestBase by @mglaman in https://github.com/palantirnet/drupal-rector/pull/211
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.18.0...0.18.1
-
0.18.010 Nov 2023Release notes
Open source →Release highlights
This release of Drupal Rector introduces backwards compatible fixes for new rectors that target deprecations in Drupal 10. This is made possible by using the new
DeprecationHelperclass introduced in Drupal 10.1.We also worked on making the code more sustainable by employing
ConfigurableRectorInterface. This interface allows passing configuration to a rector to set certain variables. This means it is easier to reuse rectors that for example rewrite a function to a static call without introducing new code.Rector has also been upgraded from 0.15 to 0.18, bringing a lot of improvement, but also making it harder to add comments to code generated by Rector. This there are instances where the previous version added comments, that the current does not.
- Support for Drupal 10 deprecations and testing by @bbrala in https://github.com/palantirnet/drupal-rector/pull/252
- Support for backwards compatible rector rules and version scoping of rules by @bbrala in https://github.com/palantirnet/drupal-rector/pull/250
Upgrade notes
Because rector moved to Laravel dependency injection a new version of
rector.phpmust be copies/configured in your project root.New rectors
- Issue #3354343: Add TwigSetList::TWIG_240 to D9 deprecations. by @m4olivei in https://github.com/palantirnet/drupal-rector/pull/223
- Add new Rector for system_sort_modules_by_info_name() by @bbrala in https://github.com/palantirnet/drupal-rector/pull/253
- module_load_install() is deprecated in 9.4 and removed in 10. by @bbrala in https://github.com/palantirnet/drupal-rector/pull/239
- Implement watchdog_exception rector by @bbrala in https://github.com/palantirnet/drupal-rector/pull/262
- 9.3 Multiple taxonomy rectors by @bbrala in https://github.com/palantirnet/drupal-rector/pull/254
What's Changed
- Remove NodesToAddCollector by @bbrala in https://github.com/palantirnet/drupal-rector/pull/225
- Remove dependency on rector-src by @bbrala in https://github.com/palantirnet/drupal-rector/pull/236
- Update PHPUnit configuration by @agentrickard in https://github.com/palantirnet/drupal-rector/pull/237
- Phase 1 - Refactor to support Rector 0.17 by @bbrala in https://github.com/palantirnet/drupal-rector/pull/238
- Simplify codebase: replace EntityLoadBase with configurable rule by @bbrala in https://github.com/palantirnet/drupal-rector/pull/228
- Refactor AssertLegacyTraitBase and ConstantToClassConstantBase to configurable rule by @bbrala in https://github.com/palantirnet/drupal-rector/pull/229
- Improve AssertNoFieldByIdRector by @mglaman in https://github.com/palantirnet/drupal-rector/pull/213
- Create FunctionToServiceRector to replace all function to service call deprecations by @bbrala in https://github.com/palantirnet/drupal-rector/pull/242
- New StaticToFunctionRector to replace StaticToFunctionBase by @bbrala in https://github.com/palantirnet/drupal-rector/pull/243
- Remove single use FunctionToImmutableConfigBase by @bbrala in https://github.com/palantirnet/drupal-rector/pull/245
- StaticArgumentRenameBase and DrupalServiceRenameBase are now covered with StaticArgumentRenameRector by @bbrala in https://github.com/palantirnet/drupal-rector/pull/241
- New ExtensionPathRector to replace ExtensionPathBase by @bbrala in https://github.com/palantirnet/drupal-rector/pull/244
- New DBRector to replace DbBase with configurable rector. by @bbrala in https://github.com/palantirnet/drupal-rector/pull/246
- GetMockRector as configurable rule by @bbrala in https://github.com/palantirnet/drupal-rector/pull/248
- Upgrade to PHPStan level 6 by @bbrala in https://github.com/palantirnet/drupal-rector/pull/249
- MethodToMethodWithCheckRector to replace methods with a certainty check by @bbrala in https://github.com/palantirnet/drupal-rector/pull/247
- Refactor Base\FunctionToStatic to configurable rule. by @bbrala in https://github.com/palantirnet/drupal-rector/pull/251
- Upgrade to Rector 0.18.x by @bbrala in https://github.com/palantirnet/drupal-rector/pull/240
- Refactored BC rules with configuration by @bbrala in https://github.com/palantirnet/drupal-rector/pull/255
- Add better labels to readme by @bbrala in https://github.com/palantirnet/drupal-rector/pull/256
- Add failing unit test for ExtensionPathRector when assining by @bbrala in https://github.com/palantirnet/drupal-rector/pull/258
- Add WatchdogExceptionRector the 10.1 setlist by @bbrala in https://github.com/palantirnet/drupal-rector/pull/263
- PHPUnit deprecations should be checked in Drupal 9 to 10 by @bbrala in https://github.com/palantirnet/drupal-rector/pull/261
- Fix MethodToMethodWithCheckRector by also matching on MethodCall. by @bbrala in https://github.com/palantirnet/drupal-rector/pull/260
- ExtensionPathRector does not handle Assignments by @bbrala in https://github.com/palantirnet/drupal-rector/pull/259
New Contributors
- @m4olivei made their first contribution in https://github.com/palantirnet/drupal-rector/pull/223
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.15.1...0.18.0
-
0.15.123 Mar 2023Release notes
Open source →What's Changed
- Update rector config to resolve bootstrap issues with recent rector releases by @mglaman in https://github.com/palantirnet/drupal-rector/pull/220
- Update rector config to resolve bootstrap issues with recent rector releases by @goba in https://github.com/palantirnet/drupal-rector/pull/219
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.15.0...0.15.1
-
0.15.011 Jan 2023Release notes
Open source →What's Changed
- Update to rector 15 and github setup v3. by @agentrickard in https://github.com/palantirnet/drupal-rector/pull/218 and @FlorentTorregrosa in https://github.com/palantirnet/drupal-rector/pull/217
- Fix function signature in tests by @chrfritsch in https://github.com/palantirnet/drupal-rector/pull/216
New Contributors
- @chrfritsch made their first contribution in https://github.com/palantirnet/drupal-rector/pull/216
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.13.1...0.15.0
-
0.13.105 Aug 2022Release notes
Open source →What's Changed
- ProtectedStaticModulesProperty rule by @mglaman in https://github.com/palantirnet/drupal-rector/pull/210
- Update rector.php so we do not use FQCN's in method arguments by @bbrala in https://github.com/palantirnet/drupal-rector/pull/209
New Contributors
- @bbrala made their first contribution in https://github.com/palantirnet/drupal-rector/pull/209
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.13.0...0.13.1
-
0.13.015 Jul 2022Release notes
Open source →What's Changed
- #3295386 Bump to rector/rector:0.13.8 by @mglaman in https://github.com/palantirnet/drupal-rector/pull/204
- Remove unneeded assert for $pathValue by @mglaman in https://github.com/palantirnet/drupal-rector/pull/206
- Scope may not be available when detecting delcaring source by @mglaman in https://github.com/palantirnet/drupal-rector/pull/207
- Prevent @doesNotPerformAssertions from being added to tests by @mglaman in https://github.com/palantirnet/drupal-rector/pull/208
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.12.4...0.13.0
-
0.12.401 Jun 2022Release notes
Open source →Release notes
-
The 0.12.4 is a stable release pinned to Rector 0.12.21. Developers should be aware that Rector 0.12.22 introduces breaking changes to how we handle Drupal configuration.
-
The 0.12.5 release of drupal-rector will include Rector 0.12.22. The upgrade path should be as simple as re-copying the configuration file.
cp vendor/palantirnet/drupal-rector/rector.php
What's Changed
- Add integration test for user_password() deprecation by @claudiu-cristea in https://github.com/palantirnet/drupal-rector/pull/201
- Issue #3282217: file_build_uri() is deprecated by @claudiu-cristea in https://github.com/palantirnet/drupal-rector/pull/202
- Remove remaining Rector conflicts up to 0.12.21 by @mglaman in https://github.com/palantirnet/drupal-rector/pull/203
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.12.3...0.12.4
-
-
0.12.324 May 2022Release notes
Open source →The 0.12.3 release bypasses a known conflict with Rector 0.12.18. The current preferred version is Rector 0.12.19.
What's Changed
- Fix PHP 8 warnings on
nulltofile_existsby @mglaman in https://github.com/palantirnet/drupal-rector/pull/196 - Issue #3277704: Remove PHPUNIT_75 constant in Rector by @FlorentTorregrosa in https://github.com/palantirnet/drupal-rector/pull/197
- Issue #3280205: drupalPostForm() with 1st param NULL by @claudiu-cristea in https://github.com/palantirnet/drupal-rector/pull/198
- user_password() deprecation by @claudiu-cristea in https://github.com/palantirnet/drupal-rector/pull/199
- Remove conflicts on rector/rector by @mglaman in https://github.com/palantirnet/drupal-rector/pull/200
New Contributors
- @claudiu-cristea made their first contribution in https://github.com/palantirnet/drupal-rector/pull/198
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.12.2...0.12.3
- Fix PHP 8 warnings on
-
0.12.204 May 2022Release notes
Open source →What's Changed
- Mark conflict on rector >=0.12.18 by @mglaman in https://github.com/palantirnet/drupal-rector/pull/195 Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.12.1...0.12.2
-
0.12.121 Feb 2022Release notes
Open source →Updates Drupal Rector for the most common Drupal 9.3 and 9.4 deprecations.
- https://www.drupal.org/project/rector/issues/3261614
What's Changed
- Update composer.json for allow-plugins by @mglaman in https://github.com/palantirnet/drupal-rector/pull/186
- Rectors for drupal_get_path & drupal_get_filename by @mglaman in https://github.com/palantirnet/drupal-rector/pull/187
- Handle custom message types by @mglaman in https://github.com/palantirnet/drupal-rector/pull/190
- Add Rector for deprecated
renderby @mglaman in https://github.com/palantirnet/drupal-rector/pull/188 - Use dev-main for rector-src by @mglaman in https://github.com/palantirnet/drupal-rector/pull/193
- Rectors for file_move, file_copy, file_save_data by @mglaman in https://github.com/palantirnet/drupal-rector/pull/189
- file_url_generator service Rector rules by @mglaman in https://github.com/palantirnet/drupal-rector/pull/191
- MetadataBag::clearCsrfTokenSeed replaced by stampNew by @mglaman in https://github.com/palantirnet/drupal-rector/pull/192
Full Changelog: https://github.com/palantirnet/drupal-rector/compare/0.12.0...0.12.1
-
0.12.019 Nov 2021 -
0.11.413 Oct 2021Release notes
Open source →This is a maintenance release that includes updates to stay compatible with Rector.
-
0.11.303 Sep 2021Release notes
Open source →This is a maintenance release that fixes a number of issues and updates the
deprecations-indexfor Drupal 9 changes.-
Cleans up internal function doc mismatches. -
Fix entity_view(), entity_delete_multiple() and EntityTypeInterface::getLowercaseLabel deprecation message -
Issue #3228110: Improve AssertNoUniqueTextRector documentation and scope -
Adds AssertLegacy and other new items to the index. -
Issue #3229896: Fix broken params on assert cache tag Rector rules -
Ensure proper rector install on github ci. -
Issue #3221584: Use "*" over sha for sandbox test -
Issue #3228113: Make PassRector more specific and fix documentation -
Prevents stubs used for testing from breaking end user's PHPUnit tests for Drupal -
Fixes BuildXPathQuery docs. -
Fix REQUEST_TIME deprecation message. Noted by @mglaman -
Issue #3222671: Rector for assertNoFieldByName() -
Issue #3222671: Rector for assertUniqueText() and assertNoUniqueText() -
Issue #3222671: Rector for pass()
-
-
0.11.229 Jul 2021Release notes
Open source →This release corrects an error in Rector 0.11.38 that was fixed in later versions (https://github.com/rectorphp/rector-src/pull/484).
See https://www.drupal.org/project/rector/issues/3225019 and a hat-tip to
Grimreaperfor reporting and testing this issue. -
0.11.106 Jul 2021Release notes
Open source →The release prepares drupal-rector to handle Drupal 9 deprecations, using PHP 8 and rector v 0.11.
This release also changes the file structure of the underlying code and introduced PHPUnit testing.
Note that this version can be run in PHP 7 without PHPUnit, which is not necessary for running rector upgrades on your code.
This release supports 8.x and 9.x code conversions and can be run with either Drupal 8 or Drupal 9.
-
0.11.030 Jun 2021Release notes
Open source →This release brings us up-to-date with Rector 11 and adds support for PHPUnit testing.
PHPUnit testing requires PHP 8 and is used for development.
Creating new Rector rules and running the Rector update requires PHP 7 or higher.
-
0.10.023 Jun 2021Release notes
Open source →This release updates to Rector version 0.10.0 and prepares for more substantial changes coming to prepare for Drupal 10.
Major changes
- We now use
rector.phpinstead ofrector.ymlfor configuration. - Adds PHPStan for static code analysis.
- We are deprecating the Behat tests in favor of PHPUnit (See #152)
New rules
- entity_view
- We now use
-
0.5.605 Jun 2020Release notes
Open source →Summary of updates in this release:
- 3 new Rector rules:
- DatetimeDateStorageFormatRector
- DatetimeDatetimeStorageFormatRector
- DatetimeStorageTimezoneRector
- Upgrade to rector-prefixed 0.7.27
- Fix internal Github tests
- 3 new Rector rules:
-
0.5.529 May 2020Release notes
Open source →Summary of updates in this release:
- Bug fixes for Rector rules
- Running the latest rector-prefixed
- Commented out PHPUnit8 code upgrade option in
rector.yml - Drupal Rector rules documentation
- Add comments to call out edge cases in Drupal Rector code replacements (this option can be disabled through
rector.yml)
-
0.5.422 May 2020Release notes
Open source →Using latest rector-prefixed, which would stop creating diffs with unnecessary indentation fixes.
Added new Rector rules for the following deprecations:
- FILE_EXISTS_RENAME
- LinkGeneratorTrait::l()
- entity_create()
- SafeMarkup::format()
-
0.5.314 May 2020Release notes
Open source →Added new Rector rules for the following deprecations:
- Unicode::strlen
- Unicode::substr
- EntityInterface:link()
- entity_load()
- node_load()
- file_load()
- file_directory_temp
- file_directory_os_temp
- drupal_realpath()
- file_uri_target()
-
0.5.208 May 2020Release notes
Open source →Added new Rector rules for the following deprecations:
- db_update()
- file_scan_directory()
- REQUEST_TIME
- entity_get_display
- entity_get_form_display
- file_default_scheme()
- EntityInterface:urlInfo()
-
0.5.128 Apr 2020Release notes
Open source →Added new Rector rules for the following deprecations:
- FILE_MODIFY_PERMISSIONS
- db_delete()
-
0.5.026 Apr 2020Release notes
Open source →Added new Rector rules for the following deprecations:
- file_unmanaged_save_data()
-
0.4.125 Apr 2020Release notes
Open source →Rector-prefix 0.7.19 is broken - Issue: rectorphp/rector#3256
PR to prevent it from happening in the future: rectorphp/rector#3255 (comment)
-
0.4.017 Apr 2020Release notes
Open source →Upgraded to latest Rector (version 0.7.x)
Added CI test using Github Actions
Added new Rector rules for the following deprecations:
- format_date
- Unicode::strtolower
- FILE_CREATE_DIRECTORY
- FILE_EXISTS_REPLACE
- Drupal::l()
- drupal_render()
- drupal_render_root()
-
0.3.311 Apr 2020Release notes
Open source →Deprecations covered:
drupal_set_message() entityManager() Drupal::entityManager() ControllerBase::entityManager() db_insert db_select db_query file_prepare_directory() getMock() BrowserTestBase::getMock() KernelTestBase::getMock() UnitTestCase::getMock() Drupal::url() -
0.3.217 Feb 2020Nothing published for this version
-
0.3.117 Feb 2020 -
0.3.022 Jan 2020Nothing published for this version
-
0.2.016 Jan 2020Nothing published for this version