equal
deleted
inserted
replaced
5 * @package WordPress |
5 * @package WordPress |
6 * @subpackage Site_Health |
6 * @subpackage Site_Health |
7 * @since 5.2.0 |
7 * @since 5.2.0 |
8 */ |
8 */ |
9 |
9 |
|
10 #[AllowDynamicProperties] |
10 class WP_Site_Health_Auto_Updates { |
11 class WP_Site_Health_Auto_Updates { |
11 /** |
12 /** |
12 * WP_Site_Health_Auto_Updates constructor. |
13 * WP_Site_Health_Auto_Updates constructor. |
13 * |
14 * |
14 * @since 5.2.0 |
15 * @since 5.2.0 |
17 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; |
18 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; |
18 } |
19 } |
19 |
20 |
20 |
21 |
21 /** |
22 /** |
22 * Run tests to determine if auto-updates can run. |
23 * Runs tests to determine if auto-updates can run. |
23 * |
24 * |
24 * @since 5.2.0 |
25 * @since 5.2.0 |
25 * |
26 * |
26 * @return array The test results. |
27 * @return array The test results. |
27 */ |
28 */ |
39 $this->test_accepts_minor_updates(), |
40 $this->test_accepts_minor_updates(), |
40 ); |
41 ); |
41 |
42 |
42 $tests = array_filter( $tests ); |
43 $tests = array_filter( $tests ); |
43 $tests = array_map( |
44 $tests = array_map( |
44 static function( $test ) { |
45 static function ( $test ) { |
45 $test = (object) $test; |
46 $test = (object) $test; |
46 |
47 |
47 if ( empty( $test->severity ) ) { |
48 if ( empty( $test->severity ) ) { |
48 $test->severity = 'warning'; |
49 $test->severity = 'warning'; |
49 } |
50 } |
55 |
56 |
56 return $tests; |
57 return $tests; |
57 } |
58 } |
58 |
59 |
59 /** |
60 /** |
60 * Test if auto-updates related constants are set correctly. |
61 * Tests if auto-updates related constants are set correctly. |
61 * |
62 * |
62 * @since 5.2.0 |
63 * @since 5.2.0 |
63 * @since 5.5.1 The `$value` parameter can accept an array. |
64 * @since 5.5.1 The `$value` parameter can accept an array. |
64 * |
65 * |
65 * @param string $constant The name of the constant to check. |
66 * @param string $constant The name of the constant to check. |
71 $acceptable_values = (array) $value; |
72 $acceptable_values = (array) $value; |
72 |
73 |
73 if ( defined( $constant ) && ! in_array( constant( $constant ), $acceptable_values, true ) ) { |
74 if ( defined( $constant ) && ! in_array( constant( $constant ), $acceptable_values, true ) ) { |
74 return array( |
75 return array( |
75 'description' => sprintf( |
76 'description' => sprintf( |
76 /* translators: %s: Name of the constant used. */ |
77 /* translators: 1: Name of the constant used. 2: Value of the constant used. */ |
77 __( 'The %s constant is defined and enabled.' ), |
78 __( 'The %1$s constant is defined as %2$s' ), |
78 "<code>$constant</code>" |
79 "<code>$constant</code>", |
79 ), |
80 '<code>' . esc_html( var_export( constant( $constant ), true ) ) . '</code>' |
80 'severity' => 'fail', |
81 ), |
81 ); |
82 'severity' => 'fail', |
82 } |
83 ); |
83 } |
84 } |
84 |
85 } |
85 /** |
86 |
86 * Check if updates are intercepted by a filter. |
87 /** |
|
88 * Checks if updates are intercepted by a filter. |
87 * |
89 * |
88 * @since 5.2.0 |
90 * @since 5.2.0 |
89 * |
91 * |
90 * @return array The test results. |
92 * @return array The test results. |
91 */ |
93 */ |
103 ); |
105 ); |
104 } |
106 } |
105 } |
107 } |
106 |
108 |
107 /** |
109 /** |
108 * Check if automatic updates are disabled by a filter. |
110 * Checks if automatic updates are disabled by a filter. |
109 * |
111 * |
110 * @since 5.2.0 |
112 * @since 5.2.0 |
111 * |
113 * |
112 * @return array The test results. |
114 * @return array The test results. |
113 */ |
115 */ |
124 ); |
126 ); |
125 } |
127 } |
126 } |
128 } |
127 |
129 |
128 /** |
130 /** |
129 * Check if automatic updates are disabled. |
131 * Checks if automatic updates are disabled. |
130 * |
132 * |
131 * @since 5.3.0 |
133 * @since 5.3.0 |
132 * |
134 * |
133 * @return array|false The test results. False if auto-updates are enabled. |
135 * @return array|false The test results. False if auto-updates are enabled. |
134 */ |
136 */ |
148 'severity' => 'fail', |
150 'severity' => 'fail', |
149 ); |
151 ); |
150 } |
152 } |
151 |
153 |
152 /** |
154 /** |
153 * Check if automatic updates have tried to run, but failed, previously. |
155 * Checks if automatic updates have tried to run, but failed, previously. |
154 * |
156 * |
155 * @since 5.2.0 |
157 * @since 5.2.0 |
156 * |
158 * |
157 * @return array|false The test results. False if the auto-updates failed. |
159 * @return array|false The test results. False if the auto-updates failed. |
158 */ |
160 */ |
164 } |
166 } |
165 |
167 |
166 if ( ! empty( $failed['critical'] ) ) { |
168 if ( ! empty( $failed['critical'] ) ) { |
167 $description = __( 'A previous automatic background update ended with a critical failure, so updates are now disabled.' ); |
169 $description = __( 'A previous automatic background update ended with a critical failure, so updates are now disabled.' ); |
168 $description .= ' ' . __( 'You would have received an email because of this.' ); |
170 $description .= ' ' . __( 'You would have received an email because of this.' ); |
169 $description .= ' ' . __( "When you've been able to update using the \"Update now\" button on Dashboard > Updates, we'll clear this error for future update attempts." ); |
171 $description .= ' ' . __( "When you've been able to update using the \"Update now\" button on Dashboard > Updates, this error will be cleared for future update attempts." ); |
170 $description .= ' ' . sprintf( |
172 $description .= ' ' . sprintf( |
171 /* translators: %s: Code of error shown. */ |
173 /* translators: %s: Code of error shown. */ |
172 __( 'The error code was %s.' ), |
174 __( 'The error code was %s.' ), |
173 '<code>' . $failed['error_code'] . '</code>' |
175 '<code>' . $failed['error_code'] . '</code>' |
174 ); |
176 ); |
181 $description = __( 'A previous automatic background update could not occur.' ); |
183 $description = __( 'A previous automatic background update could not occur.' ); |
182 if ( empty( $failed['retry'] ) ) { |
184 if ( empty( $failed['retry'] ) ) { |
183 $description .= ' ' . __( 'You would have received an email because of this.' ); |
185 $description .= ' ' . __( 'You would have received an email because of this.' ); |
184 } |
186 } |
185 |
187 |
186 $description .= ' ' . __( "We'll try again with the next release." ); |
188 $description .= ' ' . __( 'Another attempt will be made with the next release.' ); |
187 $description .= ' ' . sprintf( |
189 $description .= ' ' . sprintf( |
188 /* translators: %s: Code of error shown. */ |
190 /* translators: %s: Code of error shown. */ |
189 __( 'The error code was %s.' ), |
191 __( 'The error code was %s.' ), |
190 '<code>' . $failed['error_code'] . '</code>' |
192 '<code>' . $failed['error_code'] . '</code>' |
191 ); |
193 ); |
194 'severity' => 'warning', |
196 'severity' => 'warning', |
195 ); |
197 ); |
196 } |
198 } |
197 |
199 |
198 /** |
200 /** |
199 * Check if WordPress is controlled by a VCS (Git, Subversion etc). |
201 * Checks if WordPress is controlled by a VCS (Git, Subversion etc). |
200 * |
202 * |
201 * @since 5.2.0 |
203 * @since 5.2.0 |
202 * |
204 * |
203 * @return array The test results. |
205 * @return array The test results. |
204 */ |
206 */ |
224 $check_dirs = array_unique( $check_dirs ); |
226 $check_dirs = array_unique( $check_dirs ); |
225 |
227 |
226 // Search all directories we've found for evidence of version control. |
228 // Search all directories we've found for evidence of version control. |
227 foreach ( $vcs_dirs as $vcs_dir ) { |
229 foreach ( $vcs_dirs as $vcs_dir ) { |
228 foreach ( $check_dirs as $check_dir ) { |
230 foreach ( $check_dirs as $check_dir ) { |
229 // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition,Squiz.PHP.DisallowMultipleAssignments |
231 // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition,Squiz.PHP.DisallowMultipleAssignments |
230 if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) { |
232 if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) { |
231 break 2; |
233 break 2; |
232 } |
234 } |
233 } |
235 } |
234 } |
236 } |
264 'severity' => 'pass', |
266 'severity' => 'pass', |
265 ); |
267 ); |
266 } |
268 } |
267 |
269 |
268 /** |
270 /** |
269 * Check if we can access files without providing credentials. |
271 * Checks if we can access files without providing credentials. |
270 * |
272 * |
271 * @since 5.2.0 |
273 * @since 5.2.0 |
272 * |
274 * |
273 * @return array The test results. |
275 * @return array The test results. |
274 */ |
276 */ |
275 public function test_check_wp_filesystem_method() { |
277 public function test_check_wp_filesystem_method() { |
276 // Make sure the `request_filesystem_credentials()` function is available during our REST API call. |
278 // Make sure the `request_filesystem_credentials()` function is available during our REST API call. |
277 if ( ! function_exists( 'request_filesystem_credentials' ) ) { |
279 if ( ! function_exists( 'request_filesystem_credentials' ) ) { |
278 require_once ABSPATH . '/wp-admin/includes/file.php'; |
280 require_once ABSPATH . 'wp-admin/includes/file.php'; |
279 } |
281 } |
280 |
282 |
281 $skin = new Automatic_Upgrader_Skin; |
283 $skin = new Automatic_Upgrader_Skin(); |
282 $success = $skin->request_filesystem_credentials( false, ABSPATH ); |
284 $success = $skin->request_filesystem_credentials( false, ABSPATH ); |
283 |
285 |
284 if ( ! $success ) { |
286 if ( ! $success ) { |
285 $description = __( 'Your installation of WordPress prompts for FTP credentials to perform updates.' ); |
287 $description = __( 'Your installation of WordPress prompts for FTP credentials to perform updates.' ); |
286 $description .= ' ' . __( '(Your site is performing updates over FTP due to file ownership. Talk to your hosting company.)' ); |
288 $description .= ' ' . __( '(Your site is performing updates over FTP due to file ownership. Talk to your hosting company.)' ); |
296 'severity' => 'pass', |
298 'severity' => 'pass', |
297 ); |
299 ); |
298 } |
300 } |
299 |
301 |
300 /** |
302 /** |
301 * Check if core files are writable by the web user/group. |
303 * Checks if core files are writable by the web user/group. |
302 * |
304 * |
303 * @since 5.2.0 |
305 * @since 5.2.0 |
304 * |
306 * |
305 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. |
307 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. |
306 * |
308 * |
309 public function test_all_files_writable() { |
311 public function test_all_files_writable() { |
310 global $wp_filesystem; |
312 global $wp_filesystem; |
311 |
313 |
312 require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z |
314 require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z |
313 |
315 |
314 $skin = new Automatic_Upgrader_Skin; |
316 $skin = new Automatic_Upgrader_Skin(); |
315 $success = $skin->request_filesystem_credentials( false, ABSPATH ); |
317 $success = $skin->request_filesystem_credentials( false, ABSPATH ); |
316 |
318 |
317 if ( ! $success ) { |
319 if ( ! $success ) { |
318 return false; |
320 return false; |
319 } |
321 } |
324 return false; |
326 return false; |
325 } |
327 } |
326 |
328 |
327 // Make sure the `get_core_checksums()` function is available during our REST API call. |
329 // Make sure the `get_core_checksums()` function is available during our REST API call. |
328 if ( ! function_exists( 'get_core_checksums' ) ) { |
330 if ( ! function_exists( 'get_core_checksums' ) ) { |
329 require_once ABSPATH . '/wp-admin/includes/update.php'; |
331 require_once ABSPATH . 'wp-admin/includes/update.php'; |
330 } |
332 } |
331 |
333 |
332 $checksums = get_core_checksums( $wp_version, 'en_US' ); |
334 $checksums = get_core_checksums( $wp_version, 'en_US' ); |
333 $dev = ( false !== strpos( $wp_version, '-' ) ); |
335 $dev = ( str_contains( $wp_version, '-' ) ); |
334 // Get the last stable version's files and test against that. |
336 // Get the last stable version's files and test against that. |
335 if ( ! $checksums && $dev ) { |
337 if ( ! $checksums && $dev ) { |
336 $checksums = get_core_checksums( (float) $wp_version - 0.1, 'en_US' ); |
338 $checksums = get_core_checksums( (float) $wp_version - 0.1, 'en_US' ); |
337 } |
339 } |
338 |
340 |
354 ); |
356 ); |
355 } |
357 } |
356 |
358 |
357 $unwritable_files = array(); |
359 $unwritable_files = array(); |
358 foreach ( array_keys( $checksums ) as $file ) { |
360 foreach ( array_keys( $checksums ) as $file ) { |
359 if ( 'wp-content' === substr( $file, 0, 10 ) ) { |
361 if ( str_starts_with( $file, 'wp-content' ) ) { |
360 continue; |
362 continue; |
361 } |
363 } |
362 if ( ! file_exists( ABSPATH . $file ) ) { |
364 if ( ! file_exists( ABSPATH . $file ) ) { |
363 continue; |
365 continue; |
364 } |
366 } |
383 ); |
385 ); |
384 } |
386 } |
385 } |
387 } |
386 |
388 |
387 /** |
389 /** |
388 * Check if the install is using a development branch and can use nightly packages. |
390 * Checks if the install is using a development branch and can use nightly packages. |
389 * |
391 * |
390 * @since 5.2.0 |
392 * @since 5.2.0 |
391 * |
393 * |
392 * @return array|false The test results. False if it isn't a development version. |
394 * @return array|false The test results. False if it isn't a development version. |
393 */ |
395 */ |
394 public function test_accepts_dev_updates() { |
396 public function test_accepts_dev_updates() { |
395 require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z |
397 require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z |
396 // Only for dev versions. |
398 // Only for dev versions. |
397 if ( false === strpos( $wp_version, '-' ) ) { |
399 if ( ! str_contains( $wp_version, '-' ) ) { |
398 return false; |
400 return false; |
399 } |
401 } |
400 |
402 |
401 if ( defined( 'WP_AUTO_UPDATE_CORE' ) && ( 'minor' === WP_AUTO_UPDATE_CORE || false === WP_AUTO_UPDATE_CORE ) ) { |
403 if ( defined( 'WP_AUTO_UPDATE_CORE' ) && ( 'minor' === WP_AUTO_UPDATE_CORE || false === WP_AUTO_UPDATE_CORE ) ) { |
402 return array( |
404 return array( |
421 ); |
423 ); |
422 } |
424 } |
423 } |
425 } |
424 |
426 |
425 /** |
427 /** |
426 * Check if the site supports automatic minor updates. |
428 * Checks if the site supports automatic minor updates. |
427 * |
429 * |
428 * @since 5.2.0 |
430 * @since 5.2.0 |
429 * |
431 * |
430 * @return array The test results. |
432 * @return array The test results. |
431 */ |
433 */ |