| | <?php |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | class Theme_Upgrader extends WP_Upgrader { |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public $result; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | public $bulk = false; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public $new_theme_data = array(); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | public function upgrade_strings() { |
| | $this->strings['up_to_date'] = __( 'The theme is at the latest version.' ); |
| | $this->strings['no_package'] = __( 'Update package not available.' ); |
| | |
| | $this->strings['downloading_package'] = sprintf( __( 'Downloading update from %s…' ), '<span class="code pre">%s</span>' ); |
| | $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.' ); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | public function install_strings() { |
| | $this->strings['no_package'] = __( 'Installation package not available.' ); |
| | |
| | $this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s…' ), '<span class="code pre">%s</span>' ); |
| | $this->strings['unpack_package'] = __( 'Unpacking the package…' ); |
| | $this->strings['installing_package'] = __( 'Installing the theme…' ); |
| | $this->strings['remove_old'] = __( 'Removing the old version of the theme…' ); |
| | $this->strings['remove_old_failed'] = __( 'Could not remove the old theme.' ); |
| | $this->strings['no_files'] = __( 'The theme contains no files.' ); |
| | $this->strings['process_failed'] = __( 'Theme installation failed.' ); |
| | $this->strings['process_success'] = __( 'Theme installed successfully.' ); |
| | |
| | $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…' ); |
| | |
| | $this->strings['parent_theme_prepare_install'] = __( 'Preparing to install <strong>%1$s %2$s</strong>…' ); |
| | |
| | $this->strings['parent_theme_currently_installed'] = __( 'The parent theme, <strong>%1$s %2$s</strong>, is currently installed.' ); |
| | |
| | $this->strings['parent_theme_install_success'] = __( 'Successfully installed the parent theme, <strong>%1$s %2$s</strong>.' ); |
| | |
| | $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>' ); |
| | |
| | $this->strings['current_theme_has_errors'] = __( 'The active theme has the following error: "%s".' ); |
| |
|
| | 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.' ); |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function check_parent_theme_filter( $install_result, $hook_extra, $child_result ) { |
| | |
| | $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' ) ); |
| | |
| | return $install_result; |
| | } |
| |
|
| | |
| | $api = themes_api( |
| | 'theme_information', |
| | array( |
| | 'slug' => $theme_info->get( 'Template' ), |
| | 'fields' => array( |
| | 'sections' => false, |
| | 'tags' => false, |
| | ), |
| | ) |
| | ); |
| |
|
| | if ( ! $api || is_wp_error( $api ) ) { |
| | $this->skin->feedback( 'parent_theme_not_found', $theme_info->get( 'Template' ) ); |
| | |
| | add_filter( 'install_theme_complete_actions', array( $this, 'hide_activate_preview_actions' ) ); |
| | return $install_result; |
| | } |
| |
|
| | |
| | $child_api = $this->skin->api; |
| | $child_success_message = $this->strings['process_success']; |
| |
|
| | |
| | $this->skin->api = $api; |
| |
|
| | $this->strings['process_success_specific'] = $this->strings['parent_theme_install_success']; |
| |
|
| | $this->skin->feedback( 'parent_theme_prepare_install', $api->name, $api->version ); |
| |
|
| | add_filter( 'install_theme_complete_actions', '__return_false', 999 ); |
| |
|
| | |
| | $parent_result = $this->run( |
| | array( |
| | 'package' => $api->download_link, |
| | 'destination' => get_theme_root(), |
| | 'clear_destination' => false, // Do not overwrite files. |
| | 'clear_working' => true, |
| | ) |
| | ); |
| |
|
| | if ( is_wp_error( $parent_result ) ) { |
| | add_filter( 'install_theme_complete_actions', array( $this, 'hide_activate_preview_actions' ) ); |
| | } |
| |
|
| | |
| | remove_filter( 'install_theme_complete_actions', '__return_false', 999 ); |
| |
|
| | |
| | $this->result = $child_result; |
| | $this->skin->api = $child_api; |
| | $this->strings['process_success'] = $child_success_message; |
| |
|
| | return $install_result; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function hide_activate_preview_actions( $actions ) { |
| | unset( $actions['activate'], $actions['preview'] ); |
| | return $actions; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function install( $package, $args = array() ) { |
| | $defaults = array( |
| | 'clear_update_cache' => true, |
| | 'overwrite_package' => false, |
| | ); |
| | $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 ); |
| |
|
| | if ( $parsed_args['clear_update_cache'] ) { |
| | |
| | add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 ); |
| | } |
| |
|
| | $this->run( |
| | array( |
| | 'package' => $package, |
| | 'destination' => get_theme_root(), |
| | 'clear_destination' => $parsed_args['overwrite_package'], |
| | '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; |
| | } |
| |
|
| | |
| | wp_clean_themes_cache( $parsed_args['clear_update_cache'] ); |
| |
|
| | if ( $parsed_args['overwrite_package'] ) { |
| | |
| | do_action( 'upgrader_overwrote_package', $package, $this->new_theme_data, 'theme' ); |
| | } |
| |
|
| | return true; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function upgrade( $theme, $args = array() ) { |
| | $defaults = array( |
| | 'clear_update_cache' => true, |
| | ); |
| | $parsed_args = wp_parse_args( $args, $defaults ); |
| |
|
| | $this->init(); |
| | $this->upgrade_strings(); |
| |
|
| | |
| | $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'] ) { |
| | |
| | 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( |
| | 'theme' => $theme, |
| | 'type' => 'theme', |
| | 'action' => 'update', |
| | 'temp_backup' => array( |
| | 'slug' => $theme, |
| | 'src' => get_theme_root( $theme ), |
| | 'dir' => 'themes', |
| | ), |
| | ), |
| | ) |
| | ); |
| |
|
| | 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'] ); |
| |
|
| | |
| | |
| | |
| | |
| | $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 ); |
| | } |
| |
|
| | return true; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function bulk_upgrade( $themes, $args = array() ) { |
| | global $wp_version; |
| |
|
| | $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(); |
| |
|
| | |
| | $res = $this->fs_connect( array( WP_CONTENT_DIR ) ); |
| | if ( ! $res ) { |
| | $this->skin->footer(); |
| | return false; |
| | } |
| |
|
| | $this->skin->bulk_header(); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | $maintenance = ( is_multisite() && ! empty( $themes ) ); |
| | foreach ( $themes as $theme ) { |
| | $maintenance = $maintenance || get_stylesheet() === $theme || get_template() === $theme; |
| | } |
| | 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; |
| | } |
| |
|
| | |
| | $r = $current->response[ $theme ]; |
| |
|
| | if ( isset( $r['requires'] ) && ! is_wp_version_compatible( $r['requires'] ) ) { |
| | $result = new WP_Error( |
| | 'incompatible_wp_required_version', |
| | sprintf( |
| | |
| | __( 'Your WordPress version is %1$s, however the new theme version requires %2$s.' ), |
| | $wp_version, |
| | $r['requires'] |
| | ) |
| | ); |
| |
|
| | $this->skin->before( $result ); |
| | $this->skin->error( $result ); |
| | $this->skin->after(); |
| | } elseif ( isset( $r['requires_php'] ) && ! is_php_version_compatible( $r['requires_php'] ) ) { |
| | $result = new WP_Error( |
| | 'incompatible_php_required_version', |
| | sprintf( |
| | |
| | __( 'The PHP version on your server is %1$s, however the new theme version requires %2$s.' ), |
| | PHP_VERSION, |
| | $r['requires_php'] |
| | ) |
| | ); |
| |
|
| | $this->skin->before( $result ); |
| | $this->skin->error( $result ); |
| | $this->skin->after(); |
| | } else { |
| | add_filter( 'upgrader_source_selection', array( $this, 'check_package' ) ); |
| | $result = $this->run( |
| | array( |
| | 'package' => $r['package'], |
| | 'destination' => get_theme_root( $theme ), |
| | 'clear_destination' => true, |
| | 'clear_working' => true, |
| | 'is_multi' => true, |
| | 'hook_extra' => array( |
| | 'theme' => $theme, |
| | 'temp_backup' => array( |
| | 'slug' => $theme, |
| | 'src' => get_theme_root( $theme ), |
| | 'dir' => 'themes', |
| | ), |
| | ), |
| | ) |
| | ); |
| | remove_filter( 'upgrader_source_selection', array( $this, 'check_package' ) ); |
| | } |
| |
|
| | $results[ $theme ] = $result; |
| |
|
| | |
| | if ( false === $result ) { |
| | break; |
| | } |
| | } |
| |
|
| | $this->maintenance_mode( false ); |
| |
|
| | |
| | wp_clean_themes_cache( $parsed_args['clear_update_cache'] ); |
| |
|
| | |
| | do_action( |
| | 'upgrader_process_complete', |
| | $this, |
| | array( |
| | 'action' => 'update', |
| | 'type' => 'theme', |
| | 'bulk' => true, |
| | 'themes' => $themes, |
| | ) |
| | ); |
| |
|
| | $this->skin->bulk_footer(); |
| |
|
| | $this->skin->footer(); |
| |
|
| | |
| | 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' ) ); |
| |
|
| | |
| | |
| | |
| | |
| | $past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() ); |
| |
|
| | foreach ( $results as $theme => $result ) { |
| | |
| | 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 ); |
| |
|
| | return $results; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function check_package( $source ) { |
| | global $wp_filesystem, $wp_version; |
| |
|
| | $this->new_theme_data = array(); |
| |
|
| | if ( is_wp_error( $source ) ) { |
| | return $source; |
| | } |
| |
|
| | |
| | $working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit( WP_CONTENT_DIR ), $source ); |
| | if ( ! is_dir( $working_directory ) ) { |
| | return $source; |
| | } |
| |
|
| | |
| | if ( ! file_exists( $working_directory . 'style.css' ) ) { |
| | return new WP_Error( |
| | 'incompatible_archive_theme_no_style', |
| | $this->strings['incompatible_archive'], |
| | sprintf( |
| | |
| | __( 'The theme is missing the %s stylesheet.' ), |
| | '<code>style.css</code>' |
| | ) |
| | ); |
| | } |
| |
|
| | |
| | $info = get_file_data( |
| | $working_directory . 'style.css', |
| | array( |
| | 'Name' => 'Theme Name', |
| | 'Version' => 'Version', |
| | 'Author' => 'Author', |
| | 'Template' => 'Template', |
| | 'RequiresWP' => 'Requires at least', |
| | 'RequiresPHP' => 'Requires PHP', |
| | ) |
| | ); |
| |
|
| | if ( empty( $info['Name'] ) ) { |
| | return new WP_Error( |
| | 'incompatible_archive_theme_no_name', |
| | $this->strings['incompatible_archive'], |
| | sprintf( |
| | |
| | __( 'The %s stylesheet does not contain a valid theme header.' ), |
| | '<code>style.css</code>' |
| | ) |
| | ); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | 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' ) |
| | ) { |
| | return new WP_Error( |
| | 'incompatible_archive_theme_no_index', |
| | $this->strings['incompatible_archive'], |
| | sprintf( |
| | |
| | __( '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>' |
| | ) |
| | ); |
| | } |
| |
|
| | $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( |
| | |
| | __( 'The PHP version on your server is %1$s, however the uploaded theme requires %2$s.' ), |
| | PHP_VERSION, |
| | $requires_php |
| | ); |
| |
|
| | return new WP_Error( 'incompatible_php_required_version', $this->strings['incompatible_archive'], $error ); |
| | } |
| | if ( ! is_wp_version_compatible( $requires_wp ) ) { |
| | $error = sprintf( |
| | |
| | __( 'Your WordPress version is %1$s, however the uploaded theme requires %2$s.' ), |
| | $wp_version, |
| | $requires_wp |
| | ); |
| |
|
| | return new WP_Error( 'incompatible_wp_required_version', $this->strings['incompatible_archive'], $error ); |
| | } |
| |
|
| | $this->new_theme_data = $info; |
| |
|
| | return $source; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function current_before( $response, $theme ) { |
| | if ( is_wp_error( $response ) ) { |
| | return $response; |
| | } |
| |
|
| | $theme = isset( $theme['theme'] ) ? $theme['theme'] : ''; |
| |
|
| | |
| | if ( get_stylesheet() !== $theme ) { |
| | return $response; |
| | } |
| |
|
| | |
| | if ( ! $this->bulk ) { |
| | $this->maintenance_mode( true ); |
| | } |
| |
|
| | return $response; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function current_after( $response, $theme ) { |
| | if ( is_wp_error( $response ) ) { |
| | return $response; |
| | } |
| |
|
| | $theme = isset( $theme['theme'] ) ? $theme['theme'] : ''; |
| |
|
| | |
| | if ( get_stylesheet() !== $theme ) { |
| | return $response; |
| | } |
| |
|
| | |
| | if ( get_stylesheet() === $theme && $theme !== $this->result['destination_name'] ) { |
| | wp_clean_themes_cache(); |
| | $stylesheet = $this->result['destination_name']; |
| | switch_theme( $stylesheet ); |
| | } |
| |
|
| | |
| | if ( ! $this->bulk ) { |
| | $this->maintenance_mode( false ); |
| | } |
| | return $response; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function delete_old_theme( $removed, $local_destination, $remote_destination, $theme ) { |
| | global $wp_filesystem; |
| |
|
| | if ( is_wp_error( $removed ) ) { |
| | return $removed; |
| | } |
| |
|
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function theme_info( $theme = null ) { |
| | if ( empty( $theme ) ) { |
| | if ( ! empty( $this->result['destination_name'] ) ) { |
| | $theme = $this->result['destination_name']; |
| | } else { |
| | return false; |
| | } |
| | } |
| |
|
| | $theme = wp_get_theme( $theme ); |
| | $theme->cache_delete(); |
| |
|
| | return $theme; |
| | } |
| | } |
| |
|