Rename folders to match PHP PSR-4 autoloading conventions: - schemas → Schemas - shared → Shared - Wordpress → WordPress (in all locations) Fixes deployment issues on Linux servers where filesystem is case-sensitive. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
181 lines
5.0 KiB
PHP
181 lines
5.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace ROITheme\Shared\Infrastructure\Services;
|
|
|
|
use ROITheme\Shared\Domain\Contracts\CSSGeneratorInterface;
|
|
|
|
/**
|
|
* Class CSSGeneratorService
|
|
*
|
|
* Implementación concreta del generador de CSS.
|
|
* Convierte arrays de configuración de estilos en reglas CSS válidas y formateadas.
|
|
*
|
|
* Responsabilidades:
|
|
* - Generar string CSS a partir de selector y estilos
|
|
* - Convertir propiedades snake_case → kebab-case
|
|
* - Normalizar nombres de propiedades (text_color → color)
|
|
* - Formatear reglas CSS con indentación legible
|
|
* - Sanitizar valores para prevenir inyección
|
|
*
|
|
* @package ROITheme\Shared\Infrastructure\Services
|
|
*/
|
|
final class CSSGeneratorService implements CSSGeneratorInterface
|
|
{
|
|
/**
|
|
* Mapa de nombres de propiedades CSS normalizadas.
|
|
*
|
|
* @var array<string, string>
|
|
*/
|
|
private const PROPERTY_MAP = [
|
|
'text-color' => 'color',
|
|
'bg-color' => 'background-color',
|
|
];
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function generate(string $selector, array $styles): string
|
|
{
|
|
if (empty($styles)) {
|
|
return '';
|
|
}
|
|
|
|
// Filtrar valores vacíos o null
|
|
$styles = $this->filterEmptyValues($styles);
|
|
|
|
if (empty($styles)) {
|
|
return '';
|
|
}
|
|
|
|
// Convertir array de estilos a propiedades CSS
|
|
$cssProperties = $this->buildCSSProperties($styles);
|
|
|
|
// Formatear regla CSS completa
|
|
return $this->formatCSSRule($selector, $cssProperties);
|
|
}
|
|
|
|
/**
|
|
* Filtra valores vacíos, null o que solo contienen espacios en blanco.
|
|
*
|
|
* @param array<string, mixed> $styles Array de estilos
|
|
* @return array<string, string> Array filtrado
|
|
*/
|
|
private function filterEmptyValues(array $styles): array
|
|
{
|
|
return array_filter(
|
|
$styles,
|
|
fn($value) => $value !== null && $value !== '' && trim((string)$value) !== ''
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Convierte array de estilos a propiedades CSS formateadas.
|
|
*
|
|
* @param array<string, string> $styles Array de estilos
|
|
* @return array<int, string> Array de propiedades CSS formateadas
|
|
*/
|
|
private function buildCSSProperties(array $styles): array
|
|
{
|
|
$properties = [];
|
|
|
|
foreach ($styles as $property => $value) {
|
|
// Convertir snake_case a kebab-case
|
|
$cssProperty = $this->convertToKebabCase($property);
|
|
|
|
// Normalizar nombre de propiedad
|
|
$cssProperty = $this->normalizePropertyName($cssProperty);
|
|
|
|
// Sanitizar valor
|
|
$sanitizedValue = $this->sanitizeValue((string)$value);
|
|
|
|
// Agregar propiedad formateada
|
|
$properties[] = sprintf('%s: %s;', $cssProperty, $sanitizedValue);
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Convierte snake_case a kebab-case.
|
|
*
|
|
* Ejemplos:
|
|
* - background_color → background-color
|
|
* - font_size → font-size
|
|
* - padding_top → padding-top
|
|
*
|
|
* @param string $property Nombre de propiedad en snake_case
|
|
* @return string Nombre de propiedad en kebab-case
|
|
*/
|
|
private function convertToKebabCase(string $property): string
|
|
{
|
|
return str_replace('_', '-', strtolower($property));
|
|
}
|
|
|
|
/**
|
|
* Normaliza nombres de propiedades CSS a su forma estándar.
|
|
*
|
|
* Mapea alias comunes a nombres de propiedades CSS estándar:
|
|
* - text-color → color
|
|
* - bg-color → background-color
|
|
*
|
|
* @param string $property Nombre de propiedad
|
|
* @return string Nombre de propiedad normalizado
|
|
*/
|
|
private function normalizePropertyName(string $property): string
|
|
{
|
|
return self::PROPERTY_MAP[$property] ?? $property;
|
|
}
|
|
|
|
/**
|
|
* Sanitiza valores CSS para prevenir inyección de código.
|
|
*
|
|
* Remueve tags HTML y caracteres potencialmente peligrosos,
|
|
* manteniendo valores CSS válidos como colores, unidades, etc.
|
|
*
|
|
* @param string $value Valor CSS sin sanitizar
|
|
* @return string Valor CSS sanitizado
|
|
*/
|
|
private function sanitizeValue(string $value): string
|
|
{
|
|
// Remover tags HTML
|
|
$value = strip_tags($value);
|
|
|
|
// Remover caracteres de control excepto espacios
|
|
$value = preg_replace('/[^\P{C}\s]/u', '', $value);
|
|
|
|
// Trim espacios
|
|
$value = trim($value);
|
|
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Formatea la regla CSS completa con selector y propiedades.
|
|
*
|
|
* Genera CSS con formato legible:
|
|
* ```css
|
|
* .selector {
|
|
* property: value;
|
|
* property2: value2;
|
|
* }
|
|
* ```
|
|
*
|
|
* @param string $selector Selector CSS
|
|
* @param array<int, string> $properties Array de propiedades formateadas
|
|
* @return string Regla CSS completa
|
|
*/
|
|
private function formatCSSRule(string $selector, array $properties): string
|
|
{
|
|
if (empty($properties)) {
|
|
return '';
|
|
}
|
|
|
|
return sprintf(
|
|
"%s {\n %s\n}",
|
|
$selector,
|
|
implode("\n ", $properties)
|
|
);
|
|
}
|
|
}
|