Files
PMG-backoffice/plugins/json-export/json-export.php
2026-02-11 16:31:03 +01:00

263 lines
8.8 KiB
PHP

<?php
namespace Grav\Plugin;
use Grav\Common\Plugin;
class JsonExportPlugin extends Plugin
{
public static function getSubscribedEvents()
{
return [
'onPluginsInitialized' => ['onPluginsInitialized', 0]
];
}
public function onPluginsInitialized()
{
if ($this->isAdmin()) {
return;
}
$this->enable([
'onPagesInitialized' => ['onPagesInitialized', 0]
]);
}
public function onPagesInitialized()
{
$uri = $this->grav['uri'];
$path = $uri->path();
if (strpos($path, '/api/') !== 0) {
return;
}
$lang = $_GET['lang'] ?? 'en';
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
if ($path === '/api/stations') {
echo json_encode($this->getStationsList($lang), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
}
if (preg_match('#^/api/station/([a-zA-Z0-9-]+)$#', $path, $matches)) {
$station = $this->getStation($matches[1], $lang);
if ($station) {
echo json_encode($station, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
} else {
http_response_code(404);
echo json_encode(['error' => 'Station not found']);
}
exit;
}
if ($path === '/api/translations') {
echo json_encode($this->getTranslations($lang), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
}
}
private function getStationsList($lang)
{
$pages = $this->grav['pages'];
$stations = [];
foreach ($pages->all() as $page) {
if ($page->template() === 'station') {
$header = $page->header();
if (!($header->active ?? true)) continue;
$stations[] = [
'id' => $header->station_id ?? $page->slug(),
'type' => $header->station_type ?? 'exhibit',
'title' => $this->getTranslated($header->title_translations ?? [], $lang),
'description' => $this->getTranslated($header->description_translations ?? [], $lang),
'order' => $header->order ?? 0
];
}
}
usort($stations, fn($a, $b) => $a['order'] <=> $b['order']);
return $stations;
}
private function getStation($stationId, $lang)
{
$pages = $this->grav['pages'];
foreach ($pages->all() as $page) {
if ($page->template() === 'station') {
$header = $page->header();
$id = $header->station_id ?? $page->slug();
if ($id === $stationId) {
return $this->formatStation($page, $lang);
}
}
}
return null;
}
private function formatStation($page, $lang)
{
$header = $page->header();
$station = [
'id' => $header->station_id ?? $page->slug(),
'type' => $header->station_type ?? 'exhibit',
'language' => $lang,
'title' => $this->getTranslated($header->title_translations ?? [], $lang),
'description' => $this->getTranslated($header->description_translations ?? [], $lang),
'components' => []
];
if (isset($header->components) && is_array($header->components)) {
foreach ($header->components as $comp) {
$station['components'][] = $this->formatComponent($comp, $lang);
}
}
return $station;
}
private function formatComponent($comp, $lang)
{
$out = [
'id' => $comp['id'] ?? uniqid(),
'type' => $comp['type'] ?? 'text'
];
switch ($comp['type']) {
case 'heading':
$out['level'] = $comp['level'] ?? 'h2';
$out['content'] = $this->getTranslated($comp['content'] ?? [], $lang);
break;
case 'text':
$out['content'] = $this->getTranslated($comp['content'] ?? [], $lang);
break;
case 'video':
$out['src'] = $this->getTranslated($comp['src'] ?? [], $lang);
$out['poster'] = $comp['poster'] ?? null;
$out['caption'] = $this->getTranslated($comp['caption'] ?? [], $lang);
break;
case 'audio':
$out['src'] = $this->getTranslated($comp['src'] ?? [], $lang);
$out['caption'] = $this->getTranslated($comp['caption'] ?? [], $lang);
break;
case 'tabs':
$out['tabs'] = [];
foreach ($comp['tabs'] ?? [] as $tab) {
$out['tabs'][] = [
'title' => $this->getTranslated($tab['title'] ?? [], $lang),
'content' => $this->getTranslated($tab['content'] ?? [], $lang)
];
}
break;
case 'slideshow':
$out['slides'] = [];
foreach ($comp['slides'] ?? [] as $slide) {
$out['slides'][] = [
'image' => $slide['image'] ?? '',
'caption' => $this->getTranslated($slide['caption'] ?? [], $lang)
];
}
break;
}
return $out;
}
private function getTranslated($field, $lang)
{
if (is_string($field)) return $field;
return $field[$lang] ?? $field['en'] ?? reset($field) ?: '';
}
private function getTranslations($lang)
{
$t = [
'en' => [
'appTitle' => 'EU Media Guide',
'scanQR' => 'Scan QR Code',
'selectLanguage' => 'Select Language',
'contentLibrary' => 'Content Library',
'loading' => 'Loading...',
'play' => 'Play',
'pause' => 'Pause',
'next' => 'Next',
'previous' => 'Previous',
'menu' => 'Menu',
'close' => 'Close'
],
'fr' => [
'appTitle' => 'Guide Média UE',
'scanQR' => 'Scanner le code QR',
'selectLanguage' => 'Choisir la langue',
'contentLibrary' => 'Bibliothèque',
'loading' => 'Chargement...',
'play' => 'Lecture',
'pause' => 'Pause',
'next' => 'Suivant',
'previous' => 'Précédent',
'menu' => 'Menu',
'close' => 'Fermer'
],
'de' => [
'appTitle' => 'EU Medienführer',
'scanQR' => 'QR-Code scannen',
'selectLanguage' => 'Sprache wählen',
'contentLibrary' => 'Inhaltsbibliothek',
'loading' => 'Laden...',
'play' => 'Abspielen',
'pause' => 'Pause',
'next' => 'Weiter',
'previous' => 'Zurück',
'menu' => 'Menü',
'close' => 'Schließen'
],
'nl' => [
'appTitle' => 'EU Mediagids',
'scanQR' => 'QR-code scannen',
'selectLanguage' => 'Taal selecteren',
'contentLibrary' => 'Inhoudsbibliotheek',
'loading' => 'Laden...',
'play' => 'Afspelen',
'pause' => 'Pauze',
'next' => 'Volgende',
'previous' => 'Vorige',
'menu' => 'Menu',
'close' => 'Sluiten'
],
'it' => [
'appTitle' => 'Guida Media UE',
'scanQR' => 'Scansiona codice QR',
'selectLanguage' => 'Seleziona lingua',
'contentLibrary' => 'Libreria contenuti',
'loading' => 'Caricamento...',
'play' => 'Riproduci',
'pause' => 'Pausa',
'next' => 'Successivo',
'previous' => 'Precedente',
'menu' => 'Menu',
'close' => 'Chiudi'
],
'es' => [
'appTitle' => 'Guía de Medios UE',
'scanQR' => 'Escanear código QR',
'selectLanguage' => 'Seleccionar idioma',
'contentLibrary' => 'Biblioteca de contenido',
'loading' => 'Cargando...',
'play' => 'Reproducir',
'pause' => 'Pausa',
'next' => 'Siguiente',
'previous' => 'Anterior',
'menu' => 'Menú',
'close' => 'Cerrar'
]
];
return $t[$lang] ?? $t['en'];
}
}