Cómo verificar si un usuario (no el actual) ha iniciado sesión

22 nov 2011, 00:28:06
Vistas: 19.3K
Votos: 24

Necesito mostrar el estado en línea (conectado/desconectado) para cada página de autor (plantilla personalizada de página de autor).

is_user_logged_in() solo se aplica al usuario actual y no encuentro un enfoque relevante para el autor actual, como por ejemplo is_author_logged_in()

¿Alguna idea?

Respuesta

One Trick Pony tuvo la amabilidad de preparar el código para dos o tres funciones usando transients, algo que no había usado antes.

http://codex.wordpress.org/Transients_API

Añade esto a functions.php:

add_action('wp', 'update_online_users_status');
function update_online_users_status(){

  if(is_user_logged_in()){

    // obtener la lista de usuarios en línea
    if(($logged_in_users = get_transient('users_online')) === false) $logged_in_users = array();

    $current_user = wp_get_current_user();
    $current_user = $current_user->ID;  
    $current_time = current_time('timestamp');

    if(!isset($logged_in_users[$current_user]) || ($logged_in_users[$current_user] < ($current_time - (15 * 60)))){
      $logged_in_users[$current_user] = $current_time;
      set_transient('users_online', $logged_in_users, 30 * 60);
    }

  }
}

Añade esto a author.php (u otra plantilla de página):

function is_user_online($user_id) {

  // obtener la lista de usuarios en línea
  $logged_in_users = get_transient('users_online');

  // en línea, si está en la lista y la última actividad fue hace menos de 15 minutos
  return isset($logged_in_users[$user_id]) && ($logged_in_users[$user_id] > (current_time('timestamp') - (15 * 60)));
}

$passthis_id = $curauth->ID;
if(is_user_online($passthis_id)){
echo 'El usuario está en línea.';}
else {
echo'El usuario no está en línea.';}

Segunda Respuesta (no usar)

Esta respuesta se incluye como referencia. Como señaló One Trick Pony, este es un enfoque no deseable porque la base de datos se actualiza en cada carga de página. Tras un examen más detallado, el código solo parecía detectar el estado de inicio de sesión del usuario actual en lugar de compararlo además con el autor actual.

1) Instala este plugin: http://wordpress.org/extend/plugins/who-is-online/

2) Añade lo siguiente a tu plantilla de página:

// Establecer la variable $curauth
if(isset($_GET['author_name'])) :
$curauth = get_userdatabylogin($author_name);
else :
$curauth = get_userdata(intval($author));
endif;

// Definir el ID de la página de autor que se está viendo.
$authortemplate_id = $curauth->ID;

// Conectar a la base de datos.
global $wpdb;
// Definir tabla como variable.
$who_is_online_table = $wpdb->prefix . 'who_is_online';
// Consulta: Contar el número de user_id's (plugin) que coincidan con el id del autor (página de autor).
$onlinestatus_check = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM ".$who_is_online_table." WHERE user_id = '".$authortemplate_id."';" ) );

// Si se encuentra una coincidencia...
if ($onlinestatus_check == "1"){
echo "<p>¡El usuario está <strong>en línea</strong> ahora!</p>";
}
else{
echo "<p>El usuario está actualmente <strong>desconectado</strong>.</p>";
}
2
Comentarios

Esa es una de las peores soluciones que podrías encontrar. Ese plugin actualiza la base de datos en cada carga de página...

onetrickpony onetrickpony
22 nov 2011 03:42:13

Gracias por revisarlo. Lo evitaré. He respondido a tu respuesta (abajo). Estoy atascado creando la función.

Dominor Novus Dominor Novus
22 nov 2011 04:11:48
Todas las respuestas a la pregunta 3
6
16

