diff --git a/src/wp-admin/import.php b/src/wp-admin/import.php index ce17a70f20cf3..c999e01a633ff 100644 --- a/src/wp-admin/import.php +++ b/src/wp-admin/import.php @@ -33,12 +33,8 @@ '
' . __( 'Support forums' ) . '
' ); -if ( current_user_can( 'install_plugins' ) ) { - // List of popular importer plugins from the WordPress.org API. - $popular_importers = wp_get_popular_importers(); -} else { - $popular_importers = array(); -} +// List of popular importer plugins from the WordPress.org API. +$popular_importers = wp_get_popular_importers(); // Detect and redirect invalid importers like 'movabletype', which is registered as 'mt'. if ( ! empty( $_GET['invalid'] ) && isset( $popular_importers[ $_GET['invalid'] ] ) ) { @@ -78,25 +74,8 @@ $pop_data ) { - if ( isset( $importers[ $pop_importer ] ) ) { - continue; - } - if ( isset( $importers[ $pop_data['importer-id'] ] ) ) { - continue; - } - - // Fill the array of registered (already installed) importers with data of the popular importers from the WordPress.org API. - $importers[ $pop_data['importer-id'] ] = array( - $pop_data['name'], - $pop_data['description'], - 'install' => $pop_data['plugin-slug'], - ); -} +// Registered importers plus popular importer plugins from the WordPress.org API. +$importers = wp_get_available_importers( $popular_importers ); if ( empty( $importers ) ) { echo '' . __( 'No importers are available.' ) . '
'; // TODO: Make more helpful. @@ -120,24 +99,29 @@ if ( ! empty( $plugins ) ) { $keys = array_keys( $plugins ); $plugin_file = $plugin_slug . '/' . $keys[0]; - $url = wp_nonce_url( - add_query_arg( - array( - 'action' => 'activate', - 'plugin' => $plugin_file, - 'from' => 'import', + + if ( current_user_can( 'activate_plugin', $plugin_file ) ) { + $url = wp_nonce_url( + add_query_arg( + array( + 'action' => 'activate', + 'plugin' => $plugin_file, + 'from' => 'import', + ), + admin_url( 'plugins.php' ) ), - admin_url( 'plugins.php' ) - ), - 'activate-plugin_' . $plugin_file - ); - $action = sprintf( - '%s', - esc_url( $url ), - /* translators: %s: Importer name. */ - esc_attr( sprintf( __( 'Run %s' ), $data[0] ) ), - __( 'Run Importer' ) - ); + 'activate-plugin_' . $plugin_file + ); + $action = sprintf( + '%s', + esc_url( $url ), + /* translators: %s: Importer name. */ + esc_attr( sprintf( __( 'Run %s' ), $data[0] ) ), + __( 'Run Importer' ) + ); + } else { + $action = __( 'This importer is installed but not active. Please activate it from the Plugins screen.' ); + } $is_plugin_installed = true; } diff --git a/src/wp-admin/includes/import.php b/src/wp-admin/includes/import.php index 530045894c745..d84e20716eee7 100644 --- a/src/wp-admin/includes/import.php +++ b/src/wp-admin/includes/import.php @@ -16,12 +16,53 @@ */ function get_importers() { global $wp_importers; + if ( is_array( $wp_importers ) ) { uasort( $wp_importers, '_usort_by_first_member' ); } + return $wp_importers; } +/** + * Retrieves the list of available importers for the Import screen. + * + * This includes registered importers and popular importer plugins from WordPress.org + * that can be installed or activated. + * + * @since 7.1.0 + * + * @param array|null $popular_importers Optional. Popular importer data keyed by slug. + * Defaults to the result of wp_get_popular_importers(). + * @return array Available importers. + */ +function wp_get_available_importers( ?array $popular_importers = null ) { + $importers = get_importers(); + + if ( null === $popular_importers ) { + $popular_importers = wp_get_popular_importers(); + } + + // If a popular importer is not registered, create a dummy registration that links to the plugin installer. + foreach ( $popular_importers as $pop_importer => $pop_data ) { + if ( isset( $importers[ $pop_importer ] ) ) { + continue; + } + + if ( isset( $importers[ $pop_data['importer-id'] ] ) ) { + continue; + } + + $importers[ $pop_data['importer-id'] ] = array( + $pop_data['name'], + $pop_data['description'], + 'install' => $pop_data['plugin-slug'], + ); + } + + return $importers; +} + /** * Sorts a multidimensional array by first member of each top level member. * diff --git a/tests/phpunit/tests/import/import.php b/tests/phpunit/tests/import/import.php index be99ea2f2d87d..2608cf37e495a 100644 --- a/tests/phpunit/tests/import/import.php +++ b/tests/phpunit/tests/import/import.php @@ -9,6 +9,7 @@ class Tests_Import_Import extends WP_UnitTestCase { */ public function test_ordering_of_importers() { global $wp_importers; + $_wp_importers = $wp_importers; // Preserve global state. $wp_importers = array( 'xyz1' => array( 'xyz1' ), @@ -27,6 +28,46 @@ public function test_ordering_of_importers() { ), get_importers() ); + + $wp_importers = $_wp_importers; // Restore global state. + } + + /** + * @covers ::wp_get_available_importers + */ + public function test_wp_get_available_importers_adds_popular_importers() { + global $wp_importers; + + $_wp_importers = $wp_importers; // Preserve global state. + $wp_importers = array( + 'xyz1' => array( 'xyz1', 'Registered importer', '__return_null' ), + ); + + $popular_importers = array( + 'wordpress' => array( + 'name' => 'WordPress', + 'description' => 'Import posts, pages, comments, custom fields, categories, and tags from a WordPress export file.', + 'plugin-slug' => 'wordpress-importer', + 'importer-id' => 'wordpress', + ), + ); + + $available_importers = wp_get_available_importers( $popular_importers ); + + $this->assertArrayHasKey( 'xyz1', $available_importers ); + $this->assertSame( array( 'xyz1', 'Registered importer', '__return_null' ), $available_importers['xyz1'] ); + + // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText -- Importer slugs are lowercase. + $this->assertArrayHasKey( 'wordpress', $available_importers ); + $this->assertSame( + array( + 'WordPress', + 'Import posts, pages, comments, custom fields, categories, and tags from a WordPress export file.', + 'install' => 'wordpress-importer', + ), + $available_importers['wordpress'] + ); + $wp_importers = $_wp_importers; // Restore global state. } }