✅Controla los Accesos a tu WordPress con este Código (Incluye Exportación CSV)

En la administración de un sitio web en WordPress, mantener un registro detallado de los accesos y salidas de los usuarios es crucial para garantizar la seguridad y el buen funcionamiento del sistema. Este código te permite implementar una solución completa y eficiente para gestionar y controlar estos registros de manera ordenada y práctica. A través de una tabla interactiva, podrás visualizar cada inicio y cierre de sesión de los usuarios registrados, exportar los datos en formato CSV para archivarlos, y eliminar los registros antiguos para mantener tu base de datos limpia y optimizada.

El funcionamiento es simple pero poderoso: cada vez que un usuario inicia o cierra sesión en tu sitio, se genera un registro que incluye su nombre, correo electrónico, rol de usuario, tipo de evento (inicio o cierre) y la fecha y hora correspondiente. Estos registros se almacenan en una tabla personalizada dentro de la base de datos de WordPress y se presentan en el panel de administración mediante una tabla interactiva, que permite seleccionar, deseleccionar y eliminar registros según sea necesario.

registrar accesos wordpress

En cuanto al almacenamiento, es importante considerar cuánto espacio ocupa cada registro y cómo gestionar de manera efectiva el crecimiento de la base de datos. Cada registro ocupa aproximadamente 200 bytes, lo que significa que, en un año, si se generan 1,000 registros diarios (un volumen alto para sitios con mucho tráfico), se ocuparían alrededor de 73 MB en la base de datos. En un servidor típico de hosting compartido para WordPress, con capacidad de base de datos entre 500 MB y 1 GB, podrías almacenar fácilmente entre 500,000 y 2,000,000 de registros, siempre y cuando el resto del sistema esté bien optimizado.

Para evitar que el sistema se vuelva lento o poco eficiente, es recomendable implementar planes regulares de exportación y limpieza de la base de datos. Por ejemplo, puedes establecer un cronograma semanal o mensual para exportar los registros más recientes en formato CSV y luego eliminarlos del sistema. Esto te permitirá mantener la base de datos ligera, asegurando un buen rendimiento y una fácil recuperación de los datos almacenados, en caso de que necesites consultarlos más adelante.

Además, la funcionalidad de exportación asegura que puedas respaldar la información en tu ordenador u otro sistema de almacenamiento. Esto no solo garantiza la seguridad de los datos, sino que también te permite acceder a ellos en cualquier momento, incluso si decides mover tu sitio web a otro servidor o plataforma.

1. Función principal: acceso_usuarios_menu()

Esta función crea un nuevo menú en el panel de administración de WordPress. Su propósito es permitir a los administradores acceder a una página personalizada donde se gestionan los registros de accesos y salidas de los usuarios.

  • Hook:add_action('admin_menu', 'acceso_usuarios_menu')
    • Este hook asegura que el menú se registre en el momento adecuado.
  • Parámetros importantes:
    • Título de la página: 'Registro de Accesos'
    • Nombre en el menú: 'Registro Accesos'
    • Permisos necesarios: 'manage_options' (para administradores).
    • Icono del menú: 'dashicons-admin-users' (puedes cambiarlo por otro de Dashicons ).

2. Crear o actualizar la tabla en la base de datos: verificar_o_actualizar_tabla_acceso_usuarios()

Esta función verifica si existe la tabla personalizada wp_registro_accesos en la base de datos. Si no existe, la crea.

  • Estructura de la tabla:
    • id: Identificador único para cada registro.
    • usuario_id: ID del usuario en WordPress.
    • usuario_nombre: Nombre completo del usuario.
    • usuario_email: Dirección de correo.
    • usuario_rol: Rol del usuario (administrador, editor, etc.).
    • tipo_evento: Define si fue un «Inicio de Sesión» o «Cierre de Sesión».
    • fecha: Fecha y hora del evento.
  • Hook:add_action('init', 'verificar_o_actualizar_tabla_acceso_usuarios')
    • Esto asegura que la tabla se cree o actualice en cada carga del sitio.

