Rename module site_structure → structural_pages and vocabulary site_section → site_sections

Renames the module from site_structure to structural_pages and pluralizes
the taxonomy vocabulary machine name from site_section to site_sections,
updating all config, PHP, translations, and documentation references
while preserving field_site_section, clears_site_section, and $site_section_id.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-05 08:10:32 -03:00
parent 7c898ad339
commit 88b9605408
37 changed files with 545 additions and 281 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -3,7 +3,7 @@ status: true
dependencies:
module:
- node
- site_structure
- structural_pages
id: content_page
label: 'Content Page'
type: 'canonical_entities:node'

View File

@@ -3,7 +3,7 @@ status: true
dependencies:
module:
- node
- site_structure
- structural_pages
id: section_page
label: 'Section Page'
type: 'canonical_entities:node'

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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. |

237
docs/PLUGIN_SYSTEM_PLAN.md Normal file
View File

@@ -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

View File

@@ -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(

View File

@@ -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

View File

@@ -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'

View File

@@ -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);
}

View File

@@ -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',

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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;
/**

View File

@@ -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

View File

@@ -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. <a href=":url">Add terms</a>.', [
':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. <a href=":url">Add terms</a>.', [
':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,
];

View File

@@ -2,4 +2,4 @@ menu:
version: VERSION
css:
component:
css/site-structure-menu.css: {}
css/structural-pages-menu.css: {}

View File

@@ -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

View File

@@ -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).

View File

@@ -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'

View File

@@ -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'

View File

@@ -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.

View File

@@ -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 %}
<nav class="site-structure-menu" aria-label="{{ 'Site structure navigation'|t }}">
<nav class="structural-pages-menu" aria-label="{{ 'Site structure navigation'|t }}">
{% if show_ancestor_title and ancestor %}
<h2 class="site-structure-menu__title">
<h2 class="structural-pages-menu__title">
{% if ancestor.toUrl is defined %}
<a href="{{ ancestor.toUrl }}">{{ ancestor.label }}</a>
{% else %}
@@ -29,7 +29,7 @@
</h2>
{% endif %}
<ul class="site-structure-menu__list site-structure-menu__list--level-1">
<ul class="structural-pages-menu__list structural-pages-menu__list--level-1">
{% for item in tree %}
{{ _self.menu_item(item, active_trail, 1) }}
{% endfor %}
@@ -41,19 +41,19 @@
{% set is_active = item.id in active_trail %}
{% set has_children = item.children is not empty %}
{% set classes = [
'site-structure-menu__item',
'site-structure-menu__item--level-' ~ depth,
is_active ? 'site-structure-menu__item--active-trail',
has_children ? 'site-structure-menu__item--has-children',
'structural-pages-menu__item',
'structural-pages-menu__item--level-' ~ depth,
is_active ? 'structural-pages-menu__item--active-trail',
has_children ? 'structural-pages-menu__item--has-children',
] %}
<li{{ create_attribute().addClass(classes) }}>
<a href="{{ item.url }}" class="site-structure-menu__link{% if is_active %} site-structure-menu__link--active-trail{% endif %}">
<a href="{{ item.url }}" class="structural-pages-menu__link{% if is_active %} structural-pages-menu__link--active-trail{% endif %}">
{{- item.title -}}
</a>
{% if has_children %}
<ul class="site-structure-menu__list site-structure-menu__list--level-{{ depth + 1 }}">
<ul class="structural-pages-menu__list structural-pages-menu__list--level-{{ depth + 1 }}">
{% for child in item.children %}
{{ _self.menu_item(child, active_trail, depth + 1) }}
{% endfor %}

View File

@@ -1,10 +1,10 @@
# Portuguese (Brazil) translation for Site Structure module.
# Portuguese (Brazil) translation for Structural Pages module.
# Copyright (C) 2024
# This file is distributed under the same license as the Drupal package.
#
msgid ""
msgstr ""
"Project-Id-Version: Site Structure 1.0.0\n"
"Project-Id-Version: Structural Pages 1.0.0\n"
"POT-Creation-Date: 2024-01-01 00:00+0000\n"
"PO-Revision-Date: 2024-01-01 00:00+0000\n"
"Language-Team: Portuguese, Brazil\n"
@@ -14,19 +14,24 @@ msgstr ""
"Language: pt-br\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: site_structure.info.yml
msgid "Site Structure"
msgstr "Estrutura do Site"
#: structural_pages.info.yml
msgid "Structural Pages"
msgstr "Páginas Estruturais"
#: site_structure.info.yml
#: structural_pages.info.yml
msgid "Implements hierarchical editorial structure and contextual navigation for institutional sites."
msgstr "Implementa estrutura editorial hierárquica e navegação contextual para sites institucionais."
#: config/install/taxonomy.vocabulary.site_section.yml
#: config/install/field.field.node.section_page.field_site_section.yml
#: config/install/field.field.node.content_page.field_site_section.yml
msgid "Site Section"
msgstr "Seção do Site"
#: config/install/taxonomy.vocabulary.site_section.yml
#: config/install/taxonomy.vocabulary.site_sections.yml
msgid "Site Sections"
msgstr "Seções do Site"
#: config/install/taxonomy.vocabulary.site_sections.yml
msgid "Main hierarchical structure for site organization."
msgstr "Estrutura principal de organização hierárquica do site."
@@ -72,9 +77,9 @@ msgstr "Selecione a entidade pai. A seção do site será herdada automaticament
msgid "Body"
msgstr "Corpo"
#: config/install/pathauto.pattern.site_section_term.yml
msgid "Site Section Term"
msgstr "Termo de Seção do Site"
#: config/install/pathauto.pattern.site_sections_term.yml
msgid "Site Sections Term"
msgstr "Termo de Seções do Site"
#: config/install/views.view.child_pages.yml
msgid "Child Pages"
@@ -116,47 +121,47 @@ msgstr "Todos"
msgid "Block: Child Pages"
msgstr "Bloco: Páginas Filhas"
#: site_structure.install
msgid "Site Structure module installed successfully. Configure Pathauto patterns at /admin/config/search/path/patterns"
msgstr "Módulo Site Structure instalado com sucesso. Configure os padrões Pathauto em /admin/config/search/path/patterns"
#: structural_pages.install
msgid "Structural Pages module installed successfully. Configure Pathauto patterns at /admin/config/search/path/patterns"
msgstr "Módulo Páginas Estruturais instalado com sucesso. Configure os padrões Pathauto em /admin/config/search/path/patterns"
#: site_structure.install
msgid "Site Structure module uninstalled successfully."
msgstr "Módulo Site Structure desinstalado com sucesso."
#: structural_pages.install
msgid "Structural Pages module uninstalled successfully."
msgstr "Módulo Páginas Estruturais desinstalado com sucesso."
#: site_structure.install
#: structural_pages.install
msgid "Deleted @count @bundle nodes."
msgstr "@count nós do tipo @bundle excluídos."
#: site_structure.install
msgid "No terms in site_section vocabulary"
msgstr "Nenhum termo no vocabulário site_section"
#: structural_pages.install
msgid "No terms in site_sections vocabulary"
msgstr "Nenhum termo no vocabulário site_sections"
#: site_structure.install
msgid "The Site Structure module requires terms in the \"Site Section\" vocabulary. <a href=\":url\">Add terms</a>."
msgstr "O módulo Site Structure requer termos no vocabulário \"Seção do Site\". <a href=\":url\">Adicionar termos</a>."
#: structural_pages.install
msgid "The Structural Pages module requires terms in the \"Site Sections\" vocabulary. <a href=\":url\">Add terms</a>."
msgstr "O módulo Páginas Estruturais requer termos no vocabulário \"Seções do Site\". <a href=\":url\">Adicionar termos</a>."
#: site_structure.install
#: structural_pages.install
msgid "@count terms configured"
msgstr "@count termos configurados"
#: site_structure.module
#: structural_pages.module
msgid "Circular reference detected. A page cannot be a parent of itself or its ancestors."
msgstr "Referência circular detectada. Uma página não pode ser pai de si mesma ou de seus ancestrais."
#: site_structure.module
#: structural_pages.module
msgid "Site Section Path"
msgstr "Caminho da Seção do Site"
#: site_structure.module
msgid "The hierarchical path of the site_section taxonomy (e.g., undergraduate/courses)."
msgstr "O caminho hierárquico da taxonomia site_section (ex: graduacao/cursos)."
#: structural_pages.module
msgid "The hierarchical path of the site_sections taxonomy (e.g., undergraduate/courses)."
msgstr "O caminho hierárquico da taxonomia site_sections (ex: graduacao/cursos)."
#: site_structure.module
#: structural_pages.module
msgid "Hierarchy Path"
msgstr "Caminho Hierárquico"
#: site_structure.module
#: structural_pages.module
msgid "The hierarchical path of the term including ancestors (e.g., institutional/news)."
msgstr "O caminho hierárquico do termo incluindo ancestrais (ex: institucional/noticias)."
@@ -164,63 +169,63 @@ msgstr "O caminho hierárquico do termo incluindo ancestrais (ex: institucional/
msgid "Home"
msgstr "Início"
#: src/Form/SiteStructureSettingsForm.php
msgid "Site Structure Settings"
msgstr "Configurações da Estrutura do Site"
#: src/Form/StructuralPagesSettingsForm.php
msgid "Structural Pages Settings"
msgstr "Configurações das Páginas Estruturais"
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Select which entity types and bundles can be used as parent for Content Page nodes. This allows creating hierarchical structures where content pages can be children of different entity types."
msgstr "Selecione quais tipos de entidade e bundles podem ser usados como pai para nós de Página de Conteúdo. Isso permite criar estruturas hierárquicas onde páginas de conteúdo podem ser filhas de diferentes tipos de entidade."
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "<strong>Context behavior:</strong><br>\n - <em>Node/Taxonomy</em>: Content pages inherit the site section from the parent.<br>\n - <em>User</em>: Content pages are associated with the user profile page.<br>\n - <em>Group</em>: Content pages are associated with the group."
msgstr "<strong>Comportamento de contexto:</strong><br>\n - <em>Node/Taxonomia</em>: Páginas de conteúdo herdam a seção do site do pai.<br>\n - <em>Usuário</em>: Páginas de conteúdo são associadas à página de perfil do usuário.<br>\n - <em>Grupo</em>: Páginas de conteúdo são associadas ao grupo."
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Allowed Parent Targets"
msgstr "Alvos de Pai Permitidos"
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Content Types (node)"
msgstr "Tipos de Conteúdo (node)"
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Taxonomy Vocabularies (taxonomy_term)"
msgstr "Vocabulários de Taxonomia (taxonomy_term)"
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Users (user)"
msgstr "Usuários (user)"
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Groups (group)"
msgstr "Grupos (group)"
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "User accounts"
msgstr "Contas de usuário"
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Allow content pages to be children of user profiles."
msgstr "Permite que páginas de conteúdo sejam filhas de perfis de usuário."
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "All group types"
msgstr "Todos os tipos de grupo"
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Allow all current and future group types as parents."
msgstr "Permite todos os tipos de grupo atuais e futuros como pais."
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Field configuration updated successfully."
msgstr "Configuração do campo atualizada com sucesso."
#: site_structure.links.menu.yml
#: structural_pages.links.menu.yml
msgid "Configure allowed parent entity types for content pages."
msgstr "Configure os tipos de entidade pai permitidos para páginas de conteúdo."
#: Default taxonomy terms (site_structure.install)
#: Default taxonomy terms (structural_pages.install)
msgid "News"
msgstr "Notícias"
@@ -305,62 +310,62 @@ msgstr "Biblioteca"
msgid "IT Services"
msgstr "Informática"
#: src/Plugin/Block/SiteStructureMenuBlock.php
msgid "Site Structure Menu"
msgstr "Menu da Estrutura do Site"
#: src/Plugin/Block/StructuralPagesMenuBlock.php
msgid "Structural Pages Menu"
msgstr "Menu das Páginas Estruturais"
#: src/Plugin/Block/SiteStructureMenuBlock.php
#: src/Plugin/Block/StructuralPagesMenuBlock.php
msgid "Maximum depth"
msgstr "Profundidade máxima"
#: src/Plugin/Block/SiteStructureMenuBlock.php
#: src/Plugin/Block/StructuralPagesMenuBlock.php
msgid "Maximum number of levels to display."
msgstr "Número máximo de níveis a exibir."
#: src/Plugin/Block/SiteStructureMenuBlock.php
#: src/Plugin/Block/StructuralPagesMenuBlock.php
msgid "Show ancestor title"
msgstr "Exibir título do ancestral"
#: src/Plugin/Block/SiteStructureMenuBlock.php
#: src/Plugin/Block/StructuralPagesMenuBlock.php
msgid "Display the ancestor entity title as menu header."
msgstr "Exibir o título da entidade ancestral como cabeçalho do menu."
#: src/Plugin/Block/SiteStructureMenuBlock.php
#: src/Plugin/Block/StructuralPagesMenuBlock.php
msgid "Expand active trail"
msgstr "Expandir trilha ativa"
#: src/Plugin/Block/SiteStructureMenuBlock.php
#: src/Plugin/Block/StructuralPagesMenuBlock.php
msgid "Automatically expand menu items in the active trail."
msgstr "Expandir automaticamente os itens de menu na trilha ativa."
#: templates/site-structure-menu.html.twig
#: templates/structural-pages-menu.html.twig
msgid "Site structure navigation"
msgstr "Navegação da estrutura do site"
#: src/Plugin/ParentEntityHandler/TaxonomyTermHandler.php
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Taxonomy Vocabularies (taxonomy_term)"
msgstr "Vocabulários de Taxonomia (taxonomy_term)"
#: src/Plugin/ParentEntityHandler/UserHandler.php
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Users (user)"
msgstr "Usuários (user)"
#: src/Plugin/ParentEntityHandler/NodeHandler.php
#: src/Form/SiteStructureSettingsForm.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Content Types (node)"
msgstr "Tipos de Conteúdo (node)"
#: modules/site_structure_group/src/Plugin/ParentEntityHandler/GroupHandler.php
#: src/Form/SiteStructureSettingsForm.php
#: modules/structural_pages_group/src/Plugin/ParentEntityHandler/GroupHandler.php
#: src/Form/StructuralPagesSettingsForm.php
msgid "Groups (group)"
msgstr "Grupos (group)"
#: modules/site_structure_group/site_structure_group.info.yml
msgid "Site Structure Group Integration"
msgstr "Integração de Grupos do Site Structure"
#: modules/structural_pages_group/structural_pages_group.info.yml
msgid "Structural Pages Group Integration"
msgstr "Integração de Grupos das Páginas Estruturais"
#: modules/site_structure_group/site_structure_group.info.yml
msgid "Provides Group entity support as parent type for Site Structure module."
msgstr "Fornece suporte a entidades Grupo como tipo pai para o módulo Site Structure."
#: modules/structural_pages_group/structural_pages_group.info.yml
msgid "Provides Group entity support as parent type for Structural Pages module."
msgstr "Fornece suporte a entidades Grupo como tipo pai para o módulo Páginas Estruturais."