[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-admin/includes/ -> class-wp-upgrader.php (source)

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


Generated: Fri May 25 03:56:23 2012 Hosted by follow the white rabbit.