| 308 | * Test the server setup to see if we need to fallback to the 'alternate cron' method. |
| 309 | * Some server setups, for some reason do not allow loopback http requests. This |
| 310 | * function specifically tests whether that functionality is available, and cachees |
| 311 | * the result for 12 hours. |
| 312 | * |
| 313 | * @since 4.0.1 |
| 314 | * |
| 315 | * @return bool True, if we need to force alternate cron because of server setup, False otherwise |
| 316 | */ |
| 317 | function _maybe_force_alternate_wp_cron() { |
| 318 | |
| 319 | // if a response has been cached from earlier, then just reuse it |
| 320 | $cached_response = get_transient( 'loopback_response' ); |
| 321 | |
| 322 | // if no cache exists, and we are not already forcing alternate cron using another method |
| 323 | if ( ! $cached_response && defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) { |
| 324 | // cache buster |
| 325 | $rnd = substr( md5( time() . NONCE_SALT ), 10, 10 ); |
| 326 | |
| 327 | // create an unfiltered request to test our loopback connection with |
| 328 | $loopback_request = array( |
| 329 | 'url' => add_query_arg( 'wp_loopback_test', $loopback_request, site_url( 'wp-cron.php' ) ), |
| 330 | 'args' => array( |
| 331 | /* short timeout for the request */ |
| 332 | 'timeout' => 0.01, |
| 333 | /* make this request blocking so that we get a response code */ |
| 334 | 'blocking' => true, |
| 335 | /* force the wp-cron.php script to die early by sending post data */ |
| 336 | 'body' => array( 'wp_loopback_test_chk' => sha1( $loopback_request ) ), |
| 337 | /** This filter is documented in wp-includes/class-http.php */ |
| 338 | 'sslverify' => apply_filters( 'https_local_ssl_verify', false ) |
| 339 | ) |
| 340 | ); |
| 341 | |
| 342 | // fetch the response from the server |
| 343 | $response = wp_remote_post( $loopback_request['url'], $loopback_request['args'] ); |
| 344 | |
| 345 | // default the response to an unknown error, because wp_remote_post could return a WP_Error. |
| 346 | // if the WP_Error is returned, the failure is the same as a non-200 response |
| 347 | $cached_response = 'ERROR'; |
| 348 | |
| 349 | // parse the response into just a response code, if it is present |
| 350 | if ( is_array($response) && isset( $response['response'], $response['response']['code'] ) ) { |
| 351 | $cached_response = $response['response']['code']; |
| 352 | } |
| 353 | |
| 354 | // cache the response |
| 355 | set_transient( 'loopback_response', $cached_response, DAY_IN_SECONDS / 2 ); |
| 356 | } |
| 357 | |
| 358 | // if our response is 200, then we are good. otherwise we need to force alternate cron |
| 359 | return $cached_response != 200; |
| 360 | } |
| 361 | |
| 362 | /** |
| 363 | * Performs a check when the admin loads, to see if the server is setup so that WP Cron can |
| 364 | * function normally. Upon failure, it spawns an admin notice. |
| 365 | * |
| 366 | * @since 4.0.1 |
| 367 | * |
| 368 | * @return null Simply checks and spawns a notice if needed |
| 369 | */ |
| 370 | function wp_cron_admin_check() { |
| 371 | |
| 372 | // check if the cron is currently being forced to use the 'alternate cron' method |
| 373 | // only perform this check if the current user needs to know about it |
| 374 | // Issue: https://core.trac.wordpress.org/ticket/23133 |
| 375 | // ticket was created in regards to failed future posts, which is handled by cron, |
| 376 | // thus the edit_posts permission sounds most logical |
| 377 | if ( current_user_can( 'edit_posts' ) && _maybe_force_alternate_wp_cron() ) { |
| 378 | // if we are currently forcing it, then add a notice about it in the admin |
| 379 | add_action( 'admin_notices', 'wp_cron_admin_check_failed_message' ); |
| 380 | } |
| 381 | } |
| 382 | add_action( 'admin_init', 'wp_cron_admin_check' ); |
| 383 | |
| 384 | /** |
| 385 | * Displays an admin notice, informing the admin user they have been switched to the |
| 386 | * Alternative Cron method. Definitely needs some verbiage work, and probably a translation. |
| 387 | * |
| 388 | * @since 4.0.1 |
| 389 | * |
| 390 | * @return null Simply displays a message |
| 391 | */ |
| 392 | function wp_cron_admin_check_failed_message() { |
| 393 | echo '<div id="alternate-cron-force" class="error"><p>'; |
| 394 | echo __( 'Your server is preventing WP Cron from functioning properly. ' ); |
| 395 | echo __( 'As a fallback, you have been switched to using <a href="http://codex.wordpress.org/Editing_wp-config.php#Alternative_Cron">Alternative Cron</a> for now. ' ); |
| 396 | echo '</p></div>'; |
| 397 | } |
| 398 | |
| 399 | /** |