Files
argus-wp-defence/includes/class-argus-events.php
T
root df0f2fccb8 ARGUS WordPress Defence 1.0.0 — first production release
Automatic WordPress security: local firewall, malware and file-integrity
scanning, vulnerability protection, quarantine, scheduled backups, an
optional page cache, and automatic global threat intelligence.

See README.md for installation, update, and uninstall instructions.
2026-08-09 13:40:16 +00:00

156 lines
4.3 KiB
PHP

<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Argus_Events {
const DEFAULT_MAX_ROWS = 50000;
public static function record( $type, $severity, $summary, array $payload = array(), $ip = null ) {
global $wpdb;
$wpdb->insert(
Argus_DB::table( 'events' ),
array(
'event_type' => $type,
'severity' => $severity,
'ip' => $ip,
'summary' => $summary,
'payload' => wp_json_encode( $payload ),
'created_at' => current_time( 'mysql', true ),
),
array( '%s', '%s', '%s', '%s', '%s', '%s' )
);
return (int) $wpdb->insert_id;
}
public static function recent( $limit = 50, $type = null ) {
global $wpdb;
$table = Argus_DB::table( 'events' );
if ( $type ) {
$rows = $wpdb->get_results(
$wpdb->prepare( "SELECT * FROM {$table} WHERE event_type = %s ORDER BY created_at DESC LIMIT %d", $type, $limit ) // phpcs:ignore
);
} else {
$rows = $wpdb->get_results(
$wpdb->prepare( "SELECT * FROM {$table} ORDER BY created_at DESC LIMIT %d", $limit ) // phpcs:ignore
);
}
foreach ( $rows as &$row ) {
$row->payload = json_decode( $row->payload, true );
}
return $rows;
}
public static function counts_since( $since_mysql ) {
global $wpdb;
$table = Argus_DB::table( 'events' );
return $wpdb->get_results(
$wpdb->prepare(
"SELECT event_type, severity, COUNT(*) AS cnt FROM {$table} WHERE created_at >= %s GROUP BY event_type, severity", // phpcs:ignore
$since_mysql
)
);
}
const PER_PAGE = 10;
public static function paginated( $page = 1, array $filters = array(), $per_page = self::PER_PAGE ) {
global $wpdb;
$table = Argus_DB::table( 'events' );
$page = max( 1, (int) $page );
$offset = ( $page - 1 ) * $per_page;
$where = array( '1=1' );
$args = array();
if ( ! empty( $filters['search'] ) ) {
$where[] = 'summary LIKE %s';
$args[] = '%' . $wpdb->esc_like( $filters['search'] ) . '%';
}
if ( ! empty( $filters['severity'] ) ) {
$where[] = 'severity = %s';
$args[] = $filters['severity'];
}
if ( ! empty( $filters['type'] ) ) {
$where[] = 'event_type = %s';
$args[] = $filters['type'];
}
if ( ! empty( $filters['since'] ) ) {
$where[] = 'created_at >= %s';
$args[] = $filters['since'];
}
$where_sql = implode( ' AND ', $where );
$count_sql = "SELECT COUNT(*) FROM {$table} WHERE {$where_sql}"; // phpcs:ignore
$total = (int) ( $args ? $wpdb->get_var( $wpdb->prepare( $count_sql, $args ) ) : $wpdb->get_var( $count_sql ) ); // phpcs:ignore
$list_sql = "SELECT * FROM {$table} WHERE {$where_sql} ORDER BY created_at DESC LIMIT %d OFFSET %d"; // phpcs:ignore
$list_args = array_merge( $args, array( $per_page, $offset ) );
$rows = $wpdb->get_results( $wpdb->prepare( $list_sql, $list_args ) ); // phpcs:ignore
foreach ( $rows as &$row ) {
$row->payload = json_decode( $row->payload, true );
}
return array(
'rows' => $rows,
'total' => $total,
'total_pages' => max( 1, (int) ceil( $total / $per_page ) ),
'page' => $page,
);
}
public static function distinct_types() {
global $wpdb;
$table = Argus_DB::table( 'events' );
return $wpdb->get_col( "SELECT DISTINCT event_type FROM {$table} ORDER BY event_type ASC" ); // phpcs:ignore
}
const RETENTION_DAYS_BY_SEVERITY = array(
'info' => 30,
'low' => 90,
'medium' => 365,
'high' => 365,
'critical' => 365,
);
public static function prune() {
global $wpdb;
$table = Argus_DB::table( 'events' );
$retention = apply_filters( 'argus_wpd_event_retention_days', self::RETENTION_DAYS_BY_SEVERITY );
$deleted = 0;
foreach ( $retention as $severity => $days ) {
$cutoff = gmdate( 'Y-m-d H:i:s', time() - ( (int) $days * DAY_IN_SECONDS ) );
$deleted += (int) $wpdb->query(
$wpdb->prepare( "DELETE FROM {$table} WHERE severity = %s AND created_at < %s", $severity, $cutoff ) // phpcs:ignore
);
}
$max_rows = (int) apply_filters( 'argus_wpd_max_event_rows', self::DEFAULT_MAX_ROWS );
$total = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" ); // phpcs:ignore
if ( $total <= $max_rows ) {
return $deleted;
}
$overflow = $total - $max_rows;
$deleted += (int) $wpdb->query(
$wpdb->prepare(
"DELETE FROM {$table} ORDER BY created_at ASC LIMIT %d", // phpcs:ignore
$overflow
)
);
return $deleted;
}
}