bluefly/dita_ccms

DITA authoring and publishing framework for Drupal 10/11 with API-first approach and test-driven development.

dev-bryan1 2025-08-07 00:15 UTC

README

DITA-Compliant Enterprise Content Management
Built for technical documentation teams and enterprise knowledge management

๐Ÿ—๏ธ Architecture Overview

The DITA CCMS module provides comprehensive DITA (Darwin Information Typing Architecture) content management capabilities for Drupal, enabling technical documentation teams to author, manage, and publish structured content using industry-standard DITA XML format.

System Architecture

graph TB
    subgraph "Frontend Layer"
        UI[Authoring Interface]
        API[REST/GraphQL API]
        Admin[Admin Dashboard]
    end
    
    subgraph "Content Layer"
        DITA[DITA Topics & Maps]
        ECK[ECK Entities]
        Fields[Custom Fields]
        Workflow[Content Workflow]
    end
    
    subgraph "Processing Layer"
        Import[DITA Import]
        Export[DITA Export]
        Transform[DITA-OT Integration]
        Queue[Batch Processing]
    end
    
    subgraph "Storage Layer"
        DB[(Database)]
        Files[File Storage]
        Cache[Cache Layer]
        Search[Search Index]
    end
    
    UI --> DITA
    API --> DITA
    Admin --> Workflow
    DITA --> Import
    DITA --> Export
    Import --> DB
    Export --> Files
    Workflow --> Queue
    Queue --> Cache

DITA Content Types

graph LR
    subgraph "DITA Topic Types"
        Topic[Topic]
        Concept[Concept]
        Task[Task]
        Reference[Reference]
        Troubleshooting[Troubleshooting]
    end
    
    subgraph "Content Structure"
        Map[DITA Map]
        Bookmap[Bookmap]
        SubjectScheme[Subject Scheme]
    end
    
    subgraph "Relationships"
        RelTable[Relationship Table]
        CrossRef[Cross References]
        Links[External Links]
    end
    
    Map --> Topic
    Map --> Concept
    Map --> Task
    Topic --> RelTable
    Concept --> CrossRef
    Task --> Links

๐Ÿš€ Quick Start

Prerequisites

  • Drupal 10.3 or 11
  • PHP 8.1+
  • Required modules:
    • Entity Construction Kit (ECK) ^2.0
    • Content Moderation
    • Workflows
    • Feeds ^3.0
    • REST
    • Serialization
    • Views
    • Views Data Export
    • Field Group

Installation

# Using Composer (Recommended)
composer require drupal/dita_ccms
drush en dita_ccms -y

# Manual Installation
cd web/modules/custom/
git clone [repository-url] dita_ccms
drush en dita_ccms -y

Initial Configuration

  1. Configure DITA Topic Types

    # Navigate to admin interface
    drush uli
    # Go to: /admin/structure/dita-topic-types
    
  2. Set Up Workflows

    # Configure editorial workflow
    drush config:import:single --file=config/install/workflows.workflow.dita_editorial.yml
    
  3. Configure Import/Export

    # Set up DITA-OT integration
    drush config:set dita_ccms.settings dita_ot_path /opt/dita-ot
    

๐Ÿ“š DITA Content Management

Topic Creation Workflow

graph TD
    A[Create Topic] --> B[Select Topic Type]
    B --> C[Fill Required Fields]
    C --> D[Add Content]
    D --> E[Set Metadata]
    E --> F[Submit for Review]
    F --> G{Review Passed?}
    G -->|Yes| H[Publish]
    G -->|No| I[Return for Revision]
    I --> D
    H --> J[Archive]

Content Structure

# Example DITA Topic Structure
topic:
  title: "LLM Platform Integration Guide"
  type: "concept"
  metadata:
    audience: "developers"
    keywords: ["llm", "integration", "api"]
    status: "published"
    version: "1.0"
  content:
    - section: "Overview"
      content: "Integration guide for LLM Platform..."
    - section: "Prerequisites"
      content: "Required components and setup..."
    - section: "Implementation"
      content: "Step-by-step integration process..."

