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:
427
Shared/Application/README.md
Normal file
427
Shared/Application/README.md
Normal file
@@ -0,0 +1,427 @@
|
||||
# Capa de Aplicación (Application Layer)
|
||||
|
||||
## 📋 Propósito
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## 🎯 Responsabilidades
|
||||
|
||||
### ✅ 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
|
||||
|
||||
```
|
||||
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)
|
||||
```
|
||||
|
||||
## 🔧 Use Cases Disponibles
|
||||
|
||||
### 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
|
||||
use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentUseCase;
|
||||
use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentRequest;
|
||||
|
||||
$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();
|
||||
}
|
||||
```
|
||||
|
||||
### 2. GetComponent
|
||||
|
||||
**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();
|
||||
}
|
||||
```
|
||||
|
||||
### 3. SyncSchema
|
||||
|
||||
**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
|
||||
use ROITheme\Shared\Application\UseCases\SyncSchema\SyncSchemaUseCase;
|
||||
use ROITheme\Shared\Application\UseCases\SyncSchema\SyncSchemaRequest;
|
||||
|
||||
$useCase = new SyncSchemaUseCase($componentRepo, $defaultsRepo);
|
||||
$request = new SyncSchemaRequest('/path/to/schemas.json');
|
||||
|
||||
$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
|
||||
{
|
||||
public function __construct(
|
||||
private ComponentRepositoryInterface $repository, // ✅ Interfaz
|
||||
private ValidationServiceInterface $validator, // ✅ Interfaz
|
||||
private CacheServiceInterface $cache // ✅ Interfaz
|
||||
) {}
|
||||
}
|
||||
```
|
||||
|
||||
**❌ 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 $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 static function failure(string $error): self
|
||||
{
|
||||
return new self(false, $error);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Estrategia de Testing
|
||||
|
||||
Todos los Use Cases tienen tests unitarios con mocks de dependencias:
|
||||
|
||||
```php
|
||||
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
|
||||
{
|
||||
private ComponentRepositoryInterface $repository;
|
||||
private ValidationServiceInterface $validator;
|
||||
private SaveComponentUseCase $useCase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->repository = $this->createMock(ComponentRepositoryInterface::class);
|
||||
$this->validator = $this->createMock(ValidationServiceInterface::class);
|
||||
|
||||
$this->useCase = new SaveComponentUseCase(
|
||||
$this->repository,
|
||||
$this->validator,
|
||||
$this->cache
|
||||
);
|
||||
}
|
||||
|
||||
public function test_saves_component_successfully(): void
|
||||
{
|
||||
// Test implementation
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Ubicación de Tests
|
||||
|
||||
```
|
||||
tests/Unit/Application/UseCases/
|
||||
├── SaveComponentUseCaseTest.php
|
||||
├── GetComponentUseCaseTest.php
|
||||
├── SyncSchemaUseCaseTest.php
|
||||
└── DeleteComponentUseCaseTest.php
|
||||
```
|
||||
|
||||
### Cobertura Esperada
|
||||
|
||||
- **Objetivo**: 95%
|
||||
- **Mínimo aceptable**: 90%
|
||||
|
||||
### 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
|
||||
Reference in New Issue
Block a user