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>
This commit is contained in:
272
Shared/Domain/ValueObjects/ComponentContent.php
Normal file
272
Shared/Domain/ValueObjects/ComponentContent.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ROITheme\Shared\Domain\ValueObjects;
|
||||
|
||||
use ROITheme\Shared\Domain\Exceptions\InvalidComponentException;
|
||||
|
||||
/**
|
||||
* ComponentContent - Value Object inmutable para contenido de componente
|
||||
*
|
||||
* RESPONSABILIDAD: Representar y validar el contenido textual y de CTA de un componente
|
||||
*
|
||||
* REGLAS DE NEGOCIO:
|
||||
* - El mensaje de texto puede estar vacío (componentes sin texto)
|
||||
* - Si existe CTA URL debe existir CTA text (y viceversa)
|
||||
* - CTA URL debe ser una URL válida (formato http/https)
|
||||
* - CTA text no puede estar vacío si existe CTA URL
|
||||
* - Title es opcional
|
||||
*
|
||||
* CASOS DE USO:
|
||||
* - Componente solo con mensaje de texto
|
||||
* - Componente con mensaje y CTA
|
||||
* - Componente con title, mensaje y CTA
|
||||
* - Componente sin contenido textual (solo estilos/visibilidad)
|
||||
*
|
||||
* USO:
|
||||
* ```php
|
||||
* // Componente con mensaje y CTA
|
||||
* $content = new ComponentContent(
|
||||
* messageText: 'Welcome to our site!',
|
||||
* ctaText: 'Learn More',
|
||||
* ctaUrl: 'https://example.com/about'
|
||||
* );
|
||||
*
|
||||
* // Componente solo con mensaje
|
||||
* $content = ComponentContent::messageOnly('Hello World!');
|
||||
*
|
||||
* // Componente vacío
|
||||
* $content = ComponentContent::empty();
|
||||
* ```
|
||||
*
|
||||
* @package ROITheme\Shared\Domain\ValueObjects
|
||||
*/
|
||||
final readonly class ComponentContent
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $messageText Texto del mensaje principal
|
||||
* @param string|null $ctaText Texto del Call-to-Action
|
||||
* @param string|null $ctaUrl URL del Call-to-Action
|
||||
* @param string|null $title Título del componente
|
||||
* @throws InvalidComponentException
|
||||
*/
|
||||
public function __construct(
|
||||
private string $messageText = '',
|
||||
private ?string $ctaText = null,
|
||||
private ?string $ctaUrl = null,
|
||||
private ?string $title = null
|
||||
) {
|
||||
$this->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener mensaje de texto
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function messageText(): string
|
||||
{
|
||||
return $this->messageText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener texto del CTA
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function ctaText(): ?string
|
||||
{
|
||||
return $this->ctaText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener URL del CTA
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function ctaUrl(): ?string
|
||||
{
|
||||
return $this->ctaUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener título
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function title(): ?string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar si tiene mensaje de texto
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMessage(): bool
|
||||
{
|
||||
return !empty($this->messageText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar si tiene CTA
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCTA(): bool
|
||||
{
|
||||
return !empty($this->ctaText) && !empty($this->ctaUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar si tiene título
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTitle(): bool
|
||||
{
|
||||
return !empty($this->title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar si está completamente vacío
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return empty($this->messageText) &&
|
||||
empty($this->ctaText) &&
|
||||
empty($this->ctaUrl) &&
|
||||
empty($this->title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertir a array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_filter([
|
||||
'message_text' => $this->messageText,
|
||||
'cta_text' => $this->ctaText,
|
||||
'cta_url' => $this->ctaUrl,
|
||||
'title' => $this->title
|
||||
], fn($value) => $value !== null && $value !== '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validar reglas de negocio
|
||||
*
|
||||
* @throws InvalidComponentException
|
||||
* @return void
|
||||
*/
|
||||
private function validate(): void
|
||||
{
|
||||
// Regla 1: Si existe CTA URL debe existir CTA text
|
||||
if (!empty($this->ctaUrl) && empty($this->ctaText)) {
|
||||
throw new InvalidComponentException('CTA URL requires CTA text');
|
||||
}
|
||||
|
||||
// Regla 2: Si existe CTA text debe existir CTA URL
|
||||
if (!empty($this->ctaText) && empty($this->ctaUrl)) {
|
||||
throw new InvalidComponentException('CTA text requires CTA URL');
|
||||
}
|
||||
|
||||
// Regla 3: CTA URL debe ser URL válida
|
||||
if (!empty($this->ctaUrl) && !$this->isValidUrl($this->ctaUrl)) {
|
||||
throw new InvalidComponentException(
|
||||
sprintf('Invalid CTA URL format: %s', $this->ctaUrl)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validar si una string es URL válida
|
||||
*
|
||||
* @param string $url
|
||||
* @return bool
|
||||
*/
|
||||
private function isValidUrl(string $url): bool
|
||||
{
|
||||
// Debe comenzar con http:// o https://
|
||||
if (!preg_match('/^https?:\/\//i', $url)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Usar filter_var para validación completa
|
||||
return filter_var($url, FILTER_VALIDATE_URL) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory: Contenido vacío
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function empty(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory: Solo mensaje
|
||||
*
|
||||
* @param string $message
|
||||
* @return self
|
||||
*/
|
||||
public static function messageOnly(string $message): self
|
||||
{
|
||||
return new self(messageText: $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory: Mensaje con CTA
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $ctaText
|
||||
* @param string $ctaUrl
|
||||
* @return self
|
||||
*/
|
||||
public static function withCTA(string $message, string $ctaText, string $ctaUrl): self
|
||||
{
|
||||
return new self(
|
||||
messageText: $message,
|
||||
ctaText: $ctaText,
|
||||
ctaUrl: $ctaUrl
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crear desde array
|
||||
*
|
||||
* @param array $data
|
||||
* @return self
|
||||
*/
|
||||
public static function fromArray(array $data): self
|
||||
{
|
||||
return new self(
|
||||
messageText: $data['message_text'] ?? '',
|
||||
ctaText: $data['cta_text'] ?? null,
|
||||
ctaUrl: $data['cta_url'] ?? null,
|
||||
title: $data['title'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparar con otro ComponentContent
|
||||
*
|
||||
* @param ComponentContent $other
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(ComponentContent $other): bool
|
||||
{
|
||||
return $this->messageText === $other->messageText &&
|
||||
$this->ctaText === $other->ctaText &&
|
||||
$this->ctaUrl === $other->ctaUrl &&
|
||||
$this->title === $other->title;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user