Implement ParentEntityHandler plugin system for extensible entity support

Replace hardcoded entity type checks with a plugin-based architecture using
PHP 8 attributes. This allows adding new parent entity types without modifying
core module files.

Changes:
- Add ParentEntityHandler attribute, interface, base class, and manager
- Create built-in handlers for taxonomy_term, user, and node entities
- Move Group support to site_structure_group submodule (fixes class not found
  error when Group module is not installed)
- Refactor SiteStructureSettingsForm to use handler manager
- Refactor SiteStructureMenuBlock to use handler manager
- Refactor SectionBreadcrumbBuilder to use handler manager
- Update site_structure.module to use handler manager for clearsSiteSection
- Update documentation and translations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 08:35:04 -03:00
parent 43fa9208a9
commit 0c8f0fc778
17 changed files with 1153 additions and 117 deletions

View File

@@ -276,6 +276,15 @@ site_structure/
│ └── pt-br.po # Portuguese (Brazil) translation
├── src/
│ ├── Attribute/
│ │ └── ParentEntityHandler.php # Plugin attribute definition
│ │
│ ├── ParentEntityHandler/
│ │ ├── ParentEntityHandlerInterface.php # Handler interface
│ │ ├── ParentEntityHandlerManagerInterface.php # Manager interface
│ │ ├── ParentEntityHandlerBase.php # Base implementation
│ │ └── ParentEntityHandlerManager.php # Plugin manager
│ │
│ ├── Breadcrumb/
│ │ └── SectionBreadcrumbBuilder.php
│ │
@@ -283,8 +292,19 @@ site_structure/
│ │ └── SiteStructureSettingsForm.php
│ │
│ └── Plugin/
── Block/
└── SiteStructureMenuBlock.php # Dynamic menu block
── Block/
└── SiteStructureMenuBlock.php # Dynamic menu block
│ │
│ └── ParentEntityHandler/ # Built-in handlers
│ ├── TaxonomyTermHandler.php # taxonomy_term handler
│ ├── UserHandler.php # user handler
│ └── NodeHandler.php # node handler
├── modules/
│ └── site_structure_group/ # Group integration submodule
│ ├── site_structure_group.info.yml
│ └── src/Plugin/ParentEntityHandler/
│ └── GroupHandler.php # group handler
└── docs/
└── DESIGN.md # This document
@@ -358,16 +378,81 @@ site_structure/
---
## Parent Entity Handler Plugin System
The module uses a plugin system to support different entity types as parents for content_page nodes. This allows for extensibility without modifying the core module.
### Architecture
The plugin system consists of:
1. **Attribute**: `Drupal\site_structure\Attribute\ParentEntityHandler` - PHP 8 attribute for defining handlers
2. **Interface**: `ParentEntityHandlerInterface` - Contract for all handlers
3. **Base class**: `ParentEntityHandlerBase` - Common implementation
4. **Manager**: `ParentEntityHandlerManager` - Plugin discovery and aggregation
### Built-in Handlers
| Handler | Entity Type | Clears Site Section | Sort Field | Bundle Restrictions |
|---------|-------------|---------------------|------------|---------------------|
| TaxonomyTermHandler | taxonomy_term | No | name | site_section |
| UserHandler | user | Yes | name | - |
| NodeHandler | node | No | title | content_page, section_page |
### Creating Custom Handlers
To add support for a new entity type, create a handler plugin:
```php
<?php
namespace Drupal\my_module\Plugin\ParentEntityHandler;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\site_structure\Attribute\ParentEntityHandler;
use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerBase;
#[ParentEntityHandler(
id: 'my_entity',
label: new TranslatableMarkup('My Entities'),
entity_type_id: 'my_entity',
clears_site_section: FALSE,
sort_field: 'title',
)]
class MyEntityHandler extends ParentEntityHandlerBase {
// Override methods as needed
}
```
### Handler Attributes
| Attribute | Type | Description |
|-----------|------|-------------|
| `id` | string | Unique plugin ID |
| `label` | TranslatableMarkup | Human-readable label |
| `entity_type_id` | string | Entity type this handler manages |
| `provider_module` | string|null | Module required for availability |
| `clears_site_section` | bool | Whether to clear field_site_section |
| `sort_field` | string | Field for sorting entities |
| `route_parameter` | string|null | Route parameter name (defaults to entity_type_id) |
| `bundle_restrictions` | array | Specific bundles to handle |
| `weight` | int | Handler priority (lower = first) |
---
## Group Integration
The module supports the Group module for content organization:
Group support is provided via the `site_structure_group` submodule, which adds a handler for group entities. This submodule requires the Group module.
**Features**:
- Content pages can have groups as parent entities
- When a content_page has a group as parent, the context is the group itself
- Breadcrumbs show: Home > Group Name > Parent Nodes > Current Page
- `field_site_section` is cleared for group-parented content (context is the group)
- Per-section permissions can be implemented via Groups
**Installation**: Enable the `site_structure_group` submodule after installing the Group module.
**Configuration**: Enable group types in the settings form at `/admin/config/local-modules/site-structure`
---
@@ -394,3 +479,4 @@ The module supports the Group module for content organization:
| 1.1.0 | - | Added dynamic_entity_reference support for multi-type parents |
| 1.2.0 | - | Added user and group entity support as parent types |
| 1.3.0 | - | Added Site Structure Menu block for dynamic hierarchical navigation |
| 2.0.0 | - | Refactored to plugin system for parent entity handlers. Group support moved to submodule. |