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>
336 lines
8.7 KiB
PHP
336 lines
8.7 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace ROITheme\Shared\Domain\Entities;
|
|
|
|
use ROITheme\Shared\Domain\ValueObjects\ComponentName;
|
|
use ROITheme\Shared\Domain\ValueObjects\ComponentConfiguration;
|
|
use ROITheme\Shared\Domain\ValueObjects\ComponentVisibility;
|
|
use ROITheme\Shared\Domain\Exceptions\InvalidComponentException;
|
|
|
|
/**
|
|
* Component - Entidad del Dominio
|
|
*
|
|
* RESPONSABILIDAD: Representar un componente del tema con toda su lógica de negocio
|
|
*
|
|
* INVARIANTES (Reglas que SIEMPRE deben cumplirse):
|
|
* 1. Un componente siempre tiene un nombre válido
|
|
* 2. Un componente siempre tiene configuración (puede estar vacía)
|
|
* 3. Si tiene CTA URL debe tener CTA text (validado en ComponentConfiguration)
|
|
* 4. Los colores siempre están en formato hexadecimal válido
|
|
* 5. El timestamp de updated_at es siempre >= created_at
|
|
*
|
|
* ENTIDAD vs VALUE OBJECT:
|
|
* - Component es ENTIDAD porque tiene identidad (puede cambiar configuración pero sigue siendo el mismo componente)
|
|
* - ComponentName es VALUE OBJECT (dos nombres iguales son indistinguibles)
|
|
* - ComponentConfiguration es VALUE OBJECT (inmutable)
|
|
*
|
|
* USO:
|
|
* ```php
|
|
* $component = new Component(
|
|
* ComponentName::fromString('top_bar'),
|
|
* ComponentConfiguration::fromFlat([
|
|
* 'enabled' => true,
|
|
* 'message_text' => 'Welcome!'
|
|
* ]),
|
|
* ComponentVisibility::allDevices()
|
|
* );
|
|
*
|
|
* // Actualizar configuración (inmutabilidad)
|
|
* $updated = $component->updateConfiguration(
|
|
* $component->configuration()->withValue('content', 'message_text', 'Hello!')
|
|
* );
|
|
* ```
|
|
*
|
|
* @package ROITheme\Shared\Domain\Entities
|
|
*/
|
|
final class Component
|
|
{
|
|
/**
|
|
* @var ComponentName Nombre del componente (inmutable)
|
|
*/
|
|
private ComponentName $name;
|
|
|
|
/**
|
|
* @var ComponentConfiguration Configuración del componente
|
|
*/
|
|
private ComponentConfiguration $configuration;
|
|
|
|
/**
|
|
* @var ComponentVisibility Visibilidad del componente
|
|
*/
|
|
private ComponentVisibility $visibility;
|
|
|
|
/**
|
|
* @var bool Componente habilitado
|
|
*/
|
|
private bool $isEnabled;
|
|
|
|
/**
|
|
* @var string Versión del schema
|
|
*/
|
|
private string $schemaVersion;
|
|
|
|
/**
|
|
* @var \DateTimeImmutable Fecha de creación
|
|
*/
|
|
private \DateTimeImmutable $createdAt;
|
|
|
|
/**
|
|
* @var \DateTimeImmutable Fecha de última actualización
|
|
*/
|
|
private \DateTimeImmutable $updatedAt;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param ComponentName $name
|
|
* @param ComponentConfiguration $configuration
|
|
* @param ComponentVisibility $visibility
|
|
* @param bool $isEnabled
|
|
* @param string $schemaVersion
|
|
* @param \DateTimeImmutable|null $createdAt
|
|
* @param \DateTimeImmutable|null $updatedAt
|
|
* @throws InvalidComponentException Si se violan invariantes
|
|
*/
|
|
public function __construct(
|
|
ComponentName $name,
|
|
ComponentConfiguration $configuration,
|
|
ComponentVisibility $visibility,
|
|
bool $isEnabled = true,
|
|
string $schemaVersion = '1.0.0',
|
|
?\DateTimeImmutable $createdAt = null,
|
|
?\DateTimeImmutable $updatedAt = null
|
|
) {
|
|
$this->name = $name;
|
|
$this->configuration = $configuration;
|
|
$this->visibility = $visibility;
|
|
$this->isEnabled = $isEnabled;
|
|
$this->schemaVersion = $schemaVersion;
|
|
$this->createdAt = $createdAt ?? new \DateTimeImmutable();
|
|
$this->updatedAt = $updatedAt ?? new \DateTimeImmutable();
|
|
|
|
$this->validateInvariants();
|
|
}
|
|
|
|
/**
|
|
* Obtener nombre del componente
|
|
*
|
|
* @return ComponentName
|
|
*/
|
|
public function name(): ComponentName
|
|
{
|
|
return $this->name;
|
|
}
|
|
|
|
/**
|
|
* Obtener configuración del componente
|
|
*
|
|
* @return ComponentConfiguration
|
|
*/
|
|
public function configuration(): ComponentConfiguration
|
|
{
|
|
return $this->configuration;
|
|
}
|
|
|
|
/**
|
|
* Obtener visibilidad del componente
|
|
*
|
|
* @return ComponentVisibility
|
|
*/
|
|
public function visibility(): ComponentVisibility
|
|
{
|
|
return $this->visibility;
|
|
}
|
|
|
|
/**
|
|
* Verificar si el componente está habilitado
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isEnabled(): bool
|
|
{
|
|
return $this->isEnabled;
|
|
}
|
|
|
|
/**
|
|
* Obtener versión del schema
|
|
*
|
|
* @return string
|
|
*/
|
|
public function schemaVersion(): string
|
|
{
|
|
return $this->schemaVersion;
|
|
}
|
|
|
|
/**
|
|
* Obtener fecha de creación
|
|
*
|
|
* @return \DateTimeImmutable
|
|
*/
|
|
public function createdAt(): \DateTimeImmutable
|
|
{
|
|
return $this->createdAt;
|
|
}
|
|
|
|
/**
|
|
* Obtener fecha de última actualización
|
|
*
|
|
* @return \DateTimeImmutable
|
|
*/
|
|
public function updatedAt(): \DateTimeImmutable
|
|
{
|
|
return $this->updatedAt;
|
|
}
|
|
|
|
/**
|
|
* Crear nuevo componente con configuración actualizada
|
|
* (Inmutabilidad: retorna nueva instancia)
|
|
*
|
|
* @param ComponentConfiguration $configuration Nueva configuración
|
|
* @return self Nueva instancia
|
|
*/
|
|
public function updateConfiguration(ComponentConfiguration $configuration): self
|
|
{
|
|
return new self(
|
|
$this->name,
|
|
$configuration,
|
|
$this->visibility,
|
|
$this->isEnabled,
|
|
$this->schemaVersion,
|
|
$this->createdAt,
|
|
new \DateTimeImmutable()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Crear nuevo componente con visibilidad actualizada
|
|
* (Inmutabilidad: retorna nueva instancia)
|
|
*
|
|
* @param ComponentVisibility $visibility Nueva visibilidad
|
|
* @return self Nueva instancia
|
|
*/
|
|
public function updateVisibility(ComponentVisibility $visibility): self
|
|
{
|
|
return new self(
|
|
$this->name,
|
|
$this->configuration,
|
|
$visibility,
|
|
$this->isEnabled,
|
|
$this->schemaVersion,
|
|
$this->createdAt,
|
|
new \DateTimeImmutable()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Crear nuevo componente habilitado
|
|
* (Inmutabilidad: retorna nueva instancia)
|
|
*
|
|
* @return self Nueva instancia con isEnabled=true
|
|
*/
|
|
public function enable(): self
|
|
{
|
|
return new self(
|
|
$this->name,
|
|
$this->configuration,
|
|
$this->visibility,
|
|
true,
|
|
$this->schemaVersion,
|
|
$this->createdAt,
|
|
new \DateTimeImmutable()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Crear nuevo componente deshabilitado
|
|
* (Inmutabilidad: retorna nueva instancia)
|
|
*
|
|
* @return self Nueva instancia con isEnabled=false
|
|
*/
|
|
public function disable(): self
|
|
{
|
|
return new self(
|
|
$this->name,
|
|
$this->configuration,
|
|
$this->visibility,
|
|
false,
|
|
$this->schemaVersion,
|
|
$this->createdAt,
|
|
new \DateTimeImmutable()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Comparar con otro componente
|
|
* (Dos componentes son iguales si tienen el mismo nombre)
|
|
*
|
|
* @param Component $other Otro componente
|
|
* @return bool True si son el mismo componente
|
|
*/
|
|
public function equals(Component $other): bool
|
|
{
|
|
return $this->name->equals($other->name);
|
|
}
|
|
|
|
/**
|
|
* Obtener datos del componente para renderizado
|
|
* Retorna la configuración completa en formato array
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getData(): array
|
|
{
|
|
return $this->configuration->all();
|
|
}
|
|
|
|
/**
|
|
* Convertir a array para serialización
|
|
*
|
|
* @return array
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'name' => $this->name->value(),
|
|
'configuration' => $this->configuration->all(),
|
|
'visibility' => $this->visibility->toArray(),
|
|
'is_enabled' => $this->isEnabled,
|
|
'schema_version' => $this->schemaVersion,
|
|
'created_at' => $this->createdAt->format('Y-m-d H:i:s'),
|
|
'updated_at' => $this->updatedAt->format('Y-m-d H:i:s')
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Convertir a string para debugging
|
|
*
|
|
* @return string
|
|
*/
|
|
public function __toString(): string
|
|
{
|
|
return sprintf(
|
|
'Component(%s, enabled=%s, schema=%s)',
|
|
$this->name->value(),
|
|
$this->isEnabled ? 'true' : 'false',
|
|
$this->schemaVersion
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Validar invariantes del componente
|
|
*
|
|
* @throws InvalidComponentException Si se viola algún invariante
|
|
* @return void
|
|
*/
|
|
private function validateInvariants(): void
|
|
{
|
|
// Invariante: updated_at >= created_at
|
|
if ($this->updatedAt < $this->createdAt) {
|
|
throw new InvalidComponentException(
|
|
'Updated timestamp cannot be before created timestamp'
|
|
);
|
|
}
|
|
}
|
|
}
|