repository = new WordPressSnippetRepository($wpdb); $this->getAllUseCase = new GetAllSnippetsUseCase($this->repository); $this->saveUseCase = new SaveSnippetUseCase($this->repository); $this->deleteUseCase = new DeleteSnippetUseCase($this->repository); // Registrar handler de formulario POST $this->registerFormHandler(); } /** * Registra handler para procesar formularios POST */ private function registerFormHandler(): void { // Solo registrar una vez static $registered = false; if ($registered) { return; } $registered = true; add_action('admin_init', function() { $this->handleFormSubmission(); }); } /** * Procesa envío de formulario */ public function handleFormSubmission(): void { if (!isset($_POST['roi_css_action'])) { return; } // Verificar nonce if (!wp_verify_nonce($_POST['_wpnonce'] ?? '', self::NONCE_ACTION)) { wp_die('Nonce verification failed'); } // Verificar permisos if (!current_user_can('manage_options')) { wp_die('Insufficient permissions'); } $action = sanitize_text_field($_POST['roi_css_action']); try { match ($action) { 'save' => $this->processSave($_POST), 'delete' => $this->processDelete($_POST), default => null, }; // Redirect con mensaje de éxito wp_redirect(add_query_arg('roi_message', 'success', wp_get_referer())); exit; } catch (ValidationException $e) { // Redirect con mensaje de error wp_redirect(add_query_arg([ 'roi_message' => 'error', 'roi_error' => urlencode($e->getMessage()) ], wp_get_referer())); exit; } } /** * Procesa guardado de snippet */ private function processSave(array $data): void { $id = sanitize_text_field($data['snippet_id'] ?? ''); // Generar ID si es nuevo if (empty($id)) { $id = SnippetId::generate()->value(); } $request = SaveSnippetRequest::fromArray([ 'id' => $id, 'name' => sanitize_text_field($data['snippet_name'] ?? ''), 'description' => sanitize_textarea_field($data['snippet_description'] ?? ''), 'css' => wp_strip_all_tags($data['snippet_css'] ?? ''), 'type' => sanitize_text_field($data['snippet_type'] ?? 'deferred'), 'pages' => array_map('sanitize_text_field', $data['snippet_pages'] ?? ['all']), 'enabled' => isset($data['snippet_enabled']), 'order' => absint($data['snippet_order'] ?? 100), ]); $this->saveUseCase->execute($request); } /** * Procesa eliminación de snippet */ private function processDelete(array $data): void { $id = sanitize_text_field($data['snippet_id'] ?? ''); if (empty($id)) { throw new ValidationException('ID de snippet requerido para eliminar'); } $this->deleteUseCase->execute($id); } /** * Construye el formulario del componente * * @param string $componentId ID del componente (custom-css-manager) * @return string HTML del formulario */ public function buildForm(string $componentId): string { $snippets = $this->getAllUseCase->execute(); $message = $this->getFlashMessage(); $html = ''; // Header $html .= $this->buildHeader($componentId, count($snippets)); // Mensajes flash if ($message) { $html .= sprintf( '
Gestiona snippets de CSS personalizados. Los snippets críticos se cargan en el head, los diferidos en el footer.
'; $html .= 'No hay snippets configurados.
'; } else { $html .= '| Nombre | '; $html .= 'Tipo | '; $html .= 'Páginas | '; $html .= 'Estado | '; $html .= 'Acciones | '; $html .= '
|---|