19 * @global string $wp_version Used to check against the newest WordPress version. |
19 * @global string $wp_version Used to check against the newest WordPress version. |
20 * @global wpdb $wpdb WordPress database abstraction object. |
20 * @global wpdb $wpdb WordPress database abstraction object. |
21 * @global string $wp_local_package Locale code of the package. |
21 * @global string $wp_local_package Locale code of the package. |
22 * |
22 * |
23 * @param array $extra_stats Extra statistics to report to the WordPress.org API. |
23 * @param array $extra_stats Extra statistics to report to the WordPress.org API. |
24 * @param bool $force_check Whether to bypass the transient cache and force a fresh update check. Defaults to false, true if $extra_stats is set. |
24 * @param bool $force_check Whether to bypass the transient cache and force a fresh update check. |
|
25 * Defaults to false, true if $extra_stats is set. |
25 */ |
26 */ |
26 function wp_version_check( $extra_stats = array(), $force_check = false ) { |
27 function wp_version_check( $extra_stats = array(), $force_check = false ) { |
27 global $wpdb, $wp_local_package; |
28 global $wpdb, $wp_local_package; |
28 |
29 |
29 if ( wp_installing() ) { |
30 if ( wp_installing() ) { |
30 return; |
31 return; |
31 } |
32 } |
32 |
33 |
33 // Include an unmodified $wp_version. |
34 // Include an unmodified $wp_version. |
34 require ABSPATH . WPINC . '/version.php'; |
35 require ABSPATH . WPINC . '/version.php'; |
35 $php_version = phpversion(); |
36 $php_version = PHP_VERSION; |
36 |
37 |
37 $current = get_site_transient( 'update_core' ); |
38 $current = get_site_transient( 'update_core' ); |
38 $translations = wp_get_installed_translations( 'core' ); |
39 $translations = wp_get_installed_translations( 'core' ); |
39 |
40 |
40 // Invalidate the transient when $wp_version changes. |
41 // Invalidate the transient when $wp_version changes. |
41 if ( is_object( $current ) && $wp_version !== $current->version_checked ) { |
42 if ( is_object( $current ) && $wp_version !== $current->version_checked ) { |
42 $current = false; |
43 $current = false; |
43 } |
44 } |
44 |
45 |
45 if ( ! is_object( $current ) ) { |
46 if ( ! is_object( $current ) ) { |
46 $current = new stdClass; |
47 $current = new stdClass(); |
47 $current->updates = array(); |
48 $current->updates = array(); |
48 $current->version_checked = $wp_version; |
49 $current->version_checked = $wp_version; |
49 } |
50 } |
50 |
51 |
51 if ( ! empty( $extra_stats ) ) { |
52 if ( ! empty( $extra_stats ) ) { |
71 |
72 |
72 // Update last_checked for current to prevent multiple blocking requests if request hangs. |
73 // Update last_checked for current to prevent multiple blocking requests if request hangs. |
73 $current->last_checked = time(); |
74 $current->last_checked = time(); |
74 set_site_transient( 'update_core', $current ); |
75 set_site_transient( 'update_core', $current ); |
75 |
76 |
76 if ( method_exists( $wpdb, 'db_version' ) ) { |
77 if ( method_exists( $wpdb, 'db_server_info' ) ) { |
|
78 $mysql_version = $wpdb->db_server_info(); |
|
79 } elseif ( method_exists( $wpdb, 'db_version' ) ) { |
77 $mysql_version = preg_replace( '/[^0-9.].*/', '', $wpdb->db_version() ); |
80 $mysql_version = preg_replace( '/[^0-9.].*/', '', $wpdb->db_version() ); |
78 } else { |
81 } else { |
79 $mysql_version = 'N/A'; |
82 $mysql_version = 'N/A'; |
80 } |
83 } |
81 |
84 |
87 $multisite_enabled = 0; |
90 $multisite_enabled = 0; |
88 $num_blogs = 1; |
91 $num_blogs = 1; |
89 $wp_install = home_url( '/' ); |
92 $wp_install = home_url( '/' ); |
90 } |
93 } |
91 |
94 |
|
95 $extensions = get_loaded_extensions(); |
|
96 sort( $extensions, SORT_STRING | SORT_FLAG_CASE ); |
92 $query = array( |
97 $query = array( |
93 'version' => $wp_version, |
98 'version' => $wp_version, |
94 'php' => $php_version, |
99 'php' => $php_version, |
95 'locale' => $locale, |
100 'locale' => $locale, |
96 'mysql' => $mysql_version, |
101 'mysql' => $mysql_version, |
97 'local_package' => isset( $wp_local_package ) ? $wp_local_package : '', |
102 'local_package' => isset( $wp_local_package ) ? $wp_local_package : '', |
98 'blogs' => $num_blogs, |
103 'blogs' => $num_blogs, |
99 'users' => get_user_count(), |
104 'users' => get_user_count(), |
100 'multisite_enabled' => $multisite_enabled, |
105 'multisite_enabled' => $multisite_enabled, |
101 'initial_db_version' => get_site_option( 'initial_db_version' ), |
106 'initial_db_version' => get_site_option( 'initial_db_version' ), |
|
107 'extensions' => array_combine( $extensions, array_map( 'phpversion', $extensions ) ), |
|
108 'platform_flags' => array( |
|
109 'os' => PHP_OS, |
|
110 'bits' => PHP_INT_SIZE === 4 ? 32 : 64, |
|
111 ), |
|
112 'image_support' => array(), |
102 ); |
113 ); |
|
114 |
|
115 if ( function_exists( 'gd_info' ) ) { |
|
116 $gd_info = gd_info(); |
|
117 // Filter to supported values. |
|
118 $gd_info = array_filter( $gd_info ); |
|
119 |
|
120 // Add data for GD WebP and AVIF support. |
|
121 $query['image_support']['gd'] = array_keys( |
|
122 array_filter( |
|
123 array( |
|
124 'webp' => isset( $gd_info['WebP Support'] ), |
|
125 'avif' => isset( $gd_info['AVIF Support'] ), |
|
126 ) |
|
127 ) |
|
128 ); |
|
129 } |
|
130 |
|
131 if ( class_exists( 'Imagick' ) ) { |
|
132 // Add data for Imagick WebP and AVIF support. |
|
133 $query['image_support']['imagick'] = array_keys( |
|
134 array_filter( |
|
135 array( |
|
136 'webp' => ! empty( Imagick::queryFormats( 'WEBP' ) ), |
|
137 'avif' => ! empty( Imagick::queryFormats( 'AVIF' ) ), |
|
138 ) |
|
139 ) |
|
140 ); |
|
141 } |
103 |
142 |
104 /** |
143 /** |
105 * Filters the query arguments sent as part of the core version check. |
144 * Filters the query arguments sent as part of the core version check. |
106 * |
145 * |
107 * WARNING: Changing this data may result in your site not receiving security updates. |
146 * WARNING: Changing this data may result in your site not receiving security updates. |
161 ); |
200 ); |
162 |
201 |
163 $response = wp_remote_post( $url, $options ); |
202 $response = wp_remote_post( $url, $options ); |
164 |
203 |
165 if ( $ssl && is_wp_error( $response ) ) { |
204 if ( $ssl && is_wp_error( $response ) ) { |
166 trigger_error( |
205 wp_trigger_error( |
|
206 __FUNCTION__, |
167 sprintf( |
207 sprintf( |
168 /* translators: %s: Support forums URL. */ |
208 /* translators: %s: Support forums URL. */ |
169 __( '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>.' ), |
209 __( '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>.' ), |
170 __( 'https://wordpress.org/support/forums/' ) |
210 __( 'https://wordpress.org/support/forums/' ) |
171 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), |
211 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), |
288 |
328 |
289 $active = get_option( 'active_plugins', array() ); |
329 $active = get_option( 'active_plugins', array() ); |
290 $current = get_site_transient( 'update_plugins' ); |
330 $current = get_site_transient( 'update_plugins' ); |
291 |
331 |
292 if ( ! is_object( $current ) ) { |
332 if ( ! is_object( $current ) ) { |
293 $current = new stdClass; |
333 $current = new stdClass(); |
294 } |
334 } |
295 |
335 |
296 $updates = new stdClass; |
336 $updates = new stdClass(); |
297 $updates->last_checked = time(); |
337 $updates->last_checked = time(); |
298 $updates->response = array(); |
338 $updates->response = array(); |
299 $updates->translations = array(); |
339 $updates->translations = array(); |
300 $updates->no_update = array(); |
340 $updates->no_update = array(); |
301 |
341 |
361 * Filters the locales requested for plugin translations. |
401 * Filters the locales requested for plugin translations. |
362 * |
402 * |
363 * @since 3.7.0 |
403 * @since 3.7.0 |
364 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales. |
404 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales. |
365 * |
405 * |
366 * @param array $locales Plugin locales. Default is all available locales of the site. |
406 * @param string[] $locales Plugin locales. Default is all available locales of the site. |
367 */ |
407 */ |
368 $locales = apply_filters( 'plugins_update_check_locales', $locales ); |
408 $locales = apply_filters( 'plugins_update_check_locales', $locales ); |
369 $locales = array_unique( $locales ); |
409 $locales = array_unique( $locales ); |
370 |
410 |
371 if ( $doing_cron ) { |
411 if ( $doing_cron ) { |
372 $timeout = 30; |
412 $timeout = 30; // 30 seconds. |
373 } else { |
413 } else { |
374 // Three seconds, plus one extra second for every 10 plugins. |
414 // Three seconds, plus one extra second for every 10 plugins. |
375 $timeout = 3 + (int) ( count( $plugins ) / 10 ); |
415 $timeout = 3 + (int) ( count( $plugins ) / 10 ); |
376 } |
416 } |
377 |
417 |
399 } |
439 } |
400 |
440 |
401 $raw_response = wp_remote_post( $url, $options ); |
441 $raw_response = wp_remote_post( $url, $options ); |
402 |
442 |
403 if ( $ssl && is_wp_error( $raw_response ) ) { |
443 if ( $ssl && is_wp_error( $raw_response ) ) { |
404 trigger_error( |
444 wp_trigger_error( |
|
445 __FUNCTION__, |
405 sprintf( |
446 sprintf( |
406 /* translators: %s: Support forums URL. */ |
447 /* translators: %s: Support forums URL. */ |
407 __( '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>.' ), |
448 __( '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>.' ), |
408 __( 'https://wordpress.org/support/forums/' ) |
449 __( 'https://wordpress.org/support/forums/' ) |
409 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), |
450 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), |
467 * @type string $autoupdate Whether the translation should be automatically installed. |
508 * @type string $autoupdate Whether the translation should be automatically installed. |
468 * } |
509 * } |
469 * } |
510 * } |
470 * @param array $plugin_data Plugin headers. |
511 * @param array $plugin_data Plugin headers. |
471 * @param string $plugin_file Plugin filename. |
512 * @param string $plugin_file Plugin filename. |
472 * @param array $locales Installed locales to look translations for. |
513 * @param string[] $locales Installed locales to look up translations for. |
473 */ |
514 */ |
474 $update = apply_filters( "update_plugins_{$hostname}", false, $plugin_data, $plugin_file, $locales ); |
515 $update = apply_filters( "update_plugins_{$hostname}", false, $plugin_data, $plugin_file, $locales ); |
475 |
516 |
476 if ( ! $update ) { |
517 if ( ! $update ) { |
477 continue; |
518 continue; |
575 'Name' => $theme->get( 'Name' ), |
616 'Name' => $theme->get( 'Name' ), |
576 'Title' => $theme->get( 'Name' ), |
617 'Title' => $theme->get( 'Name' ), |
577 'Version' => $theme->get( 'Version' ), |
618 'Version' => $theme->get( 'Version' ), |
578 'Author' => $theme->get( 'Author' ), |
619 'Author' => $theme->get( 'Author' ), |
579 'Author URI' => $theme->get( 'AuthorURI' ), |
620 'Author URI' => $theme->get( 'AuthorURI' ), |
|
621 'UpdateURI' => $theme->get( 'UpdateURI' ), |
580 'Template' => $theme->get_template(), |
622 'Template' => $theme->get_template(), |
581 'Stylesheet' => $theme->get_stylesheet(), |
623 'Stylesheet' => $theme->get_stylesheet(), |
582 ); |
624 ); |
583 } |
625 } |
584 |
626 |
642 * Filters the locales requested for theme translations. |
684 * Filters the locales requested for theme translations. |
643 * |
685 * |
644 * @since 3.7.0 |
686 * @since 3.7.0 |
645 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales. |
687 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales. |
646 * |
688 * |
647 * @param array $locales Theme locales. Default is all available locales of the site. |
689 * @param string[] $locales Theme locales. Default is all available locales of the site. |
648 */ |
690 */ |
649 $locales = apply_filters( 'themes_update_check_locales', $locales ); |
691 $locales = apply_filters( 'themes_update_check_locales', $locales ); |
650 $locales = array_unique( $locales ); |
692 $locales = array_unique( $locales ); |
651 |
693 |
652 if ( $doing_cron ) { |
694 if ( $doing_cron ) { |
653 $timeout = 30; |
695 $timeout = 30; // 30 seconds. |
654 } else { |
696 } else { |
655 // Three seconds, plus one extra second for every 10 themes. |
697 // Three seconds, plus one extra second for every 10 themes. |
656 $timeout = 3 + (int) ( count( $themes ) / 10 ); |
698 $timeout = 3 + (int) ( count( $themes ) / 10 ); |
657 } |
699 } |
658 |
700 |
679 } |
721 } |
680 |
722 |
681 $raw_response = wp_remote_post( $url, $options ); |
723 $raw_response = wp_remote_post( $url, $options ); |
682 |
724 |
683 if ( $ssl && is_wp_error( $raw_response ) ) { |
725 if ( $ssl && is_wp_error( $raw_response ) ) { |
684 trigger_error( |
726 wp_trigger_error( |
|
727 __FUNCTION__, |
685 sprintf( |
728 sprintf( |
686 /* translators: %s: Support forums URL. */ |
729 /* translators: %s: Support forums URL. */ |
687 __( '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>.' ), |
730 __( '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>.' ), |
688 __( 'https://wordpress.org/support/forums/' ) |
731 __( 'https://wordpress.org/support/forums/' ) |
689 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), |
732 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), |
706 $new_update->response = $response['themes']; |
749 $new_update->response = $response['themes']; |
707 $new_update->no_update = $response['no_update']; |
750 $new_update->no_update = $response['no_update']; |
708 $new_update->translations = $response['translations']; |
751 $new_update->translations = $response['translations']; |
709 } |
752 } |
710 |
753 |
|
754 // Support updates for any themes using the `Update URI` header field. |
|
755 foreach ( $themes as $theme_stylesheet => $theme_data ) { |
|
756 if ( ! $theme_data['UpdateURI'] || isset( $new_update->response[ $theme_stylesheet ] ) ) { |
|
757 continue; |
|
758 } |
|
759 |
|
760 $hostname = wp_parse_url( sanitize_url( $theme_data['UpdateURI'] ), PHP_URL_HOST ); |
|
761 |
|
762 /** |
|
763 * Filters the update response for a given theme hostname. |
|
764 * |
|
765 * The dynamic portion of the hook name, `$hostname`, refers to the hostname |
|
766 * of the URI specified in the `Update URI` header field. |
|
767 * |
|
768 * @since 6.1.0 |
|
769 * |
|
770 * @param array|false $update { |
|
771 * The theme update data with the latest details. Default false. |
|
772 * |
|
773 * @type string $id Optional. ID of the theme for update purposes, should be a URI |
|
774 * specified in the `Update URI` header field. |
|
775 * @type string $theme Directory name of the theme. |
|
776 * @type string $version The version of the theme. |
|
777 * @type string $url The URL for details of the theme. |
|
778 * @type string $package Optional. The update ZIP for the theme. |
|
779 * @type string $tested Optional. The version of WordPress the theme is tested against. |
|
780 * @type string $requires_php Optional. The version of PHP which the theme requires. |
|
781 * @type bool $autoupdate Optional. Whether the theme should automatically update. |
|
782 * @type array $translations { |
|
783 * Optional. List of translation updates for the theme. |
|
784 * |
|
785 * @type string $language The language the translation update is for. |
|
786 * @type string $version The version of the theme this translation is for. |
|
787 * This is not the version of the language file. |
|
788 * @type string $updated The update timestamp of the translation file. |
|
789 * Should be a date in the `YYYY-MM-DD HH:MM:SS` format. |
|
790 * @type string $package The ZIP location containing the translation update. |
|
791 * @type string $autoupdate Whether the translation should be automatically installed. |
|
792 * } |
|
793 * } |
|
794 * @param array $theme_data Theme headers. |
|
795 * @param string $theme_stylesheet Theme stylesheet. |
|
796 * @param string[] $locales Installed locales to look up translations for. |
|
797 */ |
|
798 $update = apply_filters( "update_themes_{$hostname}", false, $theme_data, $theme_stylesheet, $locales ); |
|
799 |
|
800 if ( ! $update ) { |
|
801 continue; |
|
802 } |
|
803 |
|
804 $update = (object) $update; |
|
805 |
|
806 // Is it valid? We require at least a version. |
|
807 if ( ! isset( $update->version ) ) { |
|
808 continue; |
|
809 } |
|
810 |
|
811 // This should remain constant. |
|
812 $update->id = $theme_data['UpdateURI']; |
|
813 |
|
814 // WordPress needs the version field specified as 'new_version'. |
|
815 if ( ! isset( $update->new_version ) ) { |
|
816 $update->new_version = $update->version; |
|
817 } |
|
818 |
|
819 // Handle any translation updates. |
|
820 if ( ! empty( $update->translations ) ) { |
|
821 foreach ( $update->translations as $translation ) { |
|
822 if ( isset( $translation['language'], $translation['package'] ) ) { |
|
823 $translation['type'] = 'theme'; |
|
824 $translation['slug'] = isset( $update->theme ) ? $update->theme : $update->id; |
|
825 |
|
826 $new_update->translations[] = $translation; |
|
827 } |
|
828 } |
|
829 } |
|
830 |
|
831 unset( $new_update->no_update[ $theme_stylesheet ], $new_update->response[ $theme_stylesheet ] ); |
|
832 |
|
833 if ( version_compare( $update->new_version, $theme_data['Version'], '>' ) ) { |
|
834 $new_update->response[ $theme_stylesheet ] = (array) $update; |
|
835 } else { |
|
836 $new_update->no_update[ $theme_stylesheet ] = (array) $update; |
|
837 } |
|
838 } |
|
839 |
711 set_site_transient( 'update_themes', $new_update ); |
840 set_site_transient( 'update_themes', $new_update ); |
712 } |
841 } |
713 |
842 |
714 /** |
843 /** |
715 * Performs WordPress automatic background updates. |
844 * Performs WordPress automatic background updates. |
951 wp_clean_themes_cache(); |
1080 wp_clean_themes_cache(); |
952 |
1081 |
953 delete_site_transient( 'update_core' ); |
1082 delete_site_transient( 'update_core' ); |
954 } |
1083 } |
955 |
1084 |
|
1085 /** |
|
1086 * Schedules the removal of all contents in the temporary backup directory. |
|
1087 * |
|
1088 * @since 6.3.0 |
|
1089 */ |
|
1090 function wp_delete_all_temp_backups() { |
|
1091 /* |
|
1092 * Check if there is a lock, or if currently performing an Ajax request, |
|
1093 * in which case there is a chance an update is running. |
|
1094 * Reschedule for an hour from now and exit early. |
|
1095 */ |
|
1096 if ( get_option( 'core_updater.lock' ) || get_option( 'auto_updater.lock' ) || wp_doing_ajax() ) { |
|
1097 wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'wp_delete_temp_updater_backups' ); |
|
1098 return; |
|
1099 } |
|
1100 |
|
1101 // This action runs on shutdown to make sure there are no plugin updates currently running. |
|
1102 add_action( 'shutdown', '_wp_delete_all_temp_backups' ); |
|
1103 } |
|
1104 |
|
1105 /** |
|
1106 * Deletes all contents in the temporary backup directory. |
|
1107 * |
|
1108 * @since 6.3.0 |
|
1109 * |
|
1110 * @access private |
|
1111 * |
|
1112 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. |
|
1113 * |
|
1114 * @return void|WP_Error Void on success, or a WP_Error object on failure. |
|
1115 */ |
|
1116 function _wp_delete_all_temp_backups() { |
|
1117 global $wp_filesystem; |
|
1118 |
|
1119 if ( ! function_exists( 'WP_Filesystem' ) ) { |
|
1120 require_once ABSPATH . '/wp-admin/includes/file.php'; |
|
1121 } |
|
1122 |
|
1123 ob_start(); |
|
1124 $credentials = request_filesystem_credentials( '' ); |
|
1125 ob_end_clean(); |
|
1126 |
|
1127 if ( false === $credentials || ! WP_Filesystem( $credentials ) ) { |
|
1128 return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) ); |
|
1129 } |
|
1130 |
|
1131 if ( ! $wp_filesystem->wp_content_dir() ) { |
|
1132 return new WP_Error( |
|
1133 'fs_no_content_dir', |
|
1134 /* translators: %s: Directory name. */ |
|
1135 sprintf( __( 'Unable to locate WordPress content directory (%s).' ), 'wp-content' ) |
|
1136 ); |
|
1137 } |
|
1138 |
|
1139 $temp_backup_dir = $wp_filesystem->wp_content_dir() . 'upgrade-temp-backup/'; |
|
1140 $dirlist = $wp_filesystem->dirlist( $temp_backup_dir ); |
|
1141 $dirlist = $dirlist ? $dirlist : array(); |
|
1142 |
|
1143 foreach ( array_keys( $dirlist ) as $dir ) { |
|
1144 if ( '.' === $dir || '..' === $dir ) { |
|
1145 continue; |
|
1146 } |
|
1147 |
|
1148 $wp_filesystem->delete( $temp_backup_dir . $dir, true ); |
|
1149 } |
|
1150 } |
|
1151 |
956 if ( ( ! is_main_site() && ! is_network_admin() ) || wp_doing_ajax() ) { |
1152 if ( ( ! is_main_site() && ! is_network_admin() ) || wp_doing_ajax() ) { |
957 return; |
1153 return; |
958 } |
1154 } |
959 |
1155 |
960 add_action( 'admin_init', '_maybe_update_core' ); |
1156 add_action( 'admin_init', '_maybe_update_core' ); |