AnonSec Shell
Server IP : 172.67.157.199  /  Your IP : 3.138.175.52   [ Reverse IP ]
Web Server : Apache
System : Linux b70eb322-3aee-0c53-7c82-0db91281f2c6.secureserver.net 6.1.90-1.el9.elrepo.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 2 12:09:22 EDT 2024 x86_64
User : root ( 0)
PHP Version : 8.0.30.2
Disable Function : NONE
Domains : 0 Domains
MySQL : ON  |  cURL : ON  |  WGET : ON  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /var/www/wp-content/mu-plugins/object-cache-pro/src/Console/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     [ BACKUP SHELL ]     [ JUMPING ]     [ MASS DEFACE ]     [ SCAN ROOT ]     [ SYMLINK ]     

Current File : /var/www/wp-content/mu-plugins/object-cache-pro/src/Console//Commands.php
<?php
/**
 * Copyright © 2019-2024 Rhubarb Tech Inc. All Rights Reserved.
 *
 * The Object Cache Pro Software and its related materials are property and confidential
 * information of Rhubarb Tech Inc. Any reproduction, use, distribution, or exploitation
 * of the Object Cache Pro Software and its related materials, in whole or in part,
 * is strictly forbidden unless prior permission is obtained from Rhubarb Tech Inc.
 *
 * In addition, any reproduction, use, distribution, or exploitation of the Object Cache Pro
 * Software and its related materials, in whole or in part, is subject to the End-User License
 * Agreement accessible in the included `LICENSE` file, or at: https://objectcache.pro/eula
 */

declare(strict_types=1);

namespace RedisCachePro\Console;

use Throwable;
use WP_REST_Request;

use cli\Shell;

use WP_CLI;
use WP_CLI\NoOp;
use WP_CLI_Command;

use function WP_CLI\Utils\esc_cmd;
use function WP_CLI\Utils\proc_open_compat;

use RedisCachePro\Diagnostics\Diagnostics;
use RedisCachePro\Connections\RelayConnection;
use RedisCachePro\Configuration\Configuration;

use RedisCachePro\ObjectCaches\ObjectCacheInterface;
use RedisCachePro\ObjectCaches\MeasuredObjectCacheInterface;

use RedisCachePro\Plugin\Api\Analytics;

use RedisCachePro\Console\Watchers\LogWatcher;
use RedisCachePro\Console\Watchers\DigestWatcher;
use RedisCachePro\Console\Watchers\AggregateWatcher;

/**
 * Enables, disabled, flushes, and checks the status of the object cache.
 */
