3544 lines
125 KiB
PHP
3544 lines
125 KiB
PHP
<?php
|
|
namespace WpAssetCleanUp;
|
|
|
|
use WpAssetCleanUp\OptimiseAssets\CombineJs;
|
|
use WpAssetCleanUp\OptimiseAssets\DynamicLoadedAssets;
|
|
use WpAssetCleanUp\OptimiseAssets\OptimizeCommon;
|
|
|
|
/**
|
|
* Class Main
|
|
* @package WpAssetCleanUp
|
|
*/
|
|
class Main
|
|
{
|
|
/**
|
|
*
|
|
*/
|
|
const START_DEL_ENQUEUED = 'BEGIN WPACU PLUGIN JSON ENQUEUED';
|
|
|
|
/**
|
|
*
|
|
*/
|
|
const END_DEL_ENQUEUED = 'END WPACU PLUGIN JSON ENQUEUED';
|
|
|
|
/**
|
|
*
|
|
*/
|
|
const START_DEL_HARDCODED = 'BEGIN WPACU PLUGIN JSON HARDCODED';
|
|
|
|
/**
|
|
*
|
|
*/
|
|
const END_DEL_HARDCODED = 'END WPACU PLUGIN JSON HARDCODED';
|
|
|
|
/**
|
|
* Option "Plugin Usage Preferences" -> "Manage in the Dashboard" -> "Select a retrieval way:" ('Direct' or 'WP Remote Post')
|
|
*
|
|
* @var string
|
|
*/
|
|
public static $domGetType = 'direct';
|
|
|
|
/**
|
|
* Record them for debugging purposes when using /?wpacu_debug
|
|
*
|
|
* @var array
|
|
*/
|
|
public $allUnloadedAssets = array( 'styles' => array(), 'scripts' => array() );
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $globalUnloaded = array();
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $loadExceptionsPageLevel = array( 'styles' => array(), 'scripts' => array(), '_set' => false );
|
|
|
|
/**
|
|
* @var array[]
|
|
*/
|
|
public $loadExceptionsPostType = array( 'styles' => array(), 'scripts' => array(), '_set' => false );
|
|
|
|
/**
|
|
* Rule that applies site-wide: if the user is logged-in
|
|
*
|
|
* @var array
|
|
*/
|
|
public $loadExceptionsLoggedInGlobal = array( 'styles' => array(), 'scripts' => array(), '_set' => false );
|
|
|
|
/**
|
|
* @var
|
|
*/
|
|
public $fetchUrl;
|
|
|
|
// [wpacu_lite]
|
|
/**
|
|
* @var
|
|
*/
|
|
public $isUpdateable = true;
|
|
// [/wpacu_lite]
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
public $currentPostId = 0;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $currentPost = array();
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public static $vars = array( 'woo_url_not_match' => false, 'is_woo_shop_page' => false, 'for_type' => '', 'current_post_id' => 0, 'current_post_type' => '' );
|
|
|
|
/**
|
|
* This is set to `true` only if "Manage in the Front-end?" is enabled in plugin's settings
|
|
* and the logged-in administrator with plugin activation privileges
|
|
* is outside the Dashboard viewing the pages like a visitor
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $isFrontendEditView = false;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $stylesInHead = array();
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $scriptsInHead = array();
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $assetsInFooter = array( 'styles' => array(), 'scripts' => array() );
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $wpAllScripts = array();
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $wpAllStyles = array();
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $ignoreChildren = array();
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $ignoreChildrenHandlesOnTheFly = array();
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
public static $wpStylesSpecialDelimiters = array(
|
|
'start' => '<!--START-WPACU-SPECIAL-STYLES',
|
|
'end' => 'END-WPACU-SPECIAL-STYLES-->'
|
|
);
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $postTypesUnloaded = array();
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $settings = array();
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
public $isAjaxCall = false;
|
|
|
|
/**
|
|
* Fetch CSS/JS list from the Dashboard
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $isGetAssetsCall = false;
|
|
|
|
/**
|
|
* Populated in the Parser constructor
|
|
*
|
|
* @var array
|
|
*/
|
|
public $skipAssets = array( 'styles' => array(), 'scripts' => array() );
|
|
|
|
/**
|
|
* For these handles, it's strongly recommended to use 'Ignore dependency rule and keep the "children" loaded'
|
|
* if any of them are unloaded in any page
|
|
*
|
|
* @var \string[][]
|
|
*/
|
|
public $keepChildrenLoadedForHandles = array(
|
|
'css' => array(
|
|
'elementor-icons'
|
|
),
|
|
'js' => array(
|
|
'swiper',
|
|
'elementor-waypoints',
|
|
'share-link'
|
|
)
|
|
);
|
|
|
|
/**
|
|
* @var Main|null
|
|
*/
|
|
private static $singleton;
|
|
|
|
/**
|
|
* @return null|Main
|
|
*/
|
|
public static function instance()
|
|
{
|
|
if ( self::$singleton === null ) {
|
|
self::$singleton = new self();
|
|
}
|
|
|
|
return self::$singleton;
|
|
}
|
|
|
|
/**
|
|
* Parser constructor.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->skipAssets['styles'] = array_merge(
|
|
array(
|
|
'admin-bar',
|
|
// The top admin bar
|
|
'yoast-seo-adminbar',
|
|
// Yoast "WordPress SEO" plugin
|
|
'autoptimize-toolbar',
|
|
'query-monitor',
|
|
'wp-fastest-cache-toolbar',
|
|
// WP Fastest Cache plugin toolbar CSS
|
|
'litespeed-cache',
|
|
// LiteSpeed toolbar
|
|
'siteground-optimizer-combined-styles-header'
|
|
// Combine CSS in SG Optimiser (irrelevant as it made from the combined handles)
|
|
),
|
|
// Own Scripts (for admin use only)
|
|
OwnAssets::getOwnAssetsHandles('styles')
|
|
);
|
|
|
|
$this->skipAssets['scripts'] = array_merge(
|
|
array(
|
|
'admin-bar', // The top admin bar
|
|
'autoptimize-toolbar',
|
|
'query-monitor',
|
|
'wpfc-toolbar' // WP Fastest Cache plugin toolbar JS
|
|
),
|
|
// Own Scripts (for admin use only)
|
|
OwnAssets::getOwnAssetsHandles('scripts')
|
|
);
|
|
|
|
// Filter before triggering the actual unloading through "wp_deregister_script", "wp_dequeue_script", "wp_deregister_style", "wp_dequeue_style"
|
|
$this->fallbacks();
|
|
|
|
$this->isAjaxCall = ( ! empty( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) === 'xmlhttprequest' );
|
|
$this->isGetAssetsCall = isset( $_REQUEST[ WPACU_LOAD_ASSETS_REQ_KEY ] ) && $_REQUEST[ WPACU_LOAD_ASSETS_REQ_KEY ];
|
|
|
|
if ( $this->isGetAssetsCall ) {
|
|
$currentTheme = strtolower(wp_get_theme());
|
|
$noRocketInit = true;
|
|
|
|
if (strpos($currentTheme, 'uncode') !== false) {
|
|
$noRocketInit = false; // make exception for the "Uncode" Theme as it doesn't check if the get_rocket_option() function exists
|
|
}
|
|
|
|
if ($noRocketInit) {
|
|
add_filter('rocket_cache_reject_uri', function($urls) {
|
|
$urls[] = '/?wpassetcleanup_load=1';
|
|
return $urls;
|
|
});
|
|
}
|
|
|
|
// Do not output Query Monitor's information as it's irrelevant in this context
|
|
if ( class_exists( '\QueryMonitor' ) && class_exists( '\QM_Plugin' ) ) {
|
|
add_filter( 'user_has_cap', static function( $user_caps ) {
|
|
$user_caps['view_query_monitor'] = false;
|
|
return $user_caps;
|
|
}, 10, 1 );
|
|
}
|
|
|
|
add_filter( 'style_loader_tag', static function( $styleTag, $tagHandle ) {
|
|
// This is used to determine if the LINK is enqueued later on
|
|
// If the handle name is not showing up, then the LINK stylesheet has been hardcoded (not enqueued the WordPress way)
|
|
return str_replace( '<link ', '<link data-wpacu-style-handle=\'' . $tagHandle . '\' ', $styleTag );
|
|
}, PHP_INT_MAX, 2 ); // Trigger it later in case plugins such as "Ronneby Core" plugin alters it
|
|
|
|
add_filter( 'script_loader_tag', static function( $scriptTag, $tagHandle ) {
|
|
// This is used to determine if the SCRIPT is enqueued later on
|
|
// If the handle name is not showing up, then the SCRIPT has been hardcoded (not enqueued the WordPress way)
|
|
$reps = array( '<script ' => '<script data-wpacu-script-handle=\'' . $tagHandle . '\' ' );
|
|
|
|
return str_replace( array_keys( $reps ), array_values( $reps ), $scriptTag );
|
|
}, PHP_INT_MAX, 2 );
|
|
}
|
|
|
|
// "File Size:" value from the asset row
|
|
add_filter('wpacu_get_asset_file_size', array($this, 'getAssetFileSize'), 10, 2);
|
|
|
|
// Triggers only if the administrator is logged in ('wp_ajax_nopriv' is not required)
|
|
// Used to determine the total size of an external loaded assets (e.g. a CSS file from Google APIs)
|
|
add_action('wp_ajax_'.WPACU_PLUGIN_ID.'_get_external_file_size', array($this, 'ajaxGetExternalFileSize'));
|
|
|
|
// Early Triggers
|
|
$wpacuAction = Misc::isElementorMaintenanceModeOn() ? 'template_redirect' : 'wp';
|
|
|
|
if ($wpacuAction === 'wp') {
|
|
add_action( 'wp', array( $this, 'setVarsBeforeUpdate' ), 8 );
|
|
add_action( 'wp', array( $this, 'setVarsAfterAnyUpdate' ), 10 );
|
|
} else {
|
|
add_action( 'template_redirect', array( $this, 'setVarsBeforeUpdate' ), 12 ); // over 11 which is set in Elementor's maintenance-mode.php
|
|
add_action( 'template_redirect', array( $this, 'setVarsAfterAnyUpdate' ), 13 );
|
|
}
|
|
|
|
// Fetch Assets AJAX Call? Make sure the output is as clean as possible (no plugins interfering with it)
|
|
// It can also be used for debugging purposes (via /?wpacu_clean_load) when you want to view all the CSS/JS
|
|
// that are loaded in the HTML source code before they are unloaded or altered in any way
|
|
if ( $this->isGetAssetsCall || isset($_GET['wpacu_clean_load']) ) {
|
|
$wpacuCleanUp = new CleanUp();
|
|
$wpacuCleanUp->cleanUpHtmlOutputForAssetsCall();
|
|
}
|
|
|
|
// "Direct" AJAX call or "WP Remote Post" method used?
|
|
// Do not trigger the admin bar as it's not relevant
|
|
if ( $this->isAjaxCall || $this->isGetAssetsCall ) {
|
|
add_filter( 'show_admin_bar', '__return_false' );
|
|
}
|
|
|
|
// This is triggered AFTER "saveSettings" from 'Settings' class
|
|
// In case the settings were just updated, the script will get the latest values
|
|
add_action( 'init', array( $this, 'triggersAfterInit' ), 10 );
|
|
|
|
// Front-end View - Unload the assets
|
|
// If there are reasons to prevent the unloading in case 'test mode' is enabled,
|
|
// then the prevention will trigger within filterStyles() and filterScripts()
|
|
|
|
if ( ! is_admin() ) {
|
|
$this->alterWpStylesScriptsObj();
|
|
}
|
|
|
|
/*
|
|
* [START] /?wpassetcleanup_load=1 is called
|
|
*/
|
|
if ( $this->isGetAssetsCall && ! is_admin() ) {
|
|
// These actions are also called when the page is loaded without query string (regular load)
|
|
// This time, the CSS/JS will not be unloaded, but the CSS/JS marked for unload will be collected
|
|
// and passed to the AJAX call for the option "Group by loaded or unloaded status"
|
|
if ( get_option( 'siteground_optimizer_combine_css' ) ) {
|
|
add_action( 'wp_print_styles', array( $this, 'filterStyles' ), 9 ); // priority should be below 10
|
|
}
|
|
add_action( 'wp_print_styles', array( $this, 'filterStyles' ), 100000 );
|
|
add_action( 'wp_print_scripts', array( $this, 'filterScripts' ), 100000 );
|
|
add_action( 'wp_print_footer_scripts', array( $this, 'onPrintFooterScriptsStyles' ), 1 );
|
|
}
|
|
/*
|
|
* [END] /?wpassetcleanup_load=1 is called
|
|
*/
|
|
|
|
/*
|
|
* [START] Front-end page visited (e.g. by the admin or a guest visitor)
|
|
*/
|
|
if ( ! $this->isGetAssetsCall && ! is_admin() ) {
|
|
// [START] Unload CSS/JS on page request (for debugging)
|
|
add_filter( 'wpacu_ignore_child_parent_list', array( $this, 'filterIgnoreChildParentList' ) );
|
|
// [END] Unload CSS/JS on page request (for debugging)
|
|
|
|
// SG Optimizer Compatibility: Unload Styles - HEAD (Before pre_combine_header_styles() from Combinator)
|
|
if ( get_option( 'siteground_optimizer_combine_css' ) ) {
|
|
add_action( 'wp_print_styles', array( $this, 'filterStyles' ), 9 ); // priority should be below 10
|
|
}
|
|
|
|
$this->filterStylesSpecialCases(); // e.g. CSS enqueued in a different way via Oxygen Builder
|
|
|
|
add_action( 'wp_print_styles', array( $this, 'filterStyles' ), 100000 ); // Unload Styles - HEAD
|
|
add_action( 'wp_print_scripts', array( $this, 'filterScripts' ), 100000 ); // Unload Scripts - HEAD
|
|
|
|
add_action( 'wp_print_styles', array($this, 'printAnySpecialCss'), PHP_INT_MAX );
|
|
|
|
// Unload Styles & Scripts - FOOTER
|
|
// Needs to be triggered very soon as some old plugins/themes use wp_footer() to enqueue scripts
|
|
// Sometimes styles are loaded in the BODY section of the page
|
|
add_action( 'wp_print_footer_scripts', array( $this, 'onPrintFooterScriptsStyles' ), 1 );
|
|
|
|
// Preloads
|
|
add_action( 'wp_head', static function() {
|
|
if ( Plugin::preventAnyFrontendOptimization() || self::isTestModeActive() ) {
|
|
return;
|
|
}
|
|
|
|
// Only place the market IF there's at least one preload OR combine JS is activated
|
|
$preloadsClass = new Preloads();
|
|
|
|
if ( isset( $preloadsClass->preloads[ 'styles' ] ) && ! empty( $preloadsClass->preloads[ 'styles' ] ) ) {
|
|
echo Preloads::DEL_STYLES_PRELOADS;
|
|
}
|
|
|
|
if ( (isset( $preloadsClass->preloads[ 'scripts' ] ) && ! empty( $preloadsClass->preloads[ 'scripts' ] )) || CombineJs::proceedWithJsCombine() ) {
|
|
echo Preloads::DEL_SCRIPTS_PRELOADS;
|
|
}
|
|
}, 1 );
|
|
|
|
add_filter( 'style_loader_tag', static function( $styleTag, $tagHandle ) {
|
|
if ( Plugin::preventAnyFrontendOptimization() ) {
|
|
return $styleTag;
|
|
}
|
|
|
|
// Preload the plugin's CSS for assets management layout (for faster content paint if the user is logged-in and manages the assets in the front-end)
|
|
// For a better admin experience
|
|
if ( $tagHandle === WPACU_PLUGIN_ID . '-style' ) {
|
|
$styleTag = str_ireplace(
|
|
array( '<link ', 'rel=\'stylesheet\'', 'rel="stylesheet"', 'id=\'', 'id="' ),
|
|
array(
|
|
'<link rel=\'preload\' as=\'style\' data-wpacu-preload-it-async=\'1\' ',
|
|
'onload="this.onload=null;this.rel=\'stylesheet\'"',
|
|
'onload="this.rel=\'stylesheet\'"',
|
|
'id=\'wpacu-preload-',
|
|
'id="wpacu-preload-'
|
|
),
|
|
$styleTag
|
|
);
|
|
}
|
|
|
|
// Irrelevant for Critical CSS as the top admin bar is for logged-in users
|
|
// and if it's not included in the critical CSS it would cause a flash of unstyled content which is not pleasant for the admin
|
|
if ( $tagHandle === 'admin-bar' ) {
|
|
$styleTag = str_replace( '<link ', '<link data-wpacu-skip-preload=\'1\' ', $styleTag );
|
|
}
|
|
|
|
if ( Plugin::preventAnyFrontendOptimization() || self::isTestModeActive() ) {
|
|
return $styleTag;
|
|
}
|
|
|
|
// Alter for debugging purposes; triggers before anything else
|
|
// e.g. you're working on a website and there is no Dashboard access and you want to determine the handle name
|
|
// if the handle name is not showing up, then the LINK stylesheet has been hardcoded (not enqueued the WordPress way)
|
|
if ( isset($_GET['wpacu_show_handle_names']) ) {
|
|
$styleTag = str_replace( '<link ', '<link data-wpacu-debug-style-handle=\'' . $tagHandle . '\' ', $styleTag );
|
|
}
|
|
|
|
if ( strpos( $styleTag, 'data-wpacu-style-handle' ) === false ) {
|
|
$styleTag = str_replace( '<link ', '<link data-wpacu-style-handle=\'' . $tagHandle . '\' ', $styleTag );
|
|
}
|
|
|
|
return $styleTag;
|
|
}, PHP_INT_MAX, 2 ); // Trigger it later in case plugins such as "Ronneby Core" plugin alters it
|
|
|
|
add_filter( 'script_loader_tag', static function( $scriptTag, $tagHandle ) {
|
|
if ( Plugin::preventAnyFrontendOptimization() ) {
|
|
return $scriptTag;
|
|
}
|
|
|
|
// Alter for debugging purposes; triggers before anything else
|
|
// e.g. you're working on a website and there is no Dashboard access and you want to determine the handle name
|
|
// if the handle name is not showing up, then the SCRIPT has been hardcoded (not enqueued the WordPress way)
|
|
if ( isset($_GET['wpacu_show_handle_names']) ) {
|
|
$scriptTag = str_replace( '<script ', '<script data-wpacu-debug-script-handle=\'' . $tagHandle . '\' ', $scriptTag );
|
|
}
|
|
|
|
if ( strpos( $scriptTag, 'data-wpacu-script-handle' ) === false
|
|
&& Menu::userCanManageAssets()
|
|
&& self::instance()->isFrontendEditView ) {
|
|
$scriptTag = str_replace( '<script ', '<script data-wpacu-script-handle=\'' . $tagHandle . '\' ', $scriptTag );
|
|
}
|
|
|
|
if ( Plugin::preventAnyFrontendOptimization() || self::isTestModeActive() ) {
|
|
return $scriptTag;
|
|
}
|
|
|
|
if ( strpos( $scriptTag, 'data-wpacu-script-handle' ) === false ) {
|
|
$scriptTag = str_replace( '<script ', '<script data-wpacu-script-handle=\'' . $tagHandle . '\' ', $scriptTag );
|
|
}
|
|
|
|
if ( $tagHandle === 'jquery-core' ) {
|
|
$scriptTag = str_replace( '<script ', '<script data-wpacu-jquery-core-handle=1 ', $scriptTag );
|
|
}
|
|
|
|
if ( $tagHandle === 'jquery-migrate' ) {
|
|
$scriptTag = str_replace( '<script ', '<script data-wpacu-jquery-migrate-handle=1 ', $scriptTag );
|
|
}
|
|
|
|
return $scriptTag;
|
|
}, PHP_INT_MAX, 2 );
|
|
|
|
Preloads::instance()->init();
|
|
}
|
|
/*
|
|
* [END] Front-end page visited (e.g. by the admin or a guest visitor)
|
|
*/
|
|
|
|
// Only trigger it within the Dashboard when an Asset CleanUp (Pro) page is accessed and the transient is non-existent or expired
|
|
if ( is_admin() ) {
|
|
add_action( 'admin_footer', array( $this, 'ajaxFetchActivePluginsJsFooterCode' ) );
|
|
add_action( 'wp_ajax_' . WPACU_PLUGIN_ID . '_fetch_active_plugins_icons', array( $this, 'ajaxFetchActivePluginsIconsFromWordPressOrg' ) );
|
|
}
|
|
|
|
add_filter( 'duplicate_post_meta_keys_filter', static function( $meta_keys ) {
|
|
// Get the original post ID
|
|
$postId = isset( $_GET['post'] ) ? (int)$_GET['post'] : false;
|
|
|
|
if ( ! $postId ) {
|
|
$postId = isset( $_POST['post'] ) ? (int)$_POST['post'] : false;
|
|
}
|
|
|
|
if ( $postId ) {
|
|
global $wpdb;
|
|
|
|
$metaKeyLike = '_' . WPACU_PLUGIN_ID . '_%';
|
|
|
|
$assetCleanUpMetaKeysQuery = <<<SQL
|
|
SELECT `meta_key` FROM {$wpdb->postmeta} WHERE meta_key LIKE '{$metaKeyLike}' AND post_id='{$postId}'
|
|
SQL;
|
|
$assetCleanUpMetaKeys = $wpdb->get_col( $assetCleanUpMetaKeysQuery );
|
|
|
|
if ( ! empty( $assetCleanUpMetaKeys ) ) {
|
|
$meta_keys = array_merge( $meta_keys, $assetCleanUpMetaKeys );
|
|
}
|
|
}
|
|
|
|
return $meta_keys;
|
|
} );
|
|
|
|
$this->wpacuHtmlNoticeForAdmin();
|
|
|
|
add_action( 'wp_ajax_' . WPACU_PLUGIN_ID . '_check_external_urls_for_status_code', array( $this, 'ajaxCheckExternalUrlsForStatusCode' ) );
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function triggersAfterInit()
|
|
{
|
|
$wpacuSettingsClass = new Settings();
|
|
$this->settings = $wpacuSettingsClass->getAll();
|
|
|
|
if ( $this->settings['dashboard_show'] && $this->settings['dom_get_type'] ) {
|
|
self::$domGetType = $this->settings['dom_get_type'];
|
|
}
|
|
|
|
// Fetch the page in the background to see what scripts/styles are already loading
|
|
// This applies only for front-end loading
|
|
if ( ! is_admin() && ($this->isGetAssetsCall || $this->frontendShow()) ) {
|
|
if ( $this->isGetAssetsCall ) {
|
|
add_filter( 'show_admin_bar', '__return_false' );
|
|
}
|
|
|
|
// Save CSS handles list that is printed in the <HEAD>
|
|
// No room for errors, some developers might enqueue (although not ideal) assets via "wp_head" or "wp_print_styles"/"wp_print_scripts"
|
|
add_action( 'wp_enqueue_scripts', array( $this, 'saveHeadAssets' ), PHP_INT_MAX - 1 );
|
|
|
|
// Save CSS/JS list that is printed in the <BODY>
|
|
add_action( 'wp_print_footer_scripts', array( $this, 'saveFooterAssets' ), 100000000 );
|
|
add_action( 'wp_footer', array( $this, 'printScriptsStyles' ), ( PHP_INT_MAX - 1 ) );
|
|
}
|
|
|
|
// Send an AJAX request to get the list of the loaded hardcoded scripts and styles and print it
|
|
add_action( 'wp_ajax_' . WPACU_PLUGIN_ID . '_print_loaded_hardcoded_assets', array( $this, 'ajaxPrintLoadedHardcodedAssets' ) );
|
|
|
|
if ( is_admin() ) {
|
|
$metaboxes = new MetaBoxes;
|
|
|
|
// Do not load the meta box nor do any AJAX calls
|
|
// if the asset management is not enabled for the Dashboard
|
|
if ( $this->settings['dashboard_show'] == 1 ) {
|
|
// Send an AJAX request to get the list of loaded scripts and styles and print it nicely
|
|
add_action( 'wp_ajax_' . WPACU_PLUGIN_ID . '_get_loaded_assets', array( $this, 'ajaxGetJsonListCallback' ) );
|
|
|
|
// This is valid when the Gutenberg editor (not via "Classic Editor" plugin) is used and the user used the following option:
|
|
// "Do not load Asset CleanUp Pro on this page (this will disable any functionality of the plugin)"
|
|
add_action( 'wp_ajax_' . WPACU_PLUGIN_ID . '_load_page_restricted_area', array( $this, 'ajaxLoadRestrictedPageAreaCallback' ) );
|
|
}
|
|
|
|
// If assets management within the Dashboard is not enabled, an explanation message will be shown within the box unless the meta box is hidden completely
|
|
if ( $this->settings['show_assets_meta_box'] ) {
|
|
$metaboxes->initMetaBox( 'manage_page_assets' );
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
DO NOT disable the features below if the following apply:
|
|
- The option is not enabled
|
|
- Test Mode Enabled & Admin Logged in
|
|
- The user is in the Dashboard (any changes are applied in the front-end view)
|
|
*/
|
|
if ( ! ( $this->preventAssetsSettings() || is_admin() ) ) {
|
|
if ( $this->settings['disable_emojis'] == 1 ) {
|
|
$wpacuCleanUp = new CleanUp();
|
|
$wpacuCleanUp->doDisableEmojis();
|
|
}
|
|
|
|
if ( $this->settings['disable_oembed'] == 1 ) {
|
|
$wpacuCleanUp = new CleanUp();
|
|
$wpacuCleanUp->doDisableOembed();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Priority: 8 (earliest)
|
|
*/
|
|
public function setVarsBeforeUpdate()
|
|
{
|
|
// Conditions
|
|
// 1) User has rights to manage the assets and the option is enabled in plugin's Settings
|
|
// 2) Not an AJAX call from the Dashboard
|
|
// 3) Not inside the Dashboard
|
|
$this->isFrontendEditView = ( $this->frontendShow() && Menu::userCanManageAssets() // 1
|
|
&& ! $this->isGetAssetsCall // 2
|
|
&& ! is_admin() ); // 3
|
|
|
|
if ( $this->isFrontendEditView ) {
|
|
$wpacuCleanUp = new CleanUp();
|
|
$wpacuCleanUp->cleanUpHtmlOutputForAssetsCall();
|
|
}
|
|
|
|
$this->getCurrentPostId();
|
|
|
|
define( 'WPACU_CURRENT_PAGE_ID', $this->getCurrentPostId() );
|
|
}
|
|
|
|
/**
|
|
* Priority: 10 (latest)
|
|
*/
|
|
public function setVarsAfterAnyUpdate()
|
|
{
|
|
if ( ! is_admin() ) {
|
|
$this->globalUnloaded = $this->getGlobalUnload();
|
|
|
|
// [wpacu_lite]
|
|
if (! $this->isUpdateable) {
|
|
return;
|
|
}
|
|
// [/wpacu_lite]
|
|
|
|
$getCurrentPost = $this->getCurrentPost();
|
|
|
|
$post = $type = false;
|
|
|
|
if (Misc::isHomePage() && empty($getCurrentPost) && ! get_option('page_on_front')) {
|
|
$type = 'front_page';
|
|
} elseif ( ! empty($getCurrentPost) ) {
|
|
$type = 'post';
|
|
$post = $getCurrentPost;
|
|
$this->postTypesUnloaded = (isset($post->post_type) && $post->post_type) ? $this->getBulkUnload('post_type', $post->post_type) : array();
|
|
}
|
|
|
|
// [wpacu_lite]
|
|
if (! $type) {
|
|
// The request is done for a page such as is_archive(), is_author(), 404, search
|
|
// and the premium extension is not available, thus no load exceptions are available
|
|
return;
|
|
}
|
|
// [/wpacu_lite]
|
|
|
|
self::$vars['for_type'] = $type;
|
|
self::$vars['current_post_id'] = $this->currentPostId;
|
|
|
|
if ($post && $type === 'post' && isset($post->post_type) && $post->post_type) {
|
|
self::$vars['current_post_type'] = $post->post_type;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This is useful to change via hooks the "src", "ver" or other values of the loaded handle
|
|
* Example: You have your theme's main style.css that is needed on every page
|
|
* On some pages, you only need 20% of it to load, and you can manually trim the other 80% (if you're sure you know which CSS is not used)
|
|
* You can use a filter hook such as 'wpacu_{main_theme_handle_name_here}_css_handle_obj' to filter the "src" of the object and load an alternative purified CSS file
|
|
*/
|
|
public function alterWpStylesScriptsObj()
|
|
{
|
|
add_action('wp_print_styles', function() {
|
|
global $wp_styles;
|
|
|
|
if ( ! empty($wp_styles->registered) ) {
|
|
foreach (array_keys($wp_styles->registered) as $styleHandle) {
|
|
$wp_styles->registered[$styleHandle] = $this->maybeFilterAssetObject($wp_styles->registered[$styleHandle], 'css');
|
|
}
|
|
}
|
|
});
|
|
|
|
foreach (array('wp_print_scripts', 'wp_print_footer_scripts') as $actionToAdd) {
|
|
add_action( $actionToAdd, function() {
|
|
global $wp_scripts;
|
|
|
|
if ( ! empty($wp_scripts->registered) ) {
|
|
foreach (array_keys($wp_scripts->registered) as $scriptHandle) {
|
|
$wp_scripts->registered[$scriptHandle] = $this->maybeFilterAssetObject($wp_scripts->registered[$scriptHandle], 'js');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $object | as returned from $wp_styles or $wp_scripts
|
|
* @param $assetType | "css" or "js"
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function maybeFilterAssetObject($object, $assetType)
|
|
{
|
|
if ( isset($_GET['wpacu_clean_load']) || isset($_GET['wpacu_load_original']) ) {
|
|
return $object; // this is for debugging purposes, load the original source
|
|
}
|
|
|
|
if ( ! isset($object->handle, $object->src) ) {
|
|
return $object;
|
|
}
|
|
|
|
$filterTagName = 'wpacu_'.$object->handle.'_'.$assetType.'_handle_data';
|
|
|
|
if ( has_filter($filterTagName) ) {
|
|
$originData = (array)$object;
|
|
$newData = apply_filters( $filterTagName, $originData );
|
|
|
|
if ( isset($originData['src'], $newData['src']) && $newData['src'] !== $originData['src'] ) {
|
|
$object->src = $newData['src'];
|
|
$object->src_origin = $originData['src'];
|
|
|
|
$object->ver = $newData['ver'] ?: null;
|
|
$object->ver_origin = isset($originData['ver']) ? $originData['ver'] : null;
|
|
}
|
|
}
|
|
|
|
return $object;
|
|
}
|
|
|
|
/**
|
|
* In case there were assets enqueued within "wp_footer" action hook, instead of the standard "wp_enqueue_scripts"
|
|
*/
|
|
public function onPrintFooterScriptsStyles()
|
|
{
|
|
$this->filterStyles();
|
|
$this->filterScripts();
|
|
}
|
|
|
|
/* [START] Styles Dequeue */
|
|
/**
|
|
* See if there is any list with styles to be removed in JSON format
|
|
* Only the handles (the ID of the styles) is stored
|
|
*/
|
|
public function filterStyles()
|
|
{
|
|
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_styles' );/* [/wpacu_timing] */
|
|
|
|
if (is_admin()) {
|
|
return;
|
|
}
|
|
|
|
global $wp_styles;
|
|
|
|
if (current_action() === 'wp_print_styles') {
|
|
ObjectCache::wpacu_cache_set('wpacu_styles_object_after_wp_print_styles', $wp_styles);
|
|
}
|
|
|
|
$list = array();
|
|
|
|
if (current_action() === 'wp_print_footer_scripts') {
|
|
$cachedWpStyles = ObjectCache::wpacu_cache_get('wpacu_styles_object_after_wp_print_styles');
|
|
if (isset($cachedWpStyles->registered) && count($cachedWpStyles->registered) === count($wp_styles->registered)) {
|
|
// The list was already generated in "wp_print_styles" and the number of registered assets are the same
|
|
// Save resources and do not re-generate it
|
|
$list = ObjectCache::wpacu_cache_get('wpacu_styles_handles_marked_for_unload');
|
|
}
|
|
}
|
|
|
|
if ( empty($list) || ! is_array($list) ) {
|
|
// [wpacu_lite]
|
|
$nonAssetConfigPage = ( ! $this->isUpdateable && ! Misc::getShowOnFront() );
|
|
// [/wpacu_lite]
|
|
|
|
// It looks like the page loaded is neither a post, page or the front-page
|
|
// We'll see if there are assets unloaded globally and unload them
|
|
|
|
/*
|
|
* [START] Build unload list
|
|
*/
|
|
$globalUnload = $this->globalUnloaded;
|
|
|
|
// [wpacu_lite]
|
|
if ( $nonAssetConfigPage && ! empty( $globalUnload['styles'] ) ) {
|
|
$list = $globalUnload['styles'];
|
|
} else {
|
|
// [/wpacu_lite]
|
|
|
|
// Post, Page, Front-page
|
|
// and more (if the Premium Extension is activated)
|
|
$toRemove = $this->getAssetsUnloadedPageLevel();
|
|
|
|
$jsonList = @json_decode( $toRemove );
|
|
|
|
$list = array();
|
|
|
|
if ( isset( $jsonList->styles ) ) {
|
|
$list = (array) $jsonList->styles;
|
|
}
|
|
|
|
if (! is_array($list)) {
|
|
$list = array();
|
|
}
|
|
|
|
// Any global unloaded styles? Append them
|
|
if ( ! empty( $globalUnload['styles'] ) ) {
|
|
foreach ( $globalUnload['styles'] as $handleStyle ) {
|
|
$list[] = $handleStyle;
|
|
}
|
|
}
|
|
|
|
if ( self::isSingularPage() ) {
|
|
// Any bulk unloaded styles (e.g. for all pages belonging to a post type)? Append them
|
|
if ( empty( $this->postTypesUnloaded ) ) {
|
|
$post = $this->getCurrentPost();
|
|
$this->postTypesUnloaded = ( isset( $post->post_type ) && $post->post_type ) ? $this->getBulkUnload( 'post_type', $post->post_type ) : array();
|
|
}
|
|
|
|
if ( isset( $this->postTypesUnloaded['styles'] ) && ! empty( $this->postTypesUnloaded['styles'] ) ) {
|
|
foreach ( $this->postTypesUnloaded['styles'] as $handleStyle ) {
|
|
$list[] = $handleStyle;
|
|
}
|
|
}
|
|
}
|
|
// [wpacu_lite]
|
|
}
|
|
// [/wpacu_lite]
|
|
|
|
// Site-Wide Unload for "Dashicons" if user is not logged-in
|
|
if ( $this->settings['disable_dashicons_for_guests'] && ! is_user_logged_in() ) {
|
|
$list[] = 'dashicons';
|
|
}
|
|
|
|
// Any bulk unloaded styles for 'category', 'post_tag' and more?
|
|
// If the Pro version is enabled, any of the unloaded CSS will be added to the list
|
|
$list = apply_filters( 'wpacu_filter_styles_list_unload', array_unique( $list ) );
|
|
/*
|
|
* [END] Build unload list
|
|
*/
|
|
|
|
// Add handles such as the Oxygen Builder CSS ones that are missing and added differently to the queue
|
|
$allStyles = $this->wpStylesFilter( $wp_styles, 'registered', $list );
|
|
|
|
if ( $allStyles !== null && ! empty( $allStyles->registered ) ) {
|
|
// Going through all the registered styles
|
|
foreach ( $allStyles->registered as $handle => $value ) {
|
|
// This could be triggered several times, check if the style already exists
|
|
if ( ! isset( $this->wpAllStyles['registered'][ $handle ] ) ) {
|
|
$this->wpAllStyles['registered'][ $handle ] = $value;
|
|
if ( in_array( $handle, $allStyles->queue ) ) {
|
|
$this->wpAllStyles['queue'][] = $handle;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isset( $this->wpAllStyles['queue'] ) && ! empty( $this->wpAllStyles['queue'] ) ) {
|
|
$this->wpAllStyles['queue'] = array_unique( $this->wpAllStyles['queue'] );
|
|
}
|
|
}
|
|
|
|
if ( isset( $this->wpAllStyles['registered'] ) && ! empty( $this->wpAllStyles['registered'] ) ) {
|
|
ObjectCache::wpacu_cache_set( 'wpacu_all_styles_handles', array_keys( $this->wpAllStyles['registered'] ) );
|
|
}
|
|
|
|
// e.g. for test/debug mode or AJAX calls (where all assets have to load)
|
|
if ( isset($_REQUEST['wpacu_no_css_unload']) ) {
|
|
/* [wpacu_timing] */Misc::scriptExecTimer( 'filter_dequeue_styles', 'end' ); /* [/wpacu_timing] */
|
|
return;
|
|
}
|
|
|
|
if ( $this->preventAssetsSettings(array('assets_call')) ) {
|
|
/* [wpacu_timing] */Misc::scriptExecTimer( 'filter_dequeue_styles', 'end' ); /* [/wpacu_timing] */
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* [START] Load Exception Check
|
|
* */
|
|
// Load exception rules ALWAYS have priority over the unloading ones
|
|
// Thus, if an exception is found, the handle will be removed from the unloading list
|
|
// Let's see if there are load exceptions for this page or site-wide (e.g. for logged-in users)
|
|
// Only check for any load exceptions if the unloading list has at least one item
|
|
// Otherwise the action is irrelevant since the assets are loaded anyway by default
|
|
|
|
// These are LITE rules
|
|
$list = ( ! empty($list) ) ? $this->filterAssetsUnloadList($list, 'styles','load_exception') : $list;
|
|
|
|
// These are PRO rules or rules added via custom coding
|
|
$list = ( ! empty($list) ) ? apply_filters('wpacu_filter_styles_list_load_exception', $list) : $list;
|
|
/*
|
|
* [END] Load Exception Check
|
|
* */
|
|
|
|
// Is $list still empty? Nothing to unload? Stop here
|
|
if (empty($list)) {
|
|
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_styles', 'end' ); /* [/wpacu_timing] */
|
|
return;
|
|
}
|
|
}
|
|
|
|
$ignoreChildParentList = apply_filters('wpacu_ignore_child_parent_list', $this->getIgnoreChildren());
|
|
|
|
foreach ($list as $handle) {
|
|
if (isset($ignoreChildParentList['styles'], $this->wpAllStyles['registered'][$handle]->src) && is_array($ignoreChildParentList['styles']) && array_key_exists($handle, $ignoreChildParentList['styles'])) {
|
|
// Do not dequeue it as it's "children" will also be dequeued (ignore rule is applied)
|
|
// It will be stripped by cleaning its LINK tag from the HTML Source
|
|
$this->ignoreChildren['styles'][$handle] = $this->wpAllStyles['registered'][$handle]->src;
|
|
$this->ignoreChildren['styles'][$handle.'_has_unload_rule'] = 1;
|
|
$this->allUnloadedAssets['styles'][] = $handle;
|
|
continue;
|
|
}
|
|
|
|
$handle = trim($handle);
|
|
|
|
// Ignore auto generated handles for the hardcoded CSS as they were added for reference purposes
|
|
// They will get stripped later on via OptimizeCommon.php
|
|
// This is in case there are references from using the Pro version
|
|
if (strpos($handle, 'wpacu_hardcoded_link_') === 0) {
|
|
continue;
|
|
}
|
|
|
|
if (strpos($handle, 'wpacu_hardcoded_style_') === 0) {
|
|
continue;
|
|
}
|
|
|
|
// Do not unload "dashicons" if the top WordPress admin bar is showing up
|
|
if ($handle === 'dashicons' && is_admin_bar_showing()) {
|
|
continue;
|
|
}
|
|
|
|
$this->allUnloadedAssets['styles'][] = $handle;
|
|
|
|
// Only trigger the unloading on regular page load, not when the assets list is collected
|
|
if ( ! $this->isGetAssetsCall ) {
|
|
wp_deregister_style( $handle );
|
|
wp_dequeue_style( $handle );
|
|
}
|
|
}
|
|
|
|
if (current_action() === 'wp_print_styles') {
|
|
ObjectCache::wpacu_cache_set( 'wpacu_styles_handles_marked_for_unload', $list );
|
|
}
|
|
|
|
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_styles', 'end' ); /* [/wpacu_timing] */
|
|
}
|
|
|
|
/**
|
|
* @param $wpStylesFilter
|
|
* @param string $listType
|
|
* @param array $unloadedList
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function wpStylesFilter($wpStylesFilter, $listType, $unloadedList = array())
|
|
{
|
|
global $wp_styles, $oxygen_vsb_css_styles;
|
|
|
|
if ( ( $listType === 'registered' ) && isset( $oxygen_vsb_css_styles->registered ) && is_object( $oxygen_vsb_css_styles ) && ! empty( $oxygen_vsb_css_styles->registered ) ) {
|
|
$stylesSpecialCases = array();
|
|
|
|
foreach ($oxygen_vsb_css_styles->registered as $oxygenHandle => $oxygenValue) {
|
|
if (! array_key_exists($oxygenHandle, $wp_styles->registered)) {
|
|
$wpStylesFilter->registered[$oxygenHandle] = $oxygenValue;
|
|
$stylesSpecialCases[$oxygenHandle] = $oxygenValue->src;
|
|
}
|
|
}
|
|
|
|
$unloadedSpecialCases = array();
|
|
|
|
foreach ($unloadedList as $unloadedHandle) {
|
|
if (array_key_exists($unloadedHandle, $stylesSpecialCases)) {
|
|
$unloadedSpecialCases[$unloadedHandle] = $stylesSpecialCases[$unloadedHandle];
|
|
}
|
|
}
|
|
|
|
if (! empty($unloadedSpecialCases)) {
|
|
// This will be later used in 'wp_loaded' below to extract the special styles
|
|
echo self::$wpStylesSpecialDelimiters['start'] . wp_json_encode($unloadedSpecialCases) . self::$wpStylesSpecialDelimiters['end'];
|
|
}
|
|
}
|
|
|
|
if ( ( $listType === 'done' ) && isset( $oxygen_vsb_css_styles->done ) && is_object( $oxygen_vsb_css_styles ) ) {
|
|
foreach ($oxygen_vsb_css_styles->done as $oxygenHandle) {
|
|
if (! in_array($oxygenHandle, $wp_styles->done)) {
|
|
$wpStylesFilter[] = $oxygenHandle;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ( $listType === 'queue' ) && isset( $oxygen_vsb_css_styles->queue ) && is_object( $oxygen_vsb_css_styles ) ) {
|
|
foreach ($oxygen_vsb_css_styles->queue as $oxygenHandle) {
|
|
if (! in_array($oxygenHandle, $wp_styles->queue)) {
|
|
$wpStylesFilter[] = $oxygenHandle;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $wpStylesFilter;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function filterStylesSpecialCases()
|
|
{
|
|
if ( isset($_REQUEST['wpacu_no_css_unload']) ) {
|
|
return;
|
|
}
|
|
|
|
add_action('wp_loaded', static function() {
|
|
ob_start(static function($htmlSource) {
|
|
if (strpos($htmlSource, self::$wpStylesSpecialDelimiters['start']) === false && strpos($htmlSource, self::$wpStylesSpecialDelimiters['end']) === false) {
|
|
return $htmlSource;
|
|
}
|
|
|
|
$jsonStylesSpecialCases = Misc::extractBetween($htmlSource, self::$wpStylesSpecialDelimiters['start'], self::$wpStylesSpecialDelimiters['end']);
|
|
|
|
$stylesSpecialCases = json_decode($jsonStylesSpecialCases, ARRAY_A);
|
|
|
|
if (Misc::jsonLastError() === JSON_ERROR_NONE && ! empty($stylesSpecialCases)) {
|
|
foreach ($stylesSpecialCases as $styleSrc) {
|
|
$styleLocalSrc = Misc::getLocalSrc($styleSrc);
|
|
$styleRelSrc = isset($styleLocalSrc['rel_src']) ? $styleLocalSrc['rel_src'] : $styleSrc;
|
|
$htmlSource = CleanUp::cleanLinkTagFromHtmlSource($styleRelSrc, $htmlSource);
|
|
}
|
|
|
|
// Strip the info HTML comment
|
|
$htmlSource = str_replace(
|
|
self::$wpStylesSpecialDelimiters['start'] . $jsonStylesSpecialCases . self::$wpStylesSpecialDelimiters['end'],
|
|
'',
|
|
$htmlSource
|
|
);
|
|
}
|
|
|
|
return $htmlSource;
|
|
});
|
|
}, 1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function printAnySpecialCss()
|
|
{
|
|
if (isset($this->allUnloadedAssets['styles']) && ! empty($this->allUnloadedAssets['styles']) && in_array('photoswipe', $this->allUnloadedAssets['styles'])) {
|
|
?>
|
|
<?php if (current_user_can('administrator')) { ?><!-- Asset CleanUp: "photoswipe" unloaded (avoid printing useless HTML) --><?php } ?>
|
|
<style <?php echo Misc::getStyleTypeAttribute(); ?>>.pswp { display: none; }</style>
|
|
<?php
|
|
}
|
|
}
|
|
/* [END] Styles Dequeue */
|
|
|
|
/* [START] Scripts Dequeue */
|
|
/**
|
|
* See if there is any list with scripts to be removed in JSON format
|
|
* Only the handles (the ID of the scripts) are saved
|
|
*/
|
|
public function filterScripts()
|
|
{
|
|
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_scripts' );/* [/wpacu_timing] */
|
|
|
|
if (is_admin()) {
|
|
return;
|
|
}
|
|
|
|
global $wp_scripts;
|
|
|
|
if (current_action() === 'wp_print_scripts') {
|
|
ObjectCache::wpacu_cache_set('wpacu_scripts_object_after_wp_print_scripts', $wp_scripts);
|
|
}
|
|
|
|
$list = array();
|
|
|
|
if (current_action() === 'wp_print_footer_scripts') {
|
|
$cachedWpScripts = ObjectCache::wpacu_cache_get('wpacu_scripts_object_after_wp_print_scripts');
|
|
if (isset($cachedWpScripts->registered) && count($cachedWpScripts->registered) === count($wp_scripts->registered)) {
|
|
// The list was already generated in "wp_print_scripts" and the number of registered assets are the same
|
|
// Save resources and do not re-generate it
|
|
$list = ObjectCache::wpacu_cache_get('wpacu_scripts_handles_marked_for_unload');
|
|
}
|
|
}
|
|
|
|
if ( empty($list) ) {
|
|
// [wpacu_lite]
|
|
$nonAssetConfigPage = ( ! $this->isUpdateable && ! Misc::getShowOnFront() );
|
|
// [/wpacu_lite]
|
|
|
|
// It looks like the page loaded is neither a post, page or the front-page
|
|
// We'll see if there are assets unloaded globally and unload them
|
|
/*
|
|
* [START] Build unload list
|
|
*/
|
|
$globalUnload = $this->globalUnloaded;
|
|
|
|
// [wpacu_lite]
|
|
if ( $nonAssetConfigPage && ! empty( $globalUnload['scripts'] ) ) {
|
|
$list = $globalUnload['scripts'];
|
|
} else { // [/wpacu_lite]
|
|
// Post, Page or Front-page?
|
|
$toRemove = $this->getAssetsUnloadedPageLevel();
|
|
|
|
$jsonList = @json_decode( $toRemove );
|
|
|
|
$list = array();
|
|
|
|
if ( isset( $jsonList->scripts ) ) {
|
|
$list = (array) $jsonList->scripts;
|
|
}
|
|
|
|
// Any global unloaded styles? Append them
|
|
if ( ! empty( $globalUnload['scripts'] ) ) {
|
|
foreach ( $globalUnload['scripts'] as $handleScript ) {
|
|
$list[] = $handleScript;
|
|
}
|
|
}
|
|
|
|
if ( self::isSingularPage() ) {
|
|
// Any bulk unloaded styles (e.g. for all pages belonging to a post type)? Append them
|
|
if ( empty( $this->postTypesUnloaded ) ) {
|
|
$post = $this->getCurrentPost();
|
|
// Make sure the post_type is set; it's not in specific pages (e.g. BuddyPress ones)
|
|
$this->postTypesUnloaded = ( isset( $post->post_type ) && $post->post_type ) ? $this->getBulkUnload( 'post_type', $post->post_type ) : array();
|
|
}
|
|
|
|
if ( isset( $this->postTypesUnloaded['scripts'] ) && ! empty( $this->postTypesUnloaded['scripts'] ) ) {
|
|
foreach ( $this->postTypesUnloaded['scripts'] as $handleStyle ) {
|
|
$list[] = $handleStyle;
|
|
}
|
|
}
|
|
}
|
|
// [wpacu_lite]
|
|
}
|
|
// [/wpacu_lite]
|
|
|
|
// Any bulk unloaded styles for 'category', 'post_tag' and more?
|
|
// These are PRO rules or rules added via custom coding
|
|
$list = apply_filters( 'wpacu_filter_scripts_list_unload', array_unique( $list ) );
|
|
|
|
global $wp_scripts;
|
|
|
|
$allScripts = $wp_scripts;
|
|
|
|
if ( $allScripts !== null && ! empty( $allScripts->registered ) ) {
|
|
foreach ( $allScripts->registered as $handle => $value ) {
|
|
// This could be triggered several times, check if the script already exists
|
|
if ( ! isset( $this->wpAllScripts['registered'][ $handle ] ) ) {
|
|
$this->wpAllScripts['registered'][ $handle ] = $value;
|
|
if ( in_array( $handle, $allScripts->queue ) ) {
|
|
$this->wpAllScripts['queue'][] = $handle;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isset( $this->wpAllScripts['queue'] ) && ! empty( $this->wpAllScripts['queue'] ) ) {
|
|
$this->wpAllScripts['queue'] = array_unique( $this->wpAllScripts['queue'] );
|
|
}
|
|
}
|
|
/*
|
|
* [END] Build unload list
|
|
*/
|
|
|
|
/*
|
|
* [START] Load Exception Check
|
|
* */
|
|
// Load exception rules ALWAYS have priority over the unloading ones
|
|
// Thus, if an exception is found, the handle will be removed from the unloading list
|
|
// Let's see if there are load exceptions for this page or site-wide (e.g. for logged-in users)
|
|
|
|
// These are LITE rules
|
|
$list = ( ! empty($list) ) ? $this->filterAssetsUnloadList($list, 'scripts', 'load_exception') : $list;
|
|
|
|
// [wpacu_pro]
|
|
// These are PRO rules or rules added via custom coding
|
|
// Only check for any load exceptions if the unloading list has at least one item
|
|
// Otherwise the action is irrelevant since the assets are loaded anyway by default
|
|
$list = ( ! empty($list) ) ? apply_filters('wpacu_filter_scripts_list_load_exception', $list) : $list;
|
|
// [/wpacu_pro]
|
|
/*
|
|
* [END] Load Exception Check
|
|
* */
|
|
|
|
// Nothing to unload
|
|
if ( empty( $list ) ) {
|
|
/* [wpacu_timing] */Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
|
return;
|
|
}
|
|
|
|
// e.g. for test/debug mode or AJAX calls (where all assets have to load)
|
|
if ( isset($_REQUEST['wpacu_no_js_unload']) || $this->preventAssetsSettings(array('assets_call')) ) {
|
|
/* [wpacu_timing] */Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
|
return;
|
|
}
|
|
}
|
|
|
|
$ignoreChildParentList = apply_filters('wpacu_ignore_child_parent_list', $this->getIgnoreChildren());
|
|
|
|
foreach ($list as $handle) {
|
|
$handle = trim($handle);
|
|
|
|
// Ignore auto generated handles for the hardcoded CSS as they were added for reference purposes
|
|
// They will get stripped later on via OptimizeCommon.php
|
|
// The handle is used just for reference for later stripping via altering the DOM
|
|
if (strpos($handle, 'wpacu_hardcoded_script_inline_') !== false || strpos($handle, 'wpacu_hardcoded_noscript_inline_') !== false) {
|
|
// [wpacu_pro]
|
|
$saveMarkedHandles = ObjectCache::wpacu_cache_get('wpacu_hardcoded_scripts_noscripts_inline') ?: array();
|
|
$saveMarkedHandles[] = $handle;
|
|
$this->allUnloadedAssets['scripts'][] = $handle; // for "wpacu_no_load" on hardcoded list
|
|
ObjectCache::wpacu_cache_set( 'wpacu_hardcoded_scripts_noscripts_inline', $saveMarkedHandles );
|
|
// [/wpacu_pro]
|
|
continue;
|
|
}
|
|
|
|
if (strpos($handle, 'wpacu_hardcoded_script_src_') !== false) {
|
|
// [wpacu_pro]
|
|
$saveMarkedHandles = ObjectCache::wpacu_cache_get('wpacu_hardcoded_scripts_src') ?: array();
|
|
$saveMarkedHandles[] = $handle;
|
|
$this->allUnloadedAssets['scripts'][] = $handle; // for "wpacu_no_load" on hardcoded list
|
|
ObjectCache::wpacu_cache_set( 'wpacu_hardcoded_scripts_src', $saveMarkedHandles );
|
|
// [/wpacu_pro]
|
|
continue;
|
|
}
|
|
|
|
// Special Action for 'jquery-migrate' handler as it's tied to 'jquery'
|
|
if ($handle === 'jquery-migrate' && isset($this->wpAllScripts['registered']['jquery'])) {
|
|
$jQueryRegScript = $this->wpAllScripts['registered']['jquery'];
|
|
|
|
if (isset($jQueryRegScript->deps)) {
|
|
$jQueryRegScript->deps = array_diff($jQueryRegScript->deps, array('jquery-migrate'));
|
|
}
|
|
|
|
if (Misc::isPluginActive('jquery-updater/jquery-updater.php')) {
|
|
wp_dequeue_script($handle);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (isset($ignoreChildParentList['scripts'], $this->wpAllScripts['registered'][$handle]->src) && is_array($ignoreChildParentList['scripts']) && array_key_exists($handle, $ignoreChildParentList['scripts'])) {
|
|
// Do not dequeue it as it's "children" will also be dequeued (ignore rule is applied)
|
|
// It will be stripped by cleaning its SCRIPT tag from the HTML Source
|
|
$this->ignoreChildren['scripts'][$handle] = $this->wpAllScripts['registered'][$handle]->src;
|
|
$this->ignoreChildren['scripts'][$handle.'_has_unload_rule'] = 1;
|
|
$this->allUnloadedAssets['scripts'][] = $handle;
|
|
continue;
|
|
}
|
|
|
|
$this->allUnloadedAssets['scripts'][] = $handle;
|
|
|
|
// Only trigger the unloading on regular page load, not when the assets list is collected
|
|
if ( ! $this->isGetAssetsCall ) {
|
|
wp_deregister_script( $handle );
|
|
wp_dequeue_script( $handle );
|
|
}
|
|
}
|
|
|
|
if (current_action() === 'wp_print_scripts') {
|
|
ObjectCache::wpacu_cache_set( 'wpacu_scripts_handles_marked_for_unload', $list );
|
|
}
|
|
|
|
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
|
}
|
|
/* [END] Scripts Dequeue */
|
|
|
|
|
|
/**
|
|
* @param $list (should never be empty when called)
|
|
* @param $assetType
|
|
* @param $ruleType
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function filterAssetsUnloadList($list, $assetType, $ruleType)
|
|
{
|
|
// Remove any assets from the list in case there are any load exceptions detected
|
|
if ($ruleType === 'load_exception') {
|
|
$this->loadExceptionsPageLevel = $this->getLoadExceptionsPageLevel(self::$vars['for_type'], self::$vars['current_post_id']);
|
|
$this->loadExceptionsLoggedInGlobal = $this->getHandleLoadLoggedIn();
|
|
$this->loadExceptionsPostType = $this->getLoadExceptionsPostType(self::$vars['current_post_type']);
|
|
|
|
$anyAssetsLoadExceptions = ( ! empty( $this->loadExceptionsPageLevel[ $assetType ] )
|
|
|| ( ! empty( $this->loadExceptionsLoggedInGlobal[ $assetType ] ) )
|
|
|| ( ! empty( $this->loadExceptionsPostType[$assetType] ) )
|
|
);
|
|
|
|
if ( $anyAssetsLoadExceptions ) {
|
|
foreach ( $list as $handleKey => $handle ) {
|
|
$loadAssetAsException = in_array( $handle, $this->loadExceptionsPageLevel[ $assetType ] ) // 1) per page, per group pages OR
|
|
|| in_array( $handle, $this->loadExceptionsPostType[ $assetType ] ) // 2) On all pages belonging to a specific post type
|
|
|| ( in_array( $handle, $this->loadExceptionsLoggedInGlobal[ $assetType ] ) && is_user_logged_in() ); // 3) site-wide if the user is logged-in
|
|
if ( $loadAssetAsException ) {
|
|
unset( $list[ $handleKey ] );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Alter CSS/JS list marked for dequeue
|
|
* @param $for
|
|
* @return array
|
|
*/
|
|
public function unloadAssetOnTheFly($for)
|
|
{
|
|
$assetType = ($for === 'css') ? 'styles' : 'scripts';
|
|
$assetIndex = 'wpacu_unload_'.$for;
|
|
|
|
if (! ($unloadAsset = Misc::getVar('get', $assetIndex))) {
|
|
return array();
|
|
}
|
|
|
|
$assetHandles = array();
|
|
|
|
if (strpos($unloadAsset, ',') === false) { // No comma, just one asset targeted
|
|
if (strpos($unloadAsset, '[ignore-deps]') !== false) {
|
|
$unloadAsset = str_replace('[ignore-deps]', '', $unloadAsset);
|
|
$this->ignoreChildrenHandlesOnTheFly[$assetType][] = $unloadAsset;
|
|
}
|
|
|
|
$assetHandles[] = $unloadAsset;
|
|
} else { // There are commas, multiple assets targeted
|
|
foreach (explode(',', $unloadAsset) as $unloadAsset) {
|
|
$unloadAsset = trim($unloadAsset);
|
|
|
|
if ($unloadAsset) {
|
|
if (strpos($unloadAsset, '[ignore-deps]') !== false) {
|
|
$unloadAsset = str_replace('[ignore-deps]', '', $unloadAsset);
|
|
$this->ignoreChildrenHandlesOnTheFly[$assetType][] = $unloadAsset;
|
|
}
|
|
|
|
$assetHandles[] = $unloadAsset;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $assetHandles;
|
|
}
|
|
|
|
/**
|
|
* @param $exceptionsList
|
|
*
|
|
* @return array
|
|
*/
|
|
public function makeLoadExceptionOnTheFly($exceptionsList)
|
|
{
|
|
$exceptionsListDebug = array('styles' => array(), 'scripts' => array());
|
|
|
|
foreach (array('css', 'js') as $assetExt) {
|
|
$assetKey = ($assetExt === 'css') ? 'styles' : 'scripts';
|
|
$indexToCheck = 'wpacu_load_'.$assetExt;
|
|
|
|
if ($loadAsset = Misc::getVar('get', $indexToCheck)) {
|
|
if (strpos($loadAsset, ',') === false && (! in_array($loadAsset, $exceptionsList[$assetKey]))) {
|
|
$exceptionsList[$assetKey][] = $loadAsset;
|
|
$exceptionsListDebug[$assetKey][] = $loadAsset;
|
|
} else {
|
|
foreach (explode(',', $loadAsset) as $loadAsset) {
|
|
if (($loadAsset = trim($loadAsset)) && (! in_array($loadAsset, $exceptionsList[$assetKey]))) {
|
|
$exceptionsList[$assetKey][] = $loadAsset;
|
|
$exceptionsListDebug[$assetKey][] = $loadAsset;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ObjectCache::wpacu_cache_add('wpacu_exceptions_list_page_request', $exceptionsListDebug);
|
|
|
|
return $exceptionsList;
|
|
}
|
|
|
|
/**
|
|
* This fetches the "Load it on this page" exceptions
|
|
*
|
|
* @param string $type ("post", "front_page")
|
|
* @param string $postId
|
|
*
|
|
* @return array|array[]
|
|
*/
|
|
public function getLoadExceptionsPageLevel($type = 'post', $postId = '')
|
|
{
|
|
if ( $this->loadExceptionsPageLevel['_set'] ) {
|
|
return $this->loadExceptionsPageLevel; // it was set
|
|
}
|
|
|
|
$exceptionsListDefault = $exceptionsList = array( 'styles' => array(), 'scripts' => array() );
|
|
|
|
if ( $type === 'post' && ! $postId ) {
|
|
// $postId needs to have a value if $type is a 'post' type
|
|
$this->loadExceptionsPageLevel = $exceptionsListDefault;
|
|
$this->loadExceptionsPageLevel['_set'] = true;
|
|
return $this->loadExceptionsPageLevel;
|
|
}
|
|
|
|
if ( ! $type ) {
|
|
// Invalid request
|
|
$this->loadExceptionsPageLevel = $exceptionsListDefault;
|
|
$this->loadExceptionsPageLevel['_set'] = true;
|
|
return $this->loadExceptionsPageLevel;
|
|
}
|
|
|
|
// Default
|
|
$exceptionsListJson = '';
|
|
|
|
// Post or Post of the Homepage (if chosen in the Dashboard)
|
|
if ( $type === 'post' || ( Misc::getShowOnFront() === 'page' && $postId ) ) {
|
|
$exceptionsListJson = get_post_meta( $postId, '_' . WPACU_PLUGIN_ID . '_load_exceptions', true );
|
|
}
|
|
|
|
// The home page could also be the list of the latest blog posts
|
|
if ( $type === 'front_page' ) {
|
|
$exceptionsListJson = get_option( WPACU_PLUGIN_ID . '_front_page_load_exceptions' );
|
|
}
|
|
|
|
if ( $exceptionsListJson ) {
|
|
$exceptionsList = json_decode( $exceptionsListJson, true );
|
|
|
|
if ( Misc::jsonLastError() !== JSON_ERROR_NONE ) {
|
|
$exceptionsList = $exceptionsListDefault;
|
|
}
|
|
}
|
|
|
|
// Any exceptions on the fly added for debugging purposes? Make sure to grab them
|
|
$exceptionsList = $this->makeLoadExceptionOnTheFly( $exceptionsList );
|
|
|
|
// Avoid any notice errors
|
|
foreach ( array( 'styles', 'scripts' ) as $assetType ) {
|
|
if ( ! isset( $exceptionsList[ $assetType ] ) ) {
|
|
$exceptionsList[ $assetType ] = array();
|
|
}
|
|
}
|
|
|
|
$this->loadExceptionsPageLevel = $exceptionsList;
|
|
$this->loadExceptionsPageLevel['_set'] = true;
|
|
|
|
return $this->loadExceptionsPageLevel;
|
|
}
|
|
|
|
/**
|
|
* Option: 'Make an exception from any unload rule & always load it' -> 'On all pages of "post" post type'
|
|
*
|
|
* @param $postType
|
|
*
|
|
* @return \array[][]
|
|
*/
|
|
public function getLoadExceptionsPostType($postType)
|
|
{
|
|
if ($this->loadExceptionsPostType['_set']) {
|
|
return $this->loadExceptionsPostType;
|
|
}
|
|
|
|
// Not on a singular page
|
|
if ($postType === '') {
|
|
$this->loadExceptionsPostType['_set'] = true;
|
|
return $this->loadExceptionsPostType;
|
|
}
|
|
|
|
$exceptionsListDefault = array('styles' => array(), 'scripts' => array());
|
|
|
|
$exceptionsListJson = get_option(WPACU_PLUGIN_ID . '_post_type_load_exceptions');
|
|
|
|
$exceptionsList = @json_decode($exceptionsListJson, true);
|
|
|
|
// Issues with decoding the JSON file? Return an empty list
|
|
if (Misc::jsonLastError() !== JSON_ERROR_NONE) {
|
|
$this->loadExceptionsPostType = $exceptionsListDefault;
|
|
$this->loadExceptionsPostType['_set'] = true;
|
|
return $this->loadExceptionsPostType;
|
|
}
|
|
|
|
// Return any handles added as load exceptions for the requested $postType
|
|
if (isset($exceptionsList[$postType])) {
|
|
foreach ( $exceptionsList[$postType] as $assetType => $assetList ) {
|
|
foreach ( $assetList as $assetHandle => $assetValue ) {
|
|
if ( $assetValue ) {
|
|
$this->loadExceptionsPostType[ $assetType ][] = $assetHandle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->loadExceptionsPostType['_set'] = true;
|
|
return $this->loadExceptionsPostType;
|
|
}
|
|
|
|
/**
|
|
* Option: Unload site-wide * everywhere
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getGlobalUnload()
|
|
{
|
|
$existingListEmpty = array('styles' => array(), 'scripts' => array());
|
|
$existingListJson = get_option( WPACU_PLUGIN_ID . '_global_unload');
|
|
|
|
$existingListData = $this->existingList($existingListJson, $existingListEmpty);
|
|
|
|
// No 'styles' or 'scripts' - Set them as empty to avoid any PHP warning errors
|
|
foreach ( array('styles', 'scripts') as $assetType ) {
|
|
if ( ! isset( $existingListData['list'][$assetType] ) || ! is_array( $existingListData['list'][$assetType] ) ) {
|
|
$existingListData['list'][$assetType] = array();
|
|
}
|
|
}
|
|
|
|
return $existingListData['list'];
|
|
}
|
|
|
|
/**
|
|
* @param string $for (could be 'post_type', 'taxonomy' for the Pro version etc.)
|
|
* @param string $type
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getBulkUnload($for, $type = 'all')
|
|
{
|
|
$existingListEmpty = array('styles' => array(), 'scripts' => array());
|
|
|
|
$existingListAllJson = get_option( WPACU_PLUGIN_ID . '_bulk_unload');
|
|
|
|
if (! $existingListAllJson) {
|
|
return $existingListEmpty;
|
|
}
|
|
|
|
$existingListAll = json_decode($existingListAllJson, true);
|
|
|
|
if (Misc::jsonLastError() !== JSON_ERROR_NONE) {
|
|
return $existingListEmpty;
|
|
}
|
|
|
|
$existingList = $existingListEmpty;
|
|
|
|
foreach (array('styles', 'scripts') as $assetType) {
|
|
if ( isset( $existingListAll[$assetType][ $for ][ $type ] ) && is_array( $existingListAll[$assetType][ $for ][ $type ] ) ) {
|
|
$existingList[$assetType] = $existingListAll[$assetType][ $for ][ $type ];
|
|
}
|
|
}
|
|
|
|
return $existingList;
|
|
}
|
|
|
|
/**
|
|
* Option: Add Note
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getHandleNotes()
|
|
{
|
|
$handleNotes = array('styles' => array(), 'scripts' => array());
|
|
|
|
$handleNotesListJson = get_option(WPACU_PLUGIN_ID . '_global_data');
|
|
|
|
if ($handleNotesListJson) {
|
|
$handleNotesList = @json_decode($handleNotesListJson, true);
|
|
|
|
// Issues with decoding the JSON file? Return an empty list
|
|
if (Misc::jsonLastError() !== JSON_ERROR_NONE) {
|
|
return $handleNotes;
|
|
}
|
|
|
|
// Are new positions set for styles and scripts?
|
|
foreach (array('styles', 'scripts') as $assetKey) {
|
|
if ( isset( $handleNotesList[$assetKey]['notes'] ) && ! empty( $handleNotesList[$assetKey]['notes'] ) ) {
|
|
$handleNotes[$assetKey] = $handleNotesList[$assetKey]['notes'];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $handleNotes;
|
|
}
|
|
|
|
/**
|
|
* Option: 'Make an exception from any unload rule & always load it' -> 'If the user is logged-in'
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getHandleLoadLoggedIn()
|
|
{
|
|
if ($this->loadExceptionsLoggedInGlobal['_set']) {
|
|
return $this->loadExceptionsLoggedInGlobal;
|
|
}
|
|
|
|
$targetGlobalKey = 'load_it_logged_in';
|
|
|
|
$handleData = array( 'styles' => array(), 'scripts' => array() );
|
|
|
|
$handleDataListJson = get_option( WPACU_PLUGIN_ID . '_global_data' );
|
|
|
|
if ( $handleDataListJson ) {
|
|
$handleDataList = @json_decode( $handleDataListJson, true );
|
|
|
|
// Issues with decoding the JSON file? Return an empty list
|
|
if ( Misc::jsonLastError() !== JSON_ERROR_NONE ) {
|
|
$this->loadExceptionsLoggedInGlobal = $handleData;
|
|
$this->loadExceptionsLoggedInGlobal['_set'] = true;
|
|
return $handleData;
|
|
}
|
|
|
|
// Are load exceptions set for styles and scripts?
|
|
foreach ( array( 'styles', 'scripts' ) as $assetKey ) {
|
|
if ( isset( $handleDataList[ $assetKey ][ $targetGlobalKey ] ) && ! empty( $handleDataList[ $assetKey ][ $targetGlobalKey ] ) ) {
|
|
$handleData[ $assetKey ] = array_keys($handleDataList[ $assetKey ][ $targetGlobalKey ]);
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->loadExceptionsLoggedInGlobal = $handleData;
|
|
|
|
// Avoid any PHP notice errors
|
|
foreach (array('styles', 'scripts') as $assetType) {
|
|
if ( ! isset($this->loadExceptionsLoggedInGlobal[$assetType]) ) {
|
|
$this->loadExceptionsLoggedInGlobal[$assetType] = array();
|
|
}
|
|
}
|
|
|
|
$this->loadExceptionsLoggedInGlobal['_set'] = true;
|
|
|
|
return $this->loadExceptionsLoggedInGlobal;
|
|
}
|
|
|
|
/**
|
|
* Option: 'Ignore dependency rule and keep the "children" loaded'
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getIgnoreChildren()
|
|
{
|
|
if (empty($this->ignoreChildren)) {
|
|
$ignoreChildListJson = get_option(WPACU_PLUGIN_ID . '_global_data');
|
|
|
|
if ($ignoreChildListJson) {
|
|
$ignoreChildList = @json_decode($ignoreChildListJson, true);
|
|
|
|
// Issues with decoding the JSON file? Return an empty list
|
|
if (Misc::jsonLastError() !== JSON_ERROR_NONE) {
|
|
return $this->ignoreChildren;
|
|
}
|
|
|
|
// Are ignore "children" rules set for styles and scripts?
|
|
foreach (array('styles', 'scripts') as $assetKey) {
|
|
if (isset($ignoreChildList[$assetKey]['ignore_child']) && $ignoreChildList[$assetKey]['ignore_child']) {
|
|
$this->ignoreChildren[$assetKey] = $ignoreChildList[$assetKey]['ignore_child'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->ignoreChildren;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public static function getHandlesInfo()
|
|
{
|
|
$assetsInfo = array('styles' => array(), 'scripts' => array());
|
|
|
|
$wpacuGlobalDataJson = get_option(WPACU_PLUGIN_ID . '_global_data');
|
|
$wpacuGlobalData = json_decode($wpacuGlobalDataJson, ARRAY_A);
|
|
if (Misc::jsonLastError() === JSON_ERROR_NONE) {
|
|
foreach (array('styles', 'scripts') as $assetKey) {
|
|
if ( isset( $wpacuGlobalData[$assetKey]['assets_info'] ) && ! empty( $wpacuGlobalData[$assetKey]['assets_info'] ) ) {
|
|
$assetsInfo[$assetKey] = Misc::filterList( $wpacuGlobalData[$assetKey]['assets_info'] );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback for those who still use the old transient way of fetching the assets info
|
|
if ($assetsInfoTransient = get_transient(WPACU_PLUGIN_ID . '_assets_info')) {
|
|
$assetsInfoTransientArray = @json_decode($assetsInfoTransient, ARRAY_A);
|
|
|
|
if (is_array($assetsInfoTransientArray) && ! empty($assetsInfoTransientArray)) {
|
|
foreach ($assetsInfoTransientArray as $assetKeyTransient => $handlesList) {
|
|
if (! in_array($assetKeyTransient, array('styles', 'scripts'))) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($handlesList as $handleName => $handleData) {
|
|
if (! isset($assetsInfo[$assetKeyTransient][$handleName])) {
|
|
$assetsInfo[$assetKeyTransient][$handleName] = $handleData;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $assetsInfo;
|
|
}
|
|
|
|
/**
|
|
* @param $ignoreChildParentList
|
|
*
|
|
* @return array
|
|
*/
|
|
public function filterIgnoreChildParentList($ignoreChildParentList)
|
|
{
|
|
if (isset($this->ignoreChildrenHandlesOnTheFly['styles']) && ! empty($this->ignoreChildrenHandlesOnTheFly['styles'])) {
|
|
foreach ($this->ignoreChildrenHandlesOnTheFly['styles'] as $cssHandle) {
|
|
$ignoreChildParentList['styles'][$cssHandle] = 1;
|
|
}
|
|
}
|
|
|
|
if (isset($this->ignoreChildrenHandlesOnTheFly['scripts']) && ! empty($this->ignoreChildrenHandlesOnTheFly['scripts'])) {
|
|
foreach ($this->ignoreChildrenHandlesOnTheFly['scripts'] as $jsHandle) {
|
|
$ignoreChildParentList['scripts'][$jsHandle] = 1;
|
|
}
|
|
}
|
|
|
|
return $ignoreChildParentList;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function saveHeadAssets()
|
|
{
|
|
global $wp_styles, $wp_scripts;
|
|
|
|
if (isset($this->wpAllStyles['queue']) && ! empty($this->wpAllStyles['queue'])) {
|
|
$this->stylesInHead = $this->wpAllStyles['queue'];
|
|
}
|
|
|
|
if (isset($wp_styles->queue) && ! empty($wp_styles->queue)) {
|
|
foreach ($wp_styles->queue as $styleHandle) {
|
|
$this->stylesInHead[] = $styleHandle;
|
|
}
|
|
}
|
|
|
|
$this->stylesInHead = array_unique($this->stylesInHead);
|
|
|
|
if (isset($this->wpAllScripts['queue']) && ! empty($this->wpAllScripts['queue'])) {
|
|
$this->scriptsInHead = $this->wpAllScripts['queue'];
|
|
}
|
|
|
|
if (isset($wp_scripts->queue) && ! empty($wp_scripts->queue)) {
|
|
foreach ($wp_scripts->queue as $scriptHandle) {
|
|
$this->scriptsInHead[] = $scriptHandle;
|
|
}
|
|
}
|
|
|
|
$this->scriptsInHead = array_unique($this->scriptsInHead);
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function saveFooterAssets()
|
|
{
|
|
global $wp_scripts, $wp_styles;
|
|
|
|
// [Styles Collection]
|
|
$footerStyles = array();
|
|
|
|
if (isset($this->wpAllStyles['queue']) && ! empty($this->wpAllStyles['queue'])) {
|
|
foreach ( $this->wpAllStyles['queue'] as $handle ) {
|
|
if ( ! in_array( $handle, $this->stylesInHead ) ) {
|
|
$footerStyles[] = $handle;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($wp_styles->queue) && ! empty($wp_styles->queue)) {
|
|
foreach ( $wp_styles->queue as $handle ) {
|
|
if ( ! in_array( $handle, $this->stylesInHead ) ) {
|
|
$footerStyles[] = $handle;
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->assetsInFooter['styles'] = array_unique($footerStyles);
|
|
// [/Styles Collection]
|
|
|
|
// [Scripts Collection]
|
|
$this->assetsInFooter['scripts'] = (isset($wp_scripts->in_footer) && ! empty($wp_scripts->in_footer)) ? $wp_scripts->in_footer : array();
|
|
|
|
if (isset($this->wpAllScripts['queue']) && ! empty($this->wpAllScripts['queue'])) {
|
|
foreach ( $this->wpAllScripts['queue'] as $handle ) {
|
|
if ( ! in_array( $handle, $this->scriptsInHead ) ) {
|
|
$this->assetsInFooter['scripts'][] = $handle;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($wp_scripts->queue) && ! empty($wp_scripts->queue)) {
|
|
foreach ( $wp_scripts->queue as $handle ) {
|
|
if ( ! in_array( $handle, $this->scriptsInHead ) ) {
|
|
$this->assetsInFooter['scripts'][] = $handle;
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->assetsInFooter['scripts'] = array_unique($this->assetsInFooter['scripts']);
|
|
// [/Scripts Collection]
|
|
|
|
}
|
|
|
|
/**
|
|
* This output will be extracted and the JSON will be processed
|
|
* in the WP Dashboard when editing a post
|
|
*
|
|
* It will also print the asset list in the front-end
|
|
* if the option was enabled in the Settings
|
|
*/
|
|
public function printScriptsStyles()
|
|
{
|
|
// Not for WordPress AJAX calls
|
|
if (self::$domGetType === 'direct' && defined('DOING_AJAX') && DOING_AJAX) {
|
|
return;
|
|
}
|
|
|
|
$isFrontEndEditView = $this->isFrontendEditView;
|
|
$isDashboardEditView = (! $isFrontEndEditView && $this->isGetAssetsCall);
|
|
|
|
if (! $isFrontEndEditView && ! $isDashboardEditView) {
|
|
return;
|
|
}
|
|
|
|
if ($isFrontEndEditView && isset($_GET['elementor-preview']) && $_GET['elementor-preview']) {
|
|
return;
|
|
}
|
|
|
|
/* [wpacu_timing] */ $wpacuTimingName = 'output_css_js_manager'; Misc::scriptExecTimer($wpacuTimingName); /* [/wpacu_timing] */
|
|
|
|
// Prevent plugins from altering the DOM
|
|
add_filter('w3tc_minify_enable', '__return_false');
|
|
|
|
Misc::w3TotalCacheFlushObjectCache();
|
|
|
|
// This is the list of the scripts and styles that were eventually loaded
|
|
// We have also the list of the ones that were unloaded
|
|
// located in $this->wpScripts and $this->wpStyles
|
|
// We will add it to the list as they will be marked
|
|
|
|
$stylesBeforeUnload = $this->wpAllStyles;
|
|
$scriptsBeforeUnload = $this->wpAllScripts;
|
|
|
|
global $wp_scripts, $wp_styles;
|
|
|
|
$list = array();
|
|
|
|
// e.g. for "Loaded" and "Unloaded" statuses
|
|
$currentUnloadedAll = isset($this->allUnloadedAssets) ? $this->allUnloadedAssets : array('styles' => array(), 'scripts' => array());
|
|
|
|
foreach (array('styles', 'scripts') as $assetType) {
|
|
if ( isset( $currentUnloadedAll[$assetType] ) ) {
|
|
$currentUnloadedAll[$assetType] = array_unique( $currentUnloadedAll[$assetType] );
|
|
}
|
|
}
|
|
|
|
$manageStylesCore = isset($wp_styles->done) && is_array($wp_styles->done) ? $wp_styles->done : array();
|
|
$manageStyles = $this->wpStylesFilter($manageStylesCore, 'done');
|
|
|
|
$manageScripts = isset($wp_scripts->done) && is_array($wp_scripts->done) ? $wp_scripts->done : array();
|
|
|
|
if ($isFrontEndEditView) {
|
|
if (! empty($this->wpAllStyles) && isset($this->wpAllStyles['queue'])) {
|
|
$manageStyles = $this->wpStylesFilter($this->wpAllStyles['queue'], 'queue');
|
|
}
|
|
|
|
if (! empty($this->wpAllScripts) && isset($this->wpAllScripts['queue'])) {
|
|
$manageScripts = $this->wpAllScripts['queue'];
|
|
}
|
|
|
|
if (! empty($currentUnloadedAll['styles'])) {
|
|
foreach ( $currentUnloadedAll['styles'] as $currentUnloadedStyleHandle ) {
|
|
if ( ! in_array( $currentUnloadedStyleHandle, $manageStyles ) ) {
|
|
$manageStyles[] = $currentUnloadedStyleHandle;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! empty($manageStylesCore)) {
|
|
foreach ($manageStylesCore as $wpDoneStyle) {
|
|
if ( ! in_array( $wpDoneStyle, $manageStyles ) ) {
|
|
$manageStyles[] = $wpDoneStyle;
|
|
}
|
|
}
|
|
}
|
|
|
|
$manageStyles = array_unique($manageStyles);
|
|
|
|
if (! empty($currentUnloadedAll['scripts'])) {
|
|
foreach ( $currentUnloadedAll['scripts'] as $currentUnloadedScriptHandle ) {
|
|
if ( ! in_array( $currentUnloadedScriptHandle, $manageScripts ) ) {
|
|
$manageScripts[] = $currentUnloadedScriptHandle;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($wp_scripts->done) && ! empty($wp_scripts->done)) {
|
|
foreach ($wp_scripts->done as $wpDoneScript) {
|
|
if ( ! in_array( $wpDoneScript, $manageScripts ) ) {
|
|
$manageScripts[] = $wpDoneScript;
|
|
}
|
|
}
|
|
}
|
|
|
|
$manageScripts = array_unique($manageScripts);
|
|
}
|
|
|
|
/*
|
|
* Style List
|
|
*/
|
|
if ($isFrontEndEditView) { // "Manage in the Front-end"
|
|
$stylesList = $stylesBeforeUnload['registered'];
|
|
} else { // "Manage in the Dashboard"
|
|
$stylesListFilterAll = $this->wpStylesFilter($wp_styles, 'registered');
|
|
$stylesList = $stylesListFilterAll->registered;
|
|
}
|
|
|
|
if (! empty($stylesList)) {
|
|
foreach ($manageStyles as $handle) {
|
|
if (! isset($stylesList[$handle]) || in_array($handle, $this->skipAssets['styles'])) {
|
|
continue;
|
|
}
|
|
|
|
$list['styles'][] = $stylesList[$handle];
|
|
}
|
|
|
|
// Append unloaded ones (if any)
|
|
if (! empty($stylesBeforeUnload) && ! empty($currentUnloadedAll['styles'])) {
|
|
foreach ($currentUnloadedAll['styles'] as $sbuHandle) {
|
|
if (! in_array($sbuHandle, $manageStyles)) {
|
|
// Could be an old style that is not loaded anymore
|
|
// We have to check that
|
|
if (! isset($stylesBeforeUnload['registered'][$sbuHandle])) {
|
|
continue;
|
|
}
|
|
|
|
$sbuValue = $stylesBeforeUnload['registered'][$sbuHandle];
|
|
$list['styles'][] = $sbuValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
ksort($list['styles']);
|
|
}
|
|
|
|
/*
|
|
* Scripts List
|
|
*/
|
|
$scriptsList = $wp_scripts->registered;
|
|
|
|
if ($isFrontEndEditView) {
|
|
$scriptsList = $scriptsBeforeUnload['registered'];
|
|
}
|
|
|
|
if (! empty($scriptsList)) {
|
|
/* These scripts below are used by this plugin (except admin-bar) and they should not show in the list
|
|
as they are loaded only when you (or other admin) manage the assets, never for your website visitors */
|
|
foreach ($manageScripts as $handle) {
|
|
if (! isset($scriptsList[$handle]) || in_array($handle, $this->skipAssets['scripts'])) {
|
|
continue;
|
|
}
|
|
|
|
$list['scripts'][] = $scriptsList[$handle];
|
|
}
|
|
|
|
// Append unloaded ones (if any)
|
|
if (! empty($scriptsBeforeUnload) && ! empty($currentUnloadedAll['scripts'])) {
|
|
foreach ($currentUnloadedAll['scripts'] as $sbuHandle) {
|
|
if (! in_array($sbuHandle, $manageScripts)) {
|
|
// Could be an old script that is not loaded anymore
|
|
// We have to check that
|
|
if (! isset($scriptsBeforeUnload['registered'][$sbuHandle])) {
|
|
continue;
|
|
}
|
|
|
|
$sbuValue = $scriptsBeforeUnload['registered'][$sbuHandle];
|
|
|
|
$list['scripts'][] = $sbuValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
ksort($list['scripts']);
|
|
|
|
}
|
|
|
|
if (! empty($list)) {
|
|
Update::updateHandlesInfo( $list );
|
|
}
|
|
|
|
// [wpacu_lite]
|
|
if ($isFrontEndEditView && ! $this->isUpdateable) {
|
|
$this->parseTemplate('settings-frontend-lite-locked', array(), true);
|
|
}
|
|
// [/wpacu_lite]
|
|
|
|
// Front-end View while admin is logged in
|
|
elseif ($isFrontEndEditView) {
|
|
$wpacuSettings = new Settings();
|
|
|
|
$data = array(
|
|
'is_frontend_view' => true,
|
|
'post_type' => '',
|
|
'bulk_unloaded' => array( 'post_type' => array() ),
|
|
'plugin_settings' => $wpacuSettings->getAll(),
|
|
'current_unloaded_all' => $currentUnloadedAll,
|
|
'current_unloaded_page_level' => $this->getAssetsUnloadedPageLevel( $this->getCurrentPostId(), true )
|
|
);
|
|
|
|
$data['wpacu_page_just_updated'] = false;
|
|
|
|
if (isset($_GET['wpacu_time'], $_GET['nocache']) && get_transient('wpacu_page_just_updated')) {
|
|
$data['wpacu_page_just_updated'] = true;
|
|
delete_transient('wpacu_page_just_updated');
|
|
}
|
|
|
|
if ($currentDebug = ObjectCache::wpacu_cache_get('wpacu_assets_unloaded_list_page_request')) {
|
|
foreach ( array( 'styles', 'scripts' ) as $assetType ) {
|
|
if ( isset( $data['current_unloaded_all'][ $assetType ] ) && ! empty( $data['current_unloaded_all'][ $assetType ] ) ) {
|
|
foreach ( $data['current_unloaded_all'][ $assetType ] as $handleKey => $handle ) {
|
|
if ( isset( $currentDebug[ $assetType ] ) && in_array( $handle, $currentDebug[ $assetType ] ) ) {
|
|
unset( $data['current_unloaded_all'][ $assetType ][ $handleKey ] );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// e.g. /?wpacu_unload_(css|js)=
|
|
$data['current_debug'] = ObjectCache::wpacu_cache_get('wpacu_assets_unloaded_list_page_request');
|
|
|
|
$data['all']['scripts'] = $list['scripts'];
|
|
$data['all']['styles'] = $list['styles'];
|
|
|
|
if ($data['plugin_settings']['assets_list_layout'] === 'by-location') {
|
|
$data['all'] = Sorting::appendLocation($data['all']);
|
|
} else {
|
|
$data['all'] = Sorting::sortListByAlpha($data['all']);
|
|
}
|
|
|
|
$this->fetchUrl = Misc::getPageUrl($this->getCurrentPostId());
|
|
|
|
$data['fetch_url'] = $this->fetchUrl;
|
|
|
|
$data['nonce_action'] = Update::NONCE_ACTION_NAME;
|
|
$data['nonce_name'] = Update::NONCE_FIELD_NAME;
|
|
|
|
$data = $this->alterAssetObj($data);
|
|
$data['global_unload'] = $this->globalUnloaded;
|
|
|
|
$type = false;
|
|
|
|
if (Misc::isHomePage() && $this->getCurrentPostId() < 1 && ! get_option('page_on_front')) {
|
|
$type = 'front_page';
|
|
} elseif ($this->getCurrentPostId() > 0) {
|
|
$type = 'post';
|
|
}
|
|
|
|
$data['wpacu_type'] = $type;
|
|
|
|
$data['load_exceptions_per_page'] = $this->getLoadExceptionsPageLevel($type, $this->getCurrentPostId());
|
|
|
|
// Avoid the /?wpacu_load_(css|js) to interfere with the form inputs
|
|
if ($loadExceptionsDebug = ObjectCache::wpacu_cache_get( 'wpacu_exceptions_list_page_request' )) {
|
|
foreach ( array( 'styles', 'scripts' ) as $assetType ) {
|
|
if ( isset( $data['load_exceptions_per_page'][ $assetType ], $loadExceptionsDebug[ $assetType ] ) && ! empty( $data['load_exceptions_per_page'][ $assetType ] ) ) {
|
|
foreach ( $data['load_exceptions_per_page'][ $assetType ] as $handleKey => $handle ) {
|
|
if ( in_array( $handle, $loadExceptionsDebug[ $assetType ] ) ) {
|
|
unset( $data['load_exceptions_per_page'][ $assetType ][ $handleKey ] );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// e.g. /?wpacu_load_(css|js)=
|
|
$data['load_exceptions_debug'] = $loadExceptionsDebug;
|
|
}
|
|
|
|
// WooCommerce Shop Page?
|
|
$data['is_woo_shop_page'] = self::$vars['is_woo_shop_page'];
|
|
|
|
$data['is_bulk_unloadable'] = $data['bulk_unloaded_type'] = false;
|
|
|
|
$data['bulk_unloaded']['post_type'] = array('styles' => array(), 'scripts' => array());
|
|
|
|
$data['load_exceptions_post_type'] = array();
|
|
|
|
if (self::isSingularPage()) {
|
|
$post = $this->getCurrentPost();
|
|
|
|
$data['post_id'] = $post->ID;
|
|
|
|
// Current Post Type
|
|
$data['post_type'] = $post->post_type;
|
|
|
|
$data['load_exceptions_post_type'] = $this->getLoadExceptionsPostType($data['post_type']);
|
|
|
|
// Are there any assets unloaded for this specific post type?
|
|
// (e.g. page, post, product (from WooCommerce) or other custom post type)
|
|
$data['bulk_unloaded']['post_type'] = $this->getBulkUnload('post_type', $data['post_type']);
|
|
|
|
$data['bulk_unloaded_type'] = 'post_type';
|
|
|
|
$data['is_bulk_unloadable'] = true;
|
|
|
|
$data['post_type_has_tax_assoc'] = self::getAllSetTaxonomies($data['post_type']);
|
|
|
|
$data = $this->setPageTemplate($data);
|
|
}
|
|
|
|
$data['total_styles'] = ! empty($data['all']['styles']) ? count($data['all']['styles']) : false;
|
|
$data['total_scripts'] = ! empty($data['all']['scripts']) ? count($data['all']['scripts']) : false;
|
|
|
|
$data['all_deps'] = $this->getAllDeps($data['all']);
|
|
|
|
$data['preloads'] = Preloads::instance()->getPreloads();
|
|
|
|
// Load exception: If the user is logged in (applies globally)
|
|
$data['handle_load_logged_in'] = $this->getHandleLoadLoggedIn();
|
|
|
|
$data['handle_notes'] = $this->getHandleNotes();
|
|
$data['handle_rows_contracted'] = self::getHandleRowStatus();
|
|
|
|
$data['ignore_child'] = $this->getIgnoreChildren();
|
|
|
|
switch (assetCleanUpHasNoLoadMatches($data['fetch_url'])) {
|
|
case 'is_set_in_settings':
|
|
// The rules from "Settings" -> "Plugin Usage Preferences" -> "Do not load the plugin on certain pages" will be checked
|
|
$data['status'] = 5;
|
|
break;
|
|
|
|
case 'is_set_in_page':
|
|
// The following option from "Page Options" (within the CSS/JS manager of the targeted page) is set: "Do not load Asset CleanUp Pro on this page (this will disable any functionality of the plugin)"
|
|
$data['status'] = 6;
|
|
break;
|
|
|
|
default:
|
|
$data['status'] = 1;
|
|
}
|
|
|
|
$data['page_options'] = array();
|
|
$data['show_page_options'] = false;
|
|
|
|
if (in_array($type, array('post', 'front_page'))) {
|
|
$data['show_page_options'] = true;
|
|
$data['page_options'] = MetaBoxes::getPageOptions($this->getCurrentPostId(), $type);
|
|
}
|
|
|
|
$data['post_id'] = ($type === 'front_page') ? 0 : $this->getCurrentPostId();
|
|
ObjectCache::wpacu_cache_set('wpacu_settings_frontend_data', $data);
|
|
$this->parseTemplate('settings-frontend', $data, true);
|
|
} elseif ($isDashboardEditView && ! isset($_GET['wpacu_just_hardcoded'])) {
|
|
// AJAX call (not the classic WP one) from the WP Dashboard
|
|
// Send the altered value that has the initial position too
|
|
|
|
// Taken front the front-end view
|
|
$data = array();
|
|
$data['all']['scripts'] = $list['scripts'];
|
|
$data['all']['styles'] = $list['styles'];
|
|
|
|
$data = $this->alterAssetObj($data);
|
|
|
|
$list['styles'] = $data['all']['styles'];
|
|
$list['scripts'] = $data['all']['scripts'];
|
|
|
|
if ( isset($_GET['wpacu_print']) ) {
|
|
echo '<!-- '."\n".print_r(Misc::filterList($list), true)."\n".' -->';
|
|
}
|
|
|
|
// e.g. for "Loaded" and "Unloaded" statuses
|
|
$list['current_unloaded_all'] = isset($this->allUnloadedAssets) ? $this->allUnloadedAssets : array('styles' => array(), 'scripts' => array());
|
|
|
|
echo self::START_DEL_ENQUEUED . base64_encode(wp_json_encode($list)) . self::END_DEL_ENQUEUED; // Loaded via wp_enqueue_scripts()
|
|
echo self::START_DEL_HARDCODED . '{wpacu_hardcoded_assets}' . self::END_DEL_HARDCODED; // Make the user aware of any hardcoded CSS/JS (if any)
|
|
|
|
add_action('shutdown', static function() {
|
|
// Do not allow further processes as cache plugins such as W3 Total Cache could alter the source code
|
|
// and we need the non-minified version of the DOM (e.g. to determine the position of the elements)
|
|
exit();
|
|
});
|
|
} elseif ($isDashboardEditView && isset($_GET['wpacu_just_hardcoded'])) {
|
|
// AJAX call just for the hardcoded assets
|
|
echo self::START_DEL_HARDCODED . '{wpacu_hardcoded_assets}' . self::END_DEL_HARDCODED; // Make the user aware of any hardcoded CSS/JS (if any)
|
|
|
|
add_action('shutdown', static function() {
|
|
// Do not allow further processes as cache plugins such as W3 Total Cache could alter the source code,
|
|
// and we need the non-minified version of the DOM (e.g. to determine the position of the elements)
|
|
exit();
|
|
});
|
|
}
|
|
|
|
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
|
}
|
|
|
|
/**
|
|
* @param $name
|
|
* @param array $data (if present $data values are used within the included template)
|
|
* @param bool|false $echo
|
|
* @param bool|false $returnData (relevant when $echo is set to true)
|
|
* @return string|array
|
|
*/
|
|
public function parseTemplate($name, $data = array(), $echo = false, $returnData = false)
|
|
{
|
|
$templateFile = apply_filters(
|
|
'wpacu_template_file', // tag
|
|
dirname(__DIR__) . '/templates/' . $name . '.php', // value
|
|
$name // extra argument
|
|
);
|
|
|
|
if (! is_file($templateFile)) {
|
|
return 'Template '.$templateFile.' not found.';
|
|
}
|
|
|
|
ob_start();
|
|
include $templateFile;
|
|
$result = ob_get_clean();
|
|
|
|
// $echo is set to true ($returnData is not relevant), thus print the output
|
|
if ($echo) {
|
|
echo $result;
|
|
return true;
|
|
}
|
|
|
|
// $echo is set to false and $returnData to true
|
|
if ($returnData) {
|
|
return array(
|
|
'output' => $result,
|
|
'data' => $data
|
|
);
|
|
}
|
|
|
|
/// $echo is set to false (default) and $returnData to $false (default)
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function ajaxGetJsonListCallback()
|
|
{
|
|
if ( ! isset($_POST['wpacu_nonce']) ) {
|
|
echo 'Error: The security nonce was not sent for verification. Location: '.__METHOD__;
|
|
return;
|
|
}
|
|
|
|
if ( ! wp_verify_nonce($_POST['wpacu_nonce'], 'wpacu_ajax_get_loaded_assets_nonce') ) {
|
|
echo 'Error: The nonce security check has failed. Location: '.__METHOD__;
|
|
return;
|
|
}
|
|
|
|
$postId = (int)Misc::getVar('post', 'post_id'); // if any (could be home page for instance)
|
|
$pageUrl = Misc::getVar('post', 'page_url'); // post, page, custom post type, home page etc.
|
|
|
|
$postStatus = $postId > 0 ? get_post_status($postId) : false;
|
|
|
|
// Not homepage, but a post/page? Check if it's published in case AJAX call
|
|
// wasn't stopped due to JS errors or other reasons
|
|
if ($postId > 0 && ! in_array($postStatus, array('publish', 'private'))) {
|
|
exit(__('The CSS/JS files will be available to manage once the post/page is published.', 'wp-asset-clean-up'));
|
|
}
|
|
|
|
if ($postId > 0) {
|
|
$type = 'post';
|
|
} elseif ($postId == 0) {
|
|
$type = 'front_page';
|
|
}
|
|
|
|
$wpacuListE = $wpacuListH = '';
|
|
|
|
$settings = new Settings();
|
|
|
|
// If the post status is 'private' only direct method can be used to fetch the assets
|
|
// as the remote post one will return a 404 error since the page is accessed as a guest visitor
|
|
if (self::$domGetType === 'direct' || $postStatus === 'private') {
|
|
$wpacuListE = Misc::getVar('post', 'wpacu_list_e');
|
|
$wpacuListH = Misc::getVar('post', 'wpacu_list_h');
|
|
} elseif (self::$domGetType === 'wp_remote_post') {
|
|
$wpRemotePost = wp_remote_post($pageUrl, array(
|
|
'body' => array(
|
|
WPACU_LOAD_ASSETS_REQ_KEY => 1
|
|
)
|
|
));
|
|
|
|
$contents = (is_array($wpRemotePost) && isset($wpRemotePost['body']) && (! is_wp_error($wpRemotePost))) ? $wpRemotePost['body'] : '';
|
|
|
|
// Enqueued List
|
|
if ($contents
|
|
&& ( strpos($contents, self::START_DEL_ENQUEUED) !== false)
|
|
&& ( strpos($contents, self::END_DEL_ENQUEUED) !== false)) {
|
|
// Enqueued CSS/JS (most of them or all)
|
|
$wpacuListE = Misc::extractBetween(
|
|
$contents,
|
|
self::START_DEL_ENQUEUED,
|
|
self::END_DEL_ENQUEUED
|
|
);
|
|
}
|
|
|
|
// Hardcoded List
|
|
if ($contents
|
|
&& ( strpos($contents, self::START_DEL_HARDCODED) !== false)
|
|
&& ( strpos($contents, self::END_DEL_HARDCODED) !== false)) {
|
|
// Hardcoded (if any)
|
|
$wpacuListH = Misc::extractBetween(
|
|
$contents,
|
|
self::START_DEL_HARDCODED,
|
|
self::END_DEL_HARDCODED
|
|
);
|
|
}
|
|
|
|
// The list of assets COULD NOT be retrieved via "WP Remote Post" for this server
|
|
// EITHER the enqueued or hardcoded list of assets HAS TO BE RETRIEVED
|
|
// Print out the 'error' response to make the user aware about it
|
|
if ( ! ($wpacuListE || $wpacuListH) ) {
|
|
// 'body' is set, and it's not an array
|
|
if ( is_wp_error($wpRemotePost) ) {
|
|
$wpRemotePost['response']['message'] = $wpRemotePost->get_error_message();
|
|
} elseif ( isset( $wpRemotePost['body']) ) {
|
|
if ( trim( $wpRemotePost['body'] ) === '' ) {
|
|
$wpRemotePost['body'] = '<strong>Error (blank page):</strong> It looks the targeted page is loading, but it has no content. The page seems to be blank. Please load it in incognito mode (when you are not logged-in) via your browser.';
|
|
} elseif ( ! is_array( $wpRemotePost['body'] ) ) {
|
|
$wpRemotePost['body'] = strip_tags( $wpRemotePost['body'], '<p><a><strong><b><em><i>' );
|
|
}
|
|
}
|
|
|
|
$data = array(
|
|
'is_dashboard_view' => true,
|
|
'plugin_settings' => $settings->getAll(),
|
|
'wp_remote_post' => $wpRemotePost
|
|
);
|
|
|
|
if (isset($type) && $type) {
|
|
$data['page_options'] = MetaBoxes::getPageOptions( $postId, $type );
|
|
}
|
|
|
|
$this->parseTemplate('meta-box-loaded', $data, true);
|
|
exit();
|
|
}
|
|
}
|
|
|
|
$data = array(
|
|
'is_dashboard_view' => true,
|
|
'post_id' => $postId,
|
|
'plugin_settings' => $settings->getAll()
|
|
);
|
|
|
|
// [START] Enqueued CSS/JS (most of them or all)
|
|
$jsonE = base64_decode($wpacuListE);
|
|
$data['all'] = (array)json_decode($jsonE);
|
|
|
|
// Make sure if there are no STYLES enqueued, the list will be empty to avoid any notice errors
|
|
if (! isset($data['all']['styles'])) {
|
|
$data['all']['styles'] = array();
|
|
}
|
|
|
|
// Make sure if there are no SCRIPTS enqueued, the list will be empty to avoid any notice errors
|
|
if (! isset($data['all']['scripts'])) {
|
|
$data['all']['scripts'] = array();
|
|
}
|
|
// [END] Enqueued CSS/JS (most of them or all)
|
|
|
|
// [START] Hardcoded (if any)
|
|
if ($wpacuListH) {
|
|
// Only set the following variables if there is at least one hardcoded LINK/STYLE/SCRIPT
|
|
$jsonH = base64_decode( $wpacuListH );
|
|
$data['all']['hardcoded'] = (array) json_decode( $jsonH, ARRAY_A );
|
|
|
|
if (isset($data['all']['hardcoded']['within_conditional_comments']) && ! empty($data['all']['hardcoded']['within_conditional_comments'])) {
|
|
ObjectCache::wpacu_cache_set( 'wpacu_hardcoded_content_within_conditional_comments', $data['all']['hardcoded']['within_conditional_comments'] );
|
|
}
|
|
}
|
|
// [END] Hardcoded (if any)
|
|
|
|
$data['current_unloaded_page_level'] = $this->getAssetsUnloadedPageLevel( $postId, true );
|
|
|
|
// e.g. for "Loaded" and "Unloaded" statuses
|
|
$data['current_unloaded_all'] = isset($data['all']['current_unloaded_all']) ? (array)$data['all']['current_unloaded_all'] : array('styles' => array(), 'scripts' => array());
|
|
|
|
if ($data['plugin_settings']['assets_list_layout'] === 'by-location') {
|
|
$data['all'] = Sorting::appendLocation($data['all']);
|
|
} else {
|
|
$data['all'] = Sorting::sortListByAlpha($data['all']);
|
|
}
|
|
|
|
$data['fetch_url'] = $pageUrl;
|
|
$data['global_unload'] = $this->getGlobalUnload();
|
|
|
|
// [wpacu_pro]
|
|
//ObjectCache::wpacu_cache_set('wpacu_data_global_unload', $data['global_unload']);
|
|
// [/wpacu_pro]
|
|
|
|
$data['is_bulk_unloadable'] = $data['bulk_unloaded_type'] = false;
|
|
|
|
$data['bulk_unloaded']['post_type'] = array('styles' => array(), 'scripts' => array());
|
|
|
|
// Post Information
|
|
if ($postId > 0) {
|
|
$postData = get_post($postId);
|
|
|
|
if (isset($postData->post_type) && $postData->post_type) {
|
|
// Current Post Type
|
|
$data['post_type'] = $postData->post_type;
|
|
|
|
// Are there any assets unloaded for this specific post type?
|
|
// (e.g. page, post, product (from WooCommerce) or other custom post type)
|
|
$data['bulk_unloaded']['post_type'] = $this->getBulkUnload('post_type', $data['post_type']);
|
|
$data['bulk_unloaded_type'] = 'post_type';
|
|
$data['is_bulk_unloadable'] = true;
|
|
$data['post_type_has_tax_assoc'] = self::getAllSetTaxonomies($data['post_type']);
|
|
}
|
|
}
|
|
|
|
// DO NOT alter any position as it's already verified and set
|
|
// This AJAX call is for printing the assets that were already fetched
|
|
$data = $this->alterAssetObj($data, false);
|
|
|
|
$data['wpacu_type'] = $type;
|
|
|
|
// e.g. LITE rules: Load it on this page & on all pages of a specific post type
|
|
$data['load_exceptions_per_page'] = $this->getLoadExceptionsPageLevel($type, $postId);
|
|
$data['load_exceptions_post_type'] = ($type === 'post' && $data['post_type']) ? $this->getLoadExceptionsPostType($data['post_type']) : array();
|
|
|
|
|
|
$data['handle_rows_contracted'] = self::getHandleRowStatus();
|
|
|
|
$data['total_styles'] = ! empty($data['all']['styles']) ? count($data['all']['styles']) : 0;
|
|
$data['total_scripts'] = ! empty($data['all']['scripts']) ? count($data['all']['scripts']) : 0;
|
|
|
|
$data['all_deps'] = $this->getAllDeps($data['all']);
|
|
|
|
$data['preloads'] = Preloads::instance()->getPreloads();
|
|
|
|
$data['handle_load_logged_in'] = $this->getHandleLoadLoggedIn();
|
|
$data['handle_notes'] = $this->getHandleNotes();
|
|
|
|
$data['ignore_child'] = $this->getIgnoreChildren();
|
|
|
|
$data['is_for_singular'] = (Misc::getVar('post', 'is_for_singular') === 'true');
|
|
|
|
$data['page_options'] = array();
|
|
$data['show_page_options'] = false;
|
|
|
|
if (in_array($type, array('post', 'front_page'))) {
|
|
$data['show_page_options'] = true;
|
|
$data['page_options'] = MetaBoxes::getPageOptions($postId, $type);
|
|
}
|
|
|
|
$this->parseTemplate('meta-box-loaded', $data, true);
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function ajaxLoadRestrictedPageAreaCallback()
|
|
{
|
|
if ( ! isset( $_POST['wpacu_nonce'] ) || ! wp_verify_nonce( $_POST['wpacu_nonce'], 'wpacu_ajax_load_page_restricted_area_nonce' ) ) {
|
|
echo 'Error: The security nonce is not valid.';
|
|
exit();
|
|
}
|
|
|
|
$postId = (int)Misc::getVar('post', 'post_id'); // if any (could be home page for instance)
|
|
|
|
$data = array();
|
|
|
|
$data['post_id'] = $this->currentPostId = $postId;
|
|
$data['fetch_url'] = Misc::getPageUrl($postId);
|
|
|
|
$data['show_page_options'] = true;
|
|
$data['page_options'] = MetaBoxes::getPageOptions($postId);
|
|
|
|
$post = get_post($postId);
|
|
|
|
// Current Post Type
|
|
$data['post_type'] = $post->post_type;
|
|
$data['bulk_unloaded_type'] = 'post_type';
|
|
$data['is_bulk_unloadable'] = true;
|
|
|
|
$data = $this->setPageTemplate($data);
|
|
|
|
switch (assetCleanUpHasNoLoadMatches($data['fetch_url'])) {
|
|
case 'is_set_in_settings':
|
|
// The rules from "Settings" -> "Plugin Usage Preferences" -> "Do not load the plugin on certain pages" will be checked
|
|
$data['status'] = 5;
|
|
break;
|
|
|
|
case 'is_set_in_page':
|
|
// The following option from "Page Options" (within the CSS/JS manager of the targeted page) is set: "Do not load Asset CleanUp Pro on this page (this will disable any functionality of the plugin)"
|
|
$data['status'] = 6;
|
|
break;
|
|
|
|
default:
|
|
$data['status'] = 1;
|
|
}
|
|
|
|
$this->parseTemplate('meta-box-restricted-page-load', $data, true);
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function ajaxPrintLoadedHardcodedAssets()
|
|
{
|
|
if ( ! isset( $_POST['wpacu_nonce'] ) || ! wp_verify_nonce( $_POST['wpacu_nonce'], 'wpacu_print_loaded_hardcoded_assets_nonce' ) ) {
|
|
echo 'Error: The security nonce is not valid.';
|
|
exit();
|
|
}
|
|
|
|
$wpacuListH = Misc::getVar('post', 'wpacu_list_h');
|
|
$wpacuSettingsJson = base64_decode(Misc::getVar('post', 'wpacu_settings'));
|
|
$wpacuSettings = (array)json_decode($wpacuSettingsJson, ARRAY_A); // $data values are passed here
|
|
|
|
// Only set the following variables if there is at least one hardcoded LINK/STYLE/SCRIPT
|
|
$jsonH = base64_decode( $wpacuListH );
|
|
|
|
function wpacuPrintHardcodedManagementList($jsonH, $wpacuSettings) {
|
|
$data = $wpacuSettings ?: array();
|
|
$data['do_not_print_list'] = true;
|
|
$data['print_outer_html'] = false;
|
|
$data['all']['hardcoded'] = (array)json_decode($jsonH, ARRAY_A);
|
|
$totalHardcodedTags = 0; // default
|
|
|
|
if (isset($data['all']['hardcoded']['within_conditional_comments']) && ! empty($data['all']['hardcoded']['within_conditional_comments'])) {
|
|
ObjectCache::wpacu_cache_set( 'wpacu_hardcoded_content_within_conditional_comments', $data['all']['hardcoded']['within_conditional_comments'] );
|
|
}
|
|
|
|
ob_start();
|
|
// $totalHardcodedTags is set here
|
|
include_once WPACU_PLUGIN_DIR.'/templates/meta-box-loaded-assets/_assets-hardcoded-list.php'; // generate $hardcodedTagsOutput
|
|
$output = ob_get_clean();
|
|
|
|
return wp_json_encode( array(
|
|
'output' => $output,
|
|
'total_hardcoded_assets' => $totalHardcodedTags
|
|
) );
|
|
}
|
|
|
|
echo wpacuPrintHardcodedManagementList( $jsonH, $wpacuSettings );
|
|
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function ajaxCheckExternalUrlsForStatusCode()
|
|
{
|
|
if ( ! isset( $_POST['wpacu_nonce'] ) || ! wp_verify_nonce( $_POST['wpacu_nonce'], 'wpacu_ajax_check_external_urls_nonce' ) ) {
|
|
echo 'Error: The security nonce is not valid.';
|
|
exit();
|
|
}
|
|
|
|
if (! isset($_POST['action'], $_POST['wpacu_check_urls'])) {
|
|
echo 'Error: The post parameters are not the right ones.';
|
|
exit();
|
|
}
|
|
|
|
// Check privileges
|
|
if (! Menu::userCanManageAssets()) {
|
|
echo 'Error: Not enough privileges to perform this action.';
|
|
exit();
|
|
}
|
|
|
|
$checkUrls = explode('-at-wpacu-at-', $_POST['wpacu_check_urls']);
|
|
$checkUrls = array_filter(array_unique($checkUrls));
|
|
|
|
foreach ($checkUrls as $index => $checkUrl) {
|
|
if (strpos($checkUrl, '//') === 0) { // starts with // (append the right protocol)
|
|
if (strpos($checkUrl, 'fonts.googleapis.com') !== false) {
|
|
$checkUrl = 'https:'.$checkUrl;
|
|
} else {
|
|
// either HTTP or HTTPS depending on the current page situation (that the admin has loaded)
|
|
$checkUrl = (Misc::isHttpsSecure() ? 'https:' : 'http:') . $checkUrl;
|
|
}
|
|
}
|
|
|
|
$response = wp_remote_get($checkUrl);
|
|
|
|
// Remove 200 OK ones as the other ones will remain for highlighting
|
|
if (wp_remote_retrieve_response_code($response) === 200) {
|
|
unset($checkUrls[$index]);
|
|
}
|
|
}
|
|
|
|
echo wp_json_encode($checkUrls);
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function ajaxFetchActivePluginsIconsFromWordPressOrg()
|
|
{
|
|
if ( ! isset($_POST['wpacu_nonce']) ) {
|
|
echo 'Error: The security nonce was not sent for verification. Location: '.__METHOD__;
|
|
return;
|
|
}
|
|
|
|
if ( ! wp_verify_nonce($_POST['wpacu_nonce'], 'wpacu_fetch_active_plugins_icons') ) {
|
|
echo 'Error: The security check has failed. Location: '.__METHOD__;
|
|
return;
|
|
}
|
|
|
|
if (! isset($_POST['action'])) {
|
|
return;
|
|
}
|
|
|
|
if (! Menu::userCanManageAssets()) {
|
|
return;
|
|
}
|
|
|
|
echo 'POST DATA: '.print_r($_POST, true)."\n\n";
|
|
|
|
echo '- Downloading from WordPress.org'."\n\n";
|
|
|
|
$activePluginsIcons = Misc::fetchActiveFreePluginsIconsFromWordPressOrg();
|
|
|
|
if ($activePluginsIcons && is_array($activePluginsIcons) && ! empty($activePluginsIcons)) {
|
|
echo print_r($activePluginsIcons, true)."\n";
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function ajaxFetchActivePluginsJsFooterCode()
|
|
{
|
|
if (! Menu::isPluginPage()) {
|
|
return;
|
|
}
|
|
|
|
if (! Menu::userCanManageAssets()) {
|
|
return;
|
|
}
|
|
|
|
$forcePluginIconsDownload = isset($_GET['wpacu_force_plugin_icons_fetch']);
|
|
|
|
$triggerPluginIconsDownload = $forcePluginIconsDownload || ! get_transient('wpacu_active_plugins_icons');
|
|
|
|
if (! $triggerPluginIconsDownload) {
|
|
return;
|
|
}
|
|
?>
|
|
<script type="text/javascript" >
|
|
jQuery(document).ready(function($) {
|
|
var wpacuDataToSend = {
|
|
'action': '<?php echo WPACU_PLUGIN_ID.'_fetch_active_plugins_icons'; ?>',
|
|
'wpacu_nonce': '<?php echo wp_create_nonce('wpacu_fetch_active_plugins_icons'); ?>'
|
|
};
|
|
|
|
jQuery.post(ajaxurl, wpacuDataToSend, function(response) {
|
|
console.log(response);
|
|
});
|
|
});
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* @param $data
|
|
* @return mixed
|
|
*/
|
|
public function alterAssetObj($data, $alterPosition = true)
|
|
{
|
|
$siteUrl = get_site_url();
|
|
|
|
if (! empty($data['all']['styles'])) {
|
|
$data['core_styles_loaded'] = false;
|
|
|
|
foreach ($data['all']['styles'] as $key => $obj) {
|
|
if (! isset($obj->handle)) {
|
|
unset($data['all']['styles']['']);
|
|
continue;
|
|
}
|
|
|
|
// From WordPress directories (false by default, unless it was set to true before: in Sorting.php for instance)
|
|
if (! isset($data['all']['styles'][$key]->wp)) {
|
|
$data['all']['styles'][$key]->wp = false;
|
|
}
|
|
|
|
if ($alterPosition) {
|
|
if ( in_array( $obj->handle, $this->assetsInFooter['styles'] ) ) {
|
|
$data['all']['styles'][ $key ]->position = 'body';
|
|
} else {
|
|
$data['all']['styles'][ $key ]->position = 'head';
|
|
}
|
|
}
|
|
|
|
if (isset($data['all']['styles'][$key], $obj->src) && $obj->src) {
|
|
$localSrc = Misc::getLocalSrc($obj->src);
|
|
|
|
if (! empty($localSrc)) {
|
|
$data['all']['styles'][$key]->baseUrl = $localSrc['base_url'];
|
|
|
|
if (Sorting::matchesWpCoreCriteria($obj, 'styles')) {
|
|
$data['all']['styles'][ $key ]->wp = true;
|
|
$data['core_styles_loaded'] = true;
|
|
}
|
|
}
|
|
|
|
// Determine source href (starting with '/' but not starting with '//')
|
|
if (strpos($obj->src, '/') === 0 && strpos($obj->src, '//') !== 0) {
|
|
$obj->srcHref = $siteUrl . $obj->src;
|
|
} else {
|
|
$obj->srcHref = $obj->src;
|
|
}
|
|
|
|
$data['all']['styles'][$key]->size = apply_filters('wpacu_get_asset_file_size', $data['all']['styles'][$key], 'for_print');
|
|
$data['all']['styles'][$key]->sizeRaw = apply_filters('wpacu_get_asset_file_size', $data['all']['styles'][$key], 'raw');
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! empty($data['all']['scripts'])) {
|
|
$data['core_scripts_loaded'] = false;
|
|
|
|
foreach ($data['all']['scripts'] as $key => $obj) {
|
|
if (! isset($obj->handle)) {
|
|
unset($data['all']['scripts']['']);
|
|
continue;
|
|
}
|
|
|
|
// From WordPress directories (false by default, unless it was set to true before: in Sorting.php for instance)
|
|
if (! isset($data['all']['scripts'][$key]->wp)) {
|
|
$data['all']['scripts'][$key]->wp = false;
|
|
}
|
|
|
|
if ($alterPosition) {
|
|
$initialScriptPos = ObjectCache::wpacu_cache_get( $obj->handle, 'wpacu_scripts_initial_positions' );
|
|
|
|
if ( $initialScriptPos === 'body' || in_array( $obj->handle, $this->assetsInFooter['scripts'] ) ) {
|
|
$data['all']['scripts'][ $key ]->position = 'body';
|
|
} else {
|
|
$data['all']['scripts'][ $key ]->position = 'head';
|
|
}
|
|
}
|
|
|
|
if (isset($data['all']['scripts'][$key])) {
|
|
if (isset($obj->src) && $obj->src) {
|
|
$localSrc = Misc::getLocalSrc($obj->src);
|
|
|
|
if (! empty($localSrc)) {
|
|
$data['all']['scripts'][$key]->baseUrl = $localSrc['base_url'];
|
|
|
|
if (Sorting::matchesWpCoreCriteria($obj, 'scripts')) {
|
|
$data['all']['scripts'][ $key ]->wp = true;
|
|
$data['core_scripts_loaded'] = true;
|
|
}
|
|
}
|
|
|
|
// Determine source href
|
|
if (substr($obj->src, 0, 1) === '/' && substr($obj->src, 0, 2) !== '//') {
|
|
$obj->srcHref = $siteUrl . $obj->src;
|
|
} else {
|
|
$obj->srcHref = $obj->src;
|
|
}
|
|
}
|
|
|
|
if (in_array($obj->handle, array('jquery', 'jquery-core', 'jquery-migrate'))) {
|
|
$data['all']['scripts'][$key]->wp = true;
|
|
$data['core_scripts_loaded'] = true;
|
|
}
|
|
|
|
$data['all']['scripts'][$key]->size = apply_filters('wpacu_get_asset_file_size', $data['all']['scripts'][$key], 'for_print');
|
|
$data['all']['scripts'][$key]->sizeRaw = apply_filters('wpacu_get_asset_file_size', $data['all']['scripts'][$key], 'raw');
|
|
}
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* This method retrieves only the assets that are unloaded per page
|
|
* Including 404, date and search pages (they are considered as ONE page with the same rules for any URL variation)
|
|
*
|
|
* @param int $postId
|
|
* @param bool $returnAsArray
|
|
*
|
|
* @return string|array (The returned value must be a JSON one)
|
|
*/
|
|
public function getAssetsUnloadedPageLevel($postId = 0, $returnAsArray = false)
|
|
{
|
|
$defaultEmptyArrayValue = array( 'styles' => array(), 'scripts' => array() );
|
|
|
|
// Post Type (Overwrites 'front' - home page - if we are in a singular post)
|
|
if ($postId == 0) {
|
|
$postId = (int)$this->getCurrentPostId();
|
|
}
|
|
|
|
$isInAdminPageViaAjax = (is_admin() && defined('DOING_AJAX') && DOING_AJAX);
|
|
|
|
$assetsRemovedPageLevel = wp_json_encode( $defaultEmptyArrayValue );
|
|
|
|
// For Home Page (latest blog posts)
|
|
if ( $postId < 1 && ( $isInAdminPageViaAjax || Misc::isHomePage() ) ) {
|
|
$assetsRemovedPageLevel = get_option( WPACU_PLUGIN_ID . '_front_page_no_load' );
|
|
} elseif ( $postId > 0 ) { // Singular Page
|
|
$assetsRemovedPageLevel = get_post_meta( $postId, '_' . WPACU_PLUGIN_ID . '_no_load', true );
|
|
}
|
|
|
|
@json_decode( $assetsRemovedPageLevel );
|
|
|
|
if ( ! ( Misc::jsonLastError() === JSON_ERROR_NONE ) || empty( $assetsRemovedPageLevel ) || $assetsRemovedPageLevel === '[]' ) {
|
|
// Reset value to a JSON formatted one
|
|
$assetsRemovedPageLevel = wp_json_encode( $defaultEmptyArrayValue );
|
|
}
|
|
|
|
$assetsRemovedDecoded = json_decode( $assetsRemovedPageLevel, ARRAY_A );
|
|
|
|
if (! isset($assetsRemovedDecoded['styles'])) {
|
|
$assetsRemovedDecoded['styles'] = array();
|
|
}
|
|
|
|
if (! isset($assetsRemovedDecoded['scripts'])) {
|
|
$assetsRemovedDecoded['scripts'] = array();
|
|
}
|
|
|
|
/* [START] Unload CSS/JS on page request for debugging purposes */
|
|
$assetsUnloadedOnTheFly = $defaultEmptyArrayValue;
|
|
|
|
if ( Misc::getVar( 'get', 'wpacu_unload_css' ) ) {
|
|
$cssOnTheFlyList = $this->unloadAssetOnTheFly( 'css' );
|
|
|
|
if ( ! empty( $cssOnTheFlyList ) ) {
|
|
foreach ( $cssOnTheFlyList as $cssHandle ) {
|
|
if ( ! in_array( $cssHandle, $assetsRemovedDecoded['styles'] ) ) {
|
|
$assetsRemovedDecoded['styles'][] = $assetsUnloadedOnTheFly['styles'][] = $cssHandle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( Misc::getVar( 'get', 'wpacu_unload_js' ) ) {
|
|
$jsOnTheFlyList = $this->unloadAssetOnTheFly( 'js' );
|
|
|
|
if ( ! empty( $jsOnTheFlyList ) ) {
|
|
foreach ( $jsOnTheFlyList as $jsHandle ) {
|
|
if ( ! in_array( $jsHandle, $assetsRemovedDecoded['scripts'] ) ) {
|
|
$assetsRemovedDecoded['scripts'][] = $assetsUnloadedOnTheFly['scripts'][] = $jsHandle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ObjectCache::wpacu_cache_add( 'wpacu_assets_unloaded_list_page_request', $assetsUnloadedOnTheFly );
|
|
/* [END] Unload CSS/JS on page request for debugging purposes */
|
|
|
|
$assetsRemovedPageLevel = wp_json_encode( $assetsRemovedDecoded );
|
|
|
|
if ($returnAsArray) {
|
|
$assetsRemovedPageLevel = (array)@json_decode($assetsRemovedPageLevel);
|
|
|
|
// Make sure there are no objects in the array to avoid any PHP errors later on in PHP 8+
|
|
foreach ( array( 'styles', 'scripts' ) as $assetType ) {
|
|
if ( isset( $assetsRemovedPageLevel[ $assetType ] ) ) {
|
|
$assetsRemovedPageLevel[ $assetType ] = (array)$assetsRemovedPageLevel[ $assetType ];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Hmm, perhaps one of the filters was incorrectly used and returned an array instead of a JSON format; autocorrect this to avoid PHP errors
|
|
if (! $returnAsArray && is_array($assetsRemovedPageLevel)) {
|
|
return wp_json_encode( $defaultEmptyArrayValue );
|
|
}
|
|
|
|
return $assetsRemovedPageLevel;
|
|
}
|
|
|
|
/**
|
|
* @param $allAssets
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getAllDeps($allAssets)
|
|
{
|
|
$allDepsParentToChild = $allDepsChildToParent = array('styles' => array(), 'scripts' => array());
|
|
|
|
foreach (array('styles', 'scripts') as $assetType) {
|
|
if ( ! (isset($allAssets[$assetType]) && ! empty($allAssets[$assetType])) ) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($allAssets[$assetType] as $assetObj) {
|
|
if (isset($assetObj->deps) && ! empty($assetObj->deps)) {
|
|
foreach ($assetObj->deps as $dep) {
|
|
$allDepsParentToChild[$assetType][$dep][] = $assetObj->handle;
|
|
$allDepsChildToParent[$assetType][$assetObj->handle][] = $dep;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return array(
|
|
'parent_to_child' => $allDepsParentToChild,
|
|
'child_to_parent' => $allDepsChildToParent
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param $obj
|
|
* @param $format | 'for_print': Calculates the format in KB / MB - 'raw': The actual size in bytes
|
|
* @return string
|
|
*/
|
|
public function getAssetFileSize($obj, $format = 'for_print')
|
|
{
|
|
if (isset($obj->src) && $obj->src) {
|
|
$src = $obj->src;
|
|
$siteUrl = site_url();
|
|
|
|
// Starts with / but not with //
|
|
// Or starts with ../ (very rare cases)
|
|
$isRelInternalPath = (strpos($src, '/') === 0 && strpos($src, '//') !== 0) || (strpos($src, '../') === 0);
|
|
|
|
// Source starts with '//' - check if the file exists
|
|
if (strpos($obj->src, '//') === 0) {
|
|
list ($urlPrefix) = explode('//', $siteUrl);
|
|
$srcToCheck = $urlPrefix . $obj->src;
|
|
|
|
$hostSiteUrl = parse_url($siteUrl, PHP_URL_HOST);
|
|
$hostSrc = parse_url($obj->src, PHP_URL_HOST);
|
|
|
|
$siteUrlAltered = str_replace(array($hostSiteUrl, $hostSrc), '{site_host}', $siteUrl);
|
|
$srcAltered = str_replace(array($hostSiteUrl, $hostSrc), '{site_host}', $srcToCheck);
|
|
|
|
$srcMaybeRelPath = str_replace($siteUrlAltered, '', $srcAltered);
|
|
|
|
$possibleStrips = array('?ver', '?cache=');
|
|
|
|
foreach ($possibleStrips as $possibleStrip) {
|
|
if ( strpos( $srcMaybeRelPath, $possibleStrip ) !== false ) {
|
|
list ( $srcMaybeRelPath ) = explode( $possibleStrip, $srcMaybeRelPath );
|
|
}
|
|
}
|
|
|
|
if (is_file(Misc::getWpRootDirPath() . $srcMaybeRelPath)) {
|
|
$fileSize = filesize(Misc::getWpRootDirPath() . $srcMaybeRelPath);
|
|
|
|
if ($format === 'raw') {
|
|
return (int)$fileSize;
|
|
}
|
|
|
|
return Misc::formatBytes($fileSize);
|
|
}
|
|
}
|
|
|
|
// e.g. /?scss=1 (Simple Custom CSS Plugin)
|
|
if (str_replace($siteUrl, '', $src) === '/?sccss=1') {
|
|
$customCss = DynamicLoadedAssets::getSimpleCustomCss();
|
|
$sizeInBytes = mb_strlen($customCss);
|
|
|
|
if ($format === 'raw') {
|
|
return $sizeInBytes;
|
|
}
|
|
|
|
return Misc::formatBytes($sizeInBytes);
|
|
}
|
|
|
|
// External file? Use a different approach
|
|
// Return an HTML code that will be parsed via AJAX through JavaScript
|
|
$isExternalFile = (! $isRelInternalPath &&
|
|
(! (isset($obj->wp) && $obj->wp === 1))
|
|
&& strpos($src, $siteUrl) !== 0);
|
|
|
|
// e.g. /?scss=1 (Simple Custom CSS Plugin) From External Domain
|
|
// /?custom-css (JetPack Custom CSS)
|
|
$isLoadedOnTheFly = (strpos($src, '?sccss=1') !== false)
|
|
|| (strpos($src, '?custom-css') !== false);
|
|
|
|
if ($isExternalFile || $isLoadedOnTheFly) {
|
|
return '<a class="wpacu-external-file-size" data-src="' . $src . '" href="#">🔗 Get File Size</a>'.
|
|
'<span style="display: none;"><img style="width: 20px; height: 20px;" alt="" align="top" width="20" height="20" src="'.includes_url('images/spinner-2x.gif').'"></span>';
|
|
}
|
|
|
|
$forAssetType = $pathToFile = false;
|
|
|
|
if ( stripos( $src, '.css' ) !== false ) {
|
|
$forAssetType = 'css';
|
|
} elseif ( stripos( $src, '.js' ) !== false ) {
|
|
$forAssetType = 'js';
|
|
}
|
|
|
|
if ($forAssetType) {
|
|
$pathToFile = OptimizeCommon::getLocalAssetPath( $src, $forAssetType );
|
|
}
|
|
|
|
if ( ! is_file($pathToFile) ) { // Fallback, old code...
|
|
// Local file? Core or from a plugin / theme?
|
|
if ( strpos( $obj->src, $siteUrl ) !== false ) {
|
|
// Local Plugin / Theme File
|
|
// Could be a Staging site that is having the Live URL in the General Settings
|
|
$src = ltrim( str_replace( $siteUrl, '', $obj->src ), '/' );
|
|
} elseif ( ( isset( $obj->wp ) && $obj->wp === 1 ) || $isRelInternalPath ) {
|
|
// Local WordPress Core File
|
|
$src = ltrim( $obj->src, '/' );
|
|
}
|
|
|
|
$srcAlt = $src;
|
|
|
|
if ( strpos( $src, '../' ) === 0 ) {
|
|
$srcAlt = str_replace( '../', '', $srcAlt );
|
|
}
|
|
|
|
$pathToFile = Misc::getWpRootDirPath() . $srcAlt;
|
|
|
|
if ( strpos( $pathToFile, '?ver' ) !== false ) {
|
|
list( $pathToFile ) = explode( '?ver', $pathToFile );
|
|
}
|
|
|
|
// It can happen that the CSS/JS has extra parameters (rare cases)
|
|
foreach ( array( '.css?', '.js?' ) as $needlePart ) {
|
|
if ( strpos( $pathToFile, $needlePart ) !== false ) {
|
|
list( $pathToFile ) = explode( '?', $pathToFile );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (is_file($pathToFile)) {
|
|
$sizeInBytes = filesize($pathToFile);
|
|
|
|
if ($format === 'raw') {
|
|
return (int)$sizeInBytes;
|
|
}
|
|
|
|
return Misc::formatBytes($sizeInBytes);
|
|
}
|
|
|
|
return '<em>Error: Could not read '.$pathToFile.'</em>';
|
|
}
|
|
|
|
if ($obj->handle === 'jquery' && isset($obj->src) && ! $obj->src) {
|
|
return '"jquery-core" size';
|
|
}
|
|
|
|
// External or nothing to be shown (perhaps due to an error)
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Source: https://stackoverflow.com/questions/2602612/remote-file-size-without-downloading-file
|
|
*/
|
|
public function ajaxGetExternalFileSize()
|
|
{
|
|
// Check nonce
|
|
if ( ! isset( $_POST['wpacu_nonce'] ) || ! wp_verify_nonce( $_POST['wpacu_nonce'], 'wpacu_ajax_check_remote_file_size_nonce' ) ) {
|
|
echo 'Error: The security nonce is not valid.';
|
|
exit();
|
|
}
|
|
|
|
// Check privileges
|
|
if (! Menu::userCanManageAssets()) {
|
|
echo 'Error: Not enough privileges to perform this action.';
|
|
exit();
|
|
}
|
|
|
|
// Assume failure.
|
|
$result = -1;
|
|
|
|
$remoteFile = Misc::getVar('post', 'wpacu_remote_file', false);
|
|
|
|
if (! $remoteFile) {
|
|
echo 'N/A (external file)';
|
|
exit;
|
|
}
|
|
|
|
// If it starts with //
|
|
if (strpos($remoteFile, '//') === 0) {
|
|
$remoteFile = 'http:'.$remoteFile;
|
|
}
|
|
|
|
// Check if the URL is valid
|
|
if (! filter_var($remoteFile, FILTER_VALIDATE_URL)) {
|
|
echo 'The asset\'s URL - '.$remoteFile.' - is not valid.';
|
|
exit();
|
|
}
|
|
|
|
$curl = curl_init($remoteFile);
|
|
|
|
// Issue a HEAD request and follow any redirects.
|
|
curl_setopt($curl, CURLOPT_NOBODY, true);
|
|
curl_setopt($curl, CURLOPT_HEADER, true);
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
|
|
|
$data = curl_exec($curl);
|
|
curl_close($curl);
|
|
|
|
$content_length = $status = 'unknown';
|
|
|
|
if ($data) {
|
|
if (preg_match( '/^HTTP\/1\.[01] (\d\d\d)/', $data, $matches ) ) {
|
|
$status = (int)$matches[1];
|
|
}
|
|
|
|
if ( preg_match( '/Content-Length: (\d+)/', $data, $matches ) ) {
|
|
$content_length = (int)$matches[1];
|
|
}
|
|
|
|
// http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
|
|
if ( $status === 200 || ($status > 300 && $status <= 308) ) {
|
|
$result = $content_length;
|
|
}
|
|
}
|
|
|
|
if ($content_length === 'unknown') {
|
|
// One more try
|
|
$response = wp_remote_get($remoteFile);
|
|
|
|
$responseCode = wp_remote_retrieve_response_code($response);
|
|
|
|
if ($responseCode === 200) {
|
|
$result = mb_strlen(wp_remote_retrieve_body($response));
|
|
}
|
|
}
|
|
|
|
echo Misc::formatBytes($result);
|
|
|
|
if (stripos($remoteFile, '//fonts.googleapis.com/') !== false) {
|
|
// Google Font APIS CDN
|
|
echo ' + the sizes of the loaded "Google Font" files (see "url" from @font-face within the Source file)';
|
|
} elseif (stripos($remoteFile, '/font-awesome.css') || stripos($remoteFile, '/font-awesome.min.css')) {
|
|
// FontAwesome CDN
|
|
echo ' + the sizes of the loaded "FontAwesome" font files (see "url" from @font-face within the Source file)';
|
|
}
|
|
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public static function isSingularPage()
|
|
{
|
|
return (self::$vars['is_woo_shop_page'] || is_singular() || Misc::isBlogPage());
|
|
}
|
|
|
|
/**
|
|
* @return int|mixed|string
|
|
*/
|
|
public function getCurrentPostId()
|
|
{
|
|
if ($this->currentPostId > 0) {
|
|
return $this->currentPostId;
|
|
}
|
|
|
|
if (Misc::isElementorMaintenanceModeOnForCurrentAdmin() && defined('WPACU_IS_ELEMENTOR_MAINTENANCE_MODE_TEMPLATE_ID')) {
|
|
$this->currentPostId = WPACU_IS_ELEMENTOR_MAINTENANCE_MODE_TEMPLATE_ID;
|
|
return $this->currentPostId;
|
|
}
|
|
|
|
// Are we on the `Shop` page from WooCommerce?
|
|
// Only check option if function `is_shop` exists
|
|
$wooCommerceShopPageId = function_exists('is_shop') ? get_option('woocommerce_shop_page_id') : 0;
|
|
|
|
// Check if we are on the WooCommerce Shop Page
|
|
// Do not mix the WooCommerce Search Page with the Shop Page
|
|
if (function_exists('is_shop') && is_shop()) {
|
|
$this->currentPostId = $wooCommerceShopPageId;
|
|
|
|
if ($this->currentPostId > 0) {
|
|
self::$vars['is_woo_shop_page'] = true;
|
|
}
|
|
} else {
|
|
if ($wooCommerceShopPageId > 0 && Misc::isHomePage() && strpos(get_site_url(), '://') !== false) {
|
|
list($siteUrlAfterProtocol) = explode('://', get_site_url());
|
|
$currentPageUrlAfterProtocol = parse_url(site_url(), PHP_URL_HOST) . $_SERVER['REQUEST_URI'];
|
|
|
|
if ($siteUrlAfterProtocol != $currentPageUrlAfterProtocol && (strpos($siteUrlAfterProtocol, '/shop') !== false)) {
|
|
self::$vars['woo_url_not_match'] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Blog Home Page (aka: Posts page) is not a singular page, it's checked separately
|
|
if (Misc::isBlogPage()) {
|
|
$this->currentPostId = get_option('page_for_posts');
|
|
}
|
|
|
|
// It has to be a single page (no "Posts page")
|
|
if (($this->currentPostId < 1) && is_singular()) {
|
|
global $post;
|
|
$this->currentPostId = isset($post->ID) ? $post->ID : 0;
|
|
}
|
|
|
|
// [wpacu_lite]
|
|
// Undetectable? The page is not a singular one nor the home page
|
|
// It's likely an archive, category page (WooCommerce), 404 page manageable in the Pro version etc.
|
|
if (! $this->currentPostId && ! Misc::isHomePage()) {
|
|
$this->isUpdateable = false;
|
|
}
|
|
// [/wpacu_lite]
|
|
|
|
return $this->currentPostId;
|
|
}
|
|
|
|
/**
|
|
* @return array|null|\WP_Post
|
|
*/
|
|
public function getCurrentPost()
|
|
{
|
|
// Already set? Return it
|
|
if (! empty($this->currentPost)) {
|
|
return $this->currentPost;
|
|
}
|
|
|
|
// Not set? Create and return it
|
|
if (! $this->currentPost && $this->getCurrentPostId() > 0) {
|
|
$this->currentPost = get_post($this->getCurrentPostId());
|
|
return $this->currentPost;
|
|
}
|
|
|
|
// Empty
|
|
return $this->currentPost;
|
|
}
|
|
|
|
/**
|
|
* Get all contracted rows
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function getHandleRowStatus()
|
|
{
|
|
$handleRowStatus = array('styles' => array(), 'scripts' => array());
|
|
|
|
$handleRowStatusListJson = get_option(WPACU_PLUGIN_ID . '_global_data');
|
|
$globalKey = 'handle_row_contracted';
|
|
|
|
if ($handleRowStatusListJson) {
|
|
$handleRowStatusList = @json_decode($handleRowStatusListJson, true);
|
|
|
|
// Issues with decoding the JSON file? Return an empty list
|
|
if (Misc::jsonLastError() !== JSON_ERROR_NONE) {
|
|
return $handleRowStatus;
|
|
}
|
|
|
|
// Are new positions set for styles and scripts?
|
|
foreach (array('styles', 'scripts') as $assetKey) {
|
|
if ( isset( $handleRowStatusList[$assetKey][$globalKey] ) && ! empty( $handleRowStatusList[$assetKey][$globalKey] ) ) {
|
|
$handleRowStatus[$assetKey] = $handleRowStatusList[$assetKey][$globalKey];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $handleRowStatus;
|
|
}
|
|
|
|
/**
|
|
* @param $postType
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function getAllSetTaxonomies($postType)
|
|
{
|
|
if ( ! $postType ) {
|
|
return array();
|
|
}
|
|
|
|
$postTaxonomies = get_object_taxonomies($postType);
|
|
|
|
if ($postType === 'post') {
|
|
$postFormatKey = array_search('post_format', $postTaxonomies);
|
|
unset($postTaxonomies[$postFormatKey]);
|
|
}
|
|
|
|
if (empty($postTaxonomies)) {
|
|
// There are no taxonomies associate with the $postType or $postType is not valid
|
|
return array();
|
|
}
|
|
|
|
$allPostTypeTaxonomyTerms = get_terms( array(
|
|
'taxonomy' => $postTaxonomies,
|
|
'hide_empty' => true,
|
|
) );
|
|
|
|
$finalList = array();
|
|
|
|
foreach ($allPostTypeTaxonomyTerms as $obj) {
|
|
$taxonomyObj = get_taxonomy($obj->taxonomy);
|
|
|
|
if ( ! $taxonomyObj->show_ui ) {
|
|
continue;
|
|
}
|
|
$finalList[$taxonomyObj->label][] = (array)$obj;
|
|
}
|
|
|
|
if ( ! empty($finalList) ) {
|
|
foreach ( array_keys( $finalList ) as $taxonomyLabel ) {
|
|
usort( $finalList[ $taxonomyLabel ], static function( $a, $b ) {
|
|
return strcasecmp( $a['name'], $b['name'] );
|
|
} );
|
|
}
|
|
|
|
ksort($finalList);
|
|
}
|
|
|
|
return $finalList;
|
|
}
|
|
|
|
/**
|
|
* @param $data
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function setPageTemplate($data)
|
|
{
|
|
global $template;
|
|
|
|
$getPageTpl = get_post_meta($this->getCurrentPostId(), '_wp_page_template', true);
|
|
|
|
// Could be a custom post type with no template set
|
|
if (! $getPageTpl) {
|
|
$getPageTpl = get_page_template();
|
|
|
|
if (in_array(basename($getPageTpl), array('single.php', 'page.php'))) {
|
|
$getPageTpl = 'default';
|
|
}
|
|
}
|
|
|
|
if (! $getPageTpl) {
|
|
return $data;
|
|
}
|
|
|
|
$data['page_template'] = $getPageTpl;
|
|
|
|
$data['all_page_templates'] = wp_get_theme()->get_page_templates();
|
|
|
|
// Is the default template shown? Most of the time it is!
|
|
if ($data['page_template'] === 'default') {
|
|
$pageTpl = (isset($template) && $template) ? $template : get_page_template();
|
|
$data['page_template'] = basename( $pageTpl );
|
|
$data['all_page_templates'][ $data['page_template'] ] = 'Default Template';
|
|
}
|
|
|
|
if (isset($template) && $template && defined('ABSPATH')) {
|
|
$data['page_template_path'] = str_replace(
|
|
Misc::getWpRootDirPath(),
|
|
'',
|
|
'/'.$template
|
|
);
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public static function isWpDefaultSearchPage()
|
|
{
|
|
// It will not interfere with the WooCommerce search page
|
|
// which is considered to be the "Shop" page that has its own unload rules
|
|
return (is_search() && (! (function_exists('is_shop') && is_shop())));
|
|
}
|
|
|
|
/**
|
|
* @param $existingListJson
|
|
* @param $existingListEmpty
|
|
*
|
|
* @return array
|
|
*/
|
|
public function existingList($existingListJson, $existingListEmpty)
|
|
{
|
|
$validJson = $notEmpty = true;
|
|
|
|
if (! $existingListJson) {
|
|
$existingList = $existingListEmpty;
|
|
$notEmpty = false;
|
|
} else {
|
|
$existingList = json_decode($existingListJson, true);
|
|
|
|
if (Misc::jsonLastError() !== JSON_ERROR_NONE) {
|
|
$validJson = false;
|
|
$existingList = $existingListEmpty;
|
|
}
|
|
}
|
|
|
|
return array(
|
|
'list' => $existingList,
|
|
'valid_json' => $validJson,
|
|
'not_empty' => $notEmpty
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Situations when the assets will not be prevented from loading
|
|
* e.g. test mode and a visitor accessing the page, an AJAX request from the Dashboard to print all the assets
|
|
*
|
|
* @param array $ignoreList
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function preventAssetsSettings($ignoreList = array())
|
|
{
|
|
// This request specifically asks for all the assets to be loaded in order to print them in the assets management list
|
|
// This is for the AJAX requests within the Dashboard, thus the admin needs to see all the assets,
|
|
// including ones marked for unload, in case he/she decides to change their rules
|
|
if ($this->isGetAssetsCall && ! in_array('assets_call', $ignoreList)) {
|
|
return true;
|
|
}
|
|
|
|
// Is test mode enabled? Unload assets ONLY for the admin
|
|
if (self::isTestModeActive()) {
|
|
return true; // visitors (non-logged in) will view the pages with all the assets loaded
|
|
}
|
|
|
|
$isSingularPage = defined('WPACU_CURRENT_PAGE_ID') && WPACU_CURRENT_PAGE_ID > 0 && is_singular();
|
|
|
|
if ($isSingularPage || Misc::isHomePage()) {
|
|
if ($isSingularPage) {
|
|
$pageOptions = MetaBoxes::getPageOptions( WPACU_CURRENT_PAGE_ID ); // Singular page
|
|
} else {
|
|
$pageOptions = MetaBoxes::getPageOptions(0, 'front_page'); // Home page
|
|
}
|
|
|
|
if (isset($pageOptions['no_assets_settings']) && $pageOptions['no_assets_settings']) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param array $settings
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function isTestModeActive($settings = array())
|
|
{
|
|
if (defined('WPACU_IS_TEST_MODE_ACTIVE')) {
|
|
return WPACU_IS_TEST_MODE_ACTIVE;
|
|
}
|
|
|
|
if (! $settings) {
|
|
$settings = self::instance()->settings;
|
|
}
|
|
|
|
$wpacuIsTestModeActive = isset($settings['test_mode']) && $settings['test_mode'] && ! Menu::userCanManageAssets();
|
|
|
|
define('WPACU_IS_TEST_MODE_ACTIVE', $wpacuIsTestModeActive);
|
|
|
|
return $wpacuIsTestModeActive;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public static function currentUserCanViewAssetsList()
|
|
{
|
|
if ( Main::instance()->settings['allow_manage_assets_to'] === 'chosen' && ! empty(Main::instance()->settings['allow_manage_assets_to_list']) ) {
|
|
$wpacuCurrentUserId = get_current_user_id();
|
|
|
|
if ( ! in_array( $wpacuCurrentUserId, Main::instance()->settings['allow_manage_assets_to_list'] ) ) {
|
|
return false; // the current logged-in admin is not in the list of "Allow managing assets to:"
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function frontendShow()
|
|
{
|
|
// The option is disabled
|
|
if (! $this->settings['frontend_show']) {
|
|
return false;
|
|
}
|
|
|
|
// The asset list is hidden via query string: /?wpacu_no_frontend_show
|
|
if (isset($_REQUEST['wpacu_no_frontend_show'])) {
|
|
return false;
|
|
}
|
|
|
|
// Page loaded via Yellow Pencil Editor within an iframe? Do not show it as it's irrelevant there
|
|
if (isset($_GET['yellow_pencil_frame'], $_GET['yp_page_type'])) {
|
|
return false;
|
|
}
|
|
|
|
// The option is enabled, but there are show exceptions, check if the list should be hidden
|
|
if ($this->settings['frontend_show_exceptions']) {
|
|
$frontendShowExceptions = trim( $this->settings['frontend_show_exceptions'] );
|
|
|
|
// We want to make sure the RegEx rules will be working fine if certain characters (e.g. Thai ones) are used
|
|
$requestUriAsItIs = rawurldecode($_SERVER['REQUEST_URI']);
|
|
|
|
if ( strpos( $frontendShowExceptions, "\n" ) !== false ) {
|
|
foreach ( explode( "\n", $frontendShowExceptions ) as $frontendShowException ) {
|
|
$frontendShowException = trim($frontendShowException);
|
|
|
|
if ( strpos( $requestUriAsItIs, $frontendShowException ) !== false ) {
|
|
return false;
|
|
}
|
|
}
|
|
} elseif ( strpos( $requestUriAsItIs, $frontendShowExceptions ) !== false ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Allows managing assets to chosen admins and the user is not in the list
|
|
if ( ! self::currentUserCanViewAssetsList() ) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Make administrator more aware if "TEST MODE" is enabled or not
|
|
*/
|
|
public function wpacuHtmlNoticeForAdmin()
|
|
{
|
|
add_action('wp_footer', static function() {
|
|
if ((WPACU_GET_LOADED_ASSETS_ACTION === true) || (! apply_filters('wpacu_show_admin_console_notice', true)) || Plugin::preventAnyFrontendOptimization()) {
|
|
return;
|
|
}
|
|
|
|
if ( ! (Menu::userCanManageAssets() && ! is_admin())) {
|
|
return;
|
|
}
|
|
|
|
if (Main::instance()->settings['test_mode']) {
|
|
$consoleMessage = sprintf(esc_html__('%s: "TEST MODE" ENABLED (any settings or unloads will be visible ONLY to you, the logged-in administrator)', 'wp-asset-clean-up'), WPACU_PLUGIN_TITLE);
|
|
$testModeNotice = esc_html__('"Test Mode" is ENABLED. Any settings or unloads will be visible ONLY to you, the logged-in administrator.', 'wp-asset-clean-up');
|
|
} else {
|
|
$consoleMessage = sprintf(esc_html__('%s: "LIVE MODE" (test mode is not enabled, thus, all the plugin changes are visible for everyone: you, the logged-in administrator and the regular visitors)', 'wp-asset-clean-up'), WPACU_PLUGIN_TITLE);
|
|
$testModeNotice = esc_html__('The website is in LIVE MODE as "Test Mode" is not enabled. All the plugin changes are visible for everyone: logged-in administrators and regular visitors.', 'wp-asset-clean-up');
|
|
}
|
|
?>
|
|
<!--
|
|
<?php echo sprintf(esc_html__('NOTE: These "%s: Page Speed Booster" messages are only shown to you, the HTML comment is not visible for the regular visitor.', 'wp-asset-clean-up'), WPACU_PLUGIN_TITLE); ?>
|
|
|
|
<?php echo esc_html__($testModeNotice); ?>
|
|
-->
|
|
<script <?php echo Misc::getScriptTypeAttribute(); ?> data-wpacu-own-inline-script="true">
|
|
console.log('<?php echo esc_js($consoleMessage); ?>');
|
|
</script>
|
|
<?php
|
|
});
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public function fallbacks()
|
|
{
|
|
// Fallback for the old filters (e.g. Pro version below 1.2.0.7)
|
|
add_filter('wpacu_filter_styles_list_unload', function ($list) { return apply_filters('wpacu_filter_styles', $list); });
|
|
add_filter('wpacu_filter_scripts_list_unload', function ($list) { return apply_filters('wpacu_filter_scripts', $list); });
|
|
}
|
|
}
|