diff --git a/.gitignore b/.gitignore
index 0de311ac680be..30b744b4f61d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,3 +59,7 @@ _inc/jetpack-strings.php
/vendor/autoload.php
/vendor/autoload_packages.php
/vendor/autoload_functions.php
+/vendor/class-autoloader-handler.php
+/vendor/class-classes-handler.php
+/vendor/class-files-handler.php
+/vendor/class-plugins-handler.php
diff --git a/packages/autoloader/src/AutoloadGenerator.php b/packages/autoloader/src/AutoloadGenerator.php
index 2dc2047e0cfdf..6d9b9445b2450 100644
--- a/packages/autoloader/src/AutoloadGenerator.php
+++ b/packages/autoloader/src/AutoloadGenerator.php
@@ -103,6 +103,18 @@ public function dump(
file_put_contents( $vendorPath . '/autoload_functions.php', $this->getAutoloadPackageFile( 'functions.php', $suffix ) );
$this->io->writeError( 'Generated ' . $vendorPath . '/autoload_functions.php', true );
+
+ file_put_contents( $vendorPath . '/class-autoloader-handler.php', $this->getAutoloadPackageFile( 'class-autoloader-handler.php', $suffix ) );
+ $this->io->writeError( 'Generated ' . $vendorPath . '/class-autoloader-handler.php', true );
+
+ file_put_contents( $vendorPath . '/class-classes-handler.php', $this->getAutoloadPackageFile( 'class-classes-handler.php', $suffix ) );
+ $this->io->writeError( 'Generated ' . $vendorPath . '/class-classes-handler.php', true );
+
+ file_put_contents( $vendorPath . '/class-files-handler.php', $this->getAutoloadPackageFile( 'class-files-handler.php', $suffix ) );
+ $this->io->writeError( 'Generated ' . $vendorPath . '/class-files-handler.php', true );
+
+ file_put_contents( $vendorPath . '/class-plugins-handler.php', $this->getAutoloadPackageFile( 'class-plugins-handler.php', $suffix ) );
+ $this->io->writeError( 'Generated ' . $vendorPath . '/class-plugins-handler.php', true );
}
/**
@@ -330,7 +342,7 @@ private function getAutoloadFilesPackagesFile( $filesMap ) {
*/
private function getAutoloadPackageFile( $filename, $suffix ) {
$header = self::COMMENT;
- $header .= PHP_EOL . PHP_EOL;
+ $header .= PHP_EOL;
$header .= 'namespace Automattic\Jetpack\Autoloader\jp' . $suffix . ';';
$header .= PHP_EOL . PHP_EOL;
diff --git a/packages/autoloader/src/class-autoloader-handler.php b/packages/autoloader/src/class-autoloader-handler.php
new file mode 100644
index 0000000000000..5fde0720b9841
--- /dev/null
+++ b/packages/autoloader/src/class-autoloader-handler.php
@@ -0,0 +1,120 @@
+plugins_handler = $plugins_handler;
+ }
+
+ /**
+ * Finds the latest installed autoloader.
+ */
+ public function find_latest_autoloader() {
+ global $jetpack_autoloader_latest_version;
+
+ $current_autoloader_path = trailingslashit( dirname( __FILE__ ) ) . 'autoload_packages.php';
+
+ $selected_autoloader_version = null;
+ $selected_autoloader_path = null;
+
+ $active_plugins = $this->plugins_handler->get_all_active_plugins();
+
+ foreach ( $active_plugins as $plugin ) {
+ $plugin_path = plugin_dir_path( trailingslashit( WP_PLUGIN_DIR ) . $plugin );
+ $classmap_path = trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_classmap.php';
+
+ if ( file_exists( $classmap_path ) ) {
+ $packages = require $classmap_path;
+
+ $compare_version = $packages['Automattic\\Jetpack\\Autoloader\\AutoloadGenerator']['version'];
+ $compare_path = trailingslashit( $plugin_path ) . 'vendor/autoload_packages.php';
+
+ // TODO: This comparison needs to properly handle dev versions.
+ if ( version_compare( $selected_autoloader_version, $compare_version, '<' ) ) {
+ $selected_autoloader_version = $compare_version;
+ $selected_autoloader_path = $compare_path;
+ }
+ }
+ }
+
+ $jetpack_autoloader_latest_version = $selected_autoloader_version;
+ if ( $current_autoloader_path !== $selected_autoloader_path ) {
+ require $selected_autoloader_path;
+ }
+ }
+
+ /**
+ * Get this autoloader's package version.
+ *
+ * @return String The autoloader's package version.
+ */
+ public function get_current_autoloader_version() {
+ $classmap_file = trailingslashit( dirname( __FILE__ ) ) . 'composer/jetpack_autoload_classmap.php';
+ $autoloader_packages = require $classmap_file;
+
+ return $autoloader_packages['Automattic\\Jetpack\\Autoloader\\AutoloadGenerator']['version'];
+ }
+
+
+ /**
+ * Updates the spl autoloader chain:
+ * - Registers this namespace's autoloader function.
+ * - If a v1 autoloader function is registered, moves it to the end of the chain.
+ * - Removes any other v2 autoloader functions that have already been registered. This
+ * can occur when the autoloader is being reset by an activating plugin.
+ */
+ public function update_autoloader_chain() {
+ spl_autoload_register( __NAMESPACE__ . '\autoloader' );
+
+ $autoload_chain = spl_autoload_functions();
+
+ foreach ( $autoload_chain as $autoloader ) {
+ if ( ! is_string( $autoloader ) ) {
+ /*
+ * The Jetpack Autoloader functions are registered as strings, so
+ * just continue if $autoloader isn't a string.
+ */
+ continue;
+ }
+
+ if ( self::V1_AUTOLOADER_NAME === $autoloader ) {
+ // Move the v1.* autoloader function to the end of the spl autoloader chain.
+ spl_autoload_unregister( $autoloader );
+ spl_autoload_register( $autoloader );
+
+ } elseif (
+ self::V2_AUTOLOADER_BASE === substr( $autoloader, 0, strlen( self::V2_AUTOLOADER_BASE ) )
+ && __NAMESPACE__ !== substr( $autoloader, 0, strlen( __NAMESPACE__ ) )
+ ) {
+ // Unregister any other v2.* autoloader functions if they're in the chain.
+ spl_autoload_unregister( $autoloader );
+ }
+ }
+ }
+}
diff --git a/packages/autoloader/src/class-classes-handler.php b/packages/autoloader/src/class-classes-handler.php
new file mode 100644
index 0000000000000..84329f50e18d6
--- /dev/null
+++ b/packages/autoloader/src/class-classes-handler.php
@@ -0,0 +1,86 @@
+plugins_handler = $plugins_handler;
+ }
+
+ /**
+ * Adds the version of a package to the $jetpack_packages_classmap global
+ * array so that the autoloader is able to find it.
+ *
+ * @param string $class_name Name of the class that you want to autoload.
+ * @param string $version Version of the class.
+ * @param string $path Absolute path to the class so that we can load it.
+ */
+ public function enqueue_package_class( $class_name, $version, $path ) {
+ global $jetpack_packages_classmap;
+
+ if ( ! isset( $jetpack_packages_classmap[ $class_name ] ) ) {
+ $jetpack_packages_classmap[ $class_name ] = array(
+ 'version' => $version,
+ 'path' => $path,
+ );
+
+ return;
+ }
+ // If we have a @dev version set always use that one!
+ if ( 'dev-' === substr( $jetpack_packages_classmap[ $class_name ]['version'], 0, 4 ) ) {
+ return;
+ }
+
+ // Always favour the @dev version. Since that version is the same as bleeding edge.
+ // We need to make sure that we don't do this in production!
+ if ( 'dev-' === substr( $version, 0, 4 ) ) {
+ $jetpack_packages_classmap[ $class_name ] = array(
+ 'version' => $version,
+ 'path' => $path,
+ );
+
+ return;
+ }
+ // Set the latest version!
+ if ( version_compare( $jetpack_packages_classmap[ $class_name ]['version'], $version, '<' ) ) {
+ $jetpack_packages_classmap[ $class_name ] = array(
+ 'version' => $version,
+ 'path' => $path,
+ );
+ }
+ }
+
+ /**
+ * Initializes the classmap.
+ */
+ public function set_class_paths() {
+ $paths = $this->plugins_handler->get_active_plugins_paths();
+
+ foreach ( $paths as $path ) {
+ if ( is_readable( $path['class'] ) ) {
+ $class_map = require $path['class'];
+
+ if ( is_array( $class_map ) ) {
+ foreach ( $class_map as $class_name => $class_info ) {
+ $this->enqueue_package_class( $class_name, $class_info['version'], $class_info['path'] );
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/autoloader/src/class-files-handler.php b/packages/autoloader/src/class-files-handler.php
new file mode 100644
index 0000000000000..43548d65f1a0b
--- /dev/null
+++ b/packages/autoloader/src/class-files-handler.php
@@ -0,0 +1,100 @@
+plugins_handler = $plugins_handler;
+ }
+
+ /**
+ * Adds the version of a package file to the $jetpack_packages_filemap global
+ * array so that we can load the most recent version.
+ *
+ * @param string $file_identifier Unique id to file assigned by composer based on package name and filename.
+ * @param string $version Version of the file.
+ * @param string $path Absolute path to the file so that we can load it.
+ */
+ public function enqueue_package_file( $file_identifier, $version, $path ) {
+ global $jetpack_packages_filemap;
+
+ if ( ! isset( $jetpack_packages_filemap[ $file_identifier ] ) ) {
+ $jetpack_packages_filemap[ $file_identifier ] = array(
+ 'version' => $version,
+ 'path' => $path,
+ );
+
+ return;
+ }
+ // If we have a @dev version set always use that one!
+ if ( 'dev-' === substr( $jetpack_packages_filemap[ $file_identifier ]['version'], 0, 4 ) ) {
+ return;
+ }
+
+ // Always favour the @dev version. Since that version is the same as bleeding edge.
+ // We need to make sure that we don't do this in production!
+ if ( 'dev-' === substr( $version, 0, 4 ) ) {
+ $jetpack_packages_filemap[ $file_identifier ] = array(
+ 'version' => $version,
+ 'path' => $path,
+ );
+
+ return;
+ }
+ // Set the latest version!
+ if ( version_compare( $jetpack_packages_filemap[ $file_identifier ]['version'], $version, '<' ) ) {
+ $jetpack_packages_filemap[ $file_identifier ] = array(
+ 'version' => $version,
+ 'path' => $path,
+ );
+ }
+ }
+
+ /**
+ * Initializes the filemap.
+ */
+ public function set_file_paths() {
+ $paths = $this->plugins_handler->get_active_plugins_paths();
+
+ foreach ( $paths as $path ) {
+ if ( is_readable( $path['file'] ) ) {
+ $file_map = require $path['file'];
+
+ if ( is_array( $file_map ) ) {
+ foreach ( $file_map as $file_identifier => $file_data ) {
+ $this->enqueue_package_file( $file_identifier, $file_data['version'], $file_data['path'] );
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Include latest version of all enqueued files.
+ */
+ public function file_loader() {
+ global $jetpack_packages_filemap;
+ foreach ( $jetpack_packages_filemap as $file_identifier => $file_data ) {
+ if ( empty( $GLOBALS['__composer_autoload_files'][ $file_identifier ] ) ) {
+ require_once $file_data['path'];
+
+ $GLOBALS['__composer_autoload_files'][ $file_identifier ] = true;
+ }
+ }
+ }
+}
diff --git a/packages/autoloader/src/class-plugins-handler.php b/packages/autoloader/src/class-plugins-handler.php
new file mode 100644
index 0000000000000..52c802528465e
--- /dev/null
+++ b/packages/autoloader/src/class-plugins-handler.php
@@ -0,0 +1,146 @@
+get_all_activating_plugins() ) );
+
+ return $plugins;
+ }
+
+ /**
+ * Creates an array containing the paths to the classmap and filemap for the given plugin.
+ * The classmap and filemap filenames are the names of the files generated by Jetpack
+ * Autoloader with versions >=2.0.
+ *
+ * @param String $plugin The plugin string.
+ * @return Array An array containing the paths to the plugin's classmap and filemap.
+ */
+ public function create_map_path_array( $plugin ) {
+ $plugin_path = plugin_dir_path( trailingslashit( WP_PLUGIN_DIR ) . $plugin );
+
+ return array(
+ 'class' => trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_classmap.php',
+ 'file' => trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_filemap.php',
+ );
+ }
+
+ /**
+ * Returns an array containing the paths to the classmap and filemap for the active plugins.
+ */
+ public function get_active_plugins_paths() {
+ $active_plugins = $this->get_all_active_plugins();
+ return array_map( array( $this, 'create_map_path_array' ), $active_plugins );
+ }
+
+ /**
+ * Checks whether the autoloader should be reset. The autoloader should be reset
+ * when a plugin is activating via a method other than a request, for example
+ * using WP-CLI. When this occurs, the activating plugin was not known when
+ * the autoloader selected the package versions for the classmap and filemap
+ * globals, so the autoloader must reselect the versions.
+ *
+ * If the current plugin is not already known, this method will add it to the
+ * $jetpack_autoloader_activating_plugins global.
+ *
+ * @return Boolean True if the autoloder must be reset, else false.
+ */
+ public function should_autoloader_reset() {
+ global $jetpack_autoloader_activating_plugins;
+
+ $plugins = $this->get_all_active_plugins();
+ $current_plugin = $this->get_current_plugin();
+ $plugin_unknown = ! in_array( $current_plugin, $plugins, true );
+
+ if ( $plugin_unknown ) {
+ // If the current plugin isn't known, add it to the activating plugins list.
+ $jetpack_autoloader_activating_plugins[] = $current_plugin;
+ }
+
+ return $plugin_unknown;
+ }
+
+ /**
+ * Returns the names of activating plugins if the plugins are activating via a request.
+ *
+ * @return Array The array of the activating plugins or empty array.
+ */
+ private function get_plugins_activating_via_request() {
+
+ // phpcs:disable WordPress.Security.NonceVerification.Recommended
+
+ $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : false;
+ $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : false;
+ $nonce = isset( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : false;
+
+ /**
+ * Note: we're not actually checking the nonce here becase it's too early
+ * in the execution. The pluggable functions are not yet loaded to give
+ * plugins a chance to plug their versions. Therefore we're doing the bare
+ * minimum: checking whether the nonce exists and it's in the right place.
+ * The request will fail later if the nonce doesn't pass the check.
+ */
+
+ // In case of a single plugin activation there will be a plugin slug.
+ if ( 'activate' === $action && ! empty( $nonce ) ) {
+ return array( wp_unslash( $plugin ) );
+ }
+
+ $plugins = isset( $_REQUEST['checked'] ) ? $_REQUEST['checked'] : array();
+
+ // In case of bulk activation there will be an array of plugins.
+ if ( 'activate-selected' === $action && ! empty( $nonce ) ) {
+ return array_map( 'wp_unslash', $plugins );
+ }
+
+ // phpcs:enable WordPress.Security.NonceVerification.Recommended
+
+ return array();
+ }
+
+ /**
+ * Returns an array of the names of all known activating plugins. This includes
+ * plugins activating via a request and plugins that are activating via other
+ * methods.
+ *
+ * @return Array The array of all activating plugins or empty array.
+ */
+ private function get_all_activating_plugins() {
+ global $jetpack_autoloader_activating_plugins;
+
+ $activating_plugins = $this->get_plugins_activating_via_request();
+ return array_unique( array_merge( $activating_plugins, $jetpack_autoloader_activating_plugins ) );
+ }
+
+ /**
+ * Returns the name of the current plugin.
+ *
+ * @return String The name of the current plugin.
+ */
+ public function get_current_plugin() {
+ if ( ! function_exists( 'get_plugins' ) ) {
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
+ }
+
+ $dir = explode( '/', plugin_basename( __FILE__ ) )[0];
+ $file = array_keys( get_plugins( "/$dir" ) )[0];
+ return "$dir/$file";
+ }
+}
diff --git a/packages/autoloader/src/functions.php b/packages/autoloader/src/functions.php
index 014bfeb17793b..cb6379b0f5969 100644
--- a/packages/autoloader/src/functions.php
+++ b/packages/autoloader/src/functions.php
@@ -3,6 +3,7 @@
global $jetpack_packages_classmap;
global $jetpack_packages_filemap;
+global $jetpack_autoloader_activating_plugins;
if ( ! is_array( $jetpack_packages_classmap ) ) {
$jetpack_packages_classmap = array();
@@ -12,104 +13,8 @@
$jetpack_packages_filemap = array();
}
-/**
- * Adds the version of a package to the $jetpack_packages global array so that
- * the autoloader is able to find it.
- *
- * @param string $class_name Name of the class that you want to autoload.
- * @param string $version Version of the class.
- * @param string $path Absolute path to the class so that we can load it.
- */
-function enqueue_package_class( $class_name, $version, $path ) {
- global $jetpack_packages_classmap;
-
- if ( ! isset( $jetpack_packages_classmap[ $class_name ] ) ) {
- $jetpack_packages_classmap[ $class_name ] = array(
- 'version' => $version,
- 'path' => $path,
- );
-
- return;
- }
- // If we have a @dev version set always use that one!
- if ( 'dev-' === substr( $jetpack_packages_classmap[ $class_name ]['version'], 0, 4 ) ) {
- return;
- }
-
- // Always favour the @dev version. Since that version is the same as bleeding edge.
- // We need to make sure that we don't do this in production!
- if ( 'dev-' === substr( $version, 0, 4 ) ) {
- $jetpack_packages_classmap[ $class_name ] = array(
- 'version' => $version,
- 'path' => $path,
- );
-
- return;
- }
- // Set the latest version!
- if ( version_compare( $jetpack_packages_classmap[ $class_name ]['version'], $version, '<' ) ) {
- $jetpack_packages_classmap[ $class_name ] = array(
- 'version' => $version,
- 'path' => $path,
- );
- }
-}
-
-/**
- * Adds the version of a package file to the $jetpack_packages_filemap global array so that
- * we can load the most recent version after 'plugins_loaded'.
- *
- * @param string $file_identifier Unique id to file assigned by composer based on package name and filename.
- * @param string $version Version of the file.
- * @param string $path Absolute path to the file so that we can load it.
- */
-function enqueue_package_file( $file_identifier, $version, $path ) {
- global $jetpack_packages_filemap;
-
- if ( ! isset( $jetpack_packages_filemap[ $file_identifier ] ) ) {
- $jetpack_packages_filemap[ $file_identifier ] = array(
- 'version' => $version,
- 'path' => $path,
- );
-
- return;
- }
- // If we have a @dev version set always use that one!
- if ( 'dev-' === substr( $jetpack_packages_filemap[ $file_identifier ]['version'], 0, 4 ) ) {
- return;
- }
-
- // Always favour the @dev version. Since that version is the same as bleeding edge.
- // We need to make sure that we don't do this in production!
- if ( 'dev-' === substr( $version, 0, 4 ) ) {
- $jetpack_packages_filemap[ $file_identifier ] = array(
- 'version' => $version,
- 'path' => $path,
- );
-
- return;
- }
- // Set the latest version!
- if ( version_compare( $jetpack_packages_filemap[ $file_identifier ]['version'], $version, '<' ) ) {
- $jetpack_packages_filemap[ $file_identifier ] = array(
- 'version' => $version,
- 'path' => $path,
- );
- }
-}
-
-/**
- * Include latest version of all enqueued files. Should be called after all plugins are loaded.
- */
-function file_loader() {
- global $jetpack_packages_filemap;
- foreach ( $jetpack_packages_filemap as $file_identifier => $file_data ) {
- if ( empty( $GLOBALS['__composer_autoload_files'][ $file_identifier ] ) ) {
- require_once $file_data['path'];
-
- $GLOBALS['__composer_autoload_files'][ $file_identifier ] = true;
- }
- }
+if ( ! is_array( $jetpack_autoloader_activating_plugins ) ) {
+ $jetpack_autoloader_activating_plugins = array();
}
/**
@@ -132,207 +37,55 @@ function autoloader( $class_name ) {
/**
* Used for running the code that initializes class and file maps.
- */
-function enqueue_files() {
- $active_plugins = get_active_plugins();
- $paths = array_map( __NAMESPACE__ . '\create_map_path_array', $active_plugins );
-
- foreach ( $paths as $path ) {
- if ( is_readable( $path['class'] ) ) {
- $class_map = require $path['class'];
-
- if ( is_array( $class_map ) ) {
- foreach ( $class_map as $class_name => $class_info ) {
- enqueue_package_class( $class_name, $class_info['version'], $class_info['path'] );
- }
- }
- }
-
- if ( is_readable( $path['file'] ) ) {
- $file_map = require $path['file'];
-
- if ( is_array( $file_map ) ) {
- foreach ( $file_map as $file_identifier => $file_data ) {
- enqueue_package_file( $file_identifier, $file_data['version'], $file_data['path'] );
- }
- }
- }
- }
-
- file_loader();
-}
-
-/**
- * Returns an array containing the active plugins. If plugin is activating, it
- * is included in the array.
*
- * @return Array An array of plugin names as strings.
+ * @param Plugins_Handler $plugins_handler The Plugins_Handler object.
*/
-function get_active_plugins() {
- $active_plugins = array_merge(
- is_multisite()
- ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) )
- : array(),
- (array) get_option( 'active_plugins', array() )
- );
- $current_plugin = get_current_plugin();
+function enqueue_files( $plugins_handler ) {
+ require_once __DIR__ . '/class-classes-handler.php';
+ require_once __DIR__ . '/class-files-handler.php';
- if ( ! in_array( $current_plugin, $active_plugins, true ) ) {
- // The current plugin isn't active, so it must be activating. Add it to the list.
- $active_plugins[] = $current_plugin;
- }
+ $classes_handler = new Classes_Handler( $plugins_handler );
+ $classes_handler->set_class_paths();
- // If the activating plugin is not the only activating plugin, we need to add others too.
- $active_plugins = array_unique( array_merge( $active_plugins, get_activating_plugins() ) );
+ $files_handler = new Files_Handler( $plugins_handler );
+ $files_handler->set_file_paths();
- return $active_plugins;
+ $files_handler->file_loader();
}
/**
- * Creates an array containing the paths to the classmap and filemap for the given plugin.
- * The filenames are the names of the files generated by the Jetpack Autoloader version >2.0.
- *
- * @param String $plugin The plugin string.
- * @return Array An array containing the paths to the plugin's classmap and filemap.
- */
-function create_map_path_array( $plugin ) {
- $plugin_path = plugin_dir_path( trailingslashit( WP_PLUGIN_DIR ) . $plugin );
-
- return array(
- 'class' => trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_classmap.php',
- 'file' => trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_filemap.php',
- );
-}
-
-/**
- * Checks whether the current plugin is active.
- *
- * @return Boolean True if the current plugin is active, else false.
- */
-function is_current_plugin_active() {
- $active_plugins = (array) get_option( 'active_plugins', array() );
- $current_plugin = get_current_plugin();
-
- return in_array( $current_plugin, $active_plugins, true );
-}
-
-/**
- * Returns the name of activating plugin if a plugin is activating via a request.
- *
- * @return Array The array of the activating plugins or empty array.
- */
-function get_activating_plugins() {
-
- // phpcs:disable WordPress.Security.NonceVerification.Recommended
-
- $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : false;
- $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : false;
- $nonce = isset( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : false;
-
- /**
- * Note: we're not actually checking the nonce here becase it's too early
- * in the execution. The pluggable functions are not yet loaded to give
- * plugins a chance to plug their versions. Therefore we're doing the bare
- * minimum: checking whether the nonce exists and it's in the right place.
- * The request will fail later if the nonce doesn't pass the check.
- */
-
- // In case of a single plugin activation there will be a plugin slug.
- if ( 'activate' === $action && ! empty( $nonce ) ) {
- return array( wp_unslash( $plugin ) );
- }
-
- $plugins = isset( $_REQUEST['checked'] ) ? $_REQUEST['checked'] : array();
-
- // In case of bulk activation there will be an array of plugins.
- if ( 'activate-selected' === $action && ! empty( $nonce ) ) {
- return array_map( 'wp_unslash', $plugins );
- }
-
- // phpcs:enable WordPress.Security.NonceVerification.Recommended
-
- return array();
-}
-
-/**
- * Returns the name of the current plugin.
- *
- * @return String The name of the current plugin.
- */
-function get_current_plugin() {
- if ( ! function_exists( 'get_plugins' ) ) {
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
- }
-
- $dir = explode( '/', plugin_basename( __FILE__ ) )[0];
- $file = array_keys( get_plugins( "/$dir" ) )[0];
- return "$dir/$file";
-}
-
-/**
- * Find the latest installed autoloader and set up the classmap and filemap.
+ * Finds the latest installed autoloader. If this is the latest autoloader, sets
+ * up the classmap and filemap.
*/
function set_up_autoloader() {
- global $latest_autoloader_version;
+ global $jetpack_autoloader_latest_version;
global $jetpack_packages_classmap;
- if ( ! is_current_plugin_active() ) {
- // The current plugin is activating, so reset the autoloader.
- $latest_autoloader_version = null;
- $jetpack_packages_classmap = array();
- }
+ require_once __DIR__ . '/class-plugins-handler.php';
+ require_once __DIR__ . '/class-autoloader-handler.php';
- $classmap_file = trailingslashit( dirname( __FILE__ ) ) . 'composer/jetpack_autoload_classmap.php';
- $autoloader_packages = require $classmap_file;
+ $plugins_handler = new Plugins_Handler();
+ $autoloader_handler = new Autoloader_Handler( $plugins_handler );
- $current_autoloader_version = $autoloader_packages['Automattic\\Jetpack\\Autoloader\\AutoloadGenerator']['version'];
- $current_autoloader_path = trailingslashit( dirname( __FILE__ ) ) . 'autoload_packages.php';
+ if ( $plugins_handler->should_autoloader_reset() ) {
+ /*
+ * The autoloader must be reset when an activating plugin that was
+ * previously unknown is detected.
+ */
+ $jetpack_autoloader_latest_version = null;
+ $jetpack_packages_classmap = array();
+ }
// Find the latest autoloader.
- if ( ! $latest_autoloader_version ) {
- $autoloader_version = $current_autoloader_version;
- $autoloader_path = $current_autoloader_path;
- $current_plugin = get_current_plugin();
-
- $active_plugins = get_active_plugins();
-
- foreach ( $active_plugins as $plugin ) {
- if ( $current_plugin === $plugin ) {
- continue;
- }
-
- $plugin_path = plugin_dir_path( trailingslashit( WP_PLUGIN_DIR ) . $plugin );
- $classmap_path = trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_classmap.php';
- if ( file_exists( $classmap_path ) ) {
- $packages = require $classmap_path;
-
- $current_version = $packages['Automattic\\Jetpack\\Autoloader\\AutoloadGenerator']['version'];
-
- // TODO: This comparison needs to properly handle dev versions.
- if ( version_compare( $autoloader_version, $current_version, '<' ) ) {
- $autoloader_version = $current_version;
- $autoloader_path = trailingslashit( $plugin_path ) . 'vendor/autoload_packages.php';
- }
- }
- }
-
- $latest_autoloader_version = $autoloader_version;
- if ( $current_autoloader_path !== $autoloader_path ) {
- require $autoloader_path;
- }
+ if ( ! $jetpack_autoloader_latest_version ) {
+ $autoloader_handler->find_latest_autoloader();
}
- // This is the latest autoloader, so generate the classmap and filemap and register the autoloader function.
- if ( empty( $jetpack_packages_classmap ) && $current_autoloader_version === $latest_autoloader_version ) {
- enqueue_files();
-
- spl_autoload_register( __NAMESPACE__ . '\autoloader' );
+ $current_autoloader_version = $autoloader_handler->get_current_autoloader_version();
- $autoload_chain = spl_autoload_functions();
- if ( in_array( 'Automattic\Jetpack\Autoloader\autoloader', $autoload_chain, true ) ) {
- // Move the old autoloader function to the end of the spl autoloader chaain.
- spl_autoload_unregister( 'Automattic\Jetpack\Autoloader\autoloader' );
- spl_autoload_register( 'Automattic\Jetpack\Autoloader\autoloader' );
- }
+ // This is the latest autoloader, so generate the classmap and filemap and register the autoloader function.
+ if ( empty( $jetpack_packages_classmap ) && $current_autoloader_version === $jetpack_autoloader_latest_version ) {
+ enqueue_files( $plugins_handler );
+ $autoloader_handler->update_autoloader_chain();
}
}
diff --git a/packages/autoloader/tests/php/bootstrap.php b/packages/autoloader/tests/php/bootstrap.php
index 4a207582ff475..a839287b5eabd 100644
--- a/packages/autoloader/tests/php/bootstrap.php
+++ b/packages/autoloader/tests/php/bootstrap.php
@@ -20,3 +20,6 @@ function trailingslashit( $string ) {
require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../../src/functions.php';
+require_once __DIR__ . '/../../src/class-plugins-handler.php';
+require_once __DIR__ . '/../../src/class-classes-handler.php';
+require_once __DIR__ . '/../../src/class-files-handler.php';
diff --git a/packages/autoloader/tests/php/test_Autoloader.php b/packages/autoloader/tests/php/test_Autoloader.php
index 86a7715ba1735..372839478b071 100644
--- a/packages/autoloader/tests/php/test_Autoloader.php
+++ b/packages/autoloader/tests/php/test_Autoloader.php
@@ -18,7 +18,7 @@ class WP_Test_Autoloader extends TestCase {
*/
public function setup() {
parent::setup();
-
+ $this->classes_handler = new Classes_Handler( new Plugins_Handler() );
spl_autoload_register( 'autoloader' );
}
@@ -26,7 +26,7 @@ public function setup() {
* Tests whether enqueueing adds a class to the global array.
*/
public function test_enqueueing_adds_to_the_global_array() {
- enqueue_package_class( 'className', '1', 'path_to_class' );
+ $this->classes_handler->enqueue_package_class( 'className', '1', 'path_to_class' );
global $jetpack_packages_classmap;
$this->assertTrue( isset( $jetpack_packages_classmap['className'] ) );
@@ -38,8 +38,8 @@ public function test_enqueueing_adds_to_the_global_array() {
* Tests whether enqueueing adds the latest class version to the global array.
*/
public function test_enqueueing_adds_the_latest_version_to_the_global_array() {
- enqueue_package_class( 'className', '1', 'path_to_class' );
- enqueue_package_class( 'className', '2', 'path_to_class_v2' );
+ $this->classes_handler->enqueue_package_class( 'className', '1', 'path_to_class' );
+ $this->classes_handler->enqueue_package_class( 'className', '2', 'path_to_class_v2' );
global $jetpack_packages_classmap;
$this->assertTrue( isset( $jetpack_packages_classmap['className'] ) );
@@ -53,9 +53,9 @@ public function test_enqueueing_adds_the_latest_version_to_the_global_array() {
*/
public function test_enqueueing_always_adds_the_dev_version_to_the_global_array() {
- enqueue_package_class( 'className', '1', 'path_to_class' );
- enqueue_package_class( 'className', 'dev-howdy', 'path_to_class_dev' );
- enqueue_package_class( 'className', '2', 'path_to_class_v2' );
+ $this->classes_handler->enqueue_package_class( 'className', '1', 'path_to_class' );
+ $this->classes_handler->enqueue_package_class( 'className', 'dev-howdy', 'path_to_class_dev' );
+ $this->classes_handler->enqueue_package_class( 'className', '2', 'path_to_class_v2' );
global $jetpack_packages_classmap;
$this->assertTrue( isset( $jetpack_packages_classmap['className'] ) );
@@ -67,7 +67,7 @@ public function test_enqueueing_always_adds_the_dev_version_to_the_global_array(
* Tests whether enqueueing works with autoloading.
*/
public function test_enqueue_class_to_autoload_works_as_expected() {
- enqueue_package_class( 'Jetpack\TestCase_ABC\className_ABC', '1', dirname( __FILE__ ) . '/path_to_class.php' );
+ $this->classes_handler->enqueue_package_class( 'Jetpack\TestCase_ABC\className_ABC', '1', dirname( __FILE__ ) . '/path_to_class.php' );
$class = new className_ABC();
diff --git a/packages/autoloader/tests/php/test_file_loader.php b/packages/autoloader/tests/php/test_file_loader.php
index cdf73902db059..c7dafa2e948c6 100644
--- a/packages/autoloader/tests/php/test_file_loader.php
+++ b/packages/autoloader/tests/php/test_file_loader.php
@@ -12,11 +12,19 @@
*/
class WP_Test_File_Loader extends TestCase {
+ /**
+ * Setup runs before each test.
+ */
+ public function setUp() {
+ parent::setUp();
+ $this->files_handler = new Files_Handler( new Plugins_Handler() );
+ }
+
/**
* Tests whether enqueueing adds a file to the global array.
*/
public function test_enqueueing_adds_to_the_global_array() {
- enqueue_package_file( 'file_id_10', '1', 'path_to_file.php' );
+ $this->files_handler->enqueue_package_file( 'file_id_10', '1', 'path_to_file.php' );
global $jetpack_packages_filemap;
$this->assertTrue( isset( $jetpack_packages_filemap['file_id_10'] ) );
@@ -28,8 +36,8 @@ public function test_enqueueing_adds_to_the_global_array() {
* Tests whether enqueueing adds the latest file version to the global array.
*/
public function test_enqueueing_adds_the_latest_version_to_the_global_array() {
- enqueue_package_file( 'file_id', '1', 'path_to_file' );
- enqueue_package_file( 'file_id', '2', 'path_to_file_v2' );
+ $this->files_handler->enqueue_package_file( 'file_id', '1', 'path_to_file' );
+ $this->files_handler->enqueue_package_file( 'file_id', '2', 'path_to_file_v2' );
global $jetpack_packages_filemap;
$this->assertTrue( isset( $jetpack_packages_filemap['file_id'] ) );
@@ -42,9 +50,9 @@ public function test_enqueueing_adds_the_latest_version_to_the_global_array() {
*/
public function test_enqueueing_always_adds_the_dev_version_to_the_global_array() {
- enqueue_package_file( 'file_id', '1', 'path_to_file' );
- enqueue_package_file( 'file_id', 'dev-howdy', 'path_to_file_dev' );
- enqueue_package_file( 'file_id', '2', 'path_to_file_v2' );
+ $this->files_handler->enqueue_package_file( 'file_id', '1', 'path_to_file' );
+ $this->files_handler->enqueue_package_file( 'file_id', 'dev-howdy', 'path_to_file_dev' );
+ $this->files_handler->enqueue_package_file( 'file_id', '2', 'path_to_file_v2' );
global $jetpack_packages_filemap;
$this->assertTrue( isset( $jetpack_packages_filemap['file_id'] ) );
@@ -57,15 +65,15 @@ public function test_enqueueing_always_adds_the_dev_version_to_the_global_array(
*/
public function test_enqueued_file_is_actually_loaded() {
- enqueue_package_file( 'file_id', '1', __DIR__ . '/path_to_file.php' );
+ $this->files_handler->enqueue_package_file( 'file_id', '1', __DIR__ . '/path_to_file.php' );
- file_loader();
+ $this->files_handler->file_loader();
$this->assertTrue( function_exists( 'if_i_exist_then_this_test_passed' ) );
$this->assertTrue( if_i_exist_then_this_test_passed() );
- enqueue_package_file( 'file_id', '2', __DIR__ . '/bogus_path_to_file.php' );
+ $this->files_handler->enqueue_package_file( 'file_id', '2', __DIR__ . '/bogus_path_to_file.php' );
- file_loader(); // file_loader should not include same file twice.
+ $this->files_handler->file_loader(); // file_loader should not include same file twice.
$this->assertTrue( if_i_exist_then_this_test_passed() );
}