3. Registrar eventos de accesos y salidas: registrar_acceso_usuario()

Esta función registra automáticamente cada inicio y cierre de sesión de un usuario.

  • Parámetros principales:
    • tipo_evento: Define el tipo de evento, como «Inicio de Sesión» o «Cierre de Sesión».
    • user_login: Nombre de usuario (opcional, por defecto se toma el usuario actual).
  • Datos almacenados:
    • Información del usuario: ID, nombre, correo y rol.
    • Detalles del evento: Tipo de evento y fecha.
  • Vinculación con eventos:
    • Inicio de sesión: add_action('wp_login', ...)
    • Cierre de sesión: add_action('clear_auth_cookie', ...)

4. Mostrar registros en el panel de administración: mostrar_registro_accesos()

Esta función genera una tabla interactiva en el panel de administración que muestra los registros almacenados.

  • Consulta de registros:
    Recupera todos los registros ordenados por fecha en orden descendente para que los eventos más recientes aparezcan primero.
  • Tabla interactiva con DataTables:
    • Ordenar: La columna de fecha se ordena automáticamente de más reciente a más antigua.
    • Buscar: Permite realizar búsquedas rápidas dentro de los registros.
    • Seleccionar: Puedes seleccionar registros para exportarlos o eliminarlos.
  • Botones adicionales:
    • Seleccionar todos: Marca todos los registros visibles.
    • Deseleccionar todos: Desmarca todos los registros.
    • Eliminar seleccionados: Borra los registros seleccionados.

5. Exportar registros como CSV: exportar_registros_accesos()

Esta función permite exportar los registros almacenados a un archivo CSV. El archivo incluye toda la información necesaria, como ID, nombre de usuario, correo, rol, tipo de evento y fecha.

  • Orden de los datos:
    Se exportan en el mismo orden en que se muestran, es decir, de más reciente a más antiguo.
  • Encabezados del CSV:
    • Incluyen columnas como «ID», «Usuario», «Nombre», «Correo», «Rol», «Tipo de Evento» y «Fecha».
  • Propiedades de los encabezados HTTP:
    • Content-Disposition: Define el nombre del archivo como registro_accesos.csv.
registro de accesos wordpress con exportacion

6. Eliminar registros seleccionados: eliminar_registros_seleccionados()

Esta función permite limpiar la base de datos de registros innecesarios.

  • Eliminar seleccionados:
    Elimina únicamente los registros que el usuario haya marcado en la tabla interactiva.
  • AJAX:
    Utiliza AJAX para realizar las eliminaciones sin recargar la página.

7. Traducción de roles: traducir_rol()

Convierte los roles de usuario, que en WordPress están en inglés, a español para mostrarlos de manera más comprensible en la tabla.

  • Ejemplo de traducciones:
    • administratorAdministrador
    • editorEditor
    • subscriberSuscriptor
  • Extender roles personalizados:
    Si tu sitio utiliza roles personalizados, puedes añadirlos fácilmente al array de traducciones.

El siguiente código tienes que agregarlo en el functions.php de tu tema hijo o utilizar un plugin como CODE SNIPPETS. También puedes crear tu propio plugin con unos simples pasos.

// Crear página en el admin para visualizar los accesos/salidas
function acceso_usuarios_menu() {
    add_menu_page(
        'Registro de Accesos',
        'Registro Accesos',
        'manage_options',
        'registro-accesos',
        'mostrar_registro_accesos',
        'dashicons-admin-users',
        100
    );
}
add_action('admin_menu', 'acceso_usuarios_menu');

