| Server IP : 80.74.154.100 / Your IP : 216.73.217.0 Web Server : Apache System : Linux marissa.metanet.ch 4.18.0-553.141.2.lve.el7h.x86_64 #1 SMP Wed Jul 8 17:20:31 UTC 2026 x86_64 User : onlineadmin ( 10487) PHP Version : 8.5.7 Disable Function : opcache_get_status MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/httpd/vhosts/comeonline.ch/httpdocs/wp-content/plugins/zero-spam/includes/ |
Upload File : |
<?php
/**
* Plugin CLI Commands
*
* @package ZeroSpam
*/
class ZeroSpamCLI {
/**
* Auto-configure the plugin with recommended settings
*/
public function autoconfigure() {
\ZeroSpam\Core\Settings::auto_configure();
WP_CLI::success( __( 'Zero Spam has been successfully auto-configured using the recommended defaults.', 'zero-spam' ) );
}
/**
* Outputs settings
*/
public function settings() {
$modules = \ZeroSpam\Core\Settings::get_settings_by_module();
$settings = array();
foreach ( $modules as $module => $module_settings ) {
foreach ( $module_settings as $key => $setting ) {
$settings[] = array(
'module' => $module,
'setting' => $key,
'value' => isset( $setting['value'] ) ? $setting['value'] : false,
);
}
}
$fields = array( 'module', 'setting', 'value' );
WP_CLI\Utils\format_items( 'table', $settings, $fields );
}
/**
* Update a plugin setting(s)
*
* @param array $args Positional arguments.
* @param array $assoc_args Array of settings to update.
*/
public function set( $args, $assoc_args ) {
$settings = \ZeroSpam\Core\Settings::get_settings();
if ( $assoc_args ) {
foreach ( $assoc_args as $key => $value ) {
// Handle action-type settings that trigger operations rather than storing values.
if ( 'regenerate_honeypot' === $key ) {
\ZeroSpam\Core\Utilities::get_honeypot( true );
$new_key = \ZeroSpam\Core\Utilities::get_honeypot();
WP_CLI::success( 'Honeypot ID has been regenerated. New ID: ' . $new_key );
continue;
}
if ( 'update_blocked_email_domains' === $key ) {
\ZeroSpam\Core\Settings::update_blocked_email_domains();
WP_CLI::success( 'Blocked email domains have been updated to the recommended list.' );
continue;
}
if ( 'update_disallowed_words' === $key ) {
\ZeroSpam\Core\Settings::update_disallowed_words();
WP_CLI::success( 'WordPress disallowed words list has been updated to the recommended list.' );
continue;
}
if ( ! isset( $settings[ $key ] ) ) {
WP_CLI::error( $key . ' is not a valid setting.' );
} elseif ( \ZeroSpam\Core\Utilities::update_setting( $key, $value ) ) {
WP_CLI::success( '\'' . $key . '\' has been successfully updated to \'' . $value . '\'.' );
} else {
WP_CLI::error( 'There was a problem updating ' . $key . '. See the zerospam.log for more details.' );
}
}
} else {
WP_CLI::error( __( 'Oops! You didn\'t specify a setting to set (ex. wp zerospam set --share_data=enabled).', 'zero-spam' ) );
}
}
/**
* Regenerate the honeypot ID
*
* Generates a new random honeypot field name to prevent bots from
* scripting around the current ID.
*
* ## EXAMPLES
*
* wp zerospam regenerate-honeypot
*
*/
public function regenerate_honeypot() {
\ZeroSpam\Core\Utilities::get_honeypot( true );
$new_key = \ZeroSpam\Core\Utilities::get_honeypot();
WP_CLI::success( 'Honeypot ID has been regenerated. New ID: ' . $new_key );
}
/**
* Update blocked email domains
*
* ## OPTIONS
*
* [--file=<file>]
* : Path to a text file with one domain per line.
*
* [--domains=<domains>]
* : Newline-separated list of domains to set.
*
* [--recommended]
* : Use the recommended blocked email domains from Zero Spam.
*
* [--append]
* : Append to existing domains instead of replacing them.
*
* ## EXAMPLES
*
* # Use recommended domains
* wp zerospam update-blocked-domains --recommended
*
* # Set specific domains
* wp zerospam update-blocked-domains --domains="spam.com\nfake.com"
*
* # Import from file
* wp zerospam update-blocked-domains --file=/path/to/domains.txt
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function update_blocked_domains( $args, $assoc_args ) {
$domains = '';
if ( ! empty( $assoc_args['recommended'] ) ) {
\ZeroSpam\Core\Settings::update_blocked_email_domains();
WP_CLI::success( 'Blocked email domains have been updated to the recommended list.' );
return;
}
if ( ! empty( $assoc_args['file'] ) ) {
$file_path = $assoc_args['file'];
if ( ! file_exists( $file_path ) ) {
WP_CLI::error( 'File not found: ' . $file_path );
}
$domains = file_get_contents( $file_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
if ( false === $domains ) {
WP_CLI::error( 'Could not read file: ' . $file_path );
}
} elseif ( ! empty( $assoc_args['domains'] ) ) {
$domains = $assoc_args['domains'];
} else {
WP_CLI::error( 'Please specify --recommended, --domains, or --file.' );
}
// Normalize newlines.
$domains = str_replace( array( '\n', '\r\n', '\r' ), "\n", $domains );
// Optionally append to existing domains.
if ( ! empty( $assoc_args['append'] ) ) {
$existing = get_option( 'zerospam_blocked_email_domains', '' );
if ( ! empty( $existing ) ) {
$domains = trim( $existing ) . "\n" . trim( $domains );
}
}
// Clean up: trim, remove empties, deduplicate.
$domain_array = array_filter( array_map( 'trim', explode( "\n", $domains ) ) );
$domain_array = array_unique( $domain_array );
$domains = implode( "\n", $domain_array );
if ( update_option( 'zerospam_blocked_email_domains', $domains ) ) {
wp_cache_delete( 'zerospam_blocked_email_domains', 'options' );
global $wpdb;
$wpdb->query(
$wpdb->prepare(
"UPDATE $wpdb->options SET autoload = %s WHERE option_name = %s",
'no',
'zerospam_blocked_email_domains'
)
);
}
WP_CLI::success( 'Blocked email domains updated. Total domains: ' . count( $domain_array ) );
}
/**
* Display API usage statistics
*
* ## OPTIONS
*
* [--period=<period>]
* : Time period: today, yesterday, week, month, all
* ---
* default: today
* options:
* - today
* - yesterday
* - week
* - month
* - all
* ---
*
* [--site=<site_id>]
* : Site ID (multisite only)
*
* [--format=<format>]
* : Output format
* ---
* default: table
* options:
* - table
* - json
* - csv
* - yaml
* ---
*
* [--scope=<scope>]
* : Scope: site or network (multisite only)
* ---
* default: site
* options:
* - site
* - network
* ---
*
* ## EXAMPLES
*
* # Show today's usage
* wp zerospam api_usage
*
* # Show weekly usage in JSON format
* wp zerospam api_usage --period=week --format=json
*
* # Show network-wide usage (multisite)
* wp zerospam api_usage --scope=network
*
* # Export usage data as CSV
* wp zerospam api_usage --format=csv > usage.csv
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function api_usage( $args, $assoc_args ) {
// Check if monitoring is enabled.
if ( ! \ZeroSpam\Includes\API_Usage_Tracker::is_monitoring_enabled() ) {
WP_CLI::error( __( 'API usage monitoring is not enabled. Enable it in Zero Spam settings.', 'zero-spam' ) );
}
$period = isset( $assoc_args['period'] ) ? $assoc_args['period'] : 'today';
$format = isset( $assoc_args['format'] ) ? $assoc_args['format'] : 'table';
$scope = isset( $assoc_args['scope'] ) ? $assoc_args['scope'] : 'site';
$site_id = isset( $assoc_args['site'] ) ? absint( $assoc_args['site'] ) : get_current_blog_id();
// Validate period.
$valid_periods = array( 'today', 'yesterday', 'week', 'month', 'all' );
if ( ! in_array( $period, $valid_periods, true ) ) {
WP_CLI::error( sprintf( 'Invalid period. Must be one of: %s', implode( ', ', $valid_periods ) ) );
}
// Get statistics.
if ( 'network' === $scope && is_multisite() ) {
$stats = \ZeroSpam\Includes\API_Usage_Tracker::get_network_usage_stats( $period );
WP_CLI::log( WP_CLI::colorize( '%BNetwork-wide API Usage Statistics%n' ) );
} else {
$stats = \ZeroSpam\Includes\API_Usage_Tracker::get_usage_stats( $site_id, $period );
WP_CLI::log( WP_CLI::colorize( sprintf( '%%BAPI Usage Statistics (Site %d)%%n', $site_id ) ) );
}
WP_CLI::log( WP_CLI::colorize( sprintf( '%%yPeriod: %s%%n', ucfirst( $period ) ) ) );
WP_CLI::log( '' );
// Format output based on format parameter.
if ( 'table' === $format ) {
$this->display_usage_table( $stats );
// Show anomalies if site-level.
if ( 'site' === $scope ) {
$anomalies = \ZeroSpam\Includes\API_Usage_Tracker::detect_anomalies( $site_id );
if ( ! empty( $anomalies ) ) {
WP_CLI::log( '' );
WP_CLI::log( WP_CLI::colorize( '%R⚠ Anomalies Detected:%n' ) );
foreach ( $anomalies as $anomaly ) {
$icon = 'critical' === $anomaly['severity'] ? '✗' : '⚠';
WP_CLI::log( WP_CLI::colorize( sprintf( ' %%y%s %s%%n', $icon, $anomaly['message'] ) ) );
}
}
}
} else {
// For JSON/CSV/YAML formats.
$output_data = array(
array(
'metric' => 'Total Events',
'value' => $stats['total_events'],
),
array(
'metric' => 'API Calls',
'value' => $stats['api_calls'],
),
array(
'metric' => 'Cache Hits',
'value' => $stats['cache_hits'],
),
array(
'metric' => 'Errors',
'value' => $stats['errors'],
),
array(
'metric' => 'Avg Response Time (ms)',
'value' => round( $stats['avg_response_time'], 2 ),
),
);
if ( $stats['current_limit'] ) {
$output_data[] = array(
'metric' => 'Quota Limit',
'value' => $stats['current_limit'],
);
$output_data[] = array(
'metric' => 'Quota Used',
'value' => $stats['current_made'],
);
$output_data[] = array(
'metric' => 'Quota Remaining',
'value' => $stats['current_remaining'],
);
}
WP_CLI\Utils\format_items( $format, $output_data, array( 'metric', 'value' ) );
}
}
/**
* Display usage statistics in table format
*
* @param array $stats Statistics data.
*/
private function display_usage_table( $stats ) {
// Statistics table.
WP_CLI::log( WP_CLI::colorize( '%BUsage Statistics:%n' ) );
WP_CLI::log( sprintf( ' API Calls: %s', WP_CLI::colorize( '%G' . number_format( $stats['api_calls'] ) . '%n' ) ) );
WP_CLI::log( sprintf( ' Cache Hits: %s', WP_CLI::colorize( '%G' . number_format( $stats['cache_hits'] ) . '%n' ) ) );
WP_CLI::log( sprintf( ' Errors: %s', $stats['errors'] > 0 ? WP_CLI::colorize( '%R' . number_format( $stats['errors'] ) . '%n' ) : '0' ) );
WP_CLI::log( sprintf( ' Total Events: %s', number_format( $stats['total_events'] ) ) );
if ( $stats['avg_response_time'] > 0 ) {
$response_color = $stats['avg_response_time'] > 5000 ? '%R' : ( $stats['avg_response_time'] > 2000 ? '%Y' : '%G' );
WP_CLI::log( sprintf( ' Avg Response Time: %s', WP_CLI::colorize( $response_color . round( $stats['avg_response_time'], 2 ) . 'ms%n' ) ) );
}
// Quota information.
if ( $stats['current_limit'] ) {
WP_CLI::log( '' );
WP_CLI::log( WP_CLI::colorize( '%BAPI Quota:%n' ) );
WP_CLI::log( sprintf( ' Limit: %s', number_format( $stats['current_limit'] ) ) );
WP_CLI::log( sprintf( ' Used: %s', number_format( $stats['current_made'] ) ) );
$remaining_pct = ( $stats['current_remaining'] / $stats['current_limit'] ) * 100;
$remaining_color = $remaining_pct < 10 ? '%R' : ( $remaining_pct < 20 ? '%Y' : '%G' );
WP_CLI::log(
sprintf(
' Remaining: %s (%s)',
WP_CLI::colorize( $remaining_color . number_format( $stats['current_remaining'] ) . '%n' ),
WP_CLI::colorize( $remaining_color . number_format( $remaining_pct, 1 ) . '%%%n' )
)
);
}
// Performance indicators.
$total_requests = $stats['api_calls'] + $stats['cache_hits'];
if ( $total_requests > 0 ) {
$cache_hit_rate = ( $stats['cache_hits'] / $total_requests ) * 100;
$cache_color = $cache_hit_rate >= 70 ? '%G' : ( $cache_hit_rate >= 50 ? '%Y' : '%R' );
WP_CLI::log( '' );
WP_CLI::log( WP_CLI::colorize( '%BPerformance:%n' ) );
WP_CLI::log(
sprintf(
' Cache Efficiency: %s',
WP_CLI::colorize( $cache_color . number_format( $cache_hit_rate, 1 ) . '%%%n' )
)
);
if ( $stats['errors'] > 0 ) {
$error_rate = ( $stats['errors'] / $stats['total_events'] ) * 100;
$error_color = $error_rate >= 10 ? '%R' : ( $error_rate >= 5 ? '%Y' : '%G' );
WP_CLI::log(
sprintf(
' Error Rate: %s',
WP_CLI::colorize( $error_color . number_format( $error_rate, 1 ) . '%%%n' )
)
);
}
}
}
/**
* Display network-wide spam statistics
*
* ## OPTIONS
*
* [--period=<period>]
* : Time period for stats (today, yesterday, week, month). Default: month
*
* [--format=<format>]
* : Output format (table, json, csv, yaml). Default: table
*
* ## EXAMPLES
*
* wp zerospam network_stats
* wp zerospam network_stats --period=week
* wp zerospam network_stats --period=month --format=json
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function network_stats( $args, $assoc_args ) {
if ( ! is_multisite() ) {
WP_CLI::error( 'This command only works on WordPress Multisite installations.' );
}
$period = isset( $assoc_args['period'] ) ? $assoc_args['period'] : 'month';
$format = isset( $assoc_args['format'] ) ? $assoc_args['format'] : 'table';
$stats = \ZeroSpam\Includes\Network_Stats_Tracker::get_network_stats( $period );
if ( 'table' === $format ) {
WP_CLI::log( WP_CLI::colorize( '%B' . strtoupper( $period ) . ' NETWORK STATISTICS%n' ) );
WP_CLI::log( '' );
WP_CLI::log( sprintf( ' Total Spam Blocked: %s', WP_CLI::colorize( '%G' . number_format( $stats['total_spam'] ) . '%n' ) ) );
WP_CLI::log( sprintf( ' Unique IP Addresses: %s', number_format( $stats['unique_ips'] ) ) );
WP_CLI::log( sprintf( ' Spam Types: %s', number_format( $stats['spam_types'] ) ) );
} else {
WP_CLI\Utils\format_items( $format, array( $stats ), array( 'total_spam', 'unique_ips', 'spam_types' ) );
}
}
/**
* Display site rankings by spam count
*
* ## OPTIONS
*
* [--limit=<limit>]
* : Number of sites to display. Default: 10
*
* [--period=<period>]
* : Time period for stats (today, yesterday, week, month). Default: month
*
* [--format=<format>]
* : Output format (table, json, csv, yaml). Default: table
*
* ## EXAMPLES
*
* wp zerospam site_rankings
* wp zerospam site_rankings --limit=20
* wp zerospam site_rankings --period=week --format=csv
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function site_rankings( $args, $assoc_args ) {
if ( ! is_multisite() ) {
WP_CLI::error( 'This command only works on WordPress Multisite installations.' );
}
$limit = isset( $assoc_args['limit'] ) ? absint( $assoc_args['limit'] ) : 10;
$period = isset( $assoc_args['period'] ) ? $assoc_args['period'] : 'month';
$format = isset( $assoc_args['format'] ) ? $assoc_args['format'] : 'table';
$sites = \ZeroSpam\Includes\Network_Stats_Tracker::get_site_breakdown( $period, $limit, 'spam_count' );
if ( empty( $sites ) ) {
WP_CLI::warning( 'No site data available for the selected period.' );
return;
}
if ( 'table' === $format ) {
WP_CLI::log( WP_CLI::colorize( '%BTOP ' . $limit . ' SITES BY SPAM COUNT%n' ) );
WP_CLI::log( '' );
$table_data = array();
foreach ( $sites as $index => $site ) {
$table_data[] = array(
'rank' => $index + 1,
'site' => $site['site_name'],
'spam' => number_format( $site['spam_count'] ),
'unique_ips' => number_format( $site['unique_ips'] ),
'protection' => $site['has_enhanced'] ? 'Enhanced' : 'Free',
);
}
WP_CLI\Utils\format_items( 'table', $table_data, array( 'rank', 'site', 'spam', 'unique_ips', 'protection' ) );
} else {
WP_CLI\Utils\format_items( $format, $sites, array( 'site_name', 'spam_count', 'unique_ips', 'has_enhanced' ) );
}
}
/**
* Display IPs attacking multiple sites
*
* ## OPTIONS
*
* [--min-sites=<min-sites>]
* : Minimum number of sites attacked. Default: 2
*
* [--days=<days>]
* : Days to look back. Default: 7
*
* [--format=<format>]
* : Output format (table, json, csv, yaml). Default: table
*
* ## EXAMPLES
*
* wp zerospam multi_site_attackers
* wp zerospam multi_site_attackers --min-sites=3
* wp zerospam multi_site_attackers --days=14 --format=json
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function multi_site_attackers( $args, $assoc_args ) {
if ( ! is_multisite() ) {
WP_CLI::error( 'This command only works on WordPress Multisite installations.' );
}
$min_sites = isset( $assoc_args['min-sites'] ) ? absint( $assoc_args['min-sites'] ) : 2;
$days = isset( $assoc_args['days'] ) ? absint( $assoc_args['days'] ) : 7;
$format = isset( $assoc_args['format'] ) ? $assoc_args['format'] : 'table';
$attackers = \ZeroSpam\Includes\Network_Stats_Tracker::get_multi_site_attackers( $min_sites, $days );
if ( empty( $attackers ) ) {
WP_CLI::success( 'No multi-site attackers found.' );
return;
}
WP_CLI::log( WP_CLI::colorize( '%RMULTI-SITE ATTACKERS%n' ) );
WP_CLI::log( sprintf( 'Found %s IP(s) attacking %d+ sites in last %d days', WP_CLI::colorize( '%R' . count( $attackers ) . '%n' ), $min_sites, $days ) );
WP_CLI::log( '' );
WP_CLI\Utils\format_items( $format, $attackers, array( 'user_ip', 'country_name', 'attack_count' ) );
}
/**
* Backfill daily aggregation data
*
* ## OPTIONS
*
* [--days=<days>]
* : Number of days to backfill. Default: 30
*
* ## EXAMPLES
*
* wp zerospam backfill_stats
* wp zerospam backfill_stats --days=60
*
* @param array $args Positional arguments.
* @param array $assoc_args Associative arguments.
*/
public function backfill_stats( $args, $assoc_args ) {
if ( ! is_multisite() ) {
WP_CLI::error( 'This command only works on WordPress Multisite installations.' );
}
$days = isset( $assoc_args['days'] ) ? absint( $assoc_args['days'] ) : 30;
WP_CLI::log( WP_CLI::colorize( "%BBackfilling daily statistics for last {$days} days...%n" ) );
\ZeroSpam\Includes\Stats_Aggregator::backfill_daily( $days );
WP_CLI::success( "Daily stats backfilled for {$days} days." );
// Also backfill monthly.
$months = ceil( $days / 30 );
WP_CLI::log( WP_CLI::colorize( "%BBackfilling monthly statistics for last {$months} months...%n" ) );
\ZeroSpam\Includes\Stats_Aggregator::backfill_monthly( $months );
WP_CLI::success( "Monthly stats backfilled for {$months} months." );
}
}
// Register network settings commands (multisite only).
if ( is_multisite() && class_exists( '\ZeroSpam\Includes\CLI\Network_Settings_CLI' ) ) {
$network_settings_cli = new \ZeroSpam\Includes\CLI\Network_Settings_CLI();
WP_CLI::add_command( 'zerospam network-settings list', array( $network_settings_cli, 'list_settings' ) );
WP_CLI::add_command( 'zerospam network-settings show', array( $network_settings_cli, 'show' ) );
WP_CLI::add_command( 'zerospam network-settings set', array( $network_settings_cli, 'set' ) );
WP_CLI::add_command( 'zerospam network-settings lock', array( $network_settings_cli, 'lock' ) );
WP_CLI::add_command( 'zerospam network-settings unlock', array( $network_settings_cli, 'unlock' ) );
WP_CLI::add_command( 'zerospam network-settings apply-all', array( $network_settings_cli, 'apply_all' ) );
WP_CLI::add_command( 'zerospam network-settings reset', array( $network_settings_cli, 'reset_site' ) );
WP_CLI::add_command( 'zerospam network-settings status', array( $network_settings_cli, 'status' ) );
WP_CLI::add_command( 'zerospam network-settings compare', array( $network_settings_cli, 'compare' ) );
WP_CLI::add_command( 'zerospam network-settings overrides', array( $network_settings_cli, 'overrides' ) );
WP_CLI::add_command( 'zerospam network-settings export', array( $network_settings_cli, 'export' ) );
WP_CLI::add_command( 'zerospam network-settings import', array( $network_settings_cli, 'import' ) );
WP_CLI::add_command( 'zerospam network-settings audit', array( $network_settings_cli, 'audit' ) );
WP_CLI::add_command( 'zerospam network-settings template-list', array( $network_settings_cli, 'template_list' ) );
WP_CLI::add_command( 'zerospam network-settings template-apply', array( $network_settings_cli, 'template_apply' ) );
WP_CLI::add_command( 'zerospam network-settings template-create', array( $network_settings_cli, 'template_create' ) );
WP_CLI::add_command( 'zerospam network-settings template-delete', array( $network_settings_cli, 'template_delete' ) );
}
WP_CLI::add_command( 'zerospam', 'ZeroSpamCLI' );
// Register standalone convenience commands.
$zerospam_cli = new ZeroSpamCLI();
WP_CLI::add_command( 'zerospam regenerate-honeypot', array( $zerospam_cli, 'regenerate_honeypot' ) );
WP_CLI::add_command( 'zerospam update-blocked-domains', array( $zerospam_cli, 'update_blocked_domains' ) );