plugin_instance = $plugin_instance; $this->geolocation_manager = $geolocation_manager; add_action('wp_ajax_advaipbl_close_user_session', [$this,'ajax_close_user_session']); add_action('wp_ajax_advaipbl_close_all_user_sessions', [$this,'ajax_close_all_user_sessions']); add_action('wp_ajax_advaipbl_close_sessions_by_role', [$this,'ajax_close_sessions_by_role']); add_action('admin_post_advaipbl_usm_save_settings', [$this,'save_settings']); } public function enqueue_scripts_styles() { wp_enqueue_style('advaipbl-styles', plugin_dir_url(dirname(__FILE__)) . 'css/advaipbl-styles.css', [], ADVAIPBL_VERSION); wp_enqueue_script('advaipbl-script', plugin_dir_url(dirname(__FILE__)) . 'js/advaipbl-script.js', ['jquery', 'advaipbl-admin-core-js'], ADVAIPBL_VERSION, true); wp_localize_script('advaipbl-script', 'advaipbl_ajax_obj', [ 'ajax_url' => admin_url('admin-ajax.php'), 'nonce_close_session' => wp_create_nonce('advaipbl_close_session_nonce'), 'nonce_close_all' => wp_create_nonce('advaipbl_close_all_sessions_nonce'), 'nonce_close_by_role' => wp_create_nonce('advaipbl_close_sessions_by_role_nonce'), 'text_confirm_close_user' => __('Close all sessions for this user?', 'advanced-ip-blocker'), 'text_confirm_close_all' => __('Close ALL sessions for ALL users?', 'advanced-ip-blocker'), 'text_confirm_close_role' => __('Close all sessions for the selected role?', 'advanced-ip-blocker'), 'text_select_role' => __('Please select a role.', 'advanced-ip-blocker'), 'title_close_user' => __('Close User Sessions', 'advanced-ip-blocker'), 'title_close_all' => __('Close All Sessions', 'advanced-ip-blocker'), 'title_close_role' => __('Close Sessions by Role', 'advanced-ip-blocker'), 'btn_close_user' => __('Yes, Close Sessions', 'advanced-ip-blocker'), 'btn_close_all' => __('Yes, Close All', 'advanced-ip-blocker'), 'btn_close_role' => __('Yes, Close for This Role', 'advanced-ip-blocker'), 'title_clear_cache' => __('Clear Location Cache', 'advanced-ip-blocker'), 'text_confirm_clear_cache' => __('Are you sure you want to clear the location cache?', 'advanced-ip-blocker'), 'btn_clear_cache' => __('Yes, Clear Cache', 'advanced-ip-blocker'), ]); } public function display_admin_page() { if (! current_user_can('manage_options')) { wp_die(esc_html__('You do not have permission to access this page.', 'advanced-ip-blocker')); } $this->enqueue_scripts_styles(); // phpcs:disable WordPress.Security.NonceVerification.Recommended $search_term = isset($_GET['s']) ? sanitize_text_field(wp_unslash($_GET['s'])) : ''; $orderby = isset($_GET['orderby']) ? sanitize_key($_GET['orderby']) : 'last_activity'; $order = isset($_GET['order']) ? strtolower(sanitize_key($_GET['order'])) : 'desc'; $current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1; $per_page = isset($_GET['advaipbl_per_page']) ? absint($_GET['advaipbl_per_page']) : 20; $all_sessions = $this->get_active_sessions(); $sessions_to_display = $all_sessions; if (! empty($search_term)) { $sessions_to_display = array_filter( $all_sessions, function ($session) use ($search_term) { $search_in = [ $session['username'] ?? '', $session['email'] ?? '', $session['ip'] ?? '' ]; foreach ($search_in as $field) { if (stripos($field, $search_term) !== false) { return true; } } return false; } ); } $sortable_columns = [ 'username', 'role', 'ip', 'last_activity' ]; if (!in_array($orderby, $sortable_columns, true)) { $orderby = 'last_activity'; } if (!in_array($order, ['asc', 'desc'], true)) { $order = 'desc'; } usort( $sessions_to_display, function ($a, $b) use ($orderby, $order) { $a_val = $a[ $orderby ] ?? ''; $b_val = $b[ $orderby ] ?? ''; if ('last_activity' === $orderby) { $a_val = strtotime($a_val); $b_val = strtotime($b_val); } if ($a_val == $b_val) { return 0; } return ('asc' === $order) ? ($a_val <=> $b_val) : ($b_val <=> $a_val); } ); $total_items = count($sessions_to_display); $total_pages = ceil($total_items / $per_page); $sessions_page = array_slice($sessions_to_display, ($current_page - 1) * $per_page, $per_page); $all_roles = []; if (! empty($all_sessions)) { foreach ($all_sessions as $session) { if (isset($session['role'])) { foreach (explode(', ', $session['role']) as $r) { if (! empty($r)) { $all_roles[ $r ] = true; } } } } } $locations = $this->get_cached_locations(array_column($sessions_page, 'ip')); ?>

plugin_instance no es null antes de llamar al método. if ($this->plugin_instance) { $this->plugin_instance->render_per_page_selector($per_page); } ?>
add_query_arg(['paged' => '%#%', 's' => $search_term]), 'format' => '', 'total' => $total_pages, 'current' => $current_page]); if ($page_links) { echo '' . wp_kses_post($page_links) . ''; } ?>

