- Content bestanden met dezelfde naam maar ander type (md/php/html) worden correct geserveerd: URL met extensie opent dat bestand, URL zonder extensie valt terug op md > php > html (resolveContentByType helper) - Admin content editor accepteert bestanden met dezelfde naam (ander type); preview-knop linkt per extensie - Frontend navigatie/directory listing/search tonen elk bestandstype apart - getAllPages() array structuur gewijzigd naar list van ['path','title','type'] met type 'md'/'php'/'html'/'folder' - Verberg-prefix logica: _ is geen verberg-prefix meer, alleen . (en -); admin toont wél alle . bestanden/mappen - ContentAPI getPage()/pageExists() respecteren expliciete extensie - Handleiding content-api.md (NL+EN) herschreven - File-tree unificatie: _file-tree.twig + _editor-styles.twig includes - Versie verhoogd naar 2.6.3
206 lines
6.6 KiB
Markdown
206 lines
6.6 KiB
Markdown
# Content API
|
|
|
|
PHP content bestanden (`.php`) draaien binnen het CMS en hebben toegang tot een
|
|
veilige, read-only API via de variabele `$api`. De output van zo'n bestand wordt
|
|
automatisch in de actieve Twig layout geplaatst op de plek van `{{ content }}`.
|
|
|
|
## Hoe je content doorgeeft aan de Twig template
|
|
|
|
Er zijn **twee manieren** om content vanuit een `.php` bestand naar het Twig
|
|
template te sturen. De CMS kiest automatisch de juiste:
|
|
|
|
1. **Echo / print** — alles wat je echoot (of wat buiten `<?php ?>` tags staat)
|
|
wordt opgevangen en als `{{ content }}` in de layout geplaatst.
|
|
2. **Return** — als je `return` gebruikt met een string, wordt die string als
|
|
`{{ content }}` gebruikt (echt output wordt dan genegeerd).
|
|
|
|
Voorbeeld met echo:
|
|
|
|
```php
|
|
---
|
|
layout: full_content
|
|
---
|
|
<?php
|
|
/** @var ContentAPI $api */
|
|
?>
|
|
<h1>Hallo <?= htmlspecialchars($api->getSiteTitle()) ?></h1>
|
|
<p>Welkom op mijn pagina.</p>
|
|
```
|
|
|
|
Voorbeeld met return:
|
|
|
|
```php
|
|
---
|
|
layout: full_content
|
|
---
|
|
<?php
|
|
/** @var ContentAPI $api */
|
|
return '<h1>Hallo ' . htmlspecialchars($api->getSiteTitle()) . '</h1>';
|
|
```
|
|
|
|
> De frontmatter (`---` blok) wordt door het CMS gestript vóórdat de PHP code
|
|
> uitgevoerd wordt. De layout key bepaalt welke Twig template de content omringt.
|
|
|
|
## Wat kun je níét doen
|
|
|
|
- Je kunt **geen** eigen Twig variabelen zetten vanuit een `.php` bestand.
|
|
PHP content leverde alleen de `{{ content }}` placeholder. Andere template
|
|
variabelen (`menu`, `breadcrumb`, `page_title`, etc.) worden door het CMS
|
|
vastgesteld op basis van de frontmatter en config — niet door je PHP code.
|
|
- Je kunt **geen** van buitenaf een ContentAPI aanroepen; de class wordt alleen
|
|
binnen `parsePHP()` geïnstantieerd en is nooit via een URL bereikbaar.
|
|
|
|
## Beschikbare variabelen in je PHP bestand
|
|
|
|
Binnen een `.php` content bestand zijn de volgende variabelen beschikbaar:
|
|
|
|
| Variabele | Type | Omschrijving |
|
|
|-----------|------|--------------|
|
|
| `$api` | `ContentAPI` | Read-only toegang tot CMS data |
|
|
| `$pageMetadata` | `array` | De frontmatter metadata van dit bestand |
|
|
|
|
## ContentAPI methods
|
|
|
|
### Pagina's
|
|
|
|
- `getAllPages(): array` — Alle content entries (mappen + bestanden) als een list van `['path' => ..., 'title' => ..., 'type' => ...]`. `type` is `md`/`php`/`html` voor bestanden, `folder` voor mappen.
|
|
- `getPage(string $path): ?array` — Specifieke pagina; levert `title`, `content`, `path`, `layout`, `metadata`. `$path` mag een extensie bevatten.
|
|
- `pageExists(string $path): bool` — Controleer of een pagina bestaat
|
|
- `getCurrentPageTitle(): string` — Titel van de huidige pagina
|
|
- `getCurrentPagePath(): string` — Pad van de huidige pagina
|
|
- `isHomepage(): bool` — Of de huidige pagina de homepage is
|
|
|
|
### Menu & navigatie
|
|
|
|
- `getMenu(): array` — Hiërarchische menu structuur met `title`, `path`, `children`, `active`
|
|
- `buildUrl(string $page = 'index', ?string $lang = null, array $params = []): string` — Bouw een URL
|
|
|
|
### Configuratie
|
|
|
|
- `getConfig(string $key, mixed $default = null): mixed` — Config waarde via dot notatie (bijv. `'features.search_enabled'`)
|
|
- `getSiteTitle(): string` — Site titel uit config
|
|
|
|
### Taal
|
|
|
|
- `getCurrentLanguage(): string` — Huidige taal code (bijv. `'nl'`)
|
|
- `getAvailableLanguages(): array` — Beschikbare talen
|
|
- `t(string $key): string` — Vertaal een language key
|
|
|
|
### Zoeken
|
|
|
|
- `getSearchResults(): array` — Zoekresultaten (leeg als niet aan het zoeken)
|
|
- `isSearching(): bool` — Of er momenteel gezocht wordt
|
|
|
|
### Auteur
|
|
|
|
- `getPageAuthor(): array` — Auteur metadata uit frontmatter (`author_name`, `author_email`, `created`)
|
|
|
|
## Voorbeelden
|
|
|
|
### Recente pagina's tonen
|
|
|
|
```php
|
|
---
|
|
layout: full_content
|
|
---
|
|
<?php
|
|
/** @var ContentAPI $api */
|
|
$entries = $api->getAllPages();
|
|
$currentLang = $api->getCurrentLanguage();
|
|
?>
|
|
<ul>
|
|
<?php foreach ($entries as $entry): ?>
|
|
<?php if ($entry['type'] === 'folder') continue; // sla mappen over ?>
|
|
<li>
|
|
<a href="/<?= htmlspecialchars($currentLang) ?>/<?= htmlspecialchars($entry['path']) ?>">
|
|
<?= htmlspecialchars($entry['title']) ?>
|
|
<small>(<?= htmlspecialchars($entry['type']) ?>)</small>
|
|
</a>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
```
|
|
|
|
### Config waarde gebruiken
|
|
|
|
```php
|
|
---
|
|
layout: full_content
|
|
---
|
|
<?php
|
|
/** @var ContentAPI $api */
|
|
if ($api->getConfig('features.search_enabled', false)): ?>
|
|
<form method="GET" action="">
|
|
<input type="search" name="search" placeholder="<?= $api->t('search_placeholder') ?>">
|
|
<button type="submit"><?= $api->t('search_button') ?></button>
|
|
</form>
|
|
<?php endif; ?>
|
|
```
|
|
|
|
### Dynamische begroeting op basis van taal
|
|
|
|
```php
|
|
---
|
|
layout: full_content
|
|
---
|
|
<?php
|
|
/** @var ContentAPI $api */
|
|
$lang = $api->getCurrentLanguage();
|
|
$greeting = $lang === 'nl' ? 'Welkom' : 'Welcome';
|
|
?>
|
|
<h1><?= $greeting ?> op <?= htmlspecialchars($api->getSiteTitle()) ?></h1>
|
|
```
|
|
|
|
## Layout kiezen
|
|
|
|
De frontmatter `layout` key bepaalt welke Twig template je content omringt. De
|
|
beschikbare layouts staan in `themes/<actief-thema>/theme.json` onder de
|
|
`template` sectie. Bijvoorbeeld:
|
|
|
|
```yaml
|
|
---
|
|
layout: sidebar-content
|
|
---
|
|
```
|
|
|
|
Als je geen layout opgeeft, wordt `config.default_template` gebruikt, met als
|
|
fallback `full_content`. De content komt altijd terecht op de `{{ content }}`
|
|
plek in die template.
|
|
|
|
## Veiligheid
|
|
|
|
- Gebruik altijd `htmlspecialchars()` voor output van user-content of API data.
|
|
- PHP content bestanden hebben toegang tot het bestandssysteem van de server —
|
|
wees voorzichtig met `include`, `require` of `file_get_contents` op externe
|
|
paden. Blijf binnen de `content/` map.
|
|
- De ContentAPI is read-only; je kunt er geen bestanden of config mee wijzigen.
|
|
|
|
## CMSAPI (voor plugins)
|
|
|
|
Plugins gebruiken de `CMSAPI` class via `$this->api`. Deze biedt vergelijkbare
|
|
methods:
|
|
|
|
```php
|
|
$this->api->getCurrentPageTitle();
|
|
$this->api->getCurrentPageContent();
|
|
$this->api->getMenu();
|
|
$this->api->getConfig('site_title');
|
|
$this->api->getCurrentLanguage();
|
|
$this->api->isHomepage();
|
|
$this->api->hasContent();
|
|
$this->api->getSearchResults();
|
|
$this->api->isSearching();
|
|
$this->api->getAvailableLanguages();
|
|
$this->api->createUrl('over-ons');
|
|
$this->api->translate('home');
|
|
```
|
|
|
|
Daarnaast heeft de CMSAPI:
|
|
|
|
- `getCurrentPage(): array` — Volledige pagina data
|
|
- `getCurrentPageUrl(): string` — URL van huidige pagina
|
|
- `getCurrentPageFileInfo(): ?array` — Bestandsinfo (created, modified)
|
|
- `getBreadcrumb(): string` — Breadcrumb HTML
|
|
- `executePhpFile(string $filePath): string` — Voer PHP bestand uit en vang output op
|
|
- `getFileContent(string $filePath): string` — Haal content uit PHP/HTML/Markdown bestand
|
|
- `contentFileExists(string $filename): bool` — Controleer of bestand bestaat in content map |