wp_back/wp-content/plugins/wp-asset-clean-up/classes/OptimiseAssets/MinifyJs.php
2024-05-20 15:37:46 +03:00

269 lines
8.6 KiB
PHP

<?php
namespace WpAssetCleanUp\OptimiseAssets;
use WpAssetCleanUp\Main;
use WpAssetCleanUp\Menu;
use WpAssetCleanUp\MetaBoxes;
use WpAssetCleanUp\Misc;
/**
* Class MinifyJs
* @package WpAssetCleanUp\OptimiseAssets
*/
class MinifyJs
{
/**
* @param $jsContent
*
* @return string|string[]|null
*/
public static function applyMinification($jsContent)
{
if (class_exists('\MatthiasMullie\Minify\JS')) {
$sha1OriginalContent = sha1($jsContent);
$checkForAlreadyMinifiedShaOne = mb_strlen($jsContent) > 40000;
// Let's check if the content is already minified
// Save resources as the minify process can take time if the content is very large
// Limit the total number of entries to 100: if it's more than that, it's likely because there's dynamic JS altering on every page load
if ($checkForAlreadyMinifiedShaOne && OptimizeCommon::originalContentIsAlreadyMarkedAsMinified($sha1OriginalContent, 'scripts')) {
return $jsContent;
}
// Minify it
$alreadyMinified = false; // default
$minifier = new \MatthiasMullie\Minify\JS($jsContent);
$minifiedContent = trim($minifier->minify());
if (trim($minifiedContent) === trim(trim($jsContent, ';'))) {
$minifiedContent = $jsContent; // consider them the same if only the ';' at the end was stripped (it doesn't worth the resources that would be used)
$alreadyMinified = true;
}
// If the resulting content is the same, mark it as minified to avoid the minify process next time
if ($checkForAlreadyMinifiedShaOne && $alreadyMinified) {
// If the resulting content is the same, mark it as minified to avoid the minify process next time
OptimizeCommon::originalContentMarkAsAlreadyMinified( $sha1OriginalContent, 'scripts' );
}
return $minifiedContent;
}
return $jsContent;
}
/**
* @param $src
* @param string $handle
*
* @return bool
*/
public static function skipMinify($src, $handle = '')
{
// Things like WP Fastest Cache Toolbar JS shouldn't be minified and take up space on the server
if ($handle !== '' && in_array($handle, Main::instance()->skipAssets['scripts'])) {
return true;
}
$regExps = array(
'#/wp-content/plugins/wp-asset-clean-up(.*?).js#',
// Other libraries from the core that end in .min.js
'#/wp-includes/(.*?).min.js#',
// jQuery & jQuery Migrate
'#/wp-includes/js/jquery/jquery.js#',
'#/wp-includes/js/jquery/jquery-migrate.js#',
// Files within /wp-content/uploads/
// Files within /wp-content/uploads/ or /wp-content/cache/
// Could belong to plugins such as "Elementor, "Oxygen" etc.
//'#/wp-content/uploads/(.*?).js#',
'#/wp-content/cache/(.*?).js#',
// Already minified, and it also has a random name making the cache folder make bigger
'#/wp-content/bs-booster-cache/#',
// Elementor .min.js
'#/wp-content/plugins/elementor/assets/(.*?).min.js#',
// WooCommerce Assets
'#/wp-content/plugins/woocommerce/assets/js/(.*?).min.js#',
// Google Site Kit
// The files are already optimized (they just have comments once in a while)
// Minifying them causes some errors, so better to leave them load as they are
'#/wp-content/plugins/google-site-kit/#',
// TranslatePress Multilingual
'#/translatepress-multilingual/assets/js/trp-editor.js#',
);
$regExps = Misc::replaceRelPluginPath($regExps);
if (Main::instance()->settings['minify_loaded_js_exceptions'] !== '') {
$loadedJsExceptionsPatterns = trim(Main::instance()->settings['minify_loaded_js_exceptions']);
if (strpos($loadedJsExceptionsPatterns, "\n")) {
// Multiple values (one per line)
foreach (explode("\n", $loadedJsExceptionsPatterns) as $loadedJsExceptionPattern) {
$regExps[] = '#'.trim($loadedJsExceptionPattern).'#';
}
} else {
// Only one value?
$regExps[] = '#'.trim($loadedJsExceptionsPatterns).'#';
}
}
foreach ($regExps as $regExp) {
if ( preg_match( $regExp, $src ) || ( strpos($src, $regExp) !== false ) ) {
return true;
}
}
return false;
}
/**
* @param $htmlSource
*
* @return mixed|string
*/
public static function minifyInlineScriptTags($htmlSource)
{
if (stripos($htmlSource, '<script') === false) {
return $htmlSource; // no SCRIPT tags, hmm
}
$skipTagsContaining = array_map( static function ( $toMatch ) {
return preg_quote($toMatch, '/');
}, array(
'data-wpacu-skip',
'/* <![CDATA[ */', // added via wp_localize_script()
'wpacu-google-fonts-async-load',
'wpacu-preload-async-css-fallback',
/* [wpacu_pro] */'data-wpacu-inline-js-file',/* [/wpacu_pro] */
'document.body.prepend(wpacuLinkTag',
'var wc_product_block_data = JSON.parse( decodeURIComponent(',
'/(^|\s)(no-)?customize-support(?=\s|$)/', // WP Core
'b[c] += ( window.postMessage && request ? \' \' : \' no-\' ) + cs;', // WP Core
'data-wpacu-own-inline-script', // Only shown to the admin, irrelevant for any optimization (save resources)
// [wpacu_pro]
'data-wpacu-inline-js-file', // already minified/optimized since the INLINE was generated from the cached file
// [/wpacu_pro]
));
// Do not perform another \DOMDocument call if it was done already somewhere else (e.g. CombineJs)
$fetchType = 'regex'; // 'regex' or 'dom'
if ($fetchType === 'regex') {
preg_match_all( '@(<script[^>]*?>).*?</script>@si', $htmlSource, $matchesScriptTags, PREG_SET_ORDER );
if ( $matchesScriptTags === null ) {
return $htmlSource;
}
foreach ($matchesScriptTags as $matchedScript) {
if (isset($matchedScript[0]) && $matchedScript[0]) {
$originalTag = $matchedScript[0];
if (strpos($originalTag, 'src=') && strtolower(substr($originalTag, -strlen('></script>'))) === strtolower('></script>')) {
// Only inline SCRIPT tags allowed
continue;
}
// No need to use extra resources as the tag is already minified
if ( preg_match( '/(' . implode( '|', $skipTagsContaining ) . ')/', $originalTag ) ) {
continue;
}
// Only 'text/javascript' type is allowed for minification
$scriptType = Misc::getValueFromTag($originalTag, 'type') ?: 'text/javascript'; // default
if ($scriptType !== 'text/javascript') {
continue;
}
$tagOpen = $matchedScript[1];
$withTagOpenStripped = substr($originalTag, strlen($tagOpen));
$originalTagContents = substr($withTagOpenStripped, 0, -strlen('</script>'));
$newTagContents = OptimizeJs::maybeAlterContentForInlineScriptTag( $originalTagContents, true );
if ( $newTagContents !== $originalTagContents ) {
$htmlSource = str_ireplace( '>' . $originalTagContents . '</script', '>' . $newTagContents . '</script', $htmlSource );
}
}
}
}
return $htmlSource;
}
/**
* @return bool
*/
public static function isMinifyJsEnabled()
{
if (defined('WPACU_IS_MINIFY_JS_ENABLED')) {
return WPACU_IS_MINIFY_JS_ENABLED;
}
// Request Minify On The Fly
// It will preview the page with JS minified
// Only if the admin is logged-in as it uses more resources (CPU / Memory)
if ( isset($_GET['wpacu_js_minify']) && Menu::userCanManageAssets()) {
self::isMinifyJsEnabledChecked('true');
return true;
}
if ( isset($_REQUEST['wpacu_no_js_minify']) || // not on query string request (debugging purposes)
is_admin() || // not for Dashboard view
(! Main::instance()->settings['minify_loaded_js']) || // Minify JS has to be Enabled
(Main::instance()->settings['test_mode'] && ! Menu::userCanManageAssets()) ) { // Does not trigger if "Test Mode" is Enabled
self::isMinifyJsEnabledChecked('false');
return false;
}
$isSingularPage = defined('WPACU_CURRENT_PAGE_ID') && WPACU_CURRENT_PAGE_ID > 0 && is_singular();
if ($isSingularPage || Misc::isHomePage()) {
// If "Do not minify JS on this page" is checked in "Asset CleanUp: Options" side meta box
if ($isSingularPage) {
$pageOptions = MetaBoxes::getPageOptions( WPACU_CURRENT_PAGE_ID ); // Singular page
} else {
$pageOptions = MetaBoxes::getPageOptions(0, 'front_page'); // Home page
}
if ( isset( $pageOptions['no_js_minify'] ) && $pageOptions['no_js_minify'] ) {
self::isMinifyJsEnabledChecked('false');
return false;
}
}
if (OptimizeJs::isOptimizeJsEnabledByOtherParty('if_enabled')) {
self::isMinifyJsEnabledChecked('false');
return false;
}
self::isMinifyJsEnabledChecked('true');
return true;
}
/**
* @param $value
*/
public static function isMinifyJsEnabledChecked($value)
{
if (! defined('WPACU_IS_MINIFY_JS_ENABLED')) {
if ($value === 'true') {
define( 'WPACU_IS_MINIFY_JS_ENABLED', true );
} elseif ($value === 'false') {
define( 'WPACU_IS_MINIFY_JS_ENABLED', false );
}
}
}
}