true, 'redirect' => $redirect_url]; $this->logoutWordpress($payload); return $this->response($payload); } /** * Cierra la sesion de WordPress asegurando que la respuesta JSON llegue * al dashboard. * * PROBLEMA: los plugins de seguridad con URL de acceso personalizada * (SG Security, WPS Hide Login, Solid Security...) enganchan el hook * 'wp_logout' y hacen wp_redirect() + exit para no dejar ver la pagina de * login por defecto. Ese exit cortaba esta peticion antes de responder: el * dashboard se queda esperando, sigue el redirect y acaba descargando la * home entera (de ahi la espera de varios segundos), nunca recibe * success = true y por tanto no borra el auth_code ni redirige. * * SOLUCION, sin depender de ningun plugin concreto: * * a) Se anula el redirect durante la llamada. Si el filtro 'wp_redirect' * devuelve un valor vacio, wp_redirect() sale sin enviar la cabecera * Location, asi que el exit posterior deja de ser un problema. * Cubre tambien wp_safe_redirect(), que llama a wp_redirect(). * * b) Se deja la respuesta preparada en una funcion de cierre. PHP las * ejecuta aunque el plugin llame a exit, asi que el cliente recibe el * JSON igualmente. * * Si nadie interrumpe, el flujo es el normal: responde la capa REST y la * funcion de cierre no hace nada. * * Las cookies se limpian dentro de evavel_logout() y antes de cualquier * salida, que es imprescindible: si se aplazara el logout al shutdown, * wp_clear_auth_cookie() ya no podria enviar cabeceras y el usuario no * llegaria a desconectarse de WordPress. * * @param array $payload respuesta que espera el dashboard * * @return void */ protected function logoutWordpress(array $payload) { $responded = false; register_shutdown_function(function() use (&$responded, $payload) { // Salida normal: ya ha respondido la capa REST if ($responded) { return; } if (!headers_sent()) { status_header(200); header('Content-Type: application/json; charset=' . get_option('blog_charset')); } echo wp_json_encode($payload); }); add_filter('wp_redirect', '__return_false', PHP_INT_MAX); evavel_logout(); remove_filter('wp_redirect', '__return_false', PHP_INT_MAX); // Se ha llegado hasta aqui, luego nadie ha interrumpido la peticion $responded = true; } }