// Función para actualizar la tabla y añadir nuevas columnas si no existen
function verificar_o_actualizar_tabla_acceso_usuarios() {
    global $wpdb;
    $tabla = $wpdb->prefix . 'registro_accesos';

    if ($wpdb->get_var("SHOW TABLES LIKE '$tabla'") != $tabla) {
        $charset_collate = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE $tabla (
            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            usuario_id BIGINT(20) UNSIGNED DEFAULT NULL,
            usuario_nombre VARCHAR(255) DEFAULT NULL,
            usuario_usuario VARCHAR(255) DEFAULT NULL,
            usuario_email VARCHAR(255) DEFAULT NULL,
            usuario_rol VARCHAR(255) DEFAULT NULL,
            tipo_evento VARCHAR(255) NOT NULL,
            fecha DATETIME DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id)
        ) $charset_collate;";

        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }
}
add_action('init', 'verificar_o_actualizar_tabla_acceso_usuarios');

// Función para registrar eventos de acceso/salida
function registrar_acceso_usuario($tipo_evento, $user_login = null) {
    global $wpdb;

    if ($user_login) {
        $usuario = get_user_by('login', $user_login);
    } else {
        $usuario = wp_get_current_user();
    }

    $usuario_id = $usuario->ID ?? 0;
    $usuario_nombre = $usuario->first_name . ' ' . $usuario->last_name;
    $usuario_usuario = $usuario->user_login ?? 'Desconocido';
    $usuario_email = $usuario->user_email ?? 'No disponible';
    $usuario_rol = !empty($usuario->roles) ? implode(', ', $usuario->roles) : 'Sin rol';

    $tabla = $wpdb->prefix . 'registro_accesos';
    $wpdb->insert($tabla, [
        'usuario_id' => $usuario_id,
        'usuario_nombre' => $usuario_nombre,
        'usuario_usuario' => $usuario_usuario,
        'usuario_email' => $usuario_email,
        'usuario_rol' => $usuario_rol,
        'tipo_evento' => $tipo_evento,
        'fecha' => current_time('mysql'),
    ]);
}

// Registrar inicio y cierre de sesión
add_action('wp_login', function($user_login) {
    registrar_acceso_usuario('Inicio de Sesión', $user_login);
});
add_action('clear_auth_cookie', function() {
    registrar_acceso_usuario('Cierre de Sesión');
});

