Files
roi-theme/Shared/Domain/ValueObjects/ComponentName.php
FrankZamora 90863cd8f5 fix(structure): Correct case-sensitivity for Linux compatibility
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>
2025-11-26 22:53:34 -06:00

170 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
namespace ROITheme\Shared\Domain\ValueObjects;
use ROITheme\Shared\Domain\Exceptions\InvalidComponentException;
/**
* ComponentName - Value Object inmutable para nombre de componente
*
* RESPONSABILIDAD: Representar y validar el nombre de un componente del tema
*
* REGLAS DE NEGOCIO:
* - El nombre no puede estar vacío
* - El nombre debe tener entre 3 y 50 caracteres
* - El nombre solo puede contener letras minúsculas, números, guiones bajos y guiones
* - El nombre debe comenzar con una letra
*
* INVARIANTES:
* - Una vez creado, el nombre no puede cambiar (inmutable)
* - El nombre siempre está en formato normalizado (lowercase, sin espacios)
*
* USO:
* ```php
* $name = new ComponentName('top_bar');
* echo $name->value(); // "top_bar"
* echo $name->toString(); // "top_bar"
* ```
*
* @package ROITheme\Shared\Domain\ValueObjects
*/
final readonly class ComponentName
{
/**
* Longitud mínima del nombre
*/
private const MIN_LENGTH = 3;
/**
* Longitud máxima del nombre
*/
private const MAX_LENGTH = 50;
/**
* Patrón regex para validar formato del nombre
* - Debe comenzar con letra minúscula
* - Puede contener letras minúsculas, números, guiones bajos y guiones
*/
private const PATTERN = '/^[a-z][a-z0-9_-]*$/';
/**
* @param string $value Nombre del componente
* @throws InvalidComponentException Si el nombre no cumple las reglas de negocio
*/
public function __construct(private string $value)
{
$this->validate();
}
/**
* Obtener el valor del nombre
*
* @return string
*/
public function value(): string
{
return $this->value;
}
/**
* Convertir a string
*
* @return string
*/
public function toString(): string
{
return $this->value;
}
/**
* Comparar con otro ComponentName
*
* @param ComponentName $other
* @return bool
*/
public function equals(ComponentName $other): bool
{
return $this->value === $other->value;
}
/**
* Validar reglas de negocio del nombre
*
* @throws InvalidComponentException
* @return void
*/
private function validate(): void
{
// Regla 1: No puede estar vacío
if (empty($this->value)) {
throw new InvalidComponentException('Component name cannot be empty');
}
// Regla 2: Longitud entre MIN y MAX
$length = strlen($this->value);
if ($length < self::MIN_LENGTH || $length > self::MAX_LENGTH) {
throw new InvalidComponentException(
sprintf(
'Component name must be between %d and %d characters (got %d)',
self::MIN_LENGTH,
self::MAX_LENGTH,
$length
)
);
}
// Regla 3: Formato válido (lowercase, números, guiones bajos, comienza con letra)
if (!preg_match(self::PATTERN, $this->value)) {
throw new InvalidComponentException(
'Component name must start with a letter and contain only lowercase letters, numbers, underscores, and hyphens'
);
}
}
/**
* Crear desde string (factory method)
*
* @param string $value
* @return self
*/
public static function fromString(string $value): self
{
return new self($value);
}
/**
* Normalizar string a formato de nombre válido
*
* Convierte:
* - "Top Bar" → "top_bar"
* - "FOOTER-CTA" → "footer_cta"
* - " sidebar " → "sidebar"
*
* @param string $value
* @return self
*/
public static function fromNormalized(string $value): self
{
// Trim espacios
$normalized = trim($value);
// Convertir a minúsculas
$normalized = strtolower($normalized);
// Reemplazar espacios y guiones por guiones bajos
$normalized = str_replace([' ', '-'], '_', $normalized);
// Eliminar caracteres no permitidos
$normalized = preg_replace('/[^a-z0-9_]/', '', $normalized);
// Eliminar guiones bajos duplicados
$normalized = preg_replace('/_+/', '_', $normalized);
// Eliminar guiones bajos al inicio/final
$normalized = trim($normalized, '_');
return new self($normalized);
}
}