class Commands extends WP_CLI_Command
{
    /**
     * Enables the object cache.
     *
     * Copies the object cache drop-in into the content directory.
     * Will not overwrite existing files, unless the --force option is used.
     *
     * ## OPTIONS
     *
     * [--force]
     * : Overwrite existing files.
     *
     * [--skip-flush]
     * : Omit flushing the cache.
     *
     * [--skip-flush-notice]
     * : Omit the cache flush notice.
     *
     * [--skip-transients]
     * : Omit deleting transients from the database.
     *
     * ## EXAMPLES
     *
     *     # Enable the object cache.
     *     $ wp redis enable
     *
     *     # Enable the object cache and overwrite existing drop-in.
     *     $ wp redis enable --force
     *
     *     # Update the object cache drop-in without flushing the cache.
     *     $ wp redis enable --force --skip-flush --skip-flush-notice
     *
     * @alias activate
     *
     * @param  array<int, string>  $arguments
     * @param  array<mixed>  $options
     * @return void
     */
    public function enable($arguments, $options)
    {
        global $wp_filesystem;

        if (! \WP_Filesystem()) {
            WP_CLI::error('Could not gain filesystem access.');
        }

        if (! defined('\WP_REDIS_CONFIG')) {
            WP_CLI::error(WP_CLI::colorize(
                'To enable the object cache, set up the %yWP_REDIS_CONFIG%n constant.'
            ));
        }

        $force = isset($options['force']);

        $dropin = \WP_CONTENT_DIR . '/object-cache.php';
        $stub = realpath(__DIR__ . '/../../stubs/object-cache.php');

        if (! $force && $wp_filesystem->exists($dropin)) {
            WP_CLI::error(WP_CLI::colorize(
                'A object cache drop-in already exists. Run `%ywp redis enable --force%n` to overwrite it.'
            ));
        }

        if (! $wp_filesystem->copy($stub, $dropin, $force, \FS_CHMOD_FILE)) {
            WP_CLI::error('Object cache could not be enabled.');
        }

        if (function_exists('wp_opcache_invalidate')) {
            wp_opcache_invalidate($dropin, true);
        }

        WP_CLI::success('Object cache enabled.');

        if (isset($options['skip-flush'])) {
            if (! isset($options['skip-flush-notice'])) {
                WP_CLI::line(WP_CLI::colorize(
                    'To avoid outdated data, flush the object cache by calling `%ywp cache flush%n`.'
                ));
            }
        } else {
            $GLOBALS['ObjectCachePro']->resetCache()
                ? WP_CLI::success('Object cache flushed.')
                : WP_CLI::error('Object cache could not be flushed.');
        }

        if (isset($options['skip-transients'])) {
            WP_CLI::line(
                WP_CLI::colorize(
                    sprintf(
                        'To avoid outdated data, delete transients from the database by calling `%%y%s%%n`.',
                        is_multisite()
                            ? 'wp transient delete --all --network && wp site list --field=url | xargs -n1 -I % wp --url=% transient delete --all'
                            : 'wp transient delete --all'
                    )
                )
            );
        } else {
            $GLOBALS['ObjectCachePro']->deleteTransients();

            WP_CLI::success('Transients deleted from the database.');
        }
    }

    /**
     * Disables the object cache.
     *
     * ## OPTIONS
     *
     * [--skip-flush]
     * : Omit flushing the cache.
     *
     * ## EXAMPLES
     *
     *     # Disable the disable cache.
     *     $ wp redis disable
     *
     *     # Disable the object cache and don't flush the cache.
     *     $ wp redis disable --skip-flush
     *
     * @alias deactivate
     *
     * @param  array<int, string>  $arguments
     * @param  array<mixed>  $options
     * @return void
     */
    public function disable($arguments, $options)
    {
        global $wp_filesystem;

        if (! \WP_Filesystem()) {
            WP_CLI::error('Could not gain filesystem access.');
        }

        $dropin = \WP_CONTENT_DIR . '/object-cache.php';

        if (! $wp_filesystem->exists($dropin)) {
            WP_CLI::log('No object cache drop-in found.');

            return;
        }

        if (! $wp_filesystem->delete($dropin)) {
            WP_CLI::error('Object cache could not be disabled.');
        }

        if (function_exists('wp_opcache_invalidate')) {
            wp_opcache_invalidate($dropin, true);
        }

        WP_CLI::success('Object cache disabled.');

        if (! isset($options['skip-flush'])) {
            $GLOBALS['ObjectCachePro']->resetCache()
                ? WP_CLI::success('Object cache flushed.')
                : WP_CLI::error('Object cache could not be flushed.');
        }
    }

