'GET', 'callback' => [$this, 'handleRequest'], 'permission_callback' => '__return_true', 'args' => [ 'post_id' => [ 'required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint', // IMPORTANTE: postId=0 es valido (paginas de archivo, home, etc.) 'validate_callback' => static fn($value): bool => $value >= 0, ], 'nonce' => [ 'required' => false, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ], ], ]); } /** * Maneja la peticion REST. */ public function handleRequest(WP_REST_Request $request): WP_REST_Response { $this->sendNoCacheHeaders(); // Validar nonce si se proporciona $nonce = $request->get_param('nonce'); if ($nonce !== null && !wp_verify_nonce($nonce, self::NONCE_ACTION)) { return new WP_REST_Response([ 'show_ads' => false, 'reasons' => ['invalid_nonce'], 'cache_seconds' => 0, 'timestamp' => time(), ], 403); } $postId = (int) $request->get_param('post_id'); $userContext = $this->buildUserContext(); $decision = $this->useCase->execute($postId, $userContext); // El timestamp se inyecta aqui (Infrastructure) para mantener Domain puro return new WP_REST_Response($decision->toArray(time()), 200); } /** * Construye UserContext desde el estado actual de WordPress. */ private function buildUserContext(): UserContext { $isLoggedIn = is_user_logged_in(); $userRoles = []; if ($isLoggedIn) { $user = wp_get_current_user(); $userRoles = array_map( static fn(string $role): int => self::roleToId($role), $user->roles ); } // isMobile se determina por el cliente, no el servidor // El cliente enviara esta info, pero por defecto asumimos false $isMobile = false; return new UserContext( isLoggedIn: $isLoggedIn, isMobile: $isMobile, userRoles: $userRoles ); } /** * Convierte nombre de rol a ID numerico para consistencia. */ private static function roleToId(string $role): int { $roleMap = [ 'administrator' => 1, 'editor' => 2, 'author' => 3, 'contributor' => 4, 'subscriber' => 5, ]; return $roleMap[$role] ?? 0; } /** * Envia headers para prevenir cache en proxies/CDNs. */ private function sendNoCacheHeaders(): void { header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Expires: Thu, 01 Jan 1970 00:00:00 GMT'); header('Vary: Cookie'); } /** * Obtiene la accion del nonce para generacion en frontend. */ public static function getNonceAction(): string { return self::NONCE_ACTION; } }