2019-11-02 10:38:58 +01:00
< ? php
/**
* Upgrade API : Theme_Upgrader class
*
* @ package WordPress
* @ subpackage Upgrader
* @ since 4.6 . 0
*/
/**
* Core class used for upgrading / installing themes .
*
* It is designed to upgrade / install themes from a local zip , remote zip URL ,
* or uploaded zip file .
*
* @ since 2.8 . 0
* @ since 4.6 . 0 Moved to its own file from wp - admin / includes / class - wp - upgrader . php .
*
* @ see WP_Upgrader
*/
class Theme_Upgrader extends WP_Upgrader {
/**
* Result of the theme upgrade offer .
*
* @ since 2.8 . 0
* @ var array | WP_Error $result
* @ see WP_Upgrader :: $result
*/
public $result ;
/**
* Whether multiple themes are being upgraded / installed in bulk .
*
* @ since 2.9 . 0
* @ var bool $bulk
*/
public $bulk = false ;
2020-09-15 14:29:22 +02:00
/**
* New theme info .
*
* @ since 5.5 . 0
* @ var array $new_theme_data
*
* @ see check_package ()
*/
public $new_theme_data = array ();
2019-11-02 10:38:58 +01:00
/**
2023-09-26 10:33:34 +02:00
* Initializes the upgrade strings .
2019-11-02 10:38:58 +01:00
*
* @ since 2.8 . 0
*/
public function upgrade_strings () {
$this -> strings [ 'up_to_date' ] = __ ( 'The theme is at the latest version.' );
$this -> strings [ 'no_package' ] = __ ( 'Update package not available.' );
2019-11-15 22:59:44 +01:00
/* translators: %s: Package URL. */
2023-09-26 10:33:34 +02:00
$this -> strings [ 'downloading_package' ] = sprintf ( __ ( 'Downloading update from %s…' ), '<span class="code pre">%s</span>' );
2019-11-02 10:38:58 +01:00
$this -> strings [ 'unpack_package' ] = __ ( 'Unpacking the update…' );
$this -> strings [ 'remove_old' ] = __ ( 'Removing the old version of the theme…' );
$this -> strings [ 'remove_old_failed' ] = __ ( 'Could not remove the old theme.' );
$this -> strings [ 'process_failed' ] = __ ( 'Theme update failed.' );
$this -> strings [ 'process_success' ] = __ ( 'Theme updated successfully.' );
}
/**
2023-09-26 10:33:34 +02:00
* Initializes the installation strings .
2019-11-02 10:38:58 +01:00
*
* @ since 2.8 . 0
*/
public function install_strings () {
$this -> strings [ 'no_package' ] = __ ( 'Installation package not available.' );
2019-11-15 22:59:44 +01:00
/* translators: %s: Package URL. */
2023-09-26 10:33:34 +02:00
$this -> strings [ 'downloading_package' ] = sprintf ( __ ( 'Downloading installation package from %s…' ), '<span class="code pre">%s</span>' );
2019-11-02 10:38:58 +01:00
$this -> strings [ 'unpack_package' ] = __ ( 'Unpacking the package…' );
$this -> strings [ 'installing_package' ] = __ ( 'Installing the theme…' );
2020-09-15 14:29:22 +02:00
$this -> strings [ 'remove_old' ] = __ ( 'Removing the old version of the theme…' );
$this -> strings [ 'remove_old_failed' ] = __ ( 'Could not remove the old theme.' );
2019-11-02 10:38:58 +01:00
$this -> strings [ 'no_files' ] = __ ( 'The theme contains no files.' );
$this -> strings [ 'process_failed' ] = __ ( 'Theme installation failed.' );
$this -> strings [ 'process_success' ] = __ ( 'Theme installed successfully.' );
2019-11-15 22:59:44 +01:00
/* translators: 1: Theme name, 2: Theme version. */
2019-11-02 10:38:58 +01:00
$this -> strings [ 'process_success_specific' ] = __ ( 'Successfully installed the theme <strong>%1$s %2$s</strong>.' );
$this -> strings [ 'parent_theme_search' ] = __ ( 'This theme requires a parent theme. Checking if it is installed…' );
2019-11-15 22:59:44 +01:00
/* translators: 1: Theme name, 2: Theme version. */
2019-11-02 10:38:58 +01:00
$this -> strings [ 'parent_theme_prepare_install' ] = __ ( 'Preparing to install <strong>%1$s %2$s</strong>…' );
2019-11-15 22:59:44 +01:00
/* translators: 1: Theme name, 2: Theme version. */
2019-11-02 10:38:58 +01:00
$this -> strings [ 'parent_theme_currently_installed' ] = __ ( 'The parent theme, <strong>%1$s %2$s</strong>, is currently installed.' );
2019-11-15 22:59:44 +01:00
/* translators: 1: Theme name, 2: Theme version. */
2019-11-02 10:38:58 +01:00
$this -> strings [ 'parent_theme_install_success' ] = __ ( 'Successfully installed the parent theme, <strong>%1$s %2$s</strong>.' );
2019-11-15 22:59:44 +01:00
/* translators: %s: Theme name. */
2019-11-02 10:38:58 +01:00
$this -> strings [ 'parent_theme_not_found' ] = sprintf ( __ ( '<strong>The parent theme could not be found.</strong> You will need to install the parent theme, %s, before you can use this child theme.' ), '<strong>%s</strong>' );
2020-09-15 14:29:22 +02:00
/* translators: %s: Theme error. */
2022-06-16 14:03:35 +02:00
$this -> strings [ 'current_theme_has_errors' ] = __ ( 'The active theme has the following error: "%s".' );
2020-09-15 14:29:22 +02:00
if ( ! empty ( $this -> skin -> overwrite ) ) {
if ( 'update-theme' === $this -> skin -> overwrite ) {
$this -> strings [ 'installing_package' ] = __ ( 'Updating the theme…' );
$this -> strings [ 'process_failed' ] = __ ( 'Theme update failed.' );
$this -> strings [ 'process_success' ] = __ ( 'Theme updated successfully.' );
}
if ( 'downgrade-theme' === $this -> skin -> overwrite ) {
$this -> strings [ 'installing_package' ] = __ ( 'Downgrading the theme…' );
$this -> strings [ 'process_failed' ] = __ ( 'Theme downgrade failed.' );
$this -> strings [ 'process_success' ] = __ ( 'Theme downgraded successfully.' );
}
}
2019-11-02 10:38:58 +01:00
}
/**
2023-09-26 10:33:34 +02:00
* Checks if a child theme is being installed and its parent also needs to be installed .
2019-11-02 10:38:58 +01:00
*
* Hooked to the { @ see 'upgrader_post_install' } filter by Theme_Upgrader :: install () .
*
* @ since 3.4 . 0
*
* @ param bool $install_result
* @ param array $hook_extra
* @ param array $child_result
2020-05-06 17:23:38 +02:00
* @ return bool
2019-11-02 10:38:58 +01:00
*/
public function check_parent_theme_filter ( $install_result , $hook_extra , $child_result ) {
2020-05-06 17:23:38 +02:00
// Check to see if we need to install a parent theme.
2019-11-02 10:38:58 +01:00
$theme_info = $this -> theme_info ();
if ( ! $theme_info -> parent () ) {
return $install_result ;
}
$this -> skin -> feedback ( 'parent_theme_search' );
if ( ! $theme_info -> parent () -> errors () ) {
$this -> skin -> feedback ( 'parent_theme_currently_installed' , $theme_info -> parent () -> display ( 'Name' ), $theme_info -> parent () -> display ( 'Version' ) );
// We already have the theme, fall through.
return $install_result ;
}
// We don't have the parent theme, let's install it.
$api = themes_api (
'theme_information' ,
array (
'slug' => $theme_info -> get ( 'Template' ),
'fields' => array (
'sections' => false ,
'tags' => false ,
),
)
2020-05-06 17:23:38 +02:00
); // Save on a bit of bandwidth.
2019-11-02 10:38:58 +01:00
if ( ! $api || is_wp_error ( $api ) ) {
$this -> skin -> feedback ( 'parent_theme_not_found' , $theme_info -> get ( 'Template' ) );
2020-05-06 17:23:38 +02:00
// Don't show activate or preview actions after installation.
2019-11-02 10:38:58 +01:00
add_filter ( 'install_theme_complete_actions' , array ( $this , 'hide_activate_preview_actions' ) );
return $install_result ;
}
// Backup required data we're going to override:
$child_api = $this -> skin -> api ;
$child_success_message = $this -> strings [ 'process_success' ];
2020-05-06 17:23:38 +02:00
// Override them.
$this -> skin -> api = $api ;
2020-09-15 14:29:22 +02:00
$this -> strings [ 'process_success_specific' ] = $this -> strings [ 'parent_theme_install_success' ];
2019-11-02 10:38:58 +01:00
$this -> skin -> feedback ( 'parent_theme_prepare_install' , $api -> name , $api -> version );
add_filter ( 'install_theme_complete_actions' , '__return_false' , 999 ); // Don't show any actions after installing the theme.
2020-05-06 17:23:38 +02:00
// Install the parent theme.
2019-11-02 10:38:58 +01:00
$parent_result = $this -> run (
array (
'package' => $api -> download_link ,
'destination' => get_theme_root (),
2020-05-06 17:23:38 +02:00
'clear_destination' => false , // Do not overwrite files.
2019-11-02 10:38:58 +01:00
'clear_working' => true ,
)
);
if ( is_wp_error ( $parent_result ) ) {
add_filter ( 'install_theme_complete_actions' , array ( $this , 'hide_activate_preview_actions' ) );
}
2020-05-06 17:23:38 +02:00
// Start cleaning up after the parent's installation.
2019-11-02 10:38:58 +01:00
remove_filter ( 'install_theme_complete_actions' , '__return_false' , 999 );
2020-05-06 17:23:38 +02:00
// Reset child's result and data.
2019-11-02 10:38:58 +01:00
$this -> result = $child_result ;
$this -> skin -> api = $child_api ;
$this -> strings [ 'process_success' ] = $child_success_message ;
return $install_result ;
}
/**
* Don ' t display the activate and preview actions to the user .
*
* Hooked to the { @ see 'install_theme_complete_actions' } filter by
* Theme_Upgrader :: check_parent_theme_filter () when installing
* a child theme and installing the parent theme fails .
*
* @ since 3.4 . 0
*
* @ param array $actions Preview actions .
* @ return array
*/
public function hide_activate_preview_actions ( $actions ) {
unset ( $actions [ 'activate' ], $actions [ 'preview' ] );
return $actions ;
}
/**
* Install a theme package .
*
* @ since 2.8 . 0
* @ since 3.7 . 0 The `$args` parameter was added , making clearing the update cache optional .
*
* @ param string $package The full local path or URI of the package .
* @ param array $args {
* Optional . Other arguments for installing a theme package . Default empty array .
*
* @ type bool $clear_update_cache Whether to clear the updates cache if successful .
* Default true .
* }
*
* @ return bool | WP_Error True if the installation was successful , false or a WP_Error object otherwise .
*/
public function install ( $package , $args = array () ) {
$defaults = array (
'clear_update_cache' => true ,
2020-09-15 14:29:22 +02:00
'overwrite_package' => false , // Do not overwrite files.
2019-11-02 10:38:58 +01:00
);
$parsed_args = wp_parse_args ( $args , $defaults );
$this -> init ();
$this -> install_strings ();
add_filter ( 'upgrader_source_selection' , array ( $this , 'check_package' ) );
add_filter ( 'upgrader_post_install' , array ( $this , 'check_parent_theme_filter' ), 10 , 3 );
2020-09-15 14:29:22 +02:00
2019-11-02 10:38:58 +01:00
if ( $parsed_args [ 'clear_update_cache' ] ) {
// Clear cache so wp_update_themes() knows about the new theme.
add_action ( 'upgrader_process_complete' , 'wp_clean_themes_cache' , 9 , 0 );
}
$this -> run (
array (
'package' => $package ,
'destination' => get_theme_root (),
2020-09-15 14:29:22 +02:00
'clear_destination' => $parsed_args [ 'overwrite_package' ],
2019-11-02 10:38:58 +01:00
'clear_working' => true ,
'hook_extra' => array (
'type' => 'theme' ,
'action' => 'install' ,
),
)
);
remove_action ( 'upgrader_process_complete' , 'wp_clean_themes_cache' , 9 );
remove_filter ( 'upgrader_source_selection' , array ( $this , 'check_package' ) );
remove_filter ( 'upgrader_post_install' , array ( $this , 'check_parent_theme_filter' ) );
if ( ! $this -> result || is_wp_error ( $this -> result ) ) {
return $this -> result ;
}
2020-05-06 17:23:38 +02:00
// Refresh the Theme Update information.
2019-11-02 10:38:58 +01:00
wp_clean_themes_cache ( $parsed_args [ 'clear_update_cache' ] );
2020-09-15 14:29:22 +02:00
if ( $parsed_args [ 'overwrite_package' ] ) {
2021-04-27 08:32:47 +02:00
/** This action is documented in wp-admin/includes/class-plugin-upgrader.php */
2020-09-15 14:29:22 +02:00
do_action ( 'upgrader_overwrote_package' , $package , $this -> new_theme_data , 'theme' );
}
2019-11-02 10:38:58 +01:00
return true ;
}
/**
2023-09-26 10:33:34 +02:00
* Upgrades a theme .
2019-11-02 10:38:58 +01:00
*
* @ since 2.8 . 0
* @ since 3.7 . 0 The `$args` parameter was added , making clearing the update cache optional .
*
* @ param string $theme The theme slug .
* @ param array $args {
* Optional . Other arguments for upgrading a theme . Default empty array .
*
* @ type bool $clear_update_cache Whether to clear the update cache if successful .
* Default true .
* }
* @ return bool | WP_Error True if the upgrade was successful , false or a WP_Error object otherwise .
*/
public function upgrade ( $theme , $args = array () ) {
$defaults = array (
'clear_update_cache' => true ,
);
$parsed_args = wp_parse_args ( $args , $defaults );
$this -> init ();
$this -> upgrade_strings ();
// Is an update available?
$current = get_site_transient ( 'update_themes' );
if ( ! isset ( $current -> response [ $theme ] ) ) {
$this -> skin -> before ();
$this -> skin -> set_result ( false );
$this -> skin -> error ( 'up_to_date' );
$this -> skin -> after ();
return false ;
}
$r = $current -> response [ $theme ];
add_filter ( 'upgrader_pre_install' , array ( $this , 'current_before' ), 10 , 2 );
add_filter ( 'upgrader_post_install' , array ( $this , 'current_after' ), 10 , 2 );
add_filter ( 'upgrader_clear_destination' , array ( $this , 'delete_old_theme' ), 10 , 4 );
if ( $parsed_args [ 'clear_update_cache' ] ) {
// Clear cache so wp_update_themes() knows about the new theme.
add_action ( 'upgrader_process_complete' , 'wp_clean_themes_cache' , 9 , 0 );
}
$this -> run (
array (
'package' => $r [ 'package' ],
'destination' => get_theme_root ( $theme ),
'clear_destination' => true ,
'clear_working' => true ,
'hook_extra' => array (
2023-09-26 10:33:34 +02:00
'theme' => $theme ,
'type' => 'theme' ,
'action' => 'update' ,
'temp_backup' => array (
'slug' => $theme ,
'src' => get_theme_root ( $theme ),
'dir' => 'themes' ,
),
2019-11-02 10:38:58 +01:00
),
)
);
remove_action ( 'upgrader_process_complete' , 'wp_clean_themes_cache' , 9 );
remove_filter ( 'upgrader_pre_install' , array ( $this , 'current_before' ) );
remove_filter ( 'upgrader_post_install' , array ( $this , 'current_after' ) );
remove_filter ( 'upgrader_clear_destination' , array ( $this , 'delete_old_theme' ) );
if ( ! $this -> result || is_wp_error ( $this -> result ) ) {
return $this -> result ;
}
wp_clean_themes_cache ( $parsed_args [ 'clear_update_cache' ] );
2023-09-26 10:33:34 +02:00
/*
* Ensure any future auto - update failures trigger a failure email by removing
* the last failure notification from the list when themes update successfully .
*/
2020-09-15 14:29:22 +02:00
$past_failure_emails = get_option ( 'auto_plugin_theme_update_emails' , array () );
if ( isset ( $past_failure_emails [ $theme ] ) ) {
unset ( $past_failure_emails [ $theme ] );
update_option ( 'auto_plugin_theme_update_emails' , $past_failure_emails );
}
2019-11-02 10:38:58 +01:00
return true ;
}
/**
2023-09-26 10:33:34 +02:00
* Upgrades several themes at once .
2019-11-02 10:38:58 +01:00
*
* @ since 3.0 . 0
* @ since 3.7 . 0 The `$args` parameter was added , making clearing the update cache optional .
*
* @ param string [] $themes Array of the theme slugs .
* @ param array $args {
* Optional . Other arguments for upgrading several themes at once . Default empty array .
*
* @ type bool $clear_update_cache Whether to clear the update cache if successful .
* Default true .
* }
* @ return array [] | false An array of results , or false if unable to connect to the filesystem .
*/
public function bulk_upgrade ( $themes , $args = array () ) {
$defaults = array (
'clear_update_cache' => true ,
);
$parsed_args = wp_parse_args ( $args , $defaults );
$this -> init ();
$this -> bulk = true ;
$this -> upgrade_strings ();
$current = get_site_transient ( 'update_themes' );
add_filter ( 'upgrader_pre_install' , array ( $this , 'current_before' ), 10 , 2 );
add_filter ( 'upgrader_post_install' , array ( $this , 'current_after' ), 10 , 2 );
add_filter ( 'upgrader_clear_destination' , array ( $this , 'delete_old_theme' ), 10 , 4 );
$this -> skin -> header ();
2020-05-06 17:23:38 +02:00
// Connect to the filesystem first.
2019-11-02 10:38:58 +01:00
$res = $this -> fs_connect ( array ( WP_CONTENT_DIR ) );
if ( ! $res ) {
$this -> skin -> footer ();
return false ;
}
$this -> skin -> bulk_header ();
2020-05-06 17:23:38 +02:00
/*
* Only start maintenance mode if :
* - running Multisite and there are one or more themes specified , OR
* - a theme with an update available is currently in use .
* @ todo For multisite , maintenance mode should only kick in for individual sites if at all possible .
*/
2019-11-02 10:38:58 +01:00
$maintenance = ( is_multisite () && ! empty ( $themes ) );
foreach ( $themes as $theme ) {
2020-05-06 17:23:38 +02:00
$maintenance = $maintenance || get_stylesheet () === $theme || get_template () === $theme ;
2019-11-02 10:38:58 +01:00
}
if ( $maintenance ) {
$this -> maintenance_mode ( true );
}
$results = array ();
$this -> update_count = count ( $themes );
$this -> update_current = 0 ;
foreach ( $themes as $theme ) {
$this -> update_current ++ ;
$this -> skin -> theme_info = $this -> theme_info ( $theme );
if ( ! isset ( $current -> response [ $theme ] ) ) {
$this -> skin -> set_result ( true );
$this -> skin -> before ();
$this -> skin -> feedback ( 'up_to_date' );
$this -> skin -> after ();
$results [ $theme ] = true ;
continue ;
}
2020-05-06 17:23:38 +02:00
// Get the URL to the zip file.
2019-11-02 10:38:58 +01:00
$r = $current -> response [ $theme ];
$result = $this -> run (
array (
'package' => $r [ 'package' ],
'destination' => get_theme_root ( $theme ),
'clear_destination' => true ,
'clear_working' => true ,
'is_multi' => true ,
'hook_extra' => array (
2023-09-26 10:33:34 +02:00
'theme' => $theme ,
'temp_backup' => array (
'slug' => $theme ,
'src' => get_theme_root ( $theme ),
'dir' => 'themes' ,
),
2019-11-02 10:38:58 +01:00
),
)
);
2022-04-02 10:26:41 +02:00
$results [ $theme ] = $result ;
2019-11-02 10:38:58 +01:00
2020-05-06 17:23:38 +02:00
// Prevent credentials auth screen from displaying multiple times.
2019-11-02 10:38:58 +01:00
if ( false === $result ) {
break ;
}
2020-05-06 17:23:38 +02:00
} // End foreach $themes.
2019-11-02 10:38:58 +01:00
$this -> maintenance_mode ( false );
2020-05-06 17:23:38 +02:00
// Refresh the Theme Update information.
2019-11-02 10:38:58 +01:00
wp_clean_themes_cache ( $parsed_args [ 'clear_update_cache' ] );
/** This action is documented in wp-admin/includes/class-wp-upgrader.php */
do_action (
'upgrader_process_complete' ,
$this ,
array (
'action' => 'update' ,
'type' => 'theme' ,
'bulk' => true ,
'themes' => $themes ,
)
);
$this -> skin -> bulk_footer ();
$this -> skin -> footer ();
2023-09-26 10:33:34 +02:00
// Cleanup our hooks, in case something else does an upgrade on this connection.
2019-11-02 10:38:58 +01:00
remove_filter ( 'upgrader_pre_install' , array ( $this , 'current_before' ) );
remove_filter ( 'upgrader_post_install' , array ( $this , 'current_after' ) );
remove_filter ( 'upgrader_clear_destination' , array ( $this , 'delete_old_theme' ) );
2023-09-26 10:33:34 +02:00
/*
* Ensure any future auto - update failures trigger a failure email by removing
* the last failure notification from the list when themes update successfully .
*/
2020-09-15 14:29:22 +02:00
$past_failure_emails = get_option ( 'auto_plugin_theme_update_emails' , array () );
foreach ( $results as $theme => $result ) {
// Maintain last failure notification when themes failed to update manually.
if ( ! $result || is_wp_error ( $result ) || ! isset ( $past_failure_emails [ $theme ] ) ) {
continue ;
}
unset ( $past_failure_emails [ $theme ] );
}
update_option ( 'auto_plugin_theme_update_emails' , $past_failure_emails );
2019-11-02 10:38:58 +01:00
return $results ;
}
/**
2020-12-10 14:06:04 +01:00
* Checks that the package source contains a valid theme .
2019-11-02 10:38:58 +01:00
*
* Hooked to the { @ see 'upgrader_source_selection' } filter by Theme_Upgrader :: install () .
*
* @ since 3.3 . 0
*
* @ global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass .
2020-12-10 14:06:04 +01:00
* @ global string $wp_version The WordPress version string .
2019-11-02 10:38:58 +01:00
*
2020-12-10 14:06:04 +01:00
* @ param string $source The path to the downloaded package source .
* @ return string | WP_Error The source as passed , or a WP_Error object on failure .
2019-11-02 10:38:58 +01:00
*/
public function check_package ( $source ) {
2020-12-10 14:06:04 +01:00
global $wp_filesystem , $wp_version ;
2019-11-02 10:38:58 +01:00
2020-09-15 14:29:22 +02:00
$this -> new_theme_data = array ();
2019-11-02 10:38:58 +01:00
if ( is_wp_error ( $source ) ) {
return $source ;
}
2020-05-06 17:23:38 +02:00
// Check that the folder contains a valid theme.
2019-11-02 10:38:58 +01:00
$working_directory = str_replace ( $wp_filesystem -> wp_content_dir (), trailingslashit ( WP_CONTENT_DIR ), $source );
if ( ! is_dir ( $working_directory ) ) { // Sanity check, if the above fails, let's not prevent installation.
return $source ;
}
2020-05-06 17:23:38 +02:00
// A proper archive should have a style.css file in the single subdirectory.
2019-11-02 10:38:58 +01:00
if ( ! file_exists ( $working_directory . 'style.css' ) ) {
return new WP_Error (
'incompatible_archive_theme_no_style' ,
$this -> strings [ 'incompatible_archive' ],
sprintf (
/* translators: %s: style.css */
__ ( 'The theme is missing the %s stylesheet.' ),
'<code>style.css</code>'
)
);
}
2020-09-15 14:29:22 +02:00
// All these headers are needed on Theme_Installer_Skin::do_overwrite().
2019-11-02 10:38:58 +01:00
$info = get_file_data (
$working_directory . 'style.css' ,
array (
2020-09-15 14:29:22 +02:00
'Name' => 'Theme Name' ,
'Version' => 'Version' ,
'Author' => 'Author' ,
'Template' => 'Template' ,
'RequiresWP' => 'Requires at least' ,
'RequiresPHP' => 'Requires PHP' ,
2019-11-02 10:38:58 +01:00
)
);
if ( empty ( $info [ 'Name' ] ) ) {
return new WP_Error (
'incompatible_archive_theme_no_name' ,
$this -> strings [ 'incompatible_archive' ],
sprintf (
/* translators: %s: style.css */
2022-06-16 14:03:35 +02:00
__ ( 'The %s stylesheet does not contain a valid theme header.' ),
2019-11-02 10:38:58 +01:00
'<code>style.css</code>'
)
);
}
2022-06-16 14:03:35 +02:00
/*
* Parent themes must contain an index file :
* - classic themes require / index . php
* - block themes require / templates / index . html or block - templates / index . html ( deprecated 5.9 . 0 ) .
*/
if (
empty ( $info [ 'Template' ] ) &&
! file_exists ( $working_directory . 'index.php' ) &&
! file_exists ( $working_directory . 'templates/index.html' ) &&
! file_exists ( $working_directory . 'block-templates/index.html' )
) {
2019-11-02 10:38:58 +01:00
return new WP_Error (
'incompatible_archive_theme_no_index' ,
$this -> strings [ 'incompatible_archive' ],
sprintf (
2022-06-16 14:03:35 +02:00
/* translators: 1: templates/index.html, 2: index.php, 3: Documentation URL, 4: Template, 5: style.css */
__ ( 'Template is missing. Standalone themes need to have a %1$s or %2$s template file. <a href="%3$s">Child themes</a> need to have a %4$s header in the %5$s stylesheet.' ),
'<code>templates/index.html</code>' ,
'<code>index.php</code>' ,
__ ( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ),
'<code>Template</code>' ,
'<code>style.css</code>'
2019-11-02 10:38:58 +01:00
)
);
}
2020-09-15 14:29:22 +02:00
$requires_php = isset ( $info [ 'RequiresPHP' ] ) ? $info [ 'RequiresPHP' ] : null ;
$requires_wp = isset ( $info [ 'RequiresWP' ] ) ? $info [ 'RequiresWP' ] : null ;
if ( ! is_php_version_compatible ( $requires_php ) ) {
$error = sprintf (
/* translators: 1: Current PHP version, 2: Version required by the uploaded theme. */
__ ( 'The PHP version on your server is %1$s, however the uploaded theme requires %2$s.' ),
2022-12-15 17:47:31 +01:00
PHP_VERSION ,
2020-09-15 14:29:22 +02:00
$requires_php
);
return new WP_Error ( 'incompatible_php_required_version' , $this -> strings [ 'incompatible_archive' ], $error );
}
if ( ! is_wp_version_compatible ( $requires_wp ) ) {
$error = sprintf (
/* translators: 1: Current WordPress version, 2: Version required by the uploaded theme. */
__ ( 'Your WordPress version is %1$s, however the uploaded theme requires %2$s.' ),
2020-12-10 14:06:04 +01:00
$wp_version ,
2020-09-15 14:29:22 +02:00
$requires_wp
);
return new WP_Error ( 'incompatible_wp_required_version' , $this -> strings [ 'incompatible_archive' ], $error );
}
$this -> new_theme_data = $info ;
2019-11-02 10:38:58 +01:00
return $source ;
}
/**
2023-09-26 10:33:34 +02:00
* Turns on maintenance mode before attempting to upgrade the active theme .
2019-11-02 10:38:58 +01:00
*
* Hooked to the { @ see 'upgrader_pre_install' } filter by Theme_Upgrader :: upgrade () and
* Theme_Upgrader :: bulk_upgrade () .
*
* @ since 2.8 . 0
*
2022-06-16 14:03:35 +02:00
* @ param bool | WP_Error $response The installation response before the installation has started .
* @ param array $theme Theme arguments .
* @ return bool | WP_Error The original `$response` parameter or WP_Error .
2019-11-02 10:38:58 +01:00
*/
2022-06-16 14:03:35 +02:00
public function current_before ( $response , $theme ) {
if ( is_wp_error ( $response ) ) {
return $response ;
2019-11-02 10:38:58 +01:00
}
$theme = isset ( $theme [ 'theme' ] ) ? $theme [ 'theme' ] : '' ;
2022-06-16 14:03:35 +02:00
// Only run if active theme.
2020-05-06 17:23:38 +02:00
if ( get_stylesheet () !== $theme ) {
2022-06-16 14:03:35 +02:00
return $response ;
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
// Change to maintenance mode. Bulk edit handles this separately.
2019-11-02 10:38:58 +01:00
if ( ! $this -> bulk ) {
$this -> maintenance_mode ( true );
}
2022-06-16 14:03:35 +02:00
return $response ;
2019-11-02 10:38:58 +01:00
}
/**
2023-09-26 10:33:34 +02:00
* Turns off maintenance mode after upgrading the active theme .
2019-11-02 10:38:58 +01:00
*
* Hooked to the { @ see 'upgrader_post_install' } filter by Theme_Upgrader :: upgrade ()
* and Theme_Upgrader :: bulk_upgrade () .
*
* @ since 2.8 . 0
*
2022-06-16 14:03:35 +02:00
* @ param bool | WP_Error $response The installation response after the installation has finished .
* @ param array $theme Theme arguments .
* @ return bool | WP_Error The original `$response` parameter or WP_Error .
2019-11-02 10:38:58 +01:00
*/
2022-06-16 14:03:35 +02:00
public function current_after ( $response , $theme ) {
if ( is_wp_error ( $response ) ) {
return $response ;
2019-11-02 10:38:58 +01:00
}
$theme = isset ( $theme [ 'theme' ] ) ? $theme [ 'theme' ] : '' ;
2022-06-16 14:03:35 +02:00
// Only run if active theme.
2020-05-06 17:23:38 +02:00
if ( get_stylesheet () !== $theme ) {
2022-06-16 14:03:35 +02:00
return $response ;
2019-11-02 10:38:58 +01:00
}
// Ensure stylesheet name hasn't changed after the upgrade:
2020-09-15 14:29:22 +02:00
if ( get_stylesheet () === $theme && $theme !== $this -> result [ 'destination_name' ] ) {
2019-11-02 10:38:58 +01:00
wp_clean_themes_cache ();
$stylesheet = $this -> result [ 'destination_name' ];
switch_theme ( $stylesheet );
}
2020-05-06 17:23:38 +02:00
// Time to remove maintenance mode. Bulk edit handles this separately.
2019-11-02 10:38:58 +01:00
if ( ! $this -> bulk ) {
$this -> maintenance_mode ( false );
}
2022-06-16 14:03:35 +02:00
return $response ;
2019-11-02 10:38:58 +01:00
}
/**
2023-09-26 10:33:34 +02:00
* Deletes the old theme during an upgrade .
2019-11-02 10:38:58 +01:00
*
* Hooked to the { @ see 'upgrader_clear_destination' } filter by Theme_Upgrader :: upgrade ()
* and Theme_Upgrader :: bulk_upgrade () .
*
* @ since 2.8 . 0
*
* @ global WP_Filesystem_Base $wp_filesystem Subclass
*
* @ param bool $removed
* @ param string $local_destination
* @ param string $remote_destination
* @ param array $theme
* @ return bool
*/
public function delete_old_theme ( $removed , $local_destination , $remote_destination , $theme ) {
global $wp_filesystem ;
if ( is_wp_error ( $removed ) ) {
return $removed ; // Pass errors through.
}
if ( ! isset ( $theme [ 'theme' ] ) ) {
return $removed ;
}
$theme = $theme [ 'theme' ];
$themes_dir = trailingslashit ( $wp_filesystem -> wp_themes_dir ( $theme ) );
if ( $wp_filesystem -> exists ( $themes_dir . $theme ) ) {
if ( ! $wp_filesystem -> delete ( $themes_dir . $theme , true ) ) {
return false ;
}
}
return true ;
}
/**
2023-09-26 10:33:34 +02:00
* Gets the WP_Theme object for a theme .
2019-11-02 10:38:58 +01:00
*
* @ since 2.8 . 0
* @ since 3.0 . 0 The `$theme` argument was added .
*
* @ param string $theme The directory name of the theme . This is optional , and if not supplied ,
* the directory name from the last result will be used .
* @ return WP_Theme | false The theme ' s info object , or false `$theme` is not supplied
* and the last result isn ' t set .
*/
public function theme_info ( $theme = null ) {
if ( empty ( $theme ) ) {
if ( ! empty ( $this -> result [ 'destination_name' ] ) ) {
$theme = $this -> result [ 'destination_name' ];
} else {
return false ;
}
}
2020-09-15 14:29:22 +02:00
$theme = wp_get_theme ( $theme );
$theme -> cache_delete ();
return $theme ;
2019-11-02 10:38:58 +01:00
}
}