๐Ÿ”Œ API Integration

REST Endpoints

# OpenAPI Specification
openapi: 3.1.0
info:
  title: DITA CCMS API
  version: 1.0.0
paths:
  /api/dita/topics:
    get:
      summary: List DITA topics
      parameters:
        - name: type
          in: query
          schema:
            type: string
            enum: [topic, concept, task, reference]
    post:
      summary: Create DITA topic
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DitaTopic'

GraphQL Schema

# DITA Content Queries
type DitaTopic {
  id: ID!
  title: String!
  type: TopicType!
  content: String
  metadata: TopicMetadata
  workflow: WorkflowState
  created: DateTime!
  updated: DateTime!
}

type TopicMetadata {
  audience: String
  keywords: [String]
  status: String
  version: String
}

enum TopicType {
  TOPIC
  CONCEPT
  TASK
  REFERENCE
  TROUBLESHOOTING
}

๐Ÿงช Testing Strategy

Test-Driven Development

// tests/dita-content.spec.ts
import { test, expect } from '@playwright/test';

test.describe('DITA Content Management', () => {
  test('should create DITA topic', async ({ page }) => {
    await page.goto('/admin/content/dita-topics/add');
    
    // Fill required fields
    await page.fill('[name="title"]', 'Test DITA Topic');
    await page.selectOption('[name="topic_type"]', 'concept');
    await page.fill('[name="content"]', 'Test content for DITA topic');
    
    // Submit form
    await page.click('[type="submit"]');
    
    // Verify creation
    await expect(page.locator('.messages--status')).toContainText('Topic created');
  });
  
  test('should validate DITA XML export', async ({ page }) => {
    await page.goto('/admin/content/dita-topics');
    
    // Select topic for export
    await page.check('[name="topics[1]"]');
    await page.selectOption('[name="export_format"]', 'dita_xml');
    
    // Export
    await page.click('[name="export"]');
    
    // Verify XML output
    const content = await page.locator('pre').textContent();
    expect(content).toContain('<?xml version="1.0" encoding="UTF-8"?>');
    expect(content).toContain('<topic id="test-topic">');
  });
});

Quality Gates

# Run comprehensive tests
npx tddai test --module dita_ccms

# Validate OpenAPI specifications
npx tddai validate:openapi openapi/dita_ccms.openapi.yml

# Check coding standards
npx tddai standards-enforce --module dita_ccms

# Performance testing
npx tddai performance:test --module dita_ccms

๐Ÿ”„ Workflow Management

Editorial Workflow

stateDiagram-v2
    [*] --> Draft
    Draft --> InReview
    InReview --> NeedsRevision
    InReview --> Approved
    NeedsRevision --> Draft
    Approved --> Published
    Published --> Archived
    Archived --> Draft

Workflow Configuration

# config/install/workflows.workflow.dita_editorial.yml
langcode: en
status: true
dependencies:
  module:
    - content_moderation
id: dita_editorial
label: 'DITA Editorial Workflow'
type: content_moderation
type_settings:
  states:
    draft:
      label: 'Draft'
      weight: 0
      published: false
      default_revision: false
    in_review:
      label: 'In Review'
      weight: 1
      published: false
      default_revision: false
    approved:
      label: 'Approved'
      weight: 2
      published: false
      default_revision: false
    published:
      label: 'Published'
      weight: 3
      published: true
      default_revision: true
    archived:
      label: 'Archived'
      weight: 4
      published: false
      default_revision: false
  transitions:
    to_in_review:
      label: 'Submit for Review'
      from: [draft]
      to: in_review
      weight: 0
    approve:
      label: 'Approve'
      from: [in_review]
      to: approved
      weight: 0
    publish:
      label: 'Publish'
      from: [approved]
      to: published
      weight: 0
    archive:
      label: 'Archive'
      from: [published]
      to: archived
      weight: 0
    return_for_revision:
      label: 'Return for Revision'
      from: [in_review]
      to: draft
      weight: 0

