Skip to content

Instantly share code, notes, and snippets.

@westonruter
Created June 12, 2020 01:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westonruter/340dfb31c09e7f82240161529e5ec93c to your computer and use it in GitHub Desktop.
Save westonruter/340dfb31c09e7f82240161529e5ec93c to your computer and use it in GitHub Desktop.
Development plugin to test slow-loading images in content
<?php
/**
* Slow Content Images plugin bootstrap.
*
* @package Google\Mini_Plugin_Template
* @author Weston Ruter, Google
* @license GPL-2.0-or-later
* @copyright 2020 Google Inc.
*
* @wordpress-plugin
* Plugin Name: Slow Content Images
* Plugin URI: https://gist.github.com/westonruter/340dfb31c09e7f82240161529e5ec93c
* Description: Cause images in content to have an increasing delay before each starts loading. First image has a 3-second delay and each image after gets loaded 1 second after the next.
* Version: 0.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
* Gist Plugin URI: https://gist.github.com/westonruter/340dfb31c09e7f82240161529e5ec93c
*/
namespace Google\Slow_Content_Images;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
const REST_NAMESPACE = 'slow-content-images/v1';
add_filter( 'the_content', __NAMESPACE__ . '\filter_the_content', 1000 );
add_action( 'rest_api_init', __NAMESPACE__ . '\register_proxy_route' );
/**
* Register image proxy route.
*/
function register_proxy_route() {
register_rest_route(
REST_NAMESPACE,
'/proxy/(?P<base64_url>.+)',
[
'methods' => 'GET',
'callback' => __NAMESPACE__ . '\handle_rest_request',
'args' => [
'sleep' => [
'type' => 'int',
],
],
]
);
}
/**
* Handle image proxy request.
*
* @param WP_REST_Request $request Request.
* @return WP_Error|WP_REST_Response
*/
function handle_rest_request( WP_REST_Request $request ) {
$slug = str_replace(
[ '-', '_' ],
[ '+', '/' ],
$request['base64_url']
);
$url = base64_decode( $slug );
if ( false === $url ) {
return new WP_Error( 'base64_error' );
}
sleep( (int) $request['sleep'] );
$response = new WP_REST_Response();
$response->set_status( 302 );
$response->header( 'Location', '//' . $url );
return $response;
}
/**
* Filter the content to inject proxied image URLs.
*
* @param string $content Content.
*
* @return string Filtered content.
*/
function filter_the_content( $content ) {
static $base_instances = [];
return preg_replace_callback(
// Look for image-looking URLs that may have query params following them.
'#(\bhttps?://)([^\s"\',]+?\.(?:jpe?g|png|gif|webp)(?:\?[^\s"\',]+)?)\b#',
function ( $matches ) use ( &$base_instances ) {
$url = html_entity_decode( $matches[2], ENT_QUOTES );
$base = preg_replace( '/(-\d+x\d+)?\.\w+/', '', basename( wp_parse_url( $url, PHP_URL_PATH ) ) );
if ( ! in_array( $base, $base_instances, true ) ) {
$base_instances[] = $base;
}
$sleep = 2 + ( array_search( $base, $base_instances, true ) * 2 );
// Note that base64-encoding is to prevent some web servers from failing to image-looking URLs to WordPress.
$slug = str_replace(
[ '+', '/' ],
[ '-', '_' ],
base64_encode( $url )
);
return esc_url( add_query_arg(
compact( 'sleep' ),
rest_url( '/' . REST_NAMESPACE . '/proxy/' . $slug )
) );
},
$content
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment