Developer (Technical) Guide

1. Purpose and Scope

This document explains the internal architecture, data flow, and integration points of the Documentation Module. It is intended for developers maintaining, extending, or debugging the module.

The Documentation Module provides a browsable, permission-aware documentation viewer that renders Markdown files with hierarchical sidebar navigation and search capabilities.


2. High-Level Architecture

The module consists of two layers working together:

2.1 Frontend Layer

Responsibilities:

  • Route handling and URL parsing
  • Initial page rendering and layout
  • Widget initialization
  • History state management
  • User interaction handling

2.2 Webservice Layer

Responsibilities:

  • Data loading and validation
  • Permission enforcement
  • Sidebar and content rendering
  • Document resolution logic
  • Search functionality
  • Markdown file loading

2.3 Data Flow

User Request
    ↓
URL Manager (route parsing)
    ↓
Documentation Controller
    ↓
Webservice API: get-requested-widget
    ↓
Documentation Service (resolve document, load data)
    ↓
Permission filtering and menu building
    ↓
Render sidebar HTML + document content
    ↓
Return to frontend
    ↓
Display in browser with JS handlers

3. Data Model and Database Structure

3.1 Tables Overview

ML_Tabs_copy (Tabs)

Represents documentation categories/sections that appear in the sidebar.

Field Type Description
MLT_ID INT Primary key, tab identifier
MLT_Parent_ID INT Parent tab ID for hierarchy
MLT_Label VARCHAR Display name of the tab
MLT_is_Public TINYINT Visibility flag (0=restricted, 1=public)
MLT_Sequence INT Display order
MLT_is_Active TINYINT Active status

Key Points:

  • Root tabs have MLT_Parent_ID set to the menu parent
  • Child tabs can nest under parent tabs
  • MLT_Sequence determines display order in sidebar
  • MLT_is_Public = 0 marks restricted tabs

ML_Docs (Documents)

Represents individual documentation pages.

Field Type Description
MLD_ID INT Primary key, document identifier
MLD_Parent_ID INT Parent document ID (0 = root document)
MLD_Chapter_Name VARCHAR Display label for the document
MLD_File_Name VARCHAR Markdown filename (e.g., installation.md)
MLD_is_Active TINYINT Active status

Key Points:

  • Root documents: MLD_Parent_ID = 0
  • Child documents: MLD_Parent_ID > 0 (references parent MLD_ID)
  • MLD_File_Name maps to actual file in documentation directory
  • Multiple documents can share the same MLD_File_Name if in different contexts

ML_Tab_Docs (Tab-Document Mapping)

Links tabs to their root documents and controls document order.

Field Type Description
MTD_ID INT Primary key
MTD_MLT_ID INT Foreign key to ML_Tabs_copy.MLT_ID
MTD_MLD_ID INT Foreign key to ML_Docs.MLD_ID (root documents only)
MTD_Sequence INT Display order within the tab

Key Points:

  • Only root documents (MLD_Parent_ID = 0) are linked via this table
  • Child documents are discovered through MLD_Parent_ID relationships
  • MTD_Sequence determines document order within each tab

3.2 Relationship Diagram

ML_Tabs_copy (Parent Tab)
    ↓ MLT_Parent_ID
ML_Tabs_copy (Child Tabs) ←→ ML_Tab_Docs ←→ ML_Docs (Root Documents)
                              MTD_MLT_ID   MTD_MLD_ID     MLD_ID
                                                            ↓ MLD_Parent_ID
                                                      ML_Docs (Child Documents)

3.3 Example Data Structure

-- Tab: "Getting Started" (ID: 5)
ML_Tabs_copy: MLT_ID=5, MLT_Label="Getting Started", MLT_Parent_ID=1

-- Root Document: "Installation" (ID: 10)
ML_Docs: MLD_ID=10, MLD_Parent_ID=0, MLD_Chapter_Name="Installation", MLD_File_Name="installation.md"

-- Child Document: "Windows Setup" (ID: 11)
ML_Docs: MLD_ID=11, MLD_Parent_ID=10, MLD_Chapter_Name="Windows Setup", MLD_File_Name="windows-setup.md"

-- Mapping: Link tab to root document
ML_Tab_Docs: MTD_MLT_ID=5, MTD_MLD_ID=10, MTD_Sequence=1

4. URL Structure and Routing

4.1 URL Patterns

The documentation module supports the following URL patterns:

Supported URL Patterns:

Pattern Example Description
/documentation /documentation Default: loads first tab and first document
/documentation/{tabId} /documentation/5 Loads first document in specified tab
/documentation/{tabId}/{filename} /documentation/5/installation.md Loads specific file in specified tab

