= 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' ); } } }