' . __('No data to display', 'wp-slimstat') . '

'; return 0; } // Return the results if we are not echoing them (export, email, etc) if (isset($_args['echo']) && false === $_args['echo']) { // Process the data before returning it if ('on' == wp_slimstat::$settings['convert_ip_addresses']) { for ($i = 0; $i < $count_page_results; $i++) { // When the IP conversion feature is enabled, we need to return the correct values $hostname = wp_slimstat::gethostbyaddr($results[$i]['ip']); if ($hostname != $results[$i]['ip']) { $results[$i]['ip'] .= ', ' . $hostname; } } } return $results; } // Show delete button? (only those who can access the settings can see it) $current_user_can_delete = (current_user_can(wp_slimstat::$settings['capability_can_admin']) && !is_network_admin()); $delete_row = ''; // #281: inline color-code legend on the full Access Log view. Previously only // available in the report header tooltip; hidden in the compact dashboard widget. // Reuses the existing little-color-box / is-* classes (styled in admin.css). if (!$is_dashboard) { // Each swatch is grouped with its label (and a hover tooltip) so the // colour → meaning mapping is unambiguous — the swatch sits right next to // the word it explains, instead of stranding apart from it. (#impeccable) echo '

' . ' ' . esc_html__('From search result page', 'wp-slimstat') . '' . ' ' . esc_html__('Has Left Comments', 'wp-slimstat') . '' . ' ' . esc_html__('WP User', 'wp-slimstat') . '' . ' ' . esc_html__('Other Human', 'wp-slimstat') . '' . ' ' . esc_html__('Bot or Crawler', 'wp-slimstat') . '' . '

'; } // Loop through the results for ($i = 0; $i < $count_page_results; $i++) { $date_time = " " . date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $results[$i]['dt'], true); // Print visit header? if (0 == $i || $results[$i - 1]['visit_id'] != $results[$i]['visit_id'] || $results[$i - 1]['ip'] != $results[$i]['ip'] || $results[$i - 1]['browser'] != $results[$i]['browser'] || $results[$i - 1]['platform'] != $results[$i]['platform'] || $results[$i - 1]['username'] != $results[$i]['username'] || (!empty($results[$i]['fingerprint']) && ($results[$i - 1]['fingerprint'] ?? '') != $results[$i]['fingerprint'])) { // Color-coded headers $sek = isset($results[$i]['referer']) ? wp_slimstat::get_lossy_url(parse_url($results[$i]['referer'], PHP_URL_HOST)) : ''; $highlight_row = empty($search_engines[$sek]) ? (1 != $results[$i]['browser_type'] ? ' is-direct' : '') : (' is-search-engine'); // Country if (!empty($results[$i]['country']) && 'xx' != $results[$i]['country']) { $country_filter = ""; } else { $country_filter = ""; } // City, if tracked $city_filter = ''; if (!empty($results[$i]['city'])) { $city_filter = "" . esc_html($results[$i]['city']) . ""; } // Browser if (empty($results[$i]['browser_version'])) { $results[$i]['browser_version'] = ''; } $browser_title = ('on' != wp_slimstat::$settings['show_complete_user_agent_tooltip']) ? sprintf('%s %s', $results[ $i ][ 'browser' ], $results[ $i ][ 'browser_version' ]) : $results[$i]['user_agent']; $browser_filter = 'default-browser'; if (!empty($results[$i]['browser']) && in_array($results[$i]['browser'], $supported_browser_icons)) { $browser_filter = sanitize_title($results[$i]['browser']); } $browser_filter = ""; // Operating System $platform_filter = 'unknown'; if (!empty($results[$i]['platform']) && in_array($results[$i]['platform'], $supported_os_icons)) { $platform_filter = esc_attr($results[$i]['platform']); } $platform_filter = ""; // Language $language_filter = ''; // if ( !empty( $results[ $i ][ 'language' ] ) && $results[ $i ][ 'language' ] != 'xx' ) { // $language_filter = '' . wp_slimstat_i18n::get_string( 'l-' . $results[ $i ][ 'language' ] ) . ''; // } // Browser Type $browser_type_filter = ''; if (0 != $results[$i]['browser_type']) { $browser_type_filter = "", $plugin_url, $results[ $i ][ 'browser_type' ], $supported_browser_types[ $results[ $i ][ 'browser_type' ] ]); } // IP Address and user $host_by_ip = $results[$i]['ip']; if ('on' == wp_slimstat::$settings['convert_ip_addresses']) { // When the IP conversion feature is enabled, we need to return the correct values $host_by_ip = wp_slimstat::gethostbyaddr($results[$i]['ip']); } if (empty($results[$i]['username'])) { $ip_address = "" . esc_html($host_by_ip) . ""; } else { // Resolve the WP user once and reuse it for the display name, avatar, // and the profile-edit pencil (avoids a second get_user_by() lookup // per row when show_display_name is on). $user = get_user_by('login', $results[$i]['username']); $display_user_name = $results[$i]['username']; if ($user && 'on' == wp_slimstat::$settings['show_display_name'] && false !== strpos($results[$i]['notes'], 'user:')) { $display_user_name = $user->display_name; } $ip_address = ""; if ($user) { $ip_address .= get_avatar($user->ID, 16); } else { $ip_address .= get_avatar($results[$i]['username'], 16); } $ip_address .= ' ' . esc_html($display_user_name) . ''; // #273: the Access Log author cell links to the user's admin profile, // capability-guarded (get_edit_profile_link() returns '' when the // current user can't edit this user). Only for resolved WP users — // never guests/unknown logins. raw_results_to_html() already does this // for the standard reports table; the Access Log renders here instead. if ($user) { $ip_address .= wp_slimstat_reports::get_edit_profile_link($user->ID); } $display_ip_value = $results[$i]['ip']; if ('on' == (wp_slimstat::$settings['hash_ip'] ?? 'off')) { $display_ip_value = substr($results[$i]['ip'], 0, 12) . '…'; } elseif ('on' == wp_slimstat::$settings['anonymize_ip']) { // already masked in storage; still truncate for UI clarity $display_ip_value = $results[$i]['ip']; } $ip_address .= " (%s)", esc_html($display_ip_value)); $highlight_row = (false !== strpos($results[$i]['notes'], 'user:')) ? ' is-known-user' : ' is-known-visitor'; } $whois_pin = ''; if (is_admin() && !empty(wp_slimstat::$settings['ip_lookup_service']) && !wp_slimstat::is_local_ip_address($results[$i]['ip'])) { $whois_pin = ""; } // Originating IP Address $other_ip_address = ''; if (!empty($results[$i]['other_ip'])) { $other_ip_address = "( " . __('Originating IP', 'wp-slimstat') . ': ' . esc_html($results[$i]['other_ip']) . ")"; } // Screen Resolution $screen_resolution = ''; if (!empty($results[$i]['screen_width']) && !empty($results[$i]['screen_height'])) { $screen_resolution = sprintf("%sx%s", $results[ $i ][ 'screen_width' ], $results[ $i ][ 'screen_height' ]); } // Fingerprint $fingerprint = ''; if (!$is_dashboard && !empty($results[$i]['fingerprint'])) { $fingerprint = "" . esc_html(substr($results[$i]['fingerprint'], 0, 8)) . ''; } $row_output = sprintf("