print_sortable_header(__('User', 'advanced-ip-blocker'), 'username', $orderby, $order, $search_term); ?> print_sortable_header(__('Role', 'advanced-ip-blocker'), 'role', $orderby, $order, $search_term); ?> print_sortable_header(__('IP', 'advanced-ip-blocker'), 'ip', $orderby, $order, $search_term); ?> print_sortable_header(__('Last Activity', 'advanced-ip-blocker'), 'last_activity', $orderby, $order, $search_term); ?>



parse_user_agent($session['device'])); ?>

$column_key, 'order' => $next_order, 's' => $search_term ]); echo ''; echo '' . esc_html($label) . ''; echo ''; } public function ajax_close_user_session() { check_ajax_referer('advaipbl_close_session_nonce', 'nonce'); if (!current_user_can('advaipbl_manage_settings')) { wp_send_json_error(['message' => __('Permission denied.', 'advanced-ip-blocker')]); } $user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0; if ($user_id > 0) { $user_to_logout = get_userdata($user_id); WP_Session_Tokens::get_instance($user_id)->destroy_all(); delete_transient('advaipbl_active_sessions_cache'); if ($user_to_logout) { $message = sprintf(/* translators: %s is a placeholder */ __('Sessions for user "%1$s" were closed by %2$s.', 'advanced-ip-blocker'), $user_to_logout->user_login, wp_get_current_user()->user_login); if (isset($this->plugin_instance)) { $this->plugin_instance->log_event($message, 'warning'); } } wp_send_json_success(); } else { wp_send_json_error(['message' => __('Invalid user ID.', 'advanced-ip-blocker')]); } } public function ajax_close_all_user_sessions() { check_ajax_referer('advaipbl_close_all_sessions_nonce', 'nonce'); if (!current_user_can('advaipbl_manage_settings')) { wp_send_json_error(['message' => __('Permission denied.', 'advanced-ip-blocker')]); } foreach (get_users(['fields' => 'ID']) as $user_id) { WP_Session_Tokens::get_instance($user_id)->destroy_all(); } delete_transient('advaipbl_active_sessions_cache'); $message = sprintf(/* translators: %s is a placeholder */ __('All sessions for ALL users were closed by %s.', 'advanced-ip-blocker'), wp_get_current_user()->user_login); if (isset($this->plugin_instance)) { $this->plugin_instance->log_event($message, 'critical'); } wp_send_json_success(); } public function ajax_close_sessions_by_role() { check_ajax_referer('advaipbl_close_sessions_by_role_nonce', 'nonce'); if (!current_user_can('advaipbl_manage_settings')) { wp_send_json_error(['message' => __('Permission denied.', 'advanced-ip-blocker')]); } $role = isset($_POST['role']) ? sanitize_text_field(wp_unslash($_POST['role'])) : ''; if (!empty($role)) { foreach (get_users(['role' => $role, 'fields' => 'ID']) as $user_id) { WP_Session_Tokens::get_instance($user_id)->destroy_all(); } delete_transient('advaipbl_active_sessions_cache'); $message = sprintf(/* translators: %s is a placeholder */ __('All sessions for role "%1$s" were closed by %2$s.', 'advanced-ip-blocker'), $role, wp_get_current_user()->user_login); if (isset($this->plugin_instance)) { $this->plugin_instance->log_event($message, 'warning'); } } wp_send_json_success(); } public function save_settings() { if (!current_user_can('advaipbl_manage_settings') || !check_admin_referer('advaipbl_usm_save_settings_nonce')) { wp_die(esc_html__('Action not allowed.', 'advanced-ip-blocker')); }$per_page = isset($_POST['sessions_per_page']) ? intval(wp_unslash($_POST['sessions_per_page'])) : 10; update_option('advaipbl_usm_sessions_per_page', max(1, min(100, $per_page))); wp_safe_redirect(admin_url('admin.php?page=advaipbl_settings_page&tab=dashboard&sub-tab=user_sessions')); exit; } public function get_active_sessions() { $cache_key = 'advaipbl_active_sessions_cache'; $cached_sessions = get_transient($cache_key); if (false !== $cached_sessions) { return $cached_sessions; } global $wpdb; $sessions = []; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $results = $wpdb->get_results("SELECT user_id, meta_value FROM {$wpdb->usermeta} WHERE meta_key = 'session_tokens'"); foreach ($results as $row) { $tokens = maybe_unserialize($row->meta_value); if (! is_array($tokens)) { continue; } $user = get_userdata($row->user_id); if (! $user) { continue; } $role = implode(', ', $user->roles); foreach ($tokens as $token_data) { if (isset($token_data['expiration']) && $token_data['expiration'] > time()) { $sessions[] = [ 'user_id' => $user->ID, 'username' => $user->user_login, 'email' => $user->user_email, 'role' => $role, 'ip' => $token_data['ip'] ?? __('Unknown', 'advanced-ip-blocker'), 'device' => $token_data['ua'] ?? __('Unknown', 'advanced-ip-blocker'), 'last_activity' => date_i18n('Y-m-d H:i:s', $token_data['login'] ?? time()), ]; } } } set_transient($cache_key, $sessions, 60); return $sessions; } /** * Gets locations for an array of IPs, using our custom cache table. * * @param array $ips An array of IPs to locate. * @return array An associative array of [ip => location_data]. */ public function get_cached_locations($ips) { if (! $this->plugin_instance) { return []; } // La clave de caché ahora es un identificador simple para todo el grupo de localizaciones. $cache_key = ADVAIPBL_USM_LOCATION_CACHE_KEY; $cache = $this->plugin_instance->get_from_custom_cache($cache_key); if (! is_array($cache)) { $cache = []; } $unique_ips = array_unique(array_filter($ips)); $ips_to_fetch = array_filter($unique_ips, function ($ip) use ($cache) { return ! isset($cache[ $ip ]) || ! is_array($cache[ $ip ]); }); if (empty($ips_to_fetch)) { return $cache; } foreach ($ips_to_fetch as $ip) { if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) { $location = $this->geolocation_manager->fetch_location($ip); if (is_array($location)) { $cache[ $ip ] = $location; } } } $ttl = ADVAIPBL_USM_LOCATION_CACHE_TTL; $this->plugin_instance->set_in_custom_cache($cache_key, $cache, $ttl); return $cache; } public function parse_user_agent($ua) { if (empty($ua) || $ua === __('Unknown', 'advanced-ip-blocker')) { return __('Unknown', 'advanced-ip-blocker'); } $os = __('Unknown OS', 'advanced-ip-blocker'); $browser = __('Unknown Browser', 'advanced-ip-blocker'); if (preg_match('/(Windows|Macintosh|Android|iPhone|iPad|Linux)/i', $ua, $matches)) { $os = $matches[1]; } if (preg_match('/(Chrome|Firefox|Safari|Edge|MSIE|Trident)/i', $ua, $matches)) { $browser = $matches[1] == 'Trident' || $matches[1] == 'MSIE' ? 'IE' : $matches[1]; } if ($browser == 'Safari' && preg_match('/Chrome/i', $ua)) { $browser = 'Chrome'; } return sprintf(/* translators: %s is a placeholder */ __('%1$s on %2$s', 'advanced-ip-blocker'), $browser, $os); } }