wp/wp-admin/includes/class-theme-upgrader.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    46 	 * @see check_package()
    46 	 * @see check_package()
    47 	 */
    47 	 */
    48 	public $new_theme_data = array();
    48 	public $new_theme_data = array();
    49 
    49 
    50 	/**
    50 	/**
    51 	 * Initialize the upgrade strings.
    51 	 * Initializes the upgrade strings.
    52 	 *
    52 	 *
    53 	 * @since 2.8.0
    53 	 * @since 2.8.0
    54 	 */
    54 	 */
    55 	public function upgrade_strings() {
    55 	public function upgrade_strings() {
    56 		$this->strings['up_to_date'] = __( 'The theme is at the latest version.' );
    56 		$this->strings['up_to_date'] = __( 'The theme is at the latest version.' );
    57 		$this->strings['no_package'] = __( 'Update package not available.' );
    57 		$this->strings['no_package'] = __( 'Update package not available.' );
    58 		/* translators: %s: Package URL. */
    58 		/* translators: %s: Package URL. */
    59 		$this->strings['downloading_package'] = sprintf( __( 'Downloading update from %s&#8230;' ), '<span class="code">%s</span>' );
    59 		$this->strings['downloading_package'] = sprintf( __( 'Downloading update from %s&#8230;' ), '<span class="code pre">%s</span>' );
    60 		$this->strings['unpack_package']      = __( 'Unpacking the update&#8230;' );
    60 		$this->strings['unpack_package']      = __( 'Unpacking the update&#8230;' );
    61 		$this->strings['remove_old']          = __( 'Removing the old version of the theme&#8230;' );
    61 		$this->strings['remove_old']          = __( 'Removing the old version of the theme&#8230;' );
    62 		$this->strings['remove_old_failed']   = __( 'Could not remove the old theme.' );
    62 		$this->strings['remove_old_failed']   = __( 'Could not remove the old theme.' );
    63 		$this->strings['process_failed']      = __( 'Theme update failed.' );
    63 		$this->strings['process_failed']      = __( 'Theme update failed.' );
    64 		$this->strings['process_success']     = __( 'Theme updated successfully.' );
    64 		$this->strings['process_success']     = __( 'Theme updated successfully.' );
    65 	}
    65 	}
    66 
    66 
    67 	/**
    67 	/**
    68 	 * Initialize the installation strings.
    68 	 * Initializes the installation strings.
    69 	 *
    69 	 *
    70 	 * @since 2.8.0
    70 	 * @since 2.8.0
    71 	 */
    71 	 */
    72 	public function install_strings() {
    72 	public function install_strings() {
    73 		$this->strings['no_package'] = __( 'Installation package not available.' );
    73 		$this->strings['no_package'] = __( 'Installation package not available.' );
    74 		/* translators: %s: Package URL. */
    74 		/* translators: %s: Package URL. */
    75 		$this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s&#8230;' ), '<span class="code">%s</span>' );
    75 		$this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s&#8230;' ), '<span class="code pre">%s</span>' );
    76 		$this->strings['unpack_package']      = __( 'Unpacking the package&#8230;' );
    76 		$this->strings['unpack_package']      = __( 'Unpacking the package&#8230;' );
    77 		$this->strings['installing_package']  = __( 'Installing the theme&#8230;' );
    77 		$this->strings['installing_package']  = __( 'Installing the theme&#8230;' );
    78 		$this->strings['remove_old']          = __( 'Removing the old version of the theme&#8230;' );
    78 		$this->strings['remove_old']          = __( 'Removing the old version of the theme&#8230;' );
    79 		$this->strings['remove_old_failed']   = __( 'Could not remove the old theme.' );
    79 		$this->strings['remove_old_failed']   = __( 'Could not remove the old theme.' );
    80 		$this->strings['no_files']            = __( 'The theme contains no files.' );
    80 		$this->strings['no_files']            = __( 'The theme contains no files.' );
   108 			}
   108 			}
   109 		}
   109 		}
   110 	}
   110 	}
   111 
   111 
   112 	/**
   112 	/**
   113 	 * Check if a child theme is being installed and we need to install its parent.
   113 	 * Checks if a child theme is being installed and its parent also needs to be installed.
   114 	 *
   114 	 *
   115 	 * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::install().
   115 	 * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::install().
   116 	 *
   116 	 *
   117 	 * @since 3.4.0
   117 	 * @since 3.4.0
   118 	 *
   118 	 *
   276 
   276 
   277 		return true;
   277 		return true;
   278 	}
   278 	}
   279 
   279 
   280 	/**
   280 	/**
   281 	 * Upgrade a theme.
   281 	 * Upgrades a theme.
   282 	 *
   282 	 *
   283 	 * @since 2.8.0
   283 	 * @since 2.8.0
   284 	 * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
   284 	 * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
   285 	 *
   285 	 *
   286 	 * @param string $theme The theme slug.
   286 	 * @param string $theme The theme slug.
   326 				'package'           => $r['package'],
   326 				'package'           => $r['package'],
   327 				'destination'       => get_theme_root( $theme ),
   327 				'destination'       => get_theme_root( $theme ),
   328 				'clear_destination' => true,
   328 				'clear_destination' => true,
   329 				'clear_working'     => true,
   329 				'clear_working'     => true,
   330 				'hook_extra'        => array(
   330 				'hook_extra'        => array(
   331 					'theme'  => $theme,
   331 					'theme'       => $theme,
   332 					'type'   => 'theme',
   332 					'type'        => 'theme',
   333 					'action' => 'update',
   333 					'action'      => 'update',
       
   334 					'temp_backup' => array(
       
   335 						'slug' => $theme,
       
   336 						'src'  => get_theme_root( $theme ),
       
   337 						'dir'  => 'themes',
       
   338 					),
   334 				),
   339 				),
   335 			)
   340 			)
   336 		);
   341 		);
   337 
   342 
   338 		remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
   343 		remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
   344 			return $this->result;
   349 			return $this->result;
   345 		}
   350 		}
   346 
   351 
   347 		wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
   352 		wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
   348 
   353 
   349 		// Ensure any future auto-update failures trigger a failure email by removing
   354 		/*
   350 		// the last failure notification from the list when themes update successfully.
   355 		 * Ensure any future auto-update failures trigger a failure email by removing
       
   356 		 * the last failure notification from the list when themes update successfully.
       
   357 		 */
   351 		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
   358 		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
   352 
   359 
   353 		if ( isset( $past_failure_emails[ $theme ] ) ) {
   360 		if ( isset( $past_failure_emails[ $theme ] ) ) {
   354 			unset( $past_failure_emails[ $theme ] );
   361 			unset( $past_failure_emails[ $theme ] );
   355 			update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
   362 			update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
   357 
   364 
   358 		return true;
   365 		return true;
   359 	}
   366 	}
   360 
   367 
   361 	/**
   368 	/**
   362 	 * Upgrade several themes at once.
   369 	 * Upgrades several themes at once.
   363 	 *
   370 	 *
   364 	 * @since 3.0.0
   371 	 * @since 3.0.0
   365 	 * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
   372 	 * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
       
   373 	 *
       
   374 	 * @global string $wp_version The WordPress version string.
   366 	 *
   375 	 *
   367 	 * @param string[] $themes Array of the theme slugs.
   376 	 * @param string[] $themes Array of the theme slugs.
   368 	 * @param array    $args {
   377 	 * @param array    $args {
   369 	 *     Optional. Other arguments for upgrading several themes at once. Default empty array.
   378 	 *     Optional. Other arguments for upgrading several themes at once. Default empty array.
   370 	 *
   379 	 *
   372 	 *                                    Default true.
   381 	 *                                    Default true.
   373 	 * }
   382 	 * }
   374 	 * @return array[]|false An array of results, or false if unable to connect to the filesystem.
   383 	 * @return array[]|false An array of results, or false if unable to connect to the filesystem.
   375 	 */
   384 	 */
   376 	public function bulk_upgrade( $themes, $args = array() ) {
   385 	public function bulk_upgrade( $themes, $args = array() ) {
       
   386 		global $wp_version;
       
   387 
   377 		$defaults    = array(
   388 		$defaults    = array(
   378 			'clear_update_cache' => true,
   389 			'clear_update_cache' => true,
   379 		);
   390 		);
   380 		$parsed_args = wp_parse_args( $args, $defaults );
   391 		$parsed_args = wp_parse_args( $args, $defaults );
   381 
   392 
   417 		$results = array();
   428 		$results = array();
   418 
   429 
   419 		$this->update_count   = count( $themes );
   430 		$this->update_count   = count( $themes );
   420 		$this->update_current = 0;
   431 		$this->update_current = 0;
   421 		foreach ( $themes as $theme ) {
   432 		foreach ( $themes as $theme ) {
   422 			$this->update_current++;
   433 			++$this->update_current;
   423 
   434 
   424 			$this->skin->theme_info = $this->theme_info( $theme );
   435 			$this->skin->theme_info = $this->theme_info( $theme );
   425 
   436 
   426 			if ( ! isset( $current->response[ $theme ] ) ) {
   437 			if ( ! isset( $current->response[ $theme ] ) ) {
   427 				$this->skin->set_result( true );
   438 				$this->skin->set_result( true );
   433 			}
   444 			}
   434 
   445 
   435 			// Get the URL to the zip file.
   446 			// Get the URL to the zip file.
   436 			$r = $current->response[ $theme ];
   447 			$r = $current->response[ $theme ];
   437 
   448 
   438 			$result = $this->run(
   449 			if ( isset( $r['requires'] ) && ! is_wp_version_compatible( $r['requires'] ) ) {
   439 				array(
   450 				$result = new WP_Error(
   440 					'package'           => $r['package'],
   451 					'incompatible_wp_required_version',
   441 					'destination'       => get_theme_root( $theme ),
   452 					sprintf(
   442 					'clear_destination' => true,
   453 						/* translators: 1: Current WordPress version, 2: WordPress version required by the new theme version. */
   443 					'clear_working'     => true,
   454 						__( 'Your WordPress version is %1$s, however the new theme version requires %2$s.' ),
   444 					'is_multi'          => true,
   455 						$wp_version,
   445 					'hook_extra'        => array(
   456 						$r['requires']
   446 						'theme' => $theme,
   457 					)
   447 					),
   458 				);
   448 				)
   459 
   449 			);
   460 				$this->skin->before( $result );
       
   461 				$this->skin->error( $result );
       
   462 				$this->skin->after();
       
   463 			} elseif ( isset( $r['requires_php'] ) && ! is_php_version_compatible( $r['requires_php'] ) ) {
       
   464 				$result = new WP_Error(
       
   465 					'incompatible_php_required_version',
       
   466 					sprintf(
       
   467 						/* translators: 1: Current PHP version, 2: PHP version required by the new theme version. */
       
   468 						__( 'The PHP version on your server is %1$s, however the new theme version requires %2$s.' ),
       
   469 						PHP_VERSION,
       
   470 						$r['requires_php']
       
   471 					)
       
   472 				);
       
   473 
       
   474 				$this->skin->before( $result );
       
   475 				$this->skin->error( $result );
       
   476 				$this->skin->after();
       
   477 			} else {
       
   478 				add_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
       
   479 				$result = $this->run(
       
   480 					array(
       
   481 						'package'           => $r['package'],
       
   482 						'destination'       => get_theme_root( $theme ),
       
   483 						'clear_destination' => true,
       
   484 						'clear_working'     => true,
       
   485 						'is_multi'          => true,
       
   486 						'hook_extra'        => array(
       
   487 							'theme'       => $theme,
       
   488 							'temp_backup' => array(
       
   489 								'slug' => $theme,
       
   490 								'src'  => get_theme_root( $theme ),
       
   491 								'dir'  => 'themes',
       
   492 							),
       
   493 						),
       
   494 					)
       
   495 				);
       
   496 				remove_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
       
   497 			}
   450 
   498 
   451 			$results[ $theme ] = $result;
   499 			$results[ $theme ] = $result;
   452 
   500 
   453 			// Prevent credentials auth screen from displaying multiple times.
   501 			// Prevent credentials auth screen from displaying multiple times.
   454 			if ( false === $result ) {
   502 			if ( false === $result ) {
   475 
   523 
   476 		$this->skin->bulk_footer();
   524 		$this->skin->bulk_footer();
   477 
   525 
   478 		$this->skin->footer();
   526 		$this->skin->footer();
   479 
   527 
   480 		// Cleanup our hooks, in case something else does a upgrade on this connection.
   528 		// Cleanup our hooks, in case something else does an upgrade on this connection.
   481 		remove_filter( 'upgrader_pre_install', array( $this, 'current_before' ) );
   529 		remove_filter( 'upgrader_pre_install', array( $this, 'current_before' ) );
   482 		remove_filter( 'upgrader_post_install', array( $this, 'current_after' ) );
   530 		remove_filter( 'upgrader_post_install', array( $this, 'current_after' ) );
   483 		remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ) );
   531 		remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ) );
   484 
   532 
   485 		// Ensure any future auto-update failures trigger a failure email by removing
   533 		/*
   486 		// the last failure notification from the list when themes update successfully.
   534 		 * Ensure any future auto-update failures trigger a failure email by removing
       
   535 		 * the last failure notification from the list when themes update successfully.
       
   536 		 */
   487 		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
   537 		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
   488 
   538 
   489 		foreach ( $results as $theme => $result ) {
   539 		foreach ( $results as $theme => $result ) {
   490 			// Maintain last failure notification when themes failed to update manually.
   540 			// Maintain last failure notification when themes failed to update manually.
   491 			if ( ! $result || is_wp_error( $result ) || ! isset( $past_failure_emails[ $theme ] ) ) {
   541 			if ( ! $result || is_wp_error( $result ) || ! isset( $past_failure_emails[ $theme ] ) ) {
   522 			return $source;
   572 			return $source;
   523 		}
   573 		}
   524 
   574 
   525 		// Check that the folder contains a valid theme.
   575 		// Check that the folder contains a valid theme.
   526 		$working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit( WP_CONTENT_DIR ), $source );
   576 		$working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit( WP_CONTENT_DIR ), $source );
   527 		if ( ! is_dir( $working_directory ) ) { // Sanity check, if the above fails, let's not prevent installation.
   577 		if ( ! is_dir( $working_directory ) ) { // Confidence check, if the above fails, let's not prevent installation.
   528 			return $source;
   578 			return $source;
   529 		}
   579 		}
   530 
   580 
   531 		// A proper archive should have a style.css file in the single subdirectory.
   581 		// A proper archive should have a style.css file in the single subdirectory.
   532 		if ( ! file_exists( $working_directory . 'style.css' ) ) {
   582 		if ( ! file_exists( $working_directory . 'style.css' ) ) {
   597 
   647 
   598 		if ( ! is_php_version_compatible( $requires_php ) ) {
   648 		if ( ! is_php_version_compatible( $requires_php ) ) {
   599 			$error = sprintf(
   649 			$error = sprintf(
   600 				/* translators: 1: Current PHP version, 2: Version required by the uploaded theme. */
   650 				/* translators: 1: Current PHP version, 2: Version required by the uploaded theme. */
   601 				__( 'The PHP version on your server is %1$s, however the uploaded theme requires %2$s.' ),
   651 				__( 'The PHP version on your server is %1$s, however the uploaded theme requires %2$s.' ),
   602 				phpversion(),
   652 				PHP_VERSION,
   603 				$requires_php
   653 				$requires_php
   604 			);
   654 			);
   605 
   655 
   606 			return new WP_Error( 'incompatible_php_required_version', $this->strings['incompatible_archive'], $error );
   656 			return new WP_Error( 'incompatible_php_required_version', $this->strings['incompatible_archive'], $error );
   607 		}
   657 		}
   620 
   670 
   621 		return $source;
   671 		return $source;
   622 	}
   672 	}
   623 
   673 
   624 	/**
   674 	/**
   625 	 * Turn on maintenance mode before attempting to upgrade the active theme.
   675 	 * Turns on maintenance mode before attempting to upgrade the active theme.
   626 	 *
   676 	 *
   627 	 * Hooked to the {@see 'upgrader_pre_install'} filter by Theme_Upgrader::upgrade() and
   677 	 * Hooked to the {@see 'upgrader_pre_install'} filter by Theme_Upgrader::upgrade() and
   628 	 * Theme_Upgrader::bulk_upgrade().
   678 	 * Theme_Upgrader::bulk_upgrade().
   629 	 *
   679 	 *
   630 	 * @since 2.8.0
   680 	 * @since 2.8.0
   652 
   702 
   653 		return $response;
   703 		return $response;
   654 	}
   704 	}
   655 
   705 
   656 	/**
   706 	/**
   657 	 * Turn off maintenance mode after upgrading the active theme.
   707 	 * Turns off maintenance mode after upgrading the active theme.
   658 	 *
   708 	 *
   659 	 * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::upgrade()
   709 	 * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::upgrade()
   660 	 * and Theme_Upgrader::bulk_upgrade().
   710 	 * and Theme_Upgrader::bulk_upgrade().
   661 	 *
   711 	 *
   662 	 * @since 2.8.0
   712 	 * @since 2.8.0
   690 		}
   740 		}
   691 		return $response;
   741 		return $response;
   692 	}
   742 	}
   693 
   743 
   694 	/**
   744 	/**
   695 	 * Delete the old theme during an upgrade.
   745 	 * Deletes the old theme during an upgrade.
   696 	 *
   746 	 *
   697 	 * Hooked to the {@see 'upgrader_clear_destination'} filter by Theme_Upgrader::upgrade()
   747 	 * Hooked to the {@see 'upgrader_clear_destination'} filter by Theme_Upgrader::upgrade()
   698 	 * and Theme_Upgrader::bulk_upgrade().
   748 	 * and Theme_Upgrader::bulk_upgrade().
   699 	 *
   749 	 *
   700 	 * @since 2.8.0
   750 	 * @since 2.8.0
   728 
   778 
   729 		return true;
   779 		return true;
   730 	}
   780 	}
   731 
   781 
   732 	/**
   782 	/**
   733 	 * Get the WP_Theme object for a theme.
   783 	 * Gets the WP_Theme object for a theme.
   734 	 *
   784 	 *
   735 	 * @since 2.8.0
   785 	 * @since 2.8.0
   736 	 * @since 3.0.0 The `$theme` argument was added.
   786 	 * @since 3.0.0 The `$theme` argument was added.
   737 	 *
   787 	 *
   738 	 * @param string $theme The directory name of the theme. This is optional, and if not supplied,
   788 	 * @param string $theme The directory name of the theme. This is optional, and if not supplied,
   752 		$theme = wp_get_theme( $theme );
   802 		$theme = wp_get_theme( $theme );
   753 		$theme->cache_delete();
   803 		$theme->cache_delete();
   754 
   804 
   755 		return $theme;
   805 		return $theme;
   756 	}
   806 	}
   757 
       
   758 }
   807 }