// Mostrar registros de accesos y CSVs en el admin
function mostrar_registro_accesos() {
    global $wpdb;
    $tabla = $wpdb->prefix . 'registro_accesos';

    // Incluir estilos y scripts de DataTables y Select
    echo '<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">';
    echo '<link rel="stylesheet" href="https://cdn.datatables.net/select/1.5.0/css/select.dataTables.min.css">';
    echo '<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>';
    echo '<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>';
    echo '<script src="https://cdn.datatables.net/select/1.5.0/js/dataTables.select.min.js"></script>';

    if (isset($_POST['exportar_registros'])) {
        exportar_registros_accesos();
    }

    $registros = $wpdb->get_results("SELECT * FROM $tabla ORDER BY fecha DESC");

    echo '<div class="wrap"><h1>Registro de Accesos</h1>';
    echo '<form method="post" style="margin-bottom: 20px;">';
    echo '<button name="exportar_registros" class="button button-primary">Exportar Registros</button>';
    echo '</form>';

    // Botones adicionales
    echo '<button id="select-all" class="button">Seleccionar Todos</button>';
	echo '<button id="deselect-all" class="button">Deseleccionar Todos</button>';
    echo '<button id="delete-selected" class="button button-danger" disabled>Eliminar Seleccionados</button>';

    // Mostrar la tabla
    echo '<table class="widefat datatable" id="tabla_registro_accesos">
        <thead>
            <tr>
                <th>ID</th>
                <th>Usuario</th>
                <th>Nombre</th>
                <th>Correo</th>
                <th>Rol</th>
                <th>Tipo de Evento</th>
                <th>Fecha</th>
            </tr>
        </thead>
        <tbody>';

    if (!empty($registros)) {
        foreach ($registros as $registro) {
            echo '<tr>';
            echo '<td>' . esc_html($registro->id) . '</td>';
            echo '<td>' . esc_html($registro->usuario_usuario ?? 'Desconocido') . '</td>';
            echo '<td>' . esc_html($registro->usuario_nombre ?? 'No disponible') . '</td>';
            echo '<td>' . esc_html($registro->usuario_email ?? 'No disponible') . '</td>';
            echo '<td>' . esc_html(!empty($registro->usuario_rol) 
                    ? implode(', ', array_map('traducir_rol', explode(', ', $registro->usuario_rol))) 
                    : 'Sin rol') . '</td>';
            echo '<td>' . esc_html($registro->tipo_evento ?? 'Desconocido') . '</td>';
            echo '<td>' . esc_html(!empty($registro->fecha) ? date('d/m/Y H:i:s', strtotime($registro->fecha)) : 'No disponible') . '</td>';
            echo '</tr>';
        }
    } else {
        // Fila vacía si no hay registros
        echo '<tr>
                <td colspan="7" style="text-align: center; color: #999;">No hay registros disponibles.</td>
            </tr>';
    }

    echo '</tbody></table>';

    echo '<script>
        jQuery(document).ready(function($) {
            // Desactivar alertas de errores en DataTables
            $.fn.dataTable.ext.errMode = "none";

            // Inicializar DataTables con selección
            var table = $("#tabla_registro_accesos").DataTable({
                "paging": true,
                "searching": true,
                "ordering": true,
				"order": [[6, "desc"]], // Ordenar por la columna de la fecha (índice 6) en orden descendente
                "select": {
                    style: "multi" // Selección múltiple
                },
				"lengthMenu": [[10, 25, 50, 100, 500, 1000, -1], [10, 25, 50, 100, 500, 1000, "Mostrar Todos"]],
                "pageLength": 10,
                "language": {
                    "url": "https://cdn.datatables.net/plug-ins/1.13.4/i18n/es-ES.json"
                }
            });

            // Habilitar o deshabilitar el botón según las filas seleccionadas
            table.on("select deselect", function () {
                var selectedRows = table.rows({ selected: true }).count();
                $("#delete-selected").prop("disabled", selectedRows === 0);
            });

            // Seleccionar todas las filas
            $("#select-all").click(function () {
                table.rows().select();
            });
			
			   // Deseleccionar todas las filas
            $("#deselect-all").click(function () {
                table.rows().deselect();
            });

            // Eliminar filas seleccionadas
            $("#delete-selected").click(function () {
                var selectedRows = table.rows({ selected: true }).data();
                var ids = [];

                selectedRows.each(function (rowData) {
                    ids.push(rowData[0]); // Suponiendo que la primera columna es el ID
                });

                if (ids.length > 0 && confirm("¿Estás seguro de que deseas eliminar los registros seleccionados?")) {
                    // Llamada AJAX para eliminar los registros seleccionados
                    $.post(ajaxurl, { 
                        action: "eliminar_registros_seleccionados", 
                        ids: ids 
                    }, function (response) {
                        if (response.success) {
                            table.rows({ selected: true }).remove().draw();
                            alert("Registros seleccionados eliminados correctamente.");
                        } else {
                            alert("Hubo un error al eliminar los registros seleccionados.");
                        }
                    });
                }
            });

            // Eliminar todos los registros
            $("#delete-all").click(function () {
                if (confirm("¿Estás seguro de que deseas eliminar todos los registros? Esta acción no se puede deshacer.")) {
                    // Llamada AJAX para eliminar todos los registros
                    $.post(ajaxurl, { action: "eliminar_todos_registros" }, function (response) {
                        if (response.success) {
                            table.clear().draw(); // Limpiar la tabla
                            alert("Todos los registros han sido eliminados.");
                        } else {
                            alert("Hubo un error al eliminar todos los registros.");
                        }
                    });
                }
            });
        });
    </script>';
}


