Upload via GUI (30 Dateien)
This commit is contained in:
+126
-19
@@ -62,7 +62,8 @@ function wp_multi_track_user_activity($user_id, $action, $post_id = null) {
|
||||
$post_id = get_the_ID();
|
||||
}
|
||||
|
||||
if (!$user_id || !$action) {
|
||||
// user_id 0 ist gewollt: Die Seite bietet keinen Login, Aufrufe sind anonym.
|
||||
if (!$action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -92,26 +93,93 @@ function wp_multi_comment_activity($comment_id) {
|
||||
add_action('comment_post', 'wp_multi_comment_activity');
|
||||
|
||||
/**
|
||||
* Verfolgt Beitragsaufrufe.
|
||||
* Erkennt Bots und Crawler anhand des User-Agents.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function wp_multi_is_bot_request() {
|
||||
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower(sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT']))) : '';
|
||||
|
||||
// Ohne User-Agent ist es so gut wie nie ein echter Besucher
|
||||
if ($user_agent === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$signatures = apply_filters('wp_multi_bot_signatures', [
|
||||
'bot', 'crawl', 'spider', 'slurp', 'archiver', 'preview', 'monitor', 'validator',
|
||||
'facebookexternalhit', 'headless', 'phantomjs', 'python', 'curl', 'wget', 'go-http',
|
||||
'java/', 'okhttp', 'axios', 'scrapy', 'lighthouse', 'pingdom', 'uptime',
|
||||
]);
|
||||
|
||||
foreach ($signatures as $signature) {
|
||||
if (strpos($user_agent, $signature) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob dieser Besucher den Beitrag gerade erst aufgerufen hat.
|
||||
*
|
||||
* Ohne Login gibt es keine Benutzer-ID, deshalb dient ein kurzlebiger Hash aus
|
||||
* IP und User-Agent als Erkennungsmerkmal. Gespeichert wird nur der Hash, nie
|
||||
* die IP selbst – ein Reload zählt damit nicht mehrfach.
|
||||
*
|
||||
* @param int $post_id Beitrag-ID.
|
||||
* @return bool True, wenn der Aufruf bereits gezählt wurde.
|
||||
*/
|
||||
function wp_multi_view_already_counted($post_id) {
|
||||
$ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
|
||||
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '';
|
||||
|
||||
$key = 'wp_multi_view_' . md5($post_id . '|' . $ip . '|' . $user_agent . '|' . wp_salt());
|
||||
|
||||
if (get_transient($key)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sperrfrist je Besucher und Beitrag
|
||||
$ttl = (int) apply_filters('wp_multi_view_throttle', 30 * MINUTE_IN_SECONDS);
|
||||
set_transient($key, 1, $ttl);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verfolgt Beitragsaufrufe – auch von nicht eingeloggten Besuchern.
|
||||
*/
|
||||
function wp_multi_post_view_activity() {
|
||||
if (is_single() && is_user_logged_in()) {
|
||||
$user_id = get_current_user_id();
|
||||
$post_id = get_the_ID();
|
||||
wp_multi_track_user_activity($user_id, 'view', $post_id);
|
||||
if (is_admin() || !is_single() || is_feed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Eigene Aufrufe der Redaktion verfälschen die Zahlen
|
||||
if (is_user_logged_in() && current_user_can('edit_posts') && !apply_filters('wp_multi_track_editor_views', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wp_multi_is_bot_request()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = get_the_ID();
|
||||
if (!$post_id || wp_multi_view_already_counted($post_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ohne Login ist die Benutzer-ID 0 – der Aufruf zählt trotzdem
|
||||
wp_multi_track_user_activity(get_current_user_id(), 'view', $post_id);
|
||||
}
|
||||
add_action('wp_head', 'wp_multi_post_view_activity');
|
||||
|
||||
/**
|
||||
* Ruft rohe Analytics-Daten aus der Datenbank ab.
|
||||
* Baut die WHERE-Bedingung für den gewählten Zeitraum.
|
||||
*
|
||||
* @param string $date_query Datum für die Abfrage.
|
||||
* @return array Rohe Analytics-Daten.
|
||||
* @return array [WHERE-Fragment, Parameter]
|
||||
*/
|
||||
function wp_multi_fetch_raw_analytics($start_datetime = null, $end_datetime = null) {
|
||||
global $wpdb;
|
||||
|
||||
function wp_multi_analytics_date_where($start_datetime = null, $end_datetime = null) {
|
||||
if (!$start_datetime) {
|
||||
$start_datetime = gmdate('Y-m-d H:i:s', strtotime('-7 days'));
|
||||
}
|
||||
@@ -124,22 +192,60 @@ function wp_multi_fetch_raw_analytics($start_datetime = null, $end_datetime = nu
|
||||
$params[] = $end_datetime;
|
||||
}
|
||||
|
||||
$sql = "SELECT DATE(timestamp) AS date, action, post_id, COUNT(*) AS count, user_id, timestamp
|
||||
return [$where, $params];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruft die Tagessummen je Aktion ab – Grundlage für das Diagramm.
|
||||
*
|
||||
* Aggregiert in der Datenbank statt in PHP: Seit auch anonyme Aufrufe gezählt
|
||||
* werden, kämen hier sonst zehntausende Einzelzeilen an.
|
||||
*
|
||||
* @return array Zeilen mit date, action und count.
|
||||
*/
|
||||
function wp_multi_fetch_analytics_totals($start_datetime = null, $end_datetime = null) {
|
||||
global $wpdb;
|
||||
|
||||
list($where, $params) = wp_multi_analytics_date_where($start_datetime, $end_datetime);
|
||||
|
||||
$sql = "SELECT DATE(timestamp) AS date, action, COUNT(*) AS count
|
||||
FROM " . WP_MULTI_ANALYTICS_TABLE . "
|
||||
$where
|
||||
GROUP BY date, action, post_id, user_id, timestamp
|
||||
GROUP BY date, action
|
||||
ORDER BY date ASC";
|
||||
|
||||
return $wpdb->get_results($wpdb->prepare($sql, $params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruft die jüngsten Einzelereignisse ab – Grundlage für die Detailtabelle.
|
||||
*
|
||||
* @return array Rohe Analytics-Daten (begrenzt).
|
||||
*/
|
||||
function wp_multi_fetch_raw_analytics($start_datetime = null, $end_datetime = null) {
|
||||
global $wpdb;
|
||||
|
||||
list($where, $params) = wp_multi_analytics_date_where($start_datetime, $end_datetime);
|
||||
|
||||
// Ohne Limit würde die Detailtabelle bei anonymem Tracking die Seite sprengen
|
||||
$params[] = (int) apply_filters('wp_multi_analytics_detail_limit', 200);
|
||||
|
||||
$sql = "SELECT DATE(timestamp) AS date, action, post_id, 1 AS count, user_id, timestamp
|
||||
FROM " . WP_MULTI_ANALYTICS_TABLE . "
|
||||
$where
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT %d";
|
||||
|
||||
return $wpdb->get_results($wpdb->prepare($sql, $params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verarbeitet rohe Analytics-Daten für Diagramm und Tabelle.
|
||||
*
|
||||
* @param array $results Rohe Analytics-Daten.
|
||||
* @return array Verarbeitete Daten.
|
||||
*/
|
||||
function wp_multi_process_analytics_data($results) {
|
||||
function wp_multi_process_analytics_data($results, $recent = null) {
|
||||
$dates = [];
|
||||
$comment_counts = [];
|
||||
$view_counts = [];
|
||||
@@ -184,7 +290,7 @@ function wp_multi_process_analytics_data($results) {
|
||||
'fill' => false,
|
||||
]
|
||||
],
|
||||
'data' => $results
|
||||
'data' => ($recent === null) ? $results : $recent
|
||||
];
|
||||
}
|
||||
|
||||
@@ -202,8 +308,9 @@ function wp_multi_get_analytics_data($start_datetime = null, $end_datetime = nul
|
||||
return $cached_data;
|
||||
}
|
||||
|
||||
$results = wp_multi_fetch_raw_analytics($start_datetime, $end_datetime);
|
||||
$data = wp_multi_process_analytics_data($results);
|
||||
$totals = wp_multi_fetch_analytics_totals($start_datetime, $end_datetime);
|
||||
$recent = wp_multi_fetch_raw_analytics($start_datetime, $end_datetime);
|
||||
$data = wp_multi_process_analytics_data($totals, $recent);
|
||||
|
||||
set_transient($cache_key, $data, HOUR_IN_SECONDS);
|
||||
return $data;
|
||||
@@ -308,7 +415,7 @@ function wp_multi_display_user_analytics() {
|
||||
<tbody>
|
||||
<?php foreach ($results['data'] as $row) : ?>
|
||||
<tr>
|
||||
<td><?php echo esc_html($row->user_id); ?></td>
|
||||
<td><?php echo $row->user_id ? esc_html($row->user_id) : esc_html__('Gast', 'wp-multi'); ?></td>
|
||||
<td><span class="wpm-badge <?php echo $row->action === 'comment' ? 'wpm-badge--success' : ''; ?>"><?php echo esc_html($row->action); ?></span></td>
|
||||
<td>
|
||||
<?php
|
||||
|
||||
+1815
-93
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user