web/wp-admin/includes/class-wp-upgrader.php
changeset 194 32102edaa81b
parent 136 bde1974c263b
child 204 09a1c134465b
equal deleted inserted replaced
193:2f6f6f7551ca 194:32102edaa81b
    23 class WP_Upgrader {
    23 class WP_Upgrader {
    24 	var $strings = array();
    24 	var $strings = array();
    25 	var $skin = null;
    25 	var $skin = null;
    26 	var $result = array();
    26 	var $result = array();
    27 
    27 
    28 	function WP_Upgrader($skin = null) {
       
    29 		return $this->__construct($skin);
       
    30 	}
       
    31 	function __construct($skin = null) {
    28 	function __construct($skin = null) {
    32 		if ( null == $skin )
    29 		if ( null == $skin )
    33 			$this->skin = new WP_Upgrader_Skin();
    30 			$this->skin = new WP_Upgrader_Skin();
    34 		else
    31 		else
    35 			$this->skin = $skin;
    32 			$this->skin = $skin;
    41 	}
    38 	}
    42 
    39 
    43 	function generic_strings() {
    40 	function generic_strings() {
    44 		$this->strings['bad_request'] = __('Invalid Data provided.');
    41 		$this->strings['bad_request'] = __('Invalid Data provided.');
    45 		$this->strings['fs_unavailable'] = __('Could not access filesystem.');
    42 		$this->strings['fs_unavailable'] = __('Could not access filesystem.');
    46 		$this->strings['fs_error'] = __('Filesystem error');
    43 		$this->strings['fs_error'] = __('Filesystem error.');
    47 		$this->strings['fs_no_root_dir'] = __('Unable to locate WordPress Root directory.');
    44 		$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).');
    45 		$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.');
    46 		$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.');
    47 		$this->strings['fs_no_themes_dir'] = __('Unable to locate WordPress Theme directory.');
       
    48 		/* translators: %s: directory name */
    51 		$this->strings['fs_no_folder'] = __('Unable to locate needed folder (%s).');
    49 		$this->strings['fs_no_folder'] = __('Unable to locate needed folder (%s).');
    52 
    50 
    53 		$this->strings['download_failed'] = __('Download failed.');
    51 		$this->strings['download_failed'] = __('Download failed.');
    54 		$this->strings['installing_package'] = __('Installing the latest version.');
    52 		$this->strings['installing_package'] = __('Installing the latest version…');
    55 		$this->strings['folder_exists'] = __('Destination folder already exists.');
    53 		$this->strings['folder_exists'] = __('Destination folder already exists.');
    56 		$this->strings['mkdir_failed'] = __('Could not create directory.');
    54 		$this->strings['mkdir_failed'] = __('Could not create directory.');
    57 		$this->strings['bad_package'] = __('Incompatible Archive');
    55 		$this->strings['incompatible_archive'] = __('The package could not be installed.');
    58 
    56 
    59 		$this->strings['maintenance_start'] = __('Enabling Maintenance mode.');
    57 		$this->strings['maintenance_start'] = __('Enabling Maintenance mode…');
    60 		$this->strings['maintenance_end'] = __('Disabling Maintenance mode.');
    58 		$this->strings['maintenance_end'] = __('Disabling Maintenance mode…');
    61 	}
    59 	}
    62 
    60 
    63 	function fs_connect( $directories = array() ) {
    61 	function fs_connect( $directories = array() ) {
    64 		global $wp_filesystem;
    62 		global $wp_filesystem;
    65 
    63 
   153 		if ( $delete_package )
   151 		if ( $delete_package )
   154 			unlink($package);
   152 			unlink($package);
   155 
   153 
   156 		if ( is_wp_error($result) ) {
   154 		if ( is_wp_error($result) ) {
   157 			$wp_filesystem->delete($working_dir, true);
   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 			}
   158 			return $result;
   159 			return $result;
   159 		}
   160 		}
   160 
   161 
   161 		return $working_dir;
   162 		return $working_dir;
   162 	}
   163 	}
   190 
   191 
   191 		//Locate which directory to copy to the new folder, This is based on the actual folder holding the files.
   192 		//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 		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 			$source = trailingslashit($source) . trailingslashit($source_files[0]);
   194 		elseif ( count($source_files) == 0 )
   195 		elseif ( count($source_files) == 0 )
   195 			return new WP_Error('bad_package', $this->strings['bad_package']); //There are no files?
   196 			return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], __( 'The plugin contains no files.' ) ); //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 		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);
   197 
   199 
   198 		//Hook ability to change the source file location..
   200 		//Hook ability to change the source file location..
   199 		$source = apply_filters('upgrader_source_selection', $source, $remote_source, $this);
   201 		$source = apply_filters('upgrader_source_selection', $source, $remote_source, $this);
   200 		if ( is_wp_error($source) )
   202 		if ( is_wp_error($source) )
   201 			return $source;
   203 			return $source;
   208 		if ( in_array( $destination, array(ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes') ) ) {
   210 		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));
   211 			$remote_destination = trailingslashit($remote_destination) . trailingslashit(basename($source));
   210 			$destination = trailingslashit($destination) . trailingslashit(basename($source));
   212 			$destination = trailingslashit($destination) . trailingslashit(basename($source));
   211 		}
   213 		}
   212 
   214 
   213 		if ( $wp_filesystem->exists($remote_destination) ) {
   215 		if ( $clear_destination ) {
   214 			if ( $clear_destination ) {
   216 			//We're going to clear the destination if there's something there
   215 				//We're going to clear the destination if theres something there
   217 			$this->skin->feedback('remove_old');
   216 				$this->skin->feedback('remove_old');
   218 			$removed = true;
       
   219 			if ( $wp_filesystem->exists($remote_destination) )
   217 				$removed = $wp_filesystem->delete($remote_destination, true);
   220 				$removed = $wp_filesystem->delete($remote_destination, true);
   218 				$removed = apply_filters('upgrader_clear_destination', $removed, $local_destination, $remote_destination, $hook_extra);
   221 			$removed = apply_filters('upgrader_clear_destination', $removed, $local_destination, $remote_destination, $hook_extra);
   219 
   222 
   220 				if ( is_wp_error($removed) )
   223 			if ( is_wp_error($removed) )
   221 					return $removed;
   224 				return $removed;
   222 				else if ( ! $removed )
   225 			else if ( ! $removed )
   223 					return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
   226 				return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
   224 			} else {
   227 		} elseif ( $wp_filesystem->exists($remote_destination) ) {
   225 				//If we're not clearing the destination folder and something exists there allready, Bail.
   228 			//If we're not clearing the destination folder and something exists there already, Bail.
   226 				//But first check to see if there are actually any files in the folder.
   229 			//But first check to see if there are actually any files in the folder.
   227 				$_files = $wp_filesystem->dirlist($remote_destination);
   230 			$_files = $wp_filesystem->dirlist($remote_destination);
   228 				if ( ! empty($_files) ) {
   231 			if ( ! empty($_files) ) {
   229 					$wp_filesystem->delete($remote_source, true); //Clear out the source files.
   232 				$wp_filesystem->delete($remote_source, true); //Clear out the source files.
   230 					return new WP_Error('folder_exists', $this->strings['folder_exists'], $remote_destination );
   233 				return new WP_Error('folder_exists', $this->strings['folder_exists'], $remote_destination );
   231 				}
       
   232 			}
   234 			}
   233 		}
   235 		}
   234 
   236 
   235 		//Create destination if needed
   237 		//Create destination if needed
   236 		if ( !$wp_filesystem->exists($remote_destination) )
   238 		if ( !$wp_filesystem->exists($remote_destination) )
   295 
   297 
   296 		//Download the package (Note, This just returns the filename of the file if the package is a local file)
   298 		//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 );
   299 		$download = $this->download_package( $package );
   298 		if ( is_wp_error($download) ) {
   300 		if ( is_wp_error($download) ) {
   299 			$this->skin->error($download);
   301 			$this->skin->error($download);
       
   302 			$this->skin->after();
   300 			return $download;
   303 			return $download;
   301 		}
   304 		}
   302 
   305 
   303 		//Unzip's the file into a temporary directory
   306 		$delete_package = ($download != $package); // Do not delete a "local" file
   304 		$working_dir = $this->unpack_package( $download );
   307 
       
   308 		//Unzips the file into a temporary directory
       
   309 		$working_dir = $this->unpack_package( $download, $delete_package );
   305 		if ( is_wp_error($working_dir) ) {
   310 		if ( is_wp_error($working_dir) ) {
   306 			$this->skin->error($working_dir);
   311 			$this->skin->error($working_dir);
       
   312 			$this->skin->after();
   307 			return $working_dir;
   313 			return $working_dir;
   308 		}
   314 		}
   309 
   315 
   310 		//With the given options, this installs it to the destination directory.
   316 		//With the given options, this installs it to the destination directory.
   311 		$result = $this->install_package( array(
   317 		$result = $this->install_package( array(
   318 		$this->skin->set_result($result);
   324 		$this->skin->set_result($result);
   319 		if ( is_wp_error($result) ) {
   325 		if ( is_wp_error($result) ) {
   320 			$this->skin->error($result);
   326 			$this->skin->error($result);
   321 			$this->skin->feedback('process_failed');
   327 			$this->skin->feedback('process_failed');
   322 		} else {
   328 		} else {
   323 			//Install Suceeded
   329 			//Install Succeeded
   324 			$this->skin->feedback('process_success');
   330 			$this->skin->feedback('process_success');
   325 		}
   331 		}
   326 		$this->skin->after();
   332 		$this->skin->after();
   327 
   333 
   328 		if ( !$is_multi )
   334 		if ( !$is_multi )
   363 	var $bulk = false;
   369 	var $bulk = false;
   364 	var $show_before = '';
   370 	var $show_before = '';
   365 
   371 
   366 	function upgrade_strings() {
   372 	function upgrade_strings() {
   367 		$this->strings['up_to_date'] = __('The plugin is at the latest version.');
   373 		$this->strings['up_to_date'] = __('The plugin is at the latest version.');
   368 		$this->strings['no_package'] = __('Upgrade package not available.');
   374 		$this->strings['no_package'] = __('Update package not available.');
   369 		$this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>.');
   375 		$this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>&#8230;');
   370 		$this->strings['unpack_package'] = __('Unpacking the update.');
   376 		$this->strings['unpack_package'] = __('Unpacking the update&#8230;');
   371 		$this->strings['deactivate_plugin'] = __('Deactivating the plugin.');
   377 		$this->strings['remove_old'] = __('Removing the old version of the plugin&#8230;');
   372 		$this->strings['remove_old'] = __('Removing the old version of the plugin.');
       
   373 		$this->strings['remove_old_failed'] = __('Could not remove the old plugin.');
   378 		$this->strings['remove_old_failed'] = __('Could not remove the old plugin.');
   374 		$this->strings['process_failed'] = __('Plugin upgrade Failed.');
   379 		$this->strings['process_failed'] = __('Plugin update failed.');
   375 		$this->strings['process_success'] = __('Plugin upgraded successfully.');
   380 		$this->strings['process_success'] = __('Plugin updated successfully.');
   376 	}
   381 	}
   377 
   382 
   378 	function install_strings() {
   383 	function install_strings() {
   379 		$this->strings['no_package'] = __('Install package not available.');
   384 		$this->strings['no_package'] = __('Install package not available.');
   380 		$this->strings['downloading_package'] = __('Downloading install package from <span class="code">%s</span>.');
   385 		$this->strings['downloading_package'] = __('Downloading install package from <span class="code">%s</span>&#8230;');
   381 		$this->strings['unpack_package'] = __('Unpacking the package.');
   386 		$this->strings['unpack_package'] = __('Unpacking the package&#8230;');
   382 		$this->strings['installing_package'] = __('Installing the plugin.');
   387 		$this->strings['installing_package'] = __('Installing the plugin&#8230;');
   383 		$this->strings['process_failed'] = __('Plugin Install Failed.');
   388 		$this->strings['process_failed'] = __('Plugin install failed.');
   384 		$this->strings['process_success'] = __('Plugin Installed successfully.');
   389 		$this->strings['process_success'] = __('Plugin installed successfully.');
   385 	}
   390 	}
   386 
   391 
   387 	function install($package) {
   392 	function install($package) {
   388 
   393 
   389 		$this->init();
   394 		$this->init();
   390 		$this->install_strings();
   395 		$this->install_strings();
       
   396 
       
   397 		add_filter('upgrader_source_selection', array(&$this, 'check_package') );
   391 
   398 
   392 		$this->run(array(
   399 		$this->run(array(
   393 					'package' => $package,
   400 					'package' => $package,
   394 					'destination' => WP_PLUGIN_DIR,
   401 					'destination' => WP_PLUGIN_DIR,
   395 					'clear_destination' => false, //Do not overwrite files.
   402 					'clear_destination' => false, //Do not overwrite files.
   396 					'clear_working' => true,
   403 					'clear_working' => true,
   397 					'hook_extra' => array()
   404 					'hook_extra' => array()
   398 					));
   405 					));
   399 
   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 
   400 		// Force refresh of plugin update information
   412 		// Force refresh of plugin update information
   401 		delete_transient('update_plugins');
   413 		delete_site_transient('update_plugins');
   402 
   414 		wp_cache_delete( 'plugins', 'plugins' );
       
   415 
       
   416 		return true;
   403 	}
   417 	}
   404 
   418 
   405 	function upgrade($plugin) {
   419 	function upgrade($plugin) {
   406 
   420 
   407 		$this->init();
   421 		$this->init();
   408 		$this->upgrade_strings();
   422 		$this->upgrade_strings();
   409 
   423 
   410 		$current = get_transient( 'update_plugins' );
   424 		$current = get_site_transient( 'update_plugins' );
   411 		if ( !isset( $current->response[ $plugin ] ) ) {
   425 		if ( !isset( $current->response[ $plugin ] ) ) {
       
   426 			$this->skin->before();
   412 			$this->skin->set_result(false);
   427 			$this->skin->set_result(false);
   413 			$this->skin->error('up_to_date');
   428 			$this->skin->error('up_to_date');
   414 			$this->skin->after();
   429 			$this->skin->after();
   415 			return false;
   430 			return false;
   416 		}
   431 		}
   418 		// Get the URL to the zip file
   433 		// Get the URL to the zip file
   419 		$r = $current->response[ $plugin ];
   434 		$r = $current->response[ $plugin ];
   420 
   435 
   421 		add_filter('upgrader_pre_install', array(&$this, 'deactivate_plugin_before_upgrade'), 10, 2);
   436 		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);
   437 		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.
   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.
   424 
   439 
   425 		$this->run(array(
   440 		$this->run(array(
   426 					'package' => $r->package,
   441 					'package' => $r->package,
   427 					'destination' => WP_PLUGIN_DIR,
   442 					'destination' => WP_PLUGIN_DIR,
   428 					'clear_destination' => true,
   443 					'clear_destination' => true,
   430 					'hook_extra' => array(
   445 					'hook_extra' => array(
   431 								'plugin' => $plugin
   446 								'plugin' => $plugin
   432 					)
   447 					)
   433 				));
   448 				));
   434 
   449 
   435 		// Cleanup our hooks, incase something else does a upgrade on this connection.
   450 		// Cleanup our hooks, in case something else does a upgrade on this connection.
   436 		remove_filter('upgrader_pre_install', array(&$this, 'deactivate_plugin_before_upgrade'));
   451 		remove_filter('upgrader_pre_install', array(&$this, 'deactivate_plugin_before_upgrade'));
   437 		remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));
   452 		remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));
   438 
   453 
   439 		if ( ! $this->result || is_wp_error($this->result) )
   454 		if ( ! $this->result || is_wp_error($this->result) )
   440 			return $this->result;
   455 			return $this->result;
   441 
   456 
   442 		// Force refresh of plugin update information
   457 		// Force refresh of plugin update information
   443 		delete_transient('update_plugins');
   458 		delete_site_transient('update_plugins');
       
   459 		wp_cache_delete( 'plugins', 'plugins' );
   444 	}
   460 	}
   445 
   461 
   446 	function bulk_upgrade($plugins) {
   462 	function bulk_upgrade($plugins) {
   447 
   463 
   448 		$this->init();
   464 		$this->init();
   449 		$this->bulk = true;
   465 		$this->bulk = true;
   450 		$this->upgrade_strings();
   466 		$this->upgrade_strings();
   451 
   467 
   452 		$current = get_transient( 'update_plugins' );
   468 		$current = get_site_transient( 'update_plugins' );
   453 
   469 
   454 		add_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'), 10, 4);
   470 		add_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'), 10, 4);
   455 
   471 
   456 		$this->skin->header();
   472 		$this->skin->header();
   457 
   473 
   460 		if ( ! $res ) {
   476 		if ( ! $res ) {
   461 			$this->skin->footer();
   477 			$this->skin->footer();
   462 			return false;
   478 			return false;
   463 		}
   479 		}
   464 
   480 
   465 		$this->maintenance_mode(true);
   481 		$this->skin->bulk_header();
   466 
   482 
   467 		$all = count($plugins);
   483 		// Only start maintenance mode if running in Multisite OR the plugin is in use
   468 		$i = 1;
   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;
   469 		foreach ( $plugins as $plugin ) {
   494 		foreach ( $plugins as $plugin ) {
   470 
   495 			$this->update_current++;
   471 			$this->show_before = sprintf( '<h4>' . __('Updating plugin %1$d of %2$d...') . '</h4>', $i, $all );
   496 			$this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
   472 			$i++;
       
   473 
   497 
   474 			if ( !isset( $current->response[ $plugin ] ) ) {
   498 			if ( !isset( $current->response[ $plugin ] ) ) {
   475 				$this->skin->set_result(false);
   499 				$this->skin->set_result(false);
       
   500 				$this->skin->before();
   476 				$this->skin->error('up_to_date');
   501 				$this->skin->error('up_to_date');
   477 				$this->skin->after();
   502 				$this->skin->after();
   478 				$results[$plugin] = false;
   503 				$results[$plugin] = false;
   479 				continue;
   504 				continue;
   480 			}
   505 			}
   498 			$results[$plugin] = $this->result;
   523 			$results[$plugin] = $this->result;
   499 
   524 
   500 			// Prevent credentials auth screen from displaying multiple times
   525 			// Prevent credentials auth screen from displaying multiple times
   501 			if ( false === $result )
   526 			if ( false === $result )
   502 				break;
   527 				break;
   503 		}
   528 		} //end foreach $plugins
       
   529 
   504 		$this->maintenance_mode(false);
   530 		$this->maintenance_mode(false);
       
   531 
       
   532 		$this->skin->bulk_footer();
       
   533 
   505 		$this->skin->footer();
   534 		$this->skin->footer();
   506 
   535 
   507 		// Cleanup our hooks, incase something else does a upgrade on this connection.
   536 		// Cleanup our hooks, in case something else does a upgrade on this connection.
   508 		remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));
   537 		remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));
   509 
   538 
   510 		// Force refresh of plugin update information
   539 		// Force refresh of plugin update information
   511 		delete_transient('update_plugins');
   540 		delete_site_transient('update_plugins');
       
   541 		wp_cache_delete( 'plugins', 'plugins' );
   512 
   542 
   513 		return $results;
   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;
   514 	}
   570 	}
   515 
   571 
   516 	//return plugin info.
   572 	//return plugin info.
   517 	function plugin_info() {
   573 	function plugin_info() {
   518 		if ( ! is_array($this->result) )
   574 		if ( ! is_array($this->result) )
   538 		$plugin = isset($plugin['plugin']) ? $plugin['plugin'] : '';
   594 		$plugin = isset($plugin['plugin']) ? $plugin['plugin'] : '';
   539 		if ( empty($plugin) )
   595 		if ( empty($plugin) )
   540 			return new WP_Error('bad_request', $this->strings['bad_request']);
   596 			return new WP_Error('bad_request', $this->strings['bad_request']);
   541 
   597 
   542 		if ( is_plugin_active($plugin) ) {
   598 		if ( is_plugin_active($plugin) ) {
   543 			$this->skin->feedback('deactivate_plugin');
       
   544 			//Deactivate the plugin silently, Prevent deactivation hooks from running.
   599 			//Deactivate the plugin silently, Prevent deactivation hooks from running.
   545 			deactivate_plugins($plugin, true);
   600 			deactivate_plugins($plugin, true);
   546 		}
   601 		}
   547 	}
   602 	}
   548 
   603 
   562 
   617 
   563 		if ( ! $wp_filesystem->exists($this_plugin_dir) ) //If its already vanished.
   618 		if ( ! $wp_filesystem->exists($this_plugin_dir) ) //If its already vanished.
   564 			return $removed;
   619 			return $removed;
   565 
   620 
   566 		// If plugin is in its own directory, recursively delete the directory.
   621 		// 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
   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
   568 			$deleted = $wp_filesystem->delete($this_plugin_dir, true);
   623 			$deleted = $wp_filesystem->delete($this_plugin_dir, true);
   569 		else
   624 		else
   570 			$deleted = $wp_filesystem->delete($plugins_dir . $plugin);
   625 			$deleted = $wp_filesystem->delete($plugins_dir . $plugin);
   571 
   626 
   572 		if ( ! $deleted )
   627 		if ( ! $deleted )
   573 			return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
   628 			return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
   574 
   629 
   575 		return $removed;
   630 		return true;
   576 	}
   631 	}
   577 }
   632 }
   578 
   633 
   579 /**
   634 /**
   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.
   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.
   586  * @since 2.8.0
   641  * @since 2.8.0
   587  */
   642  */
   588 class Theme_Upgrader extends WP_Upgrader {
   643 class Theme_Upgrader extends WP_Upgrader {
   589 
   644 
   590 	var $result;
   645 	var $result;
       
   646 	var $bulk = false;
   591 
   647 
   592 	function upgrade_strings() {
   648 	function upgrade_strings() {
   593 		$this->strings['up_to_date'] = __('The theme is at the latest version.');
   649 		$this->strings['up_to_date'] = __('The theme is at the latest version.');
   594 		$this->strings['no_package'] = __('Upgrade package not available.');
   650 		$this->strings['no_package'] = __('Update package not available.');
   595 		$this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>.');
   651 		$this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>&#8230;');
   596 		$this->strings['unpack_package'] = __('Unpacking the update.');
   652 		$this->strings['unpack_package'] = __('Unpacking the update&#8230;');
   597 		$this->strings['remove_old'] = __('Removing the old version of the theme.');
   653 		$this->strings['remove_old'] = __('Removing the old version of the theme&#8230;');
   598 		$this->strings['remove_old_failed'] = __('Could not remove the old theme.');
   654 		$this->strings['remove_old_failed'] = __('Could not remove the old theme.');
   599 		$this->strings['process_failed'] = __('Theme upgrade Failed.');
   655 		$this->strings['process_failed'] = __('Theme update failed.');
   600 		$this->strings['process_success'] = __('Theme upgraded successfully.');
   656 		$this->strings['process_success'] = __('Theme updated successfully.');
   601 	}
   657 	}
   602 
   658 
   603 	function install_strings() {
   659 	function install_strings() {
   604 		$this->strings['no_package'] = __('Install package not available.');
   660 		$this->strings['no_package'] = __('Install package not available.');
   605 		$this->strings['downloading_package'] = __('Downloading install package from <span class="code">%s</span>.');
   661 		$this->strings['downloading_package'] = __('Downloading install package from <span class="code">%s</span>&#8230;');
   606 		$this->strings['unpack_package'] = __('Unpacking the package.');
   662 		$this->strings['unpack_package'] = __('Unpacking the package&#8230;');
   607 		$this->strings['installing_package'] = __('Installing the theme.');
   663 		$this->strings['installing_package'] = __('Installing the theme&#8230;');
   608 		$this->strings['process_failed'] = __('Theme Install Failed.');
   664 		$this->strings['process_failed'] = __('Theme install failed.');
   609 		$this->strings['process_success'] = __('Theme Installed successfully.');
   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;
   610 	}
   740 	}
   611 
   741 
   612 	function install($package) {
   742 	function install($package) {
   613 
   743 
   614 		$this->init();
   744 		$this->init();
   615 		$this->install_strings();
   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);
   616 
   749 
   617 		$options = array(
   750 		$options = array(
   618 						'package' => $package,
   751 						'package' => $package,
   619 						'destination' => WP_CONTENT_DIR . '/themes',
   752 						'destination' => WP_CONTENT_DIR . '/themes',
   620 						'clear_destination' => false, //Do not overwrite files.
   753 						'clear_destination' => false, //Do not overwrite files.
   621 						'clear_working' => true
   754 						'clear_working' => true
   622 						);
   755 						);
   623 
   756 
   624 		$this->run($options);
   757 		$this->run($options);
   625 
   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 
   626 		if ( ! $this->result || is_wp_error($this->result) )
   762 		if ( ! $this->result || is_wp_error($this->result) )
   627 			return $this->result;
   763 			return $this->result;
   628 
   764 
   629 		// Force refresh of theme update information
   765 		// Force refresh of theme update information
   630 		delete_transient('update_themes');
   766 		delete_site_transient('update_themes');
   631 
   767 		search_theme_directories( true );
   632 		if ( empty($result['destination_name']) )
   768 		foreach ( wp_get_themes() as $theme )
   633 			return false;
   769 			$theme->cache_delete();
   634 		else
   770 
   635 			return $result['destination_name'];
   771 		return true;
   636 	}
   772 	}
   637 
   773 
   638 	function upgrade($theme) {
   774 	function upgrade($theme) {
   639 
   775 
   640 		$this->init();
   776 		$this->init();
   641 		$this->upgrade_strings();
   777 		$this->upgrade_strings();
   642 
   778 
   643 		// Is an update available?
   779 		// Is an update available?
   644 		$current = get_transient( 'update_themes' );
   780 		$current = get_site_transient( 'update_themes' );
   645 		if ( !isset( $current->response[ $theme ] ) ) {
   781 		if ( !isset( $current->response[ $theme ] ) ) {
       
   782 			$this->skin->before();
   646 			$this->skin->set_result(false);
   783 			$this->skin->set_result(false);
   647 			$this->skin->error('up_to_date');
   784 			$this->skin->error('up_to_date');
   648 			$this->skin->after();
   785 			$this->skin->after();
   649 			return false;
   786 			return false;
   650 		}
   787 		}
   665 											)
   802 											)
   666 						);
   803 						);
   667 
   804 
   668 		$this->run($options);
   805 		$this->run($options);
   669 
   806 
       
   807 		remove_filter('upgrader_pre_install', array(&$this, 'current_before'), 10, 2);
       
   808 		remove_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);
       
   809 		remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);
       
   810 
   670 		if ( ! $this->result || is_wp_error($this->result) )
   811 		if ( ! $this->result || is_wp_error($this->result) )
   671 			return $this->result;
   812 			return $this->result;
   672 
   813 
   673 		// Force refresh of theme update information
   814 		// Force refresh of theme update information
   674 		delete_transient('update_themes');
   815 		delete_site_transient('update_themes');
       
   816 		search_theme_directories( true );
       
   817 		foreach ( wp_get_themes() as $theme )
       
   818 			$theme->cache_delete();
   675 
   819 
   676 		return true;
   820 		return true;
       
   821 	}
       
   822 
       
   823 	function bulk_upgrade($themes) {
       
   824 
       
   825 		$this->init();
       
   826 		$this->bulk = true;
       
   827 		$this->upgrade_strings();
       
   828 
       
   829 		$current = get_site_transient( 'update_themes' );
       
   830 
       
   831 		add_filter('upgrader_pre_install', array(&$this, 'current_before'), 10, 2);
       
   832 		add_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);
       
   833 		add_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);
       
   834 
       
   835 		$this->skin->header();
       
   836 
       
   837 		// Connect to the Filesystem first.
       
   838 		$res = $this->fs_connect( array(WP_CONTENT_DIR) );
       
   839 		if ( ! $res ) {
       
   840 			$this->skin->footer();
       
   841 			return false;
       
   842 		}
       
   843 
       
   844 		$this->skin->bulk_header();
       
   845 
       
   846 		// Only start maintenance mode if running in Multisite OR the theme is in use
       
   847 		$maintenance = is_multisite(); // @TODO: This should only kick in for individual sites if at all possible.
       
   848 		foreach ( $themes as $theme )
       
   849 			$maintenance = $maintenance || $theme == get_stylesheet() || $theme == get_template();
       
   850 		if ( $maintenance )
       
   851 			$this->maintenance_mode(true);
       
   852 
       
   853 		$results = array();
       
   854 
       
   855 		$this->update_count = count($themes);
       
   856 		$this->update_current = 0;
       
   857 		foreach ( $themes as $theme ) {
       
   858 			$this->update_current++;
       
   859 
       
   860 			if ( !isset( $current->response[ $theme ] ) ) {
       
   861 				$this->skin->set_result(false);
       
   862 				$this->skin->before();
       
   863 				$this->skin->error('up_to_date');
       
   864 				$this->skin->after();
       
   865 				$results[$theme] = false;
       
   866 				continue;
       
   867 			}
       
   868 
       
   869 			$this->skin->theme_info = $this->theme_info($theme);
       
   870 
       
   871 			// Get the URL to the zip file
       
   872 			$r = $current->response[ $theme ];
       
   873 
       
   874 			$options = array(
       
   875 							'package' => $r['package'],
       
   876 							'destination' => WP_CONTENT_DIR . '/themes',
       
   877 							'clear_destination' => true,
       
   878 							'clear_working' => true,
       
   879 							'hook_extra' => array(
       
   880 												'theme' => $theme
       
   881 												)
       
   882 							);
       
   883 
       
   884 			$result = $this->run($options);
       
   885 
       
   886 			$results[$theme] = $this->result;
       
   887 
       
   888 			// Prevent credentials auth screen from displaying multiple times
       
   889 			if ( false === $result )
       
   890 				break;
       
   891 		} //end foreach $plugins
       
   892 
       
   893 		$this->maintenance_mode(false);
       
   894 
       
   895 		$this->skin->bulk_footer();
       
   896 
       
   897 		$this->skin->footer();
       
   898 
       
   899 		// Cleanup our hooks, in case something else does a upgrade on this connection.
       
   900 		remove_filter('upgrader_pre_install', array(&$this, 'current_before'), 10, 2);
       
   901 		remove_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);
       
   902 		remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);
       
   903 
       
   904 		// Force refresh of theme update information
       
   905 		delete_site_transient('update_themes');
       
   906 		search_theme_directories( true );
       
   907 		foreach ( wp_get_themes() as $theme )
       
   908 			$theme->cache_delete();
       
   909 
       
   910 		return $results;
       
   911 	}
       
   912 
       
   913 	function check_package($source) {
       
   914 		global $wp_filesystem;
       
   915 
       
   916 		if ( is_wp_error($source) )
       
   917 			return $source;
       
   918 
       
   919 		// Check the folder contains a valid theme
       
   920 		$working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit(WP_CONTENT_DIR), $source);
       
   921 		if ( ! is_dir($working_directory) ) // Sanity check, if the above fails, lets not prevent installation.
       
   922 			return $source;
       
   923 
       
   924 		// A proper archive should have a style.css file in the single subdirectory
       
   925 		if ( ! file_exists( $working_directory . 'style.css' ) )
       
   926 			return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], __('The theme is missing the <code>style.css</code> stylesheet.') );
       
   927 
       
   928 		$info = get_file_data( $working_directory . 'style.css', array( 'Name' => 'Theme Name', 'Template' => 'Template' ) );
       
   929 
       
   930 		if ( empty( $info['Name'] ) )
       
   931 			return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], __("The <code>style.css</code> stylesheet doesn't contain a valid theme header.") );
       
   932 
       
   933 		// If it's not a child theme, it must have at least an index.php to be legit.
       
   934 		if ( empty( $info['Template'] ) && ! file_exists( $working_directory . 'index.php' ) )
       
   935 			return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], __('The theme is missing the <code>index.php</code> file.') );
       
   936 
       
   937 		return $source;
   677 	}
   938 	}
   678 
   939 
   679 	function current_before($return, $theme) {
   940 	function current_before($return, $theme) {
   680 
   941 
   681 		if ( is_wp_error($return) )
   942 		if ( is_wp_error($return) )
   683 
   944 
   684 		$theme = isset($theme['theme']) ? $theme['theme'] : '';
   945 		$theme = isset($theme['theme']) ? $theme['theme'] : '';
   685 
   946 
   686 		if ( $theme != get_stylesheet() ) //If not current
   947 		if ( $theme != get_stylesheet() ) //If not current
   687 			return $return;
   948 			return $return;
   688 		//Change to maintainence mode now.
   949 		//Change to maintenance mode now.
   689 		$this->maintenance_mode(true);
   950 		if ( ! $this->bulk )
       
   951 			$this->maintenance_mode(true);
   690 
   952 
   691 		return $return;
   953 		return $return;
   692 	}
   954 	}
       
   955 
   693 	function current_after($return, $theme) {
   956 	function current_after($return, $theme) {
   694 		if ( is_wp_error($return) )
   957 		if ( is_wp_error($return) )
   695 			return $return;
   958 			return $return;
   696 
   959 
   697 		$theme = isset($theme['theme']) ? $theme['theme'] : '';
   960 		$theme = isset($theme['theme']) ? $theme['theme'] : '';
   698 
   961 
   699 		if ( $theme != get_stylesheet() ) //If not current
   962 		if ( $theme != get_stylesheet() ) // If not current
   700 			return $return;
   963 			return $return;
   701 
   964 
   702 		//Ensure stylesheet name hasnt changed after the upgrade:
   965 		// Ensure stylesheet name hasnt changed after the upgrade:
       
   966 		// @TODO: Note, This doesn't handle the Template changing, or the Template name changing.
   703 		if ( $theme == get_stylesheet() && $theme != $this->result['destination_name'] ) {
   967 		if ( $theme == get_stylesheet() && $theme != $this->result['destination_name'] ) {
   704 			$theme_info = $this->theme_info();
   968 			$theme_info = $this->theme_info();
   705 			$stylesheet = $this->result['destination_name'];
   969 			$stylesheet = $this->result['destination_name'];
   706 			$template = !empty($theme_info['Template']) ? $theme_info['Template'] : $stylesheet;
   970 			$template = $theme_info->get_template();
   707 			switch_theme($template, $stylesheet, true);
   971 			switch_theme($template, $stylesheet, true);
   708 		}
   972 		}
   709 
   973 
   710 		//Time to remove maintainence mode
   974 		//Time to remove maintenance mode
   711 		$this->maintenance_mode(false);
   975 		if ( ! $this->bulk )
       
   976 			$this->maintenance_mode(false);
   712 		return $return;
   977 		return $return;
   713 	}
   978 	}
   714 
   979 
   715 	function delete_old_theme($removed, $local_destination, $remote_destination, $theme) {
   980 	function delete_old_theme($removed, $local_destination, $remote_destination, $theme) {
   716 		global $wp_filesystem;
   981 		global $wp_filesystem;
   725 			if ( ! $wp_filesystem->delete( trailingslashit($themes_dir) . $theme, true ) )
   990 			if ( ! $wp_filesystem->delete( trailingslashit($themes_dir) . $theme, true ) )
   726 				return false;
   991 				return false;
   727 		return true;
   992 		return true;
   728 	}
   993 	}
   729 
   994 
   730 	function theme_info() {
   995 	function theme_info($theme = null) {
   731 		if ( empty($this->result['destination_name']) )
   996 
   732 			return false;
   997 		if ( empty($theme) ) {
   733 		return get_theme_data(WP_CONTENT_DIR . '/themes/' . $this->result['destination_name'] . '/style.css');
   998 			if ( !empty($this->result['destination_name']) )
       
   999 				$theme = $this->result['destination_name'];
       
  1000 			else
       
  1001 				return false;
       
  1002 		}
       
  1003 		return wp_get_theme( $theme, WP_CONTENT_DIR . '/themes/' );
   734 	}
  1004 	}
   735 
  1005 
   736 }
  1006 }
   737 
  1007 
   738 /**
  1008 /**
   739  * Core Upgrader class for WordPress. It allows for WordPress to upgrade itself in combiantion with the wp-admin/includes/update-core.php file
  1009  * Core Upgrader class for WordPress. It allows for WordPress to upgrade itself in combination with the wp-admin/includes/update-core.php file
   740  *
  1010  *
   741  * @TODO More Detailed docs, for methods as well.
  1011  * @TODO More Detailed docs, for methods as well.
   742  *
  1012  *
   743  * @package WordPress
  1013  * @package WordPress
   744  * @subpackage Upgrader
  1014  * @subpackage Upgrader
   746  */
  1016  */
   747 class Core_Upgrader extends WP_Upgrader {
  1017 class Core_Upgrader extends WP_Upgrader {
   748 
  1018 
   749 	function upgrade_strings() {
  1019 	function upgrade_strings() {
   750 		$this->strings['up_to_date'] = __('WordPress is at the latest version.');
  1020 		$this->strings['up_to_date'] = __('WordPress is at the latest version.');
   751 		$this->strings['no_package'] = __('Upgrade package not available.');
  1021 		$this->strings['no_package'] = __('Update package not available.');
   752 		$this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>.');
  1022 		$this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>&#8230;');
   753 		$this->strings['unpack_package'] = __('Unpacking the update.');
  1023 		$this->strings['unpack_package'] = __('Unpacking the update&#8230;');
   754 		$this->strings['copy_failed'] = __('Could not copy files.');
  1024 		$this->strings['copy_failed'] = __('Could not copy files.');
       
  1025 		$this->strings['copy_failed_space'] = __('Could not copy files. You may have run out of disk space.' );
   755 	}
  1026 	}
   756 
  1027 
   757 	function upgrade($current) {
  1028 	function upgrade($current) {
   758 		global $wp_filesystem;
  1029 		global $wp_filesystem, $wp_version;
   759 
  1030 
   760 		$this->init();
  1031 		$this->init();
   761 		$this->upgrade_strings();
  1032 		$this->upgrade_strings();
   762 
  1033 
   763 		if ( !empty($feedback) )
  1034 		if ( !empty($feedback) )
   771 		if ( is_wp_error($res) )
  1042 		if ( is_wp_error($res) )
   772 			return $res;
  1043 			return $res;
   773 
  1044 
   774 		$wp_dir = trailingslashit($wp_filesystem->abspath());
  1045 		$wp_dir = trailingslashit($wp_filesystem->abspath());
   775 
  1046 
   776 		$download = $this->download_package( $current->package );
  1047 		// If partial update is returned from the API, use that, unless we're doing a reinstall.
       
  1048 		// If we cross the new_bundled version number, then use the new_bundled zip.
       
  1049 		// Don't though if the constant is set to skip bundled items.
       
  1050 		// If the API returns a no_content zip, go with it. Finally, default to the full zip.
       
  1051 		if ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version )
       
  1052 			$to_download = 'partial';
       
  1053 		elseif ( $current->packages->new_bundled && version_compare( $wp_version, $current->new_bundled, '<' )
       
  1054 			&& ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) )
       
  1055 			$to_download = 'new_bundled';
       
  1056 		elseif ( $current->packages->no_content )
       
  1057 			$to_download = 'no_content';
       
  1058 		else
       
  1059 			$to_download = 'full';
       
  1060 
       
  1061 		$download = $this->download_package( $current->packages->$to_download );
   777 		if ( is_wp_error($download) )
  1062 		if ( is_wp_error($download) )
   778 			return $download;
  1063 			return $download;
   779 
  1064 
   780 		$working_dir = $this->unpack_package( $download );
  1065 		$working_dir = $this->unpack_package( $download );
   781 		if ( is_wp_error($working_dir) )
  1066 		if ( is_wp_error($working_dir) )
   787 			return new WP_Error('copy_failed', $this->strings['copy_failed']);
  1072 			return new WP_Error('copy_failed', $this->strings['copy_failed']);
   788 		}
  1073 		}
   789 		$wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
  1074 		$wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
   790 
  1075 
   791 		require(ABSPATH . 'wp-admin/includes/update-core.php');
  1076 		require(ABSPATH . 'wp-admin/includes/update-core.php');
       
  1077 
       
  1078 		if ( ! function_exists( 'update_core' ) )
       
  1079 			return new WP_Error( 'copy_failed_space', $this->strings['copy_failed_space'] );
   792 
  1080 
   793 		return update_core($working_dir, $wp_dir);
  1081 		return update_core($working_dir, $wp_dir);
   794 	}
  1082 	}
   795 
  1083 
   796 }
  1084 }
   806  */
  1094  */
   807 class WP_Upgrader_Skin {
  1095 class WP_Upgrader_Skin {
   808 
  1096 
   809 	var $upgrader;
  1097 	var $upgrader;
   810 	var $done_header = false;
  1098 	var $done_header = false;
   811 
  1099 	var $result = false;
   812 	function WP_Upgrader_Skin($args = array()) {
  1100 
   813 		return $this->__construct($args);
       
   814 	}
       
   815 	function __construct($args = array()) {
  1101 	function __construct($args = array()) {
   816 		$defaults = array( 'url' => '', 'nonce' => '', 'title' => '', 'context' => false );
  1102 		$defaults = array( 'url' => '', 'nonce' => '', 'title' => '', 'context' => false );
   817 		$this->options = wp_parse_args($args, $defaults);
  1103 		$this->options = wp_parse_args($args, $defaults);
   818 	}
  1104 	}
   819 
  1105 
   820 	function set_upgrader(&$upgrader) {
  1106 	function set_upgrader(&$upgrader) {
   821 		if ( is_object($upgrader) )
  1107 		if ( is_object($upgrader) )
   822 			$this->upgrader =& $upgrader;
  1108 			$this->upgrader =& $upgrader;
   823 	}
  1109 		$this->add_strings();
       
  1110 	}
       
  1111 
       
  1112 	function add_strings() {
       
  1113 	}
       
  1114 
   824 	function set_result($result) {
  1115 	function set_result($result) {
   825 		$this->result = $result;
  1116 		$this->result = $result;
   826 	}
  1117 	}
   827 
  1118 
   828 	function request_filesystem_credentials($error = false) {
  1119 	function request_filesystem_credentials($error = false) {
   889  * @since 2.8.0
  1180  * @since 2.8.0
   890  */
  1181  */
   891 class Plugin_Upgrader_Skin extends WP_Upgrader_Skin {
  1182 class Plugin_Upgrader_Skin extends WP_Upgrader_Skin {
   892 	var $plugin = '';
  1183 	var $plugin = '';
   893 	var $plugin_active = false;
  1184 	var $plugin_active = false;
   894 
  1185 	var $plugin_network_active = false;
   895 	function Plugin_Upgrader_Skin($args = array()) {
       
   896 		return $this->__construct($args);
       
   897 	}
       
   898 
  1186 
   899 	function __construct($args = array()) {
  1187 	function __construct($args = array()) {
   900 		$defaults = array( 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => __('Upgrade Plugin') );
  1188 		$defaults = array( 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => __('Update Plugin') );
   901 		$args = wp_parse_args($args, $defaults);
  1189 		$args = wp_parse_args($args, $defaults);
   902 
  1190 
   903 		$this->plugin = $args['plugin'];
  1191 		$this->plugin = $args['plugin'];
   904 
  1192 
   905 		$this->plugin_active = is_plugin_active($this->plugin);
  1193 		$this->plugin_active = is_plugin_active( $this->plugin );
       
  1194 		$this->plugin_network_active = is_plugin_active_for_network( $this->plugin );
   906 
  1195 
   907 		parent::__construct($args);
  1196 		parent::__construct($args);
   908 	}
  1197 	}
   909 
  1198 
   910 	function after() {
  1199 	function after() {
   911 		if ( $this->upgrader->bulk )
       
   912 			return;
       
   913 
       
   914 		$this->plugin = $this->upgrader->plugin_info();
  1200 		$this->plugin = $this->upgrader->plugin_info();
   915 		if( !empty($this->plugin) && !is_wp_error($this->result) && $this->plugin_active ){
  1201 		if ( !empty($this->plugin) && !is_wp_error($this->result) && $this->plugin_active ){
   916 			show_message(__('Attempting reactivation of the plugin'));
  1202 			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>';
   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 		}
  1203 		}
   919 
  1204 
   920 		$update_actions =  array(
  1205 		$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>',
  1206 			'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>'
  1207 			'plugins_page' => '<a href="' . self_admin_url('plugins.php') . '" title="' . esc_attr__('Go to plugins page') . '" target="_parent">' . __('Return to Plugins page') . '</a>'
   923 		);
  1208 		);
   924 		if ( $this->plugin_active )
  1209 		if ( $this->plugin_active )
   925 			unset( $update_actions['activate_plugin'] );
  1210 			unset( $update_actions['activate_plugin'] );
   926 		if ( ! $this->result || is_wp_error($this->result) )
  1211 		if ( ! $this->result || is_wp_error($this->result) )
   927 			unset( $update_actions['activate_plugin'] );
  1212 			unset( $update_actions['activate_plugin'] );
   928 
  1213 
   929 		$update_actions = apply_filters('update_plugin_complete_actions', $update_actions, $this->plugin);
  1214 		$update_actions = apply_filters('update_plugin_complete_actions', $update_actions, $this->plugin);
   930 		if ( ! empty($update_actions) )
  1215 		if ( ! empty($update_actions) )
   931 			$this->feedback('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$update_actions));
  1216 			$this->feedback(implode(' | ', (array)$update_actions));
   932 	}
  1217 	}
   933 
  1218 
   934 	function before() {
  1219 	function before() {
   935 		if ( $this->upgrader->show_before ) {
  1220 		if ( $this->upgrader->show_before ) {
   936 			echo $this->upgrader->show_before;
  1221 			echo $this->upgrader->show_before;
   937 			$this->upgrader->show_before = '';
  1222 			$this->upgrader->show_before = '';
   938 		}
  1223 		}
       
  1224 	}
       
  1225 }
       
  1226 
       
  1227 /**
       
  1228  * Plugin Upgrader Skin for WordPress Plugin Upgrades.
       
  1229  *
       
  1230  * @package WordPress
       
  1231  * @subpackage Upgrader
       
  1232  * @since 3.0.0
       
  1233  */
       
  1234 class Bulk_Upgrader_Skin extends WP_Upgrader_Skin {
       
  1235 	var $in_loop = false;
       
  1236 	var $error = false;
       
  1237 
       
  1238 	function __construct($args = array()) {
       
  1239 		$defaults = array( 'url' => '', 'nonce' => '' );
       
  1240 		$args = wp_parse_args($args, $defaults);
       
  1241 
       
  1242 		parent::__construct($args);
       
  1243 	}
       
  1244 
       
  1245 	function add_strings() {
       
  1246 		$this->upgrader->strings['skin_upgrade_start'] = __('The update process is starting. This process may take a while on some hosts, so please be patient.');
       
  1247 		$this->upgrader->strings['skin_update_failed_error'] = __('An error occurred while updating %1$s: <strong>%2$s</strong>.');
       
  1248 		$this->upgrader->strings['skin_update_failed'] = __('The update of %1$s failed.');
       
  1249 		$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>';
       
  1250 		$this->upgrader->strings['skin_upgrade_end'] = __('All updates have been completed.');
       
  1251 	}
       
  1252 
       
  1253 	function feedback($string) {
       
  1254 		if ( isset( $this->upgrader->strings[$string] ) )
       
  1255 			$string = $this->upgrader->strings[$string];
       
  1256 
       
  1257 		if ( strpos($string, '%') !== false ) {
       
  1258 			$args = func_get_args();
       
  1259 			$args = array_splice($args, 1);
       
  1260 			if ( !empty($args) )
       
  1261 				$string = vsprintf($string, $args);
       
  1262 		}
       
  1263 		if ( empty($string) )
       
  1264 			return;
       
  1265 		if ( $this->in_loop )
       
  1266 			echo "$string<br />\n";
       
  1267 		else
       
  1268 			echo "<p>$string</p>\n";
       
  1269 	}
       
  1270 
       
  1271 	function header() {
       
  1272 		// Nothing, This will be displayed within a iframe.
       
  1273 	}
       
  1274 
       
  1275 	function footer() {
       
  1276 		// Nothing, This will be displayed within a iframe.
       
  1277 	}
       
  1278 	function error($error) {
       
  1279 		if ( is_string($error) && isset( $this->upgrader->strings[$error] ) )
       
  1280 			$this->error = $this->upgrader->strings[$error];
       
  1281 
       
  1282 		if ( is_wp_error($error) ) {
       
  1283 			foreach ( $error->get_error_messages() as $emessage ) {
       
  1284 				if ( $error->get_error_data() )
       
  1285 					$messages[] = $emessage . ' ' . $error->get_error_data();
       
  1286 				else
       
  1287 					$messages[] = $emessage;
       
  1288 			}
       
  1289 			$this->error = implode(', ', $messages);
       
  1290 		}
       
  1291 		echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js($this->upgrader->update_current) . '\').hide();</script>';
       
  1292 	}
       
  1293 
       
  1294 	function bulk_header() {
       
  1295 		$this->feedback('skin_upgrade_start');
       
  1296 	}
       
  1297 
       
  1298 	function bulk_footer() {
       
  1299 		$this->feedback('skin_upgrade_end');
       
  1300 	}
       
  1301 
       
  1302 	function before($title = '') {
       
  1303 		$this->in_loop = true;
       
  1304 		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);
       
  1305 		echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js($this->upgrader->update_current) . '\').show();</script>';
       
  1306 		echo '<div class="update-messages hide-if-js" id="progress-' . esc_attr($this->upgrader->update_current) . '"><p>';
       
  1307 		$this->flush_output();
       
  1308 	}
       
  1309 
       
  1310 	function after($title = '') {
       
  1311 		echo '</p></div>';
       
  1312 		if ( $this->error || ! $this->result ) {
       
  1313 			if ( $this->error )
       
  1314 				echo '<div class="error"><p>' . sprintf($this->upgrader->strings['skin_update_failed_error'], $title, $this->error) . '</p></div>';
       
  1315 			else
       
  1316 				echo '<div class="error"><p>' . sprintf($this->upgrader->strings['skin_update_failed'], $title) . '</p></div>';
       
  1317 
       
  1318 			echo '<script type="text/javascript">jQuery(\'#progress-' . esc_js($this->upgrader->update_current) . '\').show();</script>';
       
  1319 		}
       
  1320 		if ( !empty($this->result) && !is_wp_error($this->result) ) {
       
  1321 			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>';
       
  1322 			echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js($this->upgrader->update_current) . '\').hide();</script>';
       
  1323 		}
       
  1324 
       
  1325 		$this->reset();
       
  1326 		$this->flush_output();
       
  1327 	}
       
  1328 
       
  1329 	function reset() {
       
  1330 		$this->in_loop = false;
       
  1331 		$this->error = false;
       
  1332 	}
       
  1333 
       
  1334 	function flush_output() {
       
  1335 		wp_ob_end_flush_all();
       
  1336 		flush();
       
  1337 	}
       
  1338 }
       
  1339 
       
  1340 class Bulk_Plugin_Upgrader_Skin extends Bulk_Upgrader_Skin {
       
  1341 	var $plugin_info = array(); // Plugin_Upgrader::bulk() will fill this in.
       
  1342 
       
  1343 	function __construct($args = array()) {
       
  1344 		parent::__construct($args);
       
  1345 	}
       
  1346 
       
  1347 	function add_strings() {
       
  1348 		parent::add_strings();
       
  1349 		$this->upgrader->strings['skin_before_update_header'] = __('Updating Plugin %1$s (%2$d/%3$d)');
       
  1350 	}
       
  1351 
       
  1352 	function before() {
       
  1353 		parent::before($this->plugin_info['Title']);
       
  1354 	}
       
  1355 
       
  1356 	function after() {
       
  1357 		parent::after($this->plugin_info['Title']);
       
  1358 	}
       
  1359 	function bulk_footer() {
       
  1360 		parent::bulk_footer();
       
  1361 		$update_actions =  array(
       
  1362 			'plugins_page' => '<a href="' . self_admin_url('plugins.php') . '" title="' . esc_attr__('Go to plugins page') . '" target="_parent">' . __('Return to Plugins page') . '</a>',
       
  1363 			'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>'
       
  1364 		);
       
  1365 
       
  1366 		$update_actions = apply_filters('update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info);
       
  1367 		if ( ! empty($update_actions) )
       
  1368 			$this->feedback(implode(' | ', (array)$update_actions));
       
  1369 	}
       
  1370 }
       
  1371 
       
  1372 class Bulk_Theme_Upgrader_Skin extends Bulk_Upgrader_Skin {
       
  1373 	var $theme_info = array(); // Theme_Upgrader::bulk() will fill this in.
       
  1374 
       
  1375 	function __construct($args = array()) {
       
  1376 		parent::__construct($args);
       
  1377 	}
       
  1378 
       
  1379 	function add_strings() {
       
  1380 		parent::add_strings();
       
  1381 		$this->upgrader->strings['skin_before_update_header'] = __('Updating Theme %1$s (%2$d/%3$d)');
       
  1382 	}
       
  1383 
       
  1384 	function before() {
       
  1385 		parent::before( $this->theme_info->display('Name') );
       
  1386 	}
       
  1387 
       
  1388 	function after() {
       
  1389 		parent::after( $this->theme_info->display('Name') );
       
  1390 	}
       
  1391 
       
  1392 	function bulk_footer() {
       
  1393 		parent::bulk_footer();
       
  1394 		$update_actions =  array(
       
  1395 			'themes_page' => '<a href="' . self_admin_url('themes.php') . '" title="' . esc_attr__('Go to themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>',
       
  1396 			'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>'
       
  1397 		);
       
  1398 
       
  1399 		$update_actions = apply_filters('update_bulk_theme_complete_actions', $update_actions, $this->theme_info );
       
  1400 		if ( ! empty($update_actions) )
       
  1401 			$this->feedback(implode(' | ', (array)$update_actions));
   939 	}
  1402 	}
   940 }
  1403 }
   941 
  1404 
   942 /**
  1405 /**
   943  * Plugin Installer Skin for WordPress Plugin Installer.
  1406  * Plugin Installer Skin for WordPress Plugin Installer.
   950  */
  1413  */
   951 class Plugin_Installer_Skin extends WP_Upgrader_Skin {
  1414 class Plugin_Installer_Skin extends WP_Upgrader_Skin {
   952 	var $api;
  1415 	var $api;
   953 	var $type;
  1416 	var $type;
   954 
  1417 
   955 	function Plugin_Installer_Skin($args = array()) {
       
   956 		return $this->__construct($args);
       
   957 	}
       
   958 
       
   959 	function __construct($args = array()) {
  1418 	function __construct($args = array()) {
   960 		$defaults = array( 'type' => 'web', 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => '' );
  1419 		$defaults = array( 'type' => 'web', 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => '' );
   961 		$args = wp_parse_args($args, $defaults);
  1420 		$args = wp_parse_args($args, $defaults);
   962 
  1421 
   963 		$this->type = $args['type'];
  1422 		$this->type = $args['type'];
   973 
  1432 
   974 	function after() {
  1433 	function after() {
   975 
  1434 
   976 		$plugin_file = $this->upgrader->plugin_info();
  1435 		$plugin_file = $this->upgrader->plugin_info();
   977 
  1436 
   978 		$install_actions = array(
  1437 		$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>',
  1438 
   980 							);
  1439 		$from = isset($_GET['from']) ? stripslashes($_GET['from']) : 'plugins';
   981 
  1440 
   982 		if ( $this->type == 'web' )
  1441 		if ( 'import' == $from )
   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>';
  1442 			$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>';
   984 		else
  1443 		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>';
  1444 			$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>';
   986 
  1445 
   987 
  1446 		if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
   988 		if ( ! $this->result || is_wp_error($this->result) )
  1447 			$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>';
   989 			unset( $install_actions['activate_plugin'] );
  1448 			unset( $install_actions['activate_plugin'] );
   990 
  1449 		}
       
  1450 
       
  1451 		if ( 'import' == $from )
       
  1452 			$install_actions['importers_page'] = '<a href="' . admin_url('import.php') . '" title="' . esc_attr__('Return to Importers') . '" target="_parent">' . __('Return to Importers') . '</a>';
       
  1453 		else if ( $this->type == 'web' )
       
  1454 			$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>';
       
  1455 		else
       
  1456 			$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>';
       
  1457 
       
  1458 		if ( ! $this->result || is_wp_error($this->result) ) {
       
  1459 			unset( $install_actions['activate_plugin'] );
       
  1460 			unset( $install_actions['network_activate'] );
       
  1461 		}
   991 		$install_actions = apply_filters('install_plugin_complete_actions', $install_actions, $this->api, $plugin_file);
  1462 		$install_actions = apply_filters('install_plugin_complete_actions', $install_actions, $this->api, $plugin_file);
   992 		if ( ! empty($install_actions) )
  1463 		if ( ! empty($install_actions) )
   993 			$this->feedback('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$install_actions));
  1464 			$this->feedback(implode(' | ', (array)$install_actions));
   994 	}
  1465 	}
   995 }
  1466 }
   996 
  1467 
   997 /**
  1468 /**
   998  * Theme Installer Skin for the WordPress Theme Installer.
  1469  * Theme Installer Skin for the WordPress Theme Installer.
  1005  */
  1476  */
  1006 class Theme_Installer_Skin extends WP_Upgrader_Skin {
  1477 class Theme_Installer_Skin extends WP_Upgrader_Skin {
  1007 	var $api;
  1478 	var $api;
  1008 	var $type;
  1479 	var $type;
  1009 
  1480 
  1010 	function Theme_Installer_Skin($args = array()) {
       
  1011 		return $this->__construct($args);
       
  1012 	}
       
  1013 
       
  1014 	function __construct($args = array()) {
  1481 	function __construct($args = array()) {
  1015 		$defaults = array( 'type' => 'web', 'url' => '', 'theme' => '', 'nonce' => '', 'title' => '' );
  1482 		$defaults = array( 'type' => 'web', 'url' => '', 'theme' => '', 'nonce' => '', 'title' => '' );
  1016 		$args = wp_parse_args($args, $defaults);
  1483 		$args = wp_parse_args($args, $defaults);
  1017 
  1484 
  1018 		$this->type = $args['type'];
  1485 		$this->type = $args['type'];
  1020 
  1487 
  1021 		parent::__construct($args);
  1488 		parent::__construct($args);
  1022 	}
  1489 	}
  1023 
  1490 
  1024 	function before() {
  1491 	function before() {
  1025 		if ( !empty($this->api) ) {
  1492 		if ( !empty($this->api) )
  1026 			/* translators: 1: theme name, 2: version */
  1493 			$this->upgrader->strings['process_success'] = sprintf( $this->upgrader->strings['process_success_specific'], $this->api->name, $this->api->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 	}
  1494 	}
  1030 
  1495 
  1031 	function after() {
  1496 	function after() {
  1032 		if ( empty($this->upgrader->result['destination_name']) )
  1497 		if ( empty($this->upgrader->result['destination_name']) )
  1033 			return;
  1498 			return;
  1034 
  1499 
  1035 		$theme_info = $this->upgrader->theme_info();
  1500 		$theme_info = $this->upgrader->theme_info();
  1036 		if ( empty($theme_info) )
  1501 		if ( empty( $theme_info ) )
  1037 			return;
  1502 			return;
  1038 		$name = $theme_info['Name'];
  1503 
       
  1504 		$name       = $theme_info->display('Name');
  1039 		$stylesheet = $this->upgrader->result['destination_name'];
  1505 		$stylesheet = $this->upgrader->result['destination_name'];
  1040 		$template = !empty($theme_info['Template']) ? $theme_info['Template'] : $stylesheet;
  1506 		$template   = $theme_info->get_template();
  1041 
  1507 
  1042 		$preview_link = htmlspecialchars( add_query_arg( array('preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'TB_iframe' => 'true' ), trailingslashit(esc_url(get_option('home'))) ) );
  1508 		$preview_link = add_query_arg( array(
  1043 		$activate_link = wp_nonce_url("themes.php?action=activate&amp;template=" . urlencode($template) . "&amp;stylesheet=" . urlencode($stylesheet), 'switch-theme_' . $template);
  1509 			'preview'    => 1,
  1044 
  1510 			'template'   => urlencode( $template ),
  1045 		$install_actions = array(
  1511 			'stylesheet' => urlencode( $stylesheet ),
  1046 			'preview' => '<a href="' . $preview_link . '" class="thickbox thickbox-preview" title="' . esc_attr(sprintf(__('Preview &#8220;%s&#8221;'), $name)) . '">' . __('Preview') . '</a>',
  1512 		), trailingslashit( get_home_url() ) );
  1047 			'activate' => '<a href="' . $activate_link .  '" class="activatelink" title="' . esc_attr( sprintf( __('Activate &#8220;%s&#8221;'), $name ) ) . '">' . __('Activate') . '</a>'
  1513 
  1048 							);
  1514 		$activate_link = add_query_arg( array(
       
  1515 			'action'     => 'activate',
       
  1516 			'template'   => urlencode( $template ),
       
  1517 			'stylesheet' => urlencode( $stylesheet ),
       
  1518 		), admin_url('themes.php') );
       
  1519 		$activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );
       
  1520 
       
  1521 		$install_actions = array();
       
  1522 		$install_actions['preview']  = '<a href="' . esc_url( $preview_link ) . '" class="hide-if-customize" title="' . esc_attr( sprintf( __('Preview &#8220;%s&#8221;'), $name ) ) . '">' . __('Preview') . '</a>';
       
  1523 		$install_actions['preview'] .= '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize" title="' . esc_attr( sprintf( __('Preview &#8220;%s&#8221;'), $name ) ) . '">' . __('Live Preview') . '</a>';
       
  1524 		$install_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink" title="' . esc_attr( sprintf( __('Activate &#8220;%s&#8221;'), $name ) ) . '">' . __('Activate') . '</a>';
       
  1525 
       
  1526 		if ( is_network_admin() && current_user_can( 'manage_network_themes' ) )
       
  1527 			$install_actions['network_enable'] = '<a href="' . esc_url( wp_nonce_url( 'themes.php?action=enable&amp;theme=' . $stylesheet, 'enable-theme_' . $stylesheet ) ) . '" title="' . esc_attr__( 'Enable this theme for all sites in this network' ) . '" target="_parent">' . __( 'Network Enable' ) . '</a>';
  1049 
  1528 
  1050 		if ( $this->type == 'web' )
  1529 		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>';
  1530 			$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>';
  1052 		else
  1531 		else
  1053 			$install_actions['themes_page'] = '<a href="' . admin_url('themes.php') . '" title="' . esc_attr__('Themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>';
  1532 			$install_actions['themes_page'] = '<a href="' . self_admin_url('themes.php') . '" title="' . esc_attr__('Themes page') . '" target="_parent">' . __('Return to Themes page') . '</a>';
  1054 
  1533 
  1055 		if ( ! $this->result || is_wp_error($this->result) )
  1534 		if ( ! $this->result || is_wp_error($this->result) || is_network_admin() )
  1056 			unset( $install_actions['activate'], $install_actions['preview'] );
  1535 			unset( $install_actions['activate'], $install_actions['preview'] );
  1057 
  1536 
  1058 		$install_actions = apply_filters('install_theme_complete_actions', $install_actions, $this->api, $stylesheet, $theme_info);
  1537 		$install_actions = apply_filters('install_theme_complete_actions', $install_actions, $this->api, $stylesheet, $theme_info);
  1059 		if ( ! empty($install_actions) )
  1538 		if ( ! empty($install_actions) )
  1060 			$this->feedback('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$install_actions));
  1539 			$this->feedback(implode(' | ', (array)$install_actions));
  1061 	}
  1540 	}
  1062 }
  1541 }
  1063 
  1542 
  1064 /**
  1543 /**
  1065  * Theme Upgrader Skin for WordPress Theme Upgrades.
  1544  * Theme Upgrader Skin for WordPress Theme Upgrades.
  1071  * @since 2.8.0
  1550  * @since 2.8.0
  1072  */
  1551  */
  1073 class Theme_Upgrader_Skin extends WP_Upgrader_Skin {
  1552 class Theme_Upgrader_Skin extends WP_Upgrader_Skin {
  1074 	var $theme = '';
  1553 	var $theme = '';
  1075 
  1554 
  1076 	function Theme_Upgrader_Skin($args = array()) {
       
  1077 		return $this->__construct($args);
       
  1078 	}
       
  1079 
       
  1080 	function __construct($args = array()) {
  1555 	function __construct($args = array()) {
  1081 		$defaults = array( 'url' => '', 'theme' => '', 'nonce' => '', 'title' => __('Upgrade Theme') );
  1556 		$defaults = array( 'url' => '', 'theme' => '', 'nonce' => '', 'title' => __('Update Theme') );
  1082 		$args = wp_parse_args($args, $defaults);
  1557 		$args = wp_parse_args($args, $defaults);
  1083 
  1558 
  1084 		$this->theme = $args['theme'];
  1559 		$this->theme = $args['theme'];
  1085 
  1560 
  1086 		parent::__construct($args);
  1561 		parent::__construct($args);
  1087 	}
  1562 	}
  1088 
  1563 
  1089 	function after() {
  1564 	function after() {
  1090 
  1565 
  1091 		if ( !empty($this->upgrader->result['destination_name']) &&
  1566 		$update_actions = array();
  1092 			($theme_info = $this->upgrader->theme_info()) &&
  1567 		if ( ! empty( $this->upgrader->result['destination_name'] ) && $theme_info = $this->upgrader->theme_info() ) {
  1093 			!empty($theme_info) ) {
  1568 			$name       = $theme_info->display('Name');
  1094 
       
  1095 			$name = $theme_info['Name'];
       
  1096 			$stylesheet = $this->upgrader->result['destination_name'];
  1569 			$stylesheet = $this->upgrader->result['destination_name'];
  1097 			$template = !empty($theme_info['Template']) ? $theme_info['Template'] : $stylesheet;
  1570 			$template   = $theme_info->get_template();
  1098 
  1571 
  1099 			$preview_link = htmlspecialchars( add_query_arg( array('preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'TB_iframe' => 'true' ), trailingslashit(esc_url(get_option('home'))) ) );
  1572 			$preview_link = add_query_arg( array(
  1100 			$activate_link = wp_nonce_url("themes.php?action=activate&amp;template=" . urlencode($template) . "&amp;stylesheet=" . urlencode($stylesheet), 'switch-theme_' . $template);
  1573 				'preview'    => 1,
  1101 
  1574 				'template'   => urlencode( $template ),
  1102 			$update_actions =  array(
  1575 				'stylesheet' => urlencode( $stylesheet ),
  1103 				'preview' => '<a href="' . $preview_link . '" class="thickbox thickbox-preview" title="' . esc_attr(sprintf(__('Preview &#8220;%s&#8221;'), $name)) . '">' . __('Preview') . '</a>',
  1576 			), trailingslashit( get_home_url() ) );
  1104 				'activate' => '<a href="' . $activate_link .  '" class="activatelink" title="' . esc_attr( sprintf( __('Activate &#8220;%s&#8221;'), $name ) ) . '">' . __('Activate') . '</a>',
  1577 
  1105 			);
  1578 			$activate_link = add_query_arg( array(
  1106 			if ( ( ! $this->result || is_wp_error($this->result) ) || $stylesheet == get_stylesheet() )
  1579 				'action'     => 'activate',
  1107 				unset($update_actions['preview'], $update_actions['activate']);
  1580 				'template'   => urlencode( $template ),
  1108 		}
  1581 				'stylesheet' => urlencode( $stylesheet ),
  1109 
  1582 			), admin_url('themes.php') );
  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>';
  1583 			$activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );
       
  1584 
       
  1585 			if ( get_stylesheet() == $stylesheet ) {
       
  1586 				$update_actions['preview']  = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize" title="' . esc_attr( sprintf( __('Customize &#8220;%s&#8221;'), $name ) ) . '">' . __('Customize') . '</a>';
       
  1587 			} else {
       
  1588 				$update_actions['preview']  = '<a href="' . esc_url( $preview_link ) . '" class="hide-if-customize" title="' . esc_attr( sprintf( __('Preview &#8220;%s&#8221;'), $name ) ) . '">' . __('Preview') . '</a>';
       
  1589 				$update_actions['preview'] .= '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize" title="' . esc_attr( sprintf( __('Preview &#8220;%s&#8221;'), $name ) ) . '">' . __('Live Preview') . '</a>';
       
  1590 				$update_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink" title="' . esc_attr( sprintf( __('Activate &#8220;%s&#8221;'), $name ) ) . '">' . __('Activate') . '</a>';
       
  1591 			}
       
  1592 
       
  1593 			if ( ! $this->result || is_wp_error( $this->result ) || is_network_admin() )
       
  1594 				unset( $update_actions['preview'], $update_actions['activate'] );
       
  1595 		}
       
  1596 
       
  1597 		$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>';
  1111 
  1598 
  1112 		$update_actions = apply_filters('update_theme_complete_actions', $update_actions, $this->theme);
  1599 		$update_actions = apply_filters('update_theme_complete_actions', $update_actions, $this->theme);
  1113 		if ( ! empty($update_actions) )
  1600 		if ( ! empty($update_actions) )
  1114 			$this->feedback('<strong>' . __('Actions:') . '</strong> ' . implode(' | ', (array)$update_actions));
  1601 			$this->feedback(implode(' | ', (array)$update_actions));
  1115 	}
  1602 	}
  1116 }
  1603 }
  1117 
  1604 
  1118 /**
  1605 /**
  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.
  1606  * 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.
  1125  * @since 2.8.0
  1612  * @since 2.8.0
  1126  */
  1613  */
  1127 class File_Upload_Upgrader {
  1614 class File_Upload_Upgrader {
  1128 	var $package;
  1615 	var $package;
  1129 	var $filename;
  1616 	var $filename;
  1130 
  1617 	var $id = 0;
  1131 	function File_Upload_Upgrader($form, $urlholder) {
  1618 
  1132 		return $this->__construct($form, $urlholder);
       
  1133 	}
       
  1134 	function __construct($form, $urlholder) {
  1619 	function __construct($form, $urlholder) {
  1135 		if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) )
       
  1136 			wp_die($uploads['error']);
       
  1137 
  1620 
  1138 		if ( empty($_FILES[$form]['name']) && empty($_GET[$urlholder]) )
  1621 		if ( empty($_FILES[$form]['name']) && empty($_GET[$urlholder]) )
  1139 			wp_die(__('Please select a file'));
  1622 			wp_die(__('Please select a file'));
  1140 
  1623 
  1141 		if ( !empty($_FILES) )
  1624 		//Handle a newly uploaded file, Else assume its already been uploaded
       
  1625 		if ( ! empty($_FILES) ) {
       
  1626 			$overrides = array( 'test_form' => false, 'test_type' => false );
       
  1627 			$file = wp_handle_upload( $_FILES[$form], $overrides );
       
  1628 
       
  1629 			if ( isset( $file['error'] ) )
       
  1630 				wp_die( $file['error'] );
       
  1631 
  1142 			$this->filename = $_FILES[$form]['name'];
  1632 			$this->filename = $_FILES[$form]['name'];
  1143 		else if ( isset($_GET[$urlholder]) )
  1633 			$this->package = $file['file'];
       
  1634 
       
  1635 			// Construct the object array
       
  1636 			$object = array(
       
  1637 				'post_title' => $this->filename,
       
  1638 				'post_content' => $file['url'],
       
  1639 				'post_mime_type' => $file['type'],
       
  1640 				'guid' => $file['url'],
       
  1641 				'context' => 'upgrader',
       
  1642 				'post_status' => 'private'
       
  1643 			);
       
  1644 
       
  1645 			// Save the data
       
  1646 			$this->id = wp_insert_attachment( $object, $file['file'] );
       
  1647 
       
  1648 			// schedule a cleanup for 2 hours from now in case of failed install
       
  1649 			wp_schedule_single_event( time() + 7200, 'upgrader_scheduled_cleanup', array( $this->id ) );
       
  1650 
       
  1651 		} elseif ( is_numeric( $_GET[$urlholder] ) ) {
       
  1652 			// Numeric Package = previously uploaded file, see above.
       
  1653 			$this->id = (int) $_GET[$urlholder];
       
  1654 			$attachment = get_post( $this->id );
       
  1655 			if ( empty($attachment) )
       
  1656 				wp_die(__('Please select a file'));
       
  1657 
       
  1658 			$this->filename = $attachment->post_title;
       
  1659 			$this->package = get_attached_file( $attachment->ID );
       
  1660 		} else {
       
  1661 			// Else, It's set to something, Back compat for plugins using the old (pre-3.3) File_Uploader handler.
       
  1662 			if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) )
       
  1663 				wp_die( $uploads['error'] );
       
  1664 
  1144 			$this->filename = $_GET[$urlholder];
  1665 			$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;
  1666 			$this->package = $uploads['basedir'] . '/' . $this->filename;
  1150 
  1667 		}
  1151 			// Move the file to the uploads dir
  1668 	}
  1152 			if ( false === @ move_uploaded_file( $_FILES[$form]['tmp_name'], $this->package) )
  1669 
  1153 				wp_die( sprintf( __('The uploaded file could not be moved to %s.' ), $uploads['path']));
  1670 	function cleanup() {
  1154 		} else {
  1671 		if ( $this->id )
  1155 			$this->package = $uploads['basedir'] . '/' . $this->filename;
  1672 			wp_delete_attachment( $this->id );
  1156 		}
  1673 
       
  1674 		elseif ( file_exists( $this->package ) )
       
  1675 			return @unlink( $this->package );
       
  1676 
       
  1677 		return true;
  1157 	}
  1678 	}
  1158 }
  1679 }