diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c961598
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,24 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+
+# WordPress Coding Standards
+# https://make.wordpress.org/core/handbook/coding-standards/
+
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = tab
+
+[*.yml]
+indent_style = space
+indent_size = 2
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.txt]
+end_of_line = crlf
diff --git a/.gitattributes b/.gitattributes
index 4e632c3..5e7d7a3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,6 +2,7 @@
.gitattributes export-ignore
.gitignore export-ignore
+.editorconfig export-ignore
composer.lock export-ignore
.phpcs.xml export-ignore
.phpcs.xml.dist export-ignore
diff --git a/CHANGES.md b/CHANGES.md
index 3661fb0..a60811c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,10 @@
[unreleased]
+#### 1.14.0 / 2023-07-19
+* update _More details_ link
+* fixed strange error between slug from different sources in PD part 2
+* update JS to correctly display Plugin Card button, thanks @costdev
+
#### 1.13.0 / 2023-07-10
* update version check
* simplify plugin card notice
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 1751c36..eee6a4b 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -10,6 +10,7 @@
*/node_modules/*
*/tests/*
*/test-plugins/*
+ *.js
diff --git a/plugin.php b/plugin.php
index 0955e66..945d101 100644
--- a/plugin.php
+++ b/plugin.php
@@ -13,7 +13,7 @@
* Plugin URI: https://wordpress.org/plugins/wp-plugin-dependencies
* Description: Parses 'Requires Plugins' header, add plugin install dependencies tab, and information about dependencies.
* Author: Andy Fragen, Colin Stewart, Paul Biron
- * Version: 1.13.0
+ * Version: 1.14.0
* License: MIT
* Network: true
* Requires at least: 6.0
@@ -79,9 +79,6 @@ static function( $class_name ) {
}
);
- // Switch to simple plugin card.
- add_filter( 'pd_simple_card', '__return_true' );
-
if ( ! WP_PLUGIN_DEPENDENCIES1_COMMITTED ) {
require_once __DIR__ . '/wp-admin/includes/class-wp-plugin-dependencies.php';
diff --git a/readme.txt b/readme.txt
index 2577160..a7b452e 100644
--- a/readme.txt
+++ b/readme.txt
@@ -7,7 +7,7 @@ Network: true
Requires at least: 6.0
Requires PHP: 5.6
Tested up to: 6.3
-Stable tag: 1.13.0
+Stable tag: 1.14.0
## Description
@@ -48,6 +48,11 @@ PRs should be made against the `develop` branch.
## Changelog
+#### 1.14.0 / 2023-07-19
+* update _More details_ link
+* fixed strange error between slug from different sources in PD part 2
+* update JS to correctly display Plugin Card button, thanks @costdev
+
#### 1.13.0 / 2023-07-10
* update version check
* simplify plugin card notice
diff --git a/wp-admin/includes/class-wp-plugin-dependencies-2.php b/wp-admin/includes/class-wp-plugin-dependencies-2.php
index ec74bde..8d0eab2 100644
--- a/wp-admin/includes/class-wp-plugin-dependencies-2.php
+++ b/wp-admin/includes/class-wp-plugin-dependencies-2.php
@@ -146,7 +146,11 @@ public function add_plugin_card_dependencies( $response, $action, $args ) {
* @return array
*/
public function upgrader_package_options( $options ) {
- $options['hook_extra']['slug'] = $this->args->slug;
+ if ( isset( $options['hook_extra']['temp_backup'] ) ) {
+ $options['hook_extra']['slug'] = $options['hook_extra']['temp_backup']['slug'];
+ } else {
+ $options['hook_extra']['slug'] = $this->args->slug;
+ }
remove_filter( 'upgrader_package_options', array( $this, 'upgrader_package_options' ), 10 );
return $options;
diff --git a/wp-admin/includes/class-wp-plugin-dependencies.php b/wp-admin/includes/class-wp-plugin-dependencies.php
index 895cc89..7d0e1e4 100644
--- a/wp-admin/includes/class-wp-plugin-dependencies.php
+++ b/wp-admin/includes/class-wp-plugin-dependencies.php
@@ -96,8 +96,11 @@ public function start() {
add_action( 'admin_init', array( $this, 'modify_plugin_row' ), 15 );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
add_action( 'network_admin_notices', array( $this, 'admin_notices' ) );
+
+ add_action( 'wp_ajax_check_plugin_dependencies', array( $this, 'check_plugin_dependencies' ) );
}
$required_headers = $this->parse_plugin_headers();
@@ -127,6 +130,28 @@ public function enqueue_styles() {
}
}
+ /**
+ * Enqueues scripts for plugin dependencies on the "Add New" plugins screen.
+ *
+ * @global string $wp_version The WordPress version string.
+ * @global string $pagenow The filename of the current screen.
+ *
+ * @return void
+ */
+ public function enqueue_scripts() {
+ global $wp_version, $pagenow;
+
+ if ( 'plugin-install.php' === $pagenow ) {
+ wp_enqueue_script(
+ 'wp-plugin-dependencies-updates',
+ plugins_url( 'wp-admin/js/updates.js', 'wp-plugin-dependencies/plugin.php' ),
+ array( 'updates' ),
+ $wp_version,
+ true
+ );
+ }
+ }
+
/**
* Run get_plugins() and store result.
*
@@ -293,7 +318,7 @@ public function empty_plugins_api_result( $res, $action, $args ) {
public function get_dot_org_data() {
global $pagenow;
- if ( ! in_array( $pagenow, array( 'plugin-install.php', 'plugins.php' ), true ) ) {
+ if ( ! wp_doing_ajax() && ! in_array( $pagenow, array( 'plugin-install.php', 'plugins.php' ), true ) ) {
return;
}
@@ -603,10 +628,11 @@ public function plugin_install_description_uninstalled( $description, $plugin )
if ( isset( $plugin_data['name'] ) && ! empty( $plugin_data['version'] ) ) {
$more_details_link[ $slug ] = sprintf(
- '%3$s',
+ '%4$s',
esc_url( $url ),
/* translators: %s: Plugin name. */
esc_attr( sprintf( __( 'More information about %s' ), $plugin_data['name'] ) ),
+ esc_attr( $plugin_data['name'] ),
__( 'More details' )
);
$more_details_link[ $slug ] = esc_attr( $plugin_data['name'] ) . ' ' . $more_details_link[ $slug ];
@@ -1037,6 +1063,69 @@ private function get_requires_plugins_names( $data ) {
return isset( $names ) ? $names : '';
}
+
+ /**
+ * Handles checking plugin dependencies after a plugin is installed via AJAX.
+ */
+ public function check_plugin_dependencies() {
+ check_ajax_referer( 'updates' );
+
+ if ( empty( $_POST['slug'] ) ) {
+ wp_send_json_error(
+ array(
+ 'slug' => '',
+ 'errorCode' => 'no_plugin_specified',
+ 'errorMessage' => __( 'No plugin specified.' ),
+ )
+ );
+ }
+
+ $slug = sanitize_key( wp_unslash( $_POST['slug'] ) );
+ $status = array( 'slug' => $slug );
+
+ if ( ! isset( $this->plugin_dirnames[ $slug ] ) ) {
+ $status['errorCode'] = 'plugin_not_installed';
+ $status['errorMessage'] = __( 'The plugin is not installed.' );
+ wp_send_json_error( $status );
+ }
+
+ $plugin_file = $this->plugin_dirnames[ $slug ];
+
+ if ( ! isset( $this->requires_plugins[ $plugin_file ]['RequiresPlugins'] ) ) {
+ $status['message'] = __( 'The plugin has no required plugins.' );
+ wp_send_json_success( $status );
+ }
+
+ $dependencies = explode( ',', $this->requires_plugins[ $plugin_file ]['RequiresPlugins'] );
+ $inactive_dependencies = array();
+ foreach ( $dependencies as $dependency ) {
+ if ( is_plugin_inactive( $this->plugin_dirnames[ $dependency ] ) ) {
+ $inactive_dependencies[] = $dependency;
+ }
+ }
+
+ if ( ! empty( $inactive_dependencies ) ) {
+ $inactive_dependency_names = array_map(
+ function( $dependency ) {
+ return $this->plugin_data[ $dependency ]['name'];
+ },
+ $inactive_dependencies
+ );
+
+ $status['errorCode'] = 'inactive_dependencies';
+ $status['errorMessage'] = sprintf(
+ /* translators: %s: A list of inactive dependency plugin names. */
+ __( 'The following plugins must be activated first: %s.' ),
+ implode( ', ', $inactive_dependency_names )
+ );
+ $status['errorData'] = array_combine( $inactive_dependencies, $inactive_dependency_names );
+
+ wp_send_json_error( $status );
+ }
+
+ $status['message'] = __( 'All required plugins are installed and activated.' );
+ wp_send_json_success( $status );
+ }
}
( new WP_Plugin_Dependencies() )->start();
diff --git a/wp-admin/includes/plugin-install.php b/wp-admin/includes/plugin-install.php
index 3a98fb3..4cd58bf 100644
--- a/wp-admin/includes/plugin-install.php
+++ b/wp-admin/includes/plugin-install.php
@@ -7,12 +7,14 @@
*
* @package WordPress
* @subpackage Administration
- * @since 6.3.0
+ * @since 6.4.0
*/
/**
* Gets the markup for the plugin install action button.
*
+ * @since 6.4.0
+ *
* @param string $name Plugin name.
* @param array|object $data {
* An array or object of plugin data. Can be retrieved from the API.
@@ -23,7 +25,6 @@
* }
* @param bool $compatible_php The result of a PHP compatibility check.
* @param bool $compatible_wp The result of a WP compatibility check.
- *
* @return string $button The markup for the dependency row button.
*/
function wp_get_plugin_action_button( $name, $data, $compatible_php, $compatible_wp ) {
@@ -54,10 +55,6 @@ function wp_get_plugin_action_button( $name, $data, $compatible_php, $compatible
$all_plugin_dependencies_installed = $installed_plugin_dependencies_count === $plugin_dependencies_count;
$all_plugin_dependencies_active = $active_plugin_dependencies_count === $plugin_dependencies_count;
- if ( apply_filters( 'pd_simple_card', false ) ) {
- $plugin_dependency_met = true;
- }
-
sprintf(
'%s',
esc_attr( $data->slug ),
diff --git a/wp-admin/js/updates.js b/wp-admin/js/updates.js
new file mode 100644
index 0000000..1101c33
--- /dev/null
+++ b/wp-admin/js/updates.js
@@ -0,0 +1,83 @@
+(function( $, wp ) {
+ var $document = $( document ),
+ __ = wp.i18n.__,
+ _x = wp.i18n._x,
+ sprintf = wp.i18n.sprintf;
+
+ wp.updates.installPluginSuccess = function( response ) {
+ var $message = $( '.plugin-card-' + response.slug ).find( '.install-now' );
+
+ $message
+ .removeClass( 'updating-message' )
+ .addClass( 'updated-message installed button-disabled' )
+ .attr(
+ 'aria-label',
+ sprintf(
+ /* translators: %s: Plugin name and version. */
+ _x( '%s installed!', 'plugin' ),
+ response.pluginName
+ )
+ )
+ .text( _x( 'Installed!', 'plugin' ) );
+
+ wp.a11y.speak( __( 'Installation completed successfully.' ) );
+
+ $document.trigger( 'wp-plugin-install-success', response );
+
+ if ( response.activateUrl ) {
+ setTimeout( function() {
+ wp.updates.ajax(
+ 'check_plugin_dependencies',
+ {
+ slug: response.slug,
+ success: function() {
+ // Transform the 'Install' button into an 'Activate' button.
+ $message.removeClass( 'install-now installed button-disabled updated-message' )
+ .addClass( 'activate-now button-primary' )
+ .attr( 'href', response.activateUrl );
+
+ if ( 'plugins-network' === pagenow ) {
+ $message
+ .attr(
+ 'aria-label',
+ sprintf(
+ /* translators: %s: Plugin name. */
+ _x( 'Network Activate %s', 'plugin' ),
+ response.pluginName
+ )
+ )
+ .text( __( 'Network Activate' ) );
+ } else {
+ $message
+ .attr(
+ 'aria-label',
+ sprintf(
+ /* translators: %s: Plugin name. */
+ _x( 'Activate %s', 'plugin' ),
+ response.pluginName
+ )
+ )
+ .text( __( 'Activate' ) );
+ }
+ },
+ error: function( error ) {
+ $message
+ .removeClass( 'install-now installed updated-message' )
+ .addClass( 'activate-now button-primary' )
+ .attr(
+ 'aria-label',
+ sprintf(
+ /* translators: 1: Plugin name, 2. The reason the plugin cannot be activated. */
+ _x( 'Cannot activate %1$s. %2$s', 'plugin' ),
+ response.pluginName,
+ error.errorMessage
+ )
+ )
+ .text( __( 'Cannot Activate' ) );
+ }
+ }
+ );
+ }, 1000 );
+ }
+ };
+})( jQuery, window.wp, window._wpUpdatesSettings );