Ticket #9757: 9757.4.patch
File 9757.4.patch, 32.4 KB (added by , 4 years ago) |
---|
-
src/wp-admin/css/themes.css
1030 1030 overflow: hidden; 1031 1031 position: relative; 1032 1032 top: 10px; 1033 text-align: center; 1033 1034 } 1034 1035 1035 .upload-plugin-wrap {1036 display: none;1037 }1038 1039 1036 .show-upload-view .upload-theme, 1040 1037 .show-upload-view .upload-plugin, 1041 1038 .show-upload-view .upload-plugin-wrap, … … 1049 1046 border: 1px solid #ccd0d4; 1050 1047 padding: 30px; 1051 1048 margin: 30px auto; 1052 max-width: 380px; 1053 display: flex; 1049 display: inline-flex; 1054 1050 justify-content: space-between; 1055 1051 align-items: center; 1056 1052 } 1057 1053 1054 .upload-theme .wp-upload-form input[type="file"], 1055 .upload-plugin .wp-upload-form input[type="file"] { 1056 margin-right: 10px; 1057 } 1058 1058 1059 .upload-theme .install-help, 1059 1060 .upload-plugin .install-help { 1060 1061 color: #555d66; /* #f1f1f1 background */ … … 1093 1094 .upload-theme .install-help { 1094 1095 font-size: 15px; 1095 1096 padding: 20px 0 0; 1096 text-align: left;1097 1097 } 1098 1098 } 1099 1099 … … 1116 1116 line-height: 1.9; 1117 1117 } 1118 1118 1119 .compare-themes-table, 1120 .compare-plugins-table { 1121 text-align: left; 1122 margin: 1em 0 2em; 1123 border-collapse: collapse; 1124 } 1125 1126 .compare-themes-table th, 1127 .compare-plugins-table th { 1128 font-weight: bold; 1129 padding: 3px 10px; 1130 } 1131 1132 .compare-themes-table td, 1133 .compare-plugins-table td { 1134 padding: 3px 10px; 1135 } 1136 1137 .compare-themes-table tr.warning, 1138 .compare-plugins-table tr.warning, 1139 a.ovewrite-uploaded-theme { 1140 color: #a00; 1141 } 1142 1143 a.ovewrite-uploaded-plugin { 1144 color: #a00; 1145 margin-left: 10px; 1146 } 1147 1148 1149 a.ovewrite-uploaded-theme:hover, 1150 a.ovewrite-uploaded-plugin:hover { 1151 color: #d80707; 1152 } 1153 1119 1154 /*------------------------------------------------------------------------------ 1120 1155 16.3 - Custom Header Screen 1121 1156 ------------------------------------------------------------------------------*/ -
src/wp-admin/includes/class-plugin-installer-skin.php
18 18 class Plugin_Installer_Skin extends WP_Upgrader_Skin { 19 19 public $api; 20 20 public $type; 21 public $url; 22 public $overwrite; 21 23 24 private $is_downgrading = false; 25 22 26 /** 23 27 * @param array $args 24 28 */ 25 29 public function __construct( $args = array() ) { 26 30 $defaults = array( 27 'type' => 'web', 28 'url' => '', 29 'plugin' => '', 30 'nonce' => '', 31 'title' => '', 31 'type' => 'web', 32 'url' => '', 33 'plugin' => '', 34 'nonce' => '', 35 'title' => '', 36 'overwrite' => '', 32 37 ); 33 38 $args = wp_parse_args( $args, $defaults ); 34 39 35 $this->type = $args['type']; 36 $this->api = isset( $args['api'] ) ? $args['api'] : array(); 40 $this->type = $args['type']; 41 $this->url = $args['url']; 42 $this->api = isset( $args['api'] ) ? $args['api'] : array(); 43 $this->overwrite = $args['overwrite']; 37 44 38 45 parent::__construct( $args ); 39 46 } … … 43 50 public function before() { 44 51 if ( ! empty( $this->api ) ) { 45 52 $this->upgrader->strings['process_success'] = sprintf( 46 /* translators: 1: Plugin name, 2: Plugin version. */ 47 __( 'Successfully installed the plugin <strong>%1$s %2$s</strong>.' ), 53 $this->upgrader->strings['process_success_specific'], 48 54 $this->api->name, 49 55 $this->api->version 50 56 ); … … 54 60 /** 55 61 */ 56 62 public function after() { 63 // Check if the plugin can be overwritten and output the HTML. 64 if ( $this->do_overwrite() ) { 65 return; 66 } 67 57 68 $plugin_file = $this->upgrader->plugin_info(); 58 69 59 70 $install_actions = array(); … … 117 128 118 129 if ( ! $this->result || is_wp_error( $this->result ) ) { 119 130 unset( $install_actions['activate_plugin'], $install_actions['network_activate'] ); 120 } elseif ( ! current_user_can( 'activate_plugin', $plugin_file ) ) {131 } elseif ( ! current_user_can( 'activate_plugin', $plugin_file ) || is_plugin_active( $plugin_file ) ) { 121 132 unset( $install_actions['activate_plugin'] ); 122 133 } 123 134 … … 138 149 $this->feedback( implode( ' ', (array) $install_actions ) ); 139 150 } 140 151 } 152 153 /** 154 * Check if the plugin can be overwritten and output the HTML for overwriting a plugin on upload. 155 * 156 * @since 5.5.0 157 * 158 * @return bool Whether the plugin can be overwritten and HTML was outputted. 159 */ 160 private function do_overwrite() { 161 if ( 'upload' !== $this->type || ! is_wp_error( $this->result ) || 'folder_exists' !== $this->result->get_error_code() ) { 162 return false; 163 } 164 165 $folder = $this->result->get_error_data( 'folder_exists' ); 166 $folder = ltrim( substr( $folder, strlen( WP_PLUGIN_DIR ) ), '/' ); 167 168 $current_plugin_data = false; 169 foreach ( get_plugins() as $plugin => $plugin_data ) { 170 if ( strrpos( $plugin, $folder ) !== 0 ) { 171 continue; 172 } 173 174 $current_plugin_data = $plugin_data; 175 } 176 177 if ( empty( $current_plugin_data ) || empty( $this->upgrader->new_plugin_data ) ) { 178 return false; 179 } 180 181 $this->feedback( 'compare_before_overwrite' ); 182 183 $this->is_downgrading = version_compare( $current_plugin_data['Version'], $this->upgrader->new_plugin_data['Version'], '>' ); 184 185 $rows = array( 186 'Name' => __( 'Plugin Name' ), 187 'Version' => __( 'Version' ), 188 'Author' => __( 'Author' ), 189 'RequiresWP' => __( 'Required WordPress version' ), 190 'RequiresPHP' => __( 'Required PHP version' ), 191 ); 192 193 $table = '<table class="compare-plugins-table"><tbody>'; 194 $table .= '<tr><th></th><th>' . esc_html( __( 'Current' ) ) . '</th><th>' . esc_html( __( 'Uploaded' ) ) . '</th></tr>'; 195 196 $is_same_plugin = true; // Let's consider only these rows 197 foreach ( $rows as $field => $label ) { 198 $old_value = ! empty( $current_plugin_data[ $field ] ) ? $current_plugin_data[ $field ] : '-'; 199 $new_value = ! empty( $this->upgrader->new_plugin_data[ $field ] ) ? $this->upgrader->new_plugin_data[ $field ] : '-'; 200 201 $is_same_plugin = $is_same_plugin && ( $old_value === $new_value ); 202 203 $diff_field = ( 'Version' !== $field && $new_value !== $old_value ); 204 $diff_version = ( 'Version' === $field && $this->is_downgrading ); 205 206 $table .= ( $diff_field || $diff_version ) ? '<tr class="warning">' : '<tr>'; 207 $table .= '<td>' . $label . '</td><td>' . esc_html( $old_value ) . '</td><td>' . esc_html( $new_value ) . '</td></tr>'; 208 } 209 210 $table .= '</tbody></table>'; 211 212 if ( $is_same_plugin ) { 213 $this->feedback( 'reuploading_plugin' ); 214 } 215 216 /** 217 * Filters the compare table output for overwrite a plugin package on upload. 218 * 219 * @since 5.5.0 220 * 221 * @param string $table The output table with Name, Version, Author, RequiresWP and RequiresPHP info. 222 * @param array $current_plugin_data Array with current plugin data. 223 * @param array $new_plugin_data Array with uploaded plugin data. 224 */ 225 echo apply_filters( 'install_plugin_ovewrite_comparison', $table, $current_plugin_data, $this->upgrader->new_plugin_data ); 226 227 // Action links. 228 $install_actions = array( 229 'plugins_page' => sprintf( 230 '<a href="%s">%s</a>', 231 self_admin_url( 'plugin-install.php' ), 232 __( 'Cancel and go back' ) 233 ), 234 ); 235 236 $can_update = true; 237 238 if ( ! empty( $this->upgrader->new_plugin_data['RequiresPHP'] ) && version_compare( phpversion(), $this->upgrader->new_plugin_data['RequiresPHP'], '<' ) ) { 239 $error = sprintf( 240 /* translators: 1: Current PHP version, 2: Version required by the uploaded plugin. */ 241 __( 'The plugin cannot be updated. The PHP version on your server is %1$s, however the uploaded plugin requires %2$s.' ), 242 phpversion(), 243 $this->upgrader->new_plugin_data['RequiresPHP'] 244 ); 245 246 $this->feedback( '<div class="notice notice-error inline"><p>' . esc_html( $error ) . '</p></div>' ); 247 $can_update = false; 248 } 249 250 if ( ! empty( $this->upgrader->new_plugin_data['RequiresWP'] ) && version_compare( $GLOBALS['wp_version'], $this->upgrader->new_plugin_data['RequiresWP'], '<' ) ) { 251 $error = sprintf( 252 /* translators: 1: Current WordPress version, 2: Version required by the uploaded plugin. */ 253 __( 'The plugin cannot be updated. Your WordPress version is %1$s, however the uploaded plugin requires %2$s.' ), 254 $GLOBALS['wp_version'], 255 $this->upgrader->new_plugin_data['RequiresWP'] 256 ); 257 258 $this->feedback( '<div class="notice notice-error inline"><p>' . esc_html( $error ) . '</p></div>' ); 259 $can_update = false; 260 } 261 262 if ( $can_update ) { 263 $warning = __( '<strong>Important:</strong> Before updating, please <a href="https://wordpress.org/support/article/wordpress-backups/">back up your database and files</a>.' ); 264 $this->feedback( '<div class="notice notice-warning inline"><p>' . $warning . '</p></div>' ); 265 266 $overwrite = 'update-plugin'; 267 $label = __( 'Remove current and install the uploaded version' ); 268 269 if ( $this->is_downgrading ) { 270 $overwrite = 'downgrade-plugin'; 271 272 if ( isset( $this->upgrader->new_plugin_data['Version'] ) ) { 273 $label = sprintf( __( 'Remove current and install version %s' ), $this->upgrader->new_plugin_data['Version'] ); 274 } 275 } 276 277 $install_actions['ovewrite_plugin'] = sprintf( 278 '<a class="ovewrite-uploaded-plugin" href="%s" target="_parent">%s</a>', 279 wp_nonce_url( add_query_arg( 'overwrite', $overwrite, $this->url ), 'plugin-upload' ), 280 esc_html( $label ) 281 ); 282 } 283 284 /** 285 * Filters the list of action links available following a single plugin installation failed but ovewrite is allowed. 286 * 287 * @since 5.5.0 288 * 289 * @param string[] $install_actions Array of plugin action links. 290 * @param object $api Object containing WordPress.org API plugin data. 291 * @param array $new_plugin_data Array with uploaded plugin data. 292 */ 293 $install_actions = apply_filters( 'install_plugin_ovewrite_actions', $install_actions, $this->api, $this->upgrader->new_plugin_data ); 294 295 if ( ! empty( $install_actions ) ) { 296 $this->feedback( implode( ' ', (array) $install_actions ) ); 297 } 298 299 return true; 300 } 141 301 } -
src/wp-admin/includes/class-plugin-upgrader.php
39 39 public $bulk = false; 40 40 41 41 /** 42 * New plugin info. 43 * 44 * @since 5.5.0 45 * @var array $new_plugin_data 46 * 47 * @see check_package() 48 */ 49 public $new_plugin_data = []; 50 51 /** 42 52 * Initialize the upgrade strings. 43 53 * 44 54 * @since 2.8.0 … … 54 64 $this->strings['process_failed'] = __( 'Plugin update failed.' ); 55 65 $this->strings['process_success'] = __( 'Plugin updated successfully.' ); 56 66 $this->strings['process_bulk_success'] = __( 'Plugins updated successfully.' ); 67 68 /* translators: 1: Plugin name, 2: Plugin version. */ 69 $this->strings['process_success_specific'] = __( 'Successfully installed the plugin <strong>%1$s %2$s</strong>.' ); 57 70 } 58 71 59 72 /** … … 67 80 $this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s…' ), '<span class="code">%s</span>' ); 68 81 $this->strings['unpack_package'] = __( 'Unpacking the package…' ); 69 82 $this->strings['installing_package'] = __( 'Installing the plugin…' ); 83 $this->strings['remove_old'] = __( 'Removing the current plugin…' ); 84 $this->strings['remove_old_failed'] = __( 'Could not remove the current plugin.' ); 70 85 $this->strings['no_files'] = __( 'The plugin contains no files.' ); 71 86 $this->strings['process_failed'] = __( 'Plugin installation failed.' ); 72 87 $this->strings['process_success'] = __( 'Plugin installed successfully.' ); 88 89 $this->strings['reuploading_plugin'] = __( 'Seems you have uploaded a plugin that is already installed.' ); 90 $this->strings['compare_before_overwrite'] = __( 'Plugin information:' ); 91 92 if ( 'update-plugin' === $this->skin->overwrite ) { 93 $this->strings['installing_package'] = __( 'Updating the plugin…' ); 94 $this->strings['process_failed'] = __( 'Plugin update failed.' ); 95 $this->strings['process_success'] = __( 'Plugin updated successfully.' ); 96 } 97 98 if ( 'downgrade-plugin' === $this->skin->overwrite ) { 99 $this->strings['installing_package'] = __( 'Downgrading the plugin…' ); 100 $this->strings['process_failed'] = __( 'Plugin downgrade failed.' ); 101 $this->strings['process_success'] = __( 'Plugin downgraded successfully.' ); 102 } 73 103 } 74 104 75 105 /** … … 88 118 * @return bool|WP_Error True if the installation was successful, false or a WP_Error otherwise. 89 119 */ 90 120 public function install( $package, $args = array() ) { 91 92 121 $defaults = array( 93 122 'clear_update_cache' => true, 123 'overwrite_package' => false, // Do not overwrite files. 94 124 ); 95 125 $parsed_args = wp_parse_args( $args, $defaults ); 96 126 … … 107 137 array( 108 138 'package' => $package, 109 139 'destination' => WP_PLUGIN_DIR, 110 'clear_destination' => false, // Do not overwrite files.140 'clear_destination' => $args['overwrite_package'], 111 141 'clear_working' => true, 112 142 'hook_extra' => array( 113 143 'type' => 'plugin', … … 126 156 // Force refresh of plugin update information. 127 157 wp_clean_plugins_cache( $parsed_args['clear_update_cache'] ); 128 158 159 if ( $parsed_args['overwrite_package'] ) { 160 /** 161 * Fires when the upgrader process a install forcing a package overwrite. 162 * 163 * @since 5.5.0 164 * 165 * @param string $package The package file. 166 * @param array $new_plugin_data The new plugin data. 167 * @param string $package_type The package type (plugin or theme). 168 */ 169 do_action( 'upgrader_overwrited_package', $package, $this->new_plugin_data, 'plugin' ); 170 } 171 129 172 return true; 130 173 } 131 174 … … 145 188 * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise. 146 189 */ 147 190 public function upgrade( $plugin, $args = array() ) { 148 149 191 $defaults = array( 150 192 'clear_update_cache' => true, 151 193 ); … … 223 265 * @return array|false An array of results indexed by plugin file, or false if unable to connect to the filesystem. 224 266 */ 225 267 public function bulk_upgrade( $plugins, $args = array() ) { 226 227 268 $defaults = array( 228 269 'clear_update_cache' => true, 229 270 ); … … 349 390 public function check_package( $source ) { 350 391 global $wp_filesystem; 351 392 393 $this->new_plugin_data = []; 394 352 395 if ( is_wp_error( $source ) ) { 353 396 return $source; 354 397 } … … 359 402 } 360 403 361 404 // Check that the folder contains at least 1 valid plugin. 362 $plugins_found = false; 363 $files = glob( $working_directory . '*.php' ); 405 $files = glob( $working_directory . '*.php' ); 364 406 if ( $files ) { 365 407 foreach ( $files as $file ) { 366 408 $info = get_plugin_data( $file, false, false ); 367 409 if ( ! empty( $info['Name'] ) ) { 368 $ plugins_found = true;410 $this->new_plugin_data = $info; 369 411 break; 370 412 } 371 413 } 372 414 } 373 415 374 if ( ! $plugins_found) {416 if ( empty( $this->new_plugin_data ) ) { 375 417 return new WP_Error( 'incompatible_archive_no_plugins', $this->strings['incompatible_archive'], __( 'No valid plugins were found.' ) ); 376 418 } 377 419 -
src/wp-admin/includes/class-theme-installer-skin.php
18 18 class Theme_Installer_Skin extends WP_Upgrader_Skin { 19 19 public $api; 20 20 public $type; 21 public $url; 22 public $overwrite; 21 23 24 private $is_downgrading = false; 25 22 26 /** 23 27 * @param array $args 24 28 */ 25 29 public function __construct( $args = array() ) { 26 30 $defaults = array( 27 'type' => 'web', 28 'url' => '', 29 'theme' => '', 30 'nonce' => '', 31 'title' => '', 31 'type' => 'web', 32 'url' => '', 33 'theme' => '', 34 'nonce' => '', 35 'title' => '', 36 'overwrite' => '', 32 37 ); 33 38 $args = wp_parse_args( $args, $defaults ); 34 39 35 $this->type = $args['type']; 36 $this->api = isset( $args['api'] ) ? $args['api'] : array(); 40 $this->type = $args['type']; 41 $this->url = $args['url']; 42 $this->api = isset( $args['api'] ) ? $args['api'] : array(); 43 $this->overwrite = $args['overwrite']; 37 44 38 45 parent::__construct( $args ); 39 46 } … … 53 60 /** 54 61 */ 55 62 public function after() { 63 if ( $this->do_overwrite() ) { 64 return; 65 } 66 56 67 if ( empty( $this->upgrader->result['destination_name'] ) ) { 57 68 return; 58 69 } … … 130 141 131 142 if ( ! $this->result || is_wp_error( $this->result ) || is_network_admin() || ! current_user_can( 'switch_themes' ) ) { 132 143 unset( $install_actions['activate'], $install_actions['preview'] ); 144 } elseif ( get_option( 'template' ) === $stylesheet ) { 145 unset( $install_actions['activate'] ); 133 146 } 134 147 135 148 /** … … 147 160 $this->feedback( implode( ' | ', (array) $install_actions ) ); 148 161 } 149 162 } 163 164 /** 165 * Check if the theme can be overwritten and output the HTML for overwriting a theme on upload. 166 * 167 * @since 5.5.0 168 * 169 * @return bool Whether the theme can be overwritten and HTML was outputted. 170 */ 171 private function do_overwrite() { 172 if ( 'upload' !== $this->type || ! is_wp_error( $this->result ) || 'folder_exists' !== $this->result->get_error_code() ) { 173 return false; 174 } 175 176 $folder = $this->result->get_error_data( 'folder_exists' ); 177 $folder = rtrim( $folder, '/' ); 178 179 $current_theme_data = false; 180 $all_themes = wp_get_themes( array( 'errors' => null ) ); 181 foreach ( $all_themes as $theme ) { 182 if ( rtrim( $theme->get_stylesheet_directory(), '/' ) !== $folder ) { 183 continue; 184 } 185 186 $current_theme_data = $theme; 187 } 188 189 if ( empty( $current_theme_data ) || empty( $this->upgrader->new_theme_data ) ) { 190 return false; 191 } 192 193 $this->is_downgrading = version_compare( $current_theme_data['Version'], $this->upgrader->new_theme_data['Version'], '>' ); 194 195 $is_invalid_parent = false; 196 if ( ! empty( $this->upgrader->new_theme_data['Template'] ) ) { 197 $is_invalid_parent = ! in_array( $this->upgrader->new_theme_data['Template'], array_keys( $all_themes ), true ); 198 } 199 200 $rows = array( 201 'Name' => __( 'Theme Name' ), 202 'Version' => __( 'Version' ), 203 'Author' => __( 'Author' ), 204 'RequiresWP' => __( 'Required WordPress version' ), 205 'RequiresPHP' => __( 'Required PHP version' ), 206 'Template' => __( 'Parent Theme' ), 207 ); 208 209 $table = '<table class="compare-themes-table"><tbody>'; 210 $table .= '<tr><th></th><th>' . esc_html( __( 'Current' ) ) . '</th><th>' . esc_html( __( 'Uploaded' ) ) . '</th></tr>'; 211 212 $is_same_theme = true; // Let's consider only these rows 213 foreach ( $rows as $field => $label ) { 214 $old_value = $current_theme_data->display( $field, false ); 215 $old_value = $old_value ? $old_value : '-'; 216 217 $new_value = ! empty( $this->upgrader->new_theme_data[ $field ] ) ? $this->upgrader->new_theme_data[ $field ] : '-'; 218 219 if ( $old_value === $new_value && '-' === $new_value && 'Template' === $field ) { 220 continue; 221 } 222 223 $is_same_theme = $is_same_theme && ( $old_value === $new_value ); 224 225 $diff_field = ( 'Version' !== $field && $new_value !== $old_value ); 226 $diff_version = ( 'Version' === $field && $this->is_downgrading ); 227 $invalid_parent = false; 228 229 if ( 'Template' === $field && $is_invalid_parent ) { 230 $invalid_parent = true; 231 $new_value .= ' ' . __( '(not found)' ); 232 } 233 234 $table .= ( $diff_field || $diff_version || $invalid_parent ) ? '<tr class="warning">' : '<tr>'; 235 $table .= '<td>' . $label . '</td><td>' . esc_html( $old_value ) . '</td><td>' . esc_html( $new_value ) . '</td></tr>'; 236 } 237 238 $table .= '</tbody></table>'; 239 240 $this->feedback( 'compare_before_overwrite' ); 241 242 if ( $is_same_theme ) { 243 $this->feedback( 'reuploading_theme' ); 244 } 245 246 // Check errors for current theme 247 if ( is_wp_error( $current_theme_data->errors() ) ) { 248 $this->feedback( 'current_theme_has_errors', $current_theme_data->errors()->get_error_message() ); 249 } 250 251 /** 252 * Filters the compare table output for overwrite a theme package on upload. 253 * 254 * @since 5.5.0 255 * 256 * @param string $table The output table with Name, Version, Author, RequiresWP and RequiresPHP info. 257 * @param array $current_theme_data Array with current theme data. 258 * @param array $new_theme_data Array with uploaded theme data. 259 */ 260 echo apply_filters( 'install_theme_overwrite_comparison', $table, $current_theme_data, $this->upgrader->new_theme_data ); 261 262 $install_actions = array( 263 'themes_page' => sprintf( 264 '<a href="%s" target="_parent">%s</a>', 265 self_admin_url( 'theme-install.php' ), 266 __( 'Cancel and go back' ) 267 ), 268 ); 269 270 $can_update = true; 271 272 if ( ! empty( $this->upgrader->new_theme_data['RequiresPHP'] ) && version_compare( phpversion(), $this->upgrader->new_theme_data['RequiresPHP'], '<' ) ) { 273 $error = sprintf( 274 /* translators: 1: Current PHP version, 2: Version required by the uploaded theme. */ 275 __( 'The theme cannot be updated. The PHP version on your server is %1$s, however the uploaded theme requires %2$s.' ), 276 phpversion(), 277 $this->upgrader->new_theme_data['RequiresPHP'] 278 ); 279 280 $this->feedback( '<div class="notice notice-error inline"><p>' . esc_html( $error ) . '</p></div>' ); 281 $can_update = false; 282 } 283 284 if ( ! empty( $this->upgrader->new_theme_data['RequiresWP'] ) && version_compare( $GLOBALS['wp_version'], $this->upgrader->new_theme_data['RequiresWP'], '<' ) ) { 285 $error = sprintf( 286 /* translators: 1: Current WordPress version, 2: Version required by the uploaded theme. */ 287 __( 'The theme cannot be updated. Your WordPress version is %1$s, however the uploaded theme requires %2$s.' ), 288 $GLOBALS['wp_version'], 289 $this->upgrader->new_theme_data['RequiresWP'] 290 ); 291 292 $this->feedback( '<div class="notice notice-error inline"><p>' . esc_html( $error ) . '</p></div>' ); 293 $can_update = false; 294 } 295 296 if ( $can_update ) { 297 $overwrite = 'update-theme'; 298 $label = __( 'Remove current and install the uploaded version' ); 299 300 if ( $this->is_downgrading ) { 301 $overwrite = 'downgrade-theme'; 302 303 if ( isset( $this->upgrader->new_theme_data['Version'] ) ) { 304 $label = sprintf( __( 'Remove current and install version %s' ), $this->upgrader->new_theme_data['Version'] ); 305 } 306 } 307 308 $install_actions['ovewrite_theme'] = sprintf( 309 '<a class="ovewrite-uploaded-theme" href="%s" target="_parent">%s</a>', 310 wp_nonce_url( add_query_arg( 'overwrite', $overwrite, $this->url ), 'theme-upload' ), 311 esc_html( $label ) 312 ); 313 314 $warning = __( '<strong>Important:</strong> Before updating, please <a href="https://wordpress.org/support/article/wordpress-backups/">back up your database and files</a>.' ); 315 $this->feedback( '<div class="notice notice-warning inline"><p>' . $warning . '</p></div>' ); 316 } 317 318 /** 319 * Filters the list of action links available following a single theme installation failed but ovewrite is allowed. 320 * 321 * @since 5.5.0 322 * 323 * @param string[] $install_actions Array of theme action links. 324 * @param object $api Object containing WordPress.org API theme data. 325 * @param array $new_theme_data Array with uploaded theme data. 326 */ 327 $install_actions = apply_filters( 'install_theme_ovewrite_actions', $install_actions, $this->api, $this->upgrader->new_theme_data ); 328 if ( ! empty( $install_actions ) ) { 329 $this->feedback( implode( ' | ', (array) $install_actions ) ); 330 } 331 332 return true; 333 } 334 150 335 } -
src/wp-admin/includes/class-theme-upgrader.php
38 38 public $bulk = false; 39 39 40 40 /** 41 * New theme info. 42 * 43 * @since 5.5.0 44 * @var array $new_theme_data 45 * 46 * @see check_package() 47 */ 48 public $new_theme_data = array(); 49 50 /** 41 51 * Initialize the upgrade strings. 42 52 * 43 53 * @since 2.8.0 … … 65 75 $this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s…' ), '<span class="code">%s</span>' ); 66 76 $this->strings['unpack_package'] = __( 'Unpacking the package…' ); 67 77 $this->strings['installing_package'] = __( 'Installing the theme…' ); 78 $this->strings['remove_old'] = __( 'Removing the old version of the theme…' ); 79 $this->strings['remove_old_failed'] = __( 'Could not remove the old theme.' ); 68 80 $this->strings['no_files'] = __( 'The theme contains no files.' ); 69 81 $this->strings['process_failed'] = __( 'Theme installation failed.' ); 70 82 $this->strings['process_success'] = __( 'Theme installed successfully.' ); … … 79 91 $this->strings['parent_theme_install_success'] = __( 'Successfully installed the parent theme, <strong>%1$s %2$s</strong>.' ); 80 92 /* translators: %s: Theme name. */ 81 93 $this->strings['parent_theme_not_found'] = sprintf( __( '<strong>The parent theme could not be found.</strong> You will need to install the parent theme, %s, before you can use this child theme.' ), '<strong>%s</strong>' ); 94 95 $this->strings['compare_before_overwrite'] = __( 'Theme information:' ); 96 $this->strings['reuploading_theme'] = __( 'Seems you have uploaded a theme that is already installed.' ); 97 $this->strings['current_theme_has_errors'] = __( 'The current theme has the follow error: "%s".' ); 98 99 if ( 'update-theme' === $this->skin->overwrite ) { 100 $this->strings['installing_package'] = __( 'Updating the theme…' ); 101 $this->strings['process_failed'] = __( 'Theme update failed.' ); 102 $this->strings['process_success'] = __( 'Theme updated successfully.' ); 103 } 104 105 if ( 'downgrade-theme' === $this->skin->overwrite ) { 106 $this->strings['installing_package'] = __( 'Downgrading the theme…' ); 107 $this->strings['process_failed'] = __( 'Theme downgrade failed.' ); 108 $this->strings['process_success'] = __( 'Theme downgraded successfully.' ); 109 } 82 110 } 83 111 84 112 /** … … 200 228 * @return bool|WP_Error True if the installation was successful, false or a WP_Error object otherwise. 201 229 */ 202 230 public function install( $package, $args = array() ) { 203 204 231 $defaults = array( 205 232 'clear_update_cache' => true, 233 'overwrite_package' => false, // Do not overwrite files. 206 234 ); 207 235 $parsed_args = wp_parse_args( $args, $defaults ); 208 236 … … 220 248 array( 221 249 'package' => $package, 222 250 'destination' => get_theme_root(), 223 'clear_destination' => false, // Do not overwrite files.251 'clear_destination' => $args['overwrite_package'], 224 252 'clear_working' => true, 225 253 'hook_extra' => array( 226 254 'type' => 'theme', … … 240 268 // Refresh the Theme Update information. 241 269 wp_clean_themes_cache( $parsed_args['clear_update_cache'] ); 242 270 271 if ( $parsed_args['overwrite_package'] ) { 272 /** 273 * Fires when the upgrader process a install forcing a package overwrite. 274 * 275 * @since 5.5.0 276 * 277 * @param string $package The package file. 278 * @param array $new_plugin_data The new theme data. 279 * @param string $package_type The package type (theme or theme). 280 */ 281 do_action( 'upgrader_overwrited_package', $package, $this->new_theme_data, 'theme' ); 282 } 283 243 284 return true; 244 285 } 245 286 … … 259 300 * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise. 260 301 */ 261 302 public function upgrade( $theme, $args = array() ) { 262 263 303 $defaults = array( 264 304 'clear_update_cache' => true, 265 305 ); … … 332 372 * @return array[]|false An array of results, or false if unable to connect to the filesystem. 333 373 */ 334 374 public function bulk_upgrade( $themes, $args = array() ) { 335 336 375 $defaults = array( 337 376 'clear_update_cache' => true, 338 377 ); … … 461 500 public function check_package( $source ) { 462 501 global $wp_filesystem; 463 502 503 $this->new_theme_data = array(); 504 464 505 if ( is_wp_error( $source ) ) { 465 506 return $source; 466 507 } … … 484 525 ); 485 526 } 486 527 528 // All these headers are needed on Theme_Installer_Skin::do_overwrite(). 487 529 $info = get_file_data( 488 530 $working_directory . 'style.css', 489 531 array( 490 'Name' => 'Theme Name', 491 'Template' => 'Template', 532 'Name' => 'Theme Name', 533 'Version' => 'Version', 534 'Author' => 'Author', 535 'Template' => 'Template', 536 'RequiresWP' => 'Requires at least', 537 'RequiresPHP' => 'Requires PHP', 492 538 ) 493 539 ); 494 540 … … 517 563 ); 518 564 } 519 565 566 $this->new_theme_data = $info; 520 567 return $source; 521 568 } 522 569 … … 640 687 * and the last result isn't set. 641 688 */ 642 689 public function theme_info( $theme = null ) { 643 644 690 if ( empty( $theme ) ) { 645 691 if ( ! empty( $this->result['destination_name'] ) ) { 646 692 $theme = $this->result['destination_name']; … … 648 694 return false; 649 695 } 650 696 } 651 return wp_get_theme( $theme ); 697 698 $theme = wp_get_theme( $theme ); 699 $theme->cache_delete(); 700 701 return $theme; 652 702 } 653 703 654 704 } -
src/wp-admin/includes/plugin-install.php
353 353 <form method="post" enctype="multipart/form-data" class="wp-upload-form" action="<?php echo self_admin_url( 'update.php?action=upload-plugin' ); ?>"> 354 354 <?php wp_nonce_field( 'plugin-upload' ); ?> 355 355 <label class="screen-reader-text" for="pluginzip"><?php _e( 'Plugin zip file' ); ?></label> 356 <input type="file" id="pluginzip" name="pluginzip" />356 <input type="file" id="pluginzip" name="pluginzip" accept=".zip" /> 357 357 <?php submit_button( __( 'Install Now' ), '', 'install-plugin-submit', false ); ?> 358 358 </form> 359 359 </div> -
src/wp-admin/includes/theme-install.php
183 183 <form method="post" enctype="multipart/form-data" class="wp-upload-form" action="<?php echo self_admin_url( 'update.php?action=upload-theme' ); ?>"> 184 184 <?php wp_nonce_field( 'theme-upload' ); ?> 185 185 <label class="screen-reader-text" for="themezip"><?php _e( 'Theme zip file' ); ?></label> 186 <input type="file" id="themezip" name="themezip" />186 <input type="file" id="themezip" name="themezip" accept=".zip"/> 187 187 <?php submit_button( __( 'Install Now' ), '', 'install-theme-submit', false ); ?> 188 188 </form> 189 189 <?php -
src/wp-admin/update.php
162 162 $url = add_query_arg( array( 'package' => $file_upload->id ), 'update.php?action=upload-plugin' ); 163 163 $type = 'upload'; // Install plugin type, From Web or an Upload. 164 164 165 $ upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( compact( 'type', 'title', 'nonce', 'url' ) ) );166 $ result = $upgrader->install( $file_upload->package );165 $overwrite = isset( $_GET['overwrite'] ) ? sanitize_text_field( $_GET['overwrite'] ) : ''; 166 $overwrite = in_array( $overwrite, array( 'update-plugin', 'downgrade-plugin' ), true ) ? $overwrite : ''; 167 167 168 $upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( compact( 'type', 'title', 'nonce', 'url', 'overwrite' ) ) ); 169 $result = $upgrader->install( $file_upload->package, [ 'overwrite_package' => $overwrite ] ); 170 168 171 if ( $result || is_wp_error( $result ) ) { 169 172 $file_upload->cleanup(); 170 173 } … … 282 285 $url = add_query_arg( array( 'package' => $file_upload->id ), 'update.php?action=upload-theme' ); 283 286 $type = 'upload'; // Install theme type, From Web or an Upload. 284 287 285 $ upgrader = new Theme_Upgrader( new Theme_Installer_Skin( compact( 'type', 'title', 'nonce', 'url' ) ) );286 $ result = $upgrader->install( $file_upload->package );288 $overwrite = isset( $_GET['overwrite'] ) ? sanitize_text_field( $_GET['overwrite'] ) : ''; 289 $overwrite = in_array( $overwrite, array( 'update-theme', 'downgrade-theme' ), true ) ? $overwrite : ''; 287 290 291 $upgrader = new Theme_Upgrader( new Theme_Installer_Skin( compact( 'type', 'title', 'nonce', 'url', 'overwrite' ) ) ); 292 $result = $upgrader->install( $file_upload->package, [ 'overwrite_package' => $overwrite ] ); 293 288 294 if ( $result || is_wp_error( $result ) ) { 289 295 $file_upload->cleanup(); 290 296 }