Yo usaría transients para hacer esto:

  • Crea una función de actualización de usuario en línea que enganches a init; se vería algo así:

    // obtener la lista de actividad del usuario
    $logged_in_users = get_transient('online_status');
    
    // obtener el ID del usuario actual
    $user = wp_get_current_user();
    
    // comprobar si el usuario actual necesita actualizar su estado en línea;
    // lo necesita si no existe en la lista
    $no_need_to_update = isset($logged_in_users[$user->ID])
    
        // y si su "última actividad" fue hace menos de, digamos... 15 minutos          
        && $logged_in_users[$user->ID] >  (time() - (15 * 60));
    
    // actualizar la lista si es necesario
    if(!$no_need_to_update){
      $logged_in_users[$user->ID] = time();
      set_transient('online_status', $logged_in_users, $expire_in = (30*60)); // 30 mins 
    }
    

    Esto debería ejecutarse en cada carga de página, pero el transient solo se actualizará si es necesario. Si tienes un gran número de usuarios en línea, quizá quieras aumentar el intervalo de "última actividad" para reducir las escrituras en la base de datos, pero 15 minutos es más que suficiente para la mayoría de sitios...

  • Ahora, para comprobar si un usuario está en línea, simplemente mira dentro de ese transient para ver si un usuario específico está en línea, igual que hiciste arriba:

    // obtener la lista de actividad del usuario
    $logged_in_users = get_transient('online_status');
    
    // por ejemplo, en la página de autor
    $user_to_check = get_query_var('author'); 
    
    $online = isset($logged_in_users[$user_to_check])
       && ($logged_in_users[$user_to_check] >  (time() - (15 * 60)));
    

El transient expira en 30 minutos si no hay actividad alguna. Pero en caso de que tengas usuarios en línea todo el tiempo, no expirará, así que quizá quieras limpiar ese transient periódicamente enganchando otra función a un evento dos veces al día o algo similar. Esta función eliminaría las entradas antiguas de $logged_in_users...

22 nov 2011 02:52:04
Comentarios

Los transients son nuevos para mí. Gracias por el código. No puedo implementar el primer paso. Copié tu primer bloque de código y lo pegué en function user_online_update() { [TU CÓDIGO] }add_action('init', 'user_online_update'); en mi archivo functions.php - Estoy recibiendo un error del servidor que sugiere que algo no se está analizando correctamente o he malinterpretado tus instrucciones.

Dominor Novus Dominor Novus
22 nov 2011 04:01:32

+1 por sugerir usar transients. No mucha gente sabe sobre ellos.

Dwayne Charrington Dwayne Charrington
22 nov 2011 04:52:50

@Dominor: el código completo.

onetrickpony onetrickpony
22 nov 2011 13:28:05

@OneTrickPony: Agregué la acción a functions.php. ¿Dónde agrego la segunda función (ver línea 27 de tu código completo)? Intenté en authors.php y luego en functions.php pero sin éxito. Intenté usar la condición en la línea 25 de tu código completo. Cada vez, la página devuelve un error de servidor o no analiza nada en mi página más allá de tu código. He eliminado mi código original y desactivado el plugin "¿Quién está en línea?". ¿Qué estoy pasando por alto?

Dominor Novus Dominor Novus
22 nov 2011 17:36:23

reemplaza $time_limit con 15 y asegúrate de que has abierto/cerrado correctamente las etiquetas php...

onetrickpony onetrickpony
23 nov 2011 14:09:30

Gracias, finalmente lo resolví. Reemplacé la variable $time_limit. El código en PASTEBIN, en la línea 27, parecía faltarle un paréntesis redondo y uno cuadrado para funcionar. Lo he probado iniciando sesión en tres o cuatro cuentas usando navegadores separados para cada una. Parece estar funcionando genial. ¡Gracias! Agregué el código final a la pregunta (arriba).

Dominor Novus Dominor Novus
28 nov 2011 13:41:13
Mostrar los 1 comentarios restantes
2

Hasta donde sé, no hay una forma de hacer esto usando las funciones integradas de WordPress, pero que eso no te desanime; ¡escribe un plugin!

Una forma en que podrías hacerlo es creando una nueva tabla en la base de datos que simplemente rastree la última vez que el usuario estuvo activo en el sitio. También podrías tener una página de configuración para tu plugin que determine cuánto tiempo considerarías que un usuario registrado está "Conectado".

Implementarías esto usando un hook de WordPress. Comenzaría enganchando al inicio de sesión, para que una vez que un usuario inicie sesión, tu plugin registre la hora en la base de datos. Luego podrías explorar otras cosas como establecer su estado como 'ausente' si hacen clic en cerrar sesión, o 'inactivo' si su tiempo de inicio de sesión fue hace más de dos horas.

