cms/app/Support/PageRenderer.php

100 lines
3.4 KiB
PHP
Raw Normal View History

<?php
namespace App\Support;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\File;
class PageRenderer
{
/**
* Render the page content from JSON.
*/
public function render(array $content): string
{
$html = '';
// Handle multi-locale content structure: { "en": [...], "es": [...] }
$locale = app()->getLocale();
$blocks = [];
if (isset($content[$locale]) && is_array($content[$locale])) {
$blocks = $content[$locale];
} elseif (isset($content[0]) && is_array($content[0])) {
// Support legacy array format for internal test compatibility if still needed
// or if content was already extracted to an array.
$blocks = $content;
} else {
// If requested locale not found, try default
$defaultLocale = config('app.fallback_locale', 'en');
if (isset($content[$defaultLocale]) && is_array($content[$defaultLocale])) {
$blocks = $content[$defaultLocale];
} elseif (!empty($content)) {
// Last resort: grab the first available locale if any
$firstLocale = array_key_first($content);
if (isset($content[$firstLocale]) && is_array($content[$firstLocale])) {
$blocks = $content[$firstLocale];
}
}
}
foreach ($blocks as $block) {
$html .= $this->renderBlock($block);
}
return $html;
}
/**
* Render a single block.
*/
public function renderBlock(array $block): string
{
$type = $block['type'] ?? 'text';
$data = $block['data'] ?? [];
// Map simplified editor types to theme block types if necessary
$typeMap = [
'paragraph' => 'paragraph',
'heading' => 'heading',
'media' => 'media',
'text' => 'paragraph', // Alias for text
'header' => 'heading', // Alias for header
];
$resolvedType = $typeMap[$type] ?? $type;
// Support for Grid/Columns layout blocks (pass blocks to them)
if ($resolvedType === 'columns' || $resolvedType === 'grid') {
$data['renderer'] = $this;
}
// Determine if a theme-specific component exists
$themeManager = new ThemeManager();
$activeTheme = $themeManager->getActiveTheme();
$themePath = base_path("themes/{$activeTheme}/blocks/{$resolvedType}.blade.php");
// Use core views first if in testing or if preferred, but usually themes override core.
// For testing, we might want to ensure we're using what we just edited.
// Let's add a debug log or just ensure the path is correct.
if (File::exists($themePath)) {
// We need to use a temporary view or evaluate the blade file
return Blade::render(File::get($themePath), $data);
}
// Fallback to core block components
$coreViewPath = "blocks.{$resolvedType}";
if (view()->exists($coreViewPath)) {
return view($coreViewPath, $data)->render();
}
// Final fallback: just dump text if it's a text-like block
if (($resolvedType === 'paragraph' || $resolvedType === 'text') && isset($data['text'])) {
return "<div>{$data['text']}</div>";
}
return "<!-- Block type [{$type}] not found (resolved as [{$resolvedType}]) -->";
}
}