Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
/**
* AMP Async Validation
*
* Installation instructions:
* 1. Click the “Download ZIP” button.
* 2. Rename the downloaded ZIP file to “amp-async-validation.zip”
* 3. In the WordPress admin, go to Plugins > Add New
* 4. Click the Upload Plugin button.
* 5. Select the “amp-async-validation.zip” file and click “Install now”.
* 6. Click “Activate”
*
* @package AMP_Async_Validation
* @author Weston Ruter, Google
* @license GPL-2.0-or-later
* @copyright 2019 Google Inc.
*
* @wordpress-plugin
* Plugin Name: AMP Async Validation
* Description: This is a workaround for sites encountering slowness when updating posts due to the synchronous loopback requests which happen at post save to report back validation errors to the editor; instead of running at the <code>save_post</code> action, the post is queued for validation in an immediate event via WP Cron. The AMP plugin intends to <a href="https://github.com/ampproject/amp-wp/issues/2069">make this process asynchronous</a>, but until that lands this plugin can be used. A side effect of turning off synchronous validation is that validation error warnings are no longer displayed in the editor. To see the errors, you have to go to the AMP Validated URLs screen. An <code>amp_async_validation</code> filter can be used to control whether or not async validation should be performed.
* Plugin URI: https://gist.github.com/westonruter/31ac0e056b8b1278c98f8a9f548fcc1a
* Version: 0.2.1
* Author: Weston Ruter, Google
* Author URI: https://weston.ruter.net/
* License: GNU General Public License v2 (or later)
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace AMP_Async_Validation;
add_action( 'init', __NAMESPACE__ . '\make_save_post_validation_async' );
/**
* Make AMP validation asynchronous for post saves.
*
* @see \AMP_Validation_Manager::init()
*/
function make_save_post_validation_async() {
if (
! class_exists( 'AMP_Validation_Manager' )
||
! method_exists( 'AMP_Validation_Manager', 'post_supports_validation' )
||
! method_exists( 'AMP_Validation_Manager', 'validate_queued_posts_on_frontend' )
) {
return;
}
$is_autosave_request = ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE );
/**
* Filters whether asynchronous validation should be performed.
*
* This is useful if a site wants to disable asynchronous validation for certain users. For example, to use
* synchronous validation for administrators, add this plugin code to a mu-plugin:
*
* add_filter( 'amp_async_validation', function () {
* return ! current_user_can( 'manage_options' );
* } );
*
* @param bool $enabled Async enabled.
*/
if ( apply_filters( 'amp_async_validation', true ) ) {
// Disable synchronous validation and turn off adding the display of validation errors in the editor (since they will by delayed).
remove_action( 'save_post', [ 'AMP_Validation_Manager', 'handle_save_post_prompting_validation' ] );
remove_action( 'edit_form_top', [ 'AMP_Validation_Manager', 'print_edit_form_validation_status' ] );
remove_action( 'rest_api_init', [ 'AMP_Validation_Manager', 'add_rest_api_fields' ] );
// Enable asynchronous validation via WP Cron, but skip if an autosave request.
if ( ! $is_autosave_request ) {
add_action( 'save_post', __NAMESPACE__ . '\queue_post_for_async_validation' );
}
}
// Needs to happen unconditionally since WP Cron does not run in authenticated context.
add_action( 'amp_async_post_validation', __NAMESPACE__ . '\validate_post' );
}
/**
* Queue post for async validation.
*
* @param int|\WP_Post $post Post.
*/
function queue_post_for_async_validation( $post ) {
$post = get_post( $post );
/*
* Note only published posts can be validated because currently the loopback validation request passes through the
* user's current authenticated state, and since WP Cron does not run with a user logged-in, then draft posts will
* fail to get validated since they cannot be accessed.
*/
if ( $post && \AMP_Validation_Manager::post_supports_validation( $post ) && 'publish' === $post->post_status ) {
wp_schedule_single_event( time(), 'amp_async_post_validation', [ $post->ID ] );
}
}
/**
* Validate post during WP Cron.
*
* @see \AMP_Validation_Manager::validate_queued_posts_on_frontend()
* @param int $post_id Post ID to validate.
*/
function validate_post( $post_id ) {
if ( ! class_exists( 'AMP_Validation_Manager' ) ) {
return;
}
/*
* Re-use what the AMP plugin has for initiating the validation loopback requests at shutdown.
* Really the logic inside of AMP_Validation_Manager::validate_queued_posts_on_frontend() should be refactored
* to allow its inner logic to be called directly. But this shutdown method here ensures that other tasks are able
* to complete before starting the long-running validation loopback requests.
*/
\AMP_Validation_Manager::$posts_pending_frontend_validation[ $post_id ] = true;
if ( ! has_action( 'shutdown', [ 'AMP_Validation_Manager', 'validate_queued_posts_on_frontend' ] ) ) {
add_action( 'shutdown', [ 'AMP_Validation_Manager', 'validate_queued_posts_on_frontend' ] );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.