!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.3.27 

uname -a: Linux pdx1-shared-a4-04 6.6.104-grsec-jammy+ #3 SMP Tue Sep 16 00:28:11 UTC 2025 x86_64 

uid=6659440(dh_z2jmpm) gid=2086089(pg10499364) groups=2086089(pg10499364)  

Safe-mode: OFF (not secure)

/usr/local/wp/vendor/wp-cli/extension-command/src/   drwxr-xr-x
Free 720.05 GB of 879.6 GB (81.86%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     Plugin_Command.php (53.31 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php

use WP_CLI\ParsePluginNameInput;
use WP_CLI\Utils;
use WP_CLI\WpOrgApi;

use function WP_CLI\Utils\normalize_path;

/**
 * Manages plugins, including installs, activations, and updates.
 *
 * See the WordPress [Plugin Handbook](https://developer.wordpress.org/plugins/) developer resource for more information on plugins.
 *
 * ## EXAMPLES
 *
 *     # Activate plugin
 *     $ wp plugin activate hello
 *     Plugin 'hello' activated.
 *     Success: Activated 1 of 1 plugins.
 *
 *     # Deactivate plugin
 *     $ wp plugin deactivate hello
 *     Plugin 'hello' deactivated.
 *     Success: Deactivated 1 of 1 plugins.
 *
 *     # Delete plugin
 *     $ wp plugin delete hello
 *     Deleted 'hello' plugin.
 *     Success: Deleted 1 of 1 plugins.
 *
 *     # Install the latest version from wordpress.org and activate
 *     $ wp plugin install bbpress --activate
 *     Installing bbPress (2.5.9)
 *     Downloading install package from https://downloads.wordpress.org/plugin/bbpress.2.5.9.zip...
 *     Using cached file '/home/vagrant/.wp-cli/cache/plugin/bbpress-2.5.9.zip'...
 *     Unpacking the package...
 *     Installing the plugin...
 *     Plugin installed successfully.
 *     Activating 'bbpress'...
 *     Plugin 'bbpress' activated.
 *     Success: Installed 1 of 1 plugins.
 *
 * @package wp-cli
 */
class Plugin_Command extends \WP_CLI\CommandWithUpgrade {

    use ParsePluginNameInput;

    protected $item_type         = 'plugin';
    protected $upgrade_refresh   = 'wp_update_plugins';
    protected $upgrade_transient = 'update_plugins';
    protected $check_wporg       = [
        'status'       => false,
        'last_updated' => false,
    ];
    protected $check_headers     = [
        'tested_up_to' => false,
    ];

    protected $obj_fields = array(
        'name',
        'status',
        'update',
        'version',
        'update_version',
        'auto_update',
    );

    /**
     * Plugin fetcher instance.
     *
     * @var \WP_CLI\Fetchers\Plugin
     */
    protected $fetcher;

    public function __construct() {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
        require_once ABSPATH . 'wp-admin/includes/plugin-install.php';

        parent::__construct();

        $this->fetcher = new WP_CLI\Fetchers\Plugin();
    }

    protected function get_upgrader_class( $force ) {
        return $force ? '\\WP_CLI\\DestructivePluginUpgrader' : 'Plugin_Upgrader';
    }

    /**
     * Reveals the status of one or all plugins.
     *
     * ## OPTIONS
     *
     * [<plugin>]
     * : A particular plugin to show the status for.
     *
     * ## EXAMPLES
     *
     *     # Displays status of all plugins
     *     $ wp plugin status
     *     5 installed plugins:
     *       I akismet                3.1.11
     *       I easy-digital-downloads 2.5.16
     *       A theme-check            20160523.1
     *       I wen-logo-slider        2.0.3
     *       M ns-pack                1.0.0
     *     Legend: I = Inactive, A = Active, M = Must Use
     *
     *     # Displays status of a plugin
     *     $ wp plugin status theme-check
     *     Plugin theme-check details:
     *         Name: Theme Check
     *         Status: Active
     *         Version: 20160523.1
     *         Author: Otto42, pross
     *         Description: A simple and easy way to test your theme for all the latest WordPress standards and practices. A great theme development tool!
     */
    public function status( $args ) {
        parent::status( $args );
    }

    /**
     * Searches the WordPress.org plugin directory.
     *
     * Displays plugins in the WordPress.org plugin directory matching a given
     * search query.
     *
     * ## OPTIONS
     *
     * <search>
     * : The string to search for.
     *
     * [--page=<page>]
     * : Optional page to display.
     * ---
     * default: 1
     * ---
     *
     * [--per-page=<per-page>]
     * : Optional number of results to display.
     * ---
     * default: 10
     * ---
     *
     * [--field=<field>]
     * : Prints the value of a single field for each plugin.
     *
     * [--fields=<fields>]
     * : Ask for specific fields from the API. Defaults to name,slug,author_profile,rating. Acceptable values:
     *
     *     **name**: Plugin Name
     *     **slug**: Plugin Slug
     *     **version**: Current Version Number
     *     **author**: Plugin Author
     *     **author_profile**: Plugin Author Profile
     *     **contributors**: Plugin Contributors
     *     **requires**: Plugin Minimum Requirements
     *     **tested**: Plugin Tested Up To
     *     **compatibility**: Plugin Compatible With
     *     **rating**: Plugin Rating in Percent and Total Number
     *     **ratings**: Plugin Ratings for each star (1-5)
     *     **num_ratings**: Number of Plugin Ratings
     *     **homepage**: Plugin Author's Homepage
     *     **description**: Plugin's Description
     *     **short_description**: Plugin's Short Description
     *     **sections**: Plugin Readme Sections: description, installation, FAQ, screenshots, other notes, and changelog
     *     **downloaded**: Plugin Download Count
     *     **last_updated**: Plugin's Last Update
     *     **added**: Plugin's Date Added to wordpress.org Repository
     *     **tags**: Plugin's Tags
     *     **versions**: Plugin's Available Versions with D/L Link
     *     **donate_link**: Plugin's Donation Link
     *     **banners**: Plugin's Banner Image Link
     *     **icons**: Plugin's Icon Image Link
     *     **active_installs**: Plugin's Number of Active Installs
     *     **contributors**: Plugin's List of Contributors
     *     **url**: Plugin's URL on wordpress.org
     *
     * [--format=<format>]
     * : Render output in a particular format.
     * ---
     * default: table
     * options:
     *   - table
     *   - csv
     *   - count
     *   - json
     *   - yaml
     * ---
     *
     * ## EXAMPLES
     *
     *     $ wp plugin search dsgnwrks --per-page=20 --format=json
     *     Success: Showing 3 of 3 plugins.
     *     [{"name":"DsgnWrks Instagram Importer Debug","slug":"dsgnwrks-instagram-importer-debug","rating":0},{"name":"DsgnWrks Instagram Importer","slug":"dsgnwrks-instagram-importer","rating":84},{"name":"DsgnWrks Twitter Importer","slug":"dsgnwrks-twitter-importer","rating":80}]
     *
     *     $ wp plugin search dsgnwrks --fields=name,version,slug,rating,num_ratings
     *     Success: Showing 3 of 3 plugins.
     *     +-----------------------------------+---------+-----------------------------------+--------+-------------+
     *     | name                              | version | slug                              | rating | num_ratings |
     *     +-----------------------------------+---------+-----------------------------------+--------+-------------+
     *     | DsgnWrks Instagram Importer Debug | 0.1.6   | dsgnwrks-instagram-importer-debug | 0      | 0           |
     *     | DsgnWrks Instagram Importer       | 1.3.7   | dsgnwrks-instagram-importer       | 84     | 23          |
     *     | DsgnWrks Twitter Importer         | 1.1.1   | dsgnwrks-twitter-importer         | 80     | 1           |
     *     +-----------------------------------+---------+-----------------------------------+--------+-------------+
     */
    public function search( $args, $assoc_args ) {
        parent::_search( $args, $assoc_args );
    }

    protected function status_single( $args ) {
        $plugin = $this->fetcher->get_check( $args[0] );
        $file   = $plugin->file;

        $details = $this->get_details( $file );

        $status = $this->format_status( $this->get_status( $file ), 'long' );

        $version = $details['Version'];

        if ( $this->has_update( $file ) ) {
            $version .= ' (%gUpdate available%n)';
        }

        echo WP_CLI::colorize(
            Utils\mustache_render(
                self::get_template_path( 'plugin-status.mustache' ),
                [
                    'slug'        => Utils\get_plugin_name( $file ),
                    'status'      => $status,
                    'version'     => $version,
                    'name'        => $details['Name'],
                    'author'      => $details['Author'],
                    'description' => $details['Description'],
                ]
            )
        );
    }

    protected function get_all_items() {
        $items = $this->get_item_list();

        foreach ( get_mu_plugins() as $file => $mu_plugin ) {
            $mu_version = '';
            if ( ! empty( $mu_plugin['Version'] ) ) {
                $mu_version = $mu_plugin['Version'];
            }

            $mu_title = '';
            if ( ! empty( $mu_plugin['Name'] ) ) {
                $mu_title = $mu_plugin['Title'];
            }

            $mu_description = '';
            if ( ! empty( $mu_plugin['Description'] ) ) {
                $mu_description = $mu_plugin['Description'];
            }
            $mu_name    = Utils\get_plugin_name( $file );
            $wporg_info = $this->get_wporg_data( $mu_name );

            $items[ $file ] = array(
                'name'               => $mu_name,
                'status'             => 'must-use',
                'update'             => false,
                'update_version'     => null,
                'update_package'     => null,
                'version'            => $mu_version,
                'update_id'          => '',
                'title'              => $mu_title,
                'description'        => $mu_description,
                'file'               => $file,
                'auto_update'        => false,
                'tested_up_to'       => '',
                'requires'           => '',
                'requires_php'       => '',
                'wporg_status'       => $wporg_info['status'],
                'wporg_last_updated' => $wporg_info['last_updated'],
            );
        }

        $raw_items = get_dropins();
        $raw_data  = _get_dropins();
        foreach ( $raw_items as $name => $item_data ) {
            $description    = ! empty( $raw_data[ $name ][0] ) ? $raw_data[ $name ][0] : '';
            $items[ $name ] = [
                'name'               => $name,
                'title'              => $item_data['Title'],
                'description'        => $description,
                'status'             => 'dropin',
                'update'             => false,
                'update_version'     => null,
                'update_package'     => null,
                'update_id'          => '',
                'file'               => $name,
                'auto_update'        => false,
                'author'             => $item_data['Author'],
                'tested_up_to'       => '',
                'requires'           => '',
                'requires_php'       => '',
                'wporg_status'       => '',
                'wporg_last_updated' => '',
            ];
        }

        return $items;
    }

    /**
     * Activates one or more plugins.
     *
     * ## OPTIONS
     *
     * [<plugin>...]
     * : One or more plugins to activate.
     *
     * [--all]
     * : If set, all plugins will be activated.
     *
     * [--exclude=<name>]
     * : Comma separated list of plugin slugs to be excluded from activation.
     *
     * [--network]
     * : If set, the plugin will be activated for the entire multisite network.
     *
     * ## EXAMPLES
     *
     *     # Activate plugin
     *     $ wp plugin activate hello
     *     Plugin 'hello' activated.
     *     Success: Activated 1 of 1 plugins.
     *
     *     # Activate plugin in entire multisite network
     *     $ wp plugin activate hello --network
     *     Plugin 'hello' network activated.
     *     Success: Network activated 1 of 1 plugins.
     *
     *     # Activate plugins that were recently active.
     *     $ wp plugin activate $(wp plugin list --recently-active --field=name)
     *     Plugin 'bbpress' activated.
     *     Plugin 'buddypress' activated.
     *     Success: Activated 2 of 2 plugins.
     *
     *     # Activate plugins that were recently active on a multisite.
     *     $ wp plugin activate $(wp plugin list --recently-active --field=name) --network
     *     Plugin 'bbpress' network activated.
     *     Plugin 'buddypress' network activated.
     *     Success: Activated 2 of 2 plugins.
     */
    public function activate( $args, $assoc_args = array() ) {
        $network_wide = Utils\get_flag_value( $assoc_args, 'network', false );
        $all          = Utils\get_flag_value( $assoc_args, 'all', false );
        $all_exclude  = Utils\get_flag_value( $assoc_args, 'exclude' );

        $args = $this->check_optional_args_and_all( $args, $all, 'activate', $all_exclude );
        if ( ! $args ) {
            return;
        }

        $successes = 0;
        $errors    = 0;
        $plugins   = $this->fetcher->get_many( $args );
        if ( count( $plugins ) < count( $args ) ) {
            $errors = count( $args ) - count( $plugins );
        }
        foreach ( $plugins as $plugin ) {
            $status = $this->get_status( $plugin->file );
            if ( $all && in_array( $status, [ 'active', 'active-network' ], true ) ) {
                continue;
            }
            // Network-active is the highest level of activation status.
            if ( 'active-network' === $status ) {
                WP_CLI::warning( "Plugin '{$plugin->name}' is already network active." );
                continue;
            }
            // Don't reactivate active plugins, but do let them become network-active.
            if ( ! $network_wide && 'active' === $status ) {
                WP_CLI::warning( "Plugin '{$plugin->name}' is already active." );
                continue;
            }

            // Plugins need to be deactivated before being network activated.
            if ( $network_wide && 'active' === $status ) {
                deactivate_plugins( $plugin->file, false, false );
            }

            $result = activate_plugin( $plugin->file, '', $network_wide );

            if ( is_wp_error( $result ) ) {
                $message = $result->get_error_message();
                $message = preg_replace( '/<a\s[^>]+>.*<\/a>/im', '', $message );
                $message = wp_strip_all_tags( $message );
                $message = str_replace( 'Error: ', '', $message );
                WP_CLI::warning( "Failed to activate plugin. {$message}" );
                ++$errors;
            } else {
                $this->active_output( $plugin->name, $plugin->file, $network_wide, 'activate' );
                ++$successes;
            }
        }

        if ( ! $this->chained_command ) {
            $verb = $network_wide ? 'network activate' : 'activate';
            Utils\report_batch_operation_results( 'plugin', $verb, count( $args ), $successes, $errors );
        }
    }

    /**
     * Deactivates one or more plugins.
     *
     * ## OPTIONS
     *
     * [<plugin>...]
     * : One or more plugins to deactivate.
     *
     * [--uninstall]
     * : Uninstall the plugin after deactivation.
     *
     * [--all]
     * : If set, all plugins will be deactivated.
     *
     * [--exclude=<name>]
     * : Comma separated list of plugin slugs that should be excluded from deactivation.
     *
     * [--network]
     * : If set, the plugin will be deactivated for the entire multisite network.
     *
     * ## EXAMPLES
     *
     *     # Deactivate plugin
     *     $ wp plugin deactivate hello
     *     Plugin 'hello' deactivated.
     *     Success: Deactivated 1 of 1 plugins.
     *
     *     # Deactivate all plugins with exclusion
     *     $ wp plugin deactivate --all --exclude=hello,wordpress-seo
     *     Plugin 'contact-form-7' deactivated.
     *     Plugin 'ninja-forms' deactivated.
     *     Success: Deactivated 2 of 2 plugins.
     */
    public function deactivate( $args, $assoc_args = array() ) {
        $network_wide        = Utils\get_flag_value( $assoc_args, 'network' );
        $disable_all         = Utils\get_flag_value( $assoc_args, 'all' );
        $disable_all_exclude = Utils\get_flag_value( $assoc_args, 'exclude' );

        $args = $this->check_optional_args_and_all( $args, $disable_all, 'deactivate', $disable_all_exclude );
        if ( ! $args ) {
            return;
        }

        $successes = 0;
        $errors    = 0;
        $plugins   = $this->fetcher->get_many( $args );
        if ( count( $plugins ) < count( $args ) ) {
            $errors = count( $args ) - count( $plugins );
        }

        foreach ( $plugins as $plugin ) {

            $status = $this->get_status( $plugin->file );
            if ( $disable_all && ! in_array( $status, [ 'active', 'active-network' ], true ) ) {
                continue;
            }

            // Network active plugins must be explicitly deactivated.
            if ( ! $network_wide && 'active-network' === $status ) {
                WP_CLI::warning( "Plugin '{$plugin->name}' is network active and must be deactivated with --network flag." );
                ++$errors;
                continue;
            }

            if ( ! in_array( $status, [ 'active', 'active-network' ], true ) ) {
                WP_CLI::warning( "Plugin '{$plugin->name}' isn't active." );
                continue;
            }

            deactivate_plugins( $plugin->file, false, $network_wide );

            if ( ! is_network_admin() ) {
                update_option(
                    'recently_activated',
                    array( $plugin->file => time() ) + (array) get_option( 'recently_activated' )
                );
            } else {
                update_site_option(
                    'recently_activated',
                    array( $plugin->file => time() ) + (array) get_site_option( 'recently_activated' )
                );
            }

            $this->active_output( $plugin->name, $plugin->file, $network_wide, 'deactivate' );
            ++$successes;

            if ( Utils\get_flag_value( $assoc_args, 'uninstall' ) ) {
                WP_CLI::log( "Uninstalling '{$plugin->name}'..." );
                $this->chained_command = true;
                $this->uninstall( array( $plugin->name ) );
                $this->chained_command = false;
            }
        }

        if ( ! $this->chained_command ) {
            $verb = $network_wide ? 'network deactivate' : 'deactivate';
            Utils\report_batch_operation_results( 'plugin', $verb, count( $args ), $successes, $errors );
        }
    }

    /**
     * Toggles a plugin's activation state.
     *
     * If the plugin is active, then it will be deactivated. If the plugin is
     * inactive, then it will be activated.
     *
     * ## OPTIONS
     *
     * <plugin>...
     * : One or more plugins to toggle.
     *
     * [--network]
     * : If set, the plugin will be toggled for the entire multisite network.
     *
     * ## EXAMPLES
     *
     *     # Akismet is currently activated
     *     $ wp plugin toggle akismet
     *     Plugin 'akismet' deactivated.
     *     Success: Toggled 1 of 1 plugins.
     *
     *     # Akismet is currently deactivated
     *     $ wp plugin toggle akismet
     *     Plugin 'akismet' activated.
     *     Success: Toggled 1 of 1 plugins.
     */
    public function toggle( $args, $assoc_args = array() ) {
        $network_wide = Utils\get_flag_value( $assoc_args, 'network' );

        $successes = 0;
        $errors    = 0;
        $plugins   = $this->fetcher->get_many( $args );
        if ( count( $plugins ) < count( $args ) ) {
            $errors = count( $args ) - count( $plugins );
        }
        $this->chained_command = true;
        foreach ( $plugins as $plugin ) {
            if ( $this->check_active( $plugin->file, $network_wide ) ) {
                $this->deactivate( array( $plugin->name ), $assoc_args );
            } else {
                $this->activate( array( $plugin->name ), $assoc_args );
            }
            ++$successes;
        }
        $this->chained_command = false;
        Utils\report_batch_operation_results( 'plugin', 'toggle', count( $args ), $successes, $errors );
    }

    /**
     * Gets the path to a plugin or to the plugin directory.
     *
     * ## OPTIONS
     *
     * [<plugin>]
     * : The plugin to get the path to. If not set, will return the path to the
     * plugins directory.
     *
     * [--dir]
     * : If set, get the path to the closest parent directory, instead of the
     * plugin file.
     *
     * ## EXAMPLES
     *
     *     $ cd $(wp plugin path) && pwd
     *     /var/www/wordpress/wp-content/plugins
     */
    public function path( $args, $assoc_args ) {
        $path = untrailingslashit( WP_PLUGIN_DIR );

        if ( ! empty( $args ) ) {
            $plugin = $this->fetcher->get_check( $args[0] );
            $path  .= '/' . $plugin->file;

            if ( Utils\get_flag_value( $assoc_args, 'dir' ) ) {
                $path = dirname( $path );
            }
        }

        WP_CLI::line( $path );
    }

    protected function install_from_repo( $slug, $assoc_args ) {
        global $wp_version;
        // Extract the major WordPress version (e.g., "6.3") from the full version string
        list($wp_core_version) = explode( '-', $wp_version );
        $wp_core_version       = implode( '.', array_slice( explode( '.', $wp_core_version ), 0, 2 ) );

        $api = plugins_api( 'plugin_information', array( 'slug' => $slug ) );

        if ( is_wp_error( $api ) ) {
            return $api;
        }

        if ( isset( $assoc_args['version'] ) ) {
            self::alter_api_response( $api, $assoc_args['version'] );
        } elseif ( ! Utils\get_flag_value( $assoc_args, 'ignore-requirements', false ) ) {
            $requires_php = isset( $api->requires_php ) ? $api->requires_php : null;
            $requires_wp  = isset( $api->requires ) ? $api->requires : null;

            $compatible_php = empty( $requires_php ) || version_compare( PHP_VERSION, $requires_php, '>=' );
            $compatible_wp  = empty( $requires_wp ) || version_compare( $wp_core_version, $requires_wp, '>=' );

            if ( ! $compatible_wp ) {
                return new WP_Error( 'requirements_not_met', "This plugin does not work with your version of WordPress. Minimum WordPress requirement is $requires_wp" );
            }

            if ( ! $compatible_php ) {
                return new WP_Error( 'requirements_not_met', "This plugin does not work with your version of PHP. Minimum PHP required is $compatible_php" );
            }
        }

        $status = install_plugin_install_status( $api );

        if ( ! Utils\get_flag_value( $assoc_args, 'force' ) && 'install' !== $status['status'] ) {
            // We know this will fail, so avoid a needless download of the package.
            return new WP_Error( 'already_installed', 'Plugin already installed.' );
        }

        WP_CLI::log( sprintf( 'Installing %s (%s)', html_entity_decode( $api->name, ENT_QUOTES ), $api->version ) );
        if ( Utils\get_flag_value( $assoc_args, 'version' ) !== 'dev' ) {
            WP_CLI::get_http_cache_manager()->whitelist_package( $api->download_link, $this->item_type, $api->slug, $api->version );
        }

        // Ignore failures on accessing SSL "https://api.wordpress.org/plugins/update-check/1.1/" in `wp_update_plugins()` which seem to occur intermittently.
        set_error_handler( array( __CLASS__, 'error_handler' ), E_USER_WARNING | E_USER_NOTICE );

        $result = $this->get_upgrader( $assoc_args )->install( $api->download_link );

        restore_error_handler();

        return $result;
    }

    /**
     * Updates one or more plugins.
     *
     * ## OPTIONS
     *
     * [<plugin>...]
     * : One or more plugins to update.
     *
     * [--all]
     * : If set, all plugins that have updates will be updated.
     *
     * [--exclude=<name>]
     * : Comma separated list of plugin names that should be excluded from updating.
     *
     * [--minor]
     * : Only perform updates for minor releases (e.g. from 1.3 to 1.4 instead of 2.0)
     *
     * [--patch]
     * : Only perform updates for patch releases (e.g. from 1.3 to 1.3.3 instead of 1.4)
     *
     * [--format=<format>]
     * : Render output in a particular format.
     * ---
     * default: table
     * options:
     *   - table
     *   - csv
     *   - json
     *   - summary
     * ---
     *
     * [--version=<version>]
     * : If set, the plugin will be updated to the specified version.
     *
     * [--dry-run]
     * : Preview which plugins would be updated.
     *
     * [--insecure]
     * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack.
     *
     * ## EXAMPLES
     *
     *     $ wp plugin update bbpress --version=dev
     *     Installing bbPress (Development Version)
     *     Downloading install package from https://downloads.wordpress.org/plugin/bbpress.zip...
     *     Unpacking the package...
     *     Installing the plugin...
     *     Removing the old version of the plugin...
     *     Plugin updated successfully.
     *     Success: Updated 1 of 2 plugins.
     *
     *     $ wp plugin update --all
     *     Enabling Maintenance mode...
     *     Downloading update from https://downloads.wordpress.org/plugin/akismet.3.1.11.zip...
     *     Unpacking the update...
     *     Installing the latest version...
     *     Removing the old version of the plugin...
     *     Plugin updated successfully.
     *     Downloading update from https://downloads.wordpress.org/plugin/nginx-champuru.3.2.0.zip...
     *     Unpacking the update...
     *     Installing the latest version...
     *     Removing the old version of the plugin...
     *     Plugin updated successfully.
     *     Disabling Maintenance mode...
     *     +------------------------+-------------+-------------+---------+
     *     | name                   | old_version | new_version | status  |
     *     +------------------------+-------------+-------------+---------+
     *     | akismet                | 3.1.3       | 3.1.11      | Updated |
     *     | nginx-cache-controller | 3.1.1       | 3.2.0       | Updated |
     *     +------------------------+-------------+-------------+---------+
     *     Success: Updated 2 of 2 plugins.
     *
     *     $ wp plugin update --all --exclude=akismet
     *     Enabling Maintenance mode...
     *     Downloading update from https://downloads.wordpress.org/plugin/nginx-champuru.3.2.0.zip...
     *     Unpacking the update...
     *     Installing the latest version...
     *     Removing the old version of the plugin...
     *     Plugin updated successfully.
     *     Disabling Maintenance mode...
     *     +------------------------+-------------+-------------+---------+
     *     | name                   | old_version | new_version | status  |
     *     +------------------------+-------------+-------------+---------+
     *     | nginx-cache-controller | 3.1.1       | 3.2.0       | Updated |
     *     +------------------------+-------------+-------------+---------+
     *
     * @alias upgrade
     */
    public function update( $args, $assoc_args ) {
        $all = Utils\get_flag_value( $assoc_args, 'all', false );

        $args = $this->check_optional_args_and_all( $args, $all );
        if ( ! $args ) {
            return;
        }

        if ( isset( $assoc_args['version'] ) ) {
            foreach ( $this->fetcher->get_many( $args ) as $plugin ) {
                $assoc_args['force'] = 1;
                $this->install( array( $plugin->name ), $assoc_args );
            }
        } else {
            parent::update_many( $args, $assoc_args );
        }
    }

    protected function get_item_list() {
        global $wp_version;

        $items           = [];
        $duplicate_names = [];

        $auto_updates = get_site_option( Plugin_AutoUpdates_Command::SITE_OPTION );

        if ( ! is_array( $auto_updates ) ) {
            $auto_updates = [];
        }

        $recently_active = is_network_admin() ? get_site_option( 'recently_activated' ) : get_option( 'recently_activated' );

        if ( false === $recently_active ) {
            $recently_active = [];
        }

        foreach ( $this->get_all_plugins() as $file => $details ) {
            $all_update_info = $this->get_update_info();
            $update_info     = ( isset( $all_update_info->response[ $file ] ) && null !== $all_update_info->response[ $file ] ) ? (array) $all_update_info->response[ $file ] : null;
            $name            = Utils\get_plugin_name( $file );
            $wporg_info      = $this->get_wporg_data( $name );
            $plugin_data     = get_plugin_data( WP_PLUGIN_DIR . '/' . $file, false, false );

            if ( ! isset( $duplicate_names[ $name ] ) ) {
                $duplicate_names[ $name ] = array();
            }

            $requires     = isset( $update_info ) && isset( $update_info['requires'] ) ? $update_info['requires'] : null;
            $requires_php = isset( $update_info ) && isset( $update_info['requires_php'] ) ? $update_info['requires_php'] : null;

            // If an update has requires_php set, check to see if the local version of PHP meets that requirement
            // The plugins update API already filters out plugins that don't meet WordPress requirements, but does not
            // filter out plugins based on PHP requirements -- so we must do that here
            $compatible_php = empty( $requires_php ) || version_compare( PHP_VERSION, $requires_php, '>=' );

            if ( ! $compatible_php ) {
                $update = 'unavailable';

                $update_unavailable_reason = sprintf(
                    'This update requires PHP version %s, but the version installed is %s.',
                    $requires_php,
                    PHP_VERSION
                );
            } else {
                $update = $update_info ? 'available' : 'none';
            }

            // requires and requires_php are only provided by the plugins update API in the case of an update available.
            // For display consistency, get these values from the current plugin file if they aren't in this response
            if ( null === $requires ) {
                $requires = ! empty( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : '';
            }

            if ( null === $requires_php ) {
                    $requires_php = ! empty( $plugin_data['RequiresPHP'] ) ? $plugin_data['RequiresPHP'] : '';
            }

            $duplicate_names[ $name ][] = $file;
            $items[ $file ]             = [
                'name'                      => $name,
                'status'                    => $this->get_status( $file ),
                'update'                    => $update,
                'update_version'            => isset( $update_info ) && isset( $update_info['new_version'] ) ? $update_info['new_version'] : null,
                'update_package'            => isset( $update_info ) && isset( $update_info['package'] ) ? $update_info['package'] : null,
                'version'                   => $details['Version'],
                'update_id'                 => $file,
                'title'                     => $details['Name'],
                'description'               => wordwrap( $details['Description'] ),
                'file'                      => $file,
                'auto_update'               => in_array( $file, $auto_updates, true ),
                'author'                    => $details['Author'],
                'tested_up_to'              => '',
                'requires'                  => $requires,
                'requires_php'              => $requires_php,
                'wporg_status'              => $wporg_info['status'],
                'wporg_last_updated'        => $wporg_info['last_updated'],
                'recently_active'           => in_array( $file, array_keys( $recently_active ), true ),
                'update_unavailable_reason' => isset( $update_unavailable_reason ) ? $update_unavailable_reason : '',
            ];

            if ( $this->check_headers['tested_up_to'] ) {
                $plugin_readme = normalize_path( dirname( WP_PLUGIN_DIR . '/' . $file ) . '/readme.txt' );

                if ( file_exists( $plugin_readme ) && is_readable( $plugin_readme ) ) {
                    $readme_obj = new SplFileObject( $plugin_readme );
                    $readme_obj->setFlags( SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY );
                    $readme_line = 0;

                    // Reading the whole file can exhaust the memory, so only read the first 100 lines of the file,
                    // as the "Tested up to" header should be near the top.
                    while ( $readme_line < 100 && ! $readme_obj->eof() ) {
                        $line = $readme_obj->fgets();

                        // Similar to WP.org, it matches for both "Tested up to" and "Tested" header in the readme file.
                        preg_match( '/^tested(:| up to:) (.*)$/i', strtolower( $line ), $matches );

                        if ( isset( $matches[2] ) && ! empty( $matches[2] ) ) {
                            $items[ $file ]['tested_up_to'] = $matches[2];
                            break;
                        }

                        ++$readme_line;
                    }

                    $file_obj = null;
                }
            }

            if ( null === $update_info ) {
                // Get info for all plugins that don't have an update.
                $plugin_update_info = isset( $all_update_info->no_update[ $file ] ) ? $all_update_info->no_update[ $file ] : null;

                // Check if local version is newer than what is listed upstream.
                if ( null !== $plugin_update_info && version_compare( $details['Version'], $plugin_update_info->new_version, '>' ) ) {
                    $items[ $file ]['update']       = static::INVALID_VERSION_MESSAGE;
                    $items[ $file ]['requires']     = isset( $plugin_update_info->requires ) ? $plugin_update_info->requires : null;
                    $items[ $file ]['requires_php'] = isset( $plugin_update_info->requires_php ) ? $plugin_update_info->requires_php : null;
                }

                // If there is a plugin in no_update with a newer version than the local copy, it is because the plugins update api
                // has already filtered it because the local WordPress version is too low
                if ( null !== $plugin_update_info && version_compare( $details['Version'], $plugin_update_info->new_version, '<' ) ) {
                    $items[ $file ]['update']         = 'unavailable';
                    $items[ $file ]['update_version'] = $plugin_update_info->new_version;
                    $items[ $file ]['requires']       = isset( $plugin_update_info->requires ) ? $plugin_update_info->requires : null;
                    $items[ $file ]['requires_php']   = isset( $plugin_update_info->requires_php ) ? $plugin_update_info->requires_php : null;

                    $reason = "This update requires WordPress version $plugin_update_info->requires, but the version installed is $wp_version.";

                    $items[ $file ]['update_unavailable_reason'] = $reason;

                }
            }
        }

        foreach ( $duplicate_names as $name => $files ) {
            if ( count( $files ) <= 1 ) {
                continue;
            }
            foreach ( $files as $file ) {
                $items[ $file ]['name'] = str_replace( '.' . pathinfo( $file, PATHINFO_EXTENSION ), '', $file );
            }
        }

        return $items;
    }

    /**
     * Get the wordpress.org status of a plugin.
     *
     * @param string $plugin_name The plugin slug.
     *
     * @return string The status of the plugin, includes the last update date.
     */
    protected function get_wporg_data( $plugin_name ) {
        $data = [
            'status'       => '',
            'last_updated' => '',
        ];
        if ( ! $this->check_wporg['status'] && ! $this->check_wporg['last_updated'] ) {
            return $data;
        }

        if ( $this->check_wporg ) {
            try {
                $plugin_data = ( new WpOrgApi() )->get_plugin_info( $plugin_name );
            } catch ( Exception $e ) {
                // Request failed. The plugin is not (active) on .org.
                $plugin_data = false;
            }
            if ( $plugin_data ) {
                $data['status'] = 'active';
                if ( ! $this->check_wporg['last_updated'] ) {
                    return $data; // The plugin is active on .org, but we don't need the date.
                }
            }
            // Just because the plugin is not in the api, does not mean it was never on .org.
        }

        $request       = wp_remote_get( "https://plugins.trac.wordpress.org/log/{$plugin_name}/?limit=1&mode=stop_on_copy&format=rss" );
        $response_code = wp_remote_retrieve_response_code( $request );
        if ( 404 === $response_code ) {
            return $data; // This plugin was never on .org, there is no date to check.
        }
        if ( 'active' !== $data['status'] ) {
            $data['status'] = 'closed'; // This plugin was on .org at some point, but not anymore.
        }
        if ( ! class_exists( 'SimpleXMLElement' ) ) {
            WP_CLI::error( "The PHP extension 'SimpleXMLElement' is not available but is required for XML-formatted output." );
        }

        // Check the last update date.
        $r_body = wp_remote_retrieve_body( $request );
        if ( strpos( $r_body, 'pubDate' ) !== false ) {
            // Very raw check, not validating the format or anything else.
            $xml          = simplexml_load_string( $r_body );
            $xml_pub_date = $xml->xpath( '//pubDate' );
            if ( $xml_pub_date ) {
                $data['last_updated'] = wp_date( 'Y-m-d', (string) strtotime( $xml_pub_date[0] ) );
            }
        }

        return $data;
    }

    protected function filter_item_list( $items, $args ) {
        $basenames = wp_list_pluck( $this->fetcher->get_many( $args ), 'file' );
        return Utils\pick_fields( $items, $basenames );
    }

    /**
     * Installs one or more plugins.
     *
     * ## OPTIONS
     *
     * <plugin|zip|url>...
     * : One or more plugins to install. Accepts a plugin slug, the path to a local zip file, or a URL to a remote zip file.
     *
     * [--version=<version>]
     * : If set, get that particular version from wordpress.org, instead of the
     * stable version.
     *
     * [--force]
     * : If set, the command will overwrite any installed version of the plugin, without prompting
     * for confirmation.
     *
     * [--ignore-requirements]
     * :If set, the command will install the plugin while ignoring any WordPress or PHP version requirements
     * specified by the plugin authors.
     *
     * [--activate]
     * : If set, the plugin will be activated immediately after install.
     *
     * [--activate-network]
     * : If set, the plugin will be network activated immediately after install
     *
     * [--insecure]
     * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack.
     *
     * ## EXAMPLES
     *
     *     # Install the latest version from wordpress.org and activate
     *     $ wp plugin install bbpress --activate
     *     Installing bbPress (2.5.9)
     *     Downloading install package from https://downloads.wordpress.org/plugin/bbpress.2.5.9.zip...
     *     Using cached file '/home/vagrant/.wp-cli/cache/plugin/bbpress-2.5.9.zip'...
     *     Unpacking the package...
     *     Installing the plugin...
     *     Plugin installed successfully.
     *     Activating 'bbpress'...
     *     Plugin 'bbpress' activated.
     *     Success: Installed 1 of 1 plugins.
     *
     *     # Install the development version from wordpress.org
     *     $ wp plugin install bbpress --version=dev
     *     Installing bbPress (Development Version)
     *     Downloading install package from https://downloads.wordpress.org/plugin/bbpress.zip...
     *     Unpacking the package...
     *     Installing the plugin...
     *     Plugin installed successfully.
     *     Success: Installed 1 of 1 plugins.
     *
     *     # Install from a local zip file
     *     $ wp plugin install ../my-plugin.zip
     *     Unpacking the package...
     *     Installing the plugin...
     *     Plugin installed successfully.
     *     Success: Installed 1 of 1 plugins.
     *
     *     # Install from a remote zip file
     *     $ wp plugin install http://s3.amazonaws.com/bucketname/my-plugin.zip?AWSAccessKeyId=123&Expires=456&Signature=abcdef
     *     Downloading install package from http://s3.amazonaws.com/bucketname/my-plugin.zip?AWSAccessKeyId=123&Expires=456&Signature=abcdef
     *     Unpacking the package...
     *     Installing the plugin...
     *     Plugin installed successfully.
     *     Success: Installed 1 of 1 plugins.
     *
     *     # Update from a remote zip file
     *     $ wp plugin install https://github.com/envato/wp-envato-market/archive/master.zip --force
     *     Downloading install package from https://github.com/envato/wp-envato-market/archive/master.zip
     *     Unpacking the package...
     *     Installing the plugin...
     *     Renamed Github-based project from 'wp-envato-market-master' to 'wp-envato-market'.
     *     Plugin updated successfully
     *     Success: Installed 1 of 1 plugins.
     *
     *     # Forcefully re-install all installed plugins
     *     $ wp plugin install $(wp plugin list --field=name) --force
     *     Installing Akismet (3.1.11)
     *     Downloading install package from https://downloads.wordpress.org/plugin/akismet.3.1.11.zip...
     *     Unpacking the package...
     *     Installing the plugin...
     *     Removing the old version of the plugin...
     *     Plugin updated successfully
     *     Success: Installed 1 of 1 plugins.
     */
    public function install( $args, $assoc_args ) {

        if ( ! is_dir( WP_PLUGIN_DIR ) ) {
            wp_mkdir_p( WP_PLUGIN_DIR );
        }

        parent::install( $args, $assoc_args );
    }

    /**
     * Gets details about an installed plugin.
     *
     * ## OPTIONS
     *
     * <plugin>
     * : The plugin to get.
     *
     * [--field=<field>]
     * : Instead of returning the whole plugin, returns the value of a single field.
     *
     * [--fields=<fields>]
     * : Limit the output to specific fields. Defaults to all fields.
     *
     * [--format=<format>]
     * : Render output in a particular format.
     * ---
     * default: table
     * options:
     *   - table
     *   - csv
     *   - json
     *   - yaml
     * ---
     *
     * ## AVAILABLE FIELDS
     *
     * These fields will be displayed by default for the plugin:
     *
     * * name
     * * title
     * * author
     * * version
     * * description
     * * status
     *
     * These fields are optionally available:
     *
     * * requires_wp
     * * requires_php
     * * requires_plugins
     *
     * ## EXAMPLES
     *
     *     # Get plugin details.
     *     $ wp plugin get bbpress --format=json
     *     {"name":"bbpress","title":"bbPress","author":"The bbPress Contributors","version":"2.6.9","description":"bbPress is forum software with a twist from the creators of WordPress.","status":"active"}
     */
    public function get( $args, $assoc_args ) {
        $default_fields = array(
            'name',
            'title',
            'author',
            'version',
            'description',
            'status',
        );

        $plugin = $this->fetcher->get_check( $args[0] );
        $file   = $plugin->file;

        $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $file, false, false );

        $plugin_obj = (object) [
            'name'             => Utils\get_plugin_name( $file ),
            'title'            => $plugin_data['Name'],
            'author'           => $plugin_data['Author'],
            'version'          => $plugin_data['Version'],
            'description'      => wordwrap( $plugin_data['Description'] ),
            'status'           => $this->get_status( $file ),
            'requires_wp'      => ! empty( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : '',
            'requires_php'     => ! empty( $plugin_data['RequiresPHP'] ) ? $plugin_data['RequiresPHP'] : '',
            'requires_plugins' => ! empty( $plugin_data['RequiresPlugins'] ) ? $plugin_data['RequiresPlugins'] : '',
        ];

        if ( empty( $assoc_args['fields'] ) ) {
            $assoc_args['fields'] = $default_fields;
        }

        $formatter = $this->get_formatter( $assoc_args );
        $formatter->display_item( $plugin_obj );
    }

    /**
     * Uninstalls one or more plugins.
     *
     * ## OPTIONS
     *
     * [<plugin>...]
     * : One or more plugins to uninstall.
     *
     * [--deactivate]
     * : Deactivate the plugin before uninstalling. Default behavior is to warn and skip if the plugin is active.
     *
     * [--skip-delete]
     * : If set, the plugin files will not be deleted. Only the uninstall procedure
     * will be run.
     *
     * [--all]
     * : If set, all plugins will be uninstalled.
     *
     * [--exclude=<name>]
     * : Comma separated list of plugin slugs to be excluded from uninstall.
     *
     * ## EXAMPLES
     *
     *     $ wp plugin uninstall hello
     *     Uninstalled and deleted 'hello' plugin.
     *     Success: Uninstalled 1 of 1 plugins.
     *
     *     # Uninstall all plugins excluding specified ones
     *     $ wp plugin uninstall --all --exclude=hello-dolly,jetpack
     *     Uninstalled and deleted 'akismet' plugin.
     *     Uninstalled and deleted 'tinymce-templates' plugin.
     *     Success: Uninstalled 2 of 2 plugins.
     */
    public function uninstall( $args, $assoc_args = array() ) {

        $all         = Utils\get_flag_value( $assoc_args, 'all', false );
        $all_exclude = Utils\get_flag_value( $assoc_args, 'exclude', false );

        // Check if plugin names or --all is passed.
        $args = $this->check_optional_args_and_all( $args, $all, 'uninstall', $all_exclude );
        if ( ! $args ) {
            return;
        }

        $successes            = 0;
        $errors               = 0;
        $delete_errors        = array();
        $deleted_plugin_files = array();

        $plugins = $this->fetcher->get_many( $args );
        if ( count( $plugins ) < count( $args ) ) {
            $errors = count( $args ) - count( $plugins );
        }

        foreach ( $plugins as $plugin ) {
            if ( is_plugin_active( $plugin->file ) && ! WP_CLI\Utils\get_flag_value( $assoc_args, 'deactivate' ) ) {
                WP_CLI::warning( "The '{$plugin->name}' plugin is active." );
                ++$errors;
                continue;
            }

            if ( Utils\get_flag_value( $assoc_args, 'deactivate' ) ) {
                WP_CLI::log( "Deactivating '{$plugin->name}'..." );
                $this->chained_command = true;
                $this->deactivate( array( $plugin->name ) );
                $this->chained_command = false;
            }

            uninstall_plugin( $plugin->file );

            $plugin_translations = wp_get_installed_translations( 'plugins' );

            $plugin_slug = dirname( $plugin->file );

            if ( 'hello.php' === $plugin->file ) {
                $plugin_slug = 'hello-dolly';
            }

            // Remove language files, silently.
            if ( '.' !== $plugin_slug && ! empty( $plugin_translations[ $plugin_slug ] ) ) {
                $translations = $plugin_translations[ $plugin_slug ];

                global $wp_filesystem;
                require_once ABSPATH . '/wp-admin/includes/file.php';
                WP_Filesystem();

                foreach ( $translations as $translation => $data ) {
                    $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.po' );
                    $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.mo' );
                    $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.l10n.php' );

                    $json_translation_files = glob( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '-*.json' );
                    if ( $json_translation_files ) {
                        array_map( array( $wp_filesystem, 'delete' ), $json_translation_files );
                    }
                }
            }

            if ( ! Utils\get_flag_value( $assoc_args, 'skip-delete' ) ) {
                if ( $this->delete_plugin( $plugin ) ) {
                    $deleted_plugin_files[] = $plugin->file;
                    WP_CLI::log( "Uninstalled and deleted '$plugin->name' plugin." );
                } else {
                    $delete_errors[] = $plugin->file;
                    WP_CLI::log( "Ran uninstall procedure for '$plugin->name' plugin. Deletion of plugin files failed" );
                    ++$errors;
                    continue;
                }
            } else {
                WP_CLI::log( "Ran uninstall procedure for '$plugin->name' plugin without deleting." );
            }
            ++$successes;
        }

        // Remove deleted plugins from the plugin updates list.
        $current = get_site_transient( $this->upgrade_transient );
        if ( $current ) {
            // Don't remove the plugins that weren't deleted.
            $deleted = array_diff( $deleted_plugin_files, $delete_errors );

            foreach ( $deleted as $plugin_file ) {
                unset( $current->response[ $plugin_file ] );
                unset( $current->checked[ $plugin_file ] );
            }

            set_site_transient( $this->upgrade_transient, $current );
        }

        if ( ! $this->chained_command ) {
            Utils\report_batch_operation_results( 'plugin', 'uninstall', count( $args ), $successes, $errors );
        }
    }

    /**
     * Checks if a given plugin is installed.
     *
     * Returns exit code 0 when installed, 1 when uninstalled.
     *
     * ## OPTIONS
     *
     * <plugin>
     * : The plugin to check.
     *
     * ## EXAMPLES
     *
     *     # Check whether plugin is installed; exit status 0 if installed, otherwise 1
     *     $ wp plugin is-installed hello
     *     $ echo $?
     *     1
     *
     * @subcommand is-installed
     */
    public function is_installed( $args, $assoc_args = array() ) {
        if ( $this->fetcher->get( $args[0] ) ) {
            WP_CLI::halt( 0 );
        } else {
            WP_CLI::halt( 1 );
        }
    }

    /**
     * Checks if a given plugin is active.
     *
     * Returns exit code 0 when active, 1 when not active.
     *
     * ## OPTIONS
     *
     * <plugin>
     * : The plugin to check.
     *
     * [--network]
     * : If set, check if plugin is network-activated.
     *
     * ## EXAMPLES
     *
     *     # Check whether plugin is Active; exit status 0 if active, otherwise 1
     *     $ wp plugin is-active hello
     *     $ echo $?
     *     1
     *
     * @subcommand is-active
     */
    public function is_active( $args, $assoc_args = array() ) {
        $network_wide = Utils\get_flag_value( $assoc_args, 'network' );

        $plugin = $this->fetcher->get( $args[0] );

        if ( ! $plugin ) {
            WP_CLI::halt( 1 );
        }

        $this->check_active( $plugin->file, $network_wide ) ? WP_CLI::halt( 0 ) : WP_CLI::halt( 1 );
    }

    /**
     * Deletes plugin files without deactivating or uninstalling.
     *
     * ## OPTIONS
     *
     * [<plugin>...]
     * : One or more plugins to delete.
     *
     * [--all]
     * : If set, all plugins will be deleted.
     *
     * [--exclude=<name>]
     * : Comma separated list of plugin slugs to be excluded from deletion.
     *
     * ## EXAMPLES
     *
     *     # Delete plugin
     *     $ wp plugin delete hello
     *     Deleted 'hello' plugin.
     *     Success: Deleted 1 of 1 plugins.
     *
     *     # Delete inactive plugins
     *     $ wp plugin delete $(wp plugin list --status=inactive --field=name)
     *     Deleted 'tinymce-templates' plugin.
     *     Success: Deleted 1 of 1 plugins.
     *
     *     # Delete all plugins excluding specified ones
     *     $ wp plugin delete --all --exclude=hello-dolly,jetpack
     *     Deleted 'akismet' plugin.
     *     Deleted 'tinymce-templates' plugin.
     *     Success: Deleted 2 of 2 plugins.
     */
    public function delete( $args, $assoc_args = array() ) {
        $all         = Utils\get_flag_value( $assoc_args, 'all', false );
        $all_exclude = Utils\get_flag_value( $assoc_args, 'exclude', false );

        // Check if plugin names or --all is passed.
        $args = $this->check_optional_args_and_all( $args, $all, 'delete', $all_exclude );
        if ( ! $args ) {
            return;
        }

        $successes = 0;
        $errors    = 0;

        foreach ( $this->fetcher->get_many( $args ) as $plugin ) {
            if ( $this->delete_plugin( $plugin ) ) {
                WP_CLI::log( "Deleted '{$plugin->name}' plugin." );
                ++$successes;
            } else {
                WP_CLI::warning( "The '{$plugin->name}' plugin could not be deleted." );
                ++$errors;
            }
        }
        if ( ! $this->chained_command ) {
            Utils\report_batch_operation_results( 'plugin', 'delete', count( $args ), $successes, $errors );
        }
    }

    /**
     * Gets a list of plugins.
     *
     * Displays a list of the plugins installed on the site with activation
     * status, whether or not there's an update available, etc.
     *
     * Use `--status=dropin` to list installed dropins (e.g. `object-cache.php`).
     *
     * ## OPTIONS
     *
     * [--<field>=<value>]
     * : Filter results based on the value of a field.
     *
     * [--field=<field>]
     * : Prints the value of a single field for each plugin.
     *
     * [--fields=<fields>]
     * : Limit the output to specific object fields.
     *
     * [--format=<format>]
     * : Render output in a particular format.
     * ---
     * default: table
     * options:
     *   - table
     *   - csv
     *   - count
     *   - json
     *   - yaml
     * ---
     *
     * [--status=<status>]
     * : Filter the output by plugin status.
     * ---
     * options:
     *   - active
     *   - active-network
     *   - dropin
     *   - inactive
     *   - must-use
     * ---
     *
     * [--skip-update-check]
     * : If set, the plugin update check will be skipped.
     *
     * [--recently-active]
     * : If set, only recently active plugins will be shown and the status filter will be ignored.
     *
     * ## AVAILABLE FIELDS
     *
     * These fields will be displayed by default for each plugin:
     *
     * * name
     * * status
     * * update
     * * version
     * * update_version
     * * auto_update
     *
     * These fields are optionally available:
     *
     * * update_package
     * * update_id
     * * title
     * * description
     * * file
     * * author
     * * tested_up_to
     * * requires
     * * requires_php
     * * wporg_status
     * * wporg_last_updated
     *
     * ## EXAMPLES
     *
     *     # List active plugins on the site.
     *     $ wp plugin list --status=active --format=json
     *     [{"name":"dynamic-hostname","status":"active","update":"none","version":"0.4.2","update_version":"","auto_update":"off"},{"name":"tinymce-templates","status":"active","update":"none","version":"4.8.1","update_version":"","auto_update":"off"},{"name":"wp-multibyte-patch","status":"active","update":"none","version":"2.9","update_version":"","auto_update":"off"},{"name":"wp-total-hacks","status":"active","update":"none","version":"4.7.2","update_version":"","auto_update":"off"}]
     *
     *     # List plugins on each site in a network.
     *     $ wp site list --field=url | xargs -I % wp plugin list --url=%
     *     +---------+----------------+-----------+---------+-----------------+------------+
     *     | name    | status         | update    | version | update_version | auto_update |
     *     +---------+----------------+-----------+---------+----------------+-------------+
     *     | akismet | active-network | none      | 5.3.1   |                | on          |
     *     | hello   | inactive       | available | 1.6     | 1.7.2          | off         |
     *     +---------+----------------+-----------+---------+----------------+-------------+
     *     +---------+----------------+-----------+---------+----------------+-------------+
     *     | name    | status         | update    | version | update_version | auto_update |
     *     +---------+----------------+-----------+---------+----------------+-------------+
     *     | akismet | active-network | none      | 5.3.1   |                | on          |
     *     | hello   | inactive       | available | 1.6     | 1.7.2          | off         |
     *     +---------+----------------+-----------+---------+----------------+-------------+
     *
     *     # Check whether plugins are still active on WordPress.org
     *     $ wp plugin list --fields=name,wporg_status,wporg_last_updated
     *     +--------------------+--------------+--------------------+
     *     | name               | wporg_status | wporg_last_updated |
     *     +--------------------+--------------+--------------------+
     *     | akismet            | active       | 2023-12-11         |
     *     | user-switching     | active       | 2023-11-17         |
     *     | wordpress-importer | active       | 2023-04-28         |
     *     | local              |              |                    |
     *     +--------------------+--------------+--------------------+
     *
     *     # List recently active plugins on the site.
     *     $ wp plugin list --recently-active --field=name --format=json
     *     ["akismet","bbpress","buddypress"]
     *
     * @subcommand list
     */
    public function list_( $_, $assoc_args ) {
        $fields = Utils\get_flag_value( $assoc_args, 'fields' );
        if ( ! empty( $fields ) ) {
            $fields                            = explode( ',', $fields );
            $this->check_wporg['status']       = in_array( 'wporg_status', $fields, true );
            $this->check_wporg['last_updated'] = in_array( 'wporg_last_updated', $fields, true );

            $this->check_headers['tested_up_to'] = in_array( 'tested_up_to', $fields, true );
        }

        $field = Utils\get_flag_value( $assoc_args, 'field' );
        if ( 'wporg_status' === $field ) {
            $this->check_wporg['status'] = true;
        } elseif ( 'wporg_last_updated' === $field ) {
            $this->check_wporg['last_updated'] = true;
        }

        $this->check_headers['tested_up_to'] = 'tested_up_to' === $field || $this->check_headers['tested_up_to'];

        parent::_list( $_, $assoc_args );
    }

    /* PRIVATES */

    private function check_active( $file, $network_wide ) {
        $required = $network_wide ? 'active-network' : 'active';

        return $required === $this->get_status( $file );
    }

    private function active_output( $name, $file, $network_wide, $action ) {
        $network_wide = $network_wide || ( is_multisite() && is_network_only_plugin( $file ) );

        $check = $this->check_active( $file, $network_wide );

        if ( ( 'activate' === $action ) ? $check : ! $check ) {
            if ( $network_wide ) {
                WP_CLI::log( "Plugin '{$name}' network {$action}d." );
            } else {
                WP_CLI::log( "Plugin '{$name}' {$action}d." );
            }
        } else {
            WP_CLI::warning( "Could not {$action} the '{$name}' plugin." );
        }
    }

    protected function get_status( $file ) {
        if ( is_plugin_active_for_network( $file ) ) {
            return 'active-network';
        }
        if ( is_plugin_active( $file ) ) {
            return 'active';
        }

        return 'inactive';
    }

    /**
     * Gets the template path based on installation type.
     */
    private static function get_template_path( $template ) {
        $command_root  = Utils\phar_safe_path( dirname( __DIR__ ) );
        $template_path = "{$command_root}/templates/{$template}";

        if ( ! file_exists( $template_path ) ) {
            WP_CLI::error( "Couldn't find {$template}" );
        }

        return $template_path;
    }

    /**
     * Gets the details of a plugin.
     *
     * @param object
     * @return array
     */
    private function get_details( $file ) {
        $plugin_folder = get_plugins( '/' . plugin_basename( dirname( $file ) ) );
        $plugin_file   = Utils\basename( $file );

        return $plugin_folder[ $plugin_file ];
    }

    /**
     * Performs deletion of plugin files
     *
     * @param $plugin - Plugin fetcher object (name, file)
     * @return bool - If plugin was deleted
     */
    private function delete_plugin( $plugin ) {
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
        do_action( 'delete_plugin', $plugin->file );

        $plugin_dir = dirname( $plugin->file );
        if ( '.' === $plugin_dir ) {
            $plugin_dir = $plugin->file;
        }

        $path = path_join( WP_PLUGIN_DIR, $plugin_dir );

        if ( Utils\is_windows() ) {
            // Handles plugins that are not in own folders
            // e.g. Hello Dolly -> plugins/hello.php
            if ( is_file( $path ) ) {
                $command = 'del /f /q ';
            } else {
                $command = 'rd /s /q ';
            }
            $path = str_replace( '/', '\\', $path );
        } else {
            $command = 'rm -rf ';
        }

        $result = ! WP_CLI::launch( $command . escapeshellarg( $path ), false );

        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
        do_action( 'deleted_plugin', $plugin->file, $result );

        return $result;
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0127 ]--