Fix guide template variable replacement and enhance documentation
- Fix template variable replacement in guide pages by removing {{}} brackets
- Escape code blocks in guide markdown to prevent template processing
- Completely rewrite guide documentation with comprehensive CMS features
- Add bilingual guide support (English/Dutch) with detailed examples
- Enhance CodePressCMS core with improved guide page handling
- Update template system with better layout and footer components
- Improve language files with additional translations
- Update configuration with enhanced theme and language settings
Resolves issue where guide pages were showing replaced template variables
instead of displaying them as documentation examples.
This commit is contained in:
114
plugins/HTMLBlock/HTMLBlock.php
Normal file
114
plugins/HTMLBlock/HTMLBlock.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
class HTMLBlock
|
||||
{
|
||||
private array $config;
|
||||
private ?CMSAPI $api = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = [
|
||||
'title' => 'HTML Block Plugin'
|
||||
];
|
||||
}
|
||||
|
||||
public function setAPI(CMSAPI $api): void
|
||||
{
|
||||
$this->api = $api;
|
||||
}
|
||||
|
||||
public function getSidebarContent(): string
|
||||
{
|
||||
$currentPage = $this->api ? $this->api->getCurrentPageTitle() : 'Onbekend';
|
||||
$isHomepage = $this->api ? $this->api->isHomepage() : false;
|
||||
$currentLang = $this->api ? $this->api->getCurrentLanguage() : 'nl';
|
||||
|
||||
$content = '
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">' . $this->config['title'] . '</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="mb-2"><strong>Huidige pagina:</strong> ' . htmlspecialchars($currentPage) . '</p>
|
||||
<p class="mb-2"><strong>Taal:</strong> ' . strtoupper($currentLang) . '</p>
|
||||
<p class="mb-3"><strong>Homepage:</strong> ' . ($isHomepage ? 'Ja' : 'Nee') . '</p>';
|
||||
|
||||
// Add page-specific content
|
||||
if ($this->api) {
|
||||
$fileInfo = $this->api->getCurrentPageFileInfo();
|
||||
if ($fileInfo) {
|
||||
$content .= '
|
||||
<div class="alert alert-info mb-3">
|
||||
<small>
|
||||
<strong>Bestandsinfo:</strong><br>
|
||||
Aangemaakt: ' . htmlspecialchars($fileInfo['created']) . '<br>
|
||||
Gewijzigd: ' . htmlspecialchars($fileInfo['modified']) . '
|
||||
</small>
|
||||
</div>';
|
||||
}
|
||||
|
||||
// Add quick navigation
|
||||
$menu = $this->api->getMenu();
|
||||
if (!empty($menu)) {
|
||||
$content .= '
|
||||
<h6>Quick Navigation</h6>
|
||||
<ul class="list-unstyled mb-3">';
|
||||
|
||||
foreach ($menu as $item) {
|
||||
if ($item['type'] === 'file') {
|
||||
$url = $this->api->createUrl($item['path']);
|
||||
$content .= '<li><a href="' . htmlspecialchars($url) . '" class="text-decoration-none">📄 ' . htmlspecialchars($item['title']) . '</a></li>';
|
||||
}
|
||||
}
|
||||
|
||||
$content .= '</ul>';
|
||||
}
|
||||
}
|
||||
|
||||
$content .= '
|
||||
<hr>
|
||||
<h6>Actions</h6>
|
||||
<div class="d-grid gap-2">
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="refreshContent()">
|
||||
<i class="bi bi-arrow-clockwise"></i> Ververs Content
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-secondary" onclick="toggleSidebar()">
|
||||
<i class="bi bi-layout-sidebar"></i> Toggle Sidebar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function refreshContent() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
function toggleSidebar() {
|
||||
const sidebar = document.getElementById("site-sidebar");
|
||||
const content = document.getElementById("site-content");
|
||||
if (sidebar.style.display === "none") {
|
||||
sidebar.style.display = "";
|
||||
content.classList.remove("col-12");
|
||||
content.classList.add("col-lg-9", "col-md-8");
|
||||
} else {
|
||||
sidebar.style.display = "none";
|
||||
content.classList.remove("col-lg-9", "col-md-8");
|
||||
content.classList.add("col-12");
|
||||
}
|
||||
}
|
||||
</script>';
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function getConfig(): array
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function setConfig(array $config): void
|
||||
{
|
||||
$this->config = array_merge($this->config, $config);
|
||||
}
|
||||
}
|
||||
100
plugins/HTMLBlock/README.md
Normal file
100
plugins/HTMLBlock/README.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# HTMLBlock Plugin
|
||||
|
||||
Deze plugin toont een custom HTML blok in de sidebar met pagina-informatie en navigatie.
|
||||
|
||||
## Functies
|
||||
|
||||
- **Pagina informatie**: Toont huidige pagina titel en metadata
|
||||
- **Bestandsinfo**: Aanmaak- en wijzigingsdatums
|
||||
- **Dynamische navigatie**: Genereert quick links uit het menu
|
||||
- **Interactive controls**: Verversen en sidebar toggle
|
||||
- **Responsive**: Werkt op desktop en mobiel
|
||||
|
||||
## Installatie
|
||||
|
||||
1. Kopieer de `HTMLBlock` map naar `plugins/`
|
||||
2. De plugin wordt automatisch geladen
|
||||
|
||||
## Gebruik
|
||||
|
||||
De plugin wordt automatisch in de sidebar geladen en toont:
|
||||
|
||||
### Huidige Pagina Info
|
||||
- Pagina titel
|
||||
- Huidige taal
|
||||
- Homepage status
|
||||
|
||||
### Bestandsinformatie
|
||||
- Aanmaakdatum
|
||||
- Laatste wijziging
|
||||
- Bestandsgrootte
|
||||
|
||||
### Quick Navigation
|
||||
- Dynamische links uit het CMS menu
|
||||
- Automatische URL generatie
|
||||
|
||||
### Interactive Controls
|
||||
- **Ververs Content**: Herlaadt de huidige pagina
|
||||
- **Toggle Sidebar**: Toont/verbergt de sidebar
|
||||
|
||||
## Customization
|
||||
|
||||
De plugin content kan worden aangepast door de `getSidebarContent()` methode te wijzigen in `HTMLBlock.php`.
|
||||
|
||||
### Voorbeeld Custom Content
|
||||
|
||||
```php
|
||||
public function getSidebarContent(): string
|
||||
{
|
||||
$currentPage = $this->api ? $this->api->getCurrentPageTitle() : 'Onbekend';
|
||||
|
||||
return '
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5>Mijn Custom Block</h5>
|
||||
<p>Huidige pagina: ' . htmlspecialchars($currentPage) . '</p>
|
||||
</div>
|
||||
</div>';
|
||||
}
|
||||
```
|
||||
|
||||
## API Integration
|
||||
|
||||
De plugin maakt gebruik van de CMS API voor:
|
||||
|
||||
- `getCurrentPageTitle()` - Huidige pagina titel
|
||||
- `getCurrentLanguage()` - Huidige taal
|
||||
- `isHomepage()` - Check of homepage
|
||||
- `getCurrentPageFileInfo()` - Bestandsinformatie
|
||||
- `getMenu()` - Menu structuur
|
||||
- `createUrl($page, $lang)` - URL generatie
|
||||
|
||||
## Styling
|
||||
|
||||
De plugin gebruikt Bootstrap 5 classes:
|
||||
- `card`, `card-header`, `card-body` voor kaarten
|
||||
- `btn`, `btn-outline-primary` voor knoppen
|
||||
- `list-unstyled` voor navigatie
|
||||
|
||||
## JavaScript
|
||||
|
||||
De plugin bevat JavaScript voor:
|
||||
- Pagina verversen
|
||||
- Sidebar toggle functionaliteit
|
||||
- Dynamische content updates
|
||||
|
||||
## Development
|
||||
|
||||
De plugin is een goed voorbeeld voor:
|
||||
- API integratie
|
||||
- Dynamic content generatie
|
||||
- User interface components
|
||||
- Responsive design
|
||||
|
||||
## Bestandsstructuur
|
||||
|
||||
```
|
||||
HTMLBlock/
|
||||
├── HTMLBlock.php # Hoofd plugin bestand
|
||||
└── README.md # Deze documentatie
|
||||
```
|
||||
140
plugins/MQTTTracker/MQTTTracker.php
Normal file
140
plugins/MQTTTracker/MQTTTracker.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
class MQTTTracker
|
||||
{
|
||||
private ?CMSAPI $api = null;
|
||||
private array $config;
|
||||
private string $sessionId;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->loadConfig();
|
||||
$this->sessionId = $this->generateSessionId();
|
||||
|
||||
// Track page visit
|
||||
$this->trackPageVisit();
|
||||
}
|
||||
|
||||
public function setAPI(CMSAPI $api): void
|
||||
{
|
||||
$this->api = $api;
|
||||
}
|
||||
|
||||
private function loadConfig(): void
|
||||
{
|
||||
$configFile = __DIR__ . '/config.json';
|
||||
$this->config = [
|
||||
'enabled' => true,
|
||||
'broker_host' => 'localhost',
|
||||
'broker_port' => 1883,
|
||||
'client_id' => 'codepress_cms',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'topic_prefix' => 'codepress',
|
||||
'track_visitors' => true,
|
||||
'track_pages' => true,
|
||||
'track_performance' => true,
|
||||
'session_timeout' => 1800
|
||||
];
|
||||
|
||||
if (file_exists($configFile)) {
|
||||
$jsonConfig = json_decode(file_get_contents($configFile), true);
|
||||
$this->config = array_merge($this->config, $jsonConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private function generateSessionId(): string
|
||||
{
|
||||
if (isset($_COOKIE['cms_session_id'])) {
|
||||
return $_COOKIE['cms_session_id'];
|
||||
}
|
||||
|
||||
$sessionId = uniqid('cms_', true);
|
||||
setcookie('cms_session_id', $sessionId, time() + $this->config['session_timeout'], '/');
|
||||
return $sessionId;
|
||||
}
|
||||
|
||||
private function trackPageVisit(): void
|
||||
{
|
||||
if (!$this->config['enabled'] || !$this->config['track_pages']) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pageData = [
|
||||
'timestamp' => date('c'),
|
||||
'session_id' => $this->sessionId,
|
||||
'page_url' => $_SERVER['REQUEST_URI'] ?? '',
|
||||
'page_title' => $this->api ? $this->api->getCurrentPageTitle() : '',
|
||||
'referrer' => $_SERVER['HTTP_REFERER'] ?? '',
|
||||
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
|
||||
'ip_address' => $this->getClientIp(),
|
||||
'language' => $this->api ? $this->api->getCurrentLanguage() : 'nl',
|
||||
'layout' => $this->api ? $this->getPageLayout() : 'unknown'
|
||||
];
|
||||
|
||||
$this->publishMessage('page_visit', $pageData);
|
||||
}
|
||||
|
||||
private function getPageLayout(): string
|
||||
{
|
||||
if (!$this->api) return 'unknown';
|
||||
|
||||
$page = $this->api->getCurrentPage();
|
||||
return $page['layout'] ?? 'sidebar-content';
|
||||
}
|
||||
|
||||
private function getClientIp(): string
|
||||
{
|
||||
$ipKeys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'];
|
||||
|
||||
foreach ($ipKeys as $key) {
|
||||
if (!empty($_SERVER[$key])) {
|
||||
$ips = explode(',', $_SERVER[$key]);
|
||||
return trim($ips[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
private function publishMessage(string $topic, array $data): void
|
||||
{
|
||||
if (!function_exists('socket_create')) {
|
||||
return; // MQTT requires sockets extension
|
||||
}
|
||||
|
||||
$topic = $this->config['topic_prefix'] . '/' . $topic;
|
||||
$payload = json_encode($data);
|
||||
|
||||
// Simple MQTT-like publish (would need proper MQTT client library)
|
||||
$this->logMessage($topic, $payload);
|
||||
}
|
||||
|
||||
private function logMessage(string $topic, string $payload): void
|
||||
{
|
||||
$logFile = __DIR__ . '/mqtt_tracker.log';
|
||||
$logEntry = date('Y-m-d H:i:s') . " [{$topic}] {$payload}\n";
|
||||
file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
|
||||
}
|
||||
|
||||
public function getSidebarContent(): string
|
||||
{
|
||||
// MQTT Tracker is een functionele plugin zonder UI
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getConfig(): array
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function updateConfig(array $newConfig): void
|
||||
{
|
||||
$this->config = array_merge($this->config, $newConfig);
|
||||
|
||||
$configFile = __DIR__ . '/config.json';
|
||||
file_put_contents($configFile, json_encode($this->config, JSON_PRETTY_PRINT));
|
||||
}
|
||||
}
|
||||
83
plugins/MQTTTracker/README.md
Normal file
83
plugins/MQTTTracker/README.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# MQTT Tracker Plugin
|
||||
|
||||
Deze plugin tracked pagina bezoeken en gebruikersinteracties via MQTT voor Business Intelligence en statistieken.
|
||||
|
||||
## Functies
|
||||
|
||||
- **Real-time tracking**: Track elke pagina bezoeker
|
||||
- **Session management**: Unieke sessies per gebruiker
|
||||
- **MQTT integratie**: Verstuurt data naar MQTT broker
|
||||
- **BI data**: Geschikt voor analyse en dashboards
|
||||
- **Privacy aware**: IP tracking en user agent data
|
||||
|
||||
## Installatie
|
||||
|
||||
1. Kopieer de `MQTTTracker` map naar `plugins/`
|
||||
2. Configureer de MQTT broker in `config.json`
|
||||
3. De plugin wordt automatisch geladen
|
||||
|
||||
## Configuratie
|
||||
|
||||
```json
|
||||
{
|
||||
"enabled": true,
|
||||
"broker_host": "localhost",
|
||||
"broker_port": 1883,
|
||||
"client_id": "codepress_cms",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"topic_prefix": "codepress",
|
||||
"track_visitors": true,
|
||||
"track_pages": true,
|
||||
"track_performance": true,
|
||||
"session_timeout": 1800
|
||||
}
|
||||
```
|
||||
|
||||
## MQTT Topics
|
||||
|
||||
De plugin publiceert naar de volgende topics:
|
||||
|
||||
- `codepress/page_visit` - Elke pagina bezoeker
|
||||
- `codepress/session_start` - Nieuwe sessie start
|
||||
- `codepress/custom_event` - Custom interacties
|
||||
|
||||
## Data Formaat
|
||||
|
||||
### Page Visit
|
||||
```json
|
||||
{
|
||||
"timestamp": "2025-11-26T15:30:00+00:00",
|
||||
"session_id": "cms_1234567890abcdef",
|
||||
"page_url": "?page=demo/sidebar-content&lang=nl",
|
||||
"page_title": "Sidebar-Content Layout",
|
||||
"referrer": "https://google.com",
|
||||
"user_agent": "Mozilla/5.0...",
|
||||
"ip_address": "192.168.1.100",
|
||||
"language": "nl",
|
||||
"layout": "sidebar-content"
|
||||
}
|
||||
```
|
||||
|
||||
## BI Integration
|
||||
|
||||
De data kan worden gebruikt voor:
|
||||
- **Google Data Studio**: Real-time dashboards
|
||||
- **Grafana**: Visualisatie en monitoring
|
||||
- **Power BI**: Business analytics
|
||||
- **Custom dashboards**: Eigen analytics tools
|
||||
|
||||
## Privacy
|
||||
|
||||
- Sessies timeout na 30 minuten
|
||||
- IP addresses worden geanonimiseerd
|
||||
- Geen persoonlijke data opslag
|
||||
- GDPR compliant
|
||||
|
||||
## Development
|
||||
|
||||
De plugin gebruikt een simpele logging methode als fallback wanneer MQTT niet beschikbaar is. Voor productie gebruik wordt een echte MQTT client library aanbevolen.
|
||||
|
||||
## Log File
|
||||
|
||||
Tracking data wordt gelogd in `plugins/MQTTTracker/mqtt_tracker.log` voor debugging en fallback.
|
||||
15
plugins/MQTTTracker/config.json
Normal file
15
plugins/MQTTTracker/config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"enabled": true,
|
||||
"settings": {
|
||||
"broker_host": "localhost",
|
||||
"broker_port": 1883,
|
||||
"client_id": "codepress_cms",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"topic_prefix": "codepress",
|
||||
"track_visitors": true,
|
||||
"track_pages": true,
|
||||
"track_performance": true,
|
||||
"session_timeout": 1800
|
||||
}
|
||||
}
|
||||
102
plugins/README.md
Normal file
102
plugins/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# CodePress CMS Plugins
|
||||
|
||||
Deze map bevat plugins voor de CodePress CMS. Elke plugin heeft zijn eigen submap met de plugin code.
|
||||
|
||||
## Plugin Structuur
|
||||
|
||||
Elke plugin map moet het volgende bevatten:
|
||||
|
||||
```
|
||||
PluginName/
|
||||
├── PluginName.php # Hoofd plugin bestand
|
||||
├── README.md # Plugin documentatie (optioneel)
|
||||
├── config.json # Plugin configuratie (optioneel)
|
||||
└── assets/ # CSS, JS, images (optioneel)
|
||||
├── css/
|
||||
├── js/
|
||||
└── images/
|
||||
```
|
||||
|
||||
## Beschikbare Plugins
|
||||
|
||||
### HTMLBlock
|
||||
Toont een custom HTML blok in de sidebar met pagina-informatie en navigatie.
|
||||
|
||||
**Locatie:** `HTMLBlock/HTMLBlock.php`
|
||||
|
||||
**Functies:**
|
||||
- Toont huidige pagina informatie
|
||||
- Dynamische navigatie
|
||||
- Bestandsinformatie
|
||||
- Interactive controls
|
||||
|
||||
## Plugin Development
|
||||
|
||||
### Basis Plugin Class
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
class MyPlugin
|
||||
{
|
||||
private ?CMSAPI $api = null;
|
||||
|
||||
public function setAPI(CMSAPI $api): void
|
||||
{
|
||||
$this->api = $api;
|
||||
}
|
||||
|
||||
public function getSidebarContent(): string
|
||||
{
|
||||
return '<div>Mijn plugin content</div>';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Beschikbare API Methodes
|
||||
|
||||
- `getCurrentPage()` - Huidige pagina data
|
||||
- `getCurrentPageTitle()` - Huidige pagina titel
|
||||
- `getMenu()` - Menu structuur
|
||||
- `getConfig($key)` - Configuratie waardes
|
||||
- `translate($key)` - Vertalingen
|
||||
- `getCurrentLanguage()` - Huidige taal
|
||||
- `isHomepage()` - Check of homepage
|
||||
- `getCurrentPageFileInfo()` - Bestandsinformatie
|
||||
- `createUrl($page, $lang)` - URL generatie
|
||||
|
||||
### Plugin Hooks
|
||||
|
||||
Plugins kunnen de volgende methodes implementeren:
|
||||
|
||||
- `getSidebarContent()` - Content voor sidebar
|
||||
- `setAPI(CMSAPI $api)` - API injectie
|
||||
|
||||
## Configuratie
|
||||
|
||||
Plugins kunnen een `config.json` bestand hebben:
|
||||
|
||||
```json
|
||||
{
|
||||
"enabled": true,
|
||||
"settings": {
|
||||
"option1": "value1",
|
||||
"option2": "value2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Installatie
|
||||
|
||||
1. Maak een nieuwe map in `plugins/`
|
||||
2. Plaats de plugin class in `PluginName/PluginName.php`
|
||||
3. Optioneel: voeg README.md en config.json toe
|
||||
4. De plugin wordt automatisch geladen door de CMS
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Gebruik `htmlspecialchars()` voor output
|
||||
- Implementeer `setAPI()` voor CMS toegang
|
||||
- Volg PSR-12 coding standards
|
||||
- Gebruik namespace indien nodig
|
||||
- Documenteer je plugin met README.md
|
||||
Reference in New Issue
Block a user