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:
215
Shared/Infrastructure/Api/WordPress/AjaxController.php
Normal file
215
Shared/Infrastructure/Api/WordPress/AjaxController.php
Normal file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ROITheme\Shared\Infrastructure\Api\Wordpress;
|
||||
|
||||
use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentUseCase;
|
||||
use ROITheme\Shared\Application\UseCases\SaveComponent\SaveComponentRequest;
|
||||
use ROITheme\Shared\Application\UseCases\GetComponent\GetComponentUseCase;
|
||||
use ROITheme\Shared\Application\UseCases\GetComponent\GetComponentRequest;
|
||||
use ROITheme\Shared\Application\UseCases\DeleteComponent\DeleteComponentUseCase;
|
||||
use ROITheme\Shared\Application\UseCases\DeleteComponent\DeleteComponentRequest;
|
||||
use ROITheme\Shared\Infrastructure\Di\DIContainer;
|
||||
|
||||
/**
|
||||
* AjaxController - Endpoints AJAX de WordPress
|
||||
*
|
||||
* RESPONSABILIDAD: Manejar HTTP (request/response)
|
||||
*
|
||||
* PRINCIPIOS:
|
||||
* - Single Responsibility: Solo maneja HTTP, delega lógica a Use Cases
|
||||
* - Dependency Inversion: Depende de Use Cases (Application)
|
||||
*
|
||||
* SEGURIDAD:
|
||||
* - Verifica nonce
|
||||
* - Verifica capabilities (manage_options)
|
||||
* - Sanitiza inputs
|
||||
*
|
||||
* @package ROITheme\Infrastructure\Api\WordPress
|
||||
*/
|
||||
final class AjaxController
|
||||
{
|
||||
private const NONCE_ACTION = 'roi_theme_admin_nonce';
|
||||
|
||||
public function __construct(
|
||||
private DIContainer $container
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Registrar hooks de WordPress
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
add_action('wp_ajax_roi_theme_save_component', [$this, 'saveComponent']);
|
||||
add_action('wp_ajax_roi_theme_get_component', [$this, 'getComponent']);
|
||||
add_action('wp_ajax_roi_theme_delete_component', [$this, 'deleteComponent']);
|
||||
add_action('wp_ajax_roi_theme_sync_schema', [$this, 'syncSchema']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint: Guardar componente
|
||||
*
|
||||
* POST /wp-admin/admin-ajax.php?action=roi_theme_save_component
|
||||
* Body: { nonce, component_name, data }
|
||||
*
|
||||
* @return void (usa wp_send_json_*)
|
||||
*/
|
||||
public function saveComponent(): void
|
||||
{
|
||||
// 1. Seguridad
|
||||
if (!$this->verifySecurity()) {
|
||||
wp_send_json_error([
|
||||
'message' => 'Security check failed'
|
||||
], 403);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Sanitizar input
|
||||
$componentName = sanitize_key($_POST['component_name'] ?? '');
|
||||
$data = $_POST['data'] ?? [];
|
||||
|
||||
if (empty($componentName)) {
|
||||
wp_send_json_error([
|
||||
'message' => 'Component name is required'
|
||||
], 400);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Crear Request DTO
|
||||
$request = new SaveComponentRequest($componentName, $data);
|
||||
|
||||
// 4. Ejecutar Use Case
|
||||
$useCase = new SaveComponentUseCase(
|
||||
$this->container->getComponentRepository(),
|
||||
$this->container->getValidationService(),
|
||||
$this->container->getCacheService()
|
||||
);
|
||||
|
||||
$response = $useCase->execute($request);
|
||||
|
||||
// 5. Respuesta HTTP
|
||||
if ($response->isSuccess()) {
|
||||
wp_send_json_success($response->getData());
|
||||
} else {
|
||||
wp_send_json_error([
|
||||
'message' => 'Validation failed',
|
||||
'errors' => $response->getErrors()
|
||||
], 422);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint: Obtener componente
|
||||
*
|
||||
* GET /wp-admin/admin-ajax.php?action=roi_theme_get_component&component_name=xxx
|
||||
*/
|
||||
public function getComponent(): void
|
||||
{
|
||||
if (!$this->verifySecurity()) {
|
||||
wp_send_json_error(['message' => 'Security check failed'], 403);
|
||||
return;
|
||||
}
|
||||
|
||||
$componentName = sanitize_key($_GET['component_name'] ?? '');
|
||||
|
||||
if (empty($componentName)) {
|
||||
wp_send_json_error(['message' => 'Component name is required'], 400);
|
||||
return;
|
||||
}
|
||||
|
||||
$request = new GetComponentRequest($componentName);
|
||||
|
||||
$useCase = new GetComponentUseCase(
|
||||
$this->container->getComponentRepository(),
|
||||
$this->container->getCacheService()
|
||||
);
|
||||
|
||||
$response = $useCase->execute($request);
|
||||
|
||||
if ($response->isSuccess()) {
|
||||
wp_send_json_success($response->getData());
|
||||
} else {
|
||||
wp_send_json_error(['message' => $response->getError()], 404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint: Eliminar componente
|
||||
*
|
||||
* POST /wp-admin/admin-ajax.php?action=roi_theme_delete_component
|
||||
* Body: { nonce, component_name }
|
||||
*/
|
||||
public function deleteComponent(): void
|
||||
{
|
||||
if (!$this->verifySecurity()) {
|
||||
wp_send_json_error(['message' => 'Security check failed'], 403);
|
||||
return;
|
||||
}
|
||||
|
||||
$componentName = sanitize_key($_POST['component_name'] ?? '');
|
||||
|
||||
if (empty($componentName)) {
|
||||
wp_send_json_error(['message' => 'Component name is required'], 400);
|
||||
return;
|
||||
}
|
||||
|
||||
$request = new DeleteComponentRequest($componentName);
|
||||
|
||||
$useCase = new DeleteComponentUseCase(
|
||||
$this->container->getComponentRepository(),
|
||||
$this->container->getCacheService()
|
||||
);
|
||||
|
||||
$response = $useCase->execute($request);
|
||||
|
||||
if ($response->isSuccess()) {
|
||||
wp_send_json_success(['message' => $response->getMessage()]);
|
||||
} else {
|
||||
wp_send_json_error(['message' => $response->getError()], 404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint: Sincronizar schemas
|
||||
*
|
||||
* POST /wp-admin/admin-ajax.php?action=roi_theme_sync_schema
|
||||
*/
|
||||
public function syncSchema(): void
|
||||
{
|
||||
if (!$this->verifySecurity()) {
|
||||
wp_send_json_error(['message' => 'Security check failed'], 403);
|
||||
return;
|
||||
}
|
||||
|
||||
$syncService = $this->container->getSchemaSyncService();
|
||||
$result = $syncService->syncAll();
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success($result['data']);
|
||||
} else {
|
||||
wp_send_json_error(['message' => $result['error']], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar seguridad (nonce + capabilities)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function verifySecurity(): bool
|
||||
{
|
||||
// Verificar nonce
|
||||
$nonce = $_REQUEST['nonce'] ?? '';
|
||||
|
||||
if (!wp_verify_nonce($nonce, self::NONCE_ACTION)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verificar permisos (solo administradores)
|
||||
if (!current_user_can('manage_options')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user