    /**
     * Shows object cache status summary.
     *
     * ## EXAMPLES
     *
     *     # Show object cache status.
     *     $ wp redis status
     *
     * @alias info
     * @alias health
     *
     * @return void
     */
    public function status()
    {
        global $wp_object_cache;

        $diagnostics = (new Diagnostics($wp_object_cache))
            ->withFilesystemAccess()
            ->toArray();

        WP_CLI::log(WP_CLI::colorize(sprintf('%%b[%s]%%n', 'Cache')));

        $diagnostic = $diagnostics[Diagnostics::GENERAL]['status'];
        WP_CLI::log(sprintf('%s: %s', $diagnostic->name, WP_CLI::colorize($diagnostic->withComment()->cli)));

        $diagnostic = $diagnostics[Diagnostics::GENERAL]['dropin'];
        WP_CLI::log(sprintf('%s: %s', $diagnostic->name, WP_CLI::colorize($diagnostic->withComment()->cli)));

        if (! empty($diagnostics[Diagnostics::ERRORS])) {
            WP_CLI::log('');
            WP_CLI::log(WP_CLI::colorize(sprintf('%%b[%s]%%n', 'Errors')));

            foreach ($diagnostics[Diagnostics::ERRORS] as $error) {
                WP_CLI::log(WP_CLI::colorize("%r{$error}%n"));
            }
        }

        WP_CLI::log('');
        WP_CLI::log(WP_CLI::colorize(sprintf('%%b[%s]%%n', 'Plugin')));

        $diagnostic = $diagnostics[Diagnostics::GENERAL]['license'];
        WP_CLI::log(sprintf('%s: %s', $diagnostic->name, WP_CLI::colorize($diagnostic->withComment()->cli)));

        $diagnostic = $diagnostics[Diagnostics::GENERAL]['mu'];
        WP_CLI::log(sprintf('%s: %s', $diagnostic->name, WP_CLI::colorize($diagnostic->withComment()->cli)));

        $diagnostic = $diagnostics[Diagnostics::VERSIONS]['plugin'];
        WP_CLI::log(sprintf('%s: %s', 'Version', WP_CLI::colorize($diagnostic->withComment()->cli)));

        WP_CLI::log('');
        WP_CLI::log(WP_CLI::colorize(sprintf('%%b[%s]%%n', 'WordPress')));

        $diagnostic = $diagnostics[Diagnostics::GENERAL]['host'];
        WP_CLI::log(sprintf('%s: %s', $diagnostic->name, WP_CLI::colorize($diagnostic->withComment()->cli)));

        $diagnostic = $diagnostics[Diagnostics::GENERAL]['filesystem'];
        WP_CLI::log(sprintf('%s: %s', $diagnostic->name, WP_CLI::colorize($diagnostic->withComment()->cli)));

        $diagnostic = $diagnostics[Diagnostics::VERSIONS]['php'];
        WP_CLI::log(sprintf('%s: %s', $diagnostic->name, WP_CLI::colorize($diagnostic->withComment()->cli)));

        WP_CLI::log('');
        WP_CLI::log(WP_CLI::colorize(sprintf('%%b[%s]%%n', 'Redis')));

        $diagnostic = $diagnostics[Diagnostics::GENERAL]['eviction-policy'];
        WP_CLI::log(sprintf('%s: %s', $diagnostic->name, WP_CLI::colorize($diagnostic->withComment()->cli)));

        $diagnostic = $diagnostics[Diagnostics::VERSIONS]['redis'];
        WP_CLI::log(sprintf('%s: %s', 'Version', WP_CLI::colorize($diagnostic->withComment()->cli)));

        if (extension_loaded('relay')) {
            WP_CLI::log('');
            WP_CLI::log(WP_CLI::colorize(sprintf('%%b[%s]%%n', 'Relay')));

            $diagnostic = $diagnostics[Diagnostics::RELAY]['relay-cache'];
            WP_CLI::log(sprintf('%s: %s', 'Cache', WP_CLI::colorize($diagnostic->withComment()->cli)));

            $diagnostic = $diagnostics[Diagnostics::RELAY]['relay-license'];
            WP_CLI::log(sprintf('%s: %s', 'License', WP_CLI::colorize($diagnostic->withComment()->cli)));

            $diagnostic = $diagnostics[Diagnostics::RELAY]['relay-eviction'];
            WP_CLI::log(sprintf('%s: %s', 'Eviction Policy', WP_CLI::colorize($diagnostic->withComment()->cli)));

            $diagnostic = $diagnostics[Diagnostics::VERSIONS]['relay'];
            WP_CLI::log(sprintf('%s: %s', 'Version', WP_CLI::colorize($diagnostic->withComment()->cli)));
        }
    }

