File: /var/www/html/shootinschool/wp-content/plugins/sg-cachepress/core/Combinator/Js_Combinator.php
<?php
namespace SiteGround_Optimizer\Combinator;
use SiteGround_Optimizer\Options\Options;
use SiteGround_Optimizer\Front_End_Optimization\Front_End_Optimization;
use SiteGround_Helper\Helper_Service;
use SiteGround_Optimizer\Helper\Helper;
/**
* SG JS_Combinator main plugin class
*/
class Js_Combinator extends Abstract_Combinator {
/**
* Array containing all excluded inline content.
*
* @since 5.5.0
*
* @var array Array containing all excluded inline content.
*/
private $excluded_inline_content = array(
'CDATA',
'window.bookly',
'var _iub',
'#fld_',
'.shop-filter',
'var markersData',
'setREVStartSize',
'countUp',
'a2a_config',
'spg_current_url',
'ctSetCookie',
'stm_ajax_add_review',
'stm_lms',
'ywapo_textarea_',
'var disqus_config',
'map.write("map_id',
'wpfh-print-action',
'tdbMenuItem',
'avadaFusionSliderVars',
'tgpli',
'tgpQueue',
'gem_fix_fullwidth_position',
'window.opener.location.href="',
'var __CONFIG__',
'var DTGS_NONCE_FRONTEND',
'revslider_ajax_call_front',
'#wpb_wcma_menu_',
'UNCODE.initRow',
'$(\'head\').append(\'<style',
'$("head").append("<style',
'#dfd-isotope-container-',
'#dfd-horizontal-scroll-',
'var form_container =',
'var container = document.querySelectorAll( \'[data-view-breakpoint-pointer="',
'var et_animation_data =',
'_ASP.initialize',
'theChampSiteUrl',
'var _beeketing =',
'glami(\'track',
'pysWooSelectContentData',
'init_scroll_shortcode',
'_leartsInlineStyle',
'div[rel=tipsy]\')',
'g5core-social-networks',
'woocs_array_of_get',
'woocs_current_currency',
'DokanWholesale',
'woocommerce_price_slider_params',
'amzn_assoc_ad_type',
'var logview',
'wc-livechat-script',
'window.SIDX',
'$(\'.room-check-form',
'var css = \'#lordcros',
'currentQuestion = {',
'et_core_api_spam_recaptcha',
'var __eae_open',
'var WIL_SINGLE_LISTING',
'tcb_post_lists',
'DSListTracData',
'tribe_js_config',
'var tracking_id =',
'var side_feed',
'tdbSearchItem.blockUid = \'t',
'_initLayerSlider',
'var quickViewNonce',
'getElementById("eeb-',
'function reenableButton',
'bs_ajax_paginate_',
'subscribe-field',
'_paq',
'NSLPopupCenter',
'fwduvpMainPlaylist',
'fts_security',
'post_id',
'theChampLJAuthUrl',
'ulp_content_id',
'#iphorm-',
'clicky_site_ids',
'hc_rand_id',
'mdf_current_page_url',
'syntaxhighlighter',
'Bibblio.initRelatedContent',
'idcomments_acct',
'ch_client',
'"+nRemaining+"',
'_mmunch',
'woopack_config',
'currency_data=',
'contextly',
'adthrive',
'_atrk_opts',
'wcct_info',
'oneall_social_login_providers_',
'var categories_',
'gt_request_uri',
'showUFC()',
'wphc_data',
'nonce',
'galleries.gallery_',
'Springbot.product_id',
'w2dc_js_objects',
'document.write',
'_gaLt',
'wcj_evt.prodID',
'loadCSS',
'edToolbar',
'WP_Statistics_http',
'cherry_ajax',
'alsp_map_markers_attrs',
'owl=$("#',
'hbspt.forms.create',
'lazyLoadOptions',
'theChampRegRedirectionUrl',
'elementid',
'GoogleAnalyticsObject',
'sc_online_t',
'ult-carousel-',
'jetpack_remote_comment',
'betterads_screen_width',
'WPCOM_sharing_counts',
'RecaptchaLoad',
'theChampTwitterRedirect',
'omapi_localized',
'rankMath = {',
'wpp_params',
'bs_deferred_loading_',
'clicky_custom',
'after_share_easyoptin',
'RBL_ADD',
'wpRestNonce',
'#svc_carousel2_container_',
'advads.move',
'#fancy-',
'pysWooProductData',
'bannersnack_embed',
'yithautocomplete',
'function svc_center_',
'zeen_',
'_stq',
'nfForms',
'woof_really_curr_tax',
'atatags-',
'dfd-heading',
'google_tag_params',
'setAttribute( "id"',
'Insticator',
'penci_block_',
'theChampFBCommentUrl',
'arf_conditional_logic',
'iworks_upprev',
'ci_cap_',
'"url":',
'yith_wcevti_tickets',
'omapi_data',
'ANS_customer_id',
'data-parallax-speed',
'advadsGATracking.postContext',
'_thriveCurrentPost',
'adsbygoogle',
'window.metrilo.ensure_cbuid',
'theChampRedirectionUrl',
'tabs.easyResponsiveTabs',
'woocommerce_wishlist_add_to_wishlist_url',
'gtag',
'tdLocalCache',
'esc_login_url',
'styles: \' #custom-menu-',
'thirstyFunctions.isThirstyLink',
'penci_megamenu',
'PHP.wp_p_id',
'currentAjaxUrl',
'avia_framework_globals',
'function(c,h,i,m,p)',
'geodir_event_call_calendar_',
'searchwp_live_search_params',
'quicklinkOptions',
'heateorSsHorSharingShortUrl',
'orig_request_uri',
'uLogin.customInit',
'algoliaAutocomplete',
'ven_video_key',
'doGTranslate',
'LogHuman',
'advads_has_ads',
'dataLayer',
'selection+pagelink',
'bimber_front_microshare',
'e.Newsletter2GoTrackingObject',
'ESSB_CACHE_URL',
'top.location,thispage',
'dataTable({',
'setAttribute("id"',
'ct_checkjs_',
'ic_window_resolution',
'wpseo_map_init',
'AfsAnalyticsObject',
'wordpress_page_root',
'ctSetCookie(\'ct_checkjs\'',
'_stq',
'wp-cumulus/tagcloud.swf?r=',
'TribeEventsPro',
'#wpnbio-show',
'vtn_player_type',
'tminusnow',
'docTitle',
'f._fbq',
'TL_Const',
'searchlocationHeader',
'google_ad',
'elementorFrontendConfig',
'cedexisData',
'i18n_no_matching_variations_text',
'ShopifyBuy.UI.onReady(client)',
'advads_tracking_ads',
'metrilo.event',
'location_data.push',
'disqusIdentifier',
'tdBlock',
'_gaq.push',
'gtm',
'cartsguru_cart_token',
'var inc_opt =',
'ad_block_',
'peepsotimedata',
'e.setAttribute(\'unselectable',
'function auxinNS(n)',
'script_memory_usage',
'var jetReviewsWidget',
'var wpa_hidden_field',
'snaptr',
'function awbMapInit',
'loginform .user-pass-wrap\').attr(\'id\', \'lable_password_input', //Admin Custom Login Plugin.
'wcBlocksMiddlewareConfig' // exclude nonce generator var, script handle - wc-blocks-middleware
);
/**
* Excluded paths.
*
* @since 5.5.0
*
* @var array Array containing all paths that should be excluded.
*/
private $excluded_paths = array(
'scripts.sirv.com',
'cdn.ampproject.org',
'app.getresponse.com',
'googleadservices.com',
'a.optmnstr.com',
'adthrive.com',
'www.uplaunch.com',
'widget-prime.rafflecopter.com',
'gist.github.com',
'html5.js',
'video.unrulymedia.com',
'forms.aweber.com',
'scripts.chitika.net/',
'apps.shareaholic.com',
'mailmunch.co',
'stats.wp.com',
'c.ad6media.fr',
'code.tidio.co',
's0.wp.com',
'a.optmstr.com',
'histats.com/js',
'recaptcha/api.js',
'mediavine.com',
'nutrifox.com',
'show_ads.js',
'stats.wordpress.com',
'contextual.media.net',
'googlesyndication.com',
'imagesrv.adition.com',
'releases.flowplayer.org',
'ws.amazon.com/widgets',
'www.smava.de',
's.gravatar.com',
'verify.authorize.net',
'/ads/',
'files.bannersnack.com',
'cdn.stickyadstv.com',
'dsms0mj1bbhn4.cloudfront.net',
'js.juicyads.com',
'app.ecwid.com',
'smarticon.geotrust.com',
'jotform.com/',
'embed.finanzcheck.de',
'www.industriejobs.de',
'js.hsforms.net',
'form.jotformeu.com',
'speakerdeck.com',
'widget.rafflecopter.com',
'amazon-adsystem.com',
'ads.themoneytizer.com',
'ads.investingchannel.com',
'web.ventunotech.com',
'intensedebate.com',
'widget.reviewability.com',
'js.gleam.io',
'wprp.zemanta.com',
'content.jwplatform.com',
'adserver.reklamstore.com',
'f.convertkit.com',
);
/**
* Move after the combined script.
*
* @since 5.5.0
*
* @var array $move_after Inline JS patterns to move after the combined JS file
*/
private $move_after_excludes = array(
'#product-search-field-',
'wpseo-address-wrapper',
'ec:addProduct',
'gform_ajax_frame_',
'#owl-carousel-instagram-',
'et_animation_data=',
'window.FlowFlowOpts',
'wlt_pop_distance_',
'data.token',
'it_logo_field_owl-box_',
'#views-extra-css").text',
'.flo-block-slideshow-',
'jQuery(\'.td_uid_',
'wmp_update',
'wlt_star_',
'cb_nombre',
'test_run_nf_conditional_logic',
'a3revWCDynamicGallery_',
'smart_list_tip',
'woof_is_mobile',
'_wca',
'gd-wgt-pagi-',
'sinceID_',
'dfads_ajax_load_ads',
'data-rf-id=',
'ip_common_function()',
'h5ab-print-article',
'.woocommerce-tabs-',
'vc_prepareHoverBox',
'callback:window.renderBadge',
'vc-row-destroy-equal-heights-',
'wpt_view_count',
'electro-wc-product-gallery',
'startclock',
'dfd-icon-list-',
'user_rating.prototype.eraseCookie',
'var dateNow',
'platform.stumbleupon.com',
'berocket_aapf_time_to_fix_products_style',
'$("#myCarousel',
'fbq(\'trackCustom\'',
'fusetag.setTargeting',
'dfd-button-hover-in',
'_wswebinarsystem_already_',
'pa_woo_product_info',
'ec:addImpression',
'dpsp-networks-btns-wrapper',
'gform_post_render',
'mec_skin_',
'WLTChangeState',
'hit.uptrendsdata.com',
'window.SLB',
'#ut-background-video-ut-section',
'gallery_product_',
'GOTMLS_login_offset',
'+window.comment_tab_width+',
'td_live_css_uid',
'#dfd-vcard-widget-',
'jQuery(\'.videonextup',
'CustomEvent.prototype=window.Event.prototype',
'wpvl_paramReplace',
'clear_better_facebook_comments',
'act_css_tooltip',
'sharrre',
'window.vc_googleMapsPointer',
'sharing_enabled_on_post_via_metabox',
'mts_view_count',
'tdAjaxCount',
'data=\'api-key=ct-',
'fbq(\'track\'',
'penci_megamenu__',
'jQuery(".slider-',
'#sf-instagram-widget-',
'us.templateDirectoryUri=',
'function($){google_maps_',
'("style#gsf-custom-css").append',
'tvc_po=',
'tie_postviews',
'SFM_template',
'test_run_nf_conditional',
'scrapeazon',
'current_url="',
'.fat-gallery-item',
'$(\'.fl-node-',
'wp-temp-form-div',
'map_fusion_map_',
'wpp_params',
'_taboola',
'.ratingbox',
'wp.apiFetch.nonceMiddleware',
'initMap',
);
/**
* Regex parts.
*
* @since 5.5.0
*
* @var array Javascript tags regular expression
*/
public $regex_parts = array(
'~', // The php quotes.
'<script\b', // Opening script tag.
'([^>]*)', // Tag attributes.
'>', // Closing script tag.
'(?:\/\*\s*<!\[CDATA\[\s*\*\/)?\s*', // Match CDATA.
'([\s\S]*?)', // The script content, if any.
'\s*(?:\/\*\s*\]\]>\s*\*\/)?', // Anything else until closing tag.
'<\/script>', // Closing script tag.
'~', // The php quotes.
'ims', // The flags.
);
/**
* Src attribute regex parts.
*
* @since 5.5.0
*
* @var array Javascript src attributes regular expression.
*/
public $src_regex_parts = array(
'~',
'<script\s+',
'([^>]+[\s\'"])?',
'src\s*=\s*[\'"]\s*?',
'([^\'"]+\.js(?:[^\'"]*)?)\s*?',
'[\'"]',
'([^>]+)?',
'\/?>',
'~',
'Umsi',
);
/**
* Inline javascript regex parts.
*
* @since 5.5.0
*
* @var array Inline javascript regular expression.
*/
public $inline_regex_parts = array(
'~',
'<script\b',
'(?<attrs>[^>]*)>',
'(?:\/\*\s*<!\[CDATA\[\s*\*\/)?',
'\s*(?<content>[\s\S]*?)\s*',
'(?:\/\*\s*\]\]>\s*\*\/)?',
'<\/script>',
'~',
'msi',
);
/**
* Array containing all scripts handles that should be excluded.
*
* @since 5.5.0
*
* @var array Array containing all scripts handles that should be excluded.
*/
private $combined_scripts_exclude_handles = array(
'jquery',
'jquery-core',
'wc-authorize-net-cim',
'sv-wc-payment-gateway-payment-form',
'elementor-menus-frontend',
'uncode-app',
'uncode-plugins',
'uncode-init',
'lodash',
'wp-api-fetch',
'wp-i18n',
'wp-polyfill',
'wp-url',
'wp-hooks',
'wc-square',
);
/**
* Array containing all script ids that should be excluded.
*
* @since 7.7.0
*
* @var array Array containing all script ids that should be excluded.
*/
public $excluded_ids = array(
'@wordpress/block-library/navigation-js-module',
);
/**
* Array containing all script handle regex' that should be excluded.
*
* @since 7.1.0
*
* @var array Array containing all script handle regex' that should be excluded.
*/
private $combined_scripts_exclude_regex = array(
'sv-wc-payment-gateway-payment-form-', // Authorize.NET payment gateway payment form script.
);
/**
* The singleton instance.
*
* @since 5.5.2
*
* @var The singleton instance.
*/
private static $instance;
/**
* The constructor.
*
* @since 5.5.2
*/
public function __construct() {
parent::__construct();
self::$instance = $this;
}
/**
* Get the singleton instance.
*
* @since 5.5.2
*
* @return The singleton instance.
*/
public static function get_instance() {
if ( null == self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Combine scripts included in header and footer
*
* @since 5.5.0
*
* @param string $html The page html.
*
* @return string Modified html with combined scripts tag.
*/
public function run( $html ) {
// Prepaare the localized scripts.
$this->prepare_localized_scripts();
// Prepaare the localized scripts.
$this->prepare_excluded_scripts();
// Hide comments from html.
$html_without_comments = $this->hide_comments( $html );
// Get scripts from the html.
$scripts = $this->get_items( $html_without_comments );
// Bail if there are no scripts to combine.
if ( empty( $scripts ) ) {
return $html;
}
// Get scripts content.
$content = $this->parse( $scripts );
// Bail if the scripts content is empty.
if ( empty( $content ) ) {
return $html;
}
return $this->get_new_html( $html, $content );
}
/**
* Prepare localized scripts.
*
* @since 5.5.0
*/
public function prepare_localized_scripts() {
// Get all scripts.
global $wp_scripts;
$scripts = array();
// Loop through all scripts in the queue and get all extra scripts.
foreach ( array_unique( $wp_scripts->queue ) as $item ) {
$scripts[] = wp_scripts()->print_extra_script( $item, false );
}
// Remove the empty items and set the localized scripts.
$this->localized_scripts = array_filter( $scripts );
}
/**
* Prepare the excluded scripts
*
* @since 5.5.0
*/
public function prepare_excluded_scripts() {
global $wp_scripts;
// Get the excluded scripts list.
$excluded_handles = apply_filters(
'sgo_javascript_combine_exclude',
array_merge(
$this->combined_scripts_exclude_handles,
get_option( 'siteground_optimizer_combine_javascript_exclude', array() )
)
);
// Get handles of all registered scripts.
$registered = array_keys( $wp_scripts->registered );
$excluded = array();
// Remove excluded script handles using regex.
foreach ( $this->combined_scripts_exclude_regex as $regex ) {
$excluded_handles = array_merge( $excluded_handles, Helper::get_script_handle_regex( $regex, $registered ) );
}
// Loop through all excluded handles and get their src.
foreach ( $excluded_handles as $handle ) {
// Bail if handle is now found.
if ( ! in_array( $handle, $registered ) ) {
continue;
}
// Replace the site url and get the src.
$excluded[] = trim( str_replace( Helper_Service::get_site_url(), '', strtok( wp_scripts()->registered[ $handle ]->src, '?' ) ), '/\\' );
}
// Set the excluded urls.
$this->excluded_urls = $excluded;
}
/**
* Get combined js tag.
*
* @since 5.5.0
*
* @param string $html The original page content.
* @param string $scripts_data Script data.
*
* @return string Modified html.
*/
public function get_new_html( $html, $scripts_data ) {
$move_after = '';
// Build move after content and remove the original scripts.
if ( ! empty( $this->move_after ) ) {
foreach ( $this->move_after as $script ) {
$move_after .= $script;
$html = str_replace( $script, '', $html );
}
}
// Remove script tags.
foreach ( $scripts_data as $script => $content ) {
$html = str_replace( $script, '', $html );
$new_content[] = $content;
}
$tag_data = $this->create_temp_file_and_get_url( $new_content, 'combined-js', 'js' );
// Add defer attribute to combined script if the javascript async loaded is enabled.
$atts = Options::is_enabled( 'siteground_optimizer_optimize_javascript_async' ) ? 'defer' : '';
// Add combined script tag.
// phpcs:ignore
return str_replace( '</body>', '<script ' . $atts . ' src="' . $tag_data['url'] . '"></script>' . $move_after . '</body>', $html );
}
/**
* Parse ans prepare scripts for combination.
*
* @since 5.5.0
*
* @param array $scripts Array of scripts data.
*
* @return array Array of scripts content.
*/
public function parse( $scripts ) {
foreach ( $scripts as $script ) {
// Try to get the source of the script.
preg_match(
/**
Build the regular expression.
~<script\s+([^>]+[\s\'"])?src\s*=\s*[\'"]\s*?([^\'"]+\.js(?:\?[^\'"]*)?)\s*?[\'"]([^>]+)?\/?>~Umsi
*/
implode( '', $this->src_regex_parts ),
$script[0], // The script tag.
$matches // The matches.
);
// If the script tag exists, retrieve the script id, check if it should be excluded, if so - continue with the next script.
if ( isset( $script[0] ) ) {
preg_match( '/id="([^"]+)"/', $script[0], $match_id );
if ( ! empty( $match_id ) ) {
$script_id = $match_id[1];
$excluded_ids = apply_filters( 'sgo_javascript_combine_exclude_ids', $this->excluded_ids );
if ( in_array( $script_id, $excluded_ids ) ) {
continue;
}
}
}
if ( isset( $matches[2] ) ) {
$content[ $script[0] ] = $this->process_script( $matches[2] );
} else {
$content[ $script[0] ] = $this->try_to_process_inline_script( $script[0] );
}
}
return array_filter( $content );
}
/**
* Process script.
*
* @since 5.5.0
*
* @param string $src Script source attribute.
*
* @return string Script content.
*/
public function process_script( $src ) {
$is_external = false;
if (
@strpos( Helper_Service::get_home_url(), parse_url( $src, PHP_URL_HOST ) ) === false &&
! @strpos( $src, 'wp-includes' )
) {
$is_external = true;
}
if ( $this->is_excluded( $src, $is_external ) ) {
return;
}
return true === $is_external ? $this->get_external_file_content( $src, 'js', 'externals' ) : $this->get_content( $src );
}
/**
* Check if the script is inline and process it.
*
* @since 5.5.0
*
* @param string $script The script tag.
*
* @return string Script content.
*/
public function try_to_process_inline_script( $script ) {
// Check if all inline scripts are excluded from combination via filter.
if ( true === apply_filters( 'sgo_javascript_combine_exclude_all_inline', false ) ) {
return;
}
// Check if all inline module scripts are excluded from combination via filter.
if (
preg_match( '~script type=["\']module["\']~', $script ) &&
true === apply_filters( 'sgo_javascript_combine_exclude_all_inline_modules', false )
) {
return;
}
preg_match(
/**
Build the regular expression.
~<script\b(?<attrs>[^>]*)>(?:\/\*\s*<!\[CDATA\[\s*\*\/)?\s*(?<content>[\s\S]*?)\s*(?:\/\*\s*\]\]>\s*\*\/)?<\/script>~msi
*/
implode( '', $this->inline_regex_parts ),
$script, // The script tag.
$matches // The matches.
);
if ( $this->is_excluded_inline_content( $matches ) ) {
return;
}
return $matches['content'];
}
/**
* Check if the inline content is excluded.
*
* @since 5.5.0
*
* @param array $data Script data.
*
* @return boolean True of the script is excluded, false otherwise.
*/
public function is_excluded_inline_content( $data ) {
// Check for catastrophic backtracking.
// More info: https://www.regular-expressions.info/catastrophic.html
if ( PREG_BACKTRACK_LIMIT_ERROR == preg_last_error() ) {
return true;
}
// Bail if the script doesn't a src attribute.
if ( false !== @strpos( $data['attrs'], 'src=' ) ) {
return true;
}
// Bail if the type is not js/es.
if (
@strpos( $data['attrs'], 'type' ) !== false &&
! preg_match( '/type\s*=\s*["\']?(?:text|application)\/(?:(?:x\-)?javascript|ecmascript)["\']?/i', $data['attrs'] )
) {
return true;
}
// Bail if it's localized script.
if ( in_array( $data['content'], $this->localized_scripts, true ) ) {
return true;
}
// Get excluded inline content.
$excluded_inline_content = apply_filters( 'sgo_javascript_combine_excluded_inline_content', $this->excluded_inline_content );
// Do not combine excluded content.
foreach ( $excluded_inline_content as $excluded_content ) {
if ( false !== @strpos( $data['content'], $excluded_content ) ) {
return true;
}
}
// Get excluded inline content.
$move_after_scripts = apply_filters( 'sgo_javascript_combine_exclude_move_after', $this->move_after_excludes );
foreach ( $move_after_scripts as $move_after_script ) {
if ( false !== @strpos( $data['content'], $move_after_script ) ) {
$this->move_after[] = $data[0];
return true;
}
}
return false;
}
/**
* Check if the script is excluded
*
* @since 5.5.0
*
* @param string $src Script source.
* @param boolean $external Whether the script is external.
*
* @return boolean True if the script is excluded, false otherwise.
*/
public function is_excluded( $src, $external = false ) {
// Check if the script is external.
if ( true === $external ) {
$excluded_paths = apply_filters( 'sgo_javascript_combine_excluded_external_paths', $this->excluded_paths );
foreach ( $excluded_paths as $path ) {
if ( false !== @strpos( $src, $path ) ) {
return true;
}
}
} else {
$src = Front_End_Optimization::remove_query_strings( $src );
if ( in_array( str_replace( trailingslashit( Helper_Service::get_site_url() ), '', $src ), $this->excluded_urls ) ) {
return true;
}
return false;
}
}
/**
* Replace all url to full urls.
*
* @since 5.5.0
*
* @param string $contents Array with link to scripts and script content.
*
* @return string Imploded content.
*/
public function get_content_with_replacements( $contents ) {
$new_content = array();
foreach ( $contents as $url => $content ) {
$new_content[] = preg_replace(
'~^(\/\/|\/\*)(#|@)\s(sourceURL|sourceMappingURL)=(.*)(\*\/)?$~m',
'',
$content
);
}
return implode( ";\n", $new_content );
}
}