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…' ), '<span class="code">%s</span>' ); |
59 $this->strings['downloading_package'] = sprintf( __( 'Downloading update from %s…' ), '<span class="code pre">%s</span>' ); |
60 $this->strings['unpack_package'] = __( 'Unpacking the update…' ); |
60 $this->strings['unpack_package'] = __( 'Unpacking the update…' ); |
61 $this->strings['remove_old'] = __( 'Removing the old version of the theme…' ); |
61 $this->strings['remove_old'] = __( 'Removing the old version of the theme…' ); |
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…' ), '<span class="code">%s</span>' ); |
75 $this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s…' ), '<span class="code pre">%s</span>' ); |
76 $this->strings['unpack_package'] = __( 'Unpacking the package…' ); |
76 $this->strings['unpack_package'] = __( 'Unpacking the package…' ); |
77 $this->strings['installing_package'] = __( 'Installing the theme…' ); |
77 $this->strings['installing_package'] = __( 'Installing the theme…' ); |
78 $this->strings['remove_old'] = __( 'Removing the old version of the theme…' ); |
78 $this->strings['remove_old'] = __( 'Removing the old version of the theme…' ); |
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.' ); |
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 } |