Easy Theme and Plugin Upgrades - Version 2.0.2

Version Description

  • Misc: Version bump to show that this project is still active. No code changes are needed for functionality to continue.
Download this release

Release Info

Developer chrisjean
Plugin Icon wp plugin Easy Theme and Plugin Upgrades
Version 2.0.2
Comparing to
See all releases

Code changes from version 2.0.1 to 2.0.2

history.txt CHANGED
@@ -19,3 +19,5 @@
19
  Enhancement: The backup details now are found in the same format as the rest of the upgrade messages.
20
  2.0.1 - 2018-10-01 - Chris Jean
21
  Compatibility Update: Updated to indicate compatibility with WordPress 4.9.8.
 
 
19
  Enhancement: The backup details now are found in the same format as the rest of the upgrade messages.
20
  2.0.1 - 2018-10-01 - Chris Jean
21
  Compatibility Update: Updated to indicate compatibility with WordPress 4.9.8.
22
+ 2.0.2 - 2021-06-08 - Chris Jean
23
+ Misc: Version bump to show that this project is still active. No code changes are needed for functionality to continue.
init.php CHANGED
@@ -6,7 +6,7 @@ Plugin URI: http://wordpress.org/extend/plugins/easy-theme-and-plugin-upgrades/
6
  Description: Upgrade themes and plugins using a zip file without having to remove them first.
7
  Author: Chris Jean
8
  Author URI: https://chrisjean.com/
9
- Version: 2.0.1
10
  License: GPLv2 or later
11
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
12
  Text Domain: easy-theme-and-plugin-upgrades
6
  Description: Upgrade themes and plugins using a zip file without having to remove them first.
7
  Author: Chris Jean
8
  Author URI: https://chrisjean.com/
9
+ Version: 2.0.2
10
  License: GPLv2 or later
11
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
12
  Text Domain: easy-theme-and-plugin-upgrades
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: chrisjean
3
  Tags: plugin, theme, upgrade, update, upload
4
  Requires at least: 4.4
5
- Tested up to: 4.9.8
6
- Stable tag: 2.0.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -64,6 +64,9 @@ Starting with version 2.0.0, this plugin no longer requires that a drop down is
64
 
65
  == Changelog ==
66
 
 
 
 
67
  = 2.0.1 =
68
  * Compatibility Update: Updated to indicate compatibility with WordPress 4.9.8.
69
 
@@ -97,5 +100,5 @@ Starting with version 2.0.0, this plugin no longer requires that a drop down is
97
 
98
  == Upgrade Notice ==
99
 
100
- = 2.0.1 =
101
- Version 2.0.1 updates details about WordPress version compatibility. It contains no code changes.
2
  Contributors: chrisjean
3
  Tags: plugin, theme, upgrade, update, upload
4
  Requires at least: 4.4
5
+ Tested up to: 5.7.2
6
+ Stable tag: 2.0.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
64
 
65
  == Changelog ==
66
 
67
+ = 2.0.2 =
68
+ * Misc: Version bump to show that this project is still active. No code changes are needed for functionality to continue.
69
+
70
  = 2.0.1 =
71
  * Compatibility Update: Updated to indicate compatibility with WordPress 4.9.8.
72
 
100
 
101
  == Upgrade Notice ==
102
 
