[6.x] Registries (widget types, field types, ...)#19270
Open
riasvdv wants to merge 22 commits into
Open
Conversation
📚 Storybook previews@craftcms/ui — open Storybook No changed components detected in this Storybook. resources/js — open Storybook No changed components detected in this Storybook. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR migrates multiple Craft CMS extension points from “resolve-time events” to registry-based APIs, making registries the primary source of truth while preserving Yii2-adapter compatibility via explicit legacy-finalization steps.
Changes:
- Introduces a shared
TypeRegistryfoundation and new registries for key extension points (elements, fields, widgets, utilities, filesystem types, image transformers, template roots/cache collectors, GraphQL directives/argument handlers, permissions, system messages). - Refactors core services and plugin concerns to register/resolve via registries instead of dispatching “*Resolving” events.
- Updates Yii2-adapter bridges and adds/updates tests to validate modern+legacy interoperability and registry semantics.
Reviewed changes
Copilot reviewed 122 out of 122 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| CHANGELOG-WIP.md | Updates changelog entries to reference registry APIs instead of resolving events. |
| CHANGELOG.md | Updates changelog entries to reference registry APIs instead of resolving events. |
| src/Component/TypeRegistry.php | Adds a reusable base registry with identity/protection/validation semantics. |
| src/Dashboard/Dashboard.php | Switches widget type resolution to WidgetTypeRegistry. |
| src/Dashboard/Events/WidgetTypesResolving.php | Removes the widget-type resolving event (replaced by registry). |
| src/Dashboard/WidgetTypeRegistry.php | Adds widget-type registry backed by TypeRegistry. |
| src/Element/ElementTypeRegistry.php | Adds element-type registry backed by TypeRegistry. |
| src/Element/Elements.php | Switches element type resolution from events to ElementTypeRegistry. |
| src/Element/Events/ElementTypesResolving.php | Removes the element-types resolving event (replaced by registry). |
| src/Field/Events/FieldTypesResolving.php | Removes the field-types resolving event (replaced by registry). |
| src/Field/Events/LinkTypesResolving.php | Removes the link-types resolving event (replaced by registry). |
| src/Field/FieldTypeRegistry.php | Adds field-type registry backed by TypeRegistry. |
| src/Field/Fields.php | Switches field type resolution from events to FieldTypeRegistry. |
| src/Field/Link.php | Switches link type resolution to LinkTypeRegistry. |
| src/Field/LinkTypeRegistry.php | Adds link-type registry backed by TypeRegistry with protected URL identity. |
| src/Filesystem/Events/FilesystemTypesResolving.php | Removes the filesystem-types resolving event (replaced by registry). |
| src/Filesystem/FilesystemTypeRegistry.php | Adds filesystem-type registry backed by TypeRegistry. |
| src/Filesystem/Filesystems.php | Switches filesystem type resolution from events to FilesystemTypeRegistry. |
| src/Gql/ArgumentManager.php | Switches argument handlers from event resolution to GqlArgumentHandlerRegistry, adds factory support and validation. |
| src/Gql/Events/GqlArgumentHandlersResolving.php | Removes the argument-handlers resolving event (replaced by registry). |
| src/Gql/Events/GqlDirectivesResolving.php | Removes the directives resolving event (replaced by registry). |
| src/Gql/Gql.php | Switches directive loading from events to GqlDirectiveRegistry. |
| src/Gql/GqlArgumentHandlerRegistry.php | Adds argument-handler registry supporting class handlers and factories. |
| src/Gql/GqlDirectiveRegistry.php | Adds directive registry with schema-scope filtering and reserved identity protection. |
| src/Http/Controllers/Gql/SchemasController.php | Updates permission-group construction to include stable handles. |
| src/Image/Events/ImageTransformersResolving.php | Removes the image-transformers resolving event (replaced by registry). |
| src/Image/ImageTransformerRegistry.php | Adds image-transformer registry backed by TypeRegistry. |
| src/Image/ImageTransforms.php | Switches transformer type resolution from events to ImageTransformerRegistry. |
| src/Plugin/Concerns/HasElementTypes.php | Registers plugin element types via ElementTypeRegistry. |
| src/Plugin/Concerns/HasFieldtypes.php | Registers plugin field types via FieldTypeRegistry. |
| src/Plugin/Concerns/HasPermissions.php | Registers plugin permission groups via PermissionGroupRegistry instead of resolving event listeners. |
| src/Plugin/Concerns/HasUtilities.php | Registers plugin utilities via UtilityTypeRegistry. |
| src/Plugin/Concerns/HasViews.php | Registers plugin CP template roots via TemplateRootRegistry. |
| src/Plugin/Concerns/HasWidgets.php | Registers plugin widgets via WidgetTypeRegistry. |
| src/Support/Facades/HtmlSanitizers.php | Updates @see reference to local class name. |
| src/Support/Facades/Template.php | Updates @see reference to local class name. |
| src/SystemMessage/Events/SystemMessagesResolving.php | Removes system-messages resolving event (replaced by registry). |
| src/SystemMessage/SystemMessageRegistry.php | Adds system-message registry with container-invoked factories and validation. |
| src/SystemMessage/SystemMessages.php | Switches default message resolution to SystemMessageRegistry; scopes caching per locale scope. |
| src/User/Data/PermissionGroup.php | Makes permission-group handle an explicit constructor field (stable identity). |
| src/User/Events/UserPermissionsResolving.php | Removes permissions resolving event (replaced by registry). |
| src/User/PermissionGroupRegistry.php | Adds registry for permission-group providers with validation and snapshot behavior. |
| src/User/UserPermissions.php | Applies registry providers to core permission groups and assigns stable handles to core groups. |
| src/Utility/Events/UtilitiesResolving.php | Removes utilities resolving event (replaced by registry). |
| src/Utility/Utilities.php | Switches utility type resolution to UtilityTypeRegistry. |
| src/Utility/UtilityTypeRegistry.php | Adds utility-type registry with config/edition/volume-based filtering and reserved identities. |
| src/View/Events/CpTemplateRootsResolving.php | Removes CP template-roots resolving event (replaced by registry). |
| src/View/Events/SiteTemplateRootsResolving.php | Removes site template-roots resolving event (replaced by registry). |
| src/View/Events/TemplateCacheCollectorsResolving.php | Removes template-cache collector resolving event (replaced by registry). |
| src/View/TemplateCacheCollectorRegistry.php | Adds template-cache collector registry (core collectors + extensibility). |
| src/View/TemplateCaches.php | Switches collector discovery from events to TemplateCacheCollectorRegistry. |
| src/View/TemplateMode.php | Switches templateRoots() to read from TemplateRootRegistry. |
| src/View/TemplateRootRegistry.php | Adds registry for template roots keyed by mode+namespace with ordering and snapshots. |
| src/View/ViewServiceProvider.php | Adjusts template-root integration timing to bootstrap phase (BootProviders). |
| tests/Feature/Dashboard/DashboardTest.php | Updates dashboard tests to register widgets via registry. |
| tests/Feature/Element/ElementTypesTest.php | Updates element type tests to use registry and handle dynamic changes. |
| tests/Feature/Field/FieldsTest.php | Updates field type tests to use registry (including provider-based registration). |
| tests/Feature/Filesystem/FilesystemsTest.php | Updates filesystem type tests to use registry. |
| tests/Feature/Gql/ArgumentManagerTest.php | Updates argument manager tests for registry handlers, factories, and binding behavior. |
| tests/Feature/Gql/GqlTest.php | Updates directive tests to use GqlDirectiveRegistry and verify schema caching behavior. |
| tests/Feature/Http/Controllers/Elements/DeleteElementsControllerTest.php | Updates Elements service test doubles for new constructor dependency (ElementTypeRegistry). |
| tests/Feature/Http/Controllers/Elements/SaveElementControllerTest.php | Updates Elements service test doubles for new constructor dependency (ElementTypeRegistry). |
| tests/Feature/Http/Controllers/Elements/SaveElementIndexElementsControllerTest.php | Updates Elements service test doubles for new constructor dependency (ElementTypeRegistry). |
| tests/Feature/Http/Controllers/Elements/SearchControllerTest.php | Updates Elements service test doubles for new constructor dependency (ElementTypeRegistry). |
| tests/Feature/Http/Controllers/MatrixControllerTest.php | Updates Elements service test double for new constructor dependency (ElementTypeRegistry). |
| tests/Feature/Http/Controllers/SiteRouteControllerTest.php | Updates site template root setup to use TemplateRootRegistry. |
| tests/Feature/Image/ImageTransformsTest.php | Updates transformer tests to use ImageTransformerRegistry. |
| tests/Feature/SystemMessage/SystemMessagesTest.php | Updates system message tests to use SystemMessageRegistry and verify locale scoping. |
| tests/Feature/User/UserPermissionsTest.php | Adds coverage for permission registry register/remove and stable handles. |
| tests/Feature/Utility/UtilitiesTest.php | Updates utility tests to use UtilityTypeRegistry and validate filtering behavior. |
| tests/Unit/Field/LinkTest.php | Adds unit coverage for link types reading from LinkTypeRegistry. |
| tests/Unit/Gql/GqlArgumentHandlerRegistryTest.php | Adds unit coverage for handler registry ordering, updates, and validation. |
| tests/Unit/Plugin/Concerns/HasElementTypesTest.php | Updates plugin element type boot behavior tests to use registry-backed services. |
| tests/Unit/Plugin/Concerns/HasFieldtypesTest.php | Updates plugin field type boot behavior tests to use registry-backed services. |
| tests/Unit/Plugin/Concerns/HasPermissionsTest.php | Updates plugin permissions boot behavior tests to use PermissionGroupRegistry. |
| tests/Unit/Plugin/Concerns/HasUtilitiesTest.php | Updates plugin utilities boot behavior tests to use registry-backed services. |
| tests/Unit/Plugin/Concerns/HasViewsTest.php | Updates plugin view root tests to rely on TemplateMode::templateRoots()/registry. |
| tests/Unit/Plugin/Concerns/HasWidgetsTest.php | Updates plugin widget tests to use registry-backed dashboard service. |
| tests/Unit/SystemMessage/SystemMessageRegistryTest.php | Adds unit coverage for SystemMessageRegistry behavior and validation. |
| tests/Unit/Twig/TemplateResolverTest.php | Updates template resolver tests to register CP roots via TemplateRootRegistry. |
| tests/Unit/User/PermissionGroupRegistryTest.php | Adds unit coverage for permission group provider registry semantics and snapshots. |
| tests/Unit/View/TemplateCachesTest.php | Updates template cache tests to register collectors via registry. |
| tests/Unit/View/TemplateModeTest.php | Removes event-dispatch assertions now that template roots are registry-backed. |
| tests/Unit/View/TemplateRootRegistryTest.php | Adds unit coverage for TemplateRootRegistry behavior across modes and snapshots. |
| tests/Unit/View/TwigEngineTest.php | Updates TwigEngine test to register CP template roots via TemplateRootRegistry. |
| yii2-adapter/constants/Field/Concerns/LegacyFieldConstants.php | Updates legacy link-type bridging to use LinkTypeRegistry and finalize-style registration. |
| yii2-adapter/legacy/events/RegisterComponentTypesEvent.php | Updates deprecation messaging to point to registries. |
| yii2-adapter/legacy/events/RegisterEmailMessagesEvent.php | Updates deprecation messaging to point to SystemMessageRegistry. |
| yii2-adapter/legacy/events/RegisterGqlArgumentHandlersEvent.php | Updates handler typing/docs for closures and points deprecation to registry API. |
| yii2-adapter/legacy/events/RegisterGqlDirectivesEvent.php | Updates deprecation messaging to point to GqlDirectiveRegistry. |
| yii2-adapter/legacy/events/RegisterTemplateRootsEvent.php | Updates deprecation messaging to point to TemplateRootRegistry. |
| yii2-adapter/legacy/events/RegisterUserPermissionsEvent.php | Updates deprecation messaging to point to PermissionGroupRegistry. |
| yii2-adapter/legacy/services/Dashboard.php | Moves legacy widget registration bridging into finalize-style registry reconciliation. |
| yii2-adapter/legacy/services/Elements.php | Moves legacy element type registration bridging into finalize-style registry reconciliation. |
| yii2-adapter/legacy/services/Fields.php | Moves legacy field type registration bridging into finalize-style registry reconciliation. |
| yii2-adapter/legacy/services/Fs.php | Moves legacy filesystem type registration bridging into finalize-style registry reconciliation. |
| yii2-adapter/legacy/services/Gql.php | Moves legacy directive registration bridging into finalize-style registry reconciliation. |
| yii2-adapter/legacy/services/ImageTransforms.php | Moves legacy transformer type registration bridging into finalize-style registry reconciliation. |
| yii2-adapter/legacy/services/SystemMessages.php | Removes legacy system-message resolving bridge in favor of registry-based adapter implementation. |
| yii2-adapter/legacy/services/UserPermissions.php | Bridges legacy permissions via PermissionGroupRegistry provider + resets modern cache. |
| yii2-adapter/legacy/services/Utilities.php | Moves legacy utility registration bridging into finalize-style registry reconciliation. |
| yii2-adapter/legacy/web/View.php | Moves legacy template-root bridging into finalize-style registry reconciliation. |
| yii2-adapter/src/DeprecatedConcepts.php | Registers deprecated-concept-provided types via registries rather than resolving events. |
| yii2-adapter/src/Event/EventCompatibility.php | Switches adapter boot bridges to register into registries and adds explicit finalize step. |
| yii2-adapter/src/Event/LegacyGqlEvents.php | Adds registry-based finalize for legacy GQL argument handlers; removes resolve-time bridge. |
| yii2-adapter/src/LegacyApp.php | Ensures legacy finalize registration events run after boot when installed; resets deprecated support flags. |
| yii2-adapter/src/SystemMessage/LegacySystemMessageRegistry.php | Adds adapter wrapper to expose registry messages to legacy Yii event transforms with locale scoping/caching. |
| yii2-adapter/src/Yii2ServiceProvider.php | Wraps SystemMessageRegistry with legacy adapter and registers base site template root via registry. |
| yii2-adapter/tests-laravel/Fixtures/LegacyPlugin/templates/index.twig | Adds fixture template for legacy plugin template-root tests. |
| yii2-adapter/tests-laravel/Gql/LegacyGqlCompatibilityTest.php | Expands adapter test coverage for directive/argument handler bridging behavior. |
| yii2-adapter/tests-laravel/Http/LegacyActionRoutingTest.php | Updates CP routing test to register template roots via registry. |
| yii2-adapter/tests-laravel/Http/LegacySiteTemplateRoutingTest.php | Removes Once::flush() dependency now that template roots are registry-backed. |
| yii2-adapter/tests-laravel/Legacy/DeprecatedConceptRegistrationCompatibilityTest.php | Adds coverage for deprecated-concept registrations finalized through registries. |
| yii2-adapter/tests-laravel/Legacy/PermissionRegistryCompatibilityTest.php | Adds coverage for permission registry/legacy handle stability and rebuild behavior. |
| yii2-adapter/tests-laravel/Legacy/PluginLifecycleCompatibilityTest.php | Adds coverage ensuring legacy registrations finalize after legacy init + modern boot and propagate to view finder hints. |
| yii2-adapter/tests-laravel/Legacy/RegistrationRegistryCompatibilityTest.php | Adds coverage for system messages, permissions, and template roots bridging via registries. |
| yii2-adapter/tests-laravel/Legacy/TypeRegistryCompatibilityTest.php | Adds coverage for legacy type registration events applying to modern registries and identity rules. |
| yii2-adapter/tests-laravel/View/RegisterTemplateCacheCollectorsTest.php | Updates adapter test to assert collector registration via registry. |
| yii2-adapter/tests/unit/gql/ArgumentHandlerTest.php | Updates unit test to register argument handlers via GqlArgumentHandlerRegistry. |
| yii2-adapter/tests/unit/mail/MailerTest.php | Removes commented event-based system-message registration snippet (obsolete with registries). |
| yii2-adapter/tests/unit/web/ViewTest.php | Updates template root tests to populate TemplateRootRegistry instead of listening for resolving events. |
riasvdv
marked this pull request as ready for review
July 23, 2026 14:09
riasvdv
marked this pull request as draft
July 24, 2026 07:33
riasvdv
force-pushed
the
feature/registries
branch
from
July 25, 2026 07:45
0941a85 to
b431c9c
Compare
# Conflicts: # tests/Feature/Auth/Auth/Auth2faMethodsTest.php
riasvdv
marked this pull request as ready for review
July 25, 2026 09:18
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.
Description
Replaces the listed Laravel registration events with explicit, validated catalogs and service registration methods. Plugins register extensions during
boot()instead of mutating a resolving event when the catalog is read.Legacy Craft/Yii registration events remain supported by
craftcms/yii2-adapterand are reconciled after legacy plugins initialize and modern plugins boot.What changed
CraftCms\Cms\Component\TypeRegistryas the shared base for validated class-string catalogs.craft:resave:alldiscover registered Artisan commands in thecraft:resavenamespace.Type catalogs
The following event replacements use validated class-string catalogs:
CraftCms\Cms\Auth\Events\AuthMethodsResolvingCraftCms\Cms\Auth\AuthMethods::register()CraftCms\Cms\Element\Events\ElementTypesResolvingCraftCms\Cms\Element\ElementTypes::register()CraftCms\Cms\Field\Events\FieldTypesResolvingCraftCms\Cms\Field\FieldTypes::register()CraftCms\Cms\Field\Events\NestedEntryFieldTypesResolvingCraftCms\Cms\Field\NestedEntryFieldTypes::register()CraftCms\Cms\Field\Events\LinkTypesResolvingCraftCms\Cms\Field\LinkTypes::register()CraftCms\Cms\Dashboard\Events\WidgetTypesResolvingCraftCms\Cms\Dashboard\WidgetTypes::register()CraftCms\Cms\Filesystem\Events\FilesystemTypesResolvingCraftCms\Cms\Filesystem\FilesystemTypes::register()CraftCms\Cms\Image\Events\ImageTransformersResolvingCraftCms\Cms\Image\ImageTransformers::register()CraftCms\Cms\Utility\Events\UtilitiesResolvingCraftCms\Cms\Utility\UtilityTypes::register()CraftCms\Cms\Gql\Events\GqlDirectivesResolvingCraftCms\Cms\Gql\GqlDirectives::register()CraftCms\Cms\Gql\Events\GqlQueriesResolvingCraftCms\Cms\Gql\GqlQueries::register()CraftCms\Cms\Gql\Events\GqlMutationsResolvingCraftCms\Cms\Gql\GqlMutations::register()CraftCms\Cms\Gql\Events\GqlTypesResolvingCraftCms\Cms\Gql\GqlTypes::register()CraftCms\Cms\View\Events\TemplateCacheCollectorsResolvingCraftCms\Cms\View\TemplateCacheCollectors::register()Register types by injecting the concrete catalog or service:
Types can be removed explicitly:
There is no
replace()API. Remove the old type and register the new type explicitly. Protected core types cannot be removed: theurllink type and thedependenciesandresourcestemplate cache collectors.Each catalog validates its contract before changing state. Catalogs with domain identifiers also reject identity collisions, including utility IDs, link type IDs, GraphQL directive/type names, element reference handles, and template-cache collector keys. GraphQL directive names reserved by the GraphQL specification cannot be registered.
types()returns a snapshot. Modify the catalog throughregister()orremove(), not by mutating the returned collection.Asset file kinds
CraftCms\Cms\Asset\Events\AssetFileKindsResolvingis replaced byCraftCms\Cms\Asset\AssetFileKinds:Definitions may be arrays or container-invoked closures.
remove()removes custom or built-in kinds by name.GraphQL argument handlers
CraftCms\Cms\Gql\Events\GqlArgumentHandlersResolvingis replaced byCraftCms\Cms\Gql\GqlArguments:Handlers may be
ArgumentHandlerInterfaceclass names or container-invoked closures. Remove handlers by argument name withremove().Native field-layout fields
CraftCms\Cms\FieldLayout\Events\NativeFieldsResolvingis replaced by keyed providers onCraftCms\Cms\FieldLayout\NativeFields:Providers run in registration order, receive the result from earlier providers, and can receive additional container-resolved dependencies. Remove providers by handle with
remove().Control panel settings
RegisterCpSettingsandRegisterReadonlyCpSettingsare replaced by methods onCraftCms\Cms\Cp\Settings:Providers are container-invoked when the settings navigation is built.
remove($section, ...$handles)removes normal and read-only settings.System messages
CraftCms\Cms\SystemMessage\Events\SystemMessagesResolvingis replaced by methods onCraftCms\Cms\SystemMessage\SystemMessages:Factories are container-invoked when messages are requested and must return a
SystemMessagewhose key matches the registered key. Remove messages by key withremove().User permissions
CraftCms\Cms\User\Events\UserPermissionsResolvingis replaced by methods onCraftCms\Cms\User\UserPermissions:Factories are container-invoked whenever the permission catalog is rebuilt and may return
null. Registration handles and resolvedPermissionGrouphandles must match and remain unique. Handles are explicit and are no longer derived from translated headings. Remove groups withremovePermissionGroups().Template roots
CpTemplateRootsResolvingandSiteTemplateRootsResolvingare replaced byCraftCms\Cms\View\TemplateRoots:Roots are kept separately for
TemplateMode::CpandTemplateMode::Site. Repeated paths are deduplicated while preserving registration order. Remove namespaces per mode withremove().Cache-clearing options
ClearCachesOptionsResolvingandClearCachesTagOptionsResolvingare replaced by static registration methods onCraftCms\Cms\Utility\Utilities\ClearCaches:Cache option definitions and tag labels may also be container-invoked closures.
Migration tracks
CraftCms\Cms\Database\Events\MigratorsResolvingis replaced byCraftCms\Cms\Database\Commands\MigrateCommand::registerMigrator():Registered migrators participate in normal track filtering and migration execution.
Resave commands
CraftCms\Cms\Element\Events\ElementResaveCommandsResolvingis removed. Register a normal Laravel command in thecraft:resavenamespace instead.craft:resave:alldiscovers registeredcraft:resave:*commands directly from Artisan and excludes itself.Registration timing
Register extensions during a plugin or service provider
boot()method. The removed registration events are no longer redispatched when catalogs are read.Resolution remains lazy where runtime context matters:
isSelectable()when utility types are requested.Legacy plugin compatibility
Deprecated Yii registration events remain available through
craftcms/yii2-adapter.urllink type remains last.$_SERVER["argv"]after execution.