` * * Handy for hosts where WP-Cron is unreliable — point a real cron at: * wp sentrixa-analytics rollup * wp sentrixa-analytics geoip-update */ if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) { return; } class SXANL_CLI { /** * Rebuild today's and yesterday's summaries, then prune old raw data. */ public function rollup( $args, $assoc ) { SXANL_Rollup::run(); WP_CLI::success( 'Rollup complete. Last: ' . get_option( 'sxanl_last_rollup', '—' ) ); } /** * Rebuild summaries for an explicit date. * * ## OPTIONS * * : Y-m-d */ public function rebuild( $args ) { $day = isset( $args[0] ) ? $args[0] : sxanl_site_date(); SXANL_Rollup::rebuild_day( $day ); WP_CLI::success( "Rebuilt $day." ); } /** * Download + install the latest DB-IP country database. * * ## OPTIONS * [--force] * : Re-install even if the version already matches. * * @subcommand geoip-update */ public function geoip_update( $args, $assoc ) { $result = SXANL_GeoIP_Updater::update( isset( $assoc['force'] ) ); WP_CLI::log( $result ); if ( 0 === strpos( $result, 'updated' ) ) { WP_CLI::success( $result ); } else { WP_CLI::warning( $result ); } } /** * Build the packed GeoIP binary from a local CSV.gz (for packaging). * * ## OPTIONS * * : Path to dbip-country-lite-YYYY-MM.csv.gz * * : File name for the packed .dat (written inside uploads/sentrixa-analytics/) * * @subcommand geoip-build */ public function geoip_build( $args ) { list( $src, $dest ) = array( $args[0], $args[1] ); $packed = SXANL_GeoIP_Updater::build_from_csv_gz( $src ); if ( ! is_string( $packed ) || 'SXAG' !== substr( $packed, 0, 4 ) ) { WP_CLI::error( 'Build failed: ' . $packed ); } $name = sanitize_file_name( wp_basename( (string) $dest ) ); if ( ! preg_match( '/\.dat$/i', $name ) ) { WP_CLI::error( ' must be a file name ending in .dat; it is written inside the uploads/sentrixa-analytics folder.' ); } $uploads = wp_upload_dir(); $dir = trailingslashit( $uploads['basedir'] ) . 'sentrixa-analytics'; if ( ! wp_mkdir_p( $dir ) ) { WP_CLI::error( 'Could not create the uploads folder.' ); } $dest = trailingslashit( $dir ) . $name; if ( is_link( $dest ) ) { WP_CLI::error( 'Refusing to write through a symlink.' ); } file_put_contents( $dest, $packed ); // phpcs:ignore WordPress.WP.AlternativeFunctions WP_CLI::success( sprintf( 'Wrote %s (%s bytes).', $dest, number_format( strlen( $packed ) ) ) ); } /** * Show the current stats snapshot as JSON. * * ## OPTIONS * [--range=] * : today|7d|28d|90d|12mo (default 28d) */ public function stats( $args, $assoc ) { $range = isset( $assoc['range'] ) ? $assoc['range'] : '28d'; WP_CLI::print_value( SXANL_Stats_Query::dashboard_bundle( $range ), array( 'format' => 'json' ) ); } /** * Generate a pairing code for the Sentrixa Sites app. * * ## OPTIONS * [--author=] * : The account new connections act as. Defaults to `wp --user=...` if set, * otherwise the first administrator. (Note: `--user` is a WP-CLI global * flag, so this command uses `--author`.) * * @subcommand pair-code */ public function pair_code( $args, $assoc ) { if ( ! class_exists( 'SXANL_Connections' ) ) { WP_CLI::error( 'App pairing is part of the Sentrixa edition of this plugin.' ); } $user = null; if ( ! empty( $assoc['author'] ) ) { $user = is_numeric( $assoc['author'] ) ? get_user_by( 'id', (int) $assoc['author'] ) : get_user_by( 'login', $assoc['author'] ); if ( ! $user ) { WP_CLI::error( 'No account matching --author=' . $assoc['author'] ); } } if ( ! $user && get_current_user_id() ) { $user = wp_get_current_user(); } if ( ! $user || ! $user->ID ) { $admins = get_users( array( 'role' => 'administrator', 'number' => 1 ) ); $user = $admins ? $admins[0] : null; } if ( ! $user ) { WP_CLI::error( 'No usable account.' ); } $code = SXANL_Connections::generate_code( $user->ID ); WP_CLI::success( sprintf( 'Pairing code: %s (author: %s, expires %s)', $code['code'], $user->user_login, wp_date( 'H:i:s', $code['expires'] ) ) ); } /** * List the app connections. * * ## OPTIONS * [--format=] * : table, json, csv, yaml. Default table. */ public function connections( $args, $assoc ) { if ( ! class_exists( 'SXANL_Connections' ) ) { WP_CLI::error( 'App pairing is part of the Sentrixa edition of this plugin.' ); } $rows = array(); foreach ( SXANL_Connections::all() as $c ) { $rows[] = array( 'id' => $c['id'], 'label' => $c['label'], 'author_id' => $c['author_id'], 'created' => $c['created'], 'last_used' => $c['last_used'] ?: '-', ); } WP_CLI\Utils\format_items( isset( $assoc['format'] ) ? $assoc['format'] : 'table', $rows, array( 'id', 'label', 'author_id', 'created', 'last_used' ) ); } } WP_CLI::add_command( 'sentrixa-analytics', 'SXANL_CLI' );