Skip to content

Commit 13a1c22

Browse files
committed
Merge pull request #327 from thomasgriffin/feature/fix-280-283-github-installs
Adjust plugin directory name for "wrongly" packaged zips.
2 parents 4557660 + e0653ea commit 13a1c22

File tree

2 files changed

+88
-5
lines changed

2 files changed

+88
-5
lines changed

class-tgm-plugin-activation.php

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,9 @@ protected function do_plugin_install() {
552552
$upgrader = new Plugin_Upgrader( $skin = new Plugin_Installer_Skin( compact( 'type', 'title', 'url', 'nonce', 'plugin', 'api' ) ) );
553553

554554
// Perform the action and install the plugin from the $source urldecode().
555+
add_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
555556
$upgrader->install( $source );
557+
remove_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
556558

557559
// Flush plugins cache so we can make sure that the installed plugins list is always up to date.
558560
$this->flush_plugins_cache();
@@ -629,6 +631,73 @@ protected function do_plugin_install() {
629631

630632
}
631633

634+
/**
635+
* Adjust the plugin directory name if necessary.
636+
*
637+
* The final destination directory of a plugin is based on the subdirectory name found in the
638+
* (un)zipped source. In some cases - most notably GitHub repository plugin downloads -, this
639+
* subdirectory name is not the same as the expected slug and the plugin will not be recognized
640+
* as installed. This is fixed by adjusting the temporary unzipped source subdirectory name to
641+
* the expected plugin slug.
642+
*
643+
* @param string $source Path to upgrade/zipfilename.tmp/subdirectory/
644+
* @param string $remote_source Path to upgrade/zipfilename.tmp
645+
* @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin
646+
*
647+
* @return string $source
648+
*/
649+
public function maybe_adjust_source_dir( $source, $remote_source, $upgrader ) {
650+
651+
if ( ! $this->is_tgmpa_page() ) {
652+
return $source;
653+
}
654+
655+
// Check for single file plugins
656+
$source_files = array_keys( $GLOBALS['wp_filesystem']->dirlist( $remote_source ) );
657+
if ( 1 === count( $source_files ) && false === $GLOBALS['wp_filesystem']->is_dir( $source ) ) {
658+
659+
return $source;
660+
}
661+
662+
// Multi-file plugin, let's see if the directory is correctly named
663+
$desired_slug = '';
664+
665+
// Figure out what the slug is supposed to be
666+
if ( false === $upgrader->bulk ) {
667+
$desired_slug = $upgrader->skin->options['plugin']['slug'];
668+
}
669+
else {
670+
// Bulk installer contains less info, so fall back on the info registered here.
671+
foreach ( $this->plugins as $plugin ) {
672+
if ( $plugin['name'] === $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) {
673+
$desired_slug = $plugin['slug'];
674+
break;
675+
}
676+
}
677+
}
678+
679+
if ( '' !== $desired_slug ) {
680+
$subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) );
681+
682+
if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) {
683+
$from = untrailingslashit( $source );
684+
$to = trailingslashit( $remote_source ) . $desired_slug;
685+
686+
if ( true === $GLOBALS['wp_filesystem']->move( $from, $to ) ) {
687+
return trailingslashit( $to );
688+
}
689+
else {
690+
return new WP_Error( 'rename_failed', esc_html__( 'The remote plugin package is does not contain a folder with the desired slug and renaming did not work.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
691+
}
692+
}
693+
elseif ( empty( $subdir_name ) ) {
694+
return new WP_Error( 'packaged_wrong', esc_html__( 'The remote plugin package consists of more than one file, but the files are not packaged in a folder.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
695+
}
696+
}
697+
698+
return $source;
699+
}
700+
632701
/**
633702
* Echoes required plugin notice.
634703
*
@@ -1184,7 +1253,7 @@ function tgmpa( $plugins, $config = array() ) {
11841253
* @author Gary Jones
11851254
*/
11861255
class TGMPA_List_Table extends WP_List_Table {
1187-
1256+
11881257
/**
11891258
* TGMPA instance
11901259
*
@@ -1471,7 +1540,7 @@ public function column_cb( $item ) {
14711540
$plugin_url = urlencode( $plugin_url );
14721541
}
14731542

1474-
$value = $item['file_path'] . ',' . $plugin_url . ',' . $item['sanitized_plugin'];
1543+
$value = $item['file_path'] . ',' . $plugin_url . ',' . $item['sanitized_plugin'];
14751544
return sprintf( '<input type="checkbox" name="%1$s[]" value="%2$s" id="%3$s" />', esc_attr( $this->_args['singular'] ), esc_attr( $value ), esc_attr( $item['sanitized_plugin'] ) );
14761545

14771546
}
@@ -1724,8 +1793,13 @@ public function process_bulk_actions() {
17241793
// Wrap the install process with the appropriate HTML.
17251794
echo '<div class="tgmpa wrap">',
17261795
'<h2>', esc_html( get_admin_page_title() ), '</h2>';
1796+
17271797
// Process the bulk installation submissions.
1798+
// Perform the action and install the plugin from the $source urldecode().
1799+
add_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
17281800
$installer->bulk_install( $sources );
1801+
remove_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
1802+
17291803
echo '</div>';
17301804

17311805
return true;
@@ -1834,7 +1908,6 @@ function tgmpa_load_bulk_installer() {
18341908
// Get TGMPA class instance
18351909
$tgmpa_instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
18361910

1837-
18381911
if ( ! class_exists( 'WP_Upgrader' ) && ( isset( $_GET['page'] ) && $tgmpa_instance->menu === $_GET['page'] ) ) {
18391912
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
18401913

@@ -1879,7 +1952,7 @@ class TGM_Bulk_Installer extends WP_Upgrader {
18791952
* @var object
18801953
*/
18811954
protected $tgmpa;
1882-
1955+
18831956
/**
18841957
* References parent constructor and sets defaults for class.
18851958
*
@@ -1888,7 +1961,7 @@ class TGM_Bulk_Installer extends WP_Upgrader {
18881961
public function __construct( $skin = null ) {
18891962
// Get TGMPA class instance
18901963
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
1891-
1964+
18921965
parent::__construct( $skin );
18931966
}
18941967

example.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ function my_theme_register_required_plugins() {
6363
'external_url' => 'https://github.com/thomasgriffin/New-Media-Image-Uploader', // If set, overrides default API URL and points to an external URL.
6464
),
6565

66+
// This is an example of how to include a plugin from a GitHub repository in your theme.
67+
// This presumes that the plugin code is based in the root of the GitHub repository
68+
// and not in a subdirectory ('/src') of the repository.
69+
array(
70+
'name' => 'Adminbar Link Comments to Pending',
71+
'slug' => 'adminbar-link-comments-to-pending',
72+
'source' => 'https://github.com/jrfnl/WP-adminbar-comments-to-pending/archive/master.zip',
73+
'required' => false,
74+
),
75+
6676
// This is an example of how to include a plugin from the WordPress Plugin Repository.
6777
array(
6878
'name' => 'BuddyPress',

0 commit comments

Comments
 (0)