๐Ÿ“Š Performance & Scalability

Caching Strategy

graph LR
    subgraph "Cache Layers"
        L1[L1: Memory Cache]
        L2[L2: Redis Cache]
        L3[L3: Database Cache]
    end
    
    subgraph "Cache Types"
        Content[Content Cache]
        Metadata[Metadata Cache]
        Search[Search Cache]
        Export[Export Cache]
    end
    
    L1 --> Content
    L2 --> Metadata
    L3 --> Search
    L2 --> Export

Batch Processing

<?php

namespace Drupal\dita_ccms\Plugin\QueueWorker;

use Drupal\Core\Queue\QueueWorkerBase;
use Drupal\Core\Queue\RequeueException;

/**
 * Processes DITA export queue items.
 *
 * @QueueWorker(
 *   id = "dita_export",
 *   title = @Translation("DITA Export Processor"),
 *   cron = {"time" = 60}
 * )
 */
class DitaExportQueueWorker extends QueueWorkerBase {

  /**
   * {@inheritdoc}
   */
  public function processItem($data) {
    try {
      $this->exportDitaContent($data);
    }
    catch (\Exception $e) {
      // Requeue on failure
      throw new RequeueException($e->getMessage());
    }
  }
}

๐Ÿ”’ Security & Compliance

Access Control

# config/install/dita_ccms.permissions.yml
dita_ccms:
  # Content creation
  create dita_topic: true
  create dita_map: true
  
  # Content editing
  edit own dita_topic: true
  edit any dita_topic: false
  
  # Workflow management
  use dita_editorial workflow: true
  moderate dita_editorial workflow: false
  
  # Export permissions
  export dita_content: true
  export dita_xml: false  # Restricted to admins

Audit Logging

<?php

namespace Drupal\dita_ccms\EventSubscriber;

use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Logs DITA content operations for compliance.
 */
class DitaAuditSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      'dita_ccms.topic.created' => 'logTopicCreation',
      'dita_ccms.topic.updated' => 'logTopicUpdate',
      'dita_ccms.topic.deleted' => 'logTopicDeletion',
      'dita_ccms.content.exported' => 'logContentExport',
    ];
  }

  /**
   * Logs topic creation events.
   */
  public function logTopicCreation($event) {
    $this->logger->info('DITA topic created: @title by @user', [
      '@title' => $event->getTopic()->getTitle(),
      '@user' => $event->getUser()->getAccountName(),
    ]);
  }
}

๐ŸŒ Integration Examples

LLM Platform Integration

<?php

namespace Drupal\dita_ccms\Service;

use Drupal\llm\Service\LlmServiceInterface;

/**
 * Integrates DITA CCMS with LLM Platform.
 */
class LlmIntegrationService {

  /**
   * Generates DITA content using AI.
   */
  public function generateDitaContent($prompt, $topicType) {
    $llmService = \Drupal::service('llm.service');
    
    $response = $llmService->generate([
      'prompt' => "Generate DITA $topicType content: $prompt",
      'model' => 'gpt-4',
      'format' => 'dita_xml'
    ]);
    
    return $this->parseDitaResponse($response);
  }
}

MCP Server Integration

<?php

namespace Drupal\dita_ccms\Mcp;

use Drupal\mcp_registry\McpServerInterface;

/**
 * MCP Server for DITA CCMS operations.
 */
class DitaMcpServer implements McpServerInterface {

  /**
   * Lists available DITA topics.
   */
  public function listTopics($params) {
    $topics = $this->entityTypeManager
      ->getStorage('dita_topic')
      ->loadMultiple();
    
    return array_map(function($topic) {
      return [
        'id' => $topic->id(),
        'title' => $topic->getTitle(),
        'type' => $topic->getTopicType(),
        'status' => $topic->getWorkflowStatus(),
      ];
    }, $topics);
  }
}

