diff --git a/config/install/field.field.node.content_page.field_parent_page.yml b/config/install/field.field.node.content_page.field_parent_page.yml
index 03a09f5..563d7fd 100644
--- a/config/install/field.field.node.content_page.field_parent_page.yml
+++ b/config/install/field.field.node.content_page.field_parent_page.yml
@@ -5,7 +5,7 @@ dependencies:
- field.storage.node.field_parent_page
- node.type.content_page
- node.type.section_page
- - taxonomy.vocabulary.site_section
+ - taxonomy.vocabulary.site_sections
module:
- dynamic_entity_reference
id: node.content_page.field_parent_page
@@ -36,7 +36,7 @@ settings:
handler: 'default:taxonomy_term'
handler_settings:
target_bundles:
- site_section: site_section
+ site_sections: site_sections
sort:
field: name
direction: asc
diff --git a/config/install/field.field.node.content_page.field_site_section.yml b/config/install/field.field.node.content_page.field_site_section.yml
index 8bee4e5..9072e4f 100644
--- a/config/install/field.field.node.content_page.field_site_section.yml
+++ b/config/install/field.field.node.content_page.field_site_section.yml
@@ -4,7 +4,7 @@ dependencies:
config:
- field.storage.node.field_site_section
- node.type.content_page
- - taxonomy.vocabulary.site_section
+ - taxonomy.vocabulary.site_sections
module:
- taxonomy
id: node.content_page.field_site_section
@@ -21,7 +21,7 @@ settings:
handler: 'default:taxonomy_term'
handler_settings:
target_bundles:
- site_section: site_section
+ site_sections: site_sections
sort:
field: name
direction: asc
diff --git a/config/install/field.field.node.section_page.field_site_section.yml b/config/install/field.field.node.section_page.field_site_section.yml
index e6b3047..a556115 100644
--- a/config/install/field.field.node.section_page.field_site_section.yml
+++ b/config/install/field.field.node.section_page.field_site_section.yml
@@ -4,7 +4,7 @@ dependencies:
config:
- field.storage.node.field_site_section
- node.type.section_page
- - taxonomy.vocabulary.site_section
+ - taxonomy.vocabulary.site_sections
module:
- taxonomy
id: node.section_page.field_site_section
@@ -21,7 +21,7 @@ settings:
handler: 'default:taxonomy_term'
handler_settings:
target_bundles:
- site_section: site_section
+ site_sections: site_sections
sort:
field: name
direction: asc
diff --git a/config/install/pathauto.pattern.content_page.yml b/config/install/pathauto.pattern.content_page.yml
index 71b8884..900accd 100644
--- a/config/install/pathauto.pattern.content_page.yml
+++ b/config/install/pathauto.pattern.content_page.yml
@@ -3,7 +3,7 @@ status: true
dependencies:
module:
- node
- - site_structure
+ - structural_pages
id: content_page
label: 'Content Page'
type: 'canonical_entities:node'
diff --git a/config/install/pathauto.pattern.section_page.yml b/config/install/pathauto.pattern.section_page.yml
index a863f86..183b492 100644
--- a/config/install/pathauto.pattern.section_page.yml
+++ b/config/install/pathauto.pattern.section_page.yml
@@ -3,7 +3,7 @@ status: true
dependencies:
module:
- node
- - site_structure
+ - structural_pages
id: section_page
label: 'Section Page'
type: 'canonical_entities:node'
diff --git a/config/install/pathauto.pattern.site_section_term.yml b/config/install/pathauto.pattern.site_sections_term.yml
similarity index 76%
rename from config/install/pathauto.pattern.site_section_term.yml
rename to config/install/pathauto.pattern.site_sections_term.yml
index 3c1d1cf..7a926be 100644
--- a/config/install/pathauto.pattern.site_section_term.yml
+++ b/config/install/pathauto.pattern.site_sections_term.yml
@@ -2,10 +2,10 @@ langcode: en
status: true
dependencies:
module:
- - site_structure
+ - structural_pages
- taxonomy
-id: site_section_term
-label: 'Site Section Term'
+id: site_sections_term
+label: 'Site Sections Term'
type: 'canonical_entities:taxonomy_term'
pattern: '[term:hierarchy-path]'
selection_logic: and
@@ -16,5 +16,5 @@ selection_criteria:
context_mapping:
taxonomy_term: taxonomy_term
bundles:
- site_section: site_section
+ site_sections: site_sections
weight: 0
diff --git a/config/install/site_structure.settings.yml b/config/install/structural_pages.settings.yml
similarity index 89%
rename from config/install/site_structure.settings.yml
rename to config/install/structural_pages.settings.yml
index 0fc0874..a1e90bf 100644
--- a/config/install/site_structure.settings.yml
+++ b/config/install/structural_pages.settings.yml
@@ -4,7 +4,7 @@ allowed_parent_targets:
- entity_type: node
bundle: section_page
- entity_type: taxonomy_term
- bundle: site_section
+ bundle: site_sections
- entity_type: user
bundle: user
- entity_type: group
diff --git a/config/install/taxonomy.vocabulary.site_section.yml b/config/install/taxonomy.vocabulary.site_sections.yml
similarity index 74%
rename from config/install/taxonomy.vocabulary.site_section.yml
rename to config/install/taxonomy.vocabulary.site_sections.yml
index e6ceddd..c4e459f 100644
--- a/config/install/taxonomy.vocabulary.site_section.yml
+++ b/config/install/taxonomy.vocabulary.site_sections.yml
@@ -1,7 +1,7 @@
langcode: en
status: true
dependencies: { }
-name: 'Site Section'
-vid: site_section
+name: 'Site Sections'
+vid: site_sections
description: 'Main hierarchical structure for site organization.'
weight: 0
diff --git a/config/install/views.view.child_pages.yml b/config/install/views.view.child_pages.yml
index c3566be..dc5c878 100644
--- a/config/install/views.view.child_pages.yml
+++ b/config/install/views.view.child_pages.yml
@@ -240,7 +240,7 @@ display:
display_options:
display_extenders: { }
block_description: 'Child Pages'
- block_category: 'Site Structure'
+ block_category: 'Structural Pages'
cache_metadata:
max-age: -1
contexts:
diff --git a/config/schema/site_structure.schema.yml b/config/schema/structural_pages.schema.yml
similarity index 83%
rename from config/schema/site_structure.schema.yml
rename to config/schema/structural_pages.schema.yml
index fcd2b66..8026e38 100644
--- a/config/schema/site_structure.schema.yml
+++ b/config/schema/structural_pages.schema.yml
@@ -1,6 +1,6 @@
-site_structure.settings:
+structural_pages.settings:
type: config_object
- label: 'Site Structure settings'
+ label: 'Structural Pages settings'
mapping:
allowed_parent_targets:
type: sequence
diff --git a/css/site-structure-menu.css b/css/structural-pages-menu.css
similarity index 52%
rename from css/site-structure-menu.css
rename to css/structural-pages-menu.css
index b0f3521..670a99a 100644
--- a/css/site-structure-menu.css
+++ b/css/structural-pages-menu.css
@@ -1,45 +1,45 @@
/**
* @file
- * Styles for the site structure menu block.
+ * Styles for the structural pages menu block.
*/
-.site-structure-menu {
+.structural-pages-menu {
font-size: 0.9rem;
}
-.site-structure-menu__title {
+.structural-pages-menu__title {
font-size: 1.1rem;
margin-bottom: 0.75rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #ddd;
}
-.site-structure-menu__title a {
+.structural-pages-menu__title a {
text-decoration: none;
color: inherit;
}
-.site-structure-menu__title a:hover {
+.structural-pages-menu__title a:hover {
text-decoration: underline;
}
-.site-structure-menu__list {
+.structural-pages-menu__list {
list-style: none;
margin: 0;
padding: 0;
}
-.site-structure-menu__list--level-2,
-.site-structure-menu__list--level-3,
-.site-structure-menu__list--level-4 {
+.structural-pages-menu__list--level-2,
+.structural-pages-menu__list--level-3,
+.structural-pages-menu__list--level-4 {
padding-left: 1rem;
}
-.site-structure-menu__item {
+.structural-pages-menu__item {
margin: 0.25rem 0;
}
-.site-structure-menu__link {
+.structural-pages-menu__link {
display: block;
padding: 0.25rem 0.5rem;
text-decoration: none;
@@ -48,16 +48,16 @@
transition: background-color 0.15s ease;
}
-.site-structure-menu__link:hover {
+.structural-pages-menu__link:hover {
background-color: #f5f5f5;
text-decoration: none;
}
-.site-structure-menu__link--active-trail {
+.structural-pages-menu__link--active-trail {
font-weight: 600;
color: #0073bd;
}
-.site-structure-menu__item--active-trail > .site-structure-menu__link {
+.structural-pages-menu__item--active-trail > .structural-pages-menu__link {
background-color: #e8f4fc;
}
diff --git a/docs/DESIGN.md b/docs/DESIGN.md
index b9a4533..e869604 100644
--- a/docs/DESIGN.md
+++ b/docs/DESIGN.md
@@ -1,8 +1,8 @@
-# Site Structure - Design Document
+# Structural Pages - Design Document
## Overview
-The `site_structure` module implements a hierarchical editorial structure and contextual navigation for institutional sites in Drupal 11. The module was designed for higher education institutions but is generic enough for other institutional contexts.
+The `structural_pages` module implements a hierarchical editorial structure and contextual navigation for institutional sites in Drupal 11. The module was designed for higher education institutions but is generic enough for other institutional contexts.
## Problem
@@ -21,7 +21,7 @@ The module implements two complementary structures:
```
┌─────────────────────────────────────────────────────────────────────┐
-│ PRIMARY STRUCTURE: site_section Taxonomy │
+│ PRIMARY STRUCTURE: site_sections Taxonomy │
│ │
│ - Governs the overall organization of site information │
│ - Defines breadcrumbs and URLs (via Pathauto) │
@@ -48,12 +48,12 @@ The module implements two complementary structures:
## Components
-### 1. Taxonomy Vocabulary: `site_section`
+### 1. Taxonomy Vocabulary: `site_sections`
| Property | Value |
|----------|-------|
-| Machine name | `site_section` |
-| Name | Site Section |
+| Machine name | `site_sections` |
+| Name | Site Sections |
| Hierarchical | Yes |
| Description | Main hierarchical structure for site organization |
@@ -104,7 +104,7 @@ The `field_parent_page` uses the Dynamic Entity Reference module to support mult
**Default allowed targets**:
- `node:content_page` - Other content pages
- `node:section_page` - Section pages
-- `taxonomy_term:site_section` - Site section terms
+- `taxonomy_term:site_sections` - Site section terms
- `user:user` - User accounts
- `group:*` - All group types (requires Group module)
@@ -113,7 +113,7 @@ The `field_parent_page` uses the Dynamic Entity Reference module to support mult
- **User**: Content pages are associated with the user profile page (`/user/{id}`). The `field_site_section` is cleared as the context is the user itself.
- **Group**: Content pages are associated with the group. The `field_site_section` is cleared as the context is the group itself.
-**Configuration**: `/admin/config/local-modules/site-structure`
+**Configuration**: `/admin/config/local-modules/structural-pages`
### 5. Inheritance Logic
@@ -124,7 +124,7 @@ When a content_page is saved:
IF field_parent_page is filled:
IF parent is user or group:
Clear field_site_section (context is the entity itself)
- ELSE IF parent is taxonomy_term (site_section):
+ ELSE IF parent is taxonomy_term (site_sections):
Set field_site_section to the parent term ID
ELSE IF parent is node with field_site_section:
Copy field_site_section from parent node
@@ -181,12 +181,12 @@ View that lists child pages of the current `content_page`.
### 9. Settings Form
-Configuration form at `/admin/config/local-modules/site-structure` that allows administrators to:
+Configuration form at `/admin/config/local-modules/structural-pages` that allows administrators to:
- Select which node bundles can be used as parents
- Select which taxonomy vocabularies can be used as parents
- Changes automatically update the field configuration
-### 10. Block: Site Structure Menu
+### 10. Block: Structural Pages Menu
Dynamic menu block that renders hierarchical navigation based on the content structure.
@@ -221,7 +221,7 @@ Documentation (ancestor: taxonomy term)
**Usage**:
1. Navigate to Structure > Block layout
-2. Place "Site Structure Menu" block in desired region
+2. Place "Structural Pages Menu" block in desired region
3. Configure visibility (e.g., show only on content_page nodes)
4. Adjust depth and display options as needed
@@ -230,19 +230,19 @@ Documentation (ancestor: taxonomy term)
## File Structure
```
-site_structure/
-├── site_structure.info.yml # Metadata and dependencies
-├── site_structure.module # Hooks (presave, tokens, theme)
-├── site_structure.install # Installation hooks
-├── site_structure.services.yml # Service registration
-├── site_structure.routing.yml # Route definitions
-├── site_structure.links.menu.yml # Admin menu links
-├── site_structure.libraries.yml # Asset libraries (CSS)
+structural_pages/
+├── structural_pages.info.yml # Metadata and dependencies
+├── structural_pages.module # Hooks (presave, tokens, theme)
+├── structural_pages.install # Installation hooks
+├── structural_pages.services.yml # Service registration
+├── structural_pages.routing.yml # Route definitions
+├── structural_pages.links.menu.yml # Admin menu links
+├── structural_pages.libraries.yml # Asset libraries (CSS)
│
├── config/
│ ├── install/
-│ │ ├── site_structure.settings.yml # Default settings
-│ │ ├── taxonomy.vocabulary.site_section.yml
+│ │ ├── structural_pages.settings.yml # Default settings
+│ │ ├── taxonomy.vocabulary.site_sections.yml
│ │ │
│ │ ├── node.type.section_page.yml
│ │ ├── field.storage.node.field_site_section.yml
@@ -259,18 +259,18 @@ site_structure/
│ │ │
│ │ ├── pathauto.pattern.section_page.yml
│ │ ├── pathauto.pattern.content_page.yml
-│ │ ├── pathauto.pattern.site_section_term.yml
+│ │ ├── pathauto.pattern.site_sections_term.yml
│ │ │
│ │ └── views.view.child_pages.yml
│ │
│ └── schema/
-│ └── site_structure.schema.yml # Config schema
+│ └── structural_pages.schema.yml # Config schema
│
├── css/
-│ └── site-structure-menu.css # Menu block styles
+│ └── structural-pages-menu.css # Menu block styles
│
├── templates/
-│ └── site-structure-menu.html.twig # Menu block template
+│ └── structural-pages-menu.html.twig # Menu block template
│
├── translations/
│ └── pt-br.po # Portuguese (Brazil) translation
@@ -289,11 +289,11 @@ site_structure/
│ │ └── SectionBreadcrumbBuilder.php
│ │
│ ├── Form/
-│ │ └── SiteStructureSettingsForm.php
+│ │ └── StructuralPagesSettingsForm.php
│ │
│ └── Plugin/
│ ├── Block/
-│ │ └── SiteStructureMenuBlock.php # Dynamic menu block
+│ │ └── StructuralPagesMenuBlock.php # Dynamic menu block
│ │
│ └── ParentEntityHandler/ # Built-in handlers
│ ├── TaxonomyTermHandler.php # taxonomy_term handler
@@ -301,8 +301,8 @@ site_structure/
│ └── NodeHandler.php # node handler
│
├── modules/
-│ └── site_structure_group/ # Group integration submodule
-│ ├── site_structure_group.info.yml
+│ └── structural_pages_group/ # Group integration submodule
+│ ├── structural_pages_group.info.yml
│ └── src/Plugin/ParentEntityHandler/
│ └── GroupHandler.php # group handler
│
@@ -346,7 +346,7 @@ site_structure/
1. **Create root page (anchored to taxonomy term)**:
- Add content > Content Page
- - In "Parent Page", select a site_section term
+ - In "Parent Page", select a site_sections term
- Site section is set automatically from the term
- Save
@@ -370,7 +370,7 @@ site_structure/
### Configuring Allowed Parent Types
-1. Navigate to `/admin/config/local-modules/site-structure`
+1. Navigate to `/admin/config/local-modules/structural-pages`
2. Select which content types (nodes) can be used as parents
3. Select which taxonomy vocabularies can be used as parents
4. Save configuration
@@ -386,7 +386,7 @@ The module uses a plugin system to support different entity types as parents for
The plugin system consists of:
-1. **Attribute**: `Drupal\site_structure\Attribute\ParentEntityHandler` - PHP 8 attribute for defining handlers
+1. **Attribute**: `Drupal\structural_pages\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
@@ -395,7 +395,7 @@ The plugin system consists of:
| Handler | Entity Type | Clears Site Section | Sort Field | Bundle Restrictions |
|---------|-------------|---------------------|------------|---------------------|
-| TaxonomyTermHandler | taxonomy_term | No | name | site_section |
+| TaxonomyTermHandler | taxonomy_term | No | name | site_sections |
| UserHandler | user | Yes | name | - |
| NodeHandler | node | No | title | content_page, section_page |
@@ -409,8 +409,8 @@ To add support for a new entity type, create a handler plugin:
namespace Drupal\my_module\Plugin\ParentEntityHandler;
use Drupal\Core\StringTranslation\TranslatableMarkup;
-use Drupal\site_structure\Attribute\ParentEntityHandler;
-use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerBase;
+use Drupal\structural_pages\Attribute\ParentEntityHandler;
+use Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerBase;
#[ParentEntityHandler(
id: 'my_entity',
@@ -442,7 +442,7 @@ class MyEntityHandler extends ParentEntityHandlerBase {
## Group Integration
-Group support is provided via the `site_structure_group` submodule, which adds a handler for group entities. This submodule requires the Group module.
+Group support is provided via the `structural_pages_group` submodule, which adds a handler for group entities. This submodule requires the Group module.
**Features**:
- Content pages can have groups as parent entities
@@ -451,15 +451,15 @@ Group support is provided via the `site_structure_group` submodule, which adds a
- `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.
+**Installation**: Enable the `structural_pages_group` submodule after installing the Group module.
-**Configuration**: Enable group types in the settings form at `/admin/config/local-modules/site-structure`
+**Configuration**: Enable group types in the settings form at `/admin/config/local-modules/structural-pages`
---
## Installation Verification
-1. `drush en site_structure -y`
+1. `drush en structural_pages -y`
2. Verify vocabulary at `/admin/structure/taxonomy`
3. Verify content types at `/admin/structure/types`
4. Create test hierarchical terms
@@ -467,7 +467,7 @@ Group support is provided via the `site_structure_group` submodule, which adds a
6. Create root `content_page` with taxonomy term as parent
7. Create child `content_page`, verify inheritance
8. Verify child pages View
-9. Test settings form at `/admin/config/local-modules/site-structure`
+9. Test settings form at `/admin/config/local-modules/structural-pages`
---
@@ -478,5 +478,5 @@ Group support is provided via the `site_structure_group` submodule, which adds a
| 1.0.0 | - | Initial version |
| 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 |
+| 1.3.0 | - | Added Structural Pages Menu block for dynamic hierarchical navigation |
| 2.0.0 | - | Refactored to plugin system for parent entity handlers. Group support moved to submodule. |
diff --git a/docs/PLUGIN_SYSTEM_PLAN.md b/docs/PLUGIN_SYSTEM_PLAN.md
new file mode 100644
index 0000000..283f0f2
--- /dev/null
+++ b/docs/PLUGIN_SYSTEM_PLAN.md
@@ -0,0 +1,237 @@
+# Plano: Sistema de Plugins ParentEntityHandler
+
+## Problema
+
+O módulo structural_pages tem dependências hardcoded para diferentes tipos de entidade pai (taxonomy_term, user, group, node) espalhadas em múltiplos arquivos:
+
+- `StructuralPagesSettingsForm.php:46-51` - Array hardcoded `$supportedEntityTypes`
+- `structural_pages.module:55-59` - `in_array($parent_entity_type, ['user', 'group'])`
+- `StructuralPagesMenuBlock.php:14` - `use Drupal\group\Entity\GroupInterface;` (causa erro sem o módulo group)
+- `StructuralPagesMenuBlock.php:274-290` - Verificações `instanceof` para cada tipo
+- `SectionBreadcrumbBuilder.php:82-100` - Switch statement para tipos de contexto
+
+**Consequência:** Adicionar um novo tipo de entidade requer modificar múltiplos arquivos, e o import do GroupInterface causa erro quando o módulo group não está instalado.
+
+## Solução
+
+Implementar um sistema de plugins Drupal (Attribute-based para D10+) onde cada handler define:
+- Tipo de entidade que gerencia
+- Módulo provedor (para dependências opcionais)
+- Como detectar a entidade na rota
+- Como construir breadcrumbs
+- Se deve limpar `field_site_section`
+- Campo de ordenação
+
+---
+
+## Nova Estrutura de Arquivos
+
+```
+structural_pages/
+├── src/
+│ ├── Attribute/
+│ │ └── ParentEntityHandler.php # NOVO
+│ ├── ParentEntityHandler/
+│ │ ├── ParentEntityHandlerInterface.php # NOVO
+│ │ ├── ParentEntityHandlerManagerInterface.php # NOVO
+│ │ ├── ParentEntityHandlerBase.php # NOVO
+│ │ └── ParentEntityHandlerManager.php # NOVO
+│ ├── Plugin/
+│ │ ├── Block/
+│ │ │ └── StructuralPagesMenuBlock.php # REFATORAR
+│ │ └── ParentEntityHandler/ # NOVO
+│ │ ├── TaxonomyTermHandler.php # NOVO
+│ │ ├── UserHandler.php # NOVO
+│ │ └── NodeHandler.php # NOVO
+│ ├── Breadcrumb/
+│ │ └── SectionBreadcrumbBuilder.php # REFATORAR
+│ └── Form/
+│ └── StructuralPagesSettingsForm.php # REFATORAR
+├── modules/
+│ └── structural_pages_group/ # NOVO (submódulo)
+│ ├── structural_pages_group.info.yml
+│ └── src/Plugin/ParentEntityHandler/
+│ └── GroupHandler.php
+├── structural_pages.module # REFATORAR
+└── structural_pages.services.yml # ATUALIZAR
+```
+
+---
+
+## Componentes Principais
+
+### 1. Attribute (src/Attribute/ParentEntityHandler.php)
+
+```php
+#[\Attribute(\Attribute::TARGET_CLASS)]
+class ParentEntityHandler extends Plugin {
+ public function __construct(
+ public readonly string $id,
+ public readonly TranslatableMarkup $label,
+ public readonly string $entity_type_id,
+ public readonly ?string $provider_module = NULL,
+ public readonly bool $clears_site_section = FALSE,
+ public readonly string $sort_field = 'title',
+ public readonly ?string $route_parameter = NULL,
+ public readonly array $bundle_restrictions = [],
+ public readonly int $weight = 0,
+ ) {}
+}
+```
+
+### 2. Interface (src/ParentEntityHandler/ParentEntityHandlerInterface.php)
+
+Métodos principais:
+- `getEntityTypeId(): string`
+- `isAvailable(): bool`
+- `clearsSiteSection(): bool`
+- `getSortField(): string`
+- `getEntityFromRoute(RouteMatchInterface): ?EntityInterface`
+- `handlesEntity(EntityInterface): bool`
+- `buildBreadcrumb(Breadcrumb, EntityInterface): void`
+- `getSiteSectionId(EntityInterface): int|string|null`
+
+### 3. Manager (src/ParentEntityHandler/ParentEntityHandlerManager.php)
+
+Métodos principais:
+- `getAvailableHandlers(): array` - Retorna handlers com módulos instalados
+- `getHandlerForEntityType(string): ?ParentEntityHandlerInterface`
+- `getSupportedEntityTypes(): array` - Para o formulário de configurações
+- `clearsSiteSection(string): bool`
+- `getSortField(string): string`
+- `getEntityFromRoute(RouteMatchInterface): ?EntityInterface`
+- `buildBreadcrumbForEntity(Breadcrumb, EntityInterface): bool`
+
+### 4. Handlers Built-in
+
+| Handler | entity_type_id | clears_site_section | sort_field | bundle_restrictions |
+|---------|---------------|---------------------|------------|---------------------|
+| TaxonomyTermHandler | taxonomy_term | false | name | ['site_sections'] |
+| UserHandler | user | true | name | [] |
+| NodeHandler | node | false | title | ['content_page', 'section_page'] |
+
+### 5. Submódulo structural_pages_group
+
+```yaml
+# structural_pages_group.info.yml
+name: 'Structural Pages Group Integration'
+type: module
+dependencies:
+ - structural_pages:structural_pages
+ - group:group
+```
+
+GroupHandler: `entity_type_id: group`, `clears_site_section: true`, `sort_field: label`
+
+---
+
+## Refatorações
+
+### structural_pages.module (linhas 53-66)
+
+**Antes:**
+```php
+if (in_array($parent_entity_type, ['user', 'group'])) {
+ $entity->set('field_site_section', NULL);
+ return;
+}
+```
+
+**Depois:**
+```php
+$handler_manager = \Drupal::service('plugin.manager.parent_entity_handler');
+if ($handler_manager->clearsSiteSection($parent_entity_type)) {
+ $entity->set('field_site_section', NULL);
+ return;
+}
+```
+
+### StructuralPagesMenuBlock.php
+
+- Remover `use Drupal\group\Entity\GroupInterface;`
+- Injetar `ParentEntityHandlerManagerInterface`
+- Substituir `getAncestorFromRoute()`:
+
+```php
+protected function getAncestorFromRoute(): ?EntityInterface {
+ return $this->handlerManager->getEntityFromRoute($this->routeMatch);
+}
+```
+
+### SectionBreadcrumbBuilder.php
+
+- Injetar `ParentEntityHandlerManagerInterface`
+- Substituir switch statement:
+
+```php
+if ($context) {
+ $this->handlerManager->buildBreadcrumbForEntity($breadcrumb, $context['entity']);
+}
+```
+
+- Remover métodos `addUserBreadcrumb()` e `addGroupBreadcrumb()`
+
+### StructuralPagesSettingsForm.php
+
+- Injetar `ParentEntityHandlerManagerInterface`
+- Substituir `$supportedEntityTypes`:
+
+```php
+$supportedEntityTypes = $this->handlerManager->getSupportedEntityTypes();
+```
+
+- Substituir match statement de sort_field:
+
+```php
+$sort_field = $this->handlerManager->getSortField($entity_type);
+```
+
+### structural_pages.services.yml
+
+```yaml
+services:
+ plugin.manager.parent_entity_handler:
+ class: Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManager
+ arguments:
+ - '@container.namespaces'
+ - '@cache.discovery'
+ - '@module_handler'
+
+ structural_pages.breadcrumb.section:
+ class: Drupal\structural_pages\Breadcrumb\SectionBreadcrumbBuilder
+ arguments:
+ - '@entity_type.manager'
+ - '@plugin.manager.parent_entity_handler'
+ tags:
+ - { name: breadcrumb_builder, priority: 100 }
+```
+
+---
+
+## Verificação
+
+1. **Sem módulo group instalado:**
+ - O módulo structural_pages deve funcionar normalmente
+ - Formulário de configurações não deve mostrar opção "Groups"
+ - Nenhum erro de classe não encontrada
+
+2. **Com submódulo structural_pages_group ativado:**
+ - Opção "Groups" aparece no formulário de configurações
+ - Groups funcionam como entidades pai
+ - Breadcrumbs mostram nome do grupo
+
+3. **Extensibilidade:**
+ - Criar handler de teste em módulo custom
+ - Verificar que é descoberto automaticamente pelo manager
+
+4. **Cache:**
+ - Limpar cache após mudanças (`drush cr`)
+ - Verificar que handlers são cacheados corretamente
+
+---
+
+## Compatibilidade
+
+- Configuração existente (`allowed_parent_targets`) continua funcionando
+- Nenhuma alteração no schema de configuração necessária
+- Backwards compatible - apenas mudança interna de implementação
diff --git a/modules/site_structure_group/src/Plugin/ParentEntityHandler/GroupHandler.php b/modules/structural_pages_group/src/Plugin/ParentEntityHandler/GroupHandler.php
similarity index 77%
rename from modules/site_structure_group/src/Plugin/ParentEntityHandler/GroupHandler.php
rename to modules/structural_pages_group/src/Plugin/ParentEntityHandler/GroupHandler.php
index d033082..8895a90 100644
--- a/modules/site_structure_group/src/Plugin/ParentEntityHandler/GroupHandler.php
+++ b/modules/structural_pages_group/src/Plugin/ParentEntityHandler/GroupHandler.php
@@ -2,19 +2,19 @@
declare(strict_types=1);
-namespace Drupal\site_structure_group\Plugin\ParentEntityHandler;
+namespace Drupal\structural_pages_group\Plugin\ParentEntityHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\group\Entity\GroupInterface;
-use Drupal\site_structure\Attribute\ParentEntityHandler;
-use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerBase;
+use Drupal\structural_pages\Attribute\ParentEntityHandler;
+use Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerBase;
/**
* Handler for group entities.
*
- * This handler is provided by the site_structure_group submodule and is only
+ * This handler is provided by the structural_pages_group submodule and is only
* available when the Group module is installed.
*/
#[ParentEntityHandler(
diff --git a/modules/site_structure_group/site_structure_group.info.yml b/modules/structural_pages_group/structural_pages_group.info.yml
similarity index 52%
rename from modules/site_structure_group/site_structure_group.info.yml
rename to modules/structural_pages_group/structural_pages_group.info.yml
index 1f0406e..78928d5 100644
--- a/modules/site_structure_group/site_structure_group.info.yml
+++ b/modules/structural_pages_group/structural_pages_group.info.yml
@@ -1,8 +1,8 @@
-name: 'Site Structure Group Integration'
+name: 'Structural Pages Group Integration'
type: module
-description: 'Provides Group entity support as parent type for Site Structure module.'
-package: 'Site Structure'
+description: 'Provides Group entity support as parent type for Structural Pages module.'
+package: 'Structural Pages'
core_version_requirement: ^10.3 || ^11
dependencies:
- - site_structure:site_structure
+ - structural_pages:structural_pages
- group:group
diff --git a/site_structure.routing.yml b/site_structure.routing.yml
deleted file mode 100644
index 0f7b23e..0000000
--- a/site_structure.routing.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-site_structure.settings:
- path: '/admin/config/local-modules/site-structure'
- defaults:
- _form: '\Drupal\site_structure\Form\SiteStructureSettingsForm'
- _title: 'Site Structure Settings'
- requirements:
- _permission: 'administer site configuration'
diff --git a/src/Attribute/ParentEntityHandler.php b/src/Attribute/ParentEntityHandler.php
index c949498..807007b 100644
--- a/src/Attribute/ParentEntityHandler.php
+++ b/src/Attribute/ParentEntityHandler.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Drupal\site_structure\Attribute;
+namespace Drupal\structural_pages\Attribute;
use Drupal\Component\Plugin\Attribute\Plugin;
use Drupal\Core\StringTranslation\TranslatableMarkup;
@@ -12,9 +12,9 @@ use Drupal\Core\StringTranslation\TranslatableMarkup;
*
* Plugin namespace: Plugin\ParentEntityHandler.
*
- * @see \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerInterface
- * @see \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerBase
- * @see \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManager
+ * @see \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerInterface
+ * @see \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerBase
+ * @see \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManager
* @see plugin_api
*/
#[\Attribute(\Attribute::TARGET_CLASS)]
@@ -51,7 +51,7 @@ class ParentEntityHandler extends Plugin {
* (optional) The deriver class.
*/
public function __construct(
- public readonly string $id,
+ string $id,
public readonly TranslatableMarkup $label,
public readonly string $entity_type_id,
public readonly ?string $provider_module = NULL,
@@ -60,7 +60,7 @@ class ParentEntityHandler extends Plugin {
public readonly ?string $route_parameter = NULL,
public readonly array $bundle_restrictions = [],
public readonly int $weight = 0,
- public readonly ?string $deriver = NULL,
+ ?string $deriver = NULL,
) {
parent::__construct($id, $deriver);
}
diff --git a/src/Breadcrumb/SectionBreadcrumbBuilder.php b/src/Breadcrumb/SectionBreadcrumbBuilder.php
index b9eab16..355c4c8 100644
--- a/src/Breadcrumb/SectionBreadcrumbBuilder.php
+++ b/src/Breadcrumb/SectionBreadcrumbBuilder.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Drupal\site_structure\Breadcrumb;
+namespace Drupal\structural_pages\Breadcrumb;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
@@ -11,7 +11,7 @@ use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;
-use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface;
+use Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface;
/**
* Provides a breadcrumb builder for section_page and content_page content types.
@@ -30,7 +30,7 @@ class SectionBreadcrumbBuilder implements BreadcrumbBuilderInterface {
/**
* The parent entity handler manager.
*
- * @var \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface
+ * @var \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface
*/
protected ParentEntityHandlerManagerInterface $handlerManager;
@@ -46,7 +46,7 @@ class SectionBreadcrumbBuilder implements BreadcrumbBuilderInterface {
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
- * @param \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface $handler_manager
+ * @param \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface $handler_manager
* The parent entity handler manager.
*/
public function __construct(
@@ -169,7 +169,7 @@ class SectionBreadcrumbBuilder implements BreadcrumbBuilderInterface {
];
}
- // If parent is taxonomy_term, that's our context (handled via site_section).
+ // If parent is taxonomy_term, that's our context (handled via site_sections).
if ($parent_entity_type === 'taxonomy_term') {
return [
'type' => 'taxonomy_term',
diff --git a/src/Form/SiteStructureSettingsForm.php b/src/Form/StructuralPagesSettingsForm.php
similarity index 89%
rename from src/Form/SiteStructureSettingsForm.php
rename to src/Form/StructuralPagesSettingsForm.php
index ba04496..753582a 100644
--- a/src/Form/SiteStructureSettingsForm.php
+++ b/src/Form/StructuralPagesSettingsForm.php
@@ -2,20 +2,21 @@
declare(strict_types=1);
-namespace Drupal\site_structure\Form;
+namespace Drupal\structural_pages\Form;
use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
-use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface;
+use Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
- * Configuration form for Site Structure module.
+ * Configuration form for Structural Pages module.
*/
-class SiteStructureSettingsForm extends ConfigFormBase {
+class StructuralPagesSettingsForm extends ConfigFormBase {
/**
* The entity type manager.
@@ -34,29 +35,32 @@ class SiteStructureSettingsForm extends ConfigFormBase {
/**
* The parent entity handler manager.
*
- * @var \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface
+ * @var \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface
*/
protected ParentEntityHandlerManagerInterface $handlerManager;
/**
- * Constructs a SiteStructureSettingsForm object.
+ * Constructs a StructuralPagesSettingsForm object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
+ * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager
+ * The typed config manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The entity type bundle info service.
- * @param \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface $handler_manager
+ * @param \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface $handler_manager
* The parent entity handler manager.
*/
public function __construct(
ConfigFactoryInterface $config_factory,
+ TypedConfigManagerInterface $typed_config_manager,
EntityTypeManagerInterface $entity_type_manager,
EntityTypeBundleInfoInterface $entity_type_bundle_info,
ParentEntityHandlerManagerInterface $handler_manager,
) {
- parent::__construct($config_factory);
+ parent::__construct($config_factory, $typed_config_manager);
$this->entityTypeManager = $entity_type_manager;
$this->entityTypeBundleInfo = $entity_type_bundle_info;
$this->handlerManager = $handler_manager;
@@ -68,6 +72,7 @@ class SiteStructureSettingsForm extends ConfigFormBase {
public static function create(ContainerInterface $container): static {
return new static(
$container->get('config.factory'),
+ $container->get('config.typed'),
$container->get('entity_type.manager'),
$container->get('entity_type.bundle.info'),
$container->get('plugin.manager.parent_entity_handler'),
@@ -78,21 +83,21 @@ class SiteStructureSettingsForm extends ConfigFormBase {
* {@inheritdoc}
*/
public function getFormId(): string {
- return 'site_structure_settings_form';
+ return 'structural_pages_settings_form';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames(): array {
- return ['site_structure.settings'];
+ return ['structural_pages.settings'];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
- $config = $this->config('site_structure.settings');
+ $config = $this->config('structural_pages.settings');
$allowed_targets = $config->get('allowed_parent_targets') ?? [];
// Build a keyed array for easier lookup.
@@ -217,7 +222,7 @@ class SiteStructureSettingsForm extends ConfigFormBase {
}
}
- $this->config('site_structure.settings')
+ $this->config('structural_pages.settings')
->set('allowed_parent_targets', $targets)
->save();
diff --git a/src/ParentEntityHandler/ParentEntityHandlerBase.php b/src/ParentEntityHandler/ParentEntityHandlerBase.php
index defcc74..b22e820 100644
--- a/src/ParentEntityHandler/ParentEntityHandlerBase.php
+++ b/src/ParentEntityHandler/ParentEntityHandlerBase.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Drupal\site_structure\ParentEntityHandler;
+namespace Drupal\structural_pages\ParentEntityHandler;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Entity\EntityInterface;
diff --git a/src/ParentEntityHandler/ParentEntityHandlerInterface.php b/src/ParentEntityHandler/ParentEntityHandlerInterface.php
index af612d3..57b9bdd 100644
--- a/src/ParentEntityHandler/ParentEntityHandlerInterface.php
+++ b/src/ParentEntityHandler/ParentEntityHandlerInterface.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Drupal\site_structure\ParentEntityHandler;
+namespace Drupal\structural_pages\ParentEntityHandler;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Entity\EntityInterface;
diff --git a/src/ParentEntityHandler/ParentEntityHandlerManager.php b/src/ParentEntityHandler/ParentEntityHandlerManager.php
index 7d92626..1101748 100644
--- a/src/ParentEntityHandler/ParentEntityHandlerManager.php
+++ b/src/ParentEntityHandler/ParentEntityHandlerManager.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Drupal\site_structure\ParentEntityHandler;
+namespace Drupal\structural_pages\ParentEntityHandler;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Cache\CacheBackendInterface;
@@ -11,14 +11,14 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\site_structure\Attribute\ParentEntityHandler;
+use Drupal\structural_pages\Attribute\ParentEntityHandler;
/**
* Plugin manager for parent entity handlers.
*
- * @see \Drupal\site_structure\Attribute\ParentEntityHandler
- * @see \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerInterface
- * @see \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerBase
+ * @see \Drupal\structural_pages\Attribute\ParentEntityHandler
+ * @see \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerInterface
+ * @see \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerBase
*/
class ParentEntityHandlerManager extends DefaultPluginManager implements ParentEntityHandlerManagerInterface {
@@ -32,7 +32,7 @@ class ParentEntityHandlerManager extends DefaultPluginManager implements ParentE
/**
* Static cache for handler instances.
*
- * @var \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerInterface[]|null
+ * @var \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerInterface[]|null
*/
protected ?array $handlerInstances = NULL;
diff --git a/src/ParentEntityHandler/ParentEntityHandlerManagerInterface.php b/src/ParentEntityHandler/ParentEntityHandlerManagerInterface.php
index 3287024..3f9f5de 100644
--- a/src/ParentEntityHandler/ParentEntityHandlerManagerInterface.php
+++ b/src/ParentEntityHandler/ParentEntityHandlerManagerInterface.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Drupal\site_structure\ParentEntityHandler;
+namespace Drupal\structural_pages\ParentEntityHandler;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Entity\EntityInterface;
@@ -22,7 +22,7 @@ interface ParentEntityHandlerManagerInterface {
* Handlers are available if their provider module is installed and the
* entity type exists.
*
- * @return \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerInterface[]
+ * @return \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerInterface[]
* An array of available handler instances, keyed by plugin ID.
*/
public function getAvailableHandlers(): array;
@@ -33,7 +33,7 @@ interface ParentEntityHandlerManagerInterface {
* @param string $entity_type_id
* The entity type ID.
*
- * @return \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerInterface|null
+ * @return \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerInterface|null
* The handler for the entity type, or NULL if none found.
*/
public function getHandlerForEntityType(string $entity_type_id): ?ParentEntityHandlerInterface;
@@ -44,7 +44,7 @@ interface ParentEntityHandlerManagerInterface {
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
*
- * @return \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerInterface|null
+ * @return \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerInterface|null
* The handler for the entity, or NULL if none found.
*/
public function getHandlerForEntity(EntityInterface $entity): ?ParentEntityHandlerInterface;
diff --git a/src/Plugin/Block/SiteStructureMenuBlock.php b/src/Plugin/Block/StructuralPagesMenuBlock.php
similarity index 95%
rename from src/Plugin/Block/SiteStructureMenuBlock.php
rename to src/Plugin/Block/StructuralPagesMenuBlock.php
index 85b8715..646fbbe 100644
--- a/src/Plugin/Block/SiteStructureMenuBlock.php
+++ b/src/Plugin/Block/StructuralPagesMenuBlock.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Drupal\site_structure\Plugin\Block;
+namespace Drupal\structural_pages\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
@@ -12,22 +12,22 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\NodeInterface;
-use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface;
+use Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a dynamic menu block based on site structure hierarchy.
*
* @Block(
- * id = "site_structure_menu",
- * admin_label = @Translation("Site Structure Menu"),
- * category = @Translation("Site Structure"),
+ * id = "structural_pages_menu",
+ * admin_label = @Translation("Structural Pages Menu"),
+ * category = @Translation("Structural Pages"),
* context_definitions = {
* "node" = @ContextDefinition("entity:node", label = @Translation("Node"), required = FALSE),
* }
* )
*/
-class SiteStructureMenuBlock extends BlockBase implements ContainerFactoryPluginInterface {
+class StructuralPagesMenuBlock extends BlockBase implements ContainerFactoryPluginInterface {
/**
* Maximum depth to prevent infinite loops.
@@ -51,7 +51,7 @@ class SiteStructureMenuBlock extends BlockBase implements ContainerFactoryPlugin
/**
* The parent entity handler manager.
*
- * @var \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface
+ * @var \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface
*/
protected ParentEntityHandlerManagerInterface $handlerManager;
@@ -175,7 +175,7 @@ class SiteStructureMenuBlock extends BlockBase implements ContainerFactoryPlugin
}
$build = [
- '#theme' => 'site_structure_menu',
+ '#theme' => 'structural_pages_menu',
'#ancestor' => $ancestor,
'#tree' => $tree,
'#active_trail' => $active_trail,
diff --git a/src/Plugin/ParentEntityHandler/NodeHandler.php b/src/Plugin/ParentEntityHandler/NodeHandler.php
index 86ff857..4b6cef3 100644
--- a/src/Plugin/ParentEntityHandler/NodeHandler.php
+++ b/src/Plugin/ParentEntityHandler/NodeHandler.php
@@ -2,15 +2,15 @@
declare(strict_types=1);
-namespace Drupal\site_structure\Plugin\ParentEntityHandler;
+namespace Drupal\structural_pages\Plugin\ParentEntityHandler;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\node\NodeInterface;
-use Drupal\site_structure\Attribute\ParentEntityHandler;
-use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerBase;
+use Drupal\structural_pages\Attribute\ParentEntityHandler;
+use Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerBase;
/**
* Handler for node entities.
diff --git a/src/Plugin/ParentEntityHandler/TaxonomyTermHandler.php b/src/Plugin/ParentEntityHandler/TaxonomyTermHandler.php
index c2b344b..718d0fe 100644
--- a/src/Plugin/ParentEntityHandler/TaxonomyTermHandler.php
+++ b/src/Plugin/ParentEntityHandler/TaxonomyTermHandler.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
-namespace Drupal\site_structure\Plugin\ParentEntityHandler;
+namespace Drupal\structural_pages\Plugin\ParentEntityHandler;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
-use Drupal\site_structure\Attribute\ParentEntityHandler;
-use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerBase;
+use Drupal\structural_pages\Attribute\ParentEntityHandler;
+use Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerBase;
use Drupal\taxonomy\TermInterface;
/**
@@ -20,7 +20,7 @@ use Drupal\taxonomy\TermInterface;
entity_type_id: 'taxonomy_term',
clears_site_section: FALSE,
sort_field: 'name',
- bundle_restrictions: ['site_section'],
+ bundle_restrictions: ['site_sections'],
weight: 0,
)]
class TaxonomyTermHandler extends ParentEntityHandlerBase {
@@ -69,8 +69,8 @@ class TaxonomyTermHandler extends ParentEntityHandlerBase {
return NULL;
}
- // Only site_section terms can be site sections.
- if ($entity->bundle() !== 'site_section') {
+ // Only site_sections terms can be site sections.
+ if ($entity->bundle() !== 'site_sections') {
return NULL;
}
diff --git a/src/Plugin/ParentEntityHandler/UserHandler.php b/src/Plugin/ParentEntityHandler/UserHandler.php
index d953380..ae42f76 100644
--- a/src/Plugin/ParentEntityHandler/UserHandler.php
+++ b/src/Plugin/ParentEntityHandler/UserHandler.php
@@ -2,13 +2,13 @@
declare(strict_types=1);
-namespace Drupal\site_structure\Plugin\ParentEntityHandler;
+namespace Drupal\structural_pages\Plugin\ParentEntityHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
-use Drupal\site_structure\Attribute\ParentEntityHandler;
-use Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerBase;
+use Drupal\structural_pages\Attribute\ParentEntityHandler;
+use Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerBase;
use Drupal\user\UserInterface;
/**
diff --git a/site_structure.info.yml b/structural_pages.info.yml
similarity index 85%
rename from site_structure.info.yml
rename to structural_pages.info.yml
index 999cc3a..3077d22 100644
--- a/site_structure.info.yml
+++ b/structural_pages.info.yml
@@ -1,9 +1,9 @@
-name: 'Site Structure'
+name: 'Structural Pages'
type: module
description: 'Implements hierarchical editorial structure and contextual navigation for institutional sites.'
package: Custom
core_version_requirement: ^11
-configure: site_structure.settings
+configure: structural_pages.settings
dependencies:
- drupal:node
- drupal:taxonomy
diff --git a/site_structure.install b/structural_pages.install
similarity index 68%
rename from site_structure.install
rename to structural_pages.install
index 142cb8e..536d0c8 100644
--- a/site_structure.install
+++ b/structural_pages.install
@@ -2,7 +2,7 @@
/**
* @file
- * Install, update and uninstall functions for the Site Structure module.
+ * Install, update and uninstall functions for the Structural Pages module.
*/
declare(strict_types=1);
@@ -12,19 +12,19 @@ use Drupal\taxonomy\Entity\Term;
/**
* Implements hook_install().
*/
-function site_structure_install(): void {
- // Create default terms for site_section vocabulary.
- _site_structure_create_default_terms();
+function structural_pages_install(): void {
+ // Create default terms for site_sections vocabulary.
+ _structural_pages_create_default_terms();
// Display success message.
- \Drupal::messenger()->addStatus(t('Site Structure module installed successfully. Configure Pathauto patterns at /admin/config/search/path/patterns'));
+ \Drupal::messenger()->addStatus(t('Structural Pages module installed successfully. Configure Pathauto patterns at /admin/config/search/path/patterns'));
}
/**
- * Creates default terms for the site_section vocabulary.
+ * Creates default terms for the site_sections vocabulary.
*/
-function _site_structure_create_default_terms(): void {
- $vocabulary = 'site_section';
+function _structural_pages_create_default_terms(): void {
+ $vocabulary = 'site_sections';
// Check if terms already exist (avoid duplication on reinstall).
$existing = \Drupal::entityQuery('taxonomy_term')
@@ -100,7 +100,7 @@ function _site_structure_create_default_terms(): void {
/**
* Implements hook_uninstall().
*/
-function site_structure_uninstall(): void {
+function structural_pages_uninstall(): void {
$entity_type_manager = \Drupal::entityTypeManager();
// Remove nodes from module's content types.
@@ -119,10 +119,10 @@ function site_structure_uninstall(): void {
}
}
- // Remove terms from site_section vocabulary.
+ // Remove terms from site_sections vocabulary.
$tids = \Drupal::entityQuery('taxonomy_term')
->accessCheck(FALSE)
- ->condition('vid', 'site_section')
+ ->condition('vid', 'site_sections')
->execute();
if ($tids) {
$terms = $entity_type_manager->getStorage('taxonomy_term')->loadMultiple($tids);
@@ -136,7 +136,7 @@ function site_structure_uninstall(): void {
// Pathauto patterns.
'pathauto.pattern.section_page',
'pathauto.pattern.content_page',
- 'pathauto.pattern.site_section_term',
+ 'pathauto.pattern.site_sections_term',
// Entity displays.
'core.entity_form_display.node.section_page.default',
'core.entity_view_display.node.section_page.default',
@@ -155,7 +155,7 @@ function site_structure_uninstall(): void {
'node.type.section_page',
'node.type.content_page',
// Vocabulary.
- 'taxonomy.vocabulary.site_section',
+ 'taxonomy.vocabulary.site_sections',
];
$config_factory = \Drupal::configFactory();
@@ -166,36 +166,53 @@ function site_structure_uninstall(): void {
}
}
- \Drupal::messenger()->addStatus(t('Site Structure module uninstalled successfully.'));
+ \Drupal::messenger()->addStatus(t('Structural Pages module uninstalled successfully.'));
+}
+
+/**
+ * Update content_page content type name from "Guide Page" to "Content Page".
+ */
+function structural_pages_update_10001(): void {
+ $config = \Drupal::configFactory()->getEditable('node.type.content_page');
+ if (!$config->isNew()) {
+ $current_name = $config->get('name');
+ // Update if still using old name.
+ if ($current_name === 'Guide Page') {
+ $config->set('name', 'Content Page');
+ $config->set('description', 'Pages with hierarchical parent-child structure for content organization.');
+ $config->save();
+ \Drupal::messenger()->addStatus(t('Updated content_page content type name to "Content Page".'));
+ }
+ }
}
/**
* Implements hook_requirements().
*/
-function site_structure_requirements(string $phase): array {
+function structural_pages_requirements(string $phase): array {
$requirements = [];
if ($phase === 'runtime') {
- // Check if site_section vocabulary has terms.
+ // Check if site_sections vocabulary has terms.
$term_count = \Drupal::entityQuery('taxonomy_term')
->accessCheck(FALSE)
- ->condition('vid', 'site_section')
+ ->condition('vid', 'site_sections')
->count()
->execute();
if ($term_count === 0) {
- $requirements['site_structure_terms'] = [
- 'title' => t('Site Structure'),
- 'value' => t('No terms in site_section vocabulary'),
- 'description' => t('The Site Structure module requires terms in the "Site Section" vocabulary. Add terms.', [
- ':url' => '/admin/structure/taxonomy/manage/site_section/add',
+ $requirements['structural_pages_terms'] = [
+ 'title' => t('Structural Pages'),
+ 'value' => t('No terms in site_sections vocabulary'),
+ 'description' => t('The Structural Pages module requires terms in the "Site Sections" vocabulary. Add terms.', [
+ ':url' => '/admin/structure/taxonomy/manage/site_sections/add',
]),
'severity' => REQUIREMENT_WARNING,
];
}
else {
- $requirements['site_structure_terms'] = [
- 'title' => t('Site Structure'),
+ $requirements['structural_pages_terms'] = [
+ 'title' => t('Structural Pages'),
'value' => t('@count terms configured', ['@count' => $term_count]),
'severity' => REQUIREMENT_OK,
];
diff --git a/site_structure.libraries.yml b/structural_pages.libraries.yml
similarity index 54%
rename from site_structure.libraries.yml
rename to structural_pages.libraries.yml
index 56b1cc6..07d4454 100644
--- a/site_structure.libraries.yml
+++ b/structural_pages.libraries.yml
@@ -2,4 +2,4 @@ menu:
version: VERSION
css:
component:
- css/site-structure-menu.css: {}
+ css/structural-pages-menu.css: {}
diff --git a/site_structure.links.menu.yml b/structural_pages.links.menu.yml
similarity index 55%
rename from site_structure.links.menu.yml
rename to structural_pages.links.menu.yml
index 86e8a17..1494e8b 100644
--- a/site_structure.links.menu.yml
+++ b/structural_pages.links.menu.yml
@@ -1,6 +1,6 @@
-site_structure.settings:
- title: 'Site Structure'
+structural_pages.settings:
+ title: 'Structural Pages'
description: 'Configure allowed parent entity types for content pages.'
- route_name: site_structure.settings
+ route_name: structural_pages.settings
parent: site_tools.admin_config
weight: 0
diff --git a/site_structure.module b/structural_pages.module
similarity index 85%
rename from site_structure.module
rename to structural_pages.module
index 39ad5a5..3183f13 100644
--- a/site_structure.module
+++ b/structural_pages.module
@@ -2,7 +2,7 @@
/**
* @file
- * Primary module hooks for Site Structure module.
+ * Primary module hooks for Structural Pages module.
*/
declare(strict_types=1);
@@ -18,7 +18,7 @@ use Drupal\user\UserInterface;
* Inherits field_site_section from parent to content_page.
* Validates circular reference in field_parent_page.
*/
-function site_structure_entity_presave(EntityInterface $entity): void {
+function structural_pages_entity_presave(EntityInterface $entity): void {
if (!$entity instanceof NodeInterface || $entity->bundle() !== 'content_page') {
return;
}
@@ -42,7 +42,7 @@ function site_structure_entity_presave(EntityInterface $entity): void {
// Circular reference validation (only for node parents).
if ($parent_entity_type === 'node' && !$entity->isNew() && $parent_id) {
- if (_site_structure_creates_circular_reference($entity->id(), $parent_id)) {
+ if (_structural_pages_creates_circular_reference($entity->id(), $parent_id)) {
\Drupal::messenger()->addError(t('Circular reference detected. A page cannot be a parent of itself or its ancestors.'));
// Remove invalid reference.
$entity->set('field_parent_page', NULL);
@@ -52,7 +52,7 @@ function site_structure_entity_presave(EntityInterface $entity): void {
// Handle site section based on parent type.
// Some entity types (like user and group) act as context containers themselves.
- /** @var \Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManagerInterface $handler_manager */
+ /** @var \Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManagerInterface $handler_manager */
$handler_manager = \Drupal::service('plugin.manager.parent_entity_handler');
if ($handler_manager->clearsSiteSection($parent_entity_type)) {
// Clear field_site_section as the context is the parent entity, not a site section.
@@ -61,7 +61,7 @@ function site_structure_entity_presave(EntityInterface $entity): void {
}
// Inherit field_site_section based on parent type (node or taxonomy_term).
- $site_section_id = _site_structure_get_section_from_parent($parent_entity_type, $parent_id);
+ $site_section_id = _structural_pages_get_section_from_parent($parent_entity_type, $parent_id);
if ($site_section_id) {
$entity->set('field_site_section', $site_section_id);
}
@@ -78,13 +78,13 @@ function site_structure_entity_presave(EntityInterface $entity): void {
* @return int|string|null
* The site section term ID, or NULL if not found.
*/
-function _site_structure_get_section_from_parent(string $parent_entity_type, int|string $parent_id): int|string|null {
+function _structural_pages_get_section_from_parent(string $parent_entity_type, int|string $parent_id): int|string|null {
$entity_type_manager = \Drupal::entityTypeManager();
if ($parent_entity_type === 'taxonomy_term') {
- // If parent is a taxonomy term, verify it's from site_section vocabulary.
+ // If parent is a taxonomy term, verify it's from site_sections vocabulary.
$term = $entity_type_manager->getStorage('taxonomy_term')->load($parent_id);
- if ($term instanceof TermInterface && $term->bundle() === 'site_section') {
+ if ($term instanceof TermInterface && $term->bundle() === 'site_sections') {
return $term->id();
}
return NULL;
@@ -114,7 +114,7 @@ function _site_structure_get_section_from_parent(string $parent_entity_type, int
* @return array|null
* An array with 'type' and 'entity' keys, or NULL if no parent.
*/
-function _site_structure_get_parent_context(NodeInterface $node): ?array {
+function _structural_pages_get_parent_context(NodeInterface $node): ?array {
if (!$node->hasField('field_parent_page') || $node->get('field_parent_page')->isEmpty()) {
return NULL;
}
@@ -156,7 +156,7 @@ function _site_structure_get_parent_context(NodeInterface $node): ?array {
* @return bool
* TRUE if it would create circular reference, FALSE otherwise.
*/
-function _site_structure_creates_circular_reference(int|string $node_id, int|string $parent_id): bool {
+function _structural_pages_creates_circular_reference(int|string $node_id, int|string $parent_id): bool {
$visited = [];
$current_id = $parent_id;
$node_storage = \Drupal::entityTypeManager()->getStorage('node');
@@ -196,9 +196,9 @@ function _site_structure_creates_circular_reference(int|string $node_id, int|str
/**
* Implements hook_theme().
*/
-function site_structure_theme(): array {
+function structural_pages_theme(): array {
return [
- 'site_structure_menu' => [
+ 'structural_pages_menu' => [
'variables' => [
'ancestor' => NULL,
'tree' => [],
@@ -206,7 +206,7 @@ function site_structure_theme(): array {
'show_ancestor_title' => TRUE,
],
],
- 'site_structure_menu_tree' => [
+ 'structural_pages_menu_tree' => [
'variables' => [
'items' => [],
'active_trail' => [],
@@ -219,12 +219,12 @@ function site_structure_theme(): array {
/**
* Implements hook_token_info().
*/
-function site_structure_token_info(): array {
+function structural_pages_token_info(): array {
$info = [];
$info['tokens']['node']['site-section-path'] = [
'name' => t('Site Section Path'),
- 'description' => t('The hierarchical path of the site_section taxonomy (e.g., undergraduate/courses).'),
+ 'description' => t('The hierarchical path of the site_sections taxonomy (e.g., undergraduate/courses).'),
];
$info['tokens']['term']['hierarchy-path'] = [
@@ -238,14 +238,14 @@ function site_structure_token_info(): array {
/**
* Implements hook_tokens().
*/
-function site_structure_tokens(string $type, array $tokens, array $data, array $options, $bubbleable_metadata): array {
+function structural_pages_tokens(string $type, array $tokens, array $data, array $options, $bubbleable_metadata): array {
$replacements = [];
if ($type === 'node' && !empty($data['node'])) {
$node = $data['node'];
foreach ($tokens as $name => $original) {
if ($name === 'site-section-path') {
- $replacements[$original] = _site_structure_get_section_path($node);
+ $replacements[$original] = _structural_pages_get_section_path($node);
}
}
}
@@ -254,7 +254,7 @@ function site_structure_tokens(string $type, array $tokens, array $data, array $
$term = $data['term'];
foreach ($tokens as $name => $original) {
if ($name === 'hierarchy-path') {
- $replacements[$original] = _site_structure_get_term_hierarchy_path($term);
+ $replacements[$original] = _structural_pages_get_term_hierarchy_path($term);
}
}
}
@@ -271,7 +271,7 @@ function site_structure_tokens(string $type, array $tokens, array $data, array $
* @return string
* The section path (e.g., "undergraduate/courses") or empty string.
*/
-function _site_structure_get_section_path(NodeInterface $node): string {
+function _structural_pages_get_section_path(NodeInterface $node): string {
if (!$node->hasField('field_site_section') || $node->get('field_site_section')->isEmpty()) {
return '';
}
@@ -306,7 +306,7 @@ function _site_structure_get_section_path(NodeInterface $node): string {
* @return string
* The hierarchical path (e.g., "institutional/news") or empty string.
*/
-function _site_structure_get_term_hierarchy_path(TermInterface $term): string {
+function _structural_pages_get_term_hierarchy_path(TermInterface $term): string {
$term_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
// Get all ancestors of the term (including itself).
diff --git a/structural_pages.routing.yml b/structural_pages.routing.yml
new file mode 100644
index 0000000..ac938c1
--- /dev/null
+++ b/structural_pages.routing.yml
@@ -0,0 +1,7 @@
+structural_pages.settings:
+ path: '/admin/config/local-modules/structural-pages'
+ defaults:
+ _form: '\Drupal\structural_pages\Form\StructuralPagesSettingsForm'
+ _title: 'Structural Pages Settings'
+ requirements:
+ _permission: 'administer site configuration'
diff --git a/site_structure.services.yml b/structural_pages.services.yml
similarity index 63%
rename from site_structure.services.yml
rename to structural_pages.services.yml
index 5301808..24c3b3a 100644
--- a/site_structure.services.yml
+++ b/structural_pages.services.yml
@@ -1,14 +1,14 @@
services:
plugin.manager.parent_entity_handler:
- class: Drupal\site_structure\ParentEntityHandler\ParentEntityHandlerManager
+ class: Drupal\structural_pages\ParentEntityHandler\ParentEntityHandlerManager
arguments:
- '@container.namespaces'
- '@cache.discovery'
- '@module_handler'
- '@entity_type.manager'
- site_structure.breadcrumb.section:
- class: Drupal\site_structure\Breadcrumb\SectionBreadcrumbBuilder
+ structural_pages.breadcrumb.section:
+ class: Drupal\structural_pages\Breadcrumb\SectionBreadcrumbBuilder
arguments:
- '@entity_type.manager'
- '@plugin.manager.parent_entity_handler'
diff --git a/site_structure.tokens.inc b/structural_pages.tokens.inc
similarity index 52%
rename from site_structure.tokens.inc
rename to structural_pages.tokens.inc
index c2ad05e..be01ed6 100644
--- a/site_structure.tokens.inc
+++ b/structural_pages.tokens.inc
@@ -2,13 +2,13 @@
/**
* @file
- * Token integration for Site Structure module.
+ * Token integration for Structural Pages module.
*
* Este arquivo existe para compatibilidade, mas os tokens são definidos
- * diretamente em site_structure.module via hook_token_info() e hook_tokens().
+ * diretamente em structural_pages.module via hook_token_info() e hook_tokens().
*/
declare(strict_types=1);
-// Os tokens são implementados em site_structure.module.
+// Os tokens são implementados em structural_pages.module.
// Este arquivo pode ser usado para funções auxiliares adicionais se necessário.
diff --git a/templates/site-structure-menu.html.twig b/templates/structural-pages-menu.html.twig
similarity index 63%
rename from templates/site-structure-menu.html.twig
rename to templates/structural-pages-menu.html.twig
index 286d090..4cf87b0 100644
--- a/templates/site-structure-menu.html.twig
+++ b/templates/structural-pages-menu.html.twig
@@ -1,7 +1,7 @@
{#
/**
* @file
- * Template for the site structure menu block.
+ * Template for the structural pages menu block.
*
* Available variables:
* - ancestor: The ancestor entity (term, user, or group).
@@ -16,11 +16,11 @@
* - show_ancestor_title: Whether to show the ancestor title as header.
*/
#}
-{{ attach_library('site_structure/menu') }}
+{{ attach_library('structural_pages/menu') }}
{% if tree is not empty %}
-