    /**
     * Shows object cache status and diagnostics.
     *
     * ## EXAMPLES
     *
     *     # Show object cache diagnostics.
     *     $ wp redis diagnostics
     *
     * @return void
     */
    public function diagnostics()
    {
        global $wp_object_cache;

        $diagnostics = (new Diagnostics($wp_object_cache))->withFilesystemAccess();

        foreach ($diagnostics->toArray() as $groupName => $group) {
            if (empty($group)) {
                continue;
            }

            WP_CLI::log(WP_CLI::colorize(
                sprintf('%%b[%s]%%n', ucfirst($groupName))
            ));

            foreach ($group as $diagnostic) {
                if ($groupName === Diagnostics::ERRORS) {
                    WP_CLI::log(WP_CLI::colorize("%r{$diagnostic}%n"));
                } else {
                    $value = WP_CLI::colorize($diagnostic->withComment()->cli);

                    WP_CLI::log("{$diagnostic->name}: {$value}");
                }
            }

            WP_CLI::log('');
        }
    }

    /**
     * Flushes the object cache.
     *
     * ## OPTIONS
     *
     * [<site-id>...]
     * : One or more IDs of sites to flush.
     *
     * ## EXAMPLES
     *
     *     # Flush the entire cache.
     *     $ wp redis flush
     *     Success: The object cache was flushed.
     *
     *     # Flush multiple sites (networks only).
     *     $ wp redis flush 42 1337
     *     Success: The object cache of site at 'https://example.org' was flushed.
     *     Success: The object cache of site at 'https://help.example.org' was flushed.
     *
     *     # Flush site by URL (networks only).
     *     $ wp redis flush --url="https://example.org"
     *     Success: The object cache of site at 'https://example.org' was flushed.
     *
     * @alias clear
     *
     * @param  array<int, string>  $arguments
     * @param  array<mixed>  $options
     * @return void
     */
    public function flush($arguments, $options)
    {
        global $wp_object_cache;

        $this->abortIfNotConnected();

        // unset site ids when environment is not a multisite
        if (! is_multisite()) {
            $arguments = [];
        }

        // flush cache of site set via `--url` option
        if (is_multisite() && empty($arguments) && WP_CLI::get_config('url')) {
            $arguments = [get_current_blog_id()];
        }

        if (empty($arguments)) {
            try {
                $GLOBALS['ObjectCachePro']->logFlush();
                $result = $wp_object_cache->flush();
            } catch (Throwable $exception) {
                $result = false;
            }

            if (! $result) {
                WP_CLI::error('Object cache could not be flushed.');
            }

            WP_CLI::success('Object cache flushed.');

            return;
        }

        foreach ($arguments as $siteId) {
            try {
                $result = $wp_object_cache->flushBlog((int) $siteId);
            } catch (Throwable $exception) {
                WP_CLI::error($exception->getMessage());
            }

            if ($result) {
                WP_CLI::success(WP_CLI::colorize(
                    "Object cache of site [%y{$siteId}%n] was flushed."
                ));
            } else {
                WP_CLI::error(WP_CLI::colorize(
                    "Object cache of site [%y{$siteId}%n] could not be flushed."
                ), false);
            }
        }
    }

    /**
     * Flushes one or more object cache groups.
     *
     * In multisite environments the group is always flushed for all sites.
     *
     * ## OPTIONS
     *
     * <group>...
     * : One or more groups to flush.
     *
     * ## EXAMPLES
     *
     *     # Flush the entire cache.
     *     $ wp redis flush-group comments
     *     Success: "Object cache group [comments] was flushed.
     *
     *     # Flush multiple groups.
     *     $ wp redis flush-group posts post_meta
     *     Success: "Object cache group [posts] was flushed.
     *     Success: "Object cache group [post_meta] was flushed.
     *
     * @subcommand flush-group
     *
     * @param  array<int, string>  $arguments
     * @param  array<mixed>  $options
     * @return void
     */
    public function flushGroup($arguments, $options)
    {
        global $wp_object_cache;

        $this->abortIfNotConnected();

        foreach ($arguments as $group) {
            try {
                $GLOBALS['ObjectCachePro']->logGroupFlush($group);

                $result = $wp_object_cache->flush_group($group);
            } catch (Throwable $exception) {
                WP_CLI::error($exception->getMessage());
            }

            if ($result) {
                WP_CLI::success(WP_CLI::colorize(
                    "Object cache group [%y{$group}%n] was flushed."
                ));
            } else {
                WP_CLI::error(WP_CLI::colorize(
                    "Object cache group [%y{$group}%n] could not be flushed."
                ), false);
            }
        }
    }