Te encontrarías con un problema si están conectados y activos en el sitio, pero han pasado este período de dos horas. En este caso, necesitarías estar enganchado a la sección de wp-admin para que cada vez que hagan algo en wp-admin, actualice tu base de datos con la hora actual.

Luego, en las publicaciones, necesitarías hacer dos cosas: obtener el autor de la publicación actual:

<?php $user_login = the_author_meta( $user_login ); ?>

luego consultar tu base de datos para determinar si están conectados:

<?php if your_plugin_function($user_login)... ?>
...mostrar algo...
22 nov 2011 01:21:20
Comentarios

Basándome en tu solución, encontré un plugin que crea la tabla y permite definir el tiempo transcurrido mediante ajustes. Después de revisar los archivos del plugin, no estoy seguro de cómo manipular el código para mostrar en línea/fuera de línea en mi página de plantilla de autor. Si pudieras echar un vistazo a los archivos del plugin y orientarme en la dirección correcta, te lo agradecería: http://wordpress.org/extend/plugins/who-is-online/ (Siguiendo tus instrucciones, avanzaré lo más que pueda mientras tanto usando un hook en mi archivo functions.php)

Dominor Novus Dominor Novus
22 nov 2011 01:58:16

¡Éxito! Consulté la base de datos del plugin para coincidencias de ID de usuario e ID de autor. He pegado el código en mi pregunta (arriba).

Dominor Novus Dominor Novus
22 nov 2011 03:30:27
0

Decidí revisitar la respuesta dada y ajustarla para que se ajuste a los comentarios.

Un punto que se mencionó en los comentarios fue algún tipo de limpiador de transitorios diario. Como señaló @onetrickpony, podemos usar wp_schedule_event() para configurar un reinicio diario.

Decidí implementar una forma sencilla de obtener todos los usuarios actualmente en línea y recientemente fuera de línea.

Todo está basado en programación orientada a objetos, empaquetado en una clase.

Tabla de contenidos
Obtener el estado de actividad de un usuario específico a partir de su ID.
Obtener un array de todos los usuarios actualmente en línea.
Obtener un array de todos los usuarios recientemente fuera de línea.
Programar un evento recurrente diario para eliminar el transitorio de actividad de usuario.
Empaquetar todo en un buen plugin.

