Core_Upgrader

Core class used for updating core.

Defined (1)

The class is defined in the following location(s).

/wp-admin/includes/class-core-upgrader.php  
  1. class Core_Upgrader extends WP_Upgrader { 
  2.  
  3. /** 
  4. * Initialize the upgrade strings. 
  5. * @since 2.8.0 
  6. * @access public 
  7. */ 
  8. public function upgrade_strings() { 
  9. $this->strings['up_to_date'] = __('WordPress is at the latest version.'); 
  10. $this->strings['locked'] = __('Another update is currently in progress.'); 
  11. $this->strings['no_package'] = __('Update package not available.'); 
  12. $this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>…'); 
  13. $this->strings['unpack_package'] = __('Unpacking the update…'); 
  14. $this->strings['copy_failed'] = __('Could not copy files.'); 
  15. $this->strings['copy_failed_space'] = __('Could not copy files. You may have run out of disk space.' ); 
  16. $this->strings['start_rollback'] = __( 'Attempting to roll back to previous version.' ); 
  17. $this->strings['rollback_was_required'] = __( 'Due to an error during updating, WordPress has rolled back to your previous version.' ); 
  18.  
  19. /** 
  20. * Upgrade WordPress core. 
  21. * @since 2.8.0 
  22. * @access public 
  23. * @global WP_Filesystem_Base $wp_filesystem Subclass 
  24. * @global callable $_wp_filesystem_direct_method 
  25. * @param object $current Response object for whether WordPress is current. 
  26. * @param array $args { 
  27. * Optional. Arguments for upgrading WordPress core. Default empty array. 
  28. * @type bool $pre_check_md5 Whether to check the file checksums before 
  29. * attempting the upgrade. Default true. 
  30. * @type bool $attempt_rollback Whether to attempt to rollback the chances if 
  31. * there is a problem. Default false. 
  32. * @type bool $do_rollback Whether to perform this "upgrade" as a rollback. 
  33. * Default false. 
  34. * } 
  35. * @return null|false|WP_Error False or WP_Error on failure, null on success. 
  36. */ 
  37. public function upgrade( $current, $args = array() ) { 
  38. global $wp_filesystem; 
  39.  
  40. include( ABSPATH . WPINC . '/version.php' ); // $wp_version; 
  41.  
  42. $start_time = time(); 
  43.  
  44. $defaults = array( 
  45. 'pre_check_md5' => true,  
  46. 'attempt_rollback' => false,  
  47. 'do_rollback' => false,  
  48. 'allow_relaxed_file_ownership' => false,  
  49. ); 
  50. $parsed_args = wp_parse_args( $args, $defaults ); 
  51.  
  52. $this->init(); 
  53. $this->upgrade_strings(); 
  54.  
  55. // Is an update available? 
  56. if ( !isset( $current->response ) || $current->response == 'latest' ) 
  57. return new WP_Error('up_to_date', $this->strings['up_to_date']); 
  58.  
  59. $res = $this->fs_connect( array( ABSPATH, WP_CONTENT_DIR ), $parsed_args['allow_relaxed_file_ownership'] ); 
  60. if ( ! $res || is_wp_error( $res ) ) { 
  61. return $res; 
  62.  
  63. $wp_dir = trailingslashit($wp_filesystem->abspath()); 
  64.  
  65. $partial = true; 
  66. if ( $parsed_args['do_rollback'] ) 
  67. $partial = false; 
  68. elseif ( $parsed_args['pre_check_md5'] && ! $this->check_files() ) 
  69. $partial = false; 
  70.  
  71. /** 
  72. * If partial update is returned from the API, use that, unless we're doing 
  73. * a reinstall. If we cross the new_bundled version number, then use 
  74. * the new_bundled zip. Don't though if the constant is set to skip bundled items. 
  75. * If the API returns a no_content zip, go with it. Finally, default to the full zip. 
  76. */ 
  77. if ( $parsed_args['do_rollback'] && $current->packages->rollback ) 
  78. $to_download = 'rollback'; 
  79. elseif ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version && $partial ) 
  80. $to_download = 'partial'; 
  81. elseif ( $current->packages->new_bundled && version_compare( $wp_version, $current->new_bundled, '<' ) 
  82. && ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) ) 
  83. $to_download = 'new_bundled'; 
  84. elseif ( $current->packages->no_content ) 
  85. $to_download = 'no_content'; 
  86. else 
  87. $to_download = 'full'; 
  88.  
  89. // Lock to prevent multiple Core Updates occurring 
  90. $lock = WP_Upgrader::create_lock( 'core_updater', 15 * MINUTE_IN_SECONDS ); 
  91. if ( ! $lock ) { 
  92. return new WP_Error( 'locked', $this->strings['locked'] ); 
  93.  
  94. $download = $this->download_package( $current->packages->$to_download ); 
  95. if ( is_wp_error( $download ) ) { 
  96. WP_Upgrader::release_lock( 'core_updater' ); 
  97. return $download; 
  98.  
  99. $working_dir = $this->unpack_package( $download ); 
  100. if ( is_wp_error( $working_dir ) ) { 
  101. WP_Upgrader::release_lock( 'core_updater' ); 
  102. return $working_dir; 
  103.  
  104. // Copy update-core.php from the new version into place. 
  105. if ( !$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true) ) { 
  106. $wp_filesystem->delete($working_dir, true); 
  107. WP_Upgrader::release_lock( 'core_updater' ); 
  108. return new WP_Error( 'copy_failed_for_update_core_file', __( 'The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.' ), 'wp-admin/includes/update-core.php' ); 
  109. $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE); 
  110.  
  111. require_once( ABSPATH . 'wp-admin/includes/update-core.php' ); 
  112.  
  113. if ( ! function_exists( 'update_core' ) ) { 
  114. WP_Upgrader::release_lock( 'core_updater' ); 
  115. return new WP_Error( 'copy_failed_space', $this->strings['copy_failed_space'] ); 
  116.  
  117. $result = update_core( $working_dir, $wp_dir ); 
  118.  
  119. // In the event of an issue, we may be able to roll back. 
  120. if ( $parsed_args['attempt_rollback'] && $current->packages->rollback && ! $parsed_args['do_rollback'] ) { 
  121. $try_rollback = false; 
  122. if ( is_wp_error( $result ) ) { 
  123. $error_code = $result->get_error_code(); 
  124. /** 
  125. * Not all errors are equal. These codes are critical: copy_failed__copy_dir,  
  126. * mkdir_failed__copy_dir, copy_failed__copy_dir_retry, and disk_full. 
  127. * do_rollback allows for update_core() to trigger a rollback if needed. 
  128. */ 
  129. if ( false !== strpos( $error_code, 'do_rollback' ) ) 
  130. $try_rollback = true; 
  131. elseif ( false !== strpos( $error_code, '__copy_dir' ) ) 
  132. $try_rollback = true; 
  133. elseif ( 'disk_full' === $error_code ) 
  134. $try_rollback = true; 
  135.  
  136. if ( $try_rollback ) { 
  137. /** This filter is documented in wp-admin/includes/update-core.php */ 
  138. apply_filters( 'update_feedback', $result ); 
  139.  
  140. /** This filter is documented in wp-admin/includes/update-core.php */ 
  141. apply_filters( 'update_feedback', $this->strings['start_rollback'] ); 
  142.  
  143. $rollback_result = $this->upgrade( $current, array_merge( $parsed_args, array( 'do_rollback' => true ) ) ); 
  144.  
  145. $original_result = $result; 
  146. $result = new WP_Error( 'rollback_was_required', $this->strings['rollback_was_required'], (object) array( 'update' => $original_result, 'rollback' => $rollback_result ) ); 
  147.  
  148. /** This action is documented in wp-admin/includes/class-wp-upgrader.php */ 
  149. do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'core' ) ); 
  150.  
  151. // Clear the current updates 
  152. delete_site_transient( 'update_core' ); 
  153.  
  154. if ( ! $parsed_args['do_rollback'] ) { 
  155. $stats = array( 
  156. 'update_type' => $current->response,  
  157. 'success' => true,  
  158. 'fs_method' => $wp_filesystem->method,  
  159. 'fs_method_forced' => defined( 'FS_METHOD' ) || has_filter( 'filesystem_method' ),  
  160. 'fs_method_direct' => !empty( $GLOBALS['_wp_filesystem_direct_method'] ) ? $GLOBALS['_wp_filesystem_direct_method'] : '',  
  161. 'time_taken' => time() - $start_time,  
  162. 'reported' => $wp_version,  
  163. 'attempted' => $current->version,  
  164. ); 
  165.  
  166. if ( is_wp_error( $result ) ) { 
  167. $stats['success'] = false; 
  168. // Did a rollback occur? 
  169. if ( ! empty( $try_rollback ) ) { 
  170. $stats['error_code'] = $original_result->get_error_code(); 
  171. $stats['error_data'] = $original_result->get_error_data(); 
  172. // Was the rollback successful? If not, collect its error too. 
  173. $stats['rollback'] = ! is_wp_error( $rollback_result ); 
  174. if ( is_wp_error( $rollback_result ) ) { 
  175. $stats['rollback_code'] = $rollback_result->get_error_code(); 
  176. $stats['rollback_data'] = $rollback_result->get_error_data(); 
  177. } else { 
  178. $stats['error_code'] = $result->get_error_code(); 
  179. $stats['error_data'] = $result->get_error_data(); 
  180.  
  181. wp_version_check( $stats ); 
  182.  
  183. WP_Upgrader::release_lock( 'core_updater' ); 
  184.  
  185. return $result; 
  186.  
  187. /** 
  188. * Determines if this WordPress Core version should update to an offered version or not. 
  189. * @since 3.7.0 
  190. * @access public 
  191. * @static 
  192. * @param string $offered_ver The offered version, of the format x.y.z. 
  193. * @return bool True if we should update to the offered version, otherwise false. 
  194. */ 
  195. public static function should_update_to_version( $offered_ver ) { 
  196. include( ABSPATH . WPINC . '/version.php' ); // $wp_version; // x.y.z 
  197.  
  198. $current_branch = implode( '.', array_slice( preg_split( '/[.-]/', $wp_version ), 0, 2 ) ); // x.y 
  199. $new_branch = implode( '.', array_slice( preg_split( '/[.-]/', $offered_ver ), 0, 2 ) ); // x.y 
  200. $current_is_development_version = (bool) strpos( $wp_version, '-' ); 
  201.  
  202. // Defaults: 
  203. $upgrade_dev = true; 
  204. $upgrade_minor = true; 
  205. $upgrade_major = false; 
  206.  
  207. // WP_AUTO_UPDATE_CORE = true (all), 'minor', false. 
  208. if ( defined( 'WP_AUTO_UPDATE_CORE' ) ) { 
  209. if ( false === WP_AUTO_UPDATE_CORE ) { 
  210. // Defaults to turned off, unless a filter allows it 
  211. $upgrade_dev = $upgrade_minor = $upgrade_major = false; 
  212. } elseif ( true === WP_AUTO_UPDATE_CORE ) { 
  213. // ALL updates for core 
  214. $upgrade_dev = $upgrade_minor = $upgrade_major = true; 
  215. } elseif ( 'minor' === WP_AUTO_UPDATE_CORE ) { 
  216. // Only minor updates for core 
  217. $upgrade_dev = $upgrade_major = false; 
  218. $upgrade_minor = true; 
  219.  
  220. // 1: If we're already on that version, not much point in updating? 
  221. if ( $offered_ver == $wp_version ) 
  222. return false; 
  223.  
  224. // 2: If we're running a newer version, that's a nope 
  225. if ( version_compare( $wp_version, $offered_ver, '>' ) ) 
  226. return false; 
  227.  
  228. $failure_data = get_site_option( 'auto_core_update_failed' ); 
  229. if ( $failure_data ) { 
  230. // If this was a critical update failure, cannot update. 
  231. if ( ! empty( $failure_data['critical'] ) ) 
  232. return false; 
  233.  
  234. // Don't claim we can update on update-core.php if we have a non-critical failure logged. 
  235. if ( $wp_version == $failure_data['current'] && false !== strpos( $offered_ver, '.1.next.minor' ) ) 
  236. return false; 
  237.  
  238. // Cannot update if we're retrying the same A to B update that caused a non-critical failure. 
  239. // Some non-critical failures do allow retries, like download_failed. 
  240. // 3.7.1 => 3.7.2 resulted in files_not_writable, if we are still on 3.7.1 and still trying to update to 3.7.2. 
  241. if ( empty( $failure_data['retry'] ) && $wp_version == $failure_data['current'] && $offered_ver == $failure_data['attempted'] ) 
  242. return false; 
  243.  
  244. // 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2 
  245. if ( $current_is_development_version ) { 
  246.  
  247. /** 
  248. * Filters whether to enable automatic core updates for development versions. 
  249. * @since 3.7.0 
  250. * @param bool $upgrade_dev Whether to enable automatic updates for 
  251. * development versions. 
  252. */ 
  253. if ( ! apply_filters( 'allow_dev_auto_core_updates', $upgrade_dev ) ) 
  254. return false; 
  255. // Else fall through to minor + major branches below. 
  256.  
  257. // 4: Minor In-branch updates (3.7.0 -> 3.7.1 -> 3.7.2 -> 3.7.4) 
  258. if ( $current_branch == $new_branch ) { 
  259.  
  260. /** 
  261. * Filters whether to enable minor automatic core updates. 
  262. * @since 3.7.0 
  263. * @param bool $upgrade_minor Whether to enable minor automatic core updates. 
  264. */ 
  265. return apply_filters( 'allow_minor_auto_core_updates', $upgrade_minor ); 
  266.  
  267. // 5: Major version updates (3.7.0 -> 3.8.0 -> 3.9.1) 
  268. if ( version_compare( $new_branch, $current_branch, '>' ) ) { 
  269.  
  270. /** 
  271. * Filters whether to enable major automatic core updates. 
  272. * @since 3.7.0 
  273. * @param bool $upgrade_major Whether to enable major automatic core updates. 
  274. */ 
  275. return apply_filters( 'allow_major_auto_core_updates', $upgrade_major ); 
  276.  
  277. // If we're not sure, we don't want it 
  278. return false; 
  279.  
  280. /** 
  281. * Compare the disk file checksums against the expected checksums. 
  282. * @since 3.7.0 
  283. * @access public 
  284. * @global string $wp_version 
  285. * @global string $wp_local_package 
  286. * @return bool True if the checksums match, otherwise false. 
  287. */ 
  288. public function check_files() { 
  289. global $wp_version, $wp_local_package; 
  290.  
  291. $checksums = get_core_checksums( $wp_version, isset( $wp_local_package ) ? $wp_local_package : 'en_US' ); 
  292.  
  293. if ( ! is_array( $checksums ) ) 
  294. return false; 
  295.  
  296. foreach ( $checksums as $file => $checksum ) { 
  297. // Skip files which get updated 
  298. if ( 'wp-content' == substr( $file, 0, 10 ) ) 
  299. continue; 
  300. if ( ! file_exists( ABSPATH . $file ) || md5_file( ABSPATH . $file ) !== $checksum ) 
  301. return false; 
  302.  
  303. return true;