Files
roi-theme/Public/ThemeSettings/Infrastructure/Ui/ThemeSettingsRenderer.php
FrankZamora 72ef7580fc fix: Container width setting now applies correctly + Rail Ads improvements
- Fix container width not applying: css-global-responsive.css now uses
  CSS variable --roi-container-width instead of hardcoded values
- Add 8 Rail format options: slim-small (160x300), slim-medium (160x400),
  slim-large (160x500), skyscraper (160x600), slim-xlarge (160x700),
  wide-skyscraper (160x800), half-page (300x600), large-skyscraper (300x1050)
- Change rail_top_offset from text input to select with preset values
- Fix Rail Ads JavaScript positioning (moved after HTML, added retries)
- ThemeSettingsRenderer now always outputs CSS variables for layout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:30:06 -06:00

221 lines
5.8 KiB
PHP

<?php
declare(strict_types=1);
namespace ROITheme\Public\ThemeSettings\Infrastructure\Ui;
use ROITheme\Shared\Domain\Contracts\RendererInterface;
use ROITheme\Shared\Domain\Entities\Component;
/**
* ThemeSettingsRenderer
*
* Renderizador del componente Theme Settings.
* A diferencia de otros componentes, no renderiza HTML visual
* sino que genera codigo para inyectar en wp_head y wp_footer.
*
* NOTA: Este es un componente especial que solo maneja codigo personalizado.
* Analytics y AdSense se gestionan desde el componente adsense-placement.
*
* Responsabilidades:
* - Generar CSS personalizado
* - Generar JavaScript para header
* - Generar JavaScript para footer
*
* @package ROITheme\Public\ThemeSettings\Infrastructure\Ui
*/
final class ThemeSettingsRenderer implements RendererInterface
{
/**
* {@inheritDoc}
*
* Para este componente, render() no se usa directamente.
* Se usan los metodos especificos: renderHeadContent() y renderFooterContent()
*/
public function render(Component $component): string
{
// Este componente no renderiza HTML visual
// Los contenidos se inyectan via hooks wp_head y wp_footer
return '';
}
/**
* {@inheritDoc}
*/
public function supports(string $componentType): bool
{
return $componentType === 'theme-settings';
}
/**
* Genera contenido para wp_head
*
* Incluye:
* - Layout CSS (container width)
* - Custom CSS (si configurado)
* - Custom JS Header (si configurado)
*
* @param array $data Datos del componente desde BD
* @return string Contenido para wp_head
*/
public function renderHeadContent(array $data): string
{
$output = '';
// Layout CSS (container width configurable)
$layoutOutput = $this->renderLayoutCSS($data);
if (!empty($layoutOutput)) {
$output .= $layoutOutput . "\n";
}
// Custom CSS
$cssOutput = $this->renderCustomCSS($data);
if (!empty($cssOutput)) {
$output .= $cssOutput . "\n";
}
// Custom JS Header
$jsHeaderOutput = $this->renderCustomJSHeader($data);
if (!empty($jsHeaderOutput)) {
$output .= $jsHeaderOutput . "\n";
}
return $output;
}
/**
* Genera CSS para el layout configurable
*
* @param array $data Datos del componente
* @return string Bloque style con variables CSS y overrides
*/
private function renderLayoutCSS(array $data): string
{
$containerWidth = $data['layout']['container_max_width'] ?? '1320';
// Validar que el valor sea seguro
$allowedWidths = ['1140', '1200', '1320', '1400', '100%'];
if (!in_array($containerWidth, $allowedWidths, true)) {
$containerWidth = '1320'; // Fallback al default
}
// Generar el CSS
$widthValue = ($containerWidth === '100%') ? '100%' : $containerWidth . 'px';
$widthNumeric = ($containerWidth === '100%') ? '100vw' : $containerWidth . 'px';
// Siempre generar CSS variable para que otros componentes puedan usarla
$css = sprintf(
'<!-- Layout CSS (ROI Theme) -->
<style id="roi-theme-layout-css">
:root {
--roi-container-width: %s;
--roi-container-width-numeric: %s;
}',
esc_attr($widthValue),
esc_attr($widthNumeric)
);
// Solo añadir override de container si NO es el default
if ($containerWidth !== '1320') {
$css .= sprintf('
@media (min-width: 1200px) {
.container,
.container-lg,
.container-xl,
.container-xxl {
max-width: %s;
}
}',
esc_attr($widthValue)
);
}
$css .= '
</style>';
return $css;
}
/**
* Genera contenido para wp_footer
*
* Incluye:
* - Custom JS Footer (si configurado)
*
* @param array $data Datos del componente desde BD
* @return string Contenido para wp_footer
*/
public function renderFooterContent(array $data): string
{
return $this->renderCustomJSFooter($data);
}
/**
* Genera el CSS personalizado
*
* @param array $data Datos del componente
* @return string Bloque style o vacio si no hay CSS
*/
private function renderCustomCSS(array $data): string
{
$css = trim($data['custom_code']['custom_css'] ?? '');
if (empty($css)) {
return '';
}
return sprintf(
'<!-- Custom CSS (ROI Theme) -->
<style id="roi-theme-custom-css">
%s
</style>',
$css // No escapar CSS - usuario avanzado responsable
);
}
/**
* Genera el JavaScript personalizado para header
*
* @param array $data Datos del componente
* @return string Bloque script o vacio si no hay JS
*/
private function renderCustomJSHeader(array $data): string
{
$js = trim($data['custom_code']['custom_js_header'] ?? '');
if (empty($js)) {
return '';
}
return sprintf(
'<!-- Custom JS Header (ROI Theme) -->
<script id="roi-theme-custom-js-header">
%s
</script>',
$js // No escapar JS - usuario avanzado responsable
);
}
/**
* Genera el JavaScript personalizado para footer
*
* @param array $data Datos del componente
* @return string Bloque script o vacio si no hay JS
*/
private function renderCustomJSFooter(array $data): string
{
$js = trim($data['custom_code']['custom_js_footer'] ?? '');
if (empty($js)) {
return '';
}
return sprintf(
'<!-- Custom JS Footer (ROI Theme) -->
<script id="roi-theme-custom-js-footer">
%s
</script>',
$js // No escapar JS - usuario avanzado responsable
);
}
}