/** * Update an item, if appropriate. * * @since 3.7.0 * * @param string $type The type of update being checked: 'core', 'theme', 'plugin', 'translation'. * @param object $item The update offer. */ public function update($type, $item) { $skin = new Automatic_Upgrader_Skin(); switch ($type) { case 'core': // The Core upgrader doesn't use the Upgrader's skin during the actual main part of the upgrade, instead, firing a filter. add_filter('update_feedback', array($skin, 'feedback')); $upgrader = new Core_Upgrader($skin); $context = ABSPATH; break; case 'plugin': $upgrader = new Plugin_Upgrader($skin); $context = WP_PLUGIN_DIR; // We don't support custom Plugin directories, or updates for WPMU_PLUGIN_DIR break; case 'theme': $upgrader = new Theme_Upgrader($skin); $context = get_theme_root($item->theme); break; case 'translation': $upgrader = new Language_Pack_Upgrader($skin); $context = WP_CONTENT_DIR; // WP_LANG_DIR; break; } // Determine whether we can and should perform this update. if (!$this->should_update($type, $item, $context)) { return false; } $upgrader_item = $item; switch ($type) { case 'core': $skin->feedback(__('Updating to WordPress %s'), $item->version); $item_name = sprintf(__('WordPress %s'), $item->version); break; case 'theme': $upgrader_item = $item->theme; $theme = wp_get_theme($upgrader_item); $item_name = $theme->Get('Name'); $skin->feedback(__('Updating theme: %s'), $item_name); break; case 'plugin': $upgrader_item = $item->plugin; $plugin_data = get_plugin_data($context . '/' . $upgrader_item); $item_name = $plugin_data['Name']; $skin->feedback(__('Updating plugin: %s'), $item_name); break; case 'translation': $language_item_name = $upgrader->get_name_for_update($item); $item_name = sprintf(__('Translations for %s'), $language_item_name); $skin->feedback(sprintf(__('Updating translations for %1$s (%2$s)…'), $language_item_name, $item->language)); break; } $allow_relaxed_file_ownership = false; if ('core' == $type && isset($item->new_files) && !$item->new_files) { $allow_relaxed_file_ownership = true; } // Boom, This sites about to get a whole new splash of paint! $upgrade_result = $upgrader->upgrade($upgrader_item, array('clear_update_cache' => false, 'pre_check_md5' => false, 'attempt_rollback' => true, 'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership)); // If the filesystem is unavailable, false is returned. if (false === $upgrade_result) { $upgrade_result = new WP_Error('fs_unavailable', __('Could not access filesystem.')); } // Core doesn't output this, so let's append it so we don't get confused. if ('core' == $type) { if (is_wp_error($upgrade_result)) { $skin->error(__('Installation Failed'), $upgrade_result); } else { $skin->feedback(__('WordPress updated successfully')); } } $this->update_results[$type][] = (object) array('item' => $item, 'result' => $upgrade_result, 'name' => $item_name, 'messages' => $skin->get_upgrade_messages()); return $upgrade_result; }
/** * Run an upgrade/install. * * Attempts to download the package (if it is not a local file), unpack it, and * install it in the destination folder. * * @since 2.8.0 * @access public * * @param array $options { * Array or string of arguments for upgrading/installing a package. * * @type string $package The full path or URI of the package to install. * Default empty. * @type string $destination The full path to the destination folder. * Default empty. * @type bool $clear_destination Whether to delete any files already in the * destination folder. Default false. * @type bool $clear_working Whether to delete the files form the working * directory after copying to the destination. * Default false. * @type bool $abort_if_destination_exists Whether to abort the installation if the destination * folder already exists. When true, `$clear_destination` * should be false. Default true. * @type bool $is_multi Whether this run is one of multiple upgrade/install * actions being performed in bulk. When true, the skin * WP_Upgrader::header() and WP_Upgrader::footer() * aren't called. Default false. * @type array $hook_extra Extra arguments to pass to the filter hooks called by * WP_Upgrader::run(). * } * @return array|false|WP_error The result from self::install_package() on success, otherwise a WP_Error, * or false if unable to connect to the filesystem. */ public function run($options) { $defaults = array('package' => '', 'destination' => '', 'clear_destination' => false, 'abort_if_destination_exists' => true, 'clear_working' => true, 'is_multi' => false, 'hook_extra' => array()); $options = wp_parse_args($options, $defaults); /** * Filters the package options before running an update. * * See also {@see 'upgrader_process_complete'}. * * @since 4.3.0 * * @param array $options { * Options used by the upgrader. * * @type string $package Package for update. * @type string $destination Update location. * @type bool $clear_destination Clear the destination resource. * @type bool $clear_working Clear the working resource. * @type bool $abort_if_destination_exists Abort if the Destination directory exists. * @type bool $is_multi Whether the upgrader is running multiple times. * @type array $hook_extra { * Extra hook arguments. * * @type string $action Type of action. Default 'update'. * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'. * @type bool $bulk Whether the update process is a bulk update. Default true. * @type string $plugin The base plugin path from the plugins directory. * @type string $theme The stylesheet or template name of the theme. * @type string $language_update_type The language pack update type. Accepts 'plugin', 'theme', * or 'core'. * @type object $language_update The language pack update offer. * } * } */ $options = apply_filters('upgrader_package_options', $options); if (!$options['is_multi']) { // call $this->header separately if running multiple times $this->skin->header(); } // Connect to the Filesystem first. $res = $this->fs_connect(array(WP_CONTENT_DIR, $options['destination'])); // Mainly for non-connected filesystem. if (!$res) { if (!$options['is_multi']) { $this->skin->footer(); } return false; } $this->skin->before(); if (is_wp_error($res)) { $this->skin->error($res); $this->skin->after(); if (!$options['is_multi']) { $this->skin->footer(); } return $res; } /* * Download the package (Note, This just returns the filename * of the file if the package is a local file) */ $download = $this->download_package($options['package']); if (is_wp_error($download)) { $this->skin->error($download); $this->skin->after(); if (!$options['is_multi']) { $this->skin->footer(); } return $download; } $delete_package = $download != $options['package']; // Do not delete a "local" file // Unzips the file into a temporary directory. $working_dir = $this->unpack_package($download, $delete_package); if (is_wp_error($working_dir)) { $this->skin->error($working_dir); $this->skin->after(); if (!$options['is_multi']) { $this->skin->footer(); } return $working_dir; } // With the given options, this installs it to the destination directory. $result = $this->install_package(array('source' => $working_dir, 'destination' => $options['destination'], 'clear_destination' => $options['clear_destination'], 'abort_if_destination_exists' => $options['abort_if_destination_exists'], 'clear_working' => $options['clear_working'], 'hook_extra' => $options['hook_extra'])); $this->skin->set_result($result); if (is_wp_error($result)) { $this->skin->error($result); $this->skin->feedback('process_failed'); } else { // Install succeeded. $this->skin->feedback('process_success'); } $this->skin->after(); if (!$options['is_multi']) { /** * Fires when the upgrader process is complete. * * See also {@see 'upgrader_package_options'}. * * @since 3.6.0 * @since 3.7.0 Added to WP_Upgrader::run(). * @since 4.6.0 `$translations` was added as a possible argument to `$hook_extra`. * * @param WP_Upgrader $this WP_Upgrader instance. In other contexts, $this, might be a * Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance. * @param array $hook_extra { * Array of bulk item update data. * * @type string $action Type of action. Default 'update'. * @type string $type Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'. * @type bool $bulk Whether the update process is a bulk update. Default true. * @type array $plugins Array of the basename paths of the plugins' main files. * @type array $themes The theme slugs. * @type array $translations { * Array of translations update data. * * @type string $language The locale the translation is for. * @type string $type Type of translation. Accepts 'plugin', 'theme', or 'core'. * @type string $slug Text domain the translation is for. The slug of a theme/plugin or * 'default' for core translations. * @type string $version The version of a theme, plugin, or core. * } * } */ do_action('upgrader_process_complete', $this, $options['hook_extra']); $this->skin->footer(); } return $result; }