if ( ! class_exists( 'WPC_User_Activity_Monitoring' ) ) {

    class WPC_User_Activity_Monitoring {

        /**
         * @var Integer Margen de inactividad del usuario en minutos.
         */
        private const USER_INACTIVITY_MARGIN = 10 * MINUTE_IN_SECONDS;

        /**
         * @var Integer Margen de autoeliminación del transitorio en minutos.
         */
        private const TRANSIENT_SELF_CLEAR = 30 * MINUTE_IN_SECONDS;

        /**
         * Engancha métodos a un conjunto de acciones.
         *
         * @since 1.0.0
         */
        public function __construct() {

            add_action( 'init', array( $this, 'wpc_user_activity_monitoring_transient' ) );

        }
        
        /**
         * Establece y actualiza el transitorio de monitoreo de actividad de usuario WPC en interacciones del servidor.
         *
         * @since 1.0.0
         *
         * @param Integer $user_id El ID del usuario.
         *
         * @return Bool Verdadero para en línea.
         */
        public function wpc_user_activity_monitoring_transient() {
        
            if ( is_user_logged_in() ) {

                $wpc_user_activity_monitoring_transient = get_transient( 'wpc_user_activity_monitoring_transient' );
        
                if ( empty( $wpc_user_activity_monitoring_transient ) ) {
    
                    $wpc_user_activity_monitoring_transient = array();
    
                };
            
                $user_id = get_current_user_id();
                
                $timestamp = current_time( 'timestamp' );
    
                if ( empty( $wpc_user_activity_monitoring_transient[$user_id] ) || ( $wpc_user_activity_monitoring_transient[$user_id] < ( $timestamp - self::USER_INACTIVITY_MARGIN ) ) ) {
    
                    $wpc_user_activity_monitoring_transient[$user_id] = $timestamp;
    
                    set_transient( 'wpc_user_activity_monitoring_transient', $wpc_user_activity_monitoring_transient, self::TRANSIENT_SELF_CLEAR );
    
                };
        
            };
        
        }
        
        /**
         * Obtener el estado de actividad de un usuario específico a partir de su ID.
         *
         * @since 1.0.0
         *
         * @param Integer $user_id El ID del usuario.
         *
         * @return Bool Verdadero para en línea.
         */
        public function is_user_currently_online( $user_id ) {
        
            $wpc_user_activity_monitoring_transient = get_transient( 'wpc_user_activity_monitoring_transient' );

            if ( ! isset( $wpc_user_activity_monitoring_transient[$user_id] ) ) {
                return;
            };

            if ( $wpc_user_activity_monitoring_transient[$user_id] > ( current_time( 'timestamp' ) - self::USER_INACTIVITY_MARGIN ) ) {
    
                return isset( $wpc_user_activity_monitoring_transient[$user_id] );
    
            };

        }
        
        /**
         * Obtener un array de todos los usuarios actualmente en línea.
         *
         * @since 1.0.0
         *
         * @param Integer $nusers Número de usuarios en línea a recuperar.
         *
         * @return Array Un array de IDs de usuarios actualmente en línea.
         */
        public function get_currently_online_nusers() {
        
            $wpc_user_activity_monitoring_transient = array_reverse( get_transient( 'wpc_user_activity_monitoring_transient' ), true );
            
            $currently_online_nusers = array();
    
            foreach ( $wpc_user_activity_monitoring_transient as $user_id => $timestamp ) {
    
                if ( $timestamp > ( current_time( 'timestamp' ) - self::USER_INACTIVITY_MARGIN ) ) {
    
                    array_push( $currently_online_nusers, $user_id );
    
                };
    
            };
    
            return $currently_online_nusers;
        
        }

        /**
         * Obtener un array de todos los usuarios recientemente fuera de línea.
         *
         * @since 1.0.0
         *
         * @param Integer $nusers Número de usuarios recientemente fuera de línea a recuperar.
         *
         * @return Array Un array de IDs de usuarios recientemente fuera de línea.
         */
        public function get_recently_offline_nusers() {
        
            $wpc_user_activity_monitoring_transient = array_reverse( get_transient( 'wpc_user_activity_monitoring_transient' ), true );
            
            $recently_offline_nusers = array();
    
            foreach ( $wpc_user_activity_monitoring_transient as $user_id => $timestamp ) {
    
                if ( $timestamp < ( current_time( 'timestamp' ) - self::USER_INACTIVITY_MARGIN ) ) {
    
                    array_push( $recently_offline_nusers, $user_id );
    
                };
    
            };

            return $recently_offline_nusers;

        }        

    };

    $wpc_user_activity_monitoring = new WPC_User_Activity_Monitoring();

};

/**
 * Programa un evento recurrente diario, que se dispara a las 23:59:00 para eliminar el transitorio de monitoreo de actividad de usuario WPC.
 *
 * @since 1.0.0
 */
if ( ! wp_next_scheduled ( 'schedule_event_delete_wpc_user_activity_monitoring_transient' ) ) {

    wp_schedule_event( strtotime( '23:59:00' ), 'daily', 'schedule_event_delete_wpc_user_activity_monitoring_transient' );

};

/**
 * Eliminar el transitorio de monitoreo de actividad de usuario WPC.
 *
 * @since 1.0.0
 */
add_action( 'schedule_event_delete_wpc_user_activity_monitoring_transient', 'delete_wpc_user_activity_monitoring_transient' );

if ( ! function_exists( 'delete_wpc_user_activity_monitoring_transient' ) ) {

    function delete_wpc_user_activity_monitoring_transient() {

        delete_transient( 'wpc_user_activity_monitoring_transient' );

    };

};

Empaquetar todo en un buen plugin.

También he creado un plugin para una implementación sencilla. Es de código abierto en GitHub @ https://github.com/amarinediary/WPC-User-Activity-Monitoring. Hay documentación adicional y funcionalidades.

1 abr 2021 04:00:32