    /**
     * Resets the entire object cache database, including metadata and analytics.
     *
     * ## EXAMPLES
     *
     *     # Resets the entire cache.
     *     $ wp redis reset
     *     Success: The object cache was reset.
     *
     * @param  array<int, string>  $arguments
     * @param  array<mixed>  $options
     * @return void
     */
    public function reset($arguments, $options)
    {
        $GLOBALS['ObjectCachePro']->resetCache()
            ? WP_CLI::success('Object cache reset.')
            : WP_CLI::error('Object cache could not be reset.');
    }

    /**
     * Launches `redis-cli` using WordPress configuration.
     *
     * ## EXAMPLES
     *
     *     # Launch redis-cli.
     *     $ wp redis cli
     *     127.0.0.1:6379> ping
     *     PONG
     *
     * @alias shell
     *
     * @return void
     */
    public function cli()
    {
        $this->abortIfNotConfigured();

        $cliVersion = shell_exec('redis-cli -v');

        if ($cliVersion && preg_match('/\d+\.\d+\.\d+/', $cliVersion, $matches)) {
            $cliVersion = $matches[0];
        } else {
            WP_CLI::warning('Could not detect `redis-cli` version.');

            $cliVersion = '';
        }

        $config = Configuration::from(\WP_REDIS_CONFIG);

        $host = $config->host ?? '127.0.0.1';
        $port = $config->port ?? 6379;
        $database = $config->database ?? 0;
        $username = $config->username;
        $password = $config->password;

        $info = (object) [
            'server' => null,
            'scheme' => strtoupper($config->scheme),
            'auth' => 'no password',
        ];

        $command = 'redis-cli -n %s';
        $arguments = [$database];

        if (is_array($config->cluster)) {
            $command .= ' -c';

            $primary = parse_url(reset($config->cluster));
            $host = $primary['host']; // @phpstan-ignore-line
            $port = $primary['port']; // @phpstan-ignore-line

            if (strtolower($primary['scheme']) === 'tls') { // @phpstan-ignore-line
                $command .= ' --tls';
            }
        }

        if ($config->sentinels) {
            WP_CLI::error('This command does not support Redis Sentinel.');
        }

        if ($config->servers) {
            WP_CLI::error('This command does not support Redis replication.');
        }

        $arguments[] = $host;

        if ($config->scheme === 'unix') {
            $command .= ' -s %s';
            $info->server = "%y{$host}%n";
        } else {
            $command .= ' -h %s -p %s';
            $arguments[] = $port;
            $info->server = "%y{$host}%n:%y{$port}%n";
        }

        if ($password) {
            $command .= ' -a %s';
            $arguments[] = $password;
            $info->auth = 'with password';
        }

        if ($username) {
            $command .= ' --user %s';
            $arguments[] = $username;
            $info->auth = "as %y{$username}%n";
        }

        if ($config->scheme === 'tls') {
            $command .= ' --tls';
        }

        // The `--no-auth-warning` option was added in Redis 4.0
        if (($username || $password) && version_compare($cliVersion, '4.0', '>=')) {
            $command .= ' --no-auth-warning';
        }

        WP_CLI::log(WP_CLI::colorize(
            "Connecting via {$info->scheme} to {$info->server} ({$info->auth}) using database %y{$database}%n."
        ));

        $command = esc_cmd($command, ...$arguments);
        $process = proc_open_compat($command, [STDIN, STDOUT, STDERR], $pipes);

        exit(proc_close($process));
    }

