| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * WordPress Administration Update API 4 * 5 * @package WordPress 6 * @subpackage Administration 7 */ 8 9 /** 10 * Selects the first update version from the update_core option. 11 * 12 * @since 2.7.0 13 * 14 * @return object|array|false The response from the API on success, false on failure. 15 */ 16 function get_preferred_from_update_core() { 17 $updates = get_core_updates(); 18 19 if ( ! is_array( $updates ) ) { 20 return false; 21 } 22 23 if ( empty( $updates ) ) { 24 return (object) array( 'response' => 'latest' ); 25 } 26 27 return $updates[0]; 28 } 29 30 /** 31 * Gets available core updates. 32 * 33 * @since 2.7.0 34 * 35 * @param array $options Set $options['dismissed'] to true to show dismissed upgrades too, 36 * set $options['available'] to false to skip not-dismissed updates. 37 * @return array<object>|false Array of the update objects on success, false on failure. 38 */ 39 function get_core_updates( $options = array() ) { 40 $options = array_merge( 41 array( 42 'available' => true, 43 'dismissed' => false, 44 ), 45 $options 46 ); 47 48 $dismissed = get_site_option( 'dismissed_update_core' ); 49 50 if ( ! is_array( $dismissed ) ) { 51 $dismissed = array(); 52 } 53 54 $from_api = get_site_transient( 'update_core' ); 55 56 if ( ! isset( $from_api->updates ) || ! is_array( $from_api->updates ) ) { 57 return false; 58 } 59 60 $updates = $from_api->updates; 61 $result = array(); 62 63 foreach ( $updates as $update ) { 64 if ( 'autoupdate' === $update->response ) { 65 continue; 66 } 67 68 if ( array_key_exists( $update->current . '|' . $update->locale, $dismissed ) ) { 69 if ( $options['dismissed'] ) { 70 $update->dismissed = true; 71 $result[] = $update; 72 } 73 } else { 74 if ( $options['available'] ) { 75 $update->dismissed = false; 76 $result[] = $update; 77 } 78 } 79 } 80 81 return $result; 82 } 83 84 /** 85 * Gets the best available (and enabled) Auto-Update for WordPress core. 86 * 87 * If there's 1.2.3 and 1.3 on offer, it'll choose 1.3 if the installation allows it, else, 1.2.3. 88 * 89 * @since 3.7.0 90 * 91 * @return object|false The core update offering on success, false on failure. 92 */ 93 function find_core_auto_update() { 94 $updates = get_site_transient( 'update_core' ); 95 96 if ( ! $updates || empty( $updates->updates ) ) { 97 return false; 98 } 99 100 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; 101 102 $auto_update = false; 103 $upgrader = new WP_Automatic_Updater(); 104 105 foreach ( $updates->updates as $update ) { 106 if ( 'autoupdate' !== $update->response ) { 107 continue; 108 } 109 110 if ( ! $upgrader->should_update( 'core', $update, ABSPATH ) ) { 111 continue; 112 } 113 114 if ( ! $auto_update || version_compare( $update->current, $auto_update->current, '>' ) ) { 115 $auto_update = $update; 116 } 117 } 118 119 return $auto_update; 120 } 121 122 /** 123 * Gets and caches the checksums for the given version of WordPress. 124 * 125 * @since 3.7.0 126 * 127 * @param string $version Version string to query. 128 * @param string $locale Locale to query. 129 * @return array<string, string>|false An array of checksums on success, false on failure. 130 */ 131 function get_core_checksums( $version, $locale ) { 132 $http_url = 'http://api.wordpress.org/core/checksums/1.0/?' . http_build_query( compact( 'version', 'locale' ), '', '&' ); 133 $url = $http_url; 134 135 $ssl = wp_http_supports( array( 'ssl' ) ); 136 137 if ( $ssl ) { 138 $url = set_url_scheme( $url, 'https' ); 139 } 140 141 $options = array( 142 'timeout' => wp_doing_cron() ? 30 : 3, 143 ); 144 145 $response = wp_remote_get( $url, $options ); 146 147 if ( $ssl && is_wp_error( $response ) ) { 148 wp_trigger_error( 149 __FUNCTION__, 150 sprintf( 151 /* translators: %s: Support forums URL. */ 152 __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ), 153 __( 'https://wordpress.org/support/forums/' ) 154 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), 155 headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE 156 ); 157 158 $response = wp_remote_get( $http_url, $options ); 159 } 160 161 if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { 162 return false; 163 } 164 165 $body = trim( wp_remote_retrieve_body( $response ) ); 166 $body = json_decode( $body, true ); 167 168 if ( ! is_array( $body ) || ! isset( $body['checksums'] ) || ! is_array( $body['checksums'] ) ) { 169 return false; 170 } 171 172 return $body['checksums']; 173 } 174 175 /** 176 * Dismisses core update. 177 * 178 * @since 2.7.0 179 * 180 * @param object $update 181 * @return bool True if the option was updated, false otherwise. 182 */ 183 function dismiss_core_update( $update ) { 184 $dismissed = get_site_option( 'dismissed_update_core' ); 185 $dismissed[ $update->current . '|' . $update->locale ] = true; 186 187 return update_site_option( 'dismissed_update_core', $dismissed ); 188 } 189 190 /** 191 * Undismisses core update. 192 * 193 * @since 2.7.0 194 * 195 * @param string $version 196 * @param string $locale 197 * @return bool True if the option was updated, false otherwise. 198 */ 199 function undismiss_core_update( $version, $locale ) { 200 $dismissed = get_site_option( 'dismissed_update_core' ); 201 $key = $version . '|' . $locale; 202 203 if ( ! isset( $dismissed[ $key ] ) ) { 204 return false; 205 } 206 207 unset( $dismissed[ $key ] ); 208 209 return update_site_option( 'dismissed_update_core', $dismissed ); 210 } 211 212 /** 213 * Finds the available update for WordPress core. 214 * 215 * @since 2.7.0 216 * 217 * @param string $version Version string to find the update for. 218 * @param string $locale Locale to find the update for. 219 * @return object|false The core update offering on success, false on failure. 220 */ 221 function find_core_update( $version, $locale ) { 222 $from_api = get_site_transient( 'update_core' ); 223 224 if ( ! isset( $from_api->updates ) || ! is_array( $from_api->updates ) ) { 225 return false; 226 } 227 228 $updates = $from_api->updates; 229 230 foreach ( $updates as $update ) { 231 if ( $update->current === $version && $update->locale === $locale ) { 232 return $update; 233 } 234 } 235 236 return false; 237 } 238 239 /** 240 * Returns core update footer message. 241 * 242 * @since 2.3.0 243 * 244 * @param string $msg 245 * @return string The core update footer message. 246 */ 247 function core_update_footer( $msg = '' ) { 248 if ( ! current_user_can( 'update_core' ) ) { 249 /* translators: %s: WordPress version. */ 250 return sprintf( __( 'Version %s' ), get_bloginfo( 'version', 'display' ) ); 251 } 252 253 $cur = get_preferred_from_update_core(); 254 255 if ( ! is_object( $cur ) ) { 256 $cur = new stdClass(); 257 } 258 259 if ( ! isset( $cur->current ) ) { 260 $cur->current = ''; 261 } 262 263 if ( ! isset( $cur->response ) ) { 264 $cur->response = ''; 265 } 266 267 $is_development_version = preg_match( '/alpha|beta|RC/', wp_get_wp_version() ); 268 269 if ( $is_development_version ) { 270 return sprintf( 271 /* translators: 1: WordPress version number, 2: URL to WordPress Updates screen. */ 272 __( 'You are using a development version (%1$s). Cool! Please <a href="%2$s">stay updated</a>.' ), 273 get_bloginfo( 'version', 'display' ), 274 network_admin_url( 'update-core.php' ) 275 ); 276 } 277 278 switch ( $cur->response ) { 279 case 'upgrade': 280 return sprintf( 281 '<strong><a href="%s">%s</a></strong>', 282 network_admin_url( 'update-core.php' ), 283 /* translators: %s: WordPress version. */ 284 sprintf( __( 'Get Version %s' ), $cur->current ) 285 ); 286 287 case 'latest': 288 default: 289 /* translators: %s: WordPress version. */ 290 return sprintf( __( 'Version %s' ), get_bloginfo( 'version', 'display' ) ); 291 } 292 } 293 294 /** 295 * Returns core update notification message. 296 * 297 * @since 2.3.0 298 * 299 * @global string $pagenow The filename of the current screen. 300 * @return void|false Void on success, false if the update nag should not be displayed. 301 */ 302 function update_nag() { 303 global $pagenow; 304 305 if ( is_multisite() && ! current_user_can( 'update_core' ) ) { 306 return false; 307 } 308 309 if ( 'update-core.php' === $pagenow ) { 310 return; 311 } 312 313 $cur = get_preferred_from_update_core(); 314 315 if ( ! isset( $cur->response ) || 'upgrade' !== $cur->response ) { 316 return false; 317 } 318 319 $version_url = sprintf( 320 /* translators: %s: WordPress version. */ 321 esc_url( __( 'https://wordpress.org/documentation/wordpress-version/version-%s/' ) ), 322 sanitize_title( $cur->current ) 323 ); 324 325 if ( current_user_can( 'update_core' ) ) { 326 $msg = sprintf( 327 /* translators: 1: URL to WordPress release notes, 2: New WordPress version, 3: URL to network admin, 4: Accessibility text. */ 328 __( '<a href="%1$s">WordPress %2$s</a> is available! <a href="%3$s" aria-label="%4$s">Please update now</a>.' ), 329 $version_url, 330 $cur->current, 331 network_admin_url( 'update-core.php' ), 332 esc_attr__( 'Please update WordPress now' ) 333 ); 334 } else { 335 $msg = sprintf( 336 /* translators: 1: URL to WordPress release notes, 2: New WordPress version. */ 337 __( '<a href="%1$s">WordPress %2$s</a> is available! Please notify the site administrator.' ), 338 $version_url, 339 $cur->current 340 ); 341 } 342 343 wp_admin_notice( 344 $msg, 345 array( 346 'type' => 'warning', 347 'additional_classes' => array( 'update-nag', 'inline' ), 348 'paragraph_wrap' => false, 349 ) 350 ); 351 } 352 353 /** 354 * Displays WordPress version and active theme in the 'At a Glance' dashboard widget. 355 * 356 * @since 2.5.0 357 */ 358 function update_right_now_message() { 359 $theme_name = wp_get_theme(); 360 361 if ( current_user_can( 'switch_themes' ) ) { 362 $theme_name = sprintf( '<a href="themes.php">%1$s</a>', $theme_name ); 363 } 364 365 /* translators: 1: Version number, 2: Theme name. */ 366 $content = __( 'WordPress %1$s running %2$s theme.' ); 367 368 /** 369 * Filters the text displayed in the 'At a Glance' dashboard widget. 370 * 371 * Prior to 3.8.0, the widget was named 'Right Now'. 372 * 373 * @since 4.4.0 374 * 375 * @param string $content Default text. 376 */ 377 $content = apply_filters( 'update_right_now_text', $content ); 378 379 $msg = sprintf( '<span id="wp-version">' . $content . '</span>', get_bloginfo( 'version', 'display' ), $theme_name ); 380 381 if ( current_user_can( 'update_core' ) ) { 382 $cur = get_preferred_from_update_core(); 383 384 if ( isset( $cur->response ) && 'upgrade' === $cur->response ) { 385 $msg .= sprintf( 386 '<a href="%s" class="button" aria-describedby="wp-version">%s</a>', 387 network_admin_url( 'update-core.php' ), 388 /* translators: %s: WordPress version number, or 'Latest' string. */ 389 sprintf( __( 'Update to %s' ), $cur->current ? $cur->current : __( 'Latest' ) ) 390 ); 391 } 392 } 393 394 echo "<p id='wp-version-message'>$msg</p>"; 395 } 396 397 /** 398 * Retrieves plugins with updates available. 399 * 400 * @since 2.9.0 401 * 402 * @return array<string, object> Array of plugin objects with available updates. 403 */ 404 function get_plugin_updates() { 405 $all_plugins = get_plugins(); 406 $upgrade_plugins = array(); 407 $current = get_site_transient( 'update_plugins' ); 408 409 foreach ( (array) $all_plugins as $plugin_file => $plugin_data ) { 410 if ( isset( $current->response[ $plugin_file ] ) ) { 411 $upgrade_plugins[ $plugin_file ] = (object) $plugin_data; 412 $upgrade_plugins[ $plugin_file ]->update = $current->response[ $plugin_file ]; 413 } 414 } 415 416 return $upgrade_plugins; 417 } 418 419 /** 420 * Adds a callback to display update information for plugins with updates available. 421 * 422 * @since 2.9.0 423 */ 424 function wp_plugin_update_rows() { 425 if ( ! current_user_can( 'update_plugins' ) ) { 426 return; 427 } 428 429 $plugins = get_site_transient( 'update_plugins' ); 430 431 if ( isset( $plugins->response ) && is_array( $plugins->response ) ) { 432 $plugins = array_keys( $plugins->response ); 433 434 foreach ( $plugins as $plugin_file ) { 435 add_action( "after_plugin_row_{$plugin_file}", 'wp_plugin_update_row', 10, 2 ); 436 } 437 } 438 } 439 440 /** 441 * Displays update information for a plugin. 442 * 443 * @since 2.3.0 444 * 445 * @param string $file Plugin basename. 446 * @param array $plugin_data Plugin information. 447 * @return void|false Void on success, false if the plugin update is not available. 448 */ 449 function wp_plugin_update_row( $file, $plugin_data ) { 450 $current = get_site_transient( 'update_plugins' ); 451 452 if ( ! isset( $current->response[ $file ] ) ) { 453 return false; 454 } 455 456 $response = $current->response[ $file ]; 457 458 $plugins_allowedtags = array( 459 'a' => array( 460 'href' => array(), 461 'title' => array(), 462 ), 463 'abbr' => array( 'title' => array() ), 464 'acronym' => array( 'title' => array() ), 465 'code' => array(), 466 'em' => array(), 467 'strong' => array(), 468 ); 469 470 $plugin_name = wp_kses( $plugin_data['Name'], $plugins_allowedtags ); 471 $plugin_slug = $response->slug ?? $response->id; 472 473 if ( isset( $response->slug ) ) { 474 $details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $plugin_slug . '§ion=changelog' ); 475 } elseif ( isset( $response->url ) ) { 476 $details_url = $response->url; 477 } else { 478 $details_url = $plugin_data['PluginURI']; 479 } 480 481 $details_url = add_query_arg( 482 array( 483 'TB_iframe' => 'true', 484 'width' => 600, 485 'height' => 800, 486 ), 487 $details_url 488 ); 489 490 /** @var WP_Plugins_List_Table $wp_list_table */ 491 $wp_list_table = _get_list_table( 492 'WP_Plugins_List_Table', 493 array( 494 'screen' => get_current_screen(), 495 ) 496 ); 497 498 if ( is_network_admin() || ! is_multisite() ) { 499 if ( is_network_admin() ) { 500 $active_class = is_plugin_active_for_network( $file ) ? ' active' : ''; 501 } else { 502 $active_class = is_plugin_active( $file ) ? ' active' : ''; 503 } 504 505 $requires_php = $response->requires_php ?? null; 506 $compatible_php = is_php_version_compatible( $requires_php ); 507 $notice_type = $compatible_php ? 'notice-warning' : 'notice-error'; 508 509 printf( 510 '<tr class="plugin-update-tr%s" id="%s" data-slug="%s" data-plugin="%s">' . 511 '<td colspan="%s" class="plugin-update colspanchange">' . 512 '<div class="update-message notice inline %s notice-alt"><p>', 513 $active_class, 514 esc_attr( $plugin_slug . '-update' ), 515 esc_attr( $plugin_slug ), 516 esc_attr( $file ), 517 esc_attr( $wp_list_table->get_column_count() ), 518 $notice_type 519 ); 520 521 if ( ! current_user_can( 'update_plugins' ) ) { 522 printf( 523 /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number. */ 524 __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>.' ), 525 $plugin_name, 526 esc_url( $details_url ), 527 sprintf( 528 'class="thickbox open-plugin-details-modal" aria-label="%s"', 529 /* translators: 1: Plugin name, 2: Version number. */ 530 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) ) 531 ), 532 esc_attr( $response->new_version ) 533 ); 534 } elseif ( empty( $response->package ) ) { 535 printf( 536 /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number. */ 537 __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>. <em>Automatic update is unavailable for this plugin.</em>' ), 538 $plugin_name, 539 esc_url( $details_url ), 540 sprintf( 541 'class="thickbox open-plugin-details-modal" aria-label="%s"', 542 /* translators: 1: Plugin name, 2: Version number. */ 543 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) ) 544 ), 545 esc_attr( $response->new_version ) 546 ); 547 } else { 548 if ( $compatible_php ) { 549 printf( 550 /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */ 551 __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a> or <a href="%5$s" %6$s>update now</a>.' ), 552 $plugin_name, 553 esc_url( $details_url ), 554 sprintf( 555 'class="thickbox open-plugin-details-modal" aria-label="%s"', 556 /* translators: 1: Plugin name, 2: Version number. */ 557 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) ) 558 ), 559 esc_attr( $response->new_version ), 560 wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $file, 'upgrade-plugin_' . $file ), 561 sprintf( 562 'class="update-link" aria-label="%s"', 563 /* translators: %s: Plugin name. */ 564 esc_attr( sprintf( _x( 'Update %s now', 'plugin' ), $plugin_name ) ) 565 ) 566 ); 567 } else { 568 printf( 569 /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number 5: URL to Update PHP page. */ 570 __( 'There is a new version of %1$s available, but it does not work with your version of PHP. <a href="%2$s" %3$s>View version %4$s details</a> or <a href="%5$s">learn more about updating PHP</a>.' ), 571 $plugin_name, 572 esc_url( $details_url ), 573 sprintf( 574 'class="thickbox open-plugin-details-modal" aria-label="%s"', 575 /* translators: 1: Plugin name, 2: Version number. */ 576 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) ) 577 ), 578 esc_attr( $response->new_version ), 579 esc_url( wp_get_update_php_url() ) 580 ); 581 wp_update_php_annotation( '<br><em>', '</em>' ); 582 } 583 } 584 585 /** 586 * Fires at the end of the update message container in each 587 * row of the plugins list table. 588 * 589 * The dynamic portion of the hook name, `$file`, refers to the path 590 * of the plugin's primary file relative to the plugins directory. 591 * 592 * @since 2.8.0 593 * 594 * @param array $plugin_data An array of plugin metadata. See get_plugin_data() 595 * and the {@see 'plugin_row_meta'} filter for the list 596 * of possible values. 597 * @param object $response { 598 * An object of metadata about the available plugin update. 599 * 600 * @type string $id Plugin ID, e.g. `w.org/plugins/[plugin-name]`. 601 * @type string $slug Plugin slug. 602 * @type string $plugin Plugin basename. 603 * @type string $new_version New plugin version. 604 * @type string $url Plugin URL. 605 * @type string $package Plugin update package URL. 606 * @type string[] $icons An array of plugin icon URLs. 607 * @type string[] $banners An array of plugin banner URLs. 608 * @type string[] $banners_rtl An array of plugin RTL banner URLs. 609 * @type string $requires The version of WordPress which the plugin requires. 610 * @type string $tested The version of WordPress the plugin is tested against. 611 * @type string $requires_php The version of PHP which the plugin requires. 612 * } 613 */ 614 do_action( "in_plugin_update_message-{$file}", $plugin_data, $response ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores 615 616 echo '</p></div></td></tr>'; 617 } 618 } 619 620 /** 621 * Retrieves themes with updates available. 622 * 623 * @since 2.9.0 624 * 625 * @return array<string, WP_Theme> Array of theme objects with available updates. 626 */ 627 function get_theme_updates() { 628 $current = get_site_transient( 'update_themes' ); 629 630 if ( ! isset( $current->response ) ) { 631 return array(); 632 } 633 634 $update_themes = array(); 635 636 foreach ( $current->response as $stylesheet => $data ) { 637 $update_themes[ $stylesheet ] = wp_get_theme( $stylesheet ); 638 $update_themes[ $stylesheet ]->update = $data; 639 } 640 641 return $update_themes; 642 } 643 644 /** 645 * Adds a callback to display update information for themes with updates available. 646 * 647 * @since 3.1.0 648 */ 649 function wp_theme_update_rows() { 650 if ( ! current_user_can( 'update_themes' ) ) { 651 return; 652 } 653 654 $themes = get_site_transient( 'update_themes' ); 655 656 if ( isset( $themes->response ) && is_array( $themes->response ) ) { 657 $themes = array_keys( $themes->response ); 658 659 foreach ( $themes as $theme ) { 660 add_action( "after_theme_row_{$theme}", 'wp_theme_update_row', 10, 2 ); 661 } 662 } 663 } 664 665 /** 666 * Displays update information for a theme. 667 * 668 * @since 3.1.0 669 * 670 * @param string $theme_key Theme stylesheet. 671 * @param WP_Theme $theme Theme object. 672 * @return void|false Void on success, false if the theme update is not available. 673 */ 674 function wp_theme_update_row( $theme_key, $theme ) { 675 $current = get_site_transient( 'update_themes' ); 676 677 if ( ! isset( $current->response[ $theme_key ] ) ) { 678 return false; 679 } 680 681 $response = $current->response[ $theme_key ]; 682 683 $details_url = add_query_arg( 684 array( 685 'TB_iframe' => 'true', 686 'width' => 1024, 687 'height' => 800, 688 ), 689 $current->response[ $theme_key ]['url'] 690 ); 691 692 /** @var WP_MS_Themes_List_Table $wp_list_table */ 693 $wp_list_table = _get_list_table( 'WP_MS_Themes_List_Table' ); 694 695 $active = $theme->is_allowed( 'network' ) ? ' active' : ''; 696 697 $requires_wp = $response['requires'] ?? null; 698 $requires_php = $response['requires_php'] ?? null; 699 700 $compatible_wp = is_wp_version_compatible( $requires_wp ); 701 $compatible_php = is_php_version_compatible( $requires_php ); 702 703 printf( 704 '<tr class="plugin-update-tr%s" id="%s" data-slug="%s">' . 705 '<td colspan="%s" class="plugin-update colspanchange">' . 706 '<div class="update-message notice inline notice-warning notice-alt"><p>', 707 $active, 708 esc_attr( $theme->get_stylesheet() . '-update' ), 709 esc_attr( $theme->get_stylesheet() ), 710 $wp_list_table->get_column_count() 711 ); 712 713 if ( $compatible_wp && $compatible_php ) { 714 if ( ! current_user_can( 'update_themes' ) ) { 715 printf( 716 /* translators: 1: Theme name, 2: Details URL, 3: Additional link attributes, 4: Version number. */ 717 __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>.' ), 718 $theme['Name'], 719 esc_url( $details_url ), 720 sprintf( 721 'class="thickbox open-plugin-details-modal" aria-label="%s"', 722 /* translators: 1: Theme name, 2: Version number. */ 723 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) ) 724 ), 725 $response['new_version'] 726 ); 727 } elseif ( empty( $response['package'] ) ) { 728 printf( 729 /* translators: 1: Theme name, 2: Details URL, 3: Additional link attributes, 4: Version number. */ 730 __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ), 731 $theme['Name'], 732 esc_url( $details_url ), 733 sprintf( 734 'class="thickbox open-plugin-details-modal" aria-label="%s"', 735 /* translators: 1: Theme name, 2: Version number. */ 736 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) ) 737 ), 738 $response['new_version'] 739 ); 740 } else { 741 printf( 742 /* translators: 1: Theme name, 2: Details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */ 743 __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a> or <a href="%5$s" %6$s>update now</a>.' ), 744 $theme['Name'], 745 esc_url( $details_url ), 746 sprintf( 747 'class="thickbox open-plugin-details-modal" aria-label="%s"', 748 /* translators: 1: Theme name, 2: Version number. */ 749 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) ) 750 ), 751 $response['new_version'], 752 wp_nonce_url( self_admin_url( 'update.php?action=upgrade-theme&theme=' ) . $theme_key, 'upgrade-theme_' . $theme_key ), 753 sprintf( 754 'class="update-link" aria-label="%s"', 755 /* translators: %s: Theme name. */ 756 esc_attr( sprintf( _x( 'Update %s now', 'theme' ), $theme['Name'] ) ) 757 ) 758 ); 759 } 760 } else { 761 if ( ! $compatible_wp && ! $compatible_php ) { 762 printf( 763 /* translators: %s: Theme name. */ 764 __( 'There is a new version of %s available, but it does not work with your versions of WordPress and PHP.' ), 765 $theme['Name'] 766 ); 767 if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) { 768 printf( 769 /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */ 770 ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ), 771 self_admin_url( 'update-core.php' ), 772 esc_url( wp_get_update_php_url() ) 773 ); 774 wp_update_php_annotation( '</p><p><em>', '</em>' ); 775 } elseif ( current_user_can( 'update_core' ) ) { 776 printf( 777 /* translators: %s: URL to WordPress Updates screen. */ 778 ' ' . __( '<a href="%s">Please update WordPress</a>.' ), 779 self_admin_url( 'update-core.php' ) 780 ); 781 } elseif ( current_user_can( 'update_php' ) ) { 782 printf( 783 /* translators: %s: URL to Update PHP page. */ 784 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ), 785 esc_url( wp_get_update_php_url() ) 786 ); 787 wp_update_php_annotation( '</p><p><em>', '</em>' ); 788 } 789 } elseif ( ! $compatible_wp ) { 790 printf( 791 /* translators: %s: Theme name. */ 792 __( 'There is a new version of %s available, but it does not work with your version of WordPress.' ), 793 $theme['Name'] 794 ); 795 if ( current_user_can( 'update_core' ) ) { 796 printf( 797 /* translators: %s: URL to WordPress Updates screen. */ 798 ' ' . __( '<a href="%s">Please update WordPress</a>.' ), 799 self_admin_url( 'update-core.php' ) 800 ); 801 } 802 } elseif ( ! $compatible_php ) { 803 printf( 804 /* translators: %s: Theme name. */ 805 __( 'There is a new version of %s available, but it does not work with your version of PHP.' ), 806 $theme['Name'] 807 ); 808 if ( current_user_can( 'update_php' ) ) { 809 printf( 810 /* translators: %s: URL to Update PHP page. */ 811 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ), 812 esc_url( wp_get_update_php_url() ) 813 ); 814 wp_update_php_annotation( '</p><p><em>', '</em>' ); 815 } 816 } 817 } 818 819 /** 820 * Fires at the end of the update message container in each 821 * row of the themes list table. 822 * 823 * The dynamic portion of the hook name, `$theme_key`, refers to 824 * the theme slug as found in the WordPress.org themes repository. 825 * 826 * @since 3.1.0 827 * 828 * @param WP_Theme $theme The WP_Theme object. 829 * @param array $response { 830 * An array of metadata about the available theme update. 831 * 832 * @type string $new_version New theme version. 833 * @type string $url Theme URL. 834 * @type string $package Theme update package URL. 835 * } 836 */ 837 do_action( "in_theme_update_message-{$theme_key}", $theme, $response ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores 838 839 echo '</p></div></td></tr>'; 840 } 841 842 /** 843 * Displays maintenance nag HTML message. 844 * 845 * @since 2.7.0 846 * 847 * @global int $upgrading 848 * 849 * @return void|false Void on success, false if the maintenance nag should not be displayed. 850 */ 851 function maintenance_nag() { 852 global $upgrading; 853 854 $nag = isset( $upgrading ); 855 856 if ( ! $nag ) { 857 $failed = get_site_option( 'auto_core_update_failed' ); 858 /* 859 * If an update failed critically, we may have copied over version.php but not other files. 860 * In that case, if the installation claims we're running the version we attempted, nag. 861 * This is serious enough to err on the side of nagging. 862 * 863 * If we simply failed to update before we tried to copy any files, then assume things are 864 * OK if they are now running the latest. 865 * 866 * This flag is cleared whenever a successful update occurs using Core_Upgrader. 867 */ 868 $comparison = ! empty( $failed['critical'] ) ? '>=' : '>'; 869 if ( isset( $failed['attempted'] ) && version_compare( $failed['attempted'], wp_get_wp_version(), $comparison ) ) { 870 $nag = true; 871 } 872 } 873 874 if ( ! $nag ) { 875 return false; 876 } 877 878 if ( current_user_can( 'update_core' ) ) { 879 $msg = sprintf( 880 /* translators: %s: URL to WordPress Updates screen. */ 881 __( 'An automated WordPress update has failed to complete - <a href="%s">please attempt the update again now</a>.' ), 882 'update-core.php' 883 ); 884 } else { 885 $msg = __( 'An automated WordPress update has failed to complete! Please notify the site administrator.' ); 886 } 887 888 wp_admin_notice( 889 $msg, 890 array( 891 'type' => 'warning', 892 'additional_classes' => array( 'update-nag', 'inline' ), 893 'paragraph_wrap' => false, 894 ) 895 ); 896 } 897 898 /** 899 * Prints the JavaScript templates for update admin notices. 900 * 901 * @since 4.6.0 902 * 903 * Template takes one argument with four values: 904 * 905 * param {object} data { 906 * Arguments for admin notice. 907 * 908 * @type string id ID of the notice. 909 * @type string className Class names for the notice. 910 * @type string message The notice's message. 911 * @type string type The type of update the notice is for. Either 'plugin' or 'theme'. 912 * } 913 */ 914 function wp_print_admin_notice_templates() { 915 ?> 916 <script id="tmpl-wp-updates-admin-notice" type="text/html"> 917 <div <# if ( data.id ) { #>id="{{ data.id }}"<# } #> class="notice {{ data.className }}"><p>{{{ data.message }}}</p></div> 918 </script> 919 <script id="tmpl-wp-bulk-updates-admin-notice" type="text/html"> 920 <div id="{{ data.id }}" class="{{ data.className }} notice <# if ( data.errorMessage ) { #>notice-error<# } else { #>notice-success<# } #>"> 921 <p> 922 <# if ( data.successMessage ) { #> 923 {{{ data.successMessage }}} 924 <# } #> 925 <# if ( data.errorMessage ) { #> 926 <button class="button-link bulk-action-errors-collapsed" aria-expanded="false"> 927 {{{ data.errorMessage }}} 928 <span class="screen-reader-text"> 929 <?php 930 /* translators: Hidden accessibility text. */ 931 _e( 'Show more details' ); 932 ?> 933 </span> 934 <span class="toggle-indicator" aria-hidden="true"></span> 935 </button> 936 <# } #> 937 </p> 938 <# if ( data.errorMessages ) { #> 939 <ul class="bulk-action-errors hidden"> 940 <# _.each( data.errorMessages, function( errorMessage ) { #> 941 <li>{{ errorMessage }}</li> 942 <# } ); #> 943 </ul> 944 <# } #> 945 </div> 946 </script> 947 <?php 948 } 949 950 /** 951 * Prints the JavaScript templates for update and deletion rows in list tables. 952 * 953 * @since 4.6.0 954 * 955 * The update template takes one argument with four values: 956 * 957 * param {object} data { 958 * Arguments for the update row 959 * 960 * @type string slug Plugin slug. 961 * @type string plugin Plugin base name. 962 * @type string colspan The number of table columns this row spans. 963 * @type string content The row content. 964 * } 965 * 966 * The delete template takes one argument with four values: 967 * 968 * param {object} data { 969 * Arguments for the update row 970 * 971 * @type string slug Plugin slug. 972 * @type string plugin Plugin base name. 973 * @type string name Plugin name. 974 * @type string colspan The number of table columns this row spans. 975 * } 976 */ 977 function wp_print_update_row_templates() { 978 ?> 979 <script id="tmpl-item-update-row" type="text/template"> 980 <tr class="plugin-update-tr update" id="{{ data.slug }}-update" data-slug="{{ data.slug }}" <# if ( data.plugin ) { #>data-plugin="{{ data.plugin }}"<# } #>> 981 <td colspan="{{ data.colspan }}" class="plugin-update colspanchange"> 982 {{{ data.content }}} 983 </td> 984 </tr> 985 </script> 986 <script id="tmpl-item-deleted-row" type="text/template"> 987 <tr class="plugin-deleted-tr inactive deleted" id="{{ data.slug }}-deleted" data-slug="{{ data.slug }}" <# if ( data.plugin ) { #>data-plugin="{{ data.plugin }}"<# } #>> 988 <td colspan="{{ data.colspan }}" class="plugin-update colspanchange"> 989 <# if ( data.plugin ) { #> 990 <?php 991 printf( 992 /* translators: %s: Plugin name. */ 993 _x( '%s was successfully deleted.', 'plugin' ), 994 '<strong>{{{ data.name }}}</strong>' 995 ); 996 ?> 997 <# } else { #> 998 <?php 999 printf( 1000 /* translators: %s: Theme name. */ 1001 _x( '%s was successfully deleted.', 'theme' ), 1002 '<strong>{{{ data.name }}}</strong>' 1003 ); 1004 ?> 1005 <# } #> 1006 </td> 1007 </tr> 1008 </script> 1009 <?php 1010 } 1011 1012 /** 1013 * Displays a notice when the user is in recovery mode. 1014 * 1015 * @since 5.2.0 1016 */ 1017 function wp_recovery_mode_nag() { 1018 if ( ! wp_is_recovery_mode() ) { 1019 return; 1020 } 1021 1022 $url = wp_login_url(); 1023 $url = add_query_arg( 'action', WP_Recovery_Mode::EXIT_ACTION, $url ); 1024 $url = wp_nonce_url( $url, WP_Recovery_Mode::EXIT_ACTION ); 1025 1026 $message = sprintf( 1027 /* translators: %s: Recovery Mode exit link. */ 1028 __( 'You are in recovery mode. This means there may be an error with a theme or plugin. To exit recovery mode, log out or use the Exit button. <a href="%s">Exit Recovery Mode</a>' ), 1029 esc_url( $url ) 1030 ); 1031 wp_admin_notice( $message, array( 'type' => 'info' ) ); 1032 } 1033 1034 /** 1035 * Checks whether auto-updates are enabled. 1036 * 1037 * @since 5.5.0 1038 * 1039 * @param string $type The type of update being checked: Either 'theme' or 'plugin'. 1040 * @return bool True if auto-updates are enabled for `$type`, false otherwise. 1041 */ 1042 function wp_is_auto_update_enabled_for_type( $type ) { 1043 if ( ! class_exists( 'WP_Automatic_Updater' ) ) { 1044 require_once ABSPATH . 'wp-admin/includes/class-wp-automatic-updater.php'; 1045 } 1046 1047 $updater = new WP_Automatic_Updater(); 1048 $enabled = ! $updater->is_disabled(); 1049 1050 switch ( $type ) { 1051 case 'plugin': 1052 /** 1053 * Filters whether plugins auto-update is enabled. 1054 * 1055 * @since 5.5.0 1056 * 1057 * @param bool $enabled True if plugins auto-update is enabled, false otherwise. 1058 */ 1059 return apply_filters( 'plugins_auto_update_enabled', $enabled ); 1060 case 'theme': 1061 /** 1062 * Filters whether themes auto-update is enabled. 1063 * 1064 * @since 5.5.0 1065 * 1066 * @param bool $enabled True if themes auto-update is enabled, false otherwise. 1067 */ 1068 return apply_filters( 'themes_auto_update_enabled', $enabled ); 1069 } 1070 1071 return false; 1072 } 1073 1074 /** 1075 * Checks whether auto-updates are forced for an item. 1076 * 1077 * @since 5.6.0 1078 * 1079 * @param string $type The type of update being checked: Either 'theme' or 'plugin'. 1080 * @param bool|null $update Whether to update. The value of null is internally used 1081 * to detect whether nothing has hooked into this filter. 1082 * @param object $item The update offer. 1083 * @return bool True if auto-updates are forced for `$item`, false otherwise. 1084 */ 1085 function wp_is_auto_update_forced_for_item( $type, $update, $item ) { 1086 /** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */ 1087 return apply_filters( "auto_update_{$type}", $update, $item ); 1088 } 1089 1090 /** 1091 * Determines the appropriate auto-update message to be displayed. 1092 * 1093 * @since 5.5.0 1094 * 1095 * @return string The update message to be shown. 1096 */ 1097 function wp_get_auto_update_message() { 1098 $next_update_time = wp_next_scheduled( 'wp_version_check' ); 1099 1100 // Check if the event exists. 1101 if ( false === $next_update_time ) { 1102 $message = __( 'Automatic update not scheduled. There may be a problem with WP-Cron.' ); 1103 } else { 1104 $time_to_next_update = human_time_diff( (int) $next_update_time ); 1105 1106 // See if cron is overdue. 1107 $overdue = ( time() - $next_update_time ) > 0; 1108 1109 if ( $overdue ) { 1110 $message = sprintf( 1111 /* translators: %s: Duration that WP-Cron has been overdue. */ 1112 __( 'Automatic update overdue by %s. There may be a problem with WP-Cron.' ), 1113 $time_to_next_update 1114 ); 1115 } else { 1116 $message = sprintf( 1117 /* translators: %s: Time until the next update. */ 1118 __( 'Automatic update scheduled in %s.' ), 1119 $time_to_next_update 1120 ); 1121 } 1122 } 1123 1124 return $message; 1125 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Fri Jul 31 08:20:18 2026 | Cross-referenced by PHPXref |