103
+ = 2.0.2 =
104
+ Version 2.0.2 updates details about WordPress version compatibility. It contains no code changes.
trunk/admin.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ final class CAJ_ETPU_Admin {
5
+ public static function init() {
6
+ add_action( 'load-update.php', array( __CLASS__, 'set_hooks' ) );
7
+ }
8
+
9
+ public static function set_hooks() {
10
+ include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
11
+
12
+ add_action( 'admin_action_upload-theme', array( __CLASS__, 'update_theme' ) );
13
+ add_action( 'admin_action_upload-plugin', array( __CLASS__, 'update_plugin' ) );
14
+ }
15
+
16
+ public static function update_theme() {
17
+ if ( ! current_user_can( 'upload_themes' ) ) {
18
+ wp_die( esc_html__( 'Sorry, you are not allowed to install themes on this site.' ) );
19
+ }
20
+
21
+ check_admin_referer( 'theme-upload' );
22
+
23
+ $file_upload = new File_Upload_Upgrader( 'themezip', 'package' );
24
+
25
+ wp_enqueue_script( 'customize-loader' );
26
+
27
+ $title = __( 'Upload Theme' );
28
+ $parent_file = 'themes.php';
29
+ $submenu_file = 'theme-install.php';
30
+
31
+ require_once( ABSPATH . 'wp-admin/admin-header.php' );
32
+
33
+ $title = sprintf( __( 'Installing Theme from uploaded file: %s' ), esc_html( basename( $file_upload->filename ) ) );
34
+ $nonce = 'theme-upload';
35
+ $url = add_query_arg( array( 'package' => $file_upload->id ), 'update.php?action=upload-theme' );
36
+ $type = 'upload'; // Install plugin type, From Web or an Upload.
37
+
38
+ require_once( dirname( __FILE__ ) . '/custom-theme-upgrader.php' );
39
+
40
+ $upgrader = new CAJ_ETPU_Theme_Upgrader( new Theme_Installer_Skin( compact( 'type', 'title', 'nonce', 'url' ) ) );
41
+ $result = $upgrader->install( $file_upload->package );
42
+
43
+ if ( $result || is_wp_error( $result ) ) {
44
+ $file_upload->cleanup();
45
+ }
46
+
47
+ include( ABSPATH . 'wp-admin/admin-footer.php' );
48
+
49
+ exit();
50
+ }
51
+
52
+ public static function update_plugin() {
53
+ if ( ! current_user_can( 'upload_plugins' ) ) {
54
+ wp_die( esc_html__( 'Sorry, you are not allowed to install plugins on this site.' ) );
55
+ }
56
+
57
+ check_admin_referer( 'plugin-upload' );
58
+
59
+ $file_upload = new File_Upload_Upgrader( 'pluginzip', 'package' );
60
+
61
+ $title = __( 'Upload Plugin' );
62
+ $parent_file = 'plugins.php';
63
+ $submenu_file = 'plugin-install.php';
64
+ require_once( ABSPATH . 'wp-admin/admin-header.php' );
65
+
66
+ $title = sprintf( __( 'Installing Plugin from uploaded file: %s' ), esc_html( basename( $file_upload->filename ) ) );
67
+ $nonce = 'plugin-upload';
68
+ $url = add_query_arg( array( 'package' => $file_upload->id ), 'update.php?action=upload-plugin' );
69
+ $type = 'upload'; // Install plugin type, From Web or an Upload.
70
+
71
+ require_once( dirname( __FILE__ ) . '/custom-plugin-upgrader.php' );
72
+
73
+ $upgrader = new CAJ_ETPU_Plugin_Upgrader( new Plugin_Installer_Skin( compact( 'type', 'title', 'nonce', 'url' ) ) );
74
+ $result = $upgrader->install( $file_upload->package );
75
+
76
+ if ( $result || is_wp_error( $result ) ) {
77
+ $file_upload->cleanup();
78
+ }
79
+
80
+ include( ABSPATH . 'wp-admin/admin-footer.php' );
81
+
82
+ exit();
83
+ }
84
+ }
85
+ CAJ_ETPU_Admin::init();
trunk/custom-plugin-upgrader.php ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CAJ_ETPU_Plugin_Upgrader extends Plugin_Upgrader {
4
+ public function install_package( $args = array() ) {
5
+ global $wp_filesystem;
6
+
7
+ error_reporting( E_ALL );
8
+ ini_set( 'display_errors', 1 );
9
+
10
+ if ( empty( $args['source'] ) || empty( $args['destination'] ) ) {
11
+ // Only run if the arguments we need are present.
12
+ return parent::install_package( $args );
13
+ }
14
+
15
+ $source_files = array_keys( $wp_filesystem->dirlist( $args['source'] ) );
16
+ $remote_destination = $wp_filesystem->find_folder( $args['destination'] );
17
+
18
+ // Locate which directory to copy to the new folder, This is based on the actual folder holding the files.
19
+ if ( 1 === count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { // Only one folder? Then we want its contents.
20
+ $destination = trailingslashit( $remote_destination ) . trailingslashit( $source_files[0] );
21
+ } elseif ( 0 === count( $source_files ) ) {
22
+ // Looks like an empty zip, we'll let the default code handle this.
23
+ return parent::install_package( $args );
24
+ } else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename.
25
+ $destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $args['source'] ) );
26
+ }
27
+
28
+ if ( is_dir( $destination ) ) {
29
+ // This is an upgrade, clear the destination.
30
+ $args['clear_destination'] = true;
31
+
32
+ // Switch template strings to use upgrade terminology rather than install terminology.
33
+ $this->upgrade_strings();
34
+
35
+ // Replace default remove_old string to make the messages more meaningful.
36
+ $this->strings['installing_package'] = __( 'Upgrading the plugin&#8230;', 'easy-theme-and-plugin-upgrades' );
37
+ $this->strings['remove_old'] = __( 'Backing up the old version of the plugin&#8230;', 'easy-theme-and-plugin-upgrades' );
38
+ }
39
+
40
+ return parent::install_package( $args );
41
+ }
42
+
43
+ private function caj_get_plugin_data( $directory ) {
44
+ $files = glob( $directory . '*.php' );
45
+
46
+ if ( $files ) {
47
+ foreach ( $files as $file ) {
48
+ $info = get_plugin_data( $file, false, false );
49
+
50
+ if ( ! empty( $info['Name'] ) ) {
51
+ $data = array(
52
+ 'name' => $info['Name'],
53
+ 'version' => $info['Version'],
54
+ );
55
+
56
+ return $data;
57
+ }
58
+ }
59
+ }
60
+
61
+ return false;
62
+ }
63
+
64
+ public function clear_destination( $destination ) {
65
+ global $wp_filesystem;
66
+
67
+ if ( ! is_dir( $destination ) ) {
68
+ // This is an installation not an upgrade.
69
+ return parent::clear_destination( $destination );
70
+ }
71
+
72
+ $data = $this->caj_get_plugin_data( $destination );
73
+
74
+ if ( false === $data ) {
75
+ // The existing directory is not a valid plugin, skip backup.
76
+ return parent::clear_destination( $destination );
77
+ }
78
+
79
+ $backup_url = $this->caj_create_backup( $destination );
80
+
81
+ if ( ! is_wp_error( $backup_url ) ) {
82
+ /* translators: 1: plugin zip URL */
83
+ $this->skin->feedback( sprintf( __( 'A backup zip file of the old plugin version can be downloaded <a href="%1$s">here</a>.', 'easy-theme-and-plugin-upgrades' ), $backup_url ) );
84
+
85
+ // Restore default strings and display the original remove_old message.
86
+ $this->upgrade_strings();
87
+ $this->skin->feedback( 'remove_old' );
88
+
89
+ return parent::clear_destination( $destination );
90
+ }
91
+
92
+ $this->skin->error( $backup_url );
93
+ $this->skin->feedback( __( 'Moving the old version of the plugin to a new directory&#8230;', 'easy-theme-and-plugin-upgrades' ) );
94
+
95
+ $new_name = basename( $destination ) . "-{$data['version']}";
96
+ $directory = dirname( $destination );
97
+
98
+ for ( $x = 0; $x < 20; $x++ ) {
99
+ $test_name = $new_name . '-' . $this->get_random_characters( 10, 20 );
100
+
101
+ if ( ! is_dir( "$directory/$test_name" ) ) {
102
+ $new_name = $test_name;
103
+ break;
104
+ }
105
+ }
106
+
107
+ if ( is_dir( "$directory/$new_name" ) ) {
108
+ // We gave it our best effort. Time to give up on the idea of having a backup.
109
+ $this->skin->error( __( 'Unable to find a new directory name to move the old version of the plugin to. No backup will be created.', 'easy-theme-and-plugin-upgrades' ) );
110
+ } else {
111
+ $result = $wp_filesystem->move( $destination, "$directory/$new_name" );
112
+
113
+ if ( $result ) {
114
+ /* translators: 1: new plugin directory name */
115
+ $this->skin->feedback( sprintf( __( 'Moved the old version of the plugin to a new plugin directory named %1$s. This directory should be backed up and removed from the site.', 'easy-theme-and-plugin-upgrades' ), "<code>$new_name</code>" ) );
116
+ } else {
117
+ $this->skin->error( __( 'Unable to move the old version of the plugin to a new directory. No backup will be created.', 'easy-theme-and-plugin-upgrades' ) );
118
+ }
119
+ }
120
+
121
+ // Restore default strings and display the original remove_old message.
122
+ $this->upgrade_strings();
123
+ $this->skin->feedback( 'remove_old' );
124
+
125
+ return parent::clear_destination( $destination );
126
+ }
127
+
128
+ private function caj_create_backup( $directory ) {
129
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
130
+
131
+ $wp_upload_dir = wp_upload_dir();
132
+
133
+ $zip_path = $wp_upload_dir['path'];
134
+ $zip_url = $wp_upload_dir['url'];
135
+
136
+ if ( ! is_dir( $zip_path ) ) {
137
+ return new WP_Error( 'caj-etpu-cannot-backup-no-destination-path', __( 'A plugin backup can not be created since a destination path for the backup file could not be found.', 'easy-theme-and-plugin-upgrades' ) );
138
+ }
139
+
140
+ $data = $this->caj_get_plugin_data( $directory );
141
+
142
+ $rand_string = $this->get_random_characters( 10, 20 );
143
+ $zip_file = basename( $directory ) . "-{$data['version']}-$rand_string.zip";
144
+
145
+ // Reduce the chance that a timeout will occur while creating the zip file.
146
+ @set_time_limit( 600 );
147
+
148
+ // Attempt to increase memory limits.
149
+ $this->set_minimum_memory_limit( '256M' );
150
+
151
+ $zip_path .= "/$zip_file";
152
+ $zip_url .= "/$zip_file";
153
+
154
+ require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
155
+
156
+ $archive = new PclZip( $zip_path );
157
+
158
+ $zip_result = $archive->create( $directory, PCLZIP_OPT_REMOVE_PATH, dirname( $directory ) );
159
+
160
+ if ( 0 === $zip_result ) {
161
+ /* translators: 1: zip error details */
162
+ return new WP_Error( 'caj-etpu-cannot-backup-zip-failed', sprintf( __( 'A plugin backup can not be created as creation of the zip file failed with the following error: %1$s', 'easy-theme-and-plugin-upgrades' ), $archive->errorInfo( true ) ) );
163
+ }
164
+
165
+ $attachment = array(
166
+ 'post_mime_type' => 'application/zip',
167
+ 'guid' => $zip_url,
168
+ /* translators: 1: plugin name, 2: plugin version */
169
+ 'post_title' => sprintf( __( 'Plugin Backup - %1$s - %2$s', 'easy-theme-and-plugin-upgrades' ), $data['name'], $data['version'] ),
170
+ 'post_content' => '',
171
+ );
172
+
173
+ $id = wp_insert_attachment( $attachment, $zip_path );
174
+
175
+ if ( ! is_wp_error( $id ) ) {
176
+ wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $zip_path ) );
177
+ }
178
+
179
+ return $zip_url;
180
+ }
181
+
182
+ private function get_random_characters( $min_length, $max_length ) {
183
+ $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
184
+ $rand_string = '';
185
+ $length = rand( $min_length, $max_length );
186
+
187
+ for ( $count = 0; $count < $length; $count++ ) {
188
+ $rand_string .= $characters[ rand( 0, strlen( $characters ) - 1 ) ];
189
+ }
190
+
191
+ return $rand_string;
192
+ }
193
+
194
+ function set_minimum_memory_limit( $new_memory_limit ) {
195
+ $memory_limit = @ini_get( 'memory_limit' );
196
+
197
+ if ( $memory_limit > -1 ) {
198
+ $unit = strtolower( substr( $memory_limit, -1 ) );
199
+ $new_unit = strtolower( substr( $new_memory_limit, -1 ) );
200
+
201
+ $memory_limit = intval( $memory_limit );
202
+ $new_memory_limit = intval( $new_memory_limit );
203
+
204
+ if ( 'm' == $unit ) {
205
+ $memory_limit *= 1048576;
206
+ } elseif ( 'g' == $unit ) {
207
+ $memory_limit *= 1073741824;
208
+ } elseif ( 'k' == $unit ) {
209
+ $memory_limit *= 1024;
210
+ }
211
+
212
+ if ( 'm' == $new_unit ) {
213
+ $new_memory_limit *= 1048576;
214
+ } else if ( 'g' == $new_unit ) {
215
+ $new_memory_limit *= 1073741824;
216
+ } else if ( 'k' == $new_unit ) {
217
+ $new_memory_limit *= 1024;
218
+ }
219
+
220
+ if ( (int) $memory_limit < (int) $new_memory_limit ) {
221
+ @ini_set( 'memory_limit', $new_memory_limit );
222
+ }
223
+ }
224
+ }
225
+ }
trunk/custom-theme-upgrader.php ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CAJ_ETPU_Theme_Upgrader extends Theme_Upgrader {
4
+ public function install_package( $args = array() ) {
5
+ global $wp_filesystem;
6
+
7
+ error_reporting( E_ALL );
8
+ ini_set( 'display_errors', 1 );
9
+
10
+ if ( empty( $args['source'] ) || empty( $args['destination'] ) ) {
11
+ // Only run if the arguments we need are present.
12
+ return parent::install_package( $args );
13
+ }
14
+
15
+ $source_files = array_keys( $wp_filesystem->dirlist( $args['source'] ) );
16
+ $remote_destination = $wp_filesystem->find_folder( $args['destination'] );
17
+
18
+ // Locate which directory to copy to the new folder, This is based on the actual folder holding the files.
19
+ if ( 1 === count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { // Only one folder? Then we want its contents.
20
+ $destination = trailingslashit( $remote_destination ) . trailingslashit( $source_files[0] );
21
+ } elseif ( 0 === count( $source_files ) ) {
22
+ // Looks like an empty zip, we'll let the default code handle this.
23
+ return parent::install_package( $args );
24
+ } else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename.
25
+ $destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $args['source'] ) );
26
+ }
27
+
28
+ if ( is_dir( $destination ) && file_exists( "$destination/style.css" ) ) {
29
+ // This is an upgrade, clear the destination.
30
+ $args['clear_destination'] = true;
31
+
32
+ // Switch template strings to use upgrade terminology rather than install terminology.
33
+ $this->upgrade_strings();
34
+
35
+ // Replace default remove_old string to make the messages more meaningful.
36
+ $this->strings['installing_package'] = __( 'Upgrading the theme&#8230;', 'easy-theme-and-plugin-upgrades' );
37
+ $this->strings['remove_old'] = __( 'Backing up the old version of the theme&#8230;', 'easy-theme-and-plugin-upgrades' );
38
+ }
39
+
40
+ return parent::install_package( $args );
41
+ }
42
+
43
+ public function clear_destination( $destination ) {
44
+ global $wp_filesystem;
45
+
46
+ if ( ! is_dir( $destination ) || ! file_exists( "$destination/style.css" ) ) {
47
+ // This is an installation not an upgrade.
48
+ return parent::clear_destination( $destination );
49
+ }
50
+
51
+ $backup_url = $this->create_backup( $destination );
52
+
53
+ if ( ! is_wp_error( $backup_url ) ) {
54
+ /* translators: 1: theme zip URL */
55
+ $this->skin->feedback( sprintf( __( 'A backup zip file of the old theme version can be downloaded <a href="%1$s">here</a>.', 'easy-theme-and-plugin-upgrades' ), $backup_url ) );
56
+
57
+ // Restore default strings and display the original remove_old message.
58
+ $this->upgrade_strings();
59
+ $this->skin->feedback( 'remove_old' );
60
+
61
+ return parent::clear_destination( $destination );
62
+ }
63
+
64
+ $this->skin->error( $backup_url );
65
+ $this->skin->feedback( __( 'Moving the old version of the theme to a new directory&#8230;', 'easy-theme-and-plugin-upgrades' ) );
66
+
67
+ $headers = array(
68
+ 'version' => 'Version',
69
+ );
70
+ $data = get_file_data( "$destination/style.css", $headers );
71
+
72
+ $new_name = basename( $destination ) . "-{$data['version']}";
73
+ $directory = dirname( $destination );
74
+
75
+ for ( $x = 0; $x < 20; $x++ ) {
76
+ $test_name = $new_name . '-' . $this->get_random_characters( 10, 20 );
77
+
78
+ if ( ! is_dir( "$directory/$test_name" ) ) {
79
+ $new_name = $test_name;
80
+ break;
81
+ }
82
+ }
83
+
84
+ if ( is_dir( "$directory/$new_name" ) ) {
85
+ // We gave it our best effort. Time to give up on the idea of having a backup.
86
+ $this->skin->error( __( 'Unable to find a new directory name to move the old version of the theme to. No backup will be created.', 'easy-theme-and-plugin-upgrades' ) );
87
+ } else {
88
+ $result = $wp_filesystem->move( $destination, "$directory/$new_name" );
89
+
90
+ if ( $result ) {
91
+ /* translators: 1: new theme directory name */
92
+ $this->skin->feedback( sprintf( __( 'Moved the old version of the theme to a new theme directory named %1$s. This directory should be backed up and removed from the site.', 'easy-theme-and-plugin-upgrades' ), "<code>$new_name</code>" ) );
93
+ } else {
94
+ $this->skin->error( __( 'Unable to move the old version of the theme to a new directory. No backup will be created.', 'easy-theme-and-plugin-upgrades' ) );
95
+ }
96
+ }
97
+
98
+ // Restore default strings and display the original remove_old message.
99
+ $this->upgrade_strings();
100
+ $this->skin->feedback( 'remove_old' );
101
+
102
+ return parent::clear_destination( $destination );
103
+ }
104
+
105
+ private function create_backup( $directory ) {
106
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
107
+
108
+ $wp_upload_dir = wp_upload_dir();
109
+
110
+ $zip_path = $wp_upload_dir['path'];
111
+ $zip_url = $wp_upload_dir['url'];
112
+
113
+ if ( ! is_dir( $zip_path ) ) {
114
+ return new WP_Error( 'caj-etpu-cannot-backup-no-destination-path', __( 'A theme backup can not be created since a destination path for the backup file could not be found.', 'easy-theme-and-plugin-upgrades' ) );
115
+ }
116
+
117
+ $headers = array(
118
+ 'name' => 'Theme Name',
119
+ 'version' => 'Version',
120
+ );
121
+ $data = get_file_data( "$directory/style.css", $headers );
122
+
123
+ $rand_string = $this->get_random_characters( 10, 20 );
124
+ $zip_file = basename( $directory ) . "-{$data['version']}-$rand_string.zip";
125
+
126
+ // Reduce the chance that a timeout will occur while creating the zip file.
127
+ @set_time_limit( 600 );
128
+
129
+ // Attempt to increase memory limits.
130
+ $this->set_minimum_memory_limit( '256M' );
131
+
132
+ $zip_path .= "/$zip_file";
133
+ $zip_url .= "/$zip_file";
134
+
135
+ require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
136
+
137
+ $archive = new PclZip( $zip_path );
138
+
139
+ $zip_result = $archive->create( $directory, PCLZIP_OPT_REMOVE_PATH, dirname( $directory ) );
140
+
141
+ if ( 0 === $zip_result ) {
142
+ /* translators: 1: zip error details */
143
+ return new WP_Error( 'caj-etpu-cannot-backup-zip-failed', sprintf( __( 'A theme backup can not be created as creation of the zip file failed with the following error: %1$s', 'easy-theme-and-plugin-upgrades' ), $archive->errorInfo( true ) ) );
144
+ }
145
+
146
+ $attachment = array(
147
+ 'post_mime_type' => 'application/zip',
148
+ 'guid' => $zip_url,
149
+ /* translators: 1: theme name, 2: theme version */
150
+ 'post_title' => sprintf( __( 'Theme Backup - %1$s - %2$s', 'easy-theme-and-plugin-upgrades' ), $data['name'], $data['version'] ),
151
+ 'post_content' => '',
152
+ );
153
+
154
+ $id = wp_insert_attachment( $attachment, $zip_path );
155
+
156
+ if ( ! is_wp_error( $id ) ) {
157
+ wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $zip_path ) );
158
+ }
159
+
160
+ return $zip_url;
161
+ }
162
+
163
+ private function get_random_characters( $min_length, $max_length ) {
164
+ $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
165
+ $rand_string = '';
166
+ $length = rand( $min_length, $max_length );
167
+
168
+ for ( $count = 0; $count < $length; $count++ ) {
169
+ $rand_string .= $characters[ rand( 0, strlen( $characters ) - 1 ) ];
170
+ }
171
+
172
+ return $rand_string;
173
+ }
174
+
175
+ function set_minimum_memory_limit( $new_memory_limit ) {
176
+ $memory_limit = @ini_get( 'memory_limit' );
177
+
178
+ if ( $memory_limit > -1 ) {
179
+ $unit = strtolower( substr( $memory_limit, -1 ) );
180
+ $new_unit = strtolower( substr( $new_memory_limit, -1 ) );
181
+
182
+ $memory_limit = intval( $memory_limit );
183
+ $new_memory_limit = intval( $new_memory_limit );
184
+
185
+ if ( 'm' == $unit ) {
186
+ $memory_limit *= 1048576;
187
+ } elseif ( 'g' == $unit ) {
188
+ $memory_limit *= 1073741824;
189
+ } elseif ( 'k' == $unit ) {
190
+ $memory_limit *= 1024;
191
+ }
192
+
193
+ if ( 'm' == $new_unit ) {
194
+ $new_memory_limit *= 1048576;
195
+ } else if ( 'g' == $new_unit ) {
196
+ $new_memory_limit *= 1073741824;
197
+ } else if ( 'k' == $new_unit ) {
198
+ $new_memory_limit *= 1024;
199
+ }
200
+
201
+ if ( (int) $memory_limit < (int) $new_memory_limit ) {
202
+ @ini_set( 'memory_limit', $new_memory_limit );
203
+ }
204
+ }
205
+ }
206
+ }
trunk/history.txt ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1.0.0 - 2011-07-06 - Chris Jean
2
+ Release-ready
3
+ 1.0.1 - 2011-09-28 - Chris Jean
4
+ Fixed an issue with running upgrades on multisite networks
5
+ 1.0.2 - 2013-08-20 - Chris Jean
6
+ Removed a stray <i> tag in the Install Plugins screen that caused problems with installing plugins on WPEngine sites.
7
+ 1.0.3 - 2014-04-18 - Chris Jean
8
+ Fixed issue with theme upgrades working properly in WordPress 3.9.
9
+ 1.0.4 - 2014-05-29 - Chris Jean
10
+ Updated instructions on how to upgrade themes.
11
+ 1.0.5 - 2016-07-13 - Chris Jean
12
+ Compatibility Fix: Added support for PHP 7+.
13
+ 1.0.6 - 2016-07-19 - Chris Jean
14
+ Bug Fix: Fixed incorrect handling of some zip file formats. Thanks to the team at https://kairaweb.com/ for helping solve this issue.
15
+ 2.0.0 - 2016-08-15 - Chris Jean
16
+ Enhancement: Removed the requirement for the user to select "Yes" from the drop down in order to initiate an update. This new version does not change the appearance of the upload form. Instead, it automatically creates a backup and performs an upgrade if the supplied plugin or theme already exists.
17
+ Enhancement: If a zip backup file cannot be created, the old directory is renamed to a new name in order to still keep a backup.
18
+ Enhancement: Updated the code to use a better way of integrating the upgrade logic. This approach should greatly reduce the potential for conflicts with other code or site configurations.
19
+ Enhancement: The backup details now are found in the same format as the rest of the upgrade messages.
20
+ 2.0.1 - 2018-10-01 - Chris Jean
21
+ Compatibility Update: Updated to indicate compatibility with WordPress 4.9.8.
22
+ 2.0.2 - 2021-06-08 - Chris Jean
23
+ Misc: Version bump to show that this project is still active. No code changes are needed for functionality to continue.
trunk/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
trunk/init.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ Plugin Name: Easy Theme and Plugin Upgrades
5
+ Plugin URI: http://wordpress.org/extend/plugins/easy-theme-and-plugin-upgrades/
6
+ Description: Upgrade themes and plugins using a zip file without having to remove them first.
7
+ Author: Chris Jean
8
+ Author URI: https://chrisjean.com/
9
+ Version: 2.0.2
10
+ License: GPLv2 or later
11
+ License URI: https://www.gnu.org/licenses/gpl-2.0.html
12
+ Text Domain: easy-theme-and-plugin-upgrades
13
+
14
+ Easy Theme and Plugin Upgrades is free software you can redistribute
15
+ it and/or modify it under the terms of the GNU General Public License
16
+ as published by the Free Software Foundation, either version 2 of the
17
+ License, or any later version.
18
+
19
+ Easy Theme and Plugin Upgrades is distributed in the hope that it
20
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied
21
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
22
+ the GNU General Public License for more details.
23
+
24
+ You should have received a copy of the GNU General Public License
25
+ along with Easy Theme and Plugin Upgrades. If not, see
26
+ https://www.gnu.org/licenses/gpl-2.0.html.
27
+ */
28
+
29
+
30
+ if ( is_admin() ) {
31
+ require( dirname( __FILE__ ) . '/admin.php' );
32
+ }
trunk/readme.txt ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Easy Theme and Plugin Upgrades ===
2
+ Contributors: chrisjean
3
+ Tags: plugin, theme, upgrade, update, upload
4
+ Requires at least: 4.4
5
+ Tested up to: 5.9.3
6
+ Stable tag: 2.0.2
7
+ License: GPLv2 or later
8
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
+
10
+ Easily upgrade your themes and plugins using zip files without removing the theme or plugin first.
11
+
12
+
13
+ == Description ==
14
+
15
+ WordPress has a built-in feature to install themes and plugins by supplying a zip file. Unfortunately, you cannot upgrade a theme or plugin using the same process. Instead, WordPress will say "destination already exists" when trying to upgrade using a zip file and will fail to upgrade the theme or plugin.
16
+
17
+ Easy Theme and Plugin Upgrades fixes this limitation in WordPress by automatically upgrading the theme or plugin if it already exists.
18
+
19
+ While upgrading, a backup copy of the old theme or plugin is first created. This allows you to install the old version in case of problems with the new version.
20
+
21
+ Attention: Version 2.0.0 changed the functionality of the plugin. You are no longer required to select "Yes" from a drop down before the theme or plugin can be upgraded. The need for an upgrade is now detected automatically. So, if you are used to the old functionality of the plugin, do not be concerned about the absence of upgrade details on the theme and plugin upload pages. Simply upload the theme or plugin as if you were installing it, and the plugin will automatically handle upgrading as needed.
22
+
23
+
24
+ == Frequently Asked Questions ==
25
+
26
+ = Why does the plugin no longer show the drop down to select "Yes"? Is the plugin broken? =
27
+
28
+ Starting with version 2.0.0, this plugin no longer requires that a drop down is used to indicate that an upgrade is to be performed. The plugin now can determine if an upgrade is required automatically. This change not only streamlines the process for many users, it also fixed compatibility issues that some users experienced with older versions.
29
+
30
+ = How do I upgrade a theme? =
31
+
32
+ 1. Download the latest zip file for your theme.
33
+ 1. Log into your WordPress site.
34
+ 1. Go to Appearance > Themes.
35
+ 1. Click the "Add New" button at the top of the page.
36
+ 1. Click the "Upload Theme" button at the top of the page.
37
+ 1. Select the zip file with the new theme version to install.
38
+ 1. Click the "Install Now" button.
39
+
40
+ = How do I upgrade a plugin? =
41
+
42
+ 1. Download the latest zip file for your plugin.
43
+ 1. Log into your WordPress site.
44
+ 1. Go to Plugins > Add New.
45
+ 1. Click the "Upload Plugin" button at the top of the page.
46
+ 1. Select the zip file with the new plugin version to install.
47
+ 1. Click the "Install Now" button.
48
+
49
+ = How do I access the backup of an old theme or plugin? =
50
+
51
+ 1. Log into your WordPress site.
52
+ 1. Go to Media > Library.
53
+ 1. Type "backup" into the search input and press the "Enter" key.
54
+ 1. Find the desired backup from the resulting list.
55
+ 1. Click the title of the desired backup.
56
+ 1. The URL to the backup file is listed on the right side of the page under "File URL". You can copy and paste that URL into your browser's URL bar in order to start a download.
57
+
58
+
59
+ == Installation ==
60
+
61
+ 1. Download and unzip the latest release zip file
62
+ 1. Upload the entire easy-theme-and-plugin-upgrades directory to your `/wp-content/plugins/` directory
63
+ 1. Activate the plugin through the 'Plugins' menu in WordPress
64
+
65
+ == Changelog ==
66
+
67
+ = 2.0.2 =
68
+ * Misc: Version bump to show that this project is still active. No code changes are needed for functionality to continue.
69
+
70
+ = 2.0.1 =
71
+ * Compatibility Update: Updated to indicate compatibility with WordPress 4.9.8.
72
+
73
+ = 2.0.0 =
74
+ * Enhancement: Removed the requirement for the user to select "Yes" from the drop down in order to initiate an update. This new version does not change the appearance of the upload form. Instead, it automatically creates a backup and performs an upgrade if the supplied plugin or theme already exists.
75
+ * Enhancement: If a zip backup file cannot be created, the old directory is renamed to a new name in order to still keep a backup.
76
+ * Enhancement: Updated the code to use a better way of integrating the upgrade logic. This approach should greatly reduce the potential for conflicts with other code or site configurations.
77
+ * Enhancement: The backup details now are found in the same format as the rest of the upgrade messages.
78
+
79
+ = 1.0.6 =
80
+ * Bug Fix: Fixed updates not working with some formats of zip files. Thanks to the team at [Kaira](https://kairaweb.com/) for helping solve this issue.
81
+
82
+ = 1.0.5 =
83
+ * Compatibility Fix: Added support for PHP 7.
84
+
85
+ = 1.0.4 =
86
+ * Enhancement: Updated instructions on how to upgrade themes.
87
+
88
+ = 1.0.3 =
89
+ * Compatibility Fix: Added compatibility for theme upgrades in WordPress 3.9.
90
+
91
+ = 1.0.2 =
92
+ * Bug Fix: Removed a stray &lt;i&gt; tag in the Install Plugins screen that caused problems with installing plugins on WPEngine sites.
93
+
94
+ = 1.0.1 =
95
+ * Bug Fix: Fixed an issue with the "The site is being updated and will be back in a few minutes" message showing on the frontend of the site for a few minutes after an upgrade. This only happened on multisite networks.
96
+
97
+ = 1.0.0 =
98
+ * Initial release version
99
+
100
+
101
+ == Upgrade Notice ==
102
+
103
+ = 2.0.2 =
104
+ Version 2.0.2 updates details about WordPress version compatibility. It contains no code changes.