// Exportar registros como CSV
function exportar_registros_accesos() {
    global $wpdb;

    if (ob_get_length()) {
        ob_end_clean();
    }

    $tabla = $wpdb->prefix . 'registro_accesos';
    $registros = $wpdb->get_results("SELECT * FROM $tabla ORDER BY fecha DESC", ARRAY_A);

    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment;filename=registro_accesos.csv');

    $output = fopen('php://output', 'w');

    // Escribir encabezados
    fputcsv($output, array('ID', 'Usuario', 'Nombre', 'Correo', 'Rol', 'Tipo de Evento', 'Fecha'));

    // Escribir registros
    foreach ($registros as $registro) {
        fputcsv($output, array(
            $registro['id'],
            $registro['usuario_usuario'],
            $registro['usuario_nombre'],
            $registro['usuario_email'],
            implode(', ', array_map('traducir_rol', explode(', ', $registro['usuario_rol']))),
            $registro['tipo_evento'],
            date('d/m/Y H:i:s', strtotime($registro['fecha']))
        ));
    }

    fclose($output);
    exit;
}

// Traducir roles
function traducir_rol($rol) {
    $roles_traducidos = [
        'administrator' => 'Administrador',
        'editor' => 'Editor',
        'author' => 'Autor',
        'contributor' => 'Colaborador',
        'subscriber' => 'Suscriptor',
        'customer' => 'Cliente',
        'shop_manager' => 'Gerente de Tienda',
    ];

    return $roles_traducidos[$rol] ?? ucfirst($rol);
}

add_action('wp_ajax_eliminar_registros_seleccionados', 'eliminar_registros_seleccionados');
function eliminar_registros_seleccionados() {
    if (!isset($_POST['ids']) || empty($_POST['ids'])) {
        wp_send_json_error(['message' => 'No se proporcionaron IDs.']);
    }

    global $wpdb;
    $tabla = $wpdb->prefix . 'registro_accesos';
    $ids = array_map('intval', $_POST['ids']); // Sanitizar los IDs

    // Eliminar los registros de la base de datos
    $in_clause = implode(',', $ids);
    $result = $wpdb->query("DELETE FROM $tabla WHERE id IN ($in_clause)");

    if ($result !== false) {
        wp_send_json_success();
    } else {
        wp_send_json_error(['message' => 'No se pudieron eliminar los registros.']);
    }
}



Lenguaje del código: PHP (php)

Nos vemos en el siguiente tutorial. Un saludo.

5/5 - (1 voto)
Compartir Artículo

Un comentario

  1. Fran Salas Master WP 1 año atrás

    Deja tus opiniones o dudas en los comentarios.

¿Tienes una duda o sugerencia sobre este artículo?

Puedes dejar un comentario de forma anónima, sin necesidad de registrarte ni proporcionar ningún dato personal. Tu mensaje se publicará como “Usuario Anónimo No Premium”, un perfil que agrupa a todos los visitantes no registrados.

Importante: para evitar el spam automático, todos los comentarios anónimos deben comenzar con el símbolo #. Ejemplo: # Tengo una duda sobre los shortcodes personalizados...

Este espacio está destinado exclusivamente a preguntas concretas, dudas o sugerencias relacionadas con el contenido del artículo. Por respeto a los demás lectores, no se publicarán temas sin relación.

Privacidad y normas:
  • No tienes que agregar tu nombre, correo ni ningún otro dato identificativo.
  • No se permiten enlaces en comentarios anónimos.
  • No se permiten símbolos especiales como < o > (menor y mayor que), ya que se consideran intentos de insertar código y serán bloqueados.
  • Todos los comentarios anónimos pasan por revisión antes de ser publicados y solo se aprobarán si aportan valor al contenido del artículo.
¿Quieres comentar con tu nombre y que tu mensaje se publique al instante? Inicia sesión o regístrate.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

0%