Migración completa a Clean Architecture con componentes funcionales

- Reorganización de estructura: Admin/, Public/, Shared/, Schemas/
- 12 componentes migrados: TopNotificationBar, Navbar, CtaLetsTalk, Hero,
  FeaturedImage, TableOfContents, CtaBoxSidebar, SocialShare, CtaPost,
  RelatedPost, ContactForm, Footer
- Panel de administración con tabs Bootstrap 5 funcionales
- Schemas JSON para configuración de componentes
- Renderers dinámicos con CSSGeneratorService (cero CSS hardcodeado)
- FormBuilders para UI admin con Design System consistente
- Fix: Bootstrap JS cargado en header para tabs funcionales
- Fix: buildTextInput maneja valores mixed (bool/string)
- Eliminación de estructura legacy (src/, admin/, assets/css/componente-*)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-11-25 21:20:06 -06:00
parent 90de6df77c
commit 0846a3bf03
224 changed files with 21670 additions and 17816 deletions

View File

@@ -1,138 +1,427 @@
# Capa de Aplicación - Shared (Casos de Uso Compartidos)
# Capa de Aplicación (Application Layer)
## Propósito
## 📋 Propósito
La capa de Aplicación de `shared/` contiene **casos de uso y servicios compartidos** que orquestan la lógica
de dominio. Esta capa coordina el flujo de datos entre el dominio y la infraestructura.
La **Capa de Aplicación** contiene los **Use Cases** que orquestan la lógica de negocio de la aplicación. Actúa como punto de entrada coordinando el flujo entre la UI/API y la Capa de Dominio.
## Principios
Esta capa es el **corazón de la arquitectura limpia**, encapsulando las reglas de negocio específicas de la aplicación sin conocer detalles de implementación.
1. **Orquestación**: Coordina objetos de dominio para realizar casos de uso
2. **Sin lógica de negocio**: Delega la lógica al dominio
3. **Independiente de frameworks**: No depende de WordPress directamente
4. **Contratos claros**: Define interfaces para servicios
## 🎯 Responsabilidades
## Estructura
### ✅ QUÉ HACE
- **Orquestar flujo de la aplicación**: Coordina la secuencia de operaciones necesarias para completar un caso de uso
- **Coordinar llamadas entre capas**: Actúa como intermediario entre la presentación y el dominio
- **Transformar datos (DTOs)**: Utiliza Data Transfer Objects para encapsular entrada/salida
- **Manejar transacciones**: Coordina operaciones que deben ejecutarse de forma atómica
- **Validar entrada**: Verifica que los datos de entrada sean válidos antes de procesarlos
- **Gestionar cache**: Coordina estrategias de cache para optimizar rendimiento
### ❌ QUÉ NO HACE
- **NO contiene lógica de negocio**: La lógica de dominio vive en la Capa de Dominio
- **NO conoce detalles de implementación**: Solo depende de interfaces, nunca de implementaciones concretas
- **NO accede directamente a BD**: Usa repositorios a través de interfaces
- **NO maneja detalles de UI**: No conoce si la petición viene de REST, CLI o WordPress Admin
## 📁 Estructura
```
shared/Application/
├── Contracts/ # Interfaces de servicios (CacheServiceInterface, etc.)
└── Services/ # Implementaciones de servicios compartidos
Application/
├── UseCases/
│ ├── SaveComponent/
│ │ ├── SaveComponentUseCase.php (Orquestador)
│ │ ├── SaveComponentRequest.php (DTO entrada)
│ │ └── SaveComponentResponse.php (DTO salida)
│ ├── GetComponent/
│ │ ├── GetComponentUseCase.php
│ │ ├── GetComponentRequest.php
│ │ └── GetComponentResponse.php
│ ├── SyncSchema/
│ │ ├── SyncSchemaUseCase.php
│ │ ├── SyncSchemaRequest.php
│ │ └── SyncSchemaResponse.php
│ └── DeleteComponent/
│ ├── DeleteComponentUseCase.php
│ ├── DeleteComponentRequest.php
│ └── DeleteComponentResponse.php
└── README.md (este archivo)
```
## Ejemplos de Uso
## 🔧 Use Cases Disponibles
### Contracts (Interfaces de Servicios)
### 1. SaveComponent
**Propósito**: Guardar o actualizar la configuración de un componente.
**Flujo**:
1. Validar datos de entrada
2. Crear/actualizar entidad Component
3. Persistir en repositorio
4. Invalidar cache
5. Retornar confirmación
**Ejemplo de uso**:
```php
namespace ROITheme\Shared\Application\Contracts;
use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentUseCase;
use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentRequest;
interface CacheServiceInterface
{
public function get(string $key): mixed;
public function set(string $key, mixed $value, int $ttl = 3600): bool;
public function delete(string $key): bool;
public function flush(): bool;
$useCase = new SaveComponentUseCase($repository, $validator, $cache);
$request = new SaveComponentRequest('top_bar', [
'background_color' => '#ffffff',
'text_color' => '#000000',
'show_logo' => true
]);
$response = $useCase->execute($request);
if ($response->isSuccess()) {
echo "Componente guardado exitosamente";
} else {
echo "Error: " . $response->getError();
}
```
```php
namespace ROITheme\Shared\Application\Contracts;
### 2. GetComponent
interface ValidationServiceInterface
{
public function validate(array $data, array $rules): array;
public function fails(): bool;
public function errors(): array;
**Propósito**: Obtener la configuración de un componente con cache-first strategy.
**Flujo**:
1. Verificar cache
2. Si existe en cache → retornar
3. Si no → consultar repositorio
4. Guardar en cache
5. Retornar datos
**Ejemplo de uso**:
```php
use ROITheme\Shared\Application\UseCases\GetComponent\GetComponentUseCase;
use ROITheme\Shared\Application\UseCases\GetComponent\GetComponentRequest;
$useCase = new GetComponentUseCase($repository, $cache);
$request = new GetComponentRequest('top_bar');
$response = $useCase->execute($request);
if ($response->isSuccess()) {
$data = $response->getData();
// Procesar datos del componente
} else {
echo "Error: " . $response->getError();
}
```
### Services (Implementaciones Abstractas)
### 3. SyncSchema
Servicios que pueden tener múltiples implementaciones:
**Propósito**: Sincronizar múltiples componentes desde un archivo JSON de schemas.
**Flujo**:
1. Leer archivo JSON
2. Validar formato
3. Procesar cada componente del schema
4. Identificar cambios (agregados/actualizados/eliminados)
5. Retornar resumen de cambios
**Ejemplo de uso**:
```php
namespace ROITheme\Shared\Application\Services;
use ROITheme\Shared\Application\UseCases\SyncSchema\SyncSchemaUseCase;
use ROITheme\Shared\Application\UseCases\SyncSchema\SyncSchemaRequest;
use ROITheme\Shared\Application\Contracts\ValidationServiceInterface;
$useCase = new SyncSchemaUseCase($componentRepo, $defaultsRepo);
$request = new SyncSchemaRequest('/path/to/schemas.json');
abstract class BaseValidationService implements ValidationServiceInterface
$response = $useCase->execute($request);
if ($response->isSuccess()) {
echo $response->getSummary();
// Output: "Added: 2, Updated: 3, Deleted: 1"
} else {
foreach ($response->getErrors() as $error) {
echo "Error: {$error}\n";
}
}
```
### 4. DeleteComponent
**Propósito**: Eliminar un componente del sistema.
**Flujo**:
1. Verificar que el componente existe
2. Eliminar de repositorio
3. Invalidar cache
4. Retornar confirmación
**Ejemplo de uso**:
```php
use ROITheme\Shared\Application\UseCases\DeleteComponent\DeleteComponentUseCase;
use ROITheme\Shared\Application\UseCases\DeleteComponent\DeleteComponentRequest;
$useCase = new DeleteComponentUseCase($repository, $cache);
$request = new DeleteComponentRequest('old_component');
$response = $useCase->execute($request);
if ($response->isSuccess()) {
echo $response->getMessage();
} else {
echo "Error: " . $response->getError();
}
```
## 🏛️ Principios Arquitectónicos
### Regla de Dependencias
```
Application Layer
↓ (depende de)
Domain Layer (solo interfaces)
NO depende de Infrastructure Layer
```
La capa de aplicación **solo** puede depender de la capa de dominio, y únicamente de sus **interfaces**, nunca de implementaciones concretas.
### Dependency Inversion Principle
**✅ CORRECTO**:
```php
namespace ROITheme\Shared\Application\UseCases\SaveComponent;
use ROITheme\Shared\Domain\Contracts\ComponentRepositoryInterface;
use ROITheme\Shared\Domain\Contracts\ValidationServiceInterface;
final class SaveComponentUseCase
{
protected array $errors = [];
public function __construct(
private ComponentRepositoryInterface $repository, // ✅ Interfaz
private ValidationServiceInterface $validator, // ✅ Interfaz
private CacheServiceInterface $cache // ✅ Interfaz
) {}
}
```
public function fails(): bool
**❌ INCORRECTO**:
```php
use ROITheme\Infrastructure\Persistence\WordPress\WordPressComponentRepository;
final class SaveComponentUseCase
{
public function __construct(
private WordPressComponentRepository $repository // ❌ Implementación concreta
) {}
}
```
### DTOs Inmutables
Todos los Request y Response utilizan `readonly class` para garantizar inmutabilidad:
```php
final readonly class SaveComponentRequest
{
public function __construct(
private string $componentName,
private array $data
) {}
// Solo getters, sin setters
public function getComponentName(): string
{
return !empty($this->errors);
return $this->componentName;
}
}
```
### Factory Methods en Responses
Los responses utilizan factory methods para encapsular lógica de creación:
```php
final readonly class SaveComponentResponse
{
// Constructor privado
private function __construct(
private bool $success,
private ?string $error
) {}
// Factory methods públicos
public static function success(): self
{
return new self(true, null);
}
public function errors(): array
public static function failure(string $error): self
{
return $this->errors;
return new self(false, $error);
}
abstract public function validate(array $data, array $rules): array;
}
```
## Relación con Infrastructure
## 🧪 Testing
La capa de Application **define contratos** (interfaces), pero **no implementa** la lógica específica
de frameworks. Las implementaciones concretas van en `shared/Infrastructure/`:
### Estrategia de Testing
```
shared/Application/Contracts/CacheServiceInterface.php (interface)
shared/Infrastructure/Services/WordPressCacheService.php (implementación)
```
## Reglas de Dependencia
**PUEDE** depender de:
- `shared/Domain/` (Value Objects, Entities, Exceptions)
- Interfaces dentro de `shared/Application/Contracts/`
**NO PUEDE** depender de:
- `shared/Infrastructure/` (implementaciones concretas)
- `admin/` o `public/`
- WordPress functions directamente
- Detalles de implementación
## Testing
Los servicios de esta capa se testean con **tests unitarios usando mocks**:
Todos los Use Cases tienen tests unitarios con mocks de dependencias:
```php
// tests/Unit/Shared/Application/Services/SomeServiceTest.php
public function test_validates_data_correctly()
namespace ROITheme\Tests\Unit\Application\UseCases;
use PHPUnit\Framework\TestCase;
use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentUseCase;
use ROITheme\Shared\Domain\Contracts\ComponentRepositoryInterface;
use ROITheme\Shared\Domain\Contracts\ValidationServiceInterface;
class SaveComponentUseCaseTest extends TestCase
{
$validator = $this->createMock(ValidationServiceInterface::class);
$validator->method('validate')->willReturn(['name' => 'Test']);
private ComponentRepositoryInterface $repository;
private ValidationServiceInterface $validator;
private SaveComponentUseCase $useCase;
$service = new SomeService($validator);
$result = $service->process(['name' => 'Test']);
protected function setUp(): void
{
$this->repository = $this->createMock(ComponentRepositoryInterface::class);
$this->validator = $this->createMock(ValidationServiceInterface::class);
$this->assertTrue($result);
$this->useCase = new SaveComponentUseCase(
$this->repository,
$this->validator,
$this->cache
);
}
public function test_saves_component_successfully(): void
{
// Test implementation
}
}
```
## Cuándo Agregar Código Aquí
### Ubicación de Tests
Agrega código a `shared/Application/` cuando:
- Defines un contrato para un servicio compartido
- Necesitas orquestar múltiples objetos de dominio
- El servicio será usado por admin/ y public/
- Necesitas abstraer implementaciones de infraestructura
```
tests/Unit/Application/UseCases/
├── SaveComponentUseCaseTest.php
├── GetComponentUseCaseTest.php
├── SyncSchemaUseCaseTest.php
└── DeleteComponentUseCaseTest.php
```
No agregues aquí:
- Lógica de negocio (va en Domain/)
- Implementaciones concretas de WordPress (van en Infrastructure/)
- Lógica específica de un solo contexto
- Código acoplado a frameworks
### Cobertura Esperada
## Ejemplos de Servicios Comunes
- **Objetivo**: 95%
- **Mínimo aceptable**: 90%
- `ValidationServiceInterface`: Validación de datos
- `CacheServiceInterface`: Manejo de caché
- `SerializerServiceInterface`: Serialización de datos
- `LoggerServiceInterface`: Logging
- `EventDispatcherInterface`: Eventos del sistema
### Ejecutar Tests
```bash
# Todos los tests de Application
cd _planeacion/roi-theme/_testing-suite
vendor/bin/phpunit tests/Unit/Application
# Test específico
vendor/bin/phpunit tests/Unit/Application/UseCases/SaveComponentUseCaseTest.php
# Con cobertura
vendor/bin/phpunit tests/Unit/Application --coverage-text
# Reporte HTML de cobertura
vendor/bin/phpunit tests/Unit/Application --coverage-html coverage
```
## 🔍 Requisitos Técnicos
Todos los archivos de la capa de aplicación deben cumplir:
### 1. Strict Types
```php
<?php
declare(strict_types=1); // ✅ Obligatorio en todos los archivos
```
### 2. Namespace Correcto
```php
namespace ROITheme\Shared\Application\UseCases\{UseCase};
```
Patrón: **Context-First**`ROITheme\Shared\Application\...`
### 3. PHPDoc Completo
```php
/**
* SaveComponentUseCase - Guardar/actualizar componente
*
* RESPONSABILIDAD: Orquestar guardado de componente
* ...
*
* @package ROITheme\Shared\Application\UseCases\SaveComponent
*/
final class SaveComponentUseCase
{
// ...
}
```
### 4. Type Hints Estrictos
```php
// ✅ CORRECTO
public function execute(SaveComponentRequest $request): SaveComponentResponse
{
// ...
}
// ❌ INCORRECTO
public function execute($request) // Sin type hints
{
// ...
}
```
## 📚 Referencias
- **Documentación de Fase**: `_planeacion/roi-theme/_MIGRACION-CLEAN-ARCHITECTURE/Fase-05/FASE-05-PLAN-IMPLEMENTACION.md`
- **Clean Architecture**: Robert C. Martin
- **Dependency Inversion Principle**: SOLID Principles
## ✅ Checklist de Validación
Para validar que un Use Case cumple con los estándares:
- [ ] Usa `declare(strict_types=1)`
- [ ] Namespace correcto: `ROITheme\Shared\Application\UseCases\{UseCase}`
- [ ] PHPDoc completo en clase
- [ ] Solo depende de interfaces del Domain
- [ ] Request es `final readonly class`
- [ ] Response es `final readonly class` con factory methods
- [ ] UseCase es `final class`
- [ ] Constructor injection de dependencias
- [ ] Método `execute()` con type hints
- [ ] Tests unitarios con >= 90% cobertura
- [ ] Sin dependencias de Infrastructure
## 🚀 Próximos Pasos
Después de completar la Capa de Aplicación:
1. **Fase 6**: Infrastructure Layer (Repositorios, Adaptadores)
2. **Fase 7**: API Layer (REST Endpoints)
3. **Fase 8**: Integration Tests
4. **Fase 9**: Migración gradual del código legacy
---
**Mantenedor**: ROI Theme Development Team
**Última actualización**: 2025-01-19
**Versión**: 1.0.0