    /**
     * Watch object cache analytics as they happen.
     *
     * ## OPTIONS
     *
     * [<watcher>]
     * : The analytics watcher to use.
     * ---
     * default: digest
     * options:
     *   - digest
     *   - log
     *   - aggregate
     * ---
     *
     * [--seconds=<number>]
     * : How many seconds of data to aggregate?
     * ---
     * default: 5
     * ---
     *
     * [--metrics=<metrics>]
     * : Limit the output to specific metrics.
     *
     * ## AVAILABLE METRICS
     *
     * By default a different subset of metrics will be displayed for each watcher.
     *
     * These metrics are available:
     *
     * * hits
     * * misses
     * * hit-ratio
     * * bytes
     * * prefetches
     * * store-reads
     * * store-writes
     * * store-hits
     * * store-misses
     * * sql-queries
     * * ms-total
     * * ms-cache
     * * ms-cache-avg
     * * ms-cache-ratio
     * * redis-hits
     * * redis-misses
     * * redis-hit-ratio
     * * redis-ops-per-sec
     * * redis-evicted-keys
     * * redis-used-memory
     * * redis-used-memory-rss
     * * redis-memory-ratio
     * * redis-memory-fragmentation-ratio
     * * redis-connected-clients
     * * redis-tracking-clients
     * * redis-rejected-connections
     * * redis-keys
     * * relay-hits
     * * relay-misses
     * * relay-hit-ratio
     * * relay-ops-per-sec
     * * relay-keys
     * * relay-memory-used
     * * relay-memory-total
     * * relay-memory-human
     * * relay-memory-ratio
     *
     * ## EXAMPLES
     *
     *     # Show an analytics digest.
     *     $ wp redis watch
     *
     *     # Tail analytics in log format.
     *     $ wp redis watch log
     *
     *     # Aggregate analytics
     *     $ wp redis watch aggregate --seconds=2
     *
     * @param  array<int, string>  $arguments
     * @param  array<mixed>  $options
     * @return WP_CLI\NoOp
     */
    public function watch($arguments, $options)
    {
        global $wp_object_cache;

        $this->abortIfNotConfigured();
        $this->abortIfNotConnected();

        if (
            ! $wp_object_cache instanceof ObjectCacheInterface ||
            ! $wp_object_cache instanceof MeasuredObjectCacheInterface
        ) {
            WP_CLI::error('Object cache does not support analytics.');
        }

        $config = Configuration::from(\WP_REDIS_CONFIG);

        if (! $config->analytics->enabled) {
            WP_CLI::error('Object cache analytics are disabled.');
        }

        $options = array_merge([
            'compact' => false,
            'seconds' => 4,
            'metrics' => [],
        ], $options);

        if (is_string($options['metrics'])) {
            $options['metrics'] = explode(',', $options['metrics']);
        }

        switch ($arguments[0]) {
            default:
            case 'digest':
                if (Shell::isPiped()) {
                    return new NoOp;
                }

                $monitor = new DigestWatcher("Showing digest of the last %g{$options['seconds']}s%n");
                break;

            case 'log':
                $monitor = new LogWatcher('Waiting for measurements...');
                break;

            case 'aggregate':
                $monitor = new AggregateWatcher("Showing %g{$options['seconds']}s%n aggregates...");
                break;
        }

        $monitor->options = $options;
        $monitor->cache = $wp_object_cache;
        $monitor->usingRelay = $wp_object_cache->connection() instanceof RelayConnection;

        $nextTime = 0;

        while (true) { // @phpstan-ignore-line
            if ($nextTime) {
                usleep(50000);
            }

            if (microtime(true) < $nextTime) {
                $monitor->tick();
                continue;
            }

            $nextTime = microtime(true) + 1;

            $monitor->prepare();
            $monitor->tick();
        }
    }

