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_IDset to the menu parent - Child tabs can nest under parent tabs
MLT_Sequencedetermines display order in sidebarMLT_is_Public = 0marks 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 parentMLD_ID) MLD_File_Namemaps to actual file in documentation directory- Multiple documents can share the same
MLD_File_Nameif 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_IDrelationships MTD_Sequencedetermines 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:
- Explicit Document ID: If a numeric document ID is provided
- Tab ID + File Name: Match file name within specified tab
- Tab ID Only: Load first document in specified tab
- Default: Load first document in first available tab
5.2 Key Resolution Steps
Step 1: Parse URL Parameters
- Extract
tabIDandfilefrom URL - Validate tab exists and is accessible
Step 2: Locate Document
- If
fileis numeric, treat as document ID - If
fileis string, search for matchingMLD_File_Namewithin 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:
- Active Tab: Tab containing the currently displayed document
- Active Root Document: Root document of the current document (or document itself if root)
- 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
.mdextension 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 usersMLT_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
- Menu Building: Restricted tabs excluded from sidebar
- Document Loading: Access denied if tab is restricted
- Search Results: Restricted content filtered from results
- Direct URL Access: Redirect or show error if unauthorized
11. Content Loading
11.1 Markdown File Loading
Loading Process:
- Resolve document ID from URL
- Query database for
MLD_File_Name - Construct file path
- Read file contents
- 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:
- Invalid Tab: Load first available tab
- Invalid Document: Load first document in tab
- Missing File: Show error message but keep sidebar functional
- 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_IDfor hierarchy queries - Index
MLD_File_Namefor file lookups - Index
MTD_MLT_IDandMTD_MLD_IDfor 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.