Important Notes:

  • {tabId} must be numeric
  • {filename} can include subdirectories (e.g., guides/setup.md)
  • Child documents also use the same URL pattern: {tabId}/{filename} instead of a separate child ID segment
  • This ensures consistent URL structure across all documentation levels
  • Case sensitivity: File names are case-sensitive; tab IDs are numeric

4.2 URL Parameter Mapping

When a request matches a route, parameters are mapped to the controller:

public function actionIndex($tabID = null, $file = null, $menuTabID = null)
  • $tabID: From URL segment /documentation/{tabID}
  • $file: From URL segment /documentation/{tabID}/{file} (includes child document filenames)
  • $menuTabID: From query parameter or configuration (parent tab context)

4.3 Hierarchical Navigation with Consistent URLs

The URL structure remains consistent regardless of document hierarchy:

Parent Document:    /documentation/{tabId}/installation.md
Child Document:     /documentation/{tabId}/windows-setup.md
Grandchild Doc:     /documentation/{tabId}/advanced-config.md

Key Benefits:

  • Simple, predictable URL structure
  • Easy to bookmark and share
  • No special handling needed for different document levels
  • Parent-child relationships maintained through database, not URL structure

5. Document Resolution Logic

5.1 Resolution Flow

The document resolution process determines which document to display based on URL parameters and database state.

Resolution Priority:

  1. Explicit Document ID: If a numeric document ID is provided
  2. Tab ID + File Name: Match file name within specified tab
  3. Tab ID Only: Load first document in specified tab
  4. Default: Load first document in first available tab

5.2 Key Resolution Steps

Step 1: Parse URL Parameters

  • Extract tabID and file from URL
  • Validate tab exists and is accessible

Step 2: Locate Document

  • If file is numeric, treat as document ID
  • If file is string, search for matching MLD_File_Name within tab
  • Return first document if no file specified

Step 3: Verify Permissions

  • Check tab visibility (MLT_is_Public)
  • Verify user has access to requested tab
  • Fall back to accessible content if permission denied

Step 4: Load Content

  • Retrieve document metadata from database
  • Load Markdown file from file system
  • Return document content or error message

5.3 Child Document Resolution

Child documents are resolved through the same mechanism:

// Example: Loading child document
// URL: /documentation/5/windows-setup.md
// 
// Resolution:
// 1. Find document where MLD_File_Name = 'windows-setup.md'
// 2. Load parent relationship via MLD_Parent_ID
// 3. Build menu structure showing parent-child hierarchy
// 4. Mark active states in sidebar

6. Sidebar Menu Structure

6.1 Menu Building Process

The sidebar menu is built server-side with the following structure:

Tab 1
  ├─ Root Document 1
  │   ├─ Child Document 1.1
  │   └─ Child Document 1.2
  └─ Root Document 2
Tab 2
  └─ Root Document 3
      └─ Child Document 3.1

6.2 Menu Data Structure

[
    'tabs' => [
        [
            'id' => 5,
            'label' => 'Getting Started',
            'isActive' => true,
            'docs' => [
                [
                    'id' => 10,
                    'title' => 'Installation',
                    'file' => 'installation.md',
                    'isActive' => true,
                    'children' => [
                        [
                            'id' => 11,
                            'title' => 'Windows Setup',
                            'file' => 'windows-setup.md',
                            'isActive' => false
                        ]
                    ]
                ]
            ]
        ]
    ]
]

6.3 Active State Computation

Active states are computed server-side during menu building:

  1. Active Tab: Tab containing the currently displayed document
  2. Active Root Document: Root document of the current document (or document itself if root)
  3. Active Child Document: Currently displayed document if it's a child

Active State Algorithm:

For each tab:
    If tab contains currentDocument:
        Mark tab as active

For each document in active tab:
    If document.id == currentDocument.id:
        Mark document as active
    If document is parent of currentDocument:
        Mark document as active parent

For each child in active document:
    If child.id == currentDocument.id:
        Mark child as active

6.4 HTML Structure

<ul class="doc-menu">
    <li class="tab-item active">
        <span class="tab-label">Getting Started</span>
        <ul class="doc-list">
            <li class="doc-item active">
                <a href="/documentation/5/installation.md">Installation</a>
                <ul class="child-list">
                    <li class="child-item">
                        <a href="/documentation/5/windows-setup.md">Windows Setup</a>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

7. Search Functionality

7.1 Search Flow

User enters search query (min 3 characters)
    ↓
JavaScript sends AJAX request
    ↓
Server searches document content
    ↓
Returns matching documents with snippets
    ↓
Results displayed in sidebar

7.2 Search Implementation

Search Criteria:

  • Minimum query length: 3 characters
  • Searches document content (loaded from files)
  • Searches document titles (MLD_Chapter_Name)
  • Respects permission settings

