Files
wp-multisite-waas/inc/class-light-ajax.php
David Stone a815fdf179 Prep Plugin for release on WordPress.org
Escape everything that should be escaped.
Add nonce checks where needed.
Sanitize all inputs.
Apply Code style changes across the codebase.
Correct many deprecation notices.
Optimize load order of many filters.
2025-04-07 09:15:21 -06:00

165 lines
3.7 KiB
PHP

<?php
/**
* Light Ajax Implementation
*
* Helper class that mimics the Admin Ajax URL.
* Based on the code found on: https://coderwall.com/p/of7y2q/faster-ajax-for-wordpress
*
* @package WP_Ultimo
* @subpackage Light_Ajax
* @since 2.0.0
*/
namespace WP_Ultimo;
// Exit if accessed directly
defined('ABSPATH') || exit;
/**
* Adds a lighter ajax option to WP Multisite WaaS.
*
* @since 1.9.14
*/
class Light_Ajax {
use \WP_Ultimo\Traits\Singleton;
/**
* Sets up the listener
*
* @since 2.0.0
*/
public function __construct() {
if (isset($_REQUEST['wu-ajax'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$action = $this->get_when_to_run();
wu_x_header("X-Ultimo-Ajax-When: $action");
add_action($action, [$this, 'process_light_ajax'], 20);
}
}
/**
* Actions that can ignore the referer check.
*
* @since 2.0.4
* @return array
*/
protected function should_skip_referer_check(): bool {
$allowed_actions = apply_filters(
'wu_light_ajax_should_skip_referer_check',
[
/**
* Checkout Form Actions
*
* They're here because in some cases,
* the caching settings might prevent nonces from
* being properly refreshed, which could cause 403
* errors with the actions below.
*/
'wu_render_field_template',
'wu_create_order',
'wu_validate_form',
]
);
return in_array(wu_request('action', 'no-action'), $allowed_actions, true);
}
/**
* Gets the hook we should use to attach the light ajax runner to.
*
* By default, we use plugins_loaded to make sure we run as early
* as possible. This allows us to shave off almost 50% of the
* TTFB delay with these requests when compared with the regular
* WordPress admin-ajax.php.
*
* @since 2.0.0
* @return string
*/
public function get_when_to_run() {
/**
* For security reasons, we limit the number of actions
* available for hooking into. This filter allows developers
* to expand that list if necessary.
*
* @since 2.0.0
* @return array The hook list.
*/
$allowed_list = apply_filters(
'wu_light_ajax_allowed_hooks',
[
'plugins_loaded',
'setup_theme',
'after_setup_theme',
'init',
]
);
$action = isset($_REQUEST['wu-when']) ? base64_decode((string) $_REQUEST['wu-when']) : 'plugins_loaded'; // phpcs:ignore WordPress
return in_array($action, $allowed_list, true) ? $action : 'plugins_loaded';
}
/**
* Adds an wu_ajax handler.
*
* @since 1.9.14
* @return void
*/
public function process_light_ajax(): void {
// mimic the actual admin-ajax
define('DOING_AJAX', true); // phpcs:ignore
/**
* Do some light validation of the referrer,
* Just to make sure script kiddies are not using it
* as an API endpoint.
*/
$this->should_skip_referer_check() === false && check_ajax_referer('wu-ajax-nonce', 'r');
/**
* In some cases, we'll need to load extra juice to handle actions.
* This action can be used to load extra dependencies when needed.
*
* @since 2.0.0
*/
do_action('wu_before_light_ajax');
/** Allow for cross-domain requests (from the front end). */
send_origin_headers();
header('Content-Type: text/html; charset=' . get_blog_option(wu_get_main_site_id(), 'blog_charset'));
header('X-Robots-Tag: noindex');
if (empty($_REQUEST['action'])) {
status_header(400);
die('0');
}
send_nosniff_header();
// Disable caching
nocache_headers();
header('Pragma: no-cache');
$action = esc_attr(trim((string) $_REQUEST['action'])); // phpcs:ignore
if (is_user_logged_in()) {
do_action('wu_ajax_' . $action); // phpcs:ignore
} else {
do_action('wu_ajax_nopriv_' . $action); // phpcs:ignore
}
die('1');
}
}