    /**
     * Returns the analytic values.
     *
     * ## OPTIONS
     *
     * [--interval=<number>]
     * : The interval in seconds.
     * ---
     * default: 60
     * ---
     *
     * [--per_page=<number>]
     * : Maximum number of items to be returned in result set.
     * ---
     * default: 30
     * ---
     *
     * [--page=<number>]
     * : Current page of the collection.
     * ---
     * default: 1
     * ---
     *
     * [--fields=<metrics>]
     * : Limit the output to specific metrics and computations.
     *
     * [--pretty]
     * : Whether to pretty print the result.
     * ---
     * default: false
     * ---
     *
     * ## AVAILABLE METRICS
     *
     * These metrics are available:
     *
     * * hits
     * * misses
     * * hit-ratio
     * * bytes
     * * prefetches
     * * store-reads
     * * store-writes
     * * store-hits
     * * store-misses
     * * sql-queries
     * * ms-total
     * * ms-cache
     * * ms-cache-avg
     * * ms-cache-ratio
     * * redis-hits
     * * redis-misses
     * * redis-hit-ratio
     * * redis-ops-per-sec
     * * redis-evicted-keys
     * * redis-used-memory
     * * redis-used-memory-rss
     * * redis-memory-ratio
     * * redis-memory-fragmentation-ratio
     * * redis-connected-clients
     * * redis-tracking-clients
     * * redis-rejected-connections
     * * redis-keys
     * * relay-hits
     * * relay-misses
     * * relay-hit-ratio
     * * relay-ops-per-sec
     * * relay-keys
     * * relay-memory-used
     * * relay-memory-total
     * * relay-memory-human
     * * relay-memory-ratio
     *
     * ## EXAMPLES
     *
     *     # Compute analytics for the last 30 minutes in 60 second intervals
     *     $ wp redis analytics
     *
     *     # Raw measurements for the last 30 minutes in 60 second intervals
     *     $ wp redis analytics --context=raw
     *
     *     # Compute hits and misses for the last hour
     *     $ wp redis analytics --interval=3600 --per_page=1 --fields=hits,misses --pretty
     *
     *     # Compute hit ratio median for the last hour in 10 minute intervals
     *     $ wp redis analytics --interval=600 --per_page=6 --fields=hits.median,count,date_gmt
     *
     * @param  array<int, string>  $arguments
     * @param  array<mixed>  $options
     * @return void
     */
    public function analytics($arguments, $options)
    {
        $this->abortIfNotConfigured();

        $analytics = new Analytics;

        $defaults = array_map(static function ($param) {
            return $param['default'];
        }, $analytics->get_collection_params());

        $options = array_merge([
            'pretty' => false,
            'context' => $defaults['context'],
            'interval' => $defaults['interval'],
            'page' => $defaults['page'],
            'per_page' => $defaults['per_page'],
        ], $options);

        $pretty = $options['pretty'] ? \JSON_PRETTY_PRINT : 0;

        $request = new WP_REST_Request;
        $request->set_param('context', (string) $options['context']);
        $request->set_param('interval', (int) $options['interval']);
        $request->set_param('page', (int) $options['page']);
        $request->set_param('per_page', (int) $options['per_page']);

        $fields = empty($options['fields']) ? $analytics->get_fields_for_response($request) : explode(',', $options['fields']);
        $request->set_param('_fields', $fields);

        $response = $analytics->get_items($request);

        if (is_wp_error($response)) {
            WP_CLI::line((string) json_encode([
                'code' => $response->get_error_code(),
                'message' => $response->get_error_message(),
                'data' => $response->get_error_data(),
            ], JSON_PRETTY_PRINT));

            return;
        }

        WP_CLI::line((string) json_encode($response->get_data(), $pretty));
    }

    /**
     * Abort if plugin wasn't configured.
     *
     * @return void
     */
    protected function abortIfNotConfigured()
    {
        if (! defined('\WP_REDIS_CONFIG')) {
            WP_CLI::error(WP_CLI::colorize(
                'The %yWP_REDIS_CONFIG%n constant has not been defined.'
            ));
        }
    }

    /**
     * Abort if object cache isn't connected.
     *
     * @return void
     */
    protected function abortIfNotConnected()
    {
        global $wp_object_cache;

        $diagnostics = new Diagnostics($wp_object_cache);

        if (! $diagnostics->dropinExists()) {
            WP_CLI::error(WP_CLI::colorize(
                'No object cache drop-in found. Run `%ywp redis enable%n` to enable the object cache.'
            ));
        }

        if (! $diagnostics->dropinIsValid()) {
            WP_CLI::error(WP_CLI::colorize(
                'The object cache drop-in is invalid. Run `%ywp redis enable --force%n` to enable the object cache.'
            ));
        }
    }
}

Anon7 - 2022
AnonSec Team