Search Result Format:

{
    "results": [
        {
            "document_id": "10",
            "title": "Installation",
            "file": "installation.md",
            "snippet": "...matching content...",
            "tab_id": "5"
        }
    ]
}

7.3 Search Limitations

  • Simple text search (case-insensitive substring matching)
  • No fuzzy matching or typo tolerance
  • No result ranking or relevance scoring
  • Searches file content (not indexed)
  • Performance may degrade with large documentation sets

8. JavaScript Integration

8.1 Client-Side Responsibilities

Navigation Handling:

  • Intercept link clicks within documentation
  • Update URL via History API (pushState)
  • Load new content via AJAX
  • Handle browser back/forward (popstate)

Search Handling:

  • Debounce search input
  • Send search requests
  • Display search results
  • Clear results on input clear

UI State Management:

  • Toggle child document lists
  • Manage active states visually
  • Show loading indicators
  • Handle errors gracefully

8.2 Key JavaScript Functions

// Navigate to document
function loadDocument(tabId, filename) {
    // Update URL
    // Load content via AJAX
    // Update sidebar active states
}

// Handle search
function searchDocuments(query) {
    // Validate query length
    // Send AJAX request
    // Display results
}

// Browser history
window.onpopstate = function(event) {
    // Parse URL
    // Load appropriate document
    // Restore state
}

8.3 URL Construction

When constructing URLs for navigation (both for links and History API):

// All documents use same pattern: {tabId}/{filename}
const url = `/documentation/${tabId}/${filename}`;

// Examples:
// /documentation/5/installation.md         (root document)
// /documentation/5/windows-setup.md        (child document)
// /documentation/5/advanced-config.md      (grandchild document)

Important: No special URL segments for child documents - hierarchy is maintained through database relationships.


9. File System Organization

9.1 Directory Structure

docs/
└── docs/
    ├── installation.md
    ├── windows-setup.md
    ├── advanced-config.md
    ├── guides/
    │   ├── quickstart.md
    │   └── troubleshooting.md
    └── api/
        └── reference.md

9.2 File Naming Conventions

  • Use lowercase with hyphens: user-guide.md
  • Avoid spaces in filenames
  • Use .md extension for Markdown files
  • Organize related files in subdirectories
  • Keep filenames descriptive but concise

9.3 File Content Guidelines

