Rector rules and tooling based to create rectors base on dbuytaert/drupal-digests #2
Open
bbrala wants to merge 256 commits into
Open
Rector rules and tooling based to create rectors base on dbuytaert/drupal-digests #2bbrala wants to merge 256 commits into
bbrala wants to merge 256 commits into
Conversation
…Rector Previously backwardsCompatibleCall wrapping only applied when both the old and new nodes were CallLike (FuncCall, MethodCall, StaticCall, etc.). The restriction was in AbstractDrupalCoreRector, not in DeprecationHelper itself, which accepts any callable. Broaden the guard to Node\Expr so that non-CallLike transformations such as ClassConstFetch → ClassConstFetch and ClassConstFetch → PropertyFetch also get BC-wrapped when the introduced version supports it. Add a test stub rector (ClassConstFetchBCRector) and fixture to cover the new Expr → Expr path.
…eplacements FileSystemInterface::EXISTS_RENAME, EXISTS_REPLACE, and EXISTS_ERROR were deprecated in drupal:10.3.0 and removed in drupal:12.0.0 (issue #3575575). Replaced by the \Drupal\Core\File\FileExists backed enum.
- template_preprocess_{container,html,page,links,time,datetime_form,
datetime_wrapper}() → ThemePreprocess/DatePreprocess service methods
(issue #3501136)
- SystemManager::REQUIREMENT_{OK,WARNING,ERROR} → RequirementSeverity
enum cases (issue #3575841)
node_mass_update() was deprecated in drupal:11.3.0 and removed in drupal:13.0.0 (issue #3571623). Replaced by NodeBulkUpdate::process() via the service container.
…rable rectors FunctionToServiceRector (29 functions across 9 modules, issue numbers below): - ckeditor5_filter_format_edit_form_submit, _update_ckeditor5_html_filter → Ckeditor5Hooks service (#3566792) - _dblog_get_message_types, dblog_filters → DbLogFilters service (#3560398) - contact_user_profile_form_submit, contact_form_user_admin_settings_submit → ContactFormHooks service (#3566888) - 6× content_translation_* → content_translation.manager / ContentTranslationEnableTranslationPerBundle / ContentTranslationHooks (#3548571) - locale_translation_batch_update_build, _batch_fetch_build → LocaleFetch (#3572339) - 7× locale_translation_* → locale.project / LocaleSource (#3569328) - 6× menu_ui_* → MenuUiUtility / MenuUiHooks (#3571400) - text_summary → TextSummary::generate (#3568387) - user_form_process_password_confirm → UserThemeHooks (#3582106) FunctionToStaticRector (4 functions): - views_ui_form_button_was_clicked → ViewsFormHelperTrait::formButtonWasClicked - views_ui_add_limited_validation, _add_ajax_wrapper, _nojs_submit → ViewsFormAjaxHelperTrait (#3035340) ClassConstantToClassConstantRector (6 constants): - CommentItemInterface::HIDDEN/CLOSED/OPEN → CommentingStatus enum (#3574661) - CommentInterface::ANONYMOUS_* → AnonymousContact enum (#3574661)
Replaces deprecated ModuleHandlerInterface::getName($module) calls with
\Drupal::service('extension.list.module')->getName($module), BC-wrapped
for sites running Drupal 10.3+.
…ist rename Adds AliasManager::pathAliasWhitelistRebuild() -> pathAliasPrefixListRebuild() rename (drupal:11.1.0, issue #3151086). Also registers DRUPAL_111/112/113 constants in Drupal11SetList.
…n rule Replaces invalidateAll() with deleteAll() on CacheBackendInterface objects (drupal:11.2.0, issue #3498947).
…r issue #3543035 Replaces CommentManagerInterface::getCountNewComments() with \Drupal::service(\Drupal\history\HistoryManager::class)->getCountNewComments(), BC-wrapped for drupal:11.3.0.
…6062 Replaces NodeStorage::revisionIds() and userRevisionIds() with equivalent entity query chains (drupal:11.3.0, removed in drupal:13.0.0).
Replaces deprecated PluginBase::isConfigurable() calls with instanceof \Drupal\Component\Plugin\ConfigurableInterface checks (drupal:11.1.0, removed in drupal:12.0.0).
Replaces SessionManager::delete($uid) with \Drupal::service(UserSessionRepositoryInterface::class)->deleteAll($uid), BC-wrapped for drupal:11.4.0.
…sue #3490200 Renames fetchColumn() to fetchField() on database statements, skipping PDO's native $this->clientStatement->fetchColumn() (drupal:11.2.0).
Replaces ModuleHandler::loadAllIncludes() with an explicit foreach loop over getModuleList() + loadInclude() (drupal:11.3.0, removed in 13.0.0).
…Rector - ReplaceRebuildThemeDataRector: replaces ThemeHandlerInterface::rebuildThemeData() with extension.list.theme service chain (drupal:10.3.0, issue #3571068) - ViewsPluginHandlerManagerRector: replaces Views::pluginManager() and Views::handlerManager() with Drupal::service() equivalents (drupal:11.4.0, issue #3566424)
…all removal Handles 11 deprecated Drupal functions across versions 11.2–11.4 that have been removed with no direct replacement, using a configurable accumulation pattern so multiple version config files can each add their function list.
…ting removal $settings['state_cache'] deprecated in drupal:11.0.0 — state caching is permanently enabled. Adds drupal-11.0-deprecations.php config file and DRUPAL_110 set list constant.
ModuleHandlerInterface::addModule() and addProfile() are no-ops since drupal:11.2.0 and removed in drupal:12.0.0. Uses isObjectType() type check to target only calls on ModuleHandlerInterface implementors.
LinkWidget::validateTitleElement() deprecated in drupal:11.4.0, removed in drupal:12.0.0. Validation is now handled by LinkTitleRequiredConstraint on the LinkItem field type.
\$form['#submit'][] = 'automated_cron_settings_submit' deprecated in drupal:11.4.0, removed in drupal:13.0.0. Config saving is now handled automatically via #config_target on the interval element.
- drupal-11.2: FunctionCallRemovalRector (template_preprocess, 5 update manager funcs), RemoveModuleHandlerAddModuleCallsRector - drupal-11.3: FunctionCallRemovalRector (block_content_add_body_field) - drupal-11.4: FunctionCallRemovalRector (views_ui contextual suppress funcs, automated_cron_settings_submit), RemoveLinkWidgetValidateTitleElementRector, RemoveAutomatedCronSubmitHandlerRector
REQUEST_TIME constant was deprecated in drupal:8.3.0 and removed in drupal:11.0.0. Replaces all uses with \Drupal::time()->getRequestTime().
JSONAPI_FILTER_AMONG_* global constants deprecated in drupal:11.3.0, removed in drupal:13.0.0. Replaced by \Drupal\jsonapi\JsonApiFilter::AMONG_* class constants.
DRUPAL_DISABLED/OPTIONAL/REQUIRED constants and integer literals 0/1/2 in NodeTypeInterface::setPreviewMode() deprecated in drupal:11.3.0, removed in drupal:13.0.0. Replaced by NodePreviewMode enum cases.
- drupal-11.3: ReplaceJsonApiFilterConstantsRector, ReplaceNodeSetPreviewModeRector - drupal-11.4: ReplaceViewsProceduralFunctionsRector, UseEntityTypeHasIntegerIdRector
- ReplaceRequirementSeverityConstantsRector: REQUIREMENT_* global constants → RequirementSeverity::* enum cases - ReplaceCommentUriRector: comment_uri($comment) → $comment->permalink() - ReplaceUserSessionNamePropertyRector: typed $userSession->name → $userSession->getAccountName() - ReplaceLocaleConfigBatchFunctionsRector: rename locale_config_batch_set_config_langcodes and locale_config_batch_refresh_name - StripMigrationDependenciesExpandArgRector: remove expand arg from getMigrationDependencies() on MigrationInterface Also adds FunctionToStaticRector and FunctionToServiceRector config entries for drupal_requirements_severity, views field functions, file_system_settings_submit, editor/field/media library service-bound functions across 11.0–11.4 config files.
New rector classes:
- RemoveSetUriCallbackRector: remove setUriCallback() standalone + mid-chain (11.4)
- RemoveTrustDataCallRector: remove trustData() from fluent chains (11.4)
- RemoveConfigSaveTrustedDataArgRector: strip boolean arg from save(TRUE/FALSE) (11.4)
- RemoveModuleHandlerDeprecatedMethodsRector: remove writeCache(), replace getHookInfo() with [] (11.1)
- FileSystemBasenameToNativeRector: FileSystemInterface::basename() → native basename() (11.3)
- ErrorCurrentErrorHandlerRector: Error::currentErrorHandler() → get_error_handler() (11.3)
- ReplaceDateTimeRangeConstantsRector: DateTimeRangeConstantsInterface constants → enum->value, datetime_type_field_views_data_helper() → service (11.2)
Config additions:
- 11.1: RemoveModuleHandlerDeprecatedMethodsRector
- 11.2: ReplaceDateTimeRangeConstantsRector
- 11.3: FileSystemBasenameToNativeRector, ErrorCurrentErrorHandlerRector
- 11.4: RemoveSetUriCallbackRector, RemoveTrustDataCallRector, RemoveConfigSaveTrustedDataArgRector,
syslog_facility_list, syslog_logging_settings_submit, taxonomy_build_node_index,
taxonomy_delete_node_index FunctionCallRemovalRector entries
- ReplaceThemeGetSettingRector: theme_get_setting() → ThemeSettingsProvider service, _system_default_theme_features() → ThemeSettingsProvider::DEFAULT_THEME_FEATURES (11.3) - ReplaceNodeModuleProceduralFunctionsRector: node_type_get_names() → entity_type.bundle.info service, node_get_type_label($node) → $node->getBundleEntity()->label() (11.3) - RemoveCacheExpireOverrideRector: remove cacheExpire() method overrides from CachePluginBase subclasses (11.4) - Config: template_preprocess_layout → LayoutDiscoveryThemeHooks::preprocessLayout via FunctionToServiceRector (11.3)
- RemoveRootFromConvertDbUrlRector: remove deprecated string $root arg from Database::convertDbUrlToConnectionInfo() (11.3) - ReplacePdoFetchConstantsRector: PDO::FETCH_* constants → FetchAs enum cases in Drupal DB API (11.2) - ReplaceSystemPerformanceGzipKeyRector: system.performance css.gzip/js.gzip config keys → css.compress/js.compress (11.4)
…e the tests folder
Co-authored-by: Matt Glaman <nmd.matt@gmail.com>
… sets Wires up 8 rector classes that had tests but no config entry, so they were never triggered when running drupal-rector against a project. - drupal-11.1: BlockContentTestBaseStringToArrayRector, MovePointerToMouseOverRector, ReplaceAddCachedDiscoveryMethodCallRector - drupal-11.2: RemoveCacheTagChecksumAssertionsRector, RemoveRootFromCreateConnectionOptionsFromUrlRector - drupal-11.4: CheckMarkupToProcessedTextRector, RemoveFilterTipsLongParamRector, SystemSortThemesRector
- Remove dangling /rector-type-check-review entry from README (skill file never existed) - Replace rector-type-specificity-checklist.md references in rector-qa with a direct find command; bulk mode no longer depends on missing file - Add Pass 5 (registration check) to rector-qa — verifies rector is wired into a config/drupal-11/*.php deprecation set - Add type-guard reminder to Step 6 template in digest-to-rector-prompt.md so isObjectType() guards are part of the generation step, not a post-hoc gate
…est files and fixtures to be consistent.
…allback refactorWithConfiguration mutated the incoming $node in place, then returned it. AbstractDrupalCoreRector::refactor reuses that same node to build the deprecated branch of createBcCallOnExpr, so both branches of DeprecationHelper::backwardsCompatibleCall ended up calling the renamed service ID — the old-Drupal fallback was lost. Clone before mutating, and add a fixture exercising BC wrapping so the regression cannot reappear silently.
…nt hint - rector-qa/SKILL.md: drop the dangling reference to rector-type-specificity-checklist.md (which was never shipped) in the bulk-mode description; describe the actual behaviour (walks src/). - rector-implement/SKILL.md: align argument-hint with the repos/ layout produced by setup-repos.sh instead of an absolute home path.
Introduces a Keep-a-Changelog-formatted CHANGELOG.md that: - Documents the upcoming 1.0.0-beta1 release in detail (highlights, the D10.3 and per-minor D11 deprecation rule tables, infrastructure / generic shared rectors / tooling subsections, changed deps, removed Rector 1 support, fixed bugs, compatibility matrix, and upgrade notes). - Backfills all 43 historical GitHub releases (0.21.2 down to 0.3.1) verbatim from the Releases page, with stray H1/H2 headings inside the release bodies demoted to H3 so the document's heading hierarchy stays consistent.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
This PR implements Drupal deprecation rules for drupal-rector, covering Drupal 10 and Drupal 11 (11.1–11.4). It adds 52 new Drupal 11 rector classes, 4 new Drupal 10 rector classes, and 2 new generic data-driven rectors, all wired into the per-version deprecation config files. Each rule targets a specific Drupal change record and includes type-guarded transformations and version-gating tests.
The work originated as an experiment converting drupal-digests AI-generated rules into fully drupal-rector-compliant implementations — validating the conversion workflow and tooling in the process.
Also worked on a better way to control if/how BC code paths are implemented.
This PR also removed rector 1 support. Which is a little before Drupal 10 EOL in august, but made life a lot easier.
Infrastructure improvements
Generic data-driven rectors
FunctionCallRemovalRector(src/Rector/Deprecation/) — removes calls to deprecated functions with no replacement; handles 11 deprecated functions across Drupal 11.2–11.4FunctionToFirstArgMethodRector— refactored tosrc/Rector/Deprecation/as a shared base for Drupal 8/9/10/11 useBC wrapping extended
Previously,
backwardsCompatibleCall()wrapping inAbstractDrupalCoreRectoronly applied when both old and new nodes were of matching types. Extended to cover allExprnode types so mixed-type rewrites (e.g. function call → method call) also get proper BC wrapping.Version-gating tests
Added DrupalRectorSettings::setDrupalVersion() (via static::getContainer()->make(DrupalRectorSettings::class)) for clean version-specific test scenarios. Replaces the previous namespaced-class \Drupal hack that was causing test brittleness.
DrupalRectorSettings is a container-managed service that centralises the runtime settings rectors need to make version-aware decisions. It holds three values: whether backwards-compatibility wrapping is enabled, the minimum Drupal core version the project still supports, and an optional Drupal version override.
Config-driven refactoring
Three custom constant-replacement rectors were replaced with
ConstantToClassConstantRectorconfiguration entries, reducing custom code:ReplaceRequirementSeverityConstantsRector→ configReplaceJsonApiFilterConstantsRector→ configReplaceNodeSetPreviewModeRectorfor the enum path → configTooling (
.claude/skills/)Adds three Claude Code skills used to drive the conversion workflow:
rector-discoverlists unimplemented drupal-digests rules by implementation phase; regeneratesdocs/rector-index.ymlwhen stalerector-implementAI prompt that converts a drupal-digests rule into a fully compliant rector class, test, fixture, and config entryrector-qaQA checklist and fixture expansion workflow for completed rectorsNew Drupal 11 rules
11.1
AliasManager::pathAliasWhitelistRebuild()→pathAliasPrefixListRebuild()(viaRenameMethodRectorconfig)ReplaceCommentManagerGetCountNewCommentsRector— replacesCommentManagerInterface::getCountNewComments()with a service call (issue #3543035)11.2
template_preprocess_{container,html,page,links,time,datetime_form,datetime_wrapper}()→ThemePreprocess*attribute hooks (DeprecatedFilterFunctionsRectorand related)CacheBackendInterface::invalidateAll()→deleteAll()StatementPrefetchIteratorFetchColumnRector—fetchColumn()→fetchField(), skipping PDO's native$columnarg formRemoveModuleHandlerAddModuleCallsRector— removes no-opaddModule()/addProfile()callsRemoveHandlerBaseDefineExtraOptionsRector— removes deprecateddefineExtraOptions()with no replacementReplaceAlphadecimalToIntNullRector—Number::alphadecimalToInt(null/'')→0LoadAllIncludesRector—ModuleHandler::loadAllIncludes()→ explicitforeach getModuleList() + loadInclude()loopRemoveCacheExpireOverrideRector— removes deprecatedCACHE_*constant override in settingsRemoveConfigSaveTrustedDataArgRector— strips the deprecated$trusted_dataarg fromConfig::save()ReplaceDateTimeRangeConstantsRector—DateTimeRangeItem::DATETIME_TYPE_*constants →DateTimeRangeItem::*FunctionCallRemovalRectorentries (removed deprecated theme preprocess and update manager functions)11.3
NodeMassUpdateRector(viaReplaceNodeModuleProceduralFunctionsRector) —node_mass_update()→NodeBulkUpdate::process()JSONAPI_FILTER_AMONG_*constants →JsonApiFilter::*(viaConstantToClassConstantRectorconfig, issue #3560657)StripMigrationDependenciesExpandArgRector— removes deprecated$expand_dependenciesargument11.4
FunctionToServiceRectorconfig for 29 deprecated procedural functions across 9 modules (issue numbers in config)RemoveLinkWidgetValidateTitleElementRector— validation moved to element-level, call removedRemoveAutomatedCronSubmitHandlerRector— removes deprecated$form['#submit'][] = 'automated_cron_settings_submit'DRUPAL_DISABLED/OPTIONAL/REQUIREDinNodeTypeInterface::setPreviewMode()→PreviewMode::*enum (viaConstantToClassConstantRectorconfig)ReplaceRecipeRunnerInstallModuleRector—RecipeRunner::installModules()→RecipeRunner::processRecipe()ReplaceEntityReferenceRecursiveLimitRector—EntityReferenceEntityFormatter::RECURSIVE_RENDER_LIMIT→ literal20RemoveUpdaterPostInstallMethodsRector— removes deprecatedpostInstall()/postUpdate()Updater callsReplaceSystemPerformanceGzipKeyRector—system.performancecss.gzip/js.gzipkeys →gzipReplaceViewsProceduralFunctionsRector—views_embed_view(),views_get_view_result()etc. → service calls11.x (multi-version)
NodeStorageDeprecatedMethodsRector—revisionIds()/userRevisionIds()/countDefaultLanguageRevisions()→ entity query chains (11.1)PluginBaseIsConfigurableRector—isConfigurable()→instanceof ConfigurableInterface(11.2)ReplaceSessionManagerDeleteRector—SessionManager::delete($uid)→UserSessionRepository::deleteByUid()(11.3)ReplaceEntityOriginalPropertyRector—$entity->original→getOriginal()/setOriginal(), withNullsafePropertyFetchsupport (11.1)ReplaceEditorLoadRector—editor_load()→entityTypeManager()->getStorage('editor')->load()(11.4)ReplaceThemeGetSettingRector—theme_get_setting()→ThemeSettingsProviderservice (11.3)ReplaceSessionWritesWithRequestSessionRector— direct$_SESSIONwrites →RequestSessionserviceReplaceUserSessionNamePropertyRector—$this->nameinUserSessionsubclasses →$this->getAccountName()(with$thisguard to prevent recursion)MigrateSqlGetMigrationPluginManagerRector—$this->getMigrationPluginManager()→$this->migrationPluginManagerproperty, scoped toDrupal\migrate\Plugin\migrate\id_map\SqlUseEntityTypeHasIntegerIdRector—$entityType->getKey('id') === 'nid'pattern →hasIntegerId()ReplaceNodeAddBodyFieldRector—node_add_body_field()→ direct field config APIReplaceNodeAccessViewAllNodesRector—node_access_view_all_nodes()→AccessResult::allowed()ReplaceFieldgroupToFieldsetRector— fieldgroup display component migrationReplaceLocaleConfigBatchFunctionsRector—locale_config_batch_refresh_name()etc. → service callsReplacePdoFetchConstantsRector—\PDO::FETCH_*constants in Drupal DB context →Fetch::*enum valuesReplaceJsonApiFilterConstantsRector→ (refactored toConstantToClassConstantRectorconfig)RemoveStateCacheSettingRector— removes$settings['state_cache'](permanently enabled since 11.0)RemoveModuleHandlerDeprecatedMethodsRector— other deprecated ModuleHandler methodsRemoveSetUriCallbackRector— removessetUriCallback()standalone and mid-chainRemoveRootFromConvertDbUrlRector— strips deprecated$rootarg fromDatabase::convertDbUrlToConnectionInfo()RemoveTrustDataCallRector,RemoveTwigNodeTransTagArgumentRector,RemoveFilterTipsLongParamRectorRemoveViewsRowCacheKeysRector,RenameStopProceduralHookScanRectorReplaceRequirementSeverityConstantsRector—REQUIREMENT_*globals →RequirementSeverity::*enumContentEntity/Deriver, locale translation files) viaRenameClassRectorconfigReplaceFileGetContentHeadersRector—file_get_content_headers($file)→$file->getDownloadHeaders()FilterFormatFunctionsToServiceRector,DeprecatedFilterFunctionsRector,FileManagedFileSubmitRector,MediaFilterFormatEditFormValidateRector,NodeAccessRebuildFunctionsRector,ErrorCurrentErrorHandlerRector,FileSystemBasenameToNativeRector,ReplaceTwigExtensionRectorNew Drupal 10 rules
ReplaceModuleHandlerGetNameRector—ModuleHandlerInterface::getName($module)→\Drupal::service('extension.list.module')->getName($module)(issue #3571063)ReplaceRebuildThemeDataRector—ThemeHandlerInterface::rebuildThemeData()→ThemeExtensionList::reset()->getList()ReplaceRequestTimeConstantRector—REQUEST_TIMEconstant →\Drupal::time()->getRequestTime()VersionedFunctionToServiceRector+VersionedFunctionToServiceConfiguration— version-gated variant ofFunctionToServiceRectorfor cases where the service name depends on the Drupal target versionTesting
no_changecaseself::/static::forms, method-call-as-argument, class-property usage, and unrelated-class no-change guards