[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Upgrader API: Theme_Installer_Skin class 4 * 5 * @package WordPress 6 * @subpackage Upgrader 7 * @since 4.6.0 8 */ 9 10 /** 11 * Theme Installer Skin for the WordPress Theme Installer. 12 * 13 * @since 2.8.0 14 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php. 15 * 16 * @see WP_Upgrader_Skin 17 */ 18 class Theme_Installer_Skin extends WP_Upgrader_Skin { 19 public $api; 20 public $type; 21 public $url; 22 public $overwrite; 23 24 private $is_downgrading = false; 25 26 /** 27 * @param array $args 28 */ 29 public function __construct( $args = array() ) { 30 $defaults = array( 31 'type' => 'web', 32 'url' => '', 33 'theme' => '', 34 'nonce' => '', 35 'title' => '', 36 'overwrite' => '', 37 ); 38 $args = wp_parse_args( $args, $defaults ); 39 40 $this->type = $args['type']; 41 $this->url = $args['url']; 42 $this->api = isset( $args['api'] ) ? $args['api'] : array(); 43 $this->overwrite = $args['overwrite']; 44 45 parent::__construct( $args ); 46 } 47 48 /** 49 * Action to perform before installing a theme. 50 * 51 * @since 2.8.0 52 */ 53 public function before() { 54 if ( ! empty( $this->api ) ) { 55 $this->upgrader->strings['process_success'] = sprintf( 56 $this->upgrader->strings['process_success_specific'], 57 $this->api->name, 58 $this->api->version 59 ); 60 } 61 } 62 63 /** 64 * Hides the `process_failed` error when updating a theme by uploading a zip file. 65 * 66 * @since 5.5.0 67 * 68 * @param WP_Error $wp_error WP_Error object. 69 * @return bool 70 */ 71 public function hide_process_failed( $wp_error ) { 72 if ( 73 'upload' === $this->type && 74 '' === $this->overwrite && 75 $wp_error->get_error_code() === 'folder_exists' 76 ) { 77 return true; 78 } 79 80 return false; 81 } 82 83 /** 84 * Action to perform following a single theme install. 85 * 86 * @since 2.8.0 87 */ 88 public function after() { 89 if ( $this->do_overwrite() ) { 90 return; 91 } 92 93 if ( empty( $this->upgrader->result['destination_name'] ) ) { 94 return; 95 } 96 97 $theme_info = $this->upgrader->theme_info(); 98 if ( empty( $theme_info ) ) { 99 return; 100 } 101 102 $name = $theme_info->display( 'Name' ); 103 $stylesheet = $this->upgrader->result['destination_name']; 104 $template = $theme_info->get_template(); 105 106 $activate_link = add_query_arg( 107 array( 108 'action' => 'activate', 109 'template' => urlencode( $template ), 110 'stylesheet' => urlencode( $stylesheet ), 111 ), 112 admin_url( 'themes.php' ) 113 ); 114 $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet ); 115 116 $install_actions = array(); 117 118 if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) && ! $theme_info->is_block_theme() ) { 119 $customize_url = add_query_arg( 120 array( 121 'theme' => urlencode( $stylesheet ), 122 'return' => urlencode( admin_url( 'web' === $this->type ? 'theme-install.php' : 'themes.php' ) ), 123 ), 124 admin_url( 'customize.php' ) 125 ); 126 127 $install_actions['preview'] = sprintf( 128 '<a href="%s" class="hide-if-no-customize load-customize">' . 129 '<span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>', 130 esc_url( $customize_url ), 131 __( 'Live Preview' ), 132 /* translators: %s: Theme name. */ 133 sprintf( __( 'Live Preview “%s”' ), $name ) 134 ); 135 } 136 137 $install_actions['activate'] = sprintf( 138 '<a href="%s" class="activatelink">' . 139 '<span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>', 140 esc_url( $activate_link ), 141 __( 'Activate' ), 142 /* translators: %s: Theme name. */ 143 sprintf( _x( 'Activate “%s”', 'theme' ), $name ) 144 ); 145 146 if ( is_network_admin() && current_user_can( 'manage_network_themes' ) ) { 147 $install_actions['network_enable'] = sprintf( 148 '<a href="%s" target="_parent">%s</a>', 149 esc_url( wp_nonce_url( 'themes.php?action=enable&theme=' . urlencode( $stylesheet ), 'enable-theme_' . $stylesheet ) ), 150 __( 'Network Enable' ) 151 ); 152 } 153 154 if ( 'web' === $this->type ) { 155 $install_actions['themes_page'] = sprintf( 156 '<a href="%s" target="_parent">%s</a>', 157 self_admin_url( 'theme-install.php' ), 158 __( 'Go to Theme Installer' ) 159 ); 160 } elseif ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) ) { 161 $install_actions['themes_page'] = sprintf( 162 '<a href="%s" target="_parent">%s</a>', 163 self_admin_url( 'themes.php' ), 164 __( 'Go to Themes page' ) 165 ); 166 } 167 168 if ( ! $this->result || is_wp_error( $this->result ) || is_network_admin() || ! current_user_can( 'switch_themes' ) ) { 169 unset( $install_actions['activate'], $install_actions['preview'] ); 170 } elseif ( get_option( 'template' ) === $stylesheet ) { 171 unset( $install_actions['activate'] ); 172 } 173 174 /** 175 * Filters the list of action links available following a single theme installation. 176 * 177 * @since 2.8.0 178 * 179 * @param string[] $install_actions Array of theme action links. 180 * @param object $api Object containing WordPress.org API theme data. 181 * @param string $stylesheet Theme directory name. 182 * @param WP_Theme $theme_info Theme object. 183 */ 184 $install_actions = apply_filters( 'install_theme_complete_actions', $install_actions, $this->api, $stylesheet, $theme_info ); 185 if ( ! empty( $install_actions ) ) { 186 $this->feedback( implode( ' | ', (array) $install_actions ) ); 187 } 188 } 189 190 /** 191 * Check if the theme can be overwritten and output the HTML for overwriting a theme on upload. 192 * 193 * @since 5.5.0 194 * 195 * @return bool Whether the theme can be overwritten and HTML was outputted. 196 */ 197 private function do_overwrite() { 198 if ( 'upload' !== $this->type || ! is_wp_error( $this->result ) || 'folder_exists' !== $this->result->get_error_code() ) { 199 return false; 200 } 201 202 $folder = $this->result->get_error_data( 'folder_exists' ); 203 $folder = rtrim( $folder, '/' ); 204 205 $current_theme_data = false; 206 $all_themes = wp_get_themes( array( 'errors' => null ) ); 207 208 foreach ( $all_themes as $theme ) { 209 $stylesheet_dir = wp_normalize_path( $theme->get_stylesheet_directory() ); 210 211 if ( rtrim( $stylesheet_dir, '/' ) !== $folder ) { 212 continue; 213 } 214 215 $current_theme_data = $theme; 216 } 217 218 $new_theme_data = $this->upgrader->new_theme_data; 219 220 if ( ! $current_theme_data || ! $new_theme_data ) { 221 return false; 222 } 223 224 echo '<h2 class="update-from-upload-heading">' . esc_html__( 'This theme is already installed.' ) . '</h2>'; 225 226 // Check errors for active theme. 227 if ( is_wp_error( $current_theme_data->errors() ) ) { 228 $this->feedback( 'current_theme_has_errors', $current_theme_data->errors()->get_error_message() ); 229 } 230 231 $this->is_downgrading = version_compare( $current_theme_data['Version'], $new_theme_data['Version'], '>' ); 232 233 $is_invalid_parent = false; 234 if ( ! empty( $new_theme_data['Template'] ) ) { 235 $is_invalid_parent = ! in_array( $new_theme_data['Template'], array_keys( $all_themes ), true ); 236 } 237 238 $rows = array( 239 'Name' => __( 'Theme name' ), 240 'Version' => __( 'Version' ), 241 'Author' => __( 'Author' ), 242 'RequiresWP' => __( 'Required WordPress version' ), 243 'RequiresPHP' => __( 'Required PHP version' ), 244 'Template' => __( 'Parent theme' ), 245 ); 246 247 $table = '<table class="update-from-upload-comparison"><tbody>'; 248 $table .= '<tr><th></th><th>' . esc_html_x( 'Active', 'theme' ) . '</th><th>' . esc_html_x( 'Uploaded', 'theme' ) . '</th></tr>'; 249 250 $is_same_theme = true; // Let's consider only these rows. 251 252 foreach ( $rows as $field => $label ) { 253 $old_value = $current_theme_data->display( $field, false ); 254 $old_value = $old_value ? (string) $old_value : '-'; 255 256 $new_value = ! empty( $new_theme_data[ $field ] ) ? (string) $new_theme_data[ $field ] : '-'; 257 258 if ( $old_value === $new_value && '-' === $new_value && 'Template' === $field ) { 259 continue; 260 } 261 262 $is_same_theme = $is_same_theme && ( $old_value === $new_value ); 263 264 $diff_field = ( 'Version' !== $field && $new_value !== $old_value ); 265 $diff_version = ( 'Version' === $field && $this->is_downgrading ); 266 $invalid_parent = false; 267 268 if ( 'Template' === $field && $is_invalid_parent ) { 269 $invalid_parent = true; 270 $new_value .= ' ' . __( '(not found)' ); 271 } 272 273 $table .= '<tr><td class="name-label">' . $label . '</td><td>' . wp_strip_all_tags( $old_value ) . '</td>'; 274 $table .= ( $diff_field || $diff_version || $invalid_parent ) ? '<td class="warning">' : '<td>'; 275 $table .= wp_strip_all_tags( $new_value ) . '</td></tr>'; 276 } 277 278 $table .= '</tbody></table>'; 279 280 /** 281 * Filters the compare table output for overwriting a theme package on upload. 282 * 283 * @since 5.5.0 284 * 285 * @param string $table The output table with Name, Version, Author, RequiresWP, and RequiresPHP info. 286 * @param WP_Theme $current_theme_data Active theme data. 287 * @param array $new_theme_data Array with uploaded theme data. 288 */ 289 echo apply_filters( 'install_theme_overwrite_comparison', $table, $current_theme_data, $new_theme_data ); 290 291 $install_actions = array(); 292 $can_update = true; 293 294 $blocked_message = '<p>' . esc_html__( 'The theme cannot be updated due to the following:' ) . '</p>'; 295 $blocked_message .= '<ul class="ul-disc">'; 296 297 $requires_php = isset( $new_theme_data['RequiresPHP'] ) ? $new_theme_data['RequiresPHP'] : null; 298 $requires_wp = isset( $new_theme_data['RequiresWP'] ) ? $new_theme_data['RequiresWP'] : null; 299 300 if ( ! is_php_version_compatible( $requires_php ) ) { 301 $error = sprintf( 302 /* translators: 1: Current PHP version, 2: Version required by the uploaded theme. */ 303 __( 'The PHP version on your server is %1$s, however the uploaded theme requires %2$s.' ), 304 phpversion(), 305 $requires_php 306 ); 307 308 $blocked_message .= '<li>' . esc_html( $error ) . '</li>'; 309 $can_update = false; 310 } 311 312 if ( ! is_wp_version_compatible( $requires_wp ) ) { 313 $error = sprintf( 314 /* translators: 1: Current WordPress version, 2: Version required by the uploaded theme. */ 315 __( 'Your WordPress version is %1$s, however the uploaded theme requires %2$s.' ), 316 get_bloginfo( 'version' ), 317 $requires_wp 318 ); 319 320 $blocked_message .= '<li>' . esc_html( $error ) . '</li>'; 321 $can_update = false; 322 } 323 324 $blocked_message .= '</ul>'; 325 326 if ( $can_update ) { 327 if ( $this->is_downgrading ) { 328 $warning = sprintf( 329 /* translators: %s: Documentation URL. */ 330 __( 'You are uploading an older version of the active theme. You can continue to install the older version, but be sure to <a href="%s">back up your database and files</a> first.' ), 331 __( 'https://wordpress.org/support/article/wordpress-backups/' ) 332 ); 333 } else { 334 $warning = sprintf( 335 /* translators: %s: Documentation URL. */ 336 __( 'You are updating a theme. Be sure to <a href="%s">back up your database and files</a> first.' ), 337 __( 'https://wordpress.org/support/article/wordpress-backups/' ) 338 ); 339 } 340 341 echo '<p class="update-from-upload-notice">' . $warning . '</p>'; 342 343 $overwrite = $this->is_downgrading ? 'downgrade-theme' : 'update-theme'; 344 345 $install_actions['overwrite_theme'] = sprintf( 346 '<a class="button button-primary update-from-upload-overwrite" href="%s" target="_parent">%s</a>', 347 wp_nonce_url( add_query_arg( 'overwrite', $overwrite, $this->url ), 'theme-upload' ), 348 _x( 'Replace active with uploaded', 'theme' ) 349 ); 350 } else { 351 echo $blocked_message; 352 } 353 354 $cancel_url = add_query_arg( 'action', 'upload-theme-cancel-overwrite', $this->url ); 355 356 $install_actions['themes_page'] = sprintf( 357 '<a class="button" href="%s" target="_parent">%s</a>', 358 wp_nonce_url( $cancel_url, 'theme-upload-cancel-overwrite' ), 359 __( 'Cancel and go back' ) 360 ); 361 362 /** 363 * Filters the list of action links available following a single theme installation failure 364 * when overwriting is allowed. 365 * 366 * @since 5.5.0 367 * 368 * @param string[] $install_actions Array of theme action links. 369 * @param object $api Object containing WordPress.org API theme data. 370 * @param array $new_theme_data Array with uploaded theme data. 371 */ 372 $install_actions = apply_filters( 'install_theme_overwrite_actions', $install_actions, $this->api, $new_theme_data ); 373 374 if ( ! empty( $install_actions ) ) { 375 printf( 376 '<p class="update-from-upload-expired hidden">%s</p>', 377 __( 'The uploaded file has expired. Please go back and upload it again.' ) 378 ); 379 echo '<p class="update-from-upload-actions">' . implode( ' ', (array) $install_actions ) . '</p>'; 380 } 381 382 return true; 383 } 384 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Nov 21 01:00:03 2024 | Cross-referenced by PHPXref 0.7.1 |