Markdown Best Practices:

  • Use proper heading hierarchy (#, ##, ###)
  • Include code blocks with syntax highlighting
  • Use relative links for internal references
  • Add alt text for images
  • Keep lines under 120 characters for readability

10. Permission System

10.1 Permission Model

Permissions are controlled at the tab level:

  • MLT_is_Public = 1: Tab visible to all users
  • MLT_is_Public = 0: Tab restricted to authorized users

Document-Level Access:

  • Documents inherit permissions from their parent tab
  • No separate document-level permissions

10.2 Permission Checking

// Check if user has access to tab
public function hasTabAccess($tabID) {
    // Query tab visibility
    // Check user permissions
    // Return boolean
}

10.3 Permission Enforcement Points

  1. Menu Building: Restricted tabs excluded from sidebar
  2. Document Loading: Access denied if tab is restricted
  3. Search Results: Restricted content filtered from results
  4. Direct URL Access: Redirect or show error if unauthorized

11. Content Loading

11.1 Markdown File Loading

Loading Process:

  1. Resolve document ID from URL
  2. Query database for MLD_File_Name
  3. Construct file path
  4. Read file contents
  5. Return raw Markdown or error message

Error Handling:

  • File not found: Display user-friendly message
  • Read permission error: Log error and show generic message
  • Invalid file path: Sanitize and reject

11.2 Content Rendering

Rendering Flow:

Markdown file loaded from disk
    ↓
Sent to frontend as raw text
    ↓
Client-side Markdown renderer processes content
    ↓
HTML displayed in content area

Markdown Renderer Configuration:

  • Syntax highlighting for code blocks
  • Table support
  • Task list support
  • Auto-linking URLs
  • Safe mode enabled (XSS protection)

12. AJAX Operations

12.1 Load Widget Content

Endpoint: POST /documentation/documentation/get-widget

Purpose: Load sidebar and document content

Request:

{
    "file": "10",
    "menuTabID": "1",
    "parentTabID": "5",
    "rootDocId": "10"
}

Response:

{
    "sidebar": "<ul>...</ul>",
    "content": "# Installation\n\n..."
}

12.2 Resolve Document

Endpoint: POST /documentation/documentation/get-requested-widget

Purpose: Initial document resolution

Request:

{
    "tabID": "5",
    "file": "installation.md",
    "menuTabID": "1"
}

Response:

{
    "status": 1,
    "documentID": 10,
    "parentTabID": 5,
    "file": "installation.md"
}

12.3 Search Documents

Endpoint: POST /documentation/documentation/search

Purpose: Search documentation

Request:

{
    "query": "installation",
    "menuTabID": "1",
    "parentTabID": "5"
}

Response:

{
    "results": [
        {
            "document_id": "10",
            "title": "Installation",
            "file": "installation.md",
            "snippet": "...matching content...",
            "tab_id": "5"
        }
    ]
}

13. Error Handling

13.1 Common Error Scenarios

Document Not Found:

  • Database record exists but file missing
  • Response: Display message "Document content not available"

Permission Denied:

  • User lacks access to requested tab
  • Response: Redirect to default or show access denied message

Invalid Parameters:

  • Malformed tab ID or file name
  • Response: Fall back to default document

File Read Errors:

  • File system permission issues
  • Response: Log error, show generic message to user

13.2 Error Response Format

{
    "status": 0,
    "error": "Document not found",
    "message": "The requested document could not be loaded."
}

13.3 Fallback Behavior

When errors occur, the system falls back gracefully:

  1. Invalid Tab: Load first available tab
  2. Invalid Document: Load first document in tab
  3. Missing File: Show error message but keep sidebar functional
  4. Permission Denied: Redirect to accessible content

14. Performance Considerations

14.1 Optimization Strategies

Database Queries:

  • Load all tabs and documents in single query where possible
  • Use JOIN operations to reduce round trips
  • Filter by permissions early in query

File Loading:

  • Read files only when needed
  • Consider caching frequently accessed documents
  • Use efficient file reading methods

Menu Building:

  • Build complete menu structure server-side
  • Send as HTML to reduce client-side processing
  • Cache menu structure per user/permission set

14.2 Scalability Notes

For Large Documentation Sets:

  • Consider implementing lazy loading for child documents
  • Add pagination for search results
  • Implement file content caching
  • Use CDN for static Markdown files

Database Considerations:

  • Index MLT_Parent_ID for hierarchy queries
  • Index MLD_File_Name for file lookups
  • Index MTD_MLT_ID and MTD_MLD_ID for join operations

15. Testing Scenarios

15.1 Functional Tests

  • [ ] Load default page (no parameters)
  • [ ] Navigate to specific tab
  • [ ] Navigate to specific document via URL
  • [ ] Navigate to child document via URL
  • [ ] Click links in sidebar to navigate
  • [ ] Use browser back/forward buttons
  • [ ] Refresh page and verify state
  • [ ] Search for content
  • [ ] Clear search and return to navigation
  • [ ] Toggle child document lists

15.2 Permission Tests

  • [ ] Access public tab (should succeed)
  • [ ] Access restricted tab as unauthorized user (should fail)
  • [ ] Access restricted tab as authorized user (should succeed)
  • [ ] Search results exclude restricted content
  • [ ] Direct URL to restricted document (should deny)

15.3 Edge Cases

  • [ ] Document exists in database but file missing
  • [ ] Multiple documents with same filename
  • [ ] Empty tabs (no documents)
  • [ ] Very long document content
  • [ ] Search with special characters
  • [ ] Malformed URLs
  • [ ] Concurrent navigation requests

15.4 Browser Compatibility

  • [ ] Chrome/Edge (latest)
  • [ ] Firefox (latest)
  • [ ] Safari (latest)
  • [ ] Mobile browsers (iOS Safari, Chrome Android)

16. Summary

The Documentation Module is a server-driven, permission-aware system with the following key characteristics:

Architecture:

  • Two-layer design (frontend + webservice)
  • Server-side document resolution and permission enforcement
  • Client-side history management and AJAX loading

Data Model:

  • Three main tables: ML_Tabs_copy, ML_Docs, ML_Tab_Docs
  • Parent-child relationships via MLD_Parent_ID
  • Permission control via MLT_is_Public

URL Handling:

  • Consistent URL pattern for all documents: /documentation/{tabId}/{filename}
  • Child documents use the same URL structure as parent documents
  • Document hierarchy maintained through database relationships, not URL structure
  • Document resolution priority: explicit ID → filename → first in tab → default
  • Browser history integration with pushState/popstate

Active States:

  • Computed server-side during menu building
  • Applied as CSS classes in HTML
  • Not recalculated client-side

Extension Points:

  • Add documents and tabs via database
  • Modify resolution logic in service layer
  • Customize rendering in view templates
  • Enhance search functionality

This centralized, server-driven approach ensures predictable behavior, secure access control, and easy extensibility while maintaining a smooth user experience.

Use / to focus search. Press Enter to run. Esc clears.