Changeset 25227
- Timestamp:
- 09/04/2013 06:34:38 AM (12 years ago)
- Location:
- trunk/src/wp-admin/includes
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/includes/class-wp-upgrader-skins.php
r25226 r25227 1 1 <?php 2 2 /** 3 * A File upgrader class for WordPress. 4 * 5 * This set of classes are designed to be used to upgrade/install a local set of files on the filesystem via the Filesystem Abstraction classes. 6 * 7 * @link http://trac.wordpress.org/ticket/7875 consolidate plugin/theme/core upgrade/install functions 3 * The User Interface "Skins" for the WordPress File Upgrader 8 4 * 9 5 * @package WordPress … … 13 9 14 10 /** 15 * WordPress Upgrader class for Upgrading/Installing a local set of files via the Filesystem Abstraction classes from a Zip file.16 *17 * @TODO More Detailed docs, for methods as well.18 *19 * @package WordPress20 * @subpackage Upgrader21 * @since 2.8.022 */23 class WP_Upgrader {24 var $strings = array();25 var $skin = null;26 var $result = array();27 28 function __construct($skin = null) {29 if ( null == $skin )30 $this->skin = new WP_Upgrader_Skin();31 else32 $this->skin = $skin;33 }34 35 function init() {36 $this->skin->set_upgrader($this);37 $this->generic_strings();38 }39 40 function generic_strings() {41 $this->strings['bad_request'] = __('Invalid Data provided.');42 $this->strings['fs_unavailable'] = __('Could not access filesystem.');43 $this->strings['fs_error'] = __('Filesystem error.');44 $this->strings['fs_no_root_dir'] = __('Unable to locate WordPress Root directory.');45 $this->strings['fs_no_content_dir'] = __('Unable to locate WordPress Content directory (wp-content).');46 $this->strings['fs_no_plugins_dir'] = __('Unable to locate WordPress Plugin directory.');47 $this->strings['fs_no_themes_dir'] = __('Unable to locate WordPress Theme directory.');48 /* translators: %s: directory name */49 $this->strings['fs_no_folder'] = __('Unable to locate needed folder (%s).');50 51 $this->strings['download_failed'] = __('Download failed.');52 $this->strings['installing_package'] = __('Installing the latest version…');53 $this->strings['no_files'] = __('The package contains no files.');54 $this->strings['folder_exists'] = __('Destination folder already exists.');55 $this->strings['mkdir_failed'] = __('Could not create directory.');56 $this->strings['incompatible_archive'] = __('The package could not be installed.');57 58 $this->strings['maintenance_start'] = __('Enabling Maintenance mode…');59 $this->strings['maintenance_end'] = __('Disabling Maintenance mode…');60 }61 62 function fs_connect( $directories = array() ) {63 global $wp_filesystem;64 65 if ( false === ($credentials = $this->skin->request_filesystem_credentials()) )66 return false;67 68 if ( ! WP_Filesystem($credentials) ) {69 $error = true;70 if ( is_object($wp_filesystem) && $wp_filesystem->errors->get_error_code() )71 $error = $wp_filesystem->errors;72 $this->skin->request_filesystem_credentials($error); //Failed to connect, Error and request again73 return false;74 }75 76 if ( ! is_object($wp_filesystem) )77 return new WP_Error('fs_unavailable', $this->strings['fs_unavailable'] );78 79 if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() )80 return new WP_Error('fs_error', $this->strings['fs_error'], $wp_filesystem->errors);81 82 foreach ( (array)$directories as $dir ) {83 switch ( $dir ) {84 case ABSPATH:85 if ( ! $wp_filesystem->abspath() )86 return new WP_Error('fs_no_root_dir', $this->strings['fs_no_root_dir']);87 break;88 case WP_CONTENT_DIR:89 if ( ! $wp_filesystem->wp_content_dir() )90 return new WP_Error('fs_no_content_dir', $this->strings['fs_no_content_dir']);91 break;92 case WP_PLUGIN_DIR:93 if ( ! $wp_filesystem->wp_plugins_dir() )94 return new WP_Error('fs_no_plugins_dir', $this->strings['fs_no_plugins_dir']);95 break;96 case get_theme_root():97 if ( ! $wp_filesystem->wp_themes_dir() )98 return new WP_Error('fs_no_themes_dir', $this->strings['fs_no_themes_dir']);99 break;100 default:101 if ( ! $wp_filesystem->find_folder($dir) )102 return new WP_Error( 'fs_no_folder', sprintf( $this->strings['fs_no_folder'], esc_html( basename( $dir ) ) ) );103 break;104 }105 }106 return true;107 } //end fs_connect();108 109 function download_package($package) {110 111 if ( ! preg_match('!^(http|https|ftp)://!i', $package) && file_exists($package) ) //Local file or remote?112 return $package; //must be a local file..113 114 if ( empty($package) )115 return new WP_Error('no_package', $this->strings['no_package']);116 117 $this->skin->feedback('downloading_package', $package);118 119 $download_file = download_url($package);120 121 if ( is_wp_error($download_file) )122 return new WP_Error('download_failed', $this->strings['download_failed'], $download_file->get_error_message());123 124 return $download_file;125 }126 127 function unpack_package($package, $delete_package = true) {128 global $wp_filesystem;129 130 $this->skin->feedback('unpack_package');131 132 $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';133 134 //Clean up contents of upgrade directory beforehand.135 $upgrade_files = $wp_filesystem->dirlist($upgrade_folder);136 if ( !empty($upgrade_files) ) {137 foreach ( $upgrade_files as $file )138 $wp_filesystem->delete($upgrade_folder . $file['name'], true);139 }140 141 //We need a working directory142 $working_dir = $upgrade_folder . basename($package, '.zip');143 144 // Clean up working directory145 if ( $wp_filesystem->is_dir($working_dir) )146 $wp_filesystem->delete($working_dir, true);147 148 // Unzip package to working directory149 $result = unzip_file($package, $working_dir); //TODO optimizations, Copy when Move/Rename would suffice?150 151 // Once extracted, delete the package if required.152 if ( $delete_package )153 unlink($package);154 155 if ( is_wp_error($result) ) {156 $wp_filesystem->delete($working_dir, true);157 if ( 'incompatible_archive' == $result->get_error_code() ) {158 return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() );159 }160 return $result;161 }162 163 return $working_dir;164 }165 166 function install_package($args = array()) {167 global $wp_filesystem, $wp_theme_directories;168 169 $defaults = array( 'source' => '', 'destination' => '', //Please always pass these170 'clear_destination' => false, 'clear_working' => false,171 'abort_if_destination_exists' => true,172 'hook_extra' => array());173 174 $args = wp_parse_args($args, $defaults);175 extract($args);176 177 @set_time_limit( 300 );178 179 if ( empty($source) || empty($destination) )180 return new WP_Error('bad_request', $this->strings['bad_request']);181 182 $this->skin->feedback('installing_package');183 184 $res = apply_filters('upgrader_pre_install', true, $hook_extra);185 if ( is_wp_error($res) )186 return $res;187 188 //Retain the Original source and destinations189 $remote_source = $source;190 $local_destination = $destination;191 192 $source_files = array_keys( $wp_filesystem->dirlist($remote_source) );193 $remote_destination = $wp_filesystem->find_folder($local_destination);194 195 //Locate which directory to copy to the new folder, This is based on the actual folder holding the files.196 if ( 1 == count($source_files) && $wp_filesystem->is_dir( trailingslashit($source) . $source_files[0] . '/') ) //Only one folder? Then we want its contents.197 $source = trailingslashit($source) . trailingslashit($source_files[0]);198 elseif ( count($source_files) == 0 )199 return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $this->strings['no_files'] ); //There are no files?200 else //It's only a single file, the upgrader will use the foldername of this file as the destination folder. foldername is based on zip filename.201 $source = trailingslashit($source);202 203 //Hook ability to change the source file location..204 $source = apply_filters('upgrader_source_selection', $source, $remote_source, $this);205 if ( is_wp_error($source) )206 return $source;207 208 //Has the source location changed? If so, we need a new source_files list.209 if ( $source !== $remote_source )210 $source_files = array_keys( $wp_filesystem->dirlist($source) );211 212 // Protection against deleting files in any important base directories.213 // Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the destination directory (WP_PLUGIN_DIR / wp-content/themes)214 // intending to copy the directory into the directory, whilst they pass the source as the actual files to copy.215 $protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' );216 if ( is_array( $wp_theme_directories ) )217 $protected_directories = array_merge( $protected_directories, $wp_theme_directories );218 if ( in_array( $destination, $protected_directories ) ) {219 $remote_destination = trailingslashit($remote_destination) . trailingslashit(basename($source));220 $destination = trailingslashit($destination) . trailingslashit(basename($source));221 }222 223 if ( $clear_destination ) {224 //We're going to clear the destination if there's something there225 $this->skin->feedback('remove_old');226 $removed = true;227 if ( $wp_filesystem->exists($remote_destination) )228 $removed = $wp_filesystem->delete($remote_destination, true);229 $removed = apply_filters('upgrader_clear_destination', $removed, $local_destination, $remote_destination, $hook_extra);230 231 if ( is_wp_error($removed) )232 return $removed;233 else if ( ! $removed )234 return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);235 } elseif ( $abort_if_destination_exists && $wp_filesystem->exists($remote_destination) ) {236 //If we're not clearing the destination folder and something exists there already, Bail.237 //But first check to see if there are actually any files in the folder.238 $_files = $wp_filesystem->dirlist($remote_destination);239 if ( ! empty($_files) ) {240 $wp_filesystem->delete($remote_source, true); //Clear out the source files.241 return new WP_Error('folder_exists', $this->strings['folder_exists'], $remote_destination );242 }243 }244 245 //Create destination if needed246 if ( !$wp_filesystem->exists($remote_destination) )247 if ( !$wp_filesystem->mkdir($remote_destination, FS_CHMOD_DIR) )248 return new WP_Error('mkdir_failed', $this->strings['mkdir_failed'], $remote_destination);249 250 // Copy new version of item into place.251 $result = copy_dir($source, $remote_destination);252 if ( is_wp_error($result) ) {253 if ( $clear_working )254 $wp_filesystem->delete($remote_source, true);255 return $result;256 }257 258 //Clear the Working folder?259 if ( $clear_working )260 $wp_filesystem->delete($remote_source, true);261 262 $destination_name = basename( str_replace($local_destination, '', $destination) );263 if ( '.' == $destination_name )264 $destination_name = '';265 266 $this->result = compact('local_source', 'source', 'source_name', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination', 'delete_source_dir');267 268 $res = apply_filters('upgrader_post_install', true, $hook_extra, $this->result);269 if ( is_wp_error($res) ) {270 $this->result = $res;271 return $res;272 }273 274 //Bombard the calling function will all the info which we've just used.275 return $this->result;276 }277 278 function run($options) {279 280 $defaults = array( 'package' => '', //Please always pass this.281 'destination' => '', //And this282 'clear_destination' => false,283 'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please284 'clear_working' => true,285 'is_multi' => false,286 'hook_extra' => array() //Pass any extra $hook_extra args here, this will be passed to any hooked filters.287 );288 289 $options = wp_parse_args($options, $defaults);290 extract($options);291 292 //Connect to the Filesystem first.293 $res = $this->fs_connect( array(WP_CONTENT_DIR, $destination) );294 if ( ! $res ) //Mainly for non-connected filesystem.295 return false;296 297 if ( is_wp_error($res) ) {298 $this->skin->error($res);299 return $res;300 }301 302 if ( !$is_multi ) // call $this->header separately if running multiple times303 $this->skin->header();304 305 $this->skin->before();306 307 //Download the package (Note, This just returns the filename of the file if the package is a local file)308 $download = $this->download_package( $package );309 if ( is_wp_error($download) ) {310 $this->skin->error($download);311 $this->skin->after();312 return $download;313 }314 315 $delete_package = ($download != $package); // Do not delete a "local" file316 317 //Unzips the file into a temporary directory318 $working_dir = $this->unpack_package( $download, $delete_package );319 if ( is_wp_error($working_dir) ) {320 $this->skin->error($working_dir);321 $this->skin->after();322 return $working_dir;323 }324 325 //With the given options, this installs it to the destination directory.326 $result = $this->install_package( array(327 'source' => $working_dir,328 'destination' => $destination,329 'clear_destination' => $clear_destination,330 'abort_if_destination_exists' => $abort_if_destination_exists,331 'clear_working' => $clear_working,332 'hook_extra' => $hook_extra333 ) );334 $this->skin->set_result($result);335 if ( is_wp_error($result) ) {336 $this->skin->error($result);337 $this->skin->feedback('process_failed');338 } else {339 //Install Succeeded340 $this->skin->feedback('process_success');341 }342 $this->skin->after();343 344 if ( !$is_multi )345 $this->skin->footer();346 347 return $result;348 }349 350 function maintenance_mode($enable = false) {351 global $wp_filesystem;352 $file = $wp_filesystem->abspath() . '.maintenance';353 if ( $enable ) {354 $this->skin->feedback('maintenance_start');355 // Create maintenance file to signal that we are upgrading356 $maintenance_string = '<?php $upgrading = ' . time() . '; ?>';357 $wp_filesystem->delete($file);358 $wp_filesystem->put_contents($file, $maintenance_string, FS_CHMOD_FILE);359 } else if ( !$enable && $wp_filesystem->exists($file) ) {360 $this->skin->feedback('maintenance_end');361 $wp_filesystem->delete($file);362 }363 }364 365 }366 367 /**368 * Plugin Upgrader class for WordPress Plugins, It is designed to upgrade/install plugins from a local zip, remote zip URL, or uploaded zip file.369 *370 * @TODO More Detailed docs, for methods as well.371 *372 * @package WordPress373 * @subpackage Upgrader374 * @since 2.8.0375 */376 class Plugin_Upgrader extends WP_Upgrader {377 378 var $result;379 var $bulk = false;380 var $show_before = '';381 382 function upgrade_strings() {383 $this->strings['up_to_date'] = __('The plugin is at the latest version.');384 $this->strings['no_package'] = __('Update package not available.');385 $this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>…');386 $this->strings['unpack_package'] = __('Unpacking the update…');387 $this->strings['remove_old'] = __('Removing the old version of the plugin…');388 $this->strings['remove_old_failed'] = __('Could not remove the old plugin.');389 $this->strings['process_failed'] = __('Plugin update failed.');390 $this->strings['process_success'] = __('Plugin updated successfully.');391 }392 393 function install_strings() {394 $this->strings['no_package'] = __('Install package not available.');395 $this->strings['downloading_package'] = __('Downloading install package from <span class="code">%s</span>…');396 $this->strings['unpack_package'] = __('Unpacking the package…');397 $this->strings['installing_package'] = __('Installing the plugin…');398 $this->strings['no_files'] = __('The plugin contains no files.');399 $this->strings['process_failed'] = __('Plugin install failed.');400 $this->strings['process_success'] = __('Plugin installed successfully.');401 }402 403 function install($package) {404 405 $this->init();406 $this->install_strings();407 408 add_filter('upgrader_source_selection', array(&$this, 'check_package') );409 410 $this->run(array(411 'package' => $package,412 'destination' => WP_PLUGIN_DIR,413 'clear_destination' => false, //Do not overwrite files.414 'clear_working' => true,415 'hook_extra' => array()416 ));417 418 remove_filter('upgrader_source_selection', array(&$this, 'check_package') );419 420 if ( ! $this->result || is_wp_error($this->result) )421 return $this->result;422 423 // Force refresh of plugin update information424 delete_site_transient('update_plugins');425 wp_cache_delete( 'plugins', 'plugins' );426 do_action( 'upgrader_process_complete', $this, array( 'action' => 'install', 'type' => 'plugin' ), $package );427 428 return true;429 }430 431 function upgrade($plugin) {432 433 $this->init();434 $this->upgrade_strings();435 436 $current = get_site_transient( 'update_plugins' );437 if ( !isset( $current->response[ $plugin ] ) ) {438 $this->skin->before();439 $this->skin->set_result(false);440 $this->skin->error('up_to_date');441 $this->skin->after();442 return false;443 }444 445 // Get the URL to the zip file446 $r = $current->response[ $plugin ];447 448 add_filter('upgrader_pre_install', array(&$this, 'deactivate_plugin_before_upgrade'), 10, 2);449 add_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'), 10, 4);450 //'source_selection' => array(&$this, 'source_selection'), //there's a trac ticket to move up the directory for zip's which are made a bit differently, useful for non-.org plugins.451 452 $this->run(array(453 'package' => $r->package,454 'destination' => WP_PLUGIN_DIR,455 'clear_destination' => true,456 'clear_working' => true,457 'hook_extra' => array(458 'plugin' => $plugin459 )460 ));461 462 // Cleanup our hooks, in case something else does a upgrade on this connection.463 remove_filter('upgrader_pre_install', array(&$this, 'deactivate_plugin_before_upgrade'));464 remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));465 466 if ( ! $this->result || is_wp_error($this->result) )467 return $this->result;468 469 // Force refresh of plugin update information470 delete_site_transient('update_plugins');471 wp_cache_delete( 'plugins', 'plugins' );472 do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'plugin' ), $plugin );473 474 return true;475 }476 477 function bulk_upgrade($plugins) {478 479 $this->init();480 $this->bulk = true;481 $this->upgrade_strings();482 483 $current = get_site_transient( 'update_plugins' );484 485 add_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'), 10, 4);486 487 $this->skin->header();488 489 // Connect to the Filesystem first.490 $res = $this->fs_connect( array(WP_CONTENT_DIR, WP_PLUGIN_DIR) );491 if ( ! $res ) {492 $this->skin->footer();493 return false;494 }495 496 $this->skin->bulk_header();497 498 // Only start maintenance mode if:499 // - running Multisite and there are one or more plugins specified, OR500 // - a plugin with an update available is currently active.501 // @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.502 $maintenance = ( is_multisite() && ! empty( $plugins ) );503 foreach ( $plugins as $plugin )504 $maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) );505 if ( $maintenance )506 $this->maintenance_mode(true);507 508 $results = array();509 510 $this->update_count = count($plugins);511 $this->update_current = 0;512 foreach ( $plugins as $plugin ) {513 $this->update_current++;514 $this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);515 516 if ( !isset( $current->response[ $plugin ] ) ) {517 $this->skin->set_result(true);518 $this->skin->before();519 $this->skin->feedback('up_to_date');520 $this->skin->after();521 $results[$plugin] = true;522 continue;523 }524 525 // Get the URL to the zip file526 $r = $current->response[ $plugin ];527 528 $this->skin->plugin_active = is_plugin_active($plugin);529 530 $result = $this->run(array(531 'package' => $r->package,532 'destination' => WP_PLUGIN_DIR,533 'clear_destination' => true,534 'clear_working' => true,535 'is_multi' => true,536 'hook_extra' => array(537 'plugin' => $plugin538 )539 ));540 541 $results[$plugin] = $this->result;542 543 // Prevent credentials auth screen from displaying multiple times544 if ( false === $result )545 break;546 } //end foreach $plugins547 548 $this->maintenance_mode(false);549 550 $this->skin->bulk_footer();551 552 $this->skin->footer();553 554 // Cleanup our hooks, in case something else does a upgrade on this connection.555 remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));556 557 // Force refresh of plugin update information558 delete_site_transient('update_plugins');559 wp_cache_delete( 'plugins', 'plugins' );560 do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'plugin', 'bulk' => true ), $plugins );561 562 return $results;563 }564 565 function check_package($source) {566 global $wp_filesystem;567 568 if ( is_wp_error($source) )569 return $source;570 571 $working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit(WP_CONTENT_DIR), $source);572 if ( ! is_dir($working_directory) ) // Sanity check, if the above fails, lets not prevent installation.573 return $source;574 575 // Check the folder contains at least 1 valid plugin.576 $plugins_found = false;577 foreach ( glob( $working_directory . '*.php' ) as $file ) {578 $info = get_plugin_data($file, false, false);579 if ( !empty( $info['Name'] ) ) {580 $plugins_found = true;581 break;582 }583 }584 585 if ( ! $plugins_found )586 return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], __('No valid plugins were found.') );587 588 return $source;589 }590 591 //return plugin info.592 function plugin_info() {593 if ( ! is_array($this->result) )594 return false;595 if ( empty($this->result['destination_name']) )596 return false;597 598 $plugin = get_plugins('/' . $this->result['destination_name']); //Ensure to pass with leading slash599 if ( empty($plugin) )600 return false;601 602 $pluginfiles = array_keys($plugin); //Assume the requested plugin is the first in the list603 604 return $this->result['destination_name'] . '/' . $pluginfiles[0];605 }606 607 //Hooked to pre_install608 function deactivate_plugin_before_upgrade($return, $plugin) {609 610 if ( is_wp_error($return) ) //Bypass.611 return $return;612 613 $plugin = isset($plugin['plugin']) ? $plugin['plugin'] : '';614 if ( empty($plugin) )615 return new WP_Error('bad_request', $this->strings['bad_request']);616 617 if ( is_plugin_active($plugin) ) {618 //Deactivate the plugin silently, Prevent deactivation hooks from running.619 deactivate_plugins($plugin, true);620 }621 }622 623 //Hooked to upgrade_clear_destination624 function delete_old_plugin($removed, $local_destination, $remote_destination, $plugin) {625 global $wp_filesystem;626 627 if ( is_wp_error($removed) )628 return $removed; //Pass errors through.629 630 $plugin = isset($plugin['plugin']) ? $plugin['plugin'] : '';631 if ( empty($plugin) )632 return new WP_Error('bad_request', $this->strings['bad_request']);633 634 $plugins_dir = $wp_filesystem->wp_plugins_dir();635 $this_plugin_dir = trailingslashit( dirname($plugins_dir . $plugin) );636 637 if ( ! $wp_filesystem->exists($this_plugin_dir) ) //If it's already vanished.638 return $removed;639 640 // If plugin is in its own directory, recursively delete the directory.641 if ( strpos($plugin, '/') && $this_plugin_dir != $plugins_dir ) //base check on if plugin includes directory separator AND that it's not the root plugin folder642 $deleted = $wp_filesystem->delete($this_plugin_dir, true);643 else644 $deleted = $wp_filesystem->delete($plugins_dir . $plugin);645 646 if ( ! $deleted )647 return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);648 649 return true;650 }651 }652 653 /**654 * Theme Upgrader class for WordPress Themes, It is designed to upgrade/install themes from a local zip, remote zip URL, or uploaded zip file.655 *656 * @TODO More Detailed docs, for methods as well.657 *658 * @package WordPress659 * @subpackage Upgrader660 * @since 2.8.0661 */662 class Theme_Upgrader extends WP_Upgrader {663 664 var $result;665 var $bulk = false;666 667 function upgrade_strings() {668 $this->strings['up_to_date'] = __('The theme is at the latest version.');669 $this->strings['no_package'] = __('Update package not available.');670 $this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>…');671 $this->strings['unpack_package'] = __('Unpacking the update…');672 $this->strings['remove_old'] = __('Removing the old version of the theme…');673 $this->strings['remove_old_failed'] = __('Could not remove the old theme.');674 $this->strings['process_failed'] = __('Theme update failed.');675 $this->strings['process_success'] = __('Theme updated successfully.');676 }677 678 function install_strings() {679 $this->strings['no_package'] = __('Install package not available.');680 $this->strings['downloading_package'] = __('Downloading install package from <span class="code">%s</span>…');681 $this->strings['unpack_package'] = __('Unpacking the package…');682 $this->strings['installing_package'] = __('Installing the theme…');683 $this->strings['no_files'] = __('The theme contains no files.');684 $this->strings['process_failed'] = __('Theme install failed.');685 $this->strings['process_success'] = __('Theme installed successfully.');686 /* translators: 1: theme name, 2: version */687 $this->strings['process_success_specific'] = __('Successfully installed the theme <strong>%1$s %2$s</strong>.');688 $this->strings['parent_theme_search'] = __('This theme requires a parent theme. Checking if it is installed…');689 /* translators: 1: theme name, 2: version */690 $this->strings['parent_theme_prepare_install'] = __('Preparing to install <strong>%1$s %2$s</strong>…');691 /* translators: 1: theme name, 2: version */692 $this->strings['parent_theme_currently_installed'] = __('The parent theme, <strong>%1$s %2$s</strong>, is currently installed.');693 /* translators: 1: theme name, 2: version */694 $this->strings['parent_theme_install_success'] = __('Successfully installed the parent theme, <strong>%1$s %2$s</strong>.');695 $this->strings['parent_theme_not_found'] = __('<strong>The parent theme could not be found.</strong> You will need to install the parent theme, <strong>%s</strong>, before you can use this child theme.');696 }697 698 function check_parent_theme_filter($install_result, $hook_extra, $child_result) {699 // Check to see if we need to install a parent theme700 $theme_info = $this->theme_info();701 702 if ( ! $theme_info->parent() )703 return $install_result;704 705 $this->skin->feedback( 'parent_theme_search' );706 707 if ( ! $theme_info->parent()->errors() ) {708 $this->skin->feedback( 'parent_theme_currently_installed', $theme_info->parent()->display('Name'), $theme_info->parent()->display('Version') );709 // We already have the theme, fall through.710 return $install_result;711 }712 713 // We don't have the parent theme, lets install it714 $api = themes_api('theme_information', array('slug' => $theme_info->get('Template'), 'fields' => array('sections' => false, 'tags' => false) ) ); //Save on a bit of bandwidth.715 716 if ( ! $api || is_wp_error($api) ) {717 $this->skin->feedback( 'parent_theme_not_found', $theme_info->get('Template') );718 // Don't show activate or preview actions after install719 add_filter('install_theme_complete_actions', array(&$this, 'hide_activate_preview_actions') );720 return $install_result;721 }722 723 // Backup required data we're going to override:724 $child_api = $this->skin->api;725 $child_success_message = $this->strings['process_success'];726 727 // Override them728 $this->skin->api = $api;729 $this->strings['process_success_specific'] = $this->strings['parent_theme_install_success'];//, $api->name, $api->version);730 731 $this->skin->feedback('parent_theme_prepare_install', $api->name, $api->version);732 733 add_filter('install_theme_complete_actions', '__return_false', 999); // Don't show any actions after installing the theme.734 735 // Install the parent theme736 $parent_result = $this->run( array(737 'package' => $api->download_link,738 'destination' => get_theme_root(),739 'clear_destination' => false, //Do not overwrite files.740 'clear_working' => true741 ) );742 743 if ( is_wp_error($parent_result) )744 add_filter('install_theme_complete_actions', array(&$this, 'hide_activate_preview_actions') );745 746 // Start cleaning up after the parents installation747 remove_filter('install_theme_complete_actions', '__return_false', 999);748 749 // Reset child's result and data750 $this->result = $child_result;751 $this->skin->api = $child_api;752 $this->strings['process_success'] = $child_success_message;753 754 return $install_result;755 }756 757 function hide_activate_preview_actions($actions) {758 unset($actions['activate'], $actions['preview']);759 return $actions;760 }761 762 function install($package) {763 764 $this->init();765 $this->install_strings();766 767 add_filter('upgrader_source_selection', array(&$this, 'check_package') );768 add_filter('upgrader_post_install', array(&$this, 'check_parent_theme_filter'), 10, 3);769 770 $options = array(771 'package' => $package,772 'destination' => get_theme_root(),773 'clear_destination' => false, //Do not overwrite files.774 'clear_working' => true775 );776 777 $this->run($options);778 779 remove_filter('upgrader_source_selection', array(&$this, 'check_package') );780 remove_filter('upgrader_post_install', array(&$this, 'check_parent_theme_filter'));781 782 if ( ! $this->result || is_wp_error($this->result) )783 return $this->result;784 785 // Force refresh of theme update information786 wp_clean_themes_cache();787 do_action( 'upgrader_process_complete', $this, array( 'action' => 'install', 'type' => 'theme' ), $package );788 789 return true;790 }791 792 function upgrade($theme) {793 794 $this->init();795 $this->upgrade_strings();796 797 // Is an update available?798 $current = get_site_transient( 'update_themes' );799 if ( !isset( $current->response[ $theme ] ) ) {800 $this->skin->before();801 $this->skin->set_result(false);802 $this->skin->error('up_to_date');803 $this->skin->after();804 return false;805 }806 807 $r = $current->response[ $theme ];808 809 add_filter('upgrader_pre_install', array(&$this, 'current_before'), 10, 2);810 add_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);811 add_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);812 813 $options = array(814 'package' => $r['package'],815 'destination' => get_theme_root( $theme ),816 'clear_destination' => true,817 'clear_working' => true,818 'hook_extra' => array(819 'theme' => $theme820 ),821 );822 823 $this->run($options);824 825 remove_filter('upgrader_pre_install', array(&$this, 'current_before'));826 remove_filter('upgrader_post_install', array(&$this, 'current_after'));827 remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'));828 829 if ( ! $this->result || is_wp_error($this->result) )830 return $this->result;831 832 // Force refresh of theme update information833 wp_clean_themes_cache();834 do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'theme' ), $theme );835 836 return true;837 }838 839 function bulk_upgrade($themes) {840 841 $this->init();842 $this->bulk = true;843 $this->upgrade_strings();844 845 $current = get_site_transient( 'update_themes' );846 847 add_filter('upgrader_pre_install', array(&$this, 'current_before'), 10, 2);848 add_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);849 add_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);850 851 $this->skin->header();852 853 // Connect to the Filesystem first.854 $res = $this->fs_connect( array(WP_CONTENT_DIR) );855 if ( ! $res ) {856 $this->skin->footer();857 return false;858 }859 860 $this->skin->bulk_header();861 862 // Only start maintenance mode if:863 // - running Multisite and there are one or more themes specified, OR864 // - a theme with an update available is currently in use.865 // @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.866 $maintenance = ( is_multisite() && ! empty( $themes ) );867 foreach ( $themes as $theme )868 $maintenance = $maintenance || $theme == get_stylesheet() || $theme == get_template();869 if ( $maintenance )870 $this->maintenance_mode(true);871 872 $results = array();873 874 $this->update_count = count($themes);875 $this->update_current = 0;876 foreach ( $themes as $theme ) {877 $this->update_current++;878 879 $this->skin->theme_info = $this->theme_info($theme);880 881 if ( !isset( $current->response[ $theme ] ) ) {882 $this->skin->set_result(true);883 $this->skin->before();884 $this->skin->feedback('up_to_date');885 $this->skin->after();886 $results[$theme] = true;887 continue;888 }889 890 // Get the URL to the zip file891 $r = $current->response[ $theme ];892 893 $options = array(894 'package' => $r['package'],895 'destination' => get_theme_root( $theme ),896 'clear_destination' => true,897 'clear_working' => true,898 'hook_extra' => array(899 'theme' => $theme900 ),901 );902 903 $result = $this->run($options);904 905 $results[$theme] = $this->result;906 907 // Prevent credentials auth screen from displaying multiple times908 if ( false === $result )909 break;910 } //end foreach $plugins911 912 $this->maintenance_mode(false);913 914 $this->skin->bulk_footer();915 916 $this->skin->footer();917 918 // Cleanup our hooks, in case something else does a upgrade on this connection.919 remove_filter('upgrader_pre_install', array(&$this, 'current_before'));920 remove_filter('upgrader_post_install', array(&$this, 'current_after'));921 remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'));922 923 // Force refresh of theme update information924 wp_clean_themes_cache();925 do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'theme', 'bulk' => true ), $themes );926 927 return $results;928 }929 930 function check_package($source) {931 global $wp_filesystem;932 933 if ( is_wp_error($source) )934 return $source;935 936 // Check the folder contains a valid theme937 $working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit(WP_CONTENT_DIR), $source);938 if ( ! is_dir($working_directory) ) // Sanity check, if the above fails, lets not prevent installation.939 return $source;940 941 // A proper archive should have a style.css file in the single subdirectory942 if ( ! file_exists( $working_directory . 'style.css' ) )943 return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], __('The theme is missing the <code>style.css</code> stylesheet.') );944 945 $info = get_file_data( $working_directory . 'style.css', array( 'Name' => 'Theme Name', 'Template' => 'Template' ) );946 947 if ( empty( $info['Name'] ) )948 return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], __("The <code>style.css</code> stylesheet doesn't contain a valid theme header.") );949 950 // If it's not a child theme, it must have at least an index.php to be legit.951 if ( empty( $info['Template'] ) && ! file_exists( $working_directory . 'index.php' ) )952 return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], __('The theme is missing the <code>index.php</code> file.') );953 954 return $source;955 }956 957 function current_before($return, $theme) {958 959 if ( is_wp_error($return) )960 return $return;961 962 $theme = isset($theme['theme']) ? $theme['theme'] : '';963 964 if ( $theme != get_stylesheet() ) //If not current965 return $return;966 //Change to maintenance mode now.967 if ( ! $this->bulk )968 $this->maintenance_mode(true);969 970 return $return;971 }972 973 function current_after($return, $theme) {974 if ( is_wp_error($return) )975 return $return;976 977 $theme = isset($theme['theme']) ? $theme['theme'] : '';978 979 if ( $theme != get_stylesheet() ) // If not current980 return $return;981 982 // Ensure stylesheet name hasn't changed after the upgrade:983 if ( $theme == get_stylesheet() && $theme != $this->result['destination_name'] ) {984 wp_clean_themes_cache();985 $stylesheet = $this->result['destination_name'];986 switch_theme( $stylesheet );987 }988 989 //Time to remove maintenance mode990 if ( ! $this->bulk )991 $this->maintenance_mode(false);992 return $return;993 }994 995 function delete_old_theme( $removed, $local_destination, $remote_destination, $theme ) {996 global $wp_filesystem;997 998 if ( is_wp_error( $removed ) )999 return $removed; // Pass errors through.1000 1001 if ( ! isset( $theme['theme'] ) )1002 return $removed;1003 1004 $theme = $theme['theme'];1005 $themes_dir = trailingslashit( $wp_filesystem->wp_themes_dir( $theme ) );1006 if ( $wp_filesystem->exists( $themes_dir . $theme ) ) {1007 if ( ! $wp_filesystem->delete( $themes_dir . $theme, true ) )1008 return false;1009 }1010 1011 return true;1012 }1013 1014 function theme_info($theme = null) {1015 1016 if ( empty($theme) ) {1017 if ( !empty($this->result['destination_name']) )1018 $theme = $this->result['destination_name'];1019 else1020 return false;1021 }1022 return wp_get_theme( $theme );1023 }1024 1025 }1026 1027 /**1028 * Core Upgrader class for WordPress. It allows for WordPress to upgrade itself in combination with the wp-admin/includes/update-core.php file1029 *1030 * @TODO More Detailed docs, for methods as well.1031 *1032 * @package WordPress1033 * @subpackage Upgrader1034 * @since 2.8.01035 */1036 class Core_Upgrader extends WP_Upgrader {1037 1038 function upgrade_strings() {1039 $this->strings['up_to_date'] = __('WordPress is at the latest version.');1040 $this->strings['no_package'] = __('Update package not available.');1041 $this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>…');1042 $this->strings['unpack_package'] = __('Unpacking the update…');1043 $this->strings['copy_failed'] = __('Could not copy files.');1044 $this->strings['copy_failed_space'] = __('Could not copy files. You may have run out of disk space.' );1045 }1046 1047 function upgrade($current) {1048 global $wp_filesystem, $wp_version;1049 1050 $this->init();1051 $this->upgrade_strings();1052 1053 // Is an update available?1054 if ( !isset( $current->response ) || $current->response == 'latest' )1055 return new WP_Error('up_to_date', $this->strings['up_to_date']);1056 1057 $res = $this->fs_connect( array(ABSPATH, WP_CONTENT_DIR) );1058 if ( is_wp_error($res) )1059 return $res;1060 1061 $wp_dir = trailingslashit($wp_filesystem->abspath());1062 1063 // If partial update is returned from the API, use that, unless we're doing a reinstall.1064 // If we cross the new_bundled version number, then use the new_bundled zip.1065 // Don't though if the constant is set to skip bundled items.1066 // If the API returns a no_content zip, go with it. Finally, default to the full zip.1067 if ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version )1068 $to_download = 'partial';1069 elseif ( $current->packages->new_bundled && version_compare( $wp_version, $current->new_bundled, '<' )1070 && ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) )1071 $to_download = 'new_bundled';1072 elseif ( $current->packages->no_content )1073 $to_download = 'no_content';1074 else1075 $to_download = 'full';1076 1077 $download = $this->download_package( $current->packages->$to_download );1078 if ( is_wp_error($download) )1079 return $download;1080 1081 $working_dir = $this->unpack_package( $download );1082 if ( is_wp_error($working_dir) )1083 return $working_dir;1084 1085 // Copy update-core.php from the new version into place.1086 if ( !$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true) ) {1087 $wp_filesystem->delete($working_dir, true);1088 return new WP_Error('copy_failed', $this->strings['copy_failed']);1089 }1090 $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);1091 1092 require(ABSPATH . 'wp-admin/includes/update-core.php');1093 1094 if ( ! function_exists( 'update_core' ) )1095 return new WP_Error( 'copy_failed_space', $this->strings['copy_failed_space'] );1096 1097 $result = update_core( $working_dir, $wp_dir );1098 do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'core' ), $result );1099 return $result;1100 }1101 1102 }1103 1104 /**1105 11 * Generic Skin for the WordPress Upgrader classes. This skin is designed to be extended for specific purposes. 1106 *1107 * @TODO More Detailed docs, for methods as well.1108 12 * 1109 13 * @package WordPress … … 1195 99 * Plugin Upgrader Skin for WordPress Plugin Upgrades. 1196 100 * 1197 * @TODO More Detailed docs, for methods as well.1198 *1199 101 * @package WordPress 1200 102 * @subpackage Upgrader … … 1433 335 * Plugin Installer Skin for WordPress Plugin Installer. 1434 336 * 1435 * @TODO More Detailed docs, for methods as well.1436 *1437 337 * @package WordPress 1438 338 * @subpackage Upgrader … … 1498 398 * Theme Installer Skin for the WordPress Theme Installer. 1499 399 * 1500 * @TODO More Detailed docs, for methods as well.1501 *1502 400 * @package WordPress 1503 401 * @subpackage Upgrader … … 1572 470 /** 1573 471 * Theme Upgrader Skin for WordPress Theme Upgrades. 1574 *1575 * @TODO More Detailed docs, for methods as well.1576 472 * 1577 473 * @package WordPress … … 1632 528 } 1633 529 } 1634 1635 /**1636 * Upgrade Skin helper for File uploads. This class handles the upload process and passes it as if it's a local file to the Upgrade/Installer functions.1637 *1638 * @TODO More Detailed docs, for methods as well.1639 *1640 * @package WordPress1641 * @subpackage Upgrader1642 * @since 2.8.01643 */1644 class File_Upload_Upgrader {1645 var $package;1646 var $filename;1647 var $id = 0;1648 1649 function __construct($form, $urlholder) {1650 1651 if ( empty($_FILES[$form]['name']) && empty($_GET[$urlholder]) )1652 wp_die(__('Please select a file'));1653 1654 //Handle a newly uploaded file, Else assume it's already been uploaded1655 if ( ! empty($_FILES) ) {1656 $overrides = array( 'test_form' => false, 'test_type' => false );1657 $file = wp_handle_upload( $_FILES[$form], $overrides );1658 1659 if ( isset( $file['error'] ) )1660 wp_die( $file['error'] );1661 1662 $this->filename = $_FILES[$form]['name'];1663 $this->package = $file['file'];1664 1665 // Construct the object array1666 $object = array(1667 'post_title' => $this->filename,1668 'post_content' => $file['url'],1669 'post_mime_type' => $file['type'],1670 'guid' => $file['url'],1671 'context' => 'upgrader',1672 'post_status' => 'private'1673 );1674 1675 // Save the data1676 $this->id = wp_insert_attachment( $object, $file['file'] );1677 1678 // schedule a cleanup for 2 hours from now in case of failed install1679 wp_schedule_single_event( time() + 7200, 'upgrader_scheduled_cleanup', array( $this->id ) );1680 1681 } elseif ( is_numeric( $_GET[$urlholder] ) ) {1682 // Numeric Package = previously uploaded file, see above.1683 $this->id = (int) $_GET[$urlholder];1684 $attachment = get_post( $this->id );1685 if ( empty($attachment) )1686 wp_die(__('Please select a file'));1687 1688 $this->filename = $attachment->post_title;1689 $this->package = get_attached_file( $attachment->ID );1690 } else {1691 // Else, It's set to something, Back compat for plugins using the old (pre-3.3) File_Uploader handler.1692 if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) )1693 wp_die( $uploads['error'] );1694 1695 $this->filename = $_GET[$urlholder];1696 $this->package = $uploads['basedir'] . '/' . $this->filename;1697 }1698 }1699 1700 function cleanup() {1701 if ( $this->id )1702 wp_delete_attachment( $this->id );1703 1704 elseif ( file_exists( $this->package ) )1705 return @unlink( $this->package );1706 1707 return true;1708 }1709 } -
trunk/src/wp-admin/includes/class-wp-upgrader.php
r25181 r25227 12 12 */ 13 13 14 require ABSPATH . 'wp-admin/includes/class-wp-upgrader-skins.php'; 15 14 16 /** 15 17 * WordPress Upgrader class for Upgrading/Installing a local set of files via the Filesystem Abstraction classes from a Zip file. 16 *17 * @TODO More Detailed docs, for methods as well.18 18 * 19 19 * @package WordPress … … 368 368 * Plugin Upgrader class for WordPress Plugins, It is designed to upgrade/install plugins from a local zip, remote zip URL, or uploaded zip file. 369 369 * 370 * @TODO More Detailed docs, for methods as well.371 *372 370 * @package WordPress 373 371 * @subpackage Upgrader … … 653 651 /** 654 652 * Theme Upgrader class for WordPress Themes, It is designed to upgrade/install themes from a local zip, remote zip URL, or uploaded zip file. 655 *656 * @TODO More Detailed docs, for methods as well.657 653 * 658 654 * @package WordPress … … 1028 1024 * Core Upgrader class for WordPress. It allows for WordPress to upgrade itself in combination with the wp-admin/includes/update-core.php file 1029 1025 * 1030 * @TODO More Detailed docs, for methods as well.1031 *1032 1026 * @package WordPress 1033 1027 * @subpackage Upgrader … … 1103 1097 1104 1098 /** 1105 * Generic Skin for the WordPress Upgrader classes. This skin is designed to be extended for specific purposes.1106 *1107 * @TODO More Detailed docs, for methods as well.1108 *1109 * @package WordPress1110 * @subpackage Upgrader1111 * @since 2.8.01112 */1113 class WP_Upgrader_Skin {1114 1115 var $upgrader;1116 var $done_header = false;1117 var $result = false;1118 1119 function __construct($args = array()) {1120 $defaults = array( 'url' => '', 'nonce' => '', 'title' => '', 'context' => false );1121 $this->options = wp_parse_args($args, $defaults);1122 }1123 1124 function set_upgrader(&$upgrader) {1125 if ( is_object($upgrader) )1126 $this->upgrader =& $upgrader;1127 $this->add_strings();1128 }1129 1130 function add_strings() {1131 }1132 1133 function set_result($result) {1134 $this->result = $result;1135 }1136 1137 function request_filesystem_credentials($error = false) {1138 $url = $this->options['url'];1139 $context = $this->options['context'];1140 if ( !empty($this->options['nonce']) )1141 $url = wp_nonce_url($url, $this->options['nonce']);1142 return request_filesystem_credentials($url, '', $error, $context); //Possible to bring inline, Leaving as is for now.1143 }1144 1145 function header() {1146 if ( $this->done_header )1147 return;1148 $this->done_header = true;1149 echo '<div class="wrap">';1150 screen_icon();1151 echo '<h2>' . $this->options['title'] . '</h2>';1152 }1153 function footer() {1154 echo '</div>';1155 }1156 1157 function error($errors) {1158 if ( ! $this->done_header )1159 $this->header();1160 if ( is_string($errors) ) {1161 $this->feedback($errors);1162 } elseif ( is_wp_error($errors) && $errors->get_error_code() ) {1163 foreach ( $errors->get_error_messages() as $message ) {1164 if ( $errors->get_error_data() )1165 $this->feedback($message . ' ' . esc_html( $errors->get_error_data() ) );1166 else1167 $this->feedback($message);1168 }1169 }1170 }1171 1172 function feedback($string) {1173 if ( isset( $this->upgrader->strings[$string] ) )1174 $string = $this->upgrader->strings[$string];1175 1176 if ( strpos($string, '%') !== false ) {1177 $args = func_get_args();1178 $args = array_splice($args, 1);1179 if ( $args ) {1180 $args = array_map( 'strip_tags', $args );1181 $args = array_map( 'esc_html', $args );1182 $string = vsprintf($string, $args);1183 }1184 }1185 if ( empty($string) )1186 return;1187 show_message($string);1188 }1189 function before() {}1190 function after() {}1191 1192 }1193 1194 /**1195 * Plugin Upgrader Skin for WordPress Plugin Upgrades.1196 *1197 * @TODO More Detailed docs, for methods as well.1198 *1199 * @package WordPress1200 * @subpackage Upgrader1201 * @since 2.8.01202 */1203 class Plugin_Upgrader_Skin extends WP_Upgrader_Skin {1204 var $plugin = '';1205 var $plugin_active = false;1206 var $plugin_network_active = false;1207 1208 function __construct($args = array()) {1209 $defaults = array( 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => __('Update Plugin') );1210 $args = wp_parse_args($args, $defaults);1211 1212 $this->plugin = $args['plugin'];1213 1214 $this->plugin_active = is_plugin_active( $this->plugin );1215 $this->plugin_network_active = is_plugin_active_for_network( $this->plugin );1216 1217 parent::__construct($args);1218 }1219 1220 function after() {1221 $this->plugin = $this->upgrader->plugin_info();1222 if ( !empty($this->plugin) && !is_wp_error($this->result) && $this->plugin_active ){1223 echo '<iframe style="border:0;overflow:hidden" width="100%" height="170px" src="' . wp_nonce_url('update.php?action=activate-plugin&networkwide=' . $this->plugin_network_active . '&plugin=' . urlencode( $this->plugin ), 'activate-plugin_' . $this->plugin) .'"></iframe>';1224 }1225 1226 $update_actions = array(1227 'activate_plugin' => '<a href="' . wp_nonce_url('plugins.php?action=activate&plugin=' . urlencode( $this->plugin ), 'activate-plugin_' . $this->plugin) . '" title="' . esc_attr__('Activate this plugin') . '" target="_parent">' . __('Activate Plugin') . '</a>',1228 'plugins_page' => '<a href="' . self_admin_url('plugins.php') . '" title="' . esc_attr__('Go to plugins page') . '" target="_parent">' . __('Return to Plugins page') . '</a>'1229 );1230 if ( $this->plugin_active || ! $this->result || is_wp_error( $this->result ) || ! current_user_can( 'activate_plugins' ) )1231 unset( $update_actions['activate_plugin'] );1232 1233 $update_actions = apply_filters('update_plugin_complete_actions', $update_actions, $this->plugin);1234 if ( ! empty($update_actions) )1235 $this->feedback(implode(' | ', (array)$update_actions));1236 }1237 1238 function before() {1239 if ( $this->upgrader->show_before ) {1240 echo $this->upgrader->show_before;1241 $this->upgrader->show_before = '';1242 }1243 }1244 }1245 1246 /**1247 * Plugin Upgrader Skin for WordPress Plugin Upgrades.1248 *1249 * @package WordPress1250 * @subpackage Upgrader1251 * @since 3.0.01252 */1253 class Bulk_Upgrader_Skin extends WP_Upgrader_Skin {1254 var $in_loop = false;1255 var $error = false;1256 1257 function __construct($args = array()) {1258 $defaults = array( 'url' => '', 'nonce' => '' );1259 $args = wp_parse_args($args, $defaults);1260 1261 parent::__construct($args);1262 }1263 1264 function add_strings() {1265 $this->upgrader->strings['skin_upgrade_start'] = __('The update process is starting. This process may take a while on some hosts, so please be patient.');1266 $this->upgrader->strings['skin_update_failed_error'] = __('An error occurred while updating %1$s: <strong>%2$s</strong>');1267 $this->upgrader->strings['skin_update_failed'] = __('The update of %1$s failed.');1268 $this->upgrader->strings['skin_update_successful'] = __('%1$s updated successfully.').' <a onclick="%2$s" href="#" class="hide-if-no-js"><span>'.__('Show Details').'</span><span class="hidden">'.__('Hide Details').'</span>.</a>';1269 $this->upgrader->strings['skin_upgrade_end'] = __('All updates have been completed.');1270 }1271 1272 function feedback($string) {1273 if ( isset( $this->upgrader->strings[$string] ) )1274 $string = $this->upgrader->strings[$string];1275 1276 if ( strpos($string, '%') !== false ) {1277 $args = func_get_args();1278 $args = array_splice($args, 1);1279 if ( $args ) {1280 $args = array_map( 'strip_tags', $args );1281 $args = array_map( 'esc_html', $args );1282 $string = vsprintf($string, $args);1283 }1284 }1285 if ( empty($string) )1286 return;1287 if ( $this->in_loop )1288 echo "$string<br />\n";1289 else1290 echo "<p>$string</p>\n";1291 }1292 1293 function header() {1294 // Nothing, This will be displayed within a iframe.1295 }1296 1297 function footer() {1298 // Nothing, This will be displayed within a iframe.1299 }1300 function error($error) {1301 if ( is_string($error) && isset( $this->upgrader->strings[$error] ) )1302 $this->error = $this->upgrader->strings[$error];1303 1304 if ( is_wp_error($error) ) {1305 foreach ( $error->get_error_messages() as $emessage ) {1306 if ( $error->get_error_data() )1307 $messages[] = $emessage . ' ' . esc_html( $error->get_error_data() );1308 else1309 $messages[] = $emessage;1310 }1311 $this->error = implode(', ', $messages);1312 }1313 echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js($this->upgrader->update_current) . '\').hide();</script>';1314 }1315 1316 function bulk_header() {1317 $this->feedback('skin_upgrade_start');1318 }1319 1320 function bulk_footer() {1321 $this->feedback('skin_upgrade_end');1322 }1323 1324 function before($title = '') {1325 $this->in_loop = true;1326 printf( '<h4>' . $this->upgrader->strings['skin_before_update_header'] . ' <span class="spinner waiting-' . $this->upgrader->update_current . '"></span></h4>', $title, $this->upgrader->update_current, $this->upgrader->update_count);1327 echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js($this->upgrader->update_current) . '\').css("display", "inline-block");</script>';1328 echo '<div class="update-messages hide-if-js" id="progress-' . esc_attr($this->upgrader->update_current) . '"><p>';1329 $this->flush_output();1330 }1331 1332 function after($title = '') {1333 echo '</p></div>';1334 if ( $this->error || ! $this->result ) {1335 if ( $this->error )1336 echo '<div class="error"><p>' . sprintf($this->upgrader->strings['skin_update_failed_error'], $title, $this->error) . '</p></div>';1337 else1338 echo '<div class="error"><p>' . sprintf($this->upgrader->strings['skin_update_failed'], $title) . '</p></div>';1339 1340 echo '<script type="text/javascript">jQuery(\'#progress-' . esc_js($this->upgrader->update_current) . '\').show();</script>';1341 }1342 if ( $this->result && ! is_wp_error( $this->result ) ) {1343 if ( ! $this->error )1344 echo '<div class="updated"><p>' . sprintf($this->upgrader->strings['skin_update_successful'], $title, 'jQuery(\'#progress-' . esc_js($this->upgrader->update_current) . '\').toggle();jQuery(\'span\', this).toggle(); return false;') . '</p></div>';1345 echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js($this->upgrader->update_current) . '\').hide();</script>';1346 }1347 1348 $this->reset();1349 $this->flush_output();1350 }1351 1352 function reset() {1353 $this->in_loop = false;1354 $this->error = false;1355 }1356 1357 function flush_output() {1358 wp_ob_end_flush_all();1359 flush();1360 }1361 }1362 1363 class Bulk_Plugin_Upgrader_Skin extends Bulk_Upgrader_Skin {1364 var $plugin_info = array(); // Plugin_Upgrader::bulk() will fill this in.1365 1366 function __construct($args = array()) {1367 parent::__construct($args);1368 }1369 1370 function add_strings() {1371 parent::add_strings();1372 $this->upgrader->strings['skin_before_update_header'] = __('Updating Plugin %1$s (%2$d/%3$d)');1373 }1374 1375 function before($title = '') {1376 parent::before($this->plugin_info['Title']);1377 }1378 1379 function after($title = '') {1380 parent::after($this->plugin_info['Title']);1381 }1382 function bulk_footer() {1383 parent::bulk_footer();1384 $update_actions = array(1385 'plugins_page' => '<a href="' . self_admin_url('plugins.php') . '" title="' . esc_attr__('Go to plugins page') . '" target="_parent">' . __('Return to Plugins page') . '</a>',1386 'updates_page' => '<a href="' . self_admin_url('update-core.php') . '" title="' . esc_attr__('Go to WordPress Updates page') . '" target="_parent">' . __('Return to WordPress Updates') . '</a>'1387 );1388 if ( ! current_user_can( 'activate_plugins' ) )1389 unset( $update_actions['plugins_page'] );1390 1391 $update_actions = apply_filters('update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info);1392 if ( ! empty($update_actions) )1393 $this->feedback(implode(' | ', (array)$update_actions));1394 }1395 }1396 1397 class Bulk_Theme_Upgrader_Skin extends Bulk_Upgrader_Skin {1398 var $theme_info = array(); // Theme_Upgrader::bulk() will fill this in.1399 1400 function __construct($args = array()) {1401 parent::__construct($args);1402 }1403 1404 function add_strings() {1405 parent::add_strings();1406 $this->upgrader->strings['skin_before_update_header'] = __('Updating Theme %1$s (%2$d/%3$d)');1407 }1408 1409 function before($title = '') {1410 parent::before( $this->theme_info->display('Name') );1411 }1412 1413 function after($title = '') {1414 parent::after( $this->theme_info->display('Name') );1415 }1416 1417 function bulk_footer() {1418 parent::bulk_footer();1419 $update_actions = array(1420 'themes_page' => '<a href="' . self_admin_url('themes.php') . '" title="' . esc_attr__('Go to themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>',1421 'updates_page' => '<a href="' . self_admin_url('update-core.php') . '" title="' . esc_attr__('Go to WordPress Updates page') . '" target="_parent">' . __('Return to WordPress Updates') . '</a>'1422 );1423 if ( ! current_user_can( 'switch_themes' ) && ! current_user_can( 'edit_theme_options' ) )1424 unset( $update_actions['themes_page'] );1425 1426 $update_actions = apply_filters('update_bulk_theme_complete_actions', $update_actions, $this->theme_info );1427 if ( ! empty($update_actions) )1428 $this->feedback(implode(' | ', (array)$update_actions));1429 }1430 }1431 1432 /**1433 * Plugin Installer Skin for WordPress Plugin Installer.1434 *1435 * @TODO More Detailed docs, for methods as well.1436 *1437 * @package WordPress1438 * @subpackage Upgrader1439 * @since 2.8.01440 */1441 class Plugin_Installer_Skin extends WP_Upgrader_Skin {1442 var $api;1443 var $type;1444 1445 function __construct($args = array()) {1446 $defaults = array( 'type' => 'web', 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => '' );1447 $args = wp_parse_args($args, $defaults);1448 1449 $this->type = $args['type'];1450 $this->api = isset($args['api']) ? $args['api'] : array();1451 1452 parent::__construct($args);1453 }1454 1455 function before() {1456 if ( !empty($this->api) )1457 $this->upgrader->strings['process_success'] = sprintf( __('Successfully installed the plugin <strong>%s %s</strong>.'), $this->api->name, $this->api->version);1458 }1459 1460 function after() {1461 1462 $plugin_file = $this->upgrader->plugin_info();1463 1464 $install_actions = array();1465 1466 $from = isset($_GET['from']) ? wp_unslash( $_GET['from'] ) : 'plugins';1467 1468 if ( 'import' == $from )1469 $install_actions['activate_plugin'] = '<a href="' . wp_nonce_url('plugins.php?action=activate&from=import&plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file) . '" title="' . esc_attr__('Activate this plugin') . '" target="_parent">' . __('Activate Plugin & Run Importer') . '</a>';1470 else1471 $install_actions['activate_plugin'] = '<a href="' . wp_nonce_url('plugins.php?action=activate&plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file) . '" title="' . esc_attr__('Activate this plugin') . '" target="_parent">' . __('Activate Plugin') . '</a>';1472 1473 if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {1474 $install_actions['network_activate'] = '<a href="' . wp_nonce_url('plugins.php?action=activate&networkwide=1&plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file) . '" title="' . esc_attr__('Activate this plugin for all sites in this network') . '" target="_parent">' . __('Network Activate') . '</a>';1475 unset( $install_actions['activate_plugin'] );1476 }1477 1478 if ( 'import' == $from )1479 $install_actions['importers_page'] = '<a href="' . admin_url('import.php') . '" title="' . esc_attr__('Return to Importers') . '" target="_parent">' . __('Return to Importers') . '</a>';1480 else if ( $this->type == 'web' )1481 $install_actions['plugins_page'] = '<a href="' . self_admin_url('plugin-install.php') . '" title="' . esc_attr__('Return to Plugin Installer') . '" target="_parent">' . __('Return to Plugin Installer') . '</a>';1482 else1483 $install_actions['plugins_page'] = '<a href="' . self_admin_url('plugins.php') . '" title="' . esc_attr__('Return to Plugins page') . '" target="_parent">' . __('Return to Plugins page') . '</a>';1484 1485 if ( ! $this->result || is_wp_error($this->result) ) {1486 unset( $install_actions['activate_plugin'], $install_actions['network_activate'] );1487 } elseif ( ! current_user_can( 'activate_plugins' ) ) {1488 unset( $install_actions['activate_plugin'] );1489 }1490 1491 $install_actions = apply_filters('install_plugin_complete_actions', $install_actions, $this->api, $plugin_file);1492 if ( ! empty($install_actions) )1493 $this->feedback(implode(' | ', (array)$install_actions));1494 }1495 }1496 1497 /**1498 * Theme Installer Skin for the WordPress Theme Installer.1499 *1500 * @TODO More Detailed docs, for methods as well.1501 *1502 * @package WordPress1503 * @subpackage Upgrader1504 * @since 2.8.01505 */1506 class Theme_Installer_Skin extends WP_Upgrader_Skin {1507 var $api;1508 var $type;1509 1510 function __construct($args = array()) {1511 $defaults = array( 'type' => 'web', 'url' => '', 'theme' => '', 'nonce' => '', 'title' => '' );1512 $args = wp_parse_args($args, $defaults);1513 1514 $this->type = $args['type'];1515 $this->api = isset($args['api']) ? $args['api'] : array();1516 1517 parent::__construct($args);1518 }1519 1520 function before() {1521 if ( !empty($this->api) )1522 $this->upgrader->strings['process_success'] = sprintf( $this->upgrader->strings['process_success_specific'], $this->api->name, $this->api->version);1523 }1524 1525 function after() {1526 if ( empty($this->upgrader->result['destination_name']) )1527 return;1528 1529 $theme_info = $this->upgrader->theme_info();1530 if ( empty( $theme_info ) )1531 return;1532 1533 $name = $theme_info->display('Name');1534 $stylesheet = $this->upgrader->result['destination_name'];1535 $template = $theme_info->get_template();1536 1537 $preview_link = add_query_arg( array(1538 'preview' => 1,1539 'template' => urlencode( $template ),1540 'stylesheet' => urlencode( $stylesheet ),1541 ), trailingslashit( home_url() ) );1542 1543 $activate_link = add_query_arg( array(1544 'action' => 'activate',1545 'template' => urlencode( $template ),1546 'stylesheet' => urlencode( $stylesheet ),1547 ), admin_url('themes.php') );1548 $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );1549 1550 $install_actions = array();1551 $install_actions['preview'] = '<a href="' . esc_url( $preview_link ) . '" class="hide-if-customize" title="' . esc_attr( sprintf( __('Preview “%s”'), $name ) ) . '">' . __('Preview') . '</a>';1552 $install_actions['preview'] .= '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize" title="' . esc_attr( sprintf( __('Preview “%s”'), $name ) ) . '">' . __('Live Preview') . '</a>';1553 $install_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink" title="' . esc_attr( sprintf( __('Activate “%s”'), $name ) ) . '">' . __('Activate') . '</a>';1554 1555 if ( is_network_admin() && current_user_can( 'manage_network_themes' ) )1556 $install_actions['network_enable'] = '<a href="' . esc_url( wp_nonce_url( 'themes.php?action=enable&theme=' . urlencode( $stylesheet ), 'enable-theme_' . $stylesheet ) ) . '" title="' . esc_attr__( 'Enable this theme for all sites in this network' ) . '" target="_parent">' . __( 'Network Enable' ) . '</a>';1557 1558 if ( $this->type == 'web' )1559 $install_actions['themes_page'] = '<a href="' . self_admin_url('theme-install.php') . '" title="' . esc_attr__('Return to Theme Installer') . '" target="_parent">' . __('Return to Theme Installer') . '</a>';1560 elseif ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) )1561 $install_actions['themes_page'] = '<a href="' . self_admin_url('themes.php') . '" title="' . esc_attr__('Themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>';1562 1563 if ( ! $this->result || is_wp_error($this->result) || is_network_admin() || ! current_user_can( 'switch_themes' ) )1564 unset( $install_actions['activate'], $install_actions['preview'] );1565 1566 $install_actions = apply_filters('install_theme_complete_actions', $install_actions, $this->api, $stylesheet, $theme_info);1567 if ( ! empty($install_actions) )1568 $this->feedback(implode(' | ', (array)$install_actions));1569 }1570 }1571 1572 /**1573 * Theme Upgrader Skin for WordPress Theme Upgrades.1574 *1575 * @TODO More Detailed docs, for methods as well.1576 *1577 * @package WordPress1578 * @subpackage Upgrader1579 * @since 2.8.01580 */1581 class Theme_Upgrader_Skin extends WP_Upgrader_Skin {1582 var $theme = '';1583 1584 function __construct($args = array()) {1585 $defaults = array( 'url' => '', 'theme' => '', 'nonce' => '', 'title' => __('Update Theme') );1586 $args = wp_parse_args($args, $defaults);1587 1588 $this->theme = $args['theme'];1589 1590 parent::__construct($args);1591 }1592 1593 function after() {1594 1595 $update_actions = array();1596 if ( ! empty( $this->upgrader->result['destination_name'] ) && $theme_info = $this->upgrader->theme_info() ) {1597 $name = $theme_info->display('Name');1598 $stylesheet = $this->upgrader->result['destination_name'];1599 $template = $theme_info->get_template();1600 1601 $preview_link = add_query_arg( array(1602 'preview' => 1,1603 'template' => urlencode( $template ),1604 'stylesheet' => urlencode( $stylesheet ),1605 ), trailingslashit( home_url() ) );1606 1607 $activate_link = add_query_arg( array(1608 'action' => 'activate',1609 'template' => urlencode( $template ),1610 'stylesheet' => urlencode( $stylesheet ),1611 ), admin_url('themes.php') );1612 $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );1613 1614 if ( get_stylesheet() == $stylesheet ) {1615 if ( current_user_can( 'edit_theme_options' ) )1616 $update_actions['preview'] = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize" title="' . esc_attr( sprintf( __('Customize “%s”'), $name ) ) . '">' . __('Customize') . '</a>';1617 } elseif ( current_user_can( 'switch_themes' ) ) {1618 $update_actions['preview'] = '<a href="' . esc_url( $preview_link ) . '" class="hide-if-customize" title="' . esc_attr( sprintf( __('Preview “%s”'), $name ) ) . '">' . __('Preview') . '</a>';1619 $update_actions['preview'] .= '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize" title="' . esc_attr( sprintf( __('Preview “%s”'), $name ) ) . '">' . __('Live Preview') . '</a>';1620 $update_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink" title="' . esc_attr( sprintf( __('Activate “%s”'), $name ) ) . '">' . __('Activate') . '</a>';1621 }1622 1623 if ( ! $this->result || is_wp_error( $this->result ) || is_network_admin() )1624 unset( $update_actions['preview'], $update_actions['activate'] );1625 }1626 1627 $update_actions['themes_page'] = '<a href="' . self_admin_url('themes.php') . '" title="' . esc_attr__('Return to Themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>';1628 1629 $update_actions = apply_filters('update_theme_complete_actions', $update_actions, $this->theme);1630 if ( ! empty($update_actions) )1631 $this->feedback(implode(' | ', (array)$update_actions));1632 }1633 }1634 1635 /**1636 1099 * Upgrade Skin helper for File uploads. This class handles the upload process and passes it as if it's a local file to the Upgrade/Installer functions. 1637 *1638 * @TODO More Detailed docs, for methods as well.1639 1100 * 1640 1101 * @package WordPress
Note: See TracChangeset
for help on using the changeset viewer.