%s %s %s %s %s %s %s %s %s %s %s

", $highlight_row, $browser_filter, $platform_filter, $browser_type_filter, $country_filter, $whois_pin, $city_filter, $ip_address, $other_ip_address, $fingerprint, $screen_resolution, $language_filter); // Strip all the filter links, if this information is shown on the frontend if (!is_admin()) { $row_output = preg_replace('/(.*?)<\/a>/', '\\2', $row_output); } echo $row_output; } // Permalink: find post title, if available if (!empty($results[$i]['resource'])) { if (isset($results[$i]['blog_id'])) { $results[$i]['resource'] = get_site_url($results[$i]['blog_id']) . $results[$i]['resource']; $resource_title = $results[$i]['resource']; } else { $resource_title = wp_slimstat_reports::get_resource_title($results[$i]['resource']); } $results[$i]['resource'] = rawurldecode($results[$i]['resource']); $results[$i]['resource'] = " " . esc_html($resource_title) . ''; } else { if (!empty($results[$i]['notes'])) { $exploded_notes = explode('][', substr($results[$i]['notes'], 1, -1)); foreach ($exploded_notes as $a_note) { if (false !== strpos($a_note, 'results:')) { $search_terms_info = $results[$i]['searchterms'] . ' (' . $a_note . ')'; break; } } } $results[$i]['resource'] = __('Local search results page', 'wp-slimstat'); } // Defensive: ensure 'searchterms' and 'referer' keys exist to avoid undefined index if (!isset($results[$i]['searchterms'])) { $results[$i]['searchterms'] = ''; } if (!isset($results[$i]['referer'])) { $results[$i]['referer'] = ''; } if (empty($search_terms_info)) { $search_terms_info = wp_slimstat_reports::get_search_terms_info($results[$i]['searchterms'], $results[$i]['referer']); } // Search Terms, with link to original SERP, and Outbound Resource if (!empty($search_terms_info)) { $results[$i]['searchterms'] = " " . $search_terms_info); } else { $results[$i]['searchterms'] = ''; } // Let's reset this variable for the next item $search_terms_info = ''; // Server Latency and Page Speed $performance = ''; if (!$is_dashboard && (!empty($results[$i]['server_latency']) || !empty($results[$i]['page_performance']))) { $performance = " " . __('SL', 'wp-slimstat') . sprintf(': %s / ', $results[$i]['server_latency']) . __('PS', 'wp-slimstat') . (': ' . $results[$i]['page_performance']); } // Time on page $time_on_page = ''; if (!$is_dashboard && !empty($results[$i]['dt_out'])) { $duration = $results[$i]['dt_out'] - $results[$i]['dt']; $time_on_page = " " . date(($duration > 3599 ? 'H:i:s' : 'i:s'), $duration); } // Pageview Notes $notes = ''; if (is_admin() && !empty($results[$i]['notes'])) { $notes = esc_html($results[$i]['notes']); $notes = str_replace(['][', ':', '[', ']'], ['
', ': ', '', ''], $notes); $notes = sprintf("%s", $notes); } // Avoid XSS attacks through the referer URL if ($results[$i]['referer']) { $results[$i]['referer'] = str_replace(['<', '>', '%22', '%27', "'", '"', '%3C', '%3E'], ['<', '>', '', '', '', '', '<', '>'], urldecode($results[$i]['referer'])); } $login_logout = ''; if (!$is_dashboard) { $domain = parse_url($results[$i]['referer'] ?: ''); $domain = empty($domain['host']) ? __('Invalid Referrer', 'wp-slimstat') : $domain['host']; $results[$i]['referer'] = (!empty($results[$i]['referer']) && empty($results[$i]['searchterms'])) ? " %s", esc_url($results[$i]['referer']), esc_html($domain)) : ''; $results[$i]['content_type'] = empty($results[$i]['content_type']) ? '' : " %s ", esc_html($results[$i]['content_type'])); // The Outbound Links field might contain more than one link if (!empty($results[$i]['outbound_resource'])) { if ('#' !== substr($results[$i]['outbound_resource'], 0, 1)) { $results[$i]['outbound_resource'] = " %s", esc_url($results[ $i ][ 'outbound_resource' ]), esc_html($results[ $i ][ 'outbound_resource' ])); } else { $results[$i]['outbound_resource'] = " " . esc_html($results[ $i ][ 'outbound_resource' ]); } } else { $results[$i]['outbound_resource'] = ''; } if ($current_user_can_delete) { $delete_row = sprintf(""; } // Login / Logout Event $login_logout = ''; // Notes are stored bracket-delimited ([loggedin:user][...]); older rows may // use ';'. Split on either delimiter, strip the surrounding [ ], and keep // everything after the tag so usernames containing ':' still render cleanly. if ($results[$i]['notes'] && (false !== strpos($results[$i]['notes'], 'loggedin:') || false !== strpos($results[$i]['notes'], 'loggedout:'))) { $exploded_notes = preg_split('/\]\[|;/', trim($results[$i]['notes'], '[]')); foreach ($exploded_notes as $a_note) { if (0 === strpos($a_note, 'loggedin:')) { $login_logout .= " " . esc_html(substr($a_note, strlen('loggedin:'))); } elseif (0 === strpos($a_note, 'loggedout:')) { $login_logout .= " " . esc_html(substr($a_note, strlen('loggedout:'))); } } } } else { $results[$i]['referer'] = $results[$i]['outbound_resource'] = $results[$i]['content_type'] = ''; } $row_output = sprintf("

%s %s %s %s %s %s %s %s %s %s %s

", $results[$i]['resource'], $time_on_page, $login_logout, $results[$i]['searchterms'], $results[$i]['referer'], $results[$i]['outbound_resource'], $results[$i]['content_type'], $performance, $date_time, $notes, $delete_row); // Strip all the filter links, if this information is shown on the frontend if (!is_admin()) { $row_output = preg_replace('/(.*?)<\/a>/', '\\2', $row_output); } echo $row_output; } if (! defined('DOING_AJAX') || ! DOING_AJAX) { echo ''; } // Pagination echo wp_slimstat_reports::report_pagination($count_page_results, $count_all_results, !$is_dashboard, wp_slimstat::$settings['number_results_raw_data']); if (! defined('DOING_AJAX') || ! DOING_AJAX) { echo '
'; }