Files
E.Noorlander 6d5ca7cab4 v2.6.1d (Lyra): Plugin i18n, plugin editor vernieuwd, media invoegen
Plugin internationalisatie: plugins hebben eigen language/ mappen. Systeem
plugins volgen admin taal (admin.php), content plugins volgen content taal
(site.php). Fallback chain: geselecteerd -> plugin default_language -> CMS
default. PluginManager/AdminPluginAPI/CMSAPI uitgebreid met
getPluginTranslations()/t(). plugin.json settings ondersteunen
label_key/help_key/option_label_key.

Plugin uniformiteit: alle 6 plugins hebben uniforme structuur (README.md,
assets/.gitkeep, language/nl|en/). plugins/README.md herschreven.
guide plugin-development.md (NL+EN) volledig herschreven.

Plugin editor vernieuwd: geneste bestandsbrowser zijbalk, nieuw bestand
aanmaken, uploaden naar assets/, verwijderen en verplaatsen. Nieuwe routes:
plugins-file-upload, plugins-file-delete, plugins-file-move. Path-traversal
bescherming + protected plugins geblokkeerd.

Media invoegen in editor: nieuw /admin/media-list JSON endpoint + herbruikbare
_media-modal.twig include. Plugin-context scant assets/ map. editor-toolbar.js
modeMap uitgebreid voor css/scss/js/json.

Plugin overzicht knoppen: alleen iconen met title/aria-label.

Tests: pentest 30/30, WCAG 2.1 AA 25/25.
2026-08-18 13:49:52 +00:00

262 lines
7.1 KiB
PHP

<?php
/**
* Content API for PHP content files
*
* Provides a safe, read-only interface for PHP content files to access
* CMS data (pages, menu, config, navigation, translations, search).
* Only instantiated inside parsePHP() — never exposed via URL.
*/
class ContentAPI
{
private CodePressCMS $cms;
public function __construct(CodePressCMS $cms)
{
$this->cms = $cms;
}
/**
* Get all pages as a flat array of path => title pairs
*
* @return array Associative array like ['index' => 'Home', 'over-ons' => 'Over ons']
*/
public function getAllPages(): array
{
return $this->cms->getAllPageTitles();
}
/**
* Get a single page by path, including title, content, layout, and metadata
*
* @param string $path Page path without extension (e.g. 'over-ons' or 'blog/post-1')
* @return array|null Page data or null if not found
*/
public function getPage(string $path): ?array
{
$contentDir = $this->cms->config['content_dir'];
$path = preg_replace('/\.(md|php|html)$/', '', $path);
$filePath = $contentDir . '/' . $path;
$extensions = ['md', 'php', 'html'];
$actualPath = null;
foreach ($extensions as $ext) {
if (file_exists($filePath . '.' . $ext)) {
$actualPath = $filePath . '.' . $ext;
break;
}
}
if (!$actualPath || !file_exists($actualPath)) {
return null;
}
$content = file_get_contents($actualPath);
$extension = pathinfo($actualPath, PATHINFO_EXTENSION);
switch ($extension) {
case 'md':
$result = $this->cms->parseMarkdown($content, $actualPath);
break;
case 'php':
$result = $this->cms->parsePHP($actualPath);
$result['content'] = $this->cms->processContent($result['content']);
break;
case 'html':
$result = $this->cms->parseHTML($content, $actualPath);
break;
default:
return null;
}
return [
'title' => $result['title'] ?? '',
'content' => $result['content'] ?? '',
'path' => $path,
'layout' => $result['layout'] ?? 'sidebar-content',
'metadata' => $result['metadata'] ?? [],
];
}
/**
* Get the navigation menu structure
*
* @return array Hierarchical menu array with 'title', 'path', 'children', 'active' keys
*/
public function getMenu(): array
{
return $this->cms->getMenu();
}
/**
* Get a config value using dot notation
*
* @param string $key Config key, e.g. 'site_title' or 'features.search'
* @param mixed $default Default value if key is not found
* @return mixed Config value or default
*/
public function getConfig(string $key, $default = null)
{
$keys = explode('.', $key);
$value = $this->cms->config;
foreach ($keys as $k) {
if (!isset($value[$k])) {
return $default;
}
$value = $value[$k];
}
return $value;
}
/**
* Get the current language code (e.g. 'nl' or 'en')
*
* @return string
*/
public function getCurrentLanguage(): string
{
return $this->cms->currentLanguage;
}
/**
* Build a URL for a page, optionally with a specific language and extra params
*
* @param string $page Page path (default 'index')
* @param string|null $lang Language code (defaults to current language)
* @param array $params Additional query parameters
* @return string URL string starting with '?'
*/
public function buildUrl(string $page = 'index', ?string $lang = null, array $params = []): string
{
$lang = $lang ?? $this->getCurrentLanguage();
$query = 'page=' . urlencode($page) . '&lang=' . urlencode($lang);
if (!empty($params)) {
$query .= '&' . http_build_query($params);
}
return '?' . $query;
}
/**
* Check if a page exists at the given path
*
* @param string $path Page path without extension
* @return bool
*/
public function pageExists(string $path): bool
{
$contentDir = $this->cms->config['content_dir'];
$path = preg_replace('/\.(md|php|html)$/', '', $path);
$basePath = $contentDir . '/' . $path;
return file_exists($basePath . '.md')
|| file_exists($basePath . '.php')
|| file_exists($basePath . '.html');
}
/**
* Get the title of the currently viewed page
*
* @return string
*/
public function getCurrentPageTitle(): string
{
$page = $this->cms->getPage();
return $page['title'] ?? '';
}
/**
* Get the path of the currently viewed page
*
* @return string
*/
public function getCurrentPagePath(): string
{
return $_GET['page'] ?? $this->cms->config['default_page'];
}
/**
* Check if the current page is the homepage
*
* @return bool
*/
public function isHomepage(): bool
{
$defaultPage = $this->cms->config['default_page'] ?? 'index';
$currentPage = $_GET['page'] ?? $defaultPage;
return $currentPage === $defaultPage;
}
/**
* Translate a language key using the current language
*
* @param string $key Language key
* @return string Translated text
*/
public function t(string $key): string
{
return $this->cms->t($key);
}
/**
* Get the site title from config
*
* @return string
*/
public function getSiteTitle(): string
{
return $this->cms->config['site_title'] ?? 'CodePress';
}
/**
* Get all available language codes
*
* @return array Language codes like ['nl', 'en']
*/
public function getAvailableLanguages(): array
{
return $this->cms->getAvailableLanguages();
}
/**
* Get search results for the current search query
*
* @return array Search results, or empty array if not searching
*/
public function getSearchResults(): array
{
if (isset($_GET['search'])) {
return $this->cms->searchResults;
}
return [];
}
/**
* Check if a search is currently active
*
* @return bool
*/
public function isSearching(): bool
{
return isset($_GET['search']);
}
/**
* Get the author metadata for the current page.
* Returns author_name, author_email and created from the page frontmatter.
*
* @return array Author metadata with keys: author_name, author_email, created
*/
public function getPageAuthor(): array
{
$page = $this->cms->getPage();
$metadata = $page['metadata'] ?? [];
return [
'author_name' => $metadata['author_name'] ?? '',
'author_email' => $metadata['author_email'] ?? '',
'created' => $metadata['created'] ?? '',
];
}
}