๐Ÿ“ˆ Monitoring & Analytics

Performance Metrics

# config/install/dita_ccms.monitoring.yml
monitoring:
  metrics:
    content_creation_rate:
      type: counter
      description: "DITA topics created per hour"
      threshold: 100
    
    export_processing_time:
      type: histogram
      description: "Time to process export requests"
      buckets: [0.1, 0.5, 1.0, 2.0, 5.0]
    
    workflow_transition_rate:
      type: counter
      description: "Workflow state transitions per hour"
      threshold: 50

Health Checks

<?php

namespace Drupal\dita_ccms\Health;

use Drupal\Core\Health\HealthCheckInterface;

/**
 * Health check for DITA CCMS module.
 */
class DitaHealthCheck implements HealthCheckInterface {

  /**
   * {@inheritdoc}
   */
  public function run() {
    $issues = [];
    
    // Check DITA-OT availability
    if (!$this->isDitaOtAvailable()) {
      $issues[] = 'DITA Open Toolkit not available';
    }
    
    // Check workflow configuration
    if (!$this->isWorkflowConfigured()) {
      $issues[] = 'Editorial workflow not configured';
    }
    
    // Check permissions
    if (!$this->arePermissionsCorrect()) {
      $issues[] = 'Permission configuration issues detected';
    }
    
    return [
      'status' => empty($issues) ? 'healthy' : 'unhealthy',
      'issues' => $issues,
    ];
  }
}

๐Ÿ”ง Development & Customization

Custom Topic Types

<?php

namespace Drupal\custom_module\Plugin\DitaTopicType;

use Drupal\dita_ccms\Plugin\DitaTopicType\DitaTopicTypeBase;

/**
 * Custom DITA topic type for API documentation.
 *
 * @DitaTopicType(
 *   id = "api_doc",
 *   label = @Translation("API Documentation"),
 *   description = @Translation("Documentation for API endpoints and usage")
 * )
 */
class ApiDocTopicType extends DitaTopicTypeBase {

  /**
   * {@inheritdoc}
   */
  public function getFields() {
    return [
      'endpoint_url' => [
        'type' => 'string',
        'label' => 'API Endpoint URL',
        'required' => TRUE,
      ],
      'http_method' => [
        'type' => 'list',
        'label' => 'HTTP Method',
        'options' => ['GET', 'POST', 'PUT', 'DELETE'],
        'required' => TRUE,
      ],
      'request_schema' => [
        'type' => 'text_long',
        'label' => 'Request Schema (JSON)',
      ],
      'response_schema' => [
        'type' => 'text_long',
        'label' => 'Response Schema (JSON)',
      ],
    ];
  }
}

Custom Export Formats

<?php

namespace Drupal\custom_module\Plugin\DitaExportFormat;

use Drupal\dita_ccms\Plugin\DitaExportFormat\DitaExportFormatBase;

/**
 * Exports DITA content to Confluence format.
 *
 * @DitaExportFormat(
 *   id = "confluence",
 *   label = @Translation("Confluence"),
 *   description = @Translation("Export to Confluence wiki format")
 * )
 */
class ConfluenceExportFormat extends DitaExportFormatBase {

  /**
   * {@inheritdoc}
   */
  public function export($content, $options = []) {
    // Convert DITA to Confluence markup
    $confluenceMarkup = $this->convertDitaToConfluence($content);
    
    return [
      'content' => $confluenceMarkup,
      'mime_type' => 'text/plain',
      'filename' => $options['filename'] ?? 'export.txt',
    ];
  }
}

๐Ÿ“š Related Documentation

๐Ÿค Contributing

  1. Follow DITA Authoring Guidelines
  2. Use Development Templates
  3. Include Mermaid Diagrams for complex workflows
  4. Validate OpenAPI specifications before committing
  5. Run comprehensive tests: npx tddai test --module dita_ccms

๐Ÿ“ž Support

This module follows DITA 1.3 standards and integrates seamlessly with the LLM Platform ecosystem.