This commit is contained in:
2026-07-02 15:54:39 -06:00
commit 9883323161
17470 changed files with 4470592 additions and 0 deletions
@@ -0,0 +1,14 @@
<?php
/**
* All in One SEO compatibility for Boost
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\AIOSEO;
use Automattic\Jetpack_Boost\Jetpack_Boost;
// Add the Critical CSS generation query arg to the list of allowed query args of All in One SEO.
// This prevents All in One SEO from removing the query arg, which breaks Critical CSS generation.
add_filter( 'aioseo_unrecognized_allowed_query_args', array( Jetpack_Boost::class, 'whitelist_query_args' ) );
@@ -0,0 +1,53 @@
<?php
/**
* Compatibility for Beaver Builder (both lite and Pro versions).
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Beaver_Builder;
/**
* Exclude Beaver Builder custom post types from list of posts to generate critical CSS for.
*
* @param array $post_types Post types.
*/
function exclude_beaver_builder_custom_post_types( $post_types ) {
unset( $post_types['fl-builder-template'] );
unset( $post_types['fl-theme-layout'] );
return $post_types;
}
add_filter( 'jetpack_boost_critical_css_post_types_singular', __NAMESPACE__ . '\exclude_beaver_builder_custom_post_types' );
add_filter( 'jetpack_boost_critical_css_post_types_archives', __NAMESPACE__ . '\exclude_beaver_builder_custom_post_types' );
/**
* Disable JS concatenation when Beaver Builder editor is active.
* The editor depends on specific script execution order that concatenation breaks.
*
* @param bool $do_concat Whether to concatenate the script.
* @param string $handle Script handle.
* @return bool
*/
function disable_js_concatenate_for_beaver_builder( $do_concat, $handle ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
// Check for fl_builder query parameter (BB editor mode)
// BB uses ?fl_builder (no value) to indicate editor mode
$is_bb_editor = filter_input( INPUT_GET, 'fl_builder' );
if ( null !== $is_bb_editor ) {
return false;
}
// Fallback: Check BB's native function for builder active state
// @phan-suppress-next-line PhanUndeclaredClassReference
if ( class_exists( 'FLBuilderModel' ) && method_exists( 'FLBuilderModel', 'is_builder_active' ) ) {
/** @phan-suppress-next-line PhanUndeclaredClassMethod */
if ( \FLBuilderModel::is_builder_active() ) {
return false;
}
}
return $do_concat;
}
add_filter( 'js_do_concat', __NAMESPACE__ . '\disable_js_concatenate_for_beaver_builder', 10, 2 );
@@ -0,0 +1,26 @@
<?php
/**
* Compatibility for Breakdance
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Breakdance;
/**
* Exclude Breakdance custom post types from list of posts to generate critical CSS for.
*
* @param array $post_types Post types.
*/
function exclude_breakdance_custom_post_types( $post_types ) {
if ( defined( 'BREAKDANCE_ALL_EDITABLE_POST_TYPES' ) ) {
foreach ( BREAKDANCE_ALL_EDITABLE_POST_TYPES as $post_type ) {
unset( $post_types[ $post_type ] );
}
}
return $post_types;
}
add_filter( 'jetpack_boost_critical_css_post_types_singular', __NAMESPACE__ . '\exclude_breakdance_custom_post_types' );
add_filter( 'jetpack_boost_critical_css_post_types_archives', __NAMESPACE__ . '\exclude_breakdance_custom_post_types' );
@@ -0,0 +1,44 @@
<?php
/**
* Compatibility for AMP.
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Amp;
use Automattic\Jetpack_Boost\Modules\Optimizations\Critical_CSS\Critical_CSS;
/**
* Class AMP.
*/
class Amp {
/**
* Critical_CSS module instance.
*
* @var Critical_CSS
*/
private static $critical_css;
/**
* Init AMP compatibility actions after modules are initialized.
*
* @param Critical_CSS $module Critical_CSS Module instance.
*/
public static function init_compatibility( $module ) {
self::$critical_css = $module;
add_action( 'wp', array( __CLASS__, 'disable_critical_css' ), 0 );
}
/**
* Disable Critical CSS display.
*/
public static function disable_critical_css() {
if ( amp_is_request() ) {
remove_action( 'wp', array( self::$critical_css, 'display_critical_css' ) );
}
}
}
add_action( 'jetpack_boost_critical-css_initialized', array( __NAMESPACE__ . '\Amp', 'init_compatibility' ) );
@@ -0,0 +1,43 @@
<?php
/**
* Compatibility functions for Divi Builder
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Divi;
/**
* Defer JS can break Divi Builder.
*/
function disable_defer_js_for_divi_builder( $should_defer_js ) {
$is_divi_builder = filter_input( INPUT_GET, 'et_fb', FILTER_VALIDATE_INT );
if ( 1 === (int) $is_divi_builder ) {
return false;
}
$is_divi_preview = filter_input(
INPUT_GET,
'et_pb_preview',
FILTER_VALIDATE_BOOLEAN,
array(
'flags' => FILTER_NULL_ON_FAILURE,
)
);
if ( true === $is_divi_preview ) {
return false;
}
if ( function_exists( 'is_et_pb_preview' ) ) {
/** @phan-suppress-next-line PhanUndeclaredFunction */
if ( \is_et_pb_preview() ) {
return false;
}
}
return $should_defer_js;
}
add_filter( 'jetpack_boost_should_defer_js', __NAMESPACE__ . '\disable_defer_js_for_divi_builder' );
@@ -0,0 +1,37 @@
<?php
/**
* Compatibility functions for Elementor
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Elementor;
/**
* Exclude Elementor Library custom post type from the list of post types to get urls from.
*
* @param array $post_types Post types.
*/
function exclude_elementor_library_custom_post_type( $post_types ) {
if ( defined( '\Elementor\TemplateLibrary\Source_Local::CPT' ) ) {
unset( $post_types[ \Elementor\TemplateLibrary\Source_Local::CPT ] );
}
// Elementor's landing pages are broken. See https://github.com/elementor/elementor/issues/16244
if ( defined( '\Elementor\Modules\LandingPages\Module::CPT' ) ) {
unset( $post_types[ \Elementor\Modules\LandingPages\Module::CPT ] );
}
if ( defined( '\Elementor\Modules\FloatingButtons\Module::CPT_FLOATING_BUTTONS' ) ) {
unset( $post_types[ \Elementor\Modules\FloatingButtons\Module::CPT_FLOATING_BUTTONS ] );
}
if ( isset( $post_types['elementor-hf'] ) ) {
unset( $post_types['elementor-hf'] );
}
return $post_types;
}
add_filter( 'jetpack_boost_critical_css_post_types_singular', __NAMESPACE__ . '\exclude_elementor_library_custom_post_type' );
add_filter( 'jetpack_boost_critical_css_post_types_archives', __NAMESPACE__ . '\exclude_elementor_library_custom_post_type' );
@@ -0,0 +1,41 @@
<?php
/**
* Jetpack compatibility for Boost
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Jetpack;
require_once __DIR__ . '/lib/class-sync-jetpack-module-status.php';
( new Sync_Jetpack_Module_Status( 'image_cdn', 'photon' ) )->init();
/**
* Exclude Jetpack likes scripts from deferred JS. They are already in the footer,
* and are sensitive to having their order changed relative to their companion iframe.
*
* @param array $exclusions The default array of scripts to exclude from deferral.
*/
function exclude_jetpack_likes_scripts_defer( $exclusions ) {
static $likes_enabled = null;
if ( null === $likes_enabled ) {
$likes_enabled = \Jetpack::is_module_active( 'likes' );
}
if ( $likes_enabled ) {
return array_merge(
$exclusions,
array(
'jquery-core',
'postmessage',
'jetpack_likes_queuehandler',
)
);
}
return $exclusions;
}
add_filter( 'jetpack_boost_render_blocking_js_exclude_handles', __NAMESPACE__ . '\exclude_jetpack_likes_scripts_defer', 10, 1 );
@@ -0,0 +1,30 @@
<?php
/**
* Exclude known scripts that causes problem when concatenated.
*/
namespace Automattic\Jetpack_Boost\Compatibility\JS_Concatenate;
function maybe_do_not_concat( $do_concat, $handle ) {
$excluded_handles = array(
// Plugin: `event-tickets`
'tribe-tickets-block',
'tribe-tickets-provider',
// Plugin: `woocommerce-shipping`
'woocommerce-shipping-checkout-address-validation',
// Plugin: `depay-payments-for-woocommerce`
'DEPAY_WC_WIDGETS',
// Plugin: `woocommerce-bookings`
'wc-bookings-booking-form',
// WooCommerce Analytics
'woocommerce-analytics-client',
);
if ( in_array( $handle, $excluded_handles, true ) ) {
return false;
}
return $do_concat;
}
add_filter( 'js_do_concat', __NAMESPACE__ . '\maybe_do_not_concat', 10, 2 );
@@ -0,0 +1,135 @@
<?php
namespace Automattic\Jetpack_Boost\Compatibility\Jetpack;
use Automattic\Jetpack_Boost\Modules\Features_Index;
use Automattic\Jetpack_Boost\Modules\Module;
/**
* Class that handles the sync of Jetpack module status to Boost module status.
*/
class Sync_Jetpack_Module_Status {
/**
* Slug of the Jetpack module
*
* @var string
*/
public $jetpack_module_slug;
/**
* Slug of the Boost module
*
* @var string
*/
public $boost_module_slug;
public function __construct( $boost_module_slug, $jetpack_module_slug ) {
$this->boost_module_slug = str_replace( '_', '-', $boost_module_slug );
$this->jetpack_module_slug = $jetpack_module_slug;
}
public function init() {
// Use Jetpack as the source of truth for the module status
add_filter( "default_option_jetpack_boost_status_{$this->boost_module_slug}", array( $this, 'get_jetpack_module_status' ) );
add_filter( "option_jetpack_boost_status_{$this->boost_module_slug}", array( $this, 'get_jetpack_module_status' ) );
add_filter( 'jetpack_get_available_modules', array( $this, 'alter_jetpack_available_modules' ) );
$this->add_sync_to_jetpack_action();
$this->add_sync_from_jetpack_action();
/**
* Update the Jetpack Boost option to match the Jetpack option,
* in case the options are out of sync when the page is loaded.
*/
add_action( 'load-jetpack_page_jetpack-boost', array( $this, 'sync_from_jetpack' ) );
}
/**
* If a Boost module is not available, remove it from the Jetpack available modules as well.
*
* This is useful in situations like disabling a Boost module with URL parameter.
*/
public function alter_jetpack_available_modules( $jetpack_modules ) {
foreach ( Features_Index::FEATURES as $feature_class ) {
if ( str_replace( '_', '-', $feature_class::get_slug() ) !== $this->boost_module_slug ) {
continue;
}
$boost_module = new Module( new $feature_class() );
if ( ! $boost_module->is_available() ) {
unset( $jetpack_modules[ $this->jetpack_module_slug ] );
break;
}
}
return $jetpack_modules;
}
/**
* Get the status of the Jetpack module
*
* @return string
*/
public function get_jetpack_module_status() {
return (string) \Jetpack::is_module_active( $this->jetpack_module_slug );
}
/**
* Forward all module status changes to Jetpack
* when interacting with Jetpack Boost dashboard.
*/
public function sync_to_jetpack( $_unused, $new_value ) {
$this->remove_sync_from_jetpack_action();
if ( $new_value ) {
\Jetpack::activate_module( $this->jetpack_module_slug, false, false );
} else {
\Jetpack::deactivate_module( $this->jetpack_module_slug );
}
$this->add_sync_from_jetpack_action();
return $new_value;
}
/**
* The compatibility layer uses Jetpack as the single source of truth for shared modules.
* As a fallback, Boost still keeps track of the value in the database,
* This ensures that the value is still present when Jetpack is deactivated.
*
* This filter is going to track changes to the modules shared between Jetpack and Boost
* and make sure that both plugins are in in sync.
* Example: image_cdn
*/
public function sync_from_jetpack() {
$this->remove_sync_to_jetpack_action();
update_option( "jetpack_boost_status_{$this->boost_module_slug}", \Jetpack::is_module_active( $this->jetpack_module_slug ) );
$this->add_sync_to_jetpack_action();
}
/**
* Sync the status to Boost when interacting with the Jetpack dashboard.
*/
public function add_sync_from_jetpack_action() {
add_action( "jetpack_deactivate_module_{$this->jetpack_module_slug}", array( $this, 'sync_from_jetpack' ), 10, 2 );
add_action( "jetpack_activate_module_{$this->jetpack_module_slug}", array( $this, 'sync_from_jetpack' ), 10, 2 );
}
public function remove_sync_from_jetpack_action() {
remove_action( "jetpack_deactivate_module_{$this->jetpack_module_slug}", array( $this, 'sync_from_jetpack' ), 10 );
remove_action( "jetpack_activate_module_{$this->jetpack_module_slug}", array( $this, 'sync_from_jetpack' ), 10 );
}
/**
* Sync the status to Jetpack when interacting with the Boost dashboard
*/
public function add_sync_to_jetpack_action() {
add_action( "add_option_jetpack_boost_status_{$this->boost_module_slug}", array( $this, 'sync_to_jetpack' ), 10, 2 );
add_action( "update_option_jetpack_boost_status_{$this->boost_module_slug}", array( $this, 'sync_to_jetpack' ), 10, 2 );
}
public function remove_sync_to_jetpack_action() {
remove_action( "add_option_jetpack_boost_status_{$this->boost_module_slug}", array( $this, 'sync_to_jetpack' ), 10 );
remove_action( "update_option_jetpack_boost_status_{$this->boost_module_slug}", array( $this, 'sync_to_jetpack' ), 10 );
}
}
@@ -0,0 +1,52 @@
<?php
/**
* Compatibility file for Page Optimize.
*
* This will synchronize the settings from Page Optimize to Jetpack Boost.
* It will also disable the Page Optimize functionality.
*
* @package automattic/jetpack-boost
*/
if ( function_exists( 'page_optimize_js_default' ) ) {
$page_optimize_js_concatenate = (bool) get_option( 'page_optimize-js', page_optimize_js_default() );
$boost_js_concatenate = get_option( 'jetpack_boost_status_minify-js' );
// Only migrate JS Concatenation if Page Optimize has it enabled
// and if Boost's equivalent hasn't been used at all.
if ( $page_optimize_js_concatenate && false === $boost_js_concatenate ) {
add_option( 'jetpack_boost_status_minify-js', true );
}
}
if ( function_exists( 'page_optimize_js_exclude_list' ) ) {
$boost_js_excludes = get_option( 'jetpack_boost_ds_minify_js_excludes' );
// Only migrate this setting if Boost's equivalent hasn't been used.
if ( false === $boost_js_excludes ) {
$page_optimize_js_excludes = page_optimize_js_exclude_list();
add_option( 'jetpack_boost_ds_minify_js_excludes', $page_optimize_js_excludes );
}
}
if ( function_exists( 'page_optimize_css_default' ) ) {
$css_concatenate = (bool) get_option( 'page_optimize-css', page_optimize_css_default() );
$boost_css_concatenate = get_option( 'jetpack_boost_status_minify-css' );
// Only migrate CSS Concatenation if Page Optimize has it enabled
// and if Boost's equivalent hasn't been used at all.
if ( $css_concatenate && false === $boost_css_concatenate ) {
add_option( 'jetpack_boost_status_minify-css', true );
}
}
if ( function_exists( 'page_optimize_css_exclude_list' ) ) {
$boost_css_excludes = get_option( 'jetpack_boost_ds_minify_css_excludes' );
// Only migrate this setting if Boost's equivalent hasn't been used.
if ( false === $boost_css_excludes ) {
$page_optimize_css_excludes = page_optimize_css_exclude_list();
add_option( 'jetpack_boost_ds_minify_css_excludes', $page_optimize_css_excludes );
}
}
// Disable Page Optimize functionality.
remove_action( 'plugins_loaded', 'page_optimize_init' );
@@ -0,0 +1,38 @@
<?php
/**
* Compatibility for Revolution Slider
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Revslider;
/**
* Exclude Revolution Slider scripts from deferred JS.
* We can't use handles, since revslider doesn't have a standardized naming convention.
*
* @param array $scripts The scripts to exclude.
* @return array The scripts to exclude.
*/
function exclude_revslider_scripts( $scripts ) {
// Don't check scripts if Revolution Slider isn't active.
if ( ! class_exists( '\RevSliderFront' ) ) {
return $scripts;
}
// Filter out any revslider scripts
$scripts = array_filter(
$scripts,
function ( $script ) {
// Check if it's a script tag and contains revslider
if ( is_array( $script ) && isset( $script[0] ) && strpos( $script[0], '<script' ) !== false ) {
return strpos( $script[0], '/revslider/' ) === false;
}
return true;
}
);
return array_values( $scripts );
}
add_filter( 'jetpack_boost_render_blocking_js_exclude_scripts', __NAMESPACE__ . '\exclude_revslider_scripts', 10, 1 );
@@ -0,0 +1,25 @@
<?php
/**
* Compatibility for Web Stories
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Web_Stories;
/**
* Exclude Web Stories pages to be processed by the Render Blocking JS module.
*
* @param bool $should_defer_js default filter value.
*/
function web_stories_should_defer_js( $should_defer_js ) {
if ( class_exists( '\Google\Web_Stories\Story_Post_Type' )
&& defined( '\Google\Web_Stories\Story_Post_Type::POST_TYPE_SLUG' )
&& is_singular( \Google\Web_Stories\Story_Post_Type::POST_TYPE_SLUG ) ) {
return false;
}
return $should_defer_js;
}
add_filter( 'jetpack_boost_should_defer_js', __NAMESPACE__ . '\web_stories_should_defer_js' );
@@ -0,0 +1,55 @@
<?php
/**
* Compatibility functions for WooCommerce
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Woocommerce;
/**
* Exclude special Woocommerce pages from standard "single page" Critical CSS.
*
* @param object $args the query args.
*/
function exclude_woocommerce_pages_from_query( $args ) {
// Only do this for page post type.
if ( 'page' !== $args['post_type'] ) {
return $args;
}
$woocommerce_pages = get_woocommerce_page_ids();
if ( empty( $woocommerce_pages ) ) {
return $args;
}
if ( ! isset( $args['post__not_in'] ) ) {
$args['post__not_in'] = array();
}
$args['post__not_in'] = array_merge( $woocommerce_pages, $args['post__not_in'] );
return $args;
}
/**
* Get those ol' WooCommerce page IDs
*/
function get_woocommerce_page_ids() {
if ( ! function_exists( 'wc_get_page_id' ) ) {
return array();
}
$page_slugs = array( 'myaccount', 'shop', 'cart', 'checkout', 'view_order', 'terms' );
$ids = array_map( 'wc_get_page_id', $page_slugs );
$ids = array_filter(
$ids,
function ( $value ) {
return $value > 0;
}
);
return $ids;
}
add_filter( 'jetpack_boost_critical_css_post_type_query', __NAMESPACE__ . '\exclude_woocommerce_pages_from_query' );
@@ -0,0 +1,58 @@
<?php
/**
* Automatically enable Page Cache when migrating from WP Super Cache.
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Super_Cache;
use Automattic\Jetpack_Boost\Lib\Analytics;
use Automattic\Jetpack_Boost\Lib\Status;
use Automattic\Jetpack_Boost\Modules\Optimizations\Page_Cache\Page_Cache;
/**
* Accept migrations from WP Super Cache
*/
function migrate_from_super_cache() {
// Check if Jetpack Boost Page Cache module is enabled
if ( ! class_exists( Page_Cache::class ) ) {
return;
}
if ( ! Page_Cache::is_available() ) {
return;
}
// If Boost has already activated the Page Cache based on WPSC migration once, we don't want to do it again.
// For example - if the user manually de-activates Page Cache in Boost.
$migration_status = get_transient( 'jb_cache_moved_to_boost' );
// If the cache is already migrated, we don't need to do anything.
if ( get_transient( 'jb_boost_migration_complete' ) ) {
return;
}
// If Super Cache has set the transient, log it to tracks, but only once.
if ( $migration_status && ! get_transient( 'jb_boost_migration_tracked' ) ) {
set_transient( 'jb_boost_migration_tracked', true, 7 * DAY_IN_SECONDS );
Analytics::record_user_event( 'migrated_from_wpsc', array( 'source' => $migration_status ) );
}
// Only proceed to activate Page Cache in Jetpack Boost
// if the user clicked the admin notice.
if ( $migration_status !== 'notice' ) {
return;
}
// Check if Boost has Page Cache already enabled.
$status = new Status( Page_Cache::get_slug() );
if ( $status->get() === true ) {
return;
}
set_transient( 'jb_boost_migration_complete', true, 7 * DAY_IN_SECONDS );
$status->set( true );
}
add_action( 'admin_init', __NAMESPACE__ . '\migrate_from_super_cache' );
@@ -0,0 +1,45 @@
<?php
/**
* Super Cache compatibility for Boost
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Super_Cache;
/**
* Add WP Super Cache bypass query param to the URL.
*
* @param string $url The URL.
*/
function add_bypass_query_param( $url ) {
global $cache_page_secret;
return add_query_arg( 'donotcachepage', $cache_page_secret, $url );
}
/**
* Add WP Super Cache bypass query params to Critical CSS URLs.
*
* @param array $urls list of URLs to generate Critical CSS for.
*/
function critical_css_bypass_super_cache( $urls ) {
return array_map( __NAMESPACE__ . '\add_bypass_query_param', $urls );
}
add_filter( 'jetpack_boost_critical_css_urls', __NAMESPACE__ . '\critical_css_bypass_super_cache' );
/**
* Clear Super Cache's cache. Called when Critical CSS finishes generating, or
* when a module is enabled or disabled.
*/
function clear_cache() {
global $wpdb;
if ( function_exists( 'wp_cache_clear_cache' ) ) {
wp_cache_clear_cache( $wpdb->blogid );
}
// Remove the action so it doesn't run again during the same request.
remove_action( 'jetpack_boost_page_output_changed', __NAMESPACE__ . '\clear_cache' );
}
add_action( 'jetpack_boost_page_output_changed', __NAMESPACE__ . '\clear_cache' );
@@ -0,0 +1,14 @@
<?php
/**
* Yoast SEO compatibility for Boost
*
* @package automattic/jetpack-boost
*/
namespace Automattic\Jetpack_Boost\Compatibility\Yoast;
use Automattic\Jetpack_Boost\Jetpack_Boost;
// Add the Critical CSS generation query arg to Yoast's allowed query args list.
// This prevents Yoast from removing the query arg, which breaks Critical CSS generation.
add_filter( 'Yoast\WP\SEO\allowlist_permalink_vars', array( Jetpack_Boost::class, 'whitelist_query_args' ) );