[ Index ]

PHP Cross Reference of Wordpress 2.9.1

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 WP_Upgrader($skin = null) {
  29          return $this->__construct($skin);
  30      }
  31  	function __construct($skin = null) {
  32          if ( null == $skin )
  33              $this->skin = new WP_Upgrader_Skin();
  34          else
  35              $this->skin = $skin;
  36      }
  37  
  38  	function init() {
  39          $this->skin->set_upgrader($this);
  40          $this->generic_strings();
  41      }
  42  
  43  	function generic_strings() {
  44          $this->strings['bad_request'] = __('Invalid Data provided.');
  45          $this->strings['fs_unavailable'] = __('Could not access filesystem.');
  46          $this->strings['fs_error'] = __('Filesystem error');
  47          $this->strings['fs_no_root_dir'] = __('Unable to locate WordPress Root directory.');
  48          $this->strings['fs_no_content_dir'] = __('Unable to locate WordPress Content directory (wp-content).');
  49          $this->strings['fs_no_plugins_dir'] = __('Unable to locate WordPress Plugin directory.');
  50          $this->strings['fs_no_themes_dir'] = __('Unable to locate WordPress Theme directory.');
  51          $this->strings['fs_no_folder'] = __('Unable to locate needed folder (%s).');
  52  
  53          $this->strings['download_failed'] = __('Download failed.');
  54          $this->strings['installing_package'] = __('Installing the latest version.');
  55          $this->strings['folder_exists'] = __('Destination folder already exists.');
  56          $this->strings['mkdir_failed'] = __('Could not create directory.');
  57          $this->strings['bad_package'] = __('Incompatible Archive');
  58  
  59          $this->strings['maintenance_start'] = __('Enabling Maintenance mode.');
  60          $this->strings['maintenance_end'] = __('Disabling Maintenance mode.');
  61      }
  62  
  63  	function fs_connect( $directories = array() ) {
  64          global $wp_filesystem;
  65  
  66          if ( false === ($credentials = $this->skin->request_filesystem_credentials()) )
  67              return false;
  68  
  69          if ( ! WP_Filesystem($credentials) ) {
  70              $error = true;
  71              if ( is_object($wp_filesystem) && $wp_filesystem->errors->get_error_code() )
  72                  $error = $wp_filesystem->errors;
  73              $this->skin->request_filesystem_credentials($error); //Failed to connect, Error and request again
  74              return false;
  75          }
  76  
  77          if ( ! is_object($wp_filesystem) )
  78              return new WP_Error('fs_unavailable', $this->strings['fs_unavailable'] );
  79  
  80          if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() )
  81              return new WP_Error('fs_error', $this->strings['fs_error'], $wp_filesystem->errors);
  82  
  83          foreach ( (array)$directories as $dir ) {
  84              switch ( $dir ) {
  85                  case ABSPATH:
  86                      if ( ! $wp_filesystem->abspath() )
  87                          return new WP_Error('fs_no_root_dir', $this->strings['fs_no_root_dir']);
  88                      break;
  89                  case WP_CONTENT_DIR:
  90                      if ( ! $wp_filesystem->wp_content_dir() )
  91                          return new WP_Error('fs_no_content_dir', $this->strings['fs_no_content_dir']);
  92                      break;
  93                  case WP_PLUGIN_DIR:
  94                      if ( ! $wp_filesystem->wp_plugins_dir() )
  95                          return new WP_Error('fs_no_plugins_dir', $this->strings['fs_no_plugins_dir']);
  96                      break;
  97                  case WP_CONTENT_DIR . '/themes':
  98                      if ( ! $wp_filesystem->find_folder(WP_CONTENT_DIR . '/themes') )
  99                          return new WP_Error('fs_no_themes_dir', $this->strings['fs_no_themes_dir']);
 100                      break;
 101                  default:
 102                      if ( ! $wp_filesystem->find_folder($dir) )
 103                          return new WP_Error('fs_no_folder', sprintf($this->strings['fs_no_folder'], $dir));
 104                      break;
 105              }
 106          }
 107          return true;
 108      } //end fs_connect();
 109  
 110  	function download_package($package) {
 111  
 112          if ( ! preg_match('!^(http|https|ftp)://!i', $package) && file_exists($package) ) //Local file or remote?
 113              return $package; //must be a local file..
 114  
 115          if ( empty($package) )
 116              return new WP_Error('no_package', $this->strings['no_package']);
 117  
 118          $this->skin->feedback('downloading_package', $package);
 119  
 120          $download_file = download_url($package);
 121  
 122          if ( is_wp_error($download_file) )
 123              return new WP_Error('download_failed', $this->strings['download_failed'], $download_file->get_error_message());
 124  
 125          return $download_file;
 126      }
 127  
 128  	function unpack_package($package, $delete_package = true) {
 129          global $wp_filesystem;
 130  
 131          $this->skin->feedback('unpack_package');
 132  
 133          $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
 134  
 135          //Clean up contents of upgrade directory beforehand.
 136          $upgrade_files = $wp_filesystem->dirlist($upgrade_folder);
 137          if ( !empty($upgrade_files) ) {
 138              foreach ( $upgrade_files as $file )
 139                  $wp_filesystem->delete($upgrade_folder . $file['name'], true);
 140          }
 141  
 142          //We need a working directory
 143          $working_dir = $upgrade_folder . basename($package, '.zip');
 144  
 145          // Clean up working directory
 146          if ( $wp_filesystem->is_dir($working_dir) )
 147              $wp_filesystem->delete($working_dir, true);
 148  
 149          // Unzip package to working directory
 150          $result = unzip_file($package, $working_dir); //TODO optimizations, Copy when Move/Rename would suffice?
 151  
 152          // Once extracted, delete the package if required.
 153          if ( $delete_package )
 154              unlink($package);
 155  
 156          if ( is_wp_error($result) ) {
 157              $wp_filesystem->delete($working_dir, true);
 158              return $result;
 159          }
 160  
 161          return $working_dir;
 162      }
 163  
 164  	function install_package($args = array()) {
 165          global $wp_filesystem;
 166          $defaults = array( 'source' => '', 'destination' => '', //Please always pass these
 167                          'clear_destination' => false, 'clear_working' => false,
 168                          'hook_extra' => array());
 169  
 170          $args = wp_parse_args($args, $defaults);
 171          extract($args);
 172  
 173          @set_time_limit( 300 );
 174  
 175          if ( empty($source) || empty($destination) )
 176              return new WP_Error('bad_request', $this->strings['bad_request']);
 177  
 178          $this->skin->feedback('installing_package');
 179  
 180          $res = apply_filters('upgrader_pre_install', true, $hook_extra);
 181          if ( is_wp_error($res) )
 182              return $res;
 183  
 184          //Retain the Original source and destinations
 185          $remote_source = $source;
 186          $local_destination = $destination;
 187  
 188          $source_files = array_keys( $wp_filesystem->dirlist($remote_source) );
 189          $remote_destination = $wp_filesystem->find_folder($local_destination);
 190  
 191          //Locate which directory to copy to the new folder, This is based on the actual folder holding the files.
 192          if ( 1 == count($source_files) && $wp_filesystem->is_dir( trailingslashit($source) . $source_files[0] . '/') ) //Only one folder? Then we want its contents.
 193              $source = trailingslashit($source) . trailingslashit($source_files[0]);
 194          elseif ( count($source_files) == 0 )
 195              return new WP_Error('bad_package', $this->strings['bad_package']); //There are no files?
 196          //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.
 197  
 198          //Hook ability to change the source file location..
 199          $source = apply_filters('upgrader_source_selection', $source, $remote_source, $this);
 200          if ( is_wp_error($source) )
 201              return $source;
 202  
 203          //Has the source location changed? If so, we need a new source_files list.
 204          if ( $source !== $remote_source )
 205              $source_files = array_keys( $wp_filesystem->dirlist($source) );
 206  
 207          //Protection against deleting files in any important base directories.
 208          if ( in_array( $destination, array(ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes') ) ) {
 209              $remote_destination = trailingslashit($remote_destination) . trailingslashit(basename($source));
 210              $destination = trailingslashit($destination) . trailingslashit(basename($source));
 211          }
 212  
 213          if ( $wp_filesystem->exists($remote_destination) ) {
 214              if ( $clear_destination ) {
 215                  //We're going to clear the destination if theres something there
 216                  $this->skin->feedback('remove_old');
 217                  $removed = $wp_filesystem->delete($remote_destination, true);
 218                  $removed = apply_filters('upgrader_clear_destination', $removed, $local_destination, $remote_destination, $hook_extra);
 219  
 220                  if ( is_wp_error($removed) )
 221                      return $removed;
 222                  else if ( ! $removed )
 223                      return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
 224              } else {
 225                  //If we're not clearing the destination folder and something exists there allready, Bail.
 226                  //But first check to see if there are actually any files in the folder.
 227                  $_files = $wp_filesystem->dirlist($remote_destination);
 228                  if ( ! empty($_files) ) {
 229                      $wp_filesystem->delete($remote_source, true); //Clear out the source files.
 230                      return new WP_Error('folder_exists', $this->strings['folder_exists'], $remote_destination );
 231                  }
 232              }
 233          }
 234  
 235          //Create destination if needed
 236          if ( !$wp_filesystem->exists($remote_destination) )
 237              if ( !$wp_filesystem->mkdir($remote_destination, FS_CHMOD_DIR) )
 238                  return new WP_Error('mkdir_failed', $this->strings['mkdir_failed'], $remote_destination);
 239  
 240          // Copy new version of item into place.
 241          $result = copy_dir($source, $remote_destination);
 242          if ( is_wp_error($result) ) {
 243              if ( $clear_working )
 244                  $wp_filesystem->delete($remote_source, true);
 245              return $result;
 246          }
 247  
 248          //Clear the Working folder?
 249          if ( $clear_working )
 250              $wp_filesystem->delete($remote_source, true);
 251  
 252          $destination_name = basename( str_replace($local_destination, '', $destination) );
 253          if ( '.' == $destination_name )
 254              $destination_name = '';
 255  
 256          $this->result = compact('local_source', 'source', 'source_name', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination', 'delete_source_dir');
 257  
 258          $res = apply_filters('upgrader_post_install', true, $hook_extra, $this->result);
 259          if ( is_wp_error($res) ) {
 260              $this->result = $res;
 261              return $res;
 262          }
 263  
 264          //Bombard the calling function will all the info which we've just used.
 265          return $this->result;
 266      }
 267  
 268  	function run($options) {
 269  
 270          $defaults = array(     'package' => '', //Please always pass this.
 271                              'destination' => '', //And this
 272                              'clear_destination' => false,
 273                              'clear_working' => true,
 274                              'is_multi' => false,
 275                              'hook_extra' => array() //Pass any extra $hook_extra args here, this will be passed to any hooked filters.
 276                          );
 277  
 278          $options = wp_parse_args($options, $defaults);
 279          extract($options);
 280  
 281          //Connect to the Filesystem first.
 282          $res = $this->fs_connect( array(WP_CONTENT_DIR, $destination) );
 283          if ( ! $res ) //Mainly for non-connected filesystem.
 284              return false;
 285  
 286          if ( is_wp_error($res) ) {
 287              $this->skin->error($res);
 288              return $res;
 289          }
 290  
 291          if ( !$is_multi ) // call $this->header separately if running multiple times
 292              $this->skin->header();
 293  
 294          $this->skin->before();
 295  
 296          //Download the package (Note, This just returns the filename of the file if the package is a local file)
 297          $download = $this->download_package( $package );
 298          if ( is_wp_error($download) ) {
 299              $this->skin->error($download);
 300              return $download;
 301          }
 302  
 303          //Unzip's the file into a temporary directory
 304          $working_dir = $this->unpack_package( $download );
 305          if ( is_wp_error($working_dir) ) {
 306              $this->skin->error($working_dir);
 307              return $working_dir;
 308          }
 309  
 310          //With the given options, this installs it to the destination directory.
 311          $result = $this->install_package( array(
 312                                              'source' => $working_dir,
 313                                              'destination' => $destination,
 314                                              'clear_destination' => $clear_destination,
 315                                              'clear_working' => $clear_working,
 316                                              'hook_extra' => $hook_extra
 317                                          ) );
 318          $this->skin->set_result($result);
 319          if ( is_wp_error($result) ) {
 320              $this->skin->error($result);
 321              $this->skin->feedback('process_failed');
 322          } else {
 323              //Install Suceeded
 324              $this->skin->feedback('process_success');
 325          }
 326          $this->skin->after();
 327  
 328          if ( !$is_multi )
 329              $this->skin->footer();
 330  
 331          return $result;
 332      }
 333  
 334  	function maintenance_mode($enable = false) {
 335          global $wp_filesystem;
 336          $file = $wp_filesystem->abspath() . '.maintenance';
 337          if ( $enable ) {
 338              $this->skin->feedback('maintenance_start');
 339              // Create maintenance file to signal that we are upgrading
 340              $maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
 341              $wp_filesystem->delete($file);
 342              $wp_filesystem->put_contents($file, $maintenance_string, FS_CHMOD_FILE);
 343          } else if ( !$enable && $wp_filesystem->exists($file) ) {
 344              $this->skin->feedback('maintenance_end');
 345              $wp_filesystem->delete($file);
 346          }
 347      }
 348  
 349  }
 350  
 351  /**
 352   * Plugin Upgrader class for WordPress Plugins, It is designed to upgrade/install plugins from a local zip, remote zip URL, or uploaded zip file.
 353   *
 354   * @TODO More Detailed docs, for methods as well.
 355   *
 356   * @package WordPress
 357   * @subpackage Upgrader
 358   * @since 2.8.0
 359   */
 360  class Plugin_Upgrader extends WP_Upgrader {
 361  
 362      var $result;
 363      var $bulk = false;
 364      var $show_before = '';
 365  
 366  	function upgrade_strings() {
 367          $this->strings['up_to_date'] = __('The plugin is at the latest version.');
 368          $this->strings['no_package'] = __('Upgrade package not available.');
 369          $this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>.');
 370          $this->strings['unpack_package'] = __('Unpacking the update.');
 371          $this->strings['deactivate_plugin'] = __('Deactivating the plugin.');
 372          $this->strings['remove_old'] = __('Removing the old version of the plugin.');
 373          $this->strings['remove_old_failed'] = __('Could not remove the old plugin.');
 374          $this->strings['process_failed'] = __('Plugin upgrade Failed.');
 375          $this->strings['process_success'] = __('Plugin upgraded successfully.');
 376      }
 377  
 378  	function install_strings() {
 379          $this->strings['no_package'] = __('Install package not available.');
 380          $this->strings['downloading_package'] = __('Downloading install package from <span class="code">%s</span>.');
 381          $this->strings['unpack_package'] = __('Unpacking the package.');
 382          $this->strings['installing_package'] = __('Installing the plugin.');
 383          $this->strings['process_failed'] = __('Plugin Install Failed.');
 384          $this->strings['process_success'] = __('Plugin Installed successfully.');
 385      }
 386  
 387  	function install($package) {
 388  
 389          $this->init();
 390          $this->install_strings();
 391  
 392          $this->run(array(
 393                      'package' => $package,
 394                      'destination' => WP_PLUGIN_DIR,
 395                      'clear_destination' => false, //Do not overwrite files.
 396                      'clear_working' => true,
 397                      'hook_extra' => array()
 398                      ));
 399  
 400          // Force refresh of plugin update information
 401          delete_transient('update_plugins');
 402  
 403      }
 404  
 405  	function upgrade($plugin) {
 406  
 407          $this->init();
 408          $this->upgrade_strings();
 409  
 410          $current = get_transient( 'update_plugins' );
 411          if ( !isset( $current->response[ $plugin ] ) ) {
 412              $this->skin->set_result(false);
 413              $this->skin->error('up_to_date');
 414              $this->skin->after();
 415              return false;
 416          }
 417  
 418          // Get the URL to the zip file
 419          $r = $current->response[ $plugin ];
 420  
 421          add_filter('upgrader_pre_install', array(&$this, 'deactivate_plugin_before_upgrade'), 10, 2);
 422          add_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'), 10, 4);
 423          //'source_selection' => array(&$this, 'source_selection'), //theres a track ticket to move up the directory for zip's which are made a bit differently, useful for non-.org plugins.
 424  
 425          $this->run(array(
 426                      'package' => $r->package,
 427                      'destination' => WP_PLUGIN_DIR,
 428                      'clear_destination' => true,
 429                      'clear_working' => true,
 430                      'hook_extra' => array(
 431                                  'plugin' => $plugin
 432                      )
 433                  ));
 434  
 435          // Cleanup our hooks, incase something else does a upgrade on this connection.
 436          remove_filter('upgrader_pre_install', array(&$this, 'deactivate_plugin_before_upgrade'));
 437          remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));
 438  
 439          if ( ! $this->result || is_wp_error($this->result) )
 440              return $this->result;
 441  
 442          // Force refresh of plugin update information
 443          delete_transient('update_plugins');
 444      }
 445  
 446  	function bulk_upgrade($plugins) {
 447  
 448          $this->init();
 449          $this->bulk = true;
 450          $this->upgrade_strings();
 451  
 452          $current = get_transient( 'update_plugins' );
 453  
 454          add_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'), 10, 4);
 455  
 456          $this->skin->header();
 457  
 458          // Connect to the Filesystem first.
 459          $res = $this->fs_connect( array(WP_CONTENT_DIR, WP_PLUGIN_DIR) );
 460          if ( ! $res ) {
 461              $this->skin->footer();
 462              return false;
 463          }
 464  
 465          $this->maintenance_mode(true);
 466  
 467          $all = count($plugins);
 468          $i = 1;
 469          foreach ( $plugins as $plugin ) {
 470  
 471              $this->show_before = sprintf( '<h4>' . __('Updating plugin %1$d of %2$d...') . '</h4>', $i, $all );
 472              $i++;
 473  
 474              if ( !isset( $current->response[ $plugin ] ) ) {
 475                  $this->skin->set_result(false);
 476                  $this->skin->error('up_to_date');
 477                  $this->skin->after();
 478                  $results[$plugin] = false;
 479                  continue;
 480              }
 481  
 482              // Get the URL to the zip file
 483              $r = $current->response[ $plugin ];
 484  
 485              $this->skin->plugin_active = is_plugin_active($plugin);
 486  
 487              $result = $this->run(array(
 488                          'package' => $r->package,
 489                          'destination' => WP_PLUGIN_DIR,
 490                          'clear_destination' => true,
 491                          'clear_working' => true,
 492                          'is_multi' => true,
 493                          'hook_extra' => array(
 494                                      'plugin' => $plugin
 495                          )
 496                      ));
 497  
 498              $results[$plugin] = $this->result;
 499  
 500              // Prevent credentials auth screen from displaying multiple times
 501              if ( false === $result )
 502                  break;
 503          }
 504          $this->maintenance_mode(false);
 505          $this->skin->footer();
 506  
 507          // Cleanup our hooks, incase something else does a upgrade on this connection.
 508          remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));
 509  
 510          // Force refresh of plugin update information
 511          delete_transient('update_plugins');
 512  
 513          return $results;
 514      }
 515  
 516      //return plugin info.
 517  	function plugin_info() {
 518          if ( ! is_array($this->result) )
 519              return false;
 520          if ( empty($this->result['destination_name']) )
 521              return false;
 522  
 523          $plugin = get_plugins('/' . $this->result['destination_name']); //Ensure to pass with leading slash
 524          if ( empty($plugin) )
 525              return false;
 526  
 527          $pluginfiles = array_keys($plugin); //Assume the requested plugin is the first in the list
 528  
 529          return $this->result['destination_name'] . '/' . $pluginfiles[0];
 530      }
 531  
 532      //Hooked to pre_install
 533  	function deactivate_plugin_before_upgrade($return, $plugin) {
 534  
 535          if ( is_wp_error($return) ) //Bypass.
 536              return $return;
 537  
 538          $plugin = isset($plugin['plugin']) ? $plugin['plugin'] : '';
 539          if ( empty($plugin) )
 540              return new WP_Error('bad_request', $this->strings['bad_request']);
 541  
 542          if ( is_plugin_active($plugin) ) {
 543              $this->skin->feedback('deactivate_plugin');
 544              //Deactivate the plugin silently, Prevent deactivation hooks from running.
 545              deactivate_plugins($plugin, true);
 546          }
 547      }
 548  
 549      //Hooked to upgrade_clear_destination
 550  	function delete_old_plugin($removed, $local_destination, $remote_destination, $plugin) {
 551          global $wp_filesystem;
 552  
 553          if ( is_wp_error($removed) )
 554              return $removed; //Pass errors through.
 555  
 556          $plugin = isset($plugin['plugin']) ? $plugin['plugin'] : '';
 557          if ( empty($plugin) )
 558              return new WP_Error('bad_request', $this->strings['bad_request']);
 559  
 560          $plugins_dir = $wp_filesystem->wp_plugins_dir();
 561          $this_plugin_dir = trailingslashit( dirname($plugins_dir . $plugin) );
 562  
 563          if ( ! $wp_filesystem->exists($this_plugin_dir) ) //If its already vanished.
 564              return $removed;
 565  
 566          // If plugin is in its own directory, recursively delete the directory.
 567          if ( strpos($plugin, '/') && $this_plugin_dir != $plugins_dir ) //base check on if plugin includes directory seperator AND that its not the root plugin folder
 568              $deleted = $wp_filesystem->delete($this_plugin_dir, true);
 569          else
 570              $deleted = $wp_filesystem->delete($plugins_dir . $plugin);
 571  
 572          if ( ! $deleted )
 573              return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
 574  
 575          return $removed;
 576      }
 577  }
 578  
 579  /**
 580   * Theme Upgrader class for WordPress Themes, It is designed to upgrade/install themes from a local zip, remote zip URL, or uploaded zip file.
 581   *
 582   * @TODO More Detailed docs, for methods as well.
 583   *
 584   * @package WordPress
 585   * @subpackage Upgrader
 586   * @since 2.8.0
 587   */
 588  class Theme_Upgrader extends WP_Upgrader {
 589  
 590      var $result;
 591  
 592  	function upgrade_strings() {
 593          $this->strings['up_to_date'] = __('The theme is at the latest version.');
 594          $this->strings['no_package'] = __('Upgrade package not available.');
 595          $this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>.');
 596          $this->strings['unpack_package'] = __('Unpacking the update.');
 597          $this->strings['remove_old'] = __('Removing the old version of the theme.');
 598          $this->strings['remove_old_failed'] = __('Could not remove the old theme.');
 599          $this->strings['process_failed'] = __('Theme upgrade Failed.');
 600          $this->strings['process_success'] = __('Theme upgraded successfully.');
 601      }
 602  
 603  	function install_strings() {
 604          $this->strings['no_package'] = __('Install package not available.');
 605          $this->strings['downloading_package'] = __('Downloading install package from <span class="code">%s</span>.');
 606          $this->strings['unpack_package'] = __('Unpacking the package.');
 607          $this->strings['installing_package'] = __('Installing the theme.');
 608          $this->strings['process_failed'] = __('Theme Install Failed.');
 609          $this->strings['process_success'] = __('Theme Installed successfully.');
 610      }
 611  
 612  	function install($package) {
 613  
 614          $this->init();
 615          $this->install_strings();
 616  
 617          $options = array(
 618                          'package' => $package,
 619                          'destination' => WP_CONTENT_DIR . '/themes',
 620                          'clear_destination' => false, //Do not overwrite files.
 621                          'clear_working' => true
 622                          );
 623  
 624          $this->run($options);
 625  
 626          if ( ! $this->result || is_wp_error($this->result) )
 627              return $this->result;
 628  
 629          // Force refresh of theme update information
 630          delete_transient('update_themes');
 631  
 632          if ( empty($result['destination_name']) )
 633              return false;
 634          else
 635              return $result['destination_name'];
 636      }
 637  
 638  	function upgrade($theme) {
 639  
 640          $this->init();
 641          $this->upgrade_strings();
 642  
 643          // Is an update available?
 644          $current = get_transient( 'update_themes' );
 645          if ( !isset( $current->response[ $theme ] ) ) {
 646              $this->skin->set_result(false);
 647              $this->skin->error('up_to_date');
 648              $this->skin->after();
 649              return false;
 650          }
 651  
 652          $r = $current->response[ $theme ];
 653  
 654          add_filter('upgrader_pre_install', array(&$this, 'current_before'), 10, 2);
 655          add_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);
 656          add_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);
 657  
 658          $options = array(
 659                          'package' => $r['package'],
 660                          'destination' => WP_CONTENT_DIR . '/themes',
 661                          'clear_destination' => true,
 662                          'clear_working' => true,
 663                          'hook_extra' => array(
 664                                              'theme' => $theme
 665                                              )
 666                          );
 667  
 668          $this->run($options);
 669  
 670          if ( ! $this->result || is_wp_error($this->result) )
 671              return $this->result;
 672  
 673          // Force refresh of theme update information
 674          delete_transient('update_themes');
 675  
 676          return true;
 677      }
 678  
 679  	function current_before($return, $theme) {
 680  
 681          if ( is_wp_error($return) )
 682              return $return;
 683  
 684          $theme = isset($theme['theme']) ? $theme['theme'] : '';
 685  
 686          if ( $theme != get_stylesheet() ) //If not current
 687              return $return;
 688          //Change to maintainence mode now.
 689          $this->maintenance_mode(true);
 690  
 691          return $return;
 692      }
 693  	function current_after($return, $theme) {
 694          if ( is_wp_error($return) )
 695              return $return;
 696  
 697          $theme = isset($theme['theme']) ? $theme['theme'] : '';
 698  
 699          if ( $theme != get_stylesheet() ) //If not current
 700              return $return;
 701  
 702          //Ensure stylesheet name hasnt changed after the upgrade:
 703          if ( $theme == get_stylesheet() && $theme != $this->result['destination_name'] ) {
 704              $theme_info = $this->theme_info();
 705              $stylesheet = $this->result['destination_name'];
 706              $template = !empty($theme_info['Template']) ? $theme_info['Template'] : $stylesheet;
 707              switch_theme($template, $stylesheet, true);
 708          }
 709  
 710          //Time to remove maintainence mode
 711          $this->maintenance_mode(false);
 712          return $return;
 713      }
 714  
 715  	function delete_old_theme($removed, $local_destination, $remote_destination, $theme) {
 716          global $wp_filesystem;
 717  
 718          $theme = isset($theme['theme']) ? $theme['theme'] : '';
 719  
 720          if ( is_wp_error($removed) || empty($theme) )
 721              return $removed; //Pass errors through.
 722  
 723          $themes_dir = $wp_filesystem->wp_themes_dir();
 724          if ( $wp_filesystem->exists( trailingslashit($themes_dir) . $theme ) )
 725              if ( ! $wp_filesystem->delete( trailingslashit($themes_dir) . $theme, true ) )
 726                  return false;
 727          return true;
 728      }
 729  
 730  	function theme_info() {
 731          if ( empty($this->result['destination_name']) )
 732              return false;
 733          return get_theme_data(WP_CONTENT_DIR . '/themes/' . $this->result['destination_name'] . '/style.css');
 734      }
 735  
 736  }
 737  
 738  /**
 739   * Core Upgrader class for WordPress. It allows for WordPress to upgrade itself in combiantion with the wp-admin/includes/update-core.php file
 740   *
 741   * @TODO More Detailed docs, for methods as well.
 742   *
 743   * @package WordPress
 744   * @subpackage Upgrader
 745   * @since 2.8.0
 746   */
 747  class Core_Upgrader extends WP_Upgrader {
 748  
 749  	function upgrade_strings() {
 750          $this->strings['up_to_date'] = __('WordPress is at the latest version.');
 751          $this->strings['no_package'] = __('Upgrade package not available.');
 752          $this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>.');
 753          $this->strings['unpack_package'] = __('Unpacking the update.');
 754          $this->strings['copy_failed'] = __('Could not copy files.');
 755      }
 756  
 757  	function upgrade($current) {
 758          global $wp_filesystem;
 759  
 760          $this->init();
 761          $this->upgrade_strings();
 762  
 763          if ( !empty($feedback) )
 764              add_filter('update_feedback', $feedback);
 765  
 766          // Is an update available?
 767          if ( !isset( $current->response ) || $current->response == 'latest' )
 768              return new WP_Error('up_to_date', $this->strings['up_to_date']);
 769  
 770          $res = $this->fs_connect( array(ABSPATH, WP_CONTENT_DIR) );
 771          if ( is_wp_error($res) )
 772              return $res;
 773  
 774          $wp_dir = trailingslashit($wp_filesystem->abspath());
 775  
 776          $download = $this->download_package( $current->package );
 777          if ( is_wp_error($download) )
 778              return $download;
 779  
 780          $working_dir = $this->unpack_package( $download );
 781          if ( is_wp_error($working_dir) )
 782              return $working_dir;
 783  
 784          // Copy update-core.php from the new version into place.
 785          if ( !$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true) ) {
 786              $wp_filesystem->delete($working_dir, true);
 787              return new WP_Error('copy_failed', $this->strings['copy_failed']);
 788          }
 789          $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
 790  
 791          require (ABSPATH . 'wp-admin/includes/update-core.php');
 792  
 793          return update_core($working_dir, $wp_dir);
 794      }
 795  
 796  }
 797  
 798  /**
 799   * Generic Skin for the WordPress Upgrader classes. This skin is designed to be extended for specific purposes.
 800   *
 801   * @TODO More Detailed docs, for methods as well.
 802   *
 803   * @package WordPress
 804   * @subpackage Upgrader
 805   * @since 2.8.0
 806   */
 807  class WP_Upgrader_Skin {
 808  
 809      var $upgrader;
 810      var $done_header = false;
 811  
 812  	function WP_Upgrader_Skin($args = array()) {
 813          return $this->__construct($args);
 814      }
 815  	function __construct($args = array()) {
 816          $defaults = array( 'url' => '', 'nonce' => '', 'title' => '', 'context' => false );
 817          $this->options = wp_parse_args($args, $defaults);
 818      }
 819  
 820  	function set_upgrader(&$upgrader) {
 821          if ( is_object($upgrader) )
 822              $this->upgrader =& $upgrader;
 823      }
 824  	function set_result($result) {
 825          $this->result = $result;
 826      }
 827  
 828  	function request_filesystem_credentials($error = false) {
 829          $url = $this->options['url'];
 830          $context = $this->options['context'];
 831          if ( !empty($this->options['nonce']) )
 832              $url = wp_nonce_url($url, $this->options['nonce']);
 833          return request_filesystem_credentials($url, '', $error, $context); //Possible to bring inline, Leaving as is for now.
 834      }
 835  
 836  	function header() {
 837          if ( $this->done_header )
 838              return;
 839          $this->done_header = true;
 840          echo '<div class="wrap">';
 841          echo screen_icon();
 842          echo '<h2>' . $this->options['title'] . '</h2>';
 843      }
 844  	function footer() {
 845          echo '</div>';
 846      }
 847  
 848  	function error($errors) {
 849          if ( ! $this->done_header )
 850              $this->header();
 851          if ( is_string($errors) ) {
 852              $this->feedback($errors);
 853          } elseif ( is_wp_error($errors) && $errors->get_error_code() ) {
 854              foreach ( $errors->get_error_messages() as $message ) {
 855                  if ( $errors->get_error_data() )
 856                      $this->feedback($message . ' ' . $errors->get_error_data() );
 857                  else
 858                      $this->feedback($message);
 859              }
 860          }
 861      }
 862  
 863  	function feedback($string) {
 864          if ( isset( $this->upgrader->strings[$string] ) )
 865              $string = $this->upgrader->strings[$string];
 866  
 867          if ( strpos($string, '%') !== false ) {
 868              $args = func_get_args();
 869              $args = array_splice($args, 1);
 870              if ( !empty($args) )
 871                  $string = vsprintf($string, $args);
 872          }
 873          if ( empty($string) )
 874              return;
 875          show_message($string);
 876      }
 877  	function before() {}
 878  	function after() {}
 879  
 880  }
 881  
 882  /**
 883   * Plugin Upgrader Skin for WordPress Plugin Upgrades.
 884   *
 885   * @TODO More Detailed docs, for methods as well.
 886   *
 887   * @package WordPress
 888   * @subpackage Upgrader
 889   * @since 2.8.0
 890   */
 891  class Plugin_Upgrader_Skin extends WP_Upgrader_Skin {
 892      var $plugin = '';
 893      var $plugin_active = false;
 894  
 895  	function Plugin_Upgrader_Skin($args = array()) {
 896          return $this->__construct($args);
 897      }
 898  
 899  	function __construct($args = array()) {
 900          $defaults = array( 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => __('Upgrade Plugin') );
 901          $args = wp_parse_args($args, $defaults);
 902  
 903          $this->plugin = $args['plugin'];
 904  
 905          $this->plugin_active = is_plugin_active($this->plugin);
 906  
 907          parent::__construct($args);
 908      }
 909  
 910  	function after() {
 911          if ( $this->upgrader->bulk )
 912              return;
 913  
 914          $this->plugin = $this->upgrader->plugin_info();
 915          if( !empty($this->plugin) && !is_wp_error($this->result) && $this->plugin_active ){
 916              show_message(__('Attempting reactivation of the plugin'));
 917              echo '<iframe style="border:0;overflow:hidden" width="100%" height="170px" src="' . wp_nonce_url('update.php?action=activate-plugin&plugin=' . $this->plugin, 'activate-plugin_' . $this->plugin) .'"></iframe>';
 918          }
 919  
 920          $update_actions =  array(
 921              '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>',
 922              'plugins_page' => '<a href="' . admin_url('plugins.php') . '" title="' . esc_attr__('Goto plugins page') . '" target="_parent">' . __('Return to Plugins page') . '</a>'
 923          );
 924          if ( $this->plugin_active )
 925              unset( $update_actions['activate_plugin'] );
 926          if ( ! $this->result || is_wp_error($this->result) )
 927              unset( $update_actions['activate_plugin'] );
 928  
 929          $update_actions = apply_filters('update_plugin_complete_actions', $update_actions, $this->plugin);
 930          if ( ! empty($update_actions) )
 931              $this->feedback('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$update_actions));
 932      }
 933  
 934  	function before() {
 935          if ( $this->upgrader->show_before ) {
 936              echo $this->upgrader->show_before;
 937              $this->upgrader->show_before = '';
 938          }
 939      }
 940  }
 941  
 942  /**
 943   * Plugin Installer Skin for WordPress Plugin Installer.
 944   *
 945   * @TODO More Detailed docs, for methods as well.
 946   *
 947   * @package WordPress
 948   * @subpackage Upgrader
 949   * @since 2.8.0
 950   */
 951  class Plugin_Installer_Skin extends WP_Upgrader_Skin {
 952      var $api;
 953      var $type;
 954  
 955  	function Plugin_Installer_Skin($args = array()) {
 956          return $this->__construct($args);
 957      }
 958  
 959  	function __construct($args = array()) {
 960          $defaults = array( 'type' => 'web', 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => '' );
 961          $args = wp_parse_args($args, $defaults);
 962  
 963          $this->type = $args['type'];
 964          $this->api = isset($args['api']) ? $args['api'] : array();
 965  
 966          parent::__construct($args);
 967      }
 968  
 969  	function before() {
 970          if ( !empty($this->api) )
 971              $this->upgrader->strings['process_success'] = sprintf( __('Successfully installed the plugin <strong>%s %s</strong>.'), $this->api->name, $this->api->version);
 972      }
 973  
 974  	function after() {
 975  
 976          $plugin_file = $this->upgrader->plugin_info();
 977  
 978          $install_actions = array(
 979              '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>',
 980                              );
 981  
 982          if ( $this->type == 'web' )
 983              $install_actions['plugins_page'] = '<a href="' . admin_url('plugin-install.php') . '" title="' . esc_attr__('Return to Plugin Installer') . '" target="_parent">' . __('Return to Plugin Installer') . '</a>';
 984          else
 985              $install_actions['plugins_page'] = '<a href="' . admin_url('plugins.php') . '" title="' . esc_attr__('Return to Plugins page') . '" target="_parent">' . __('Return to Plugins page') . '</a>';
 986  
 987  
 988          if ( ! $this->result || is_wp_error($this->result) )
 989              unset( $install_actions['activate_plugin'] );
 990  
 991          $install_actions = apply_filters('install_plugin_complete_actions', $install_actions, $this->api, $plugin_file);
 992          if ( ! empty($install_actions) )
 993              $this->feedback('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$install_actions));
 994      }
 995  }
 996  
 997  /**
 998   * Theme Installer Skin for the WordPress Theme Installer.
 999   *
1000   * @TODO More Detailed docs, for methods as well.
1001   *
1002   * @package WordPress
1003   * @subpackage Upgrader
1004   * @since 2.8.0
1005   */
1006  class Theme_Installer_Skin extends WP_Upgrader_Skin {
1007      var $api;
1008      var $type;
1009  
1010  	function Theme_Installer_Skin($args = array()) {
1011          return $this->__construct($args);
1012      }
1013  
1014  	function __construct($args = array()) {
1015          $defaults = array( 'type' => 'web', 'url' => '', 'theme' => '', 'nonce' => '', 'title' => '' );
1016          $args = wp_parse_args($args, $defaults);
1017  
1018          $this->type = $args['type'];
1019          $this->api = isset($args['api']) ? $args['api'] : array();
1020  
1021          parent::__construct($args);
1022      }
1023  
1024  	function before() {
1025          if ( !empty($this->api) ) {
1026              /* translators: 1: theme name, 2: version */
1027              $this->upgrader->strings['process_success'] = sprintf( __('Successfully installed the theme <strong>%1$s %2$s</strong>.'), $this->api->name, $this->api->version);
1028          }
1029      }
1030  
1031  	function after() {
1032          if ( empty($this->upgrader->result['destination_name']) )
1033              return;
1034  
1035          $theme_info = $this->upgrader->theme_info();
1036          if ( empty($theme_info) )
1037              return;
1038          $name = $theme_info['Name'];
1039          $stylesheet = $this->upgrader->result['destination_name'];
1040          $template = !empty($theme_info['Template']) ? $theme_info['Template'] : $stylesheet;
1041  
1042          $preview_link = htmlspecialchars( add_query_arg( array('preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'TB_iframe' => 'true' ), trailingslashit(esc_url(get_option('home'))) ) );
1043          $activate_link = wp_nonce_url("themes.php?action=activate&amp;template=" . urlencode($template) . "&amp;stylesheet=" . urlencode($stylesheet), 'switch-theme_' . $template);
1044  
1045          $install_actions = array(
1046              'preview' => '<a href="' . $preview_link . '" class="thickbox thickbox-preview" title="' . esc_attr(sprintf(__('Preview &#8220;%s&#8221;'), $name)) . '">' . __('Preview') . '</a>',
1047              'activate' => '<a href="' . $activate_link .  '" class="activatelink" title="' . esc_attr( sprintf( __('Activate &#8220;%s&#8221;'), $name ) ) . '">' . __('Activate') . '</a>'
1048                              );
1049  
1050          if ( $this->type == 'web' )
1051              $install_actions['themes_page'] = '<a href="' . admin_url('theme-install.php') . '" title="' . esc_attr__('Return to Theme Installer') . '" target="_parent">' . __('Return to Theme Installer') . '</a>';
1052          else
1053              $install_actions['themes_page'] = '<a href="' . admin_url('themes.php') . '" title="' . esc_attr__('Themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>';
1054  
1055          if ( ! $this->result || is_wp_error($this->result) )
1056              unset( $install_actions['activate'], $install_actions['preview'] );
1057  
1058          $install_actions = apply_filters('install_theme_complete_actions', $install_actions, $this->api, $stylesheet, $theme_info);
1059          if ( ! empty($install_actions) )
1060              $this->feedback('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$install_actions));
1061      }
1062  }
1063  
1064  /**
1065   * Theme Upgrader Skin for WordPress Theme Upgrades.
1066   *
1067   * @TODO More Detailed docs, for methods as well.
1068   *
1069   * @package WordPress
1070   * @subpackage Upgrader
1071   * @since 2.8.0
1072   */
1073  class Theme_Upgrader_Skin extends WP_Upgrader_Skin {
1074      var $theme = '';
1075  
1076  	function Theme_Upgrader_Skin($args = array()) {
1077          return $this->__construct($args);
1078      }
1079  
1080  	function __construct($args = array()) {
1081          $defaults = array( 'url' => '', 'theme' => '', 'nonce' => '', 'title' => __('Upgrade Theme') );
1082          $args = wp_parse_args($args, $defaults);
1083  
1084          $this->theme = $args['theme'];
1085  
1086          parent::__construct($args);
1087      }
1088  
1089  	function after() {
1090  
1091          if ( !empty($this->upgrader->result['destination_name']) &&
1092              ($theme_info = $this->upgrader->theme_info()) &&
1093              !empty($theme_info) ) {
1094  
1095              $name = $theme_info['Name'];
1096              $stylesheet = $this->upgrader->result['destination_name'];
1097              $template = !empty($theme_info['Template']) ? $theme_info['Template'] : $stylesheet;
1098  
1099              $preview_link = htmlspecialchars( add_query_arg( array('preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'TB_iframe' => 'true' ), trailingslashit(esc_url(get_option('home'))) ) );
1100              $activate_link = wp_nonce_url("themes.php?action=activate&amp;template=" . urlencode($template) . "&amp;stylesheet=" . urlencode($stylesheet), 'switch-theme_' . $template);
1101  
1102              $update_actions =  array(
1103                  'preview' => '<a href="' . $preview_link . '" class="thickbox thickbox-preview" title="' . esc_attr(sprintf(__('Preview &#8220;%s&#8221;'), $name)) . '">' . __('Preview') . '</a>',
1104                  'activate' => '<a href="' . $activate_link .  '" class="activatelink" title="' . esc_attr( sprintf( __('Activate &#8220;%s&#8221;'), $name ) ) . '">' . __('Activate') . '</a>',
1105              );
1106              if ( ( ! $this->result || is_wp_error($this->result) ) || $stylesheet == get_stylesheet() )
1107                  unset($update_actions['preview'], $update_actions['activate']);
1108          }
1109  
1110          $update_actions['themes_page'] = '<a href="' . admin_url('themes.php') . '" title="' . esc_attr__('Return to Themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>';
1111  
1112          $update_actions = apply_filters('update_theme_complete_actions', $update_actions, $this->theme);
1113          if ( ! empty($update_actions) )
1114              $this->feedback('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$update_actions));
1115      }
1116  }
1117  
1118  /**
1119   * 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.
1120   *
1121   * @TODO More Detailed docs, for methods as well.
1122   *
1123   * @package WordPress
1124   * @subpackage Upgrader
1125   * @since 2.8.0
1126   */
1127  class File_Upload_Upgrader {
1128      var $package;
1129      var $filename;
1130  
1131  	function File_Upload_Upgrader($form, $urlholder) {
1132          return $this->__construct($form, $urlholder);
1133      }
1134  	function __construct($form, $urlholder) {
1135          if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) )
1136              wp_die($uploads['error']);
1137  
1138          if ( empty($_FILES[$form]['name']) && empty($_GET[$urlholder]) )
1139              wp_die(__('Please select a file'));
1140  
1141          if ( !empty($_FILES) )
1142              $this->filename = $_FILES[$form]['name'];
1143          else if ( isset($_GET[$urlholder]) )
1144              $this->filename = $_GET[$urlholder];
1145  
1146          //Handle a newly uploaded file, Else assume its already been uploaded
1147          if ( !empty($_FILES) ) {
1148              $this->filename = wp_unique_filename( $uploads['basedir'], $this->filename );
1149              $this->package = $uploads['basedir'] . '/' . $this->filename;
1150  
1151              // Move the file to the uploads dir
1152              if ( false === @ move_uploaded_file( $_FILES[$form]['tmp_name'], $this->package) )
1153                  wp_die( sprintf( __('The uploaded file could not be moved to %s.' ), $uploads['path']));
1154          } else {
1155              $this->package = $uploads['basedir'] . '/' . $this->filename;
1156          }
1157      }
1158  }


Generated: Fri Jan 8 00:19:48 2010 Cross-referenced by PHPXref 0.7