Files
structural_pages/docs/DESIGN.md
Quintino A. G. Souza 8a42a6f1c1 Initial commit: Site Structure module for Drupal
Drupal module that provides hierarchical site structure management
with support for sections, categories, and content items. Includes
path aliases with tokens, breadcrumb integration, and admin interface.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 19:55:00 -03:00

13 KiB

Site Structure - 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.

Problem

In Drupal, content is added in a flat manner (non-hierarchical), and menus are traditionally used to organize content into hierarchical structures. This creates user experience problems because content editors typically do not have permission to administer menus.

Solution

The module implements two complementary structures:

  1. Taxonomic Structure (primary): Organization based on hierarchical taxonomy vocabulary
  2. Parent-Child Structure (subsidiary): Direct hierarchy between pages for specific cases, supporting multiple entity types as parents

Conceptual Model

┌─────────────────────────────────────────────────────────────────────┐
│  PRIMARY STRUCTURE: site_section Taxonomy                           │
│                                                                     │
│  - Governs the overall organization of site information             │
│  - Defines breadcrumbs and URLs (via Pathauto)                      │
│  - Example: Undergraduate > Courses > Software Engineering          │
│  - Applied to content type: section_page                            │
├─────────────────────────────────────────────────────────────────────┤
│  SUBSIDIARY STRUCTURE: Parent-Child (field_parent_page)             │
│                                                                     │
│  - For specific cases: manuals, guides, sequential documentation    │
│  - Provides contextual navigation (Child pages View)                │
│  - Automatically inherits site section from parent (node/taxonomy)  │
│  - For user/group parents, context is the entity itself             │
│  - Applied to content type: content_page                            │
│  - Supports multiple parent types: content_page, section_page,      │
│    taxonomy terms, users, groups (configurable)                     │
├─────────────────────────────────────────────────────────────────────┤
│  page (core Drupal)                                                 │
│                                                                     │
│  - Remains untouched for generic use                                │
└─────────────────────────────────────────────────────────────────────┘

Components

1. Taxonomy Vocabulary: site_section

Property Value
Machine name site_section
Name Site Section
Hierarchical Yes
Description Main hierarchical structure for site organization

Usage: This vocabulary defines site sections. Terms can be nested to create hierarchies (e.g., "Undergraduate" > "Courses" > "Engineering").

2. Content Type: section_page

Property Value
Machine name section_page
Name Section Page
Description Pages organized by site section

Fields:

Field Type Required Cardinality Description
title String Yes 1 Page title (core)
body Text (formatted, long, with summary) No 1 Page content
field_site_section Entity reference (taxonomy) Yes 1 Site section

3. Content Type: content_page

Property Value
Machine name content_page
Name Content Page
Description Pages with hierarchical parent-child structure

Fields:

Field Type Required Cardinality Description
title String Yes 1 Page title (core)
body Text (formatted, long, with summary) No 1 Page content
field_parent_page Dynamic entity reference No 1 Parent entity (configurable types)
field_site_section Entity reference (taxonomy) Conditional 1 Site section (inherited or manual)

Rules for field_site_section in content_page:

  • If field_parent_page points to a taxonomy_term: uses the term itself as site section
  • If field_parent_page points to a node: inherits field_site_section from parent
  • If field_parent_page is empty (root page): must be filled manually

4. Dynamic Parent Reference

The field_parent_page uses the Dynamic Entity Reference module to support multiple entity types as parents. This is configurable via the admin interface.

Default allowed targets:

  • node:content_page - Other content pages
  • node:section_page - Section pages
  • taxonomy_term:site_section - Site section terms
  • user:user - User accounts
  • group:* - All group types (requires Group module)

Context behavior by parent type:

  • Node/Taxonomy: Content pages inherit field_site_section from the parent
  • 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

5. Inheritance Logic

Implemented via hook_entity_presave():

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):
            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
    ELSE:
        Validate that field_site_section was filled manually

Additional validations:

  • Prevent self-reference (page cannot be parent of itself)
  • Prevent circularity (A → B → C → A) - only for node parents

6. Breadcrumb Builder

Custom service that overrides Drupal's default breadcrumb for section_page and content_page.

Logic:

  1. Determine the root parent context by traversing the parent chain
  2. Build breadcrumb based on context type:
    • User context: Home > User Name > Parent Nodes > Current Page
    • Group context: Home > Group Name > Parent Nodes > Current Page
    • Taxonomy context: Home > Term Hierarchy > Parent Nodes > Current Page
  3. For content_page, also add node parents to the breadcrumb

