'; /** * Printed in HEAD */ const DEL_SCRIPTS_PRELOADS = ''; /** * @var array */ public $preloads = array('styles' => array(), 'scripts' => array()); /** * @var Preloads|null */ private static $singleton; /** * @return null|Preloads */ public static function instance() { if (self::$singleton === null) { self::$singleton = new self(); } return self::$singleton; } /** * Preloads constructor. */ public function __construct() { if (is_admin() || self::preventPreload()) { return; } $this->preloads = $this->getPreloads(); add_filter('wpfc_buffer_callback_filter', static function ($buffer) { $buffer = str_replace('rel=\'preload\' data-from-rel=\'stylesheet\'', 'rel=\'preload\'', $buffer); return $buffer; }); } /** * */ public function init() { if (self::preventPreload()) { return; } if (! is_admin()) { // Trigger only in the front-end add_filter('style_loader_tag', array($this, 'preloadCss'), 10, 2); add_filter('script_loader_tag', array($this, 'preloadJs'), 10, 2); } else { // Trigger only within the Dashboard if (Misc::getVar('post', 'wpacu_remove_preloaded_assets_nonce')) { add_action('admin_init', static function() { Preloads::removePreloadFromChosenAssets(); }); } // Trigger only in "Bulk Changes" -> "Preloaded CSS/JS" if (isset($_GET['page']) && $_GET['page'] === WPACU_PLUGIN_ID.'_bulk_unloads' && get_transient('wpacu_preloads_just_removed')) { add_action('wpacu_admin_notices', array($this, 'noticePreloadsRemoved')); delete_transient('wpacu_preloads_just_removed'); } } } /** * @param $htmlSource * * @return mixed */ public function doChanges($htmlSource) { if (self::preventPreload()) { return $htmlSource; } $this->preloads = $this->getPreloads(); if (isset($this->preloads['styles']) && ! empty($this->preloads['styles'])) { $htmlSource = self::appendPreloadsForStylesToHead($htmlSource); } return $htmlSource; } /** * @param string $for * @return bool */ public function enablePreloads($for) { if (self::preventPreload()) { return false; } $assetType = ($for === 'css') ? 'styles' : 'scripts'; if (! (isset($this->preloads[$assetType]) && ! empty($this->preloads[$assetType]))) { return false; } // Do not use the preloads if "Optimize CSS Delivery" is enabled in WP Rocket if ($for === 'css' && Misc::isPluginActive('wp-rocket/wp-rocket.php') && function_exists('get_rocket_option') && get_rocket_option('async_css')) { return false; } // WP Fastest Cache: Combine CSS/JS is enabled if (! Menu::userCanManageAssets() && Misc::isPluginActive('wp-fastest-cache/wpFastestCache.php')) { $wpfcOptionsJson = get_option('WpFastestCache'); $wpfcOptions = @json_decode($wpfcOptionsJson, ARRAY_A); if ($for === 'css' && isset($wpfcOptions['wpFastestCacheCombineCss'])) { return false; } if ($for === 'js' && isset($wpfcOptions['wpFastestCacheCombineJs'])) { return false; } } // W3 Total Cache if (Misc::isPluginActive('w3-total-cache/w3-total-cache.php')) { $w3tcConfigMaster = Misc::getW3tcMasterConfig(); if ($for === 'css') { $w3tcEnableCss = (int)trim(Misc::extractBetween($w3tcConfigMaster, '"minify.css.enable":', ','), '" '); if ($w3tcEnableCss === 1) { return false; } } if ($for === 'js') { $w3tcEnableJs = (int)trim(Misc::extractBetween($w3tcConfigMaster, '"minify.js.enable":', ','), '" '); if ($w3tcEnableJs === 1) { return false; } } } // LiteSpeed Cache if (Misc::isPluginActive('litespeed-cache/litespeed-cache.php') && ($liteSpeedCacheConf = apply_filters('litespeed_cache_get_options', get_option('litespeed-cache-conf')))) { if ($for === 'css' && isset($liteSpeedCacheConf['css_minify']) && $liteSpeedCacheConf['css_minify']) { return false; } if ($for === 'js' && isset($liteSpeedCacheConf['js_minify']) && $liteSpeedCacheConf['js_minify']) { return false; } } return true; } /** * @return array */ public function getPreloads() { $preloadsListJson = get_option(WPACU_PLUGIN_ID . '_global_data'); if ($preloadsListJson) { $preloadsList = @json_decode($preloadsListJson, true); // Issues with decoding the JSON file? Return an empty list if (Misc::jsonLastError() !== JSON_ERROR_NONE) { return $this->preloads; } // Are new positions set for styles and scripts? foreach (array('styles', 'scripts') as $assetKey) { if ( isset( $preloadsList[$assetKey]['preloads'] ) && ! empty( $preloadsList[$assetKey]['preloads'] ) ) { $this->preloads[$assetKey] = $preloadsList[$assetKey]['preloads']; } } } return $this->preloads; } /** * @param $htmlTag * @param $handle * * @return string */ public function preloadCss($htmlTag, $handle) { if (Plugin::preventAnyFrontendOptimization() || self::preventPreload()) { return $htmlTag; } if ($wpacuAsyncPreloadHandle = Misc::getVar('get', 'wpacu_preload_css')) { // For testing purposes: Check how the page loads with the requested CSS preloaded $this->preloads['styles'][$wpacuAsyncPreloadHandle] = 'basic'; } // Only valid for front-end pages with LINKs if (is_admin() || (! $this->enablePreloads('css')) || strpos($htmlTag,'preventAssetsSettings()) { return $htmlTag; } if (! isset($this->preloads['styles'])) { return $htmlTag; } if (array_key_exists($handle, $this->preloads['styles']) && $this->preloads['styles'][$handle]) { if (isset($_REQUEST['wpacu_no_css_preload_basic'])) { // do not apply it for debugging purposes return str_replace('preloads['scripts'][$wpacuJsPreloadHandle] = 1; } // Only valid for front-end pages with SCRIPTs if (is_admin() || (! $this->enablePreloads('js')) || strpos($htmlTag,'