<?php namespace Automattic\WooCommerce\Blueprint\Importers; use Automattic\WooCommerce\Blueprint\ResourceStorages; use Automattic\WooCommerce\Blueprint\StepProcessor; use Automattic\WooCommerce\Blueprint\StepProcessorResult; use Automattic\WooCommerce\Blueprint\Steps\InstallPlugin; use Automattic\WooCommerce\Blueprint\UseWPFunctions; use Plugin_Upgrader; /** * Class ImportInstallPlugin * * Handles the installation and activation of plugins based on a schema. */ class ImportInstallPlugin implements StepProcessor { use UseWPFunctions; /** * Resource storage instance for handling plugin files. * * @var ResourceStorages */ private ResourceStorages $storage; /** * Array of paths to installed plugins. * * @var array */ private array $installed_plugin_paths = array(); /** * Constructor. * * @param ResourceStorages $storage Resource storage instance. */ public function __construct( ResourceStorages $storage ) { $this->storage = $storage; } /** * Processes the schema to install and optionally activate a plugin. * * @param object $schema Schema object containing plugin information. * @return StepProcessorResult Result of the processing. */ public function process( $schema ): StepProcessorResult { $result = StepProcessorResult::success( InstallPlugin::get_step_name() ); $installed_plugins = $this->get_installed_plugins_paths(); // phpcs:ignore $plugin = $schema->pluginZipFile; if ( isset( $installed_plugins[ $plugin->slug ] ) ) { $result->add_info( "Skipped installing {$plugin->slug}. It is already installed." ); return $result; } if ( $this->storage->is_supported_resource( $plugin->resource ) === false ) { $result->add_error( "Invalid resource type for {$plugin->slug}." ); return $result; } $downloaded_path = $this->storage->download( $plugin->slug, $plugin->resource ); if ( ! $downloaded_path ) { $result->add_error( "Unable to download {$plugin->slug} with {$plugin->resource} resource type." ); return $result; } $install = $this->install( $downloaded_path ); $install && $result->add_info( "Installed {$plugin->slug}." ); if ( isset( $plugin->options, $plugin->options->activate ) && true === $plugin->options->activate ) { $activate = $this->activate( $plugin->slug ); if ( $activate instanceof \WP_Error ) { $result->add_error( "Failed to activate {$plugin->slug}." ); } if ( null === $activate ) { $result->add_info( "Activated {$plugin->slug}." ); } } return $result; } /** * Installs a plugin from the given local path. * * @param string $local_plugin_path Path to the local plugin file. * @return bool True on success, false on failure. */ protected function install( $local_plugin_path ) { if ( ! class_exists( 'Plugin_Upgrader' ) ) { include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php'; include_once ABSPATH . '/wp-admin/includes/class-plugin-upgrader.php'; } $upgrader = new \Plugin_Upgrader( new \Automatic_Upgrader_Skin() ); return $upgrader->install( $local_plugin_path ); } /** * Activates an installed plugin by its slug. * * @param string $slug Plugin slug. * @return \WP_Error|null WP_Error on failure, null on success. */ protected function activate( $slug ) { if ( empty( $this->installed_plugin_paths ) ) { $this->installed_plugin_paths = $this->get_installed_plugins_paths(); } $path = $this->installed_plugin_paths[ $slug ] ?? false; if ( ! $path ) { return new \WP_Error( 'plugin_not_installed', "Plugin {$slug} is not installed." ); } return $this->wp_activate_plugin( $path ); } /** * Retrieves an array of installed plugins and their paths. * * @return array Array of installed plugins and their paths. */ protected function get_installed_plugins_paths() { if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugins = get_plugins(); $installed_plugins = array(); foreach ( $plugins as $path => $plugin ) { $path_parts = explode( '/', $path ); $slug = $path_parts[0]; $installed_plugins[ $slug ] = $path; } return $installed_plugins; } /** * Returns the class name of the step being processed. * * @return string Class name of the step. */ public function get_step_class(): string { return InstallPlugin::class; } }