Examples:

  • Page "Chapter 1" has parent "User Guide" which is a section_page in "Documentation"
    • Breadcrumb: Home > Documentation > User Guide > Chapter 1
  • Page "My Notes" has parent user "John Doe"
    • Breadcrumb: Home > John Doe > My Notes
  • Page "Meeting Minutes" has parent group "Research Team"
    • Breadcrumb: Home > Research Team > Meeting Minutes

7. Pathauto Tokens

Custom token for hierarchical URL generation.

Token Description Example
[node:site-section-path] Path based on taxonomy hierarchy undergraduate/courses

Suggested URL pattern: [node:site-section-path]/[node:title]

Result: /undergraduate/courses/software-engineering

8. View: child_pages

View that lists child pages of the current content_page.

Property Value
Display Block
Filter field_parent_page = Current node ID (contextual)
Sort Title (A-Z) or weight (if implemented)
Usage Sidebar navigation in guides/manuals

9. Settings Form

Configuration form at /admin/config/local-modules/site-structure 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

File Structure

site_structure/
├── site_structure.info.yml              # Metadata and dependencies
├── site_structure.module                # Hooks (presave, tokens)
├── 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
│
├── config/
│   ├── install/
│   │   ├── site_structure.settings.yml  # Default settings
│   │   ├── taxonomy.vocabulary.site_section.yml
│   │   │
│   │   ├── node.type.section_page.yml
│   │   ├── field.storage.node.field_site_section.yml
│   │   ├── field.field.node.section_page.field_site_section.yml
│   │   ├── core.entity_form_display.node.section_page.default.yml
│   │   ├── core.entity_view_display.node.section_page.default.yml
│   │   │
│   │   ├── node.type.content_page.yml
│   │   ├── field.storage.node.field_parent_page.yml  # dynamic_entity_reference
│   │   ├── field.field.node.content_page.field_parent_page.yml
│   │   ├── field.field.node.content_page.field_site_section.yml
│   │   ├── core.entity_form_display.node.content_page.default.yml
│   │   ├── core.entity_view_display.node.content_page.default.yml
│   │   │
│   │   ├── pathauto.pattern.section_page.yml
│   │   ├── pathauto.pattern.content_page.yml
│   │   ├── pathauto.pattern.site_section_term.yml
│   │   │
│   │   └── views.view.child_pages.yml
│   │
│   └── schema/
│       └── site_structure.schema.yml    # Config schema
│
├── translations/
│   └── pt-br.po                         # Portuguese (Brazil) translation
│
├── src/
│   ├── Breadcrumb/
│   │   └── SectionBreadcrumbBuilder.php
│   │
│   └── Form/
│       └── SiteStructureSettingsForm.php
│
└── docs/
    └── DESIGN.md                        # This document

Dependencies

Core Modules (Drupal 11)

  • node
  • taxonomy
  • views
  • field
  • text
  • user

Contrib Modules

  • token - For custom tokens
  • pathauto - For automatic URL generation
  • dynamic_entity_reference - For multi-type parent references

Optional Modules

  • group - For group entity support as parent type

Editor Workflow

Creating a Section Page (section_page)

  1. Navigate to Content > Add content > Section Page
  2. Fill in title and body
  3. Select the appropriate site section
  4. Save
  5. URL and breadcrumb are generated automatically

Creating a Content Page (content_page)

  1. Create root page (anchored to taxonomy term):

    • Add content > Content Page
    • In "Parent Page", select a site_section term
    • Site section is set automatically from the term
    • Save
  2. Create root page (anchored to section_page):

    • Add content > Content Page
    • In "Parent Page", select a section_page
    • Site section is inherited from the section_page
    • Save
  3. Create child pages:

    • Add content > Content Page
    • In "Parent Page", select another content_page
    • Site section is inherited automatically
    • Save
  4. The child pages View appears automatically on parent pages


Administration

Configuring Allowed Parent Types

  1. Navigate to /admin/config/local-modules/site-structure
  2. Select which content types (nodes) can be used as parents
  3. Select which taxonomy vocabularies can be used as parents
  4. Save configuration
  5. Field configuration is updated automatically

Group Integration

The module supports the Group module for content organization:

  • Content pages can have groups as parent entities
  • When a content_page has a group as parent, the context is the group itself
  • Breadcrumbs show: Home > Group Name > Parent Nodes > Current Page
  • field_site_section is cleared for group-parented content (context is the group)
  • Per-section permissions can be implemented via Groups

Configuration: Enable group types in the settings form at /admin/config/local-modules/site-structure


Installation Verification

  1. drush en site_structure -y
  2. Verify vocabulary at /admin/structure/taxonomy
  3. Verify content types at /admin/structure/types
  4. Create test hierarchical terms
  5. Create section_page and verify breadcrumb/URL
  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

Changelog

Version Date Description
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