Version Description
- Once a page is updated, the plugin preloads that page for both the admin and the guest visitor, making sure any new changes would take effect, saving the admin's time and making sure any first visitor coming to that page will access it faster (not having to wait for the caching to re-built)
- If the attribute "data-wpacu-skip" is applied to any CSS/JS, then no alteration (e.g. no minify and no addition to any combine list) will be applied to that file (apart from the actual unload or attributes such as async/defer)
- 'Remove All "generator" meta tags?' improvement: Higher accuracy in stripping META tag generators if the option is enabled in case some of their attributes have no quotes around them (rare cases)
- If 'Remove "REST API" link tag?' is enabled, the /wp-json/ reference is also removed from the "Response headers" when accessing the page via remove_action()
- Compatibility with extra page builders: "X" & "PRO" themes (Theme.co), "WP Page Builder" & "Page Builder: Live Composer" plugins: whenever their editor is ON, no unloads or any other changes to the HTML source (including minification) are performed to make sure the editor is loading its files and works smoothly
- Compatibility with "Redis Object Cache" plugin: The global variable $wp_object_cache from the WordPress core is no longer used and it's replaced with a custom solution
- Compatibility with "404page your smart custom 404 error page" plugin and similar plugins that are making pages as 404 customizable ones
- For debugging purposes, the admin can use /?wpacu_no_cache to view how the website would load without the CSS/JS cache applied (the files will still be referenced from the caching directory but they will be dynamically generated instead)
- Sometimes, large inline STYLE/SCRIPT tags' content has to be minified; if it's between 40KB and 500 KB it will be cached; any tags' content over 500KB will not be minified as it would use too many resources; it's advisable to put very large tag content into a .js external file as it would affect the TTFB (time to the first byte) when the page is loaded
- Any inline CSS/JS associated with a handle (generated via wp_add_inline_style() and wp_add_inline_script() respectively) are automatically added to the combined file
- Combined CSS/JS files are all stored in /wp-content/cache/asset-cleanup/("css" or "js")/ to avoid duplicated files that used to be stored in "logged-in" directory which is no longer created; This reduces the total disk space especially when the same CSS/JS is created (sometimes these files are quite large) for both guests & logged-in users
- If "Combine loaded CSS (Stylesheets) into fewer files" is enabled, the LINK tags that are preloaded (at least two of them) will also be combined, thus reducing the number of HTTP requests
- The method loadHTML() from DOMDocument is processing tags faster as the initial HTML source passed to it as a parameter goes through several filters, making it much smaller which makes a different in page speed when it comes to large HTML sources
- Prevent certain DOMDocument calls (which can be slow on large HTML documents) when they are not necessary (e.g. when preloading CSS stylesheets and the RegEx which is faster can do the same task with the same accuracy)
- Strip LINK tags that are pointing to empty content (including any inline code associated with the enqueued style added via wp_add_inline_style() function) if "CSS Files Minification" is enabled, making sure any empty tags are also stripped when "Inline CSS Files" is enabled, this saving HTTP requests and having less DOM elements
- In some cases, the PHP function strtr() has proven to be faster than str_replace() to make replacements, thus it has been applied to some methods that are dealing with the alteration of the HTML source
- Notify the admin that unloading 'jquery-migrate' won't unload it's "child" as well, 'jquery' (as it's a special case)
- Fix: In rare cases, URLs to the assets are starting with ../ (it's not the best practice as this would only work depending on the page's URL structure); Make sure the file's size is calculated correctly and the right URL for the file is checked in the background to determine if it returns a 200 OK response or not
- Fix: Store the assets info (which are shown only within the Dashboard for reference purposes) with the relative location (UR) to the asset, in case the data is later imported from a Staging to Live environment, it won't show any Staging URLs on the Live website on pages such as "Overview", thus avoiding any confusion the admin might have
- Fix: Make sure the time dequeueing CSS/JS is calculated correctly
- Fix: If "Asynchronous via Web Font Loader (webfont.js)" was chosen for "Combine Multiple Requests Into Fewer Ones", the font weights weren't added to the final generated SCRIPT tag
- Fix: Make sure when the handle information is saved, there are no PHP notice errors if the 'src' index is missing as some handles do not have an "src"
Download this release
Release Info
Developer | gabelivan |
Plugin | Asset CleanUp: Page Speed Booster |
Version | 1.3.6.2 |
Comparing to | |
See all releases |
Code changes from version 1.3.6.1 to 1.3.6.2
- assets/script.min.js +1 -1
- classes/CleanUp.php +108 -77
- classes/Debug.php +9 -11
- classes/HardcodedAssets.php +17 -18
- classes/ImportExport.php +1 -1
- classes/Main.php +39 -44
- classes/Misc.php +57 -35
- classes/ObjectCache.php +750 -0
- classes/OptimiseAssets/CombineCss.php +181 -47
- classes/OptimiseAssets/CombineCssImports.php +0 -2
- classes/OptimiseAssets/CombineJs.php +256 -63
- classes/OptimiseAssets/FontsGoogle.php +21 -8
- classes/OptimiseAssets/FontsGoogleRemove.php +22 -7
- classes/OptimiseAssets/MinifyCss.php +126 -38
- classes/OptimiseAssets/MinifyJs.php +147 -1
- classes/OptimiseAssets/OptimizeCommon.php +223 -60
- classes/OptimiseAssets/OptimizeCss.php +250 -77
- classes/OptimiseAssets/OptimizeJs.php +230 -156
- classes/OwnAssets.php +45 -42
- classes/Plugin.php +25 -15
- classes/Preloads.php +38 -14
- classes/Settings.php +2 -13
- classes/Update.php +75 -3
- early-triggers.php +63 -14
- readme.txt +27 -2
- templates/_admin-page-settings-plugin-areas/_optimize-css.php +4 -14
- templates/_admin-page-settings-plugin-areas/_optimize-js.php +8 -15
- templates/_admin-page-settings-plugin-areas/_plugin-usage-settings.php +1 -16
- templates/meta-box-loaded-assets/_asset-script-single-row/_handle.php +35 -17
- templates/meta-box-loaded-assets/_hardcoded/_asset-script-single-row-hardcoded/_source.php +14 -1
- templates/meta-box-loaded-assets/_hardcoded/_asset-style-single-row-hardcoded/_source.php +13 -1
- templates/meta-box-loaded.php +7 -0
- wpacu-load.php +3 -4
- wpacu.php +2 -2
assets/script.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
function wpacuTabOpenSettingsArea(a,b){a.preventDefault();var c,d,e;for(d=document.getElementsByClassName("wpacu-settings-tab-content"),c=0;c<d.length;c++)d[c].style.display="none";for(e=document.getElementsByClassName("wpacu-settings-tab-link"),c=0;c<e.length;c++)e[c].className=e[c].className.replace(" active","");document.getElementById(b).style.display="table-cell",jQuery('a[href="#'+b+'"]').addClass("active"),jQuery("#wpacu-selected-tab-area").val(b)}function wpacuBytesToSize(a){return 0===a?"N/A":(a/1024).toFixed(4)+" KB"}function wpacuAjaxClearCache(){jQuery.post(wpacu_object.ajax_url+"?wpacu_clear_cache",{action:wpacu_object.plugin_id+"_clear_cache",time_r:(new Date).getTime()},function(a){setTimeout(function(){wpacuClearAutoptimizeCache()},150)})}function wpacuClearAutoptimizeCache(){jQuery("#wp-admin-bar-autoptimize-default li").length>0&&void 0!==autoptimize_ajax_object.ajaxurl&&void 0!==autoptimize_ajax_object.nonce&&jQuery.ajax({type:"GET",url:autoptimize_ajax_object.ajaxurl,data:{action:"autoptimize_delete_cache",nonce:autoptimize_ajax_object.nonce},dataType:"json",cache:!1,timeout:9e3,success:function(a){},error:function(a,b){}})}jQuery(document).ready(function(a){function b(){if(!a("#wpacu_ajax_fetch_assets_list_dashboard_view").length)return!1;var b,c,d,f,g,h={};"direct"===wpacu_object.dom_get_type?(h[wpacu_object.plugin_name+"_load"]=1,h[wpacu_object.plugin_name+"_time_r"]=(new Date).getTime(),a.ajax({method:"GET",url:wpacu_object.page_url,data:h,cache:!1,complete:function(b,c){if("error"===b.statusText){f=b.responseText.replace(/(<([^>]+)>)/gi,"");try{f=String(f).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}catch(a){console.log(a)}g=wpacu_object.ajax_direct_fetch_error,g=g.replace(/{wpacu_output}/,f),g=g.replace(/{wpacu_status_code_error}/,b.status),a("#wpacu_meta_box_content").html(g)}}}).done(function(f){if(f.lastIndexOf(wpacu_object.start_del_e)<0||f.lastIndexOf(wpacu_object.end_del_e)<0||f.lastIndexOf(wpacu_object.start_del_h)<0||f.lastIndexOf(wpacu_object.end_del_h)<0){g=wpacu_object.ajax_direct_fetch_error_with_success_response,g=g.replace(/{wpacu_output}/,xhr.responseText.replace(/(<([^>]+)>)/gi,""));try{g=String(g).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}catch(a){console.log(a)}return void a("#wpacu_meta_box_content").html(g)}c=f.substring(f.lastIndexOf(wpacu_object.start_del_e)+wpacu_object.start_del_e.length,f.lastIndexOf(wpacu_object.end_del_e)),d=f.substring(f.lastIndexOf(wpacu_object.start_del_h)+wpacu_object.start_del_h.length,f.lastIndexOf(wpacu_object.end_del_h)),b={action:wpacu_object.plugin_name+"_get_loaded_assets",wpacu_list_e:c,wpacu_list_h:d,post_id:wpacu_object.post_id,page_url:wpacu_object.page_url,tag_id:wpacu_object.tag_id,wpacu_taxonomy:wpacu_object.wpacu_taxonomy,time_r:(new Date).getTime()},a.post(wpacu_object.ajax_url,b,function(b){b&&(a("#wpacu_meta_box_content").html(b),a("#wpacu_home_page_form").length>0&&a("#submit").show(),setTimeout(function(){e.load(),a(".wpacu_asset_row").removeClass("wpacu-loading"),a("#wpacu-assets-reloading").remove(),e.checkSourcesFor404Errors()},200))})})):"wp_remote_post"===wpacu_object.dom_get_type&&(b={action:wpacu_object.plugin_name+"_get_loaded_assets",post_id:wpacu_object.post_id,page_url:wpacu_object.page_url,tag_id:wpacu_object.tag_id,wpacu_taxonomy:wpacu_object.wpacu_taxonomy,time_r:(new Date).getTime()},a.post(wpacu_object.ajax_url,b,function(b){if(!b)return!1;a("#wpacu_meta_box_content").html(b),a("#wpacu_home_page_form").length>0&&a("#submit").show(),setTimeout(function(){e.load(),setTimeout(function(){e.checkSourcesFor404Errors()},100)},200)}))}a('input[name="wpacu_sub_tab_area"]').click(function(){a(this).prop("checked")&&a("#wpacu-selected-sub-tab-area").val(a(this).val())}),a("#wpacu_minify_css_enable, #wpacu_combine_loaded_css_enable, #wpacu_minify_js_enable, #wpacu_combine_loaded_js_enable, #wpacu_cdn_rewrite_enable, #wpacu_enable_test_mode").click(function(){a(this).prop("checked")?a('[data-linked-to="'+a(this).attr("id")+'"]').find(".wpacu-circle-status").addClass("wpacu-on").removeClass("wpacu-off"):a('[data-linked-to="'+a(this).attr("id")+'"]').find(".wpacu-circle-status").addClass("wpacu-off").removeClass("wpacu-on")}),a(document).on("click","#wpacu_inline_css_files_below_size_checkbox",function(){a(this).is(":checked")?a("#wpacu_inline_css_files_enable").prop("checked",!0).trigger("tick"):""===a("#wpacu_inline_css_files_list").val()&&a("#wpacu_inline_css_files_enable").prop("checked",!1).trigger("tick")}),a(document).on("click","#wpacu_inline_js_files_below_size_checkbox",function(){if(a(this).is(":checked")){if(!confirm(wpacu_object.inline_auto_js_files_confirm_msg))return!1;a("#wpacu_inline_js_files_enable").prop("checked",!0).trigger("tick")}else""===a("#wpacu_inline_js_files_list").val()&&a("#wpacu_inline_js_files_enable").prop("checked",!1).trigger("tick")}),a("#wpacu-mark-license-valid-button").click(function(){return confirm(wpacu_object.mark_license_valid_confirm)}),a("#wpacu-license-form").submit(function(){a("#edd_license_activate_btn").attr("disabled","disabled"),a("#edd_license_deactivate_btn").attr("disabled","disabled"),a(".wpacu-license-spinner").show()});var c,d;a("#wpacu-reset-drop-down").on("change keyup keydown mouseup mousedown click",function(){""===a(this).val()?(a("#wpacu-warning-read").removeClass("wpacu-visible"),a("#wpacu-reset-submit-btn").attr("disabled","disabled").removeClass("button-primary").addClass("button-secondary")):("reset_everything"===a(this).val()?a("#wpacu-license-data-remove-area, #wpacu-cache-assets-remove-area").addClass("wpacu-visible"):a("#wpacu-license-data-remove-area, #wpacu-cache-assets-remove-area").removeClass("wpacu-visible"),a("#wpacu-warning-read").addClass("wpacu-visible"),a("#wpacu-reset-submit-btn").removeAttr("disabled").removeClass("button-secondary").addClass("button-primary")),a(".wpacu-tools-area .wpacu-warning").hide(),c=a(this).find("option:selected"),a("#"+c.attr("data-id")).show()}),a("#wpacu-reset-submit-btn").on("click",function(){if("reset_settings"===a("#wpacu-reset-drop-down").val()?d=wpacu_object.reset_settings_confirm_msg:"reset_everything_except_settings"===a("#wpacu-reset-drop-down").val()?d=wpacu_object.reset_everything_except_settings_confirm_msg:"reset_everything"===a("#wpacu-reset-drop-down").val()&&(d=wpacu_object.reset_everything_confirm_msg),!confirm(d))return!1;a("#wpacu-action-confirmed").val("yes"),setTimeout(function(){"yes"===a("#wpacu-action-confirmed").val()&&a("#wpacu-tools-form").submit()},1e3)}),a("#wpacu-import-form").submit(function(){if(!confirm(wpacu_object.import_confirm_msg))return!1;a(this).find("button").addClass("wpacu-importing").prop("disabled",!0)});var e={load:function(){var b,c,d,f=".input-unload-on-this-page.wpacu-not-locked";a(".input-unload-on-this-page").on("click change",function(f){if(b=a(this).attr("data-handle"),c=a(this).hasClass("wpacu_unload_rule_for_style")?"style":"script",a(this).prop("checked")){if("click"===f.type&&!e.triggerAlertWhenAnyUnloadRuleIsChosen(b,c))return!1;e.uncheckAllOtherBulkUnloadRules(a(this),!1),e.showHandleLoadExceptionArea(c,b),a(this).closest("tr").addClass("wpacu_not_load")}else a(this).closest("tr").removeClass("wpacu_not_load"),d=a(this).parents(".wpacu_asset_row"),e.hideHandleLoadExceptionArea(d,b,c)}),a(".wpacu-plugin-check-all").on("click",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-plugin");a('table.wpacu_list_by_location[data-wpacu-plugin="'+c+'"]').find(f).prop("checked",!0).closest("tr").addClass("wpacu_not_load")}),a(".wpacu-plugin-uncheck-all").on("click",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-plugin");a('table.wpacu_list_by_location[data-wpacu-plugin="'+c+'"]').find(f).prop("checked",!1).closest("tr").removeClass("wpacu_not_load")}),a(".wpacu-plugin-check-load-all").on("click change",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-plugin"),d=a('table.wpacu_list_by_location[data-wpacu-plugin="'+c+'"]');d.find(".wpacu_load_it_option_one.wpacu_load_exception").prop("checked",!0).closest("tr.wpacu_is_bulk_unloaded").removeClass("wpacu_not_load"),d.find(f).prop("checked",!1).trigger("change")}),a(".wpacu-plugin-uncheck-load-all").on("click change",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-plugin"),d=a('table.wpacu_list_by_location[data-wpacu-plugin="'+c+'"]');d.find(".wpacu_load_it_option_one.wpacu_load_exception").prop("checked",!1).closest("tr.wpacu_is_bulk_unloaded").addClass("wpacu_not_load"),d.find(f).prop("checked",!1).trigger("change")}),a(".wpacu_keep_bulk_rule").click(function(){a(this).prop("checked")&&a(this).parents("li").next().removeClass("remove_rule")}),a(".wpacu_remove_bulk_rule").click(function(){a(this).prop("checked")&&a(this).parents("li").addClass("remove_rule")}),a(".wpacu_bulk_unload").on("click change",function(f){b=a(this).attr("data-handle"),c=a(this).attr("data-handle-for"),d=a("[data-"+c+'-handle-row="'+b+'"]');var g=a(this).parents("li");if(a(this).prop("checked")){if("click"===f.type&&!e.triggerAlertWhenAnyUnloadRuleIsChosen(b,c))return!1;a(this).hasClass("wpacu_unload_it_regex_checkbox")?(g.find("label").addClass("wpacu_unload_checked"),g.find("textarea").prop("disabled",!1).focus().removeClass("wpacu_disabled"),g.find(".wpacu_handle_unload_regex_input_wrap").removeClass("wpacu_hide")):(a(this).parent("label").addClass("wpacu_input_load_checked"),a(this).closest("tr").addClass("wpacu_not_load")),e.showHandleLoadExceptionArea(c,b),a(this).hasClass("wpacu_global_unload")?(e.uncheckAllOtherBulkUnloadRules(a(this),!0),a('.input-unload-on-this-page[data-handle-for="'+c+'"][data-handle="'+b+'"]').prop("checked",!1)):a(this).hasClass("wpacu_post_type_unload")&&(e.uncheckAllOtherBulkUnloadRules(a(this),!1),a('.input-unload-on-this-page[data-handle-for="'+c+'"][data-handle="'+b+'"]').prop("checked",!1))}else a(this).hasClass("wpacu_unload_it_regex_checkbox")?(g.find("label").removeClass("wpacu_unload_checked"),g.find("textarea").blur().addClass("wpacu_disabled"),""===g.find("textarea").val().trim()&&(g.find("textarea").prop("disabled",!0).val(""),g.find(".wpacu_handle_unload_regex_input_wrap").addClass("wpacu_hide"))):(a(this).parent("label").removeClass("wpacu_input_load_checked"),a(this).closest("tr").removeClass("wpacu_not_load")),e.hideHandleLoadExceptionArea(d,b,c);d.hasClass("wpacu_is_bulk_unloaded")||a(".wpacu_bulk_unload:not(.wpacu_unload_it_regex_checkbox)").is(":checked")||a(this).closest("tr").removeClass("wpacu_not_load")}),a(".wpacu_load_it_option_one.wpacu_load_exception").on("click change",function(){var b=a(this).attr("data-handle");if(a(this).prop("checked")){a(this).parent("label").addClass("wpacu_global_unload_exception");var c="";a(this).hasClass("wpacu_style")?c="style":a(this).hasClass("wpacu_script")&&(c="script"),a("#"+c+"_"+b).prop("checked",!1).trigger("change")}else a(this).parent("label").removeClass("wpacu_global_unload_exception")}),a(".wpacu_load_it_option_two").on("click change",function(){var b=a(this).parents("li");a(this).prop("checked")?(b.find("label").addClass("wpacu_bold"),b.find("textarea").prop("disabled",!1).focus().removeClass("wpacu_disabled"),b.find(".wpacu_load_regex_input_wrap").removeClass("wpacu_hide")):(b.find("label").removeClass("wpacu_bold"),b.find("textarea").blur().addClass("wpacu_disabled"),""===b.find("textarea").val().trim()&&(b.find("textarea").prop("disabled",!0).val(""),b.find(".wpacu_load_regex_input_wrap").addClass("wpacu_hide")))}),a(".wpacu_script_attr_rule_input").on("click change",function(){a(this).is(":checked")&&(a(this).parents("ul").find(".wpacu_script_attr_rule_input").not(a(this)).prop("checked",!1),a(this).hasClass("wpacu_script_attr_rule_global")&&a(this).parents("ul").find(".wpacu-script-attr-make-exception").removeClass("wpacu_hide")),a(this).parents("ul").find(".wpacu_script_attr_rule_global").is(":checked")||a(this).parents("ul").find(".wpacu-script-attr-make-exception").addClass("wpacu_hide")}),a(".wpacu-add-handle-note").on("click",function(b){b.preventDefault();var c,d,e=a(this).attr("data-handle");a(this).hasClass("wpacu-for-script")?c=a('.wpacu-handle-notes-field[data-script-handle="'+e+'"]'):a(this).hasClass("wpacu-for-style")&&(c=a('.wpacu-handle-notes-field[data-style-handle="'+e+'"]')),c.length<1||(d=c.find(":input"),c.is(":hidden")?(c.show(),d.prop("disabled",!1)):(c.hide(),""===d.val().trim()&&"true"===d.attr("data-wpacu-is-empty-on-page-load")&&d.prop("disabled",!0).val("")))}),a(".wpacu-external-file-size").on("click",function(b){b.preventDefault();var c,d=a(this),e=d.attr("data-src");d.hide(),c=d.next(),c.show(),e.includes("/?")?a.get(e,{},function(a,b,d){if("success"!==b)return"N/A";c.html(wpacuBytesToSize(a.length))}):a.post(wpacu_object.ajax_url,{action:wpacu_object.plugin_id+"_get_external_file_size",wpacu_remote_file:e},function(a){c.html(a)})}),a(".wpacu_handle_row_expand_contract").on("click",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-handle"),d=a(this).attr("data-wpacu-handle-for");a(this).find("span").hasClass("dashicons-minus")?(a(this).parents("td").attr("data-wpacu-row-status","contracted").find(".wpacu_handle_row_expanded_area").addClass("wpacu_hide"),a(this).find("span").removeClass("dashicons-minus").addClass("dashicons-plus"),a("#wpacu_"+d+"_"+c+"_row_contracted_area").val("1")):a(this).find("span").hasClass("dashicons-plus")&&(a(this).parents("td").attr("data-wpacu-row-status","expanded").find(".wpacu_handle_row_expanded_area").removeClass("wpacu_hide"),a(this).find("span").removeClass("dashicons-plus").addClass("dashicons-minus"),a("#wpacu_"+d+"_"+c+"_row_contracted_area").val(""))});a('[data-is-hardcoded-asset="true"]').length>0&&(a.each(a('[data-is-hardcoded-asset="true"]'),function(b,c){e.updateHardcodedDataHiddenFieldStatus(a(this))}),a('[data-is-hardcoded-asset="true"]').on("click",".wpacu_unload_rule_input",function(){e.updateHardcodedDataHiddenFieldStatus(a(this).parents("[data-is-hardcoded-asset]"))}))},updateHardcodedDataHiddenFieldStatus:function(b){var c=!1;b.is("[data-style-handle-row]")?c=b.attr("data-style-handle-row"):b.is("[data-script-handle-row]")&&(c=b.attr("data-script-handle-row")),c&&(b.find(".wpacu_unload_rule_input:checked").length>0||b.hasClass("wpacu_not_load")?a("#"+c+"_hardcoded_data").prop("disabled",!1):a("#"+c+"_hardcoded_data").prop("disabled",!0))},triggerAlertWhenAnyUnloadRuleIsChosen:function(b,c){if("dashicons"===b&&"style"===c&&a('input[name="wpacu_ignore_child[styles][nf-display]').length>0&&!confirm(wpacu_object.dashicons_unload_alert_ninja_forms))return!1;if("script"===c){if(("jquery"===b||"jquery-core"===b)&&a("#script_jquery_ignore_children").length>0&&!confirm(wpacu_object.jquery_unload_alert))return!1;if(("backbone"===b||"underscore"===b)&&!confirm(wpacu_object.sensitive_library_unload_alert))return!1}return!0},pluginLoadManager:function(){a(".wpacu_plugin_load_it").on("click",function(){var b=a(this).attr("data-wpacu-plugin-path");a(this).prop("checked")&&(e.hidePluginLoadExceptionArea(b),a('.wpacu_plugin_unload_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide"),a('.wpacu_plugin_unload_site_wide[data-wpacu-plugin-path="'+b+'"]').parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"),a('.wpacu_plugin_unload_regex_radio[data-wpacu-plugin-path="'+b+'"]').parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"))}),a(".wpacu_plugin_unload_site_wide").on("click",function(){var b=a(this).attr("data-wpacu-plugin-path");a(this).prop("checked")?(a(this).parent("label").addClass("wpacu_plugin_unload_rule_input_checked"),a('.wpacu_plugin_unload_regex_radio[data-wpacu-plugin-path="'+b+'"]').parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"),a('.wpacu_plugin_unload_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide"),e.showPluginLoadExceptionArea(b)):(a(this).parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"),a('.wrap_plugin_load_exception_options[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide").find('input[type="checkbox"]').prop("disabled",!0))}),a(".wpacu_plugin_unload_regex_radio").on("click",function(){var b=a(this).attr("data-wpacu-plugin-path");a(this).prop("checked")?(a(this).parent("label").addClass("wpacu_plugin_unload_rule_input_checked"),a('.wpacu_plugin_unload_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').removeClass("wpacu_hide"),e.showPluginLoadExceptionArea(b),a('.wpacu_plugin_unload_site_wide[data-wpacu-plugin-path="'+b+'"]').prop("checked",!1).parent("label").removeClass("wpacu_plugin_unload_rule_input_checked")):(a('.wpacu_plugin_unload_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide"),a(this).parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"),a('.wrap_plugin_load_exception_options[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide"))}),a(".wpacu_plugin_load_exception_regex").on("click",function(){var b=a(this).attr("data-wpacu-plugin-path");a(this).prop("checked")?a('.wpacu_load_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').removeClass("wpacu_hide"):a('.wpacu_load_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide")})},showPluginLoadExceptionArea:function(b){a('.wrap_plugin_load_exception_options[data-wpacu-plugin-path="'+b+'"]').removeClass("wpacu_hide").find('input[type="checkbox"]').prop("disabled",!1)},hidePluginLoadExceptionArea:function(b){a('.wrap_plugin_load_exception_options[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide").find('input[type="checkbox"]').prop("disabled",!0)},showHandleLoadExceptionArea:function(b,c){var d=a("div.wpacu_exception_options_area_wrap[data-"+b+'-handle="'+c+'"]');d.parent("div").removeClass("wpacu_hide"),d.find('input[type="checkbox"]').prop("disabled",!1)},hideHandleLoadExceptionArea:function(b,c,d){if(!b.hasClass("wpacu_is_bulk_unloaded")&&!b.find(".wpacu_bulk_unload").is(":checked")){var e=a("div.wpacu_exception_options_area_wrap[data-"+d+'-handle="'+c+'"]');e.parent("div").addClass("wpacu_hide"),e.find('input[type="checkbox"]').prop("disabled",!0)}},uncheckAllOtherBulkUnloadRules:function(a,b){var c=".wpacu_bulk_unload";!1===b&&(c=".wpacu_bulk_unload:not(.wpacu_unload_it_regex_checkbox)"),a.closest("tr").find(c).not(a).prop("checked",!1).parent("label").removeClass("wpacu_input_load_checked").removeClass("wpacu_unload_checked")},checkSourcesFor404Errors:function(){var b=a("[data-wpacu-external-source]");if(!(b.length<1)){var c=b.length,d="";b.each(function(b){var e=a(this),f=e.attr("data-wpacu-external-source");d+=f+"-at-wpacu-at-",b===c-1&&jQuery.post(wpacu_object.ajax_url+"?wpacu_check_external_url",{action:wpacu_object.plugin_id+"_check_external_urls_for_status_code",wpacu_check_urls:d},function(b){var c=jQuery.parseJSON(b);a.each(c,function(b,c){a('[data-wpacu-external-source="'+c+'"]').css({color:"#cc0000"}).parent("div").find("[data-wpacu-external-source-status]").html('<small>* <em style="font-weight: 600;">'+wpacu_object.source_load_error_msg+"</em></small>")})})})}}};a(window).load(function(){e.checkSourcesFor404Errors()}),a("#wpacu_post_type_select").change(function(){a("#wpacu_post_type_form").submit()}),a("#wpacu_taxonomy_select").change(function(){a("#wpacu_taxonomy_form").submit()}),a("#wpacu_dashboard").click(function(){a(this).prop("checked")?a("#wpacu-settings-assets-retrieval-mode").show():a("#wpacu-settings-assets-retrieval-mode").hide()}),a(".wpacu-dom-get-type-selection").change(function(){a(this).is(":checked")&&(a(".wpacu-dom-get-type-info").hide(),a("#"+a(this).attr("data-target")).fadeIn("fast"))}),a("#wpacu_frontend").click(function(){a(this).prop("checked")?a("#wpacu-settings-frontend-exceptions").show():a("#wpacu-settings-frontend-exceptions").hide()}),a(".google_fonts_combine_type").change(function(){a(".wpacu_google_fonts_combine_type_area").hide(),"async"===a(this).val()?a("#wpacu_google_fonts_combine_type_async_info_area").fadeIn():"async_preload"===a(this).val()?a("#wpacu_google_fonts_combine_type_async_preload_info_area").fadeIn():a("#wpacu_google_fonts_combine_type_rb_info_area").fadeIn()}),a("#wpacu_assets_list_layout").on("click change",function(){"by-location"===a(this).val()?a("#wpacu-assets-list-by-location-selected").fadeIn("fast"):a("#wpacu-assets-list-by-location-selected").fadeOut("fast")}),a("#wpacu_disable_jquery_migrate").on("click",function(){return!a(this).is(":checked")||(!(!a(this).is(":checked")||!confirm(wpacu_object.jquery_migration_disable_confirm_msg))||(a(this).prop("checked",!1),!1))}),a("#wpacu_disable_comment_reply").on("click",function(){return!a(this).is(":checked")||(!(!a(this).is(":checked")||!confirm(wpacu_object.comment_reply_disable_confirm_msg))||(a(this).prop("checked",!1),!1))}),a("[data-target-opacity]").on("click change tick",function(){a(this).prop("checked")?a("#"+a(this).attr("data-target-opacity")).css({opacity:1}):a("#"+a(this).attr("data-target-opacity")).css({opacity:.4})}),a(".wpacu-combine-loaded-js-level").change(function(){a(this).is(":checked")&&(a(".wpacu_combine_loaded_js_level_area").removeClass("wpacu_active"),a("#"+a(this).attr("data-target")).addClass("wpacu_active"))});var f=a('#wpacu-update-button-area input[type="submit"]');f.parents("form").submit(function(){f.attr("disabled",!0),a("#wpacu-updating-settings").show()});var g=a("#wpacu-update-front-settings-area .wpacu_update_btn");if(g.parents("form").submit(function(){return g.attr("disabled",!0).addClass("wpacu_submitting"),a("#wpacu-updating-front-settings").show(),!0}),a("form#wpacu-settings-form, form#wpacu_home_page_form").submit(function(){return f.attr("disabled",!0),!0}),a(".wpacu_bulk_rule_checkbox, .wpacu_remove_preload").click(function(){var b=a(this).parents(".wpacu_bulk_change_row");a(this).prop("checked")?b.addClass("wpacu_selected"):b.removeClass("wpacu_selected")}),a(".wpacu_remove_regex").click(function(){var b=a(this).parents(".wpacu_regex_rule_row");a(this).prop("checked")?b.addClass("wpacu_enabled"):b.removeClass("wpacu_enabled")}),a(".wpacu_restore_position").click(function(){var b=a(this).parents(".wpacu_restore_position_row");a(this).prop("checked")?b.addClass("wpacu_selected"):b.removeClass("wpacu_selected")}),a(".wpacu_remove_global_attr").click(function(){var b=a(this).parents(".wpacu_remove_global_attr_row");a(this).prop("checked")?b.addClass("wpacu_selected"):b.removeClass("wpacu_selected")}),a("#wpacu_wrap_assets").length>0&&setTimeout(function(){e.load()},200),a("#wpacu-plugins-load-manager-wrap").length>0&&setTimeout(function(){e.pluginLoadManager()},200),"undefined"==typeof wpacu_object||a("#wpacu_meta_box_content").length<1)return!1;("default"===wpacu_object.list_show_status||""===wpacu_object.list_show_status||wpacu_object.override_assets_list_load)&&b(),"fetch_on_click"===wpacu_object.list_show_status&&a("#wpacu_ajax_fetch_on_click_btn").click(function(c){c.preventDefault(),a(this).hide(),a("#wpacu_fetching_assets_list_wrap").show(),b()}),a(document).on("click",".wp-admin.post-php .edit-post-header__settings button.is-primary",function(){var c=function(){if(0===a(".edit-post-header__settings .is-saving").length){if(a("#wpacu_unload_assets_area_loaded").length>0&&a("#wpacu_unload_assets_area_loaded").val()){a("#wpacu-assets-reloading").remove();var c='<span id="wpacu-assets-reloading" class="editor-post-saved-state is-wpacu-reloading">'+wpacu_object.reload_icon+wpacu_object.reload_msg+"</span>";a(".wp-admin.post-php .edit-post-header__settings").prepend(c)}a(".wpacu_asset_row").addClass("wpacu-loading"),b(),wpacuAjaxClearCache(),clearInterval(d)}},d=setInterval(c,900)})}),""!==wpacu_object.clear_cache_on_page_load&&wpacuAjaxClearCache(),""!==wpacu_object.clear_other_caches&&setTimeout(function(){wpacuClearAutoptimizeCache()},150),jQuery(document).ready(function(a){try{var b;a('input[type="hidden"][name="_wp_http_referer"]').length>0&&(b=a('input[type="hidden"][name="_wp_http_referer"]').val(),b.includes("term.php?taxonomy=")&&b.includes("message=")&&wpacuAjaxClearCache(),b.includes("post.php?post=")&&b.includes("message=")&&wpacuAjaxClearCache())}catch(a){console.log(a)}});
|
1 |
+
function wpacuTabOpenSettingsArea(a,b){a.preventDefault();var c,d,e;for(d=document.getElementsByClassName("wpacu-settings-tab-content"),c=0;c<d.length;c++)d[c].style.display="none";for(e=document.getElementsByClassName("wpacu-settings-tab-link"),c=0;c<e.length;c++)e[c].className=e[c].className.replace(" active","");document.getElementById(b).style.display="table-cell",jQuery('a[href="#'+b+'"]').addClass("active"),jQuery("#wpacu-selected-tab-area").val(b)}function wpacuBytesToSize(a){return 0===a?"N/A":(a/1024).toFixed(4)+" KB"}function wpacuAjaxClearCache(){jQuery.post(wpacu_object.ajax_url+"?wpacu_clear_cache",{action:wpacu_object.plugin_id+"_clear_cache",time_r:(new Date).getTime()},function(a){setTimeout(function(){wpacuClearAutoptimizeCache(),wpacu_object.is_frontend_view?jQuery.post(wpacu_object.ajax_url+"?wpacu_preload_guest",{action:wpacu_object.plugin_id+"_preload",page_url:wpacu_object.page_url,time_r:(new Date).getTime()}):jQuery.get(wpacu_object.page_url,{wpacu_preload:1,wpacu_no_frontend_show:1,time_r:(new Date).getTime()},function(){jQuery.post(wpacu_object.ajax_url+"?wpacu_preload_guest",{action:wpacu_object.plugin_id+"_preload",page_url:wpacu_object.page_url,time_r:(new Date).getTime()})})},150)})}function wpacuClearAutoptimizeCache(){jQuery("#wp-admin-bar-autoptimize-default li").length>0&&void 0!==autoptimize_ajax_object.ajaxurl&&void 0!==autoptimize_ajax_object.nonce&&jQuery.ajax({type:"GET",url:autoptimize_ajax_object.ajaxurl,data:{action:"autoptimize_delete_cache",nonce:autoptimize_ajax_object.nonce},dataType:"json",cache:!1,timeout:9e3,success:function(a){},error:function(a,b){}})}jQuery(document).ready(function(a){function b(){if(!a("#wpacu_ajax_fetch_assets_list_dashboard_view").length)return!1;var b={};if("direct"===wpacu_object.dom_get_type)b[wpacu_object.plugin_name+"_load"]=1,b[wpacu_object.plugin_name+"_time_r"]=(new Date).getTime(),a.ajax({method:"GET",url:wpacu_object.page_url,data:b,cache:!1,complete:function(b,d){if("error"===b.statusText){if(404===b.status)return void c(b.responseText,b.status);var e=b.responseText.replace(/(<([^>]+)>)/gi,"");try{e=String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}catch(a){console.log(a)}var f=wpacu_object.ajax_direct_fetch_error;f=f.replace(/{wpacu_output}/,e),f=f.replace(/{wpacu_status_code_error}/,b.status),a("#wpacu_meta_box_content").html(f)}}}).done(function(a){c(a)});else if("wp_remote_post"===wpacu_object.dom_get_type){var d={action:wpacu_object.plugin_name+"_get_loaded_assets",post_id:wpacu_object.post_id,page_url:wpacu_object.page_url,tag_id:wpacu_object.tag_id,wpacu_taxonomy:wpacu_object.wpacu_taxonomy,time_r:(new Date).getTime()};a.post(wpacu_object.ajax_url,d,function(b){if(!b)return!1;a("#wpacu_meta_box_content").html(b),a("#wpacu_home_page_form").length>0&&a("#submit").show(),setTimeout(function(){f.load(),setTimeout(function(){f.checkSourcesFor404Errors()},100)},200)})}}function c(b,c){if(b.lastIndexOf(wpacu_object.start_del_e)<0||b.lastIndexOf(wpacu_object.end_del_e)<0||b.lastIndexOf(wpacu_object.start_del_h)<0||b.lastIndexOf(wpacu_object.end_del_h)<0){var d=wpacu_object.ajax_direct_fetch_error_with_success_response;d=d.replace(/{wpacu_output}/,xhr.responseText.replace(/(<([^>]+)>)/gi,""));try{d=String(d).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}catch(a){console.log(a)}return void a("#wpacu_meta_box_content").html(d)}var e=b.substring(b.lastIndexOf(wpacu_object.start_del_e)+wpacu_object.start_del_e.length,b.lastIndexOf(wpacu_object.end_del_e)),g=b.substring(b.lastIndexOf(wpacu_object.start_del_h)+wpacu_object.start_del_h.length,b.lastIndexOf(wpacu_object.end_del_h)),h={action:wpacu_object.plugin_name+"_get_loaded_assets",wpacu_list_e:e,wpacu_list_h:g,post_id:wpacu_object.post_id,page_url:wpacu_object.page_url,tag_id:wpacu_object.tag_id,wpacu_taxonomy:wpacu_object.wpacu_taxonomy,time_r:(new Date).getTime()};a.post(wpacu_object.ajax_url,h,function(b){b&&(a("#wpacu_meta_box_content").html(b),404===c&&a("#wpacu_meta_box_content").prepend('<p><span class="dashicons dashicons-warning"></span> '+wpacu_object.server_returned_404_not_found+"</p><hr />"),a("#wpacu_home_page_form").length>0&&a("#submit").show(),setTimeout(function(){f.load(),a(".wpacu_asset_row").removeClass("wpacu-loading"),a("#wpacu-assets-reloading").remove(),f.checkSourcesFor404Errors()},200))})}a('input[name="wpacu_sub_tab_area"]').click(function(){a(this).prop("checked")&&a("#wpacu-selected-sub-tab-area").val(a(this).val())}),a("#wpacu_minify_css_enable, #wpacu_combine_loaded_css_enable, #wpacu_minify_js_enable, #wpacu_combine_loaded_js_enable, #wpacu_cdn_rewrite_enable, #wpacu_enable_test_mode").click(function(){a(this).prop("checked")?a('[data-linked-to="'+a(this).attr("id")+'"]').find(".wpacu-circle-status").addClass("wpacu-on").removeClass("wpacu-off"):a('[data-linked-to="'+a(this).attr("id")+'"]').find(".wpacu-circle-status").addClass("wpacu-off").removeClass("wpacu-on")}),a(document).on("click","#wpacu_inline_css_files_below_size_checkbox",function(){a(this).is(":checked")?a("#wpacu_inline_css_files_enable").prop("checked",!0).trigger("tick"):""===a("#wpacu_inline_css_files_list").val()&&a("#wpacu_inline_css_files_enable").prop("checked",!1).trigger("tick")}),a(document).on("click","#wpacu_inline_js_files_below_size_checkbox",function(){if(a(this).is(":checked")){if(!confirm(wpacu_object.inline_auto_js_files_confirm_msg))return!1;a("#wpacu_inline_js_files_enable").prop("checked",!0).trigger("tick")}else""===a("#wpacu_inline_js_files_list").val()&&a("#wpacu_inline_js_files_enable").prop("checked",!1).trigger("tick")}),a("#wpacu-mark-license-valid-button").click(function(){return confirm(wpacu_object.mark_license_valid_confirm)}),a("#wpacu-license-form").submit(function(){a("#edd_license_activate_btn").attr("disabled","disabled"),a("#edd_license_deactivate_btn").attr("disabled","disabled"),a(".wpacu-license-spinner").show()});var d,e;a("#wpacu-reset-drop-down").on("change keyup keydown mouseup mousedown click",function(){""===a(this).val()?(a("#wpacu-warning-read").removeClass("wpacu-visible"),a("#wpacu-reset-submit-btn").attr("disabled","disabled").removeClass("button-primary").addClass("button-secondary")):("reset_everything"===a(this).val()?a("#wpacu-license-data-remove-area, #wpacu-cache-assets-remove-area").addClass("wpacu-visible"):a("#wpacu-license-data-remove-area, #wpacu-cache-assets-remove-area").removeClass("wpacu-visible"),a("#wpacu-warning-read").addClass("wpacu-visible"),a("#wpacu-reset-submit-btn").removeAttr("disabled").removeClass("button-secondary").addClass("button-primary")),a(".wpacu-tools-area .wpacu-warning").hide(),d=a(this).find("option:selected"),a("#"+d.attr("data-id")).show()}),a("#wpacu-reset-submit-btn").on("click",function(){if("reset_settings"===a("#wpacu-reset-drop-down").val()?e=wpacu_object.reset_settings_confirm_msg:"reset_everything_except_settings"===a("#wpacu-reset-drop-down").val()?e=wpacu_object.reset_everything_except_settings_confirm_msg:"reset_everything"===a("#wpacu-reset-drop-down").val()&&(e=wpacu_object.reset_everything_confirm_msg),!confirm(e))return!1;a("#wpacu-action-confirmed").val("yes"),setTimeout(function(){"yes"===a("#wpacu-action-confirmed").val()&&a("#wpacu-tools-form").submit()},1e3)}),a("#wpacu-import-form").submit(function(){if(!confirm(wpacu_object.import_confirm_msg))return!1;a(this).find("button").addClass("wpacu-importing").prop("disabled",!0)});var f={load:function(){var b,c,d,e=".input-unload-on-this-page.wpacu-not-locked";a(".input-unload-on-this-page").on("click change",function(e){if(b=a(this).attr("data-handle"),c=a(this).hasClass("wpacu_unload_rule_for_style")?"style":"script",a(this).prop("checked")){if("click"===e.type&&!f.triggerAlertWhenAnyUnloadRuleIsChosen(b,c))return!1;f.uncheckAllOtherBulkUnloadRules(a(this),!1),f.showHandleLoadExceptionArea(c,b),a(this).closest("tr").addClass("wpacu_not_load")}else a(this).closest("tr").removeClass("wpacu_not_load"),d=a(this).parents(".wpacu_asset_row"),f.hideHandleLoadExceptionArea(d,b,c)}),a(".wpacu-plugin-check-all").on("click",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-plugin");a('table.wpacu_list_by_location[data-wpacu-plugin="'+c+'"]').find(e).prop("checked",!0).closest("tr").addClass("wpacu_not_load")}),a(".wpacu-plugin-uncheck-all").on("click",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-plugin");a('table.wpacu_list_by_location[data-wpacu-plugin="'+c+'"]').find(e).prop("checked",!1).closest("tr").removeClass("wpacu_not_load")}),a(".wpacu-plugin-check-load-all").on("click change",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-plugin"),d=a('table.wpacu_list_by_location[data-wpacu-plugin="'+c+'"]');d.find(".wpacu_load_it_option_one.wpacu_load_exception").prop("checked",!0).closest("tr.wpacu_is_bulk_unloaded").removeClass("wpacu_not_load"),d.find(e).prop("checked",!1).trigger("change")}),a(".wpacu-plugin-uncheck-load-all").on("click change",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-plugin"),d=a('table.wpacu_list_by_location[data-wpacu-plugin="'+c+'"]');d.find(".wpacu_load_it_option_one.wpacu_load_exception").prop("checked",!1).closest("tr.wpacu_is_bulk_unloaded").addClass("wpacu_not_load"),d.find(e).prop("checked",!1).trigger("change")}),a(".wpacu_keep_bulk_rule").click(function(){a(this).prop("checked")&&a(this).parents("li").next().removeClass("remove_rule")}),a(".wpacu_remove_bulk_rule").click(function(){a(this).prop("checked")&&a(this).parents("li").addClass("remove_rule")}),a(".wpacu_bulk_unload").on("click change",function(e){b=a(this).attr("data-handle"),c=a(this).attr("data-handle-for"),d=a("[data-"+c+'-handle-row="'+b+'"]');var g=a(this).parents("li");if(a(this).prop("checked")){if("click"===e.type&&!f.triggerAlertWhenAnyUnloadRuleIsChosen(b,c))return!1;a(this).hasClass("wpacu_unload_it_regex_checkbox")?(g.find("label").addClass("wpacu_unload_checked"),g.find("textarea").prop("disabled",!1).focus().removeClass("wpacu_disabled"),g.find(".wpacu_handle_unload_regex_input_wrap").removeClass("wpacu_hide")):(a(this).parent("label").addClass("wpacu_input_load_checked"),a(this).closest("tr").addClass("wpacu_not_load")),f.showHandleLoadExceptionArea(c,b),a(this).hasClass("wpacu_global_unload")?(f.uncheckAllOtherBulkUnloadRules(a(this),!0),a('.input-unload-on-this-page[data-handle-for="'+c+'"][data-handle="'+b+'"]').prop("checked",!1)):a(this).hasClass("wpacu_post_type_unload")&&(f.uncheckAllOtherBulkUnloadRules(a(this),!1),a('.input-unload-on-this-page[data-handle-for="'+c+'"][data-handle="'+b+'"]').prop("checked",!1))}else a(this).hasClass("wpacu_unload_it_regex_checkbox")?(g.find("label").removeClass("wpacu_unload_checked"),g.find("textarea").blur().addClass("wpacu_disabled"),""===g.find("textarea").val().trim()&&(g.find("textarea").prop("disabled",!0).val(""),g.find(".wpacu_handle_unload_regex_input_wrap").addClass("wpacu_hide"))):(a(this).parent("label").removeClass("wpacu_input_load_checked"),a(this).closest("tr").removeClass("wpacu_not_load")),f.hideHandleLoadExceptionArea(d,b,c);d.hasClass("wpacu_is_bulk_unloaded")||a(".wpacu_bulk_unload:not(.wpacu_unload_it_regex_checkbox)").is(":checked")||a(this).closest("tr").removeClass("wpacu_not_load")}),a(".wpacu_load_it_option_one.wpacu_load_exception").on("click change",function(){var b=a(this).attr("data-handle");if(a(this).prop("checked")){a(this).parent("label").addClass("wpacu_global_unload_exception");var c="";a(this).hasClass("wpacu_style")?c="style":a(this).hasClass("wpacu_script")&&(c="script"),a("#"+c+"_"+b).prop("checked",!1).trigger("change")}else a(this).parent("label").removeClass("wpacu_global_unload_exception")}),a(".wpacu_load_it_option_two").on("click change",function(){var b=a(this).parents("li");a(this).prop("checked")?(b.find("label").addClass("wpacu_bold"),b.find("textarea").prop("disabled",!1).focus().removeClass("wpacu_disabled"),b.find(".wpacu_load_regex_input_wrap").removeClass("wpacu_hide")):(b.find("label").removeClass("wpacu_bold"),b.find("textarea").blur().addClass("wpacu_disabled"),""===b.find("textarea").val().trim()&&(b.find("textarea").prop("disabled",!0).val(""),b.find(".wpacu_load_regex_input_wrap").addClass("wpacu_hide")))}),a(".wpacu_script_attr_rule_input").on("click change",function(){a(this).is(":checked")&&(a(this).parents("ul").find(".wpacu_script_attr_rule_input").not(a(this)).prop("checked",!1),a(this).hasClass("wpacu_script_attr_rule_global")&&a(this).parents("ul").find(".wpacu-script-attr-make-exception").removeClass("wpacu_hide")),a(this).parents("ul").find(".wpacu_script_attr_rule_global").is(":checked")||a(this).parents("ul").find(".wpacu-script-attr-make-exception").addClass("wpacu_hide")}),a(".wpacu-add-handle-note").on("click",function(b){b.preventDefault();var c,d,e=a(this).attr("data-handle");a(this).hasClass("wpacu-for-script")?c=a('.wpacu-handle-notes-field[data-script-handle="'+e+'"]'):a(this).hasClass("wpacu-for-style")&&(c=a('.wpacu-handle-notes-field[data-style-handle="'+e+'"]')),c.length<1||(d=c.find(":input"),c.is(":hidden")?(c.show(),d.prop("disabled",!1)):(c.hide(),""===d.val().trim()&&"true"===d.attr("data-wpacu-is-empty-on-page-load")&&d.prop("disabled",!0).val("")))}),a(".wpacu-external-file-size").on("click",function(b){b.preventDefault();var c,d=a(this),e=d.attr("data-src");d.hide(),c=d.next(),c.show(),e.includes("/?")?a.get(e,{},function(a,b,d){if("success"!==b)return"N/A";c.html(wpacuBytesToSize(a.length))}):a.post(wpacu_object.ajax_url,{action:wpacu_object.plugin_id+"_get_external_file_size",wpacu_remote_file:e},function(a){c.html(a)})}),a(".wpacu_handle_row_expand_contract").on("click",function(b){b.preventDefault();var c=a(this).attr("data-wpacu-handle"),d=a(this).attr("data-wpacu-handle-for");a(this).find("span").hasClass("dashicons-minus")?(a(this).parents("td").attr("data-wpacu-row-status","contracted").find(".wpacu_handle_row_expanded_area").addClass("wpacu_hide"),a(this).find("span").removeClass("dashicons-minus").addClass("dashicons-plus"),a("#wpacu_"+d+"_"+c+"_row_contracted_area").val("1")):a(this).find("span").hasClass("dashicons-plus")&&(a(this).parents("td").attr("data-wpacu-row-status","expanded").find(".wpacu_handle_row_expanded_area").removeClass("wpacu_hide"),a(this).find("span").removeClass("dashicons-plus").addClass("dashicons-minus"),a("#wpacu_"+d+"_"+c+"_row_contracted_area").val(""))});a('[data-is-hardcoded-asset="true"]').length>0&&(a.each(a('[data-is-hardcoded-asset="true"]'),function(b,c){f.updateHardcodedDataHiddenFieldStatus(a(this))}),a('[data-is-hardcoded-asset="true"]').on("click",".wpacu_unload_rule_input",function(){f.updateHardcodedDataHiddenFieldStatus(a(this).parents("[data-is-hardcoded-asset]"))}))},updateHardcodedDataHiddenFieldStatus:function(b){var c=!1;b.is("[data-style-handle-row]")?c=b.attr("data-style-handle-row"):b.is("[data-script-handle-row]")&&(c=b.attr("data-script-handle-row")),c&&(b.find(".wpacu_unload_rule_input:checked").length>0||b.hasClass("wpacu_not_load")?a("#"+c+"_hardcoded_data").prop("disabled",!1):a("#"+c+"_hardcoded_data").prop("disabled",!0))},triggerAlertWhenAnyUnloadRuleIsChosen:function(b,c){if("dashicons"===b&&"style"===c&&a('input[name="wpacu_ignore_child[styles][nf-display]').length>0&&!confirm(wpacu_object.dashicons_unload_alert_ninja_forms))return!1;if("script"===c){if(("jquery"===b||"jquery-core"===b)&&a("#script_jquery_ignore_children").length>0&&!confirm(wpacu_object.jquery_unload_alert))return!1;if(("backbone"===b||"underscore"===b)&&!confirm(wpacu_object.sensitive_library_unload_alert))return!1}return!0},pluginLoadManager:function(){a(".wpacu_plugin_load_it").on("click",function(){var b=a(this).attr("data-wpacu-plugin-path");a(this).prop("checked")&&(f.hidePluginLoadExceptionArea(b),a('.wpacu_plugin_unload_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide"),a('.wpacu_plugin_unload_site_wide[data-wpacu-plugin-path="'+b+'"]').parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"),a('.wpacu_plugin_unload_regex_radio[data-wpacu-plugin-path="'+b+'"]').parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"))}),a(".wpacu_plugin_unload_site_wide").on("click",function(){var b=a(this).attr("data-wpacu-plugin-path");a(this).prop("checked")?(a(this).parent("label").addClass("wpacu_plugin_unload_rule_input_checked"),a('.wpacu_plugin_unload_regex_radio[data-wpacu-plugin-path="'+b+'"]').parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"),a('.wpacu_plugin_unload_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide"),f.showPluginLoadExceptionArea(b)):(a(this).parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"),a('.wrap_plugin_load_exception_options[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide").find('input[type="checkbox"]').prop("disabled",!0))}),a(".wpacu_plugin_unload_regex_radio").on("click",function(){var b=a(this).attr("data-wpacu-plugin-path");a(this).prop("checked")?(a(this).parent("label").addClass("wpacu_plugin_unload_rule_input_checked"),a('.wpacu_plugin_unload_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').removeClass("wpacu_hide"),f.showPluginLoadExceptionArea(b),a('.wpacu_plugin_unload_site_wide[data-wpacu-plugin-path="'+b+'"]').prop("checked",!1).parent("label").removeClass("wpacu_plugin_unload_rule_input_checked")):(a('.wpacu_plugin_unload_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide"),a(this).parent("label").removeClass("wpacu_plugin_unload_rule_input_checked"),a('.wrap_plugin_load_exception_options[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide"))}),a(".wpacu_plugin_load_exception_regex").on("click",function(){var b=a(this).attr("data-wpacu-plugin-path");a(this).prop("checked")?a('.wpacu_load_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').removeClass("wpacu_hide"):a('.wpacu_load_regex_input_wrap[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide")})},showPluginLoadExceptionArea:function(b){a('.wrap_plugin_load_exception_options[data-wpacu-plugin-path="'+b+'"]').removeClass("wpacu_hide").find('input[type="checkbox"]').prop("disabled",!1)},hidePluginLoadExceptionArea:function(b){a('.wrap_plugin_load_exception_options[data-wpacu-plugin-path="'+b+'"]').addClass("wpacu_hide").find('input[type="checkbox"]').prop("disabled",!0)},showHandleLoadExceptionArea:function(b,c){var d=a("div.wpacu_exception_options_area_wrap[data-"+b+'-handle="'+c+'"]');d.parent("div").removeClass("wpacu_hide"),d.find('input[type="checkbox"]').prop("disabled",!1)},hideHandleLoadExceptionArea:function(b,c,d){if(!b.hasClass("wpacu_is_bulk_unloaded")&&!b.find(".wpacu_bulk_unload").is(":checked")){var e=a("div.wpacu_exception_options_area_wrap[data-"+d+'-handle="'+c+'"]');e.parent("div").addClass("wpacu_hide"),e.find('input[type="checkbox"]').prop("disabled",!0)}},uncheckAllOtherBulkUnloadRules:function(a,b){var c=".wpacu_bulk_unload";!1===b&&(c=".wpacu_bulk_unload:not(.wpacu_unload_it_regex_checkbox)"),a.closest("tr").find(c).not(a).prop("checked",!1).parent("label").removeClass("wpacu_input_load_checked").removeClass("wpacu_unload_checked")},checkSourcesFor404Errors:function(){var b=a("[data-wpacu-external-source]");if(!(b.length<1)){var c=b.length,d="";b.each(function(b){var e=a(this),f=e.attr("data-wpacu-external-source");d+=f+"-at-wpacu-at-",b===c-1&&jQuery.post(wpacu_object.ajax_url+"?wpacu_check_external_url",{action:wpacu_object.plugin_id+"_check_external_urls_for_status_code",wpacu_check_urls:d},function(b){var c=jQuery.parseJSON(b);a.each(c,function(b,c){a('[data-wpacu-external-source="'+c+'"]').css({color:"#cc0000"}).parent("div").find("[data-wpacu-external-source-status]").html('<small>* <em style="font-weight: 600;">'+wpacu_object.source_load_error_msg+"</em></small>")})})})}}};a(window).load(function(){f.checkSourcesFor404Errors()}),a("#wpacu_post_type_select").change(function(){a("#wpacu_post_type_form").submit()}),a("#wpacu_taxonomy_select").change(function(){a("#wpacu_taxonomy_form").submit()}),a("#wpacu_dashboard").click(function(){a(this).prop("checked")?a("#wpacu-settings-assets-retrieval-mode").show():a("#wpacu-settings-assets-retrieval-mode").hide()}),a(".wpacu-dom-get-type-selection").change(function(){a(this).is(":checked")&&(a(".wpacu-dom-get-type-info").hide(),a("#"+a(this).attr("data-target")).fadeIn("fast"))}),a("#wpacu_frontend").click(function(){a(this).prop("checked")?a("#wpacu-settings-frontend-exceptions").show():a("#wpacu-settings-frontend-exceptions").hide()}),a(".google_fonts_combine_type").change(function(){a(".wpacu_google_fonts_combine_type_area").hide(),"async"===a(this).val()?a("#wpacu_google_fonts_combine_type_async_info_area").fadeIn():"async_preload"===a(this).val()?a("#wpacu_google_fonts_combine_type_async_preload_info_area").fadeIn():a("#wpacu_google_fonts_combine_type_rb_info_area").fadeIn()}),a("#wpacu_assets_list_layout").on("click change",function(){"by-location"===a(this).val()?a("#wpacu-assets-list-by-location-selected").fadeIn("fast"):a("#wpacu-assets-list-by-location-selected").fadeOut("fast")}),a("#wpacu_disable_jquery_migrate").on("click",function(){return!a(this).is(":checked")||(!(!a(this).is(":checked")||!confirm(wpacu_object.jquery_migration_disable_confirm_msg))||(a(this).prop("checked",!1),!1))}),a("#wpacu_disable_comment_reply").on("click",function(){return!a(this).is(":checked")||(!(!a(this).is(":checked")||!confirm(wpacu_object.comment_reply_disable_confirm_msg))||(a(this).prop("checked",!1),!1))}),a("[data-target-opacity]").on("click change tick",function(){a(this).prop("checked")?a("#"+a(this).attr("data-target-opacity")).css({opacity:1}):a("#"+a(this).attr("data-target-opacity")).css({opacity:.4})}),a(".wpacu-combine-loaded-js-level").change(function(){a(this).is(":checked")&&(a(".wpacu_combine_loaded_js_level_area").removeClass("wpacu_active"),a("#"+a(this).attr("data-target")).addClass("wpacu_active"))});var g=a('#wpacu-update-button-area input[type="submit"]');g.parents("form").submit(function(){g.attr("disabled",!0),a("#wpacu-updating-settings").show()});var h=a("#wpacu-update-front-settings-area .wpacu_update_btn");if(h.parents("form").submit(function(){return h.attr("disabled",!0).addClass("wpacu_submitting"),a("#wpacu-updating-front-settings").show(),!0}),a("form#wpacu-settings-form, form#wpacu_home_page_form").submit(function(){return g.attr("disabled",!0),!0}),a(".wpacu_bulk_rule_checkbox, .wpacu_remove_preload").click(function(){var b=a(this).parents(".wpacu_bulk_change_row");a(this).prop("checked")?b.addClass("wpacu_selected"):b.removeClass("wpacu_selected")}),a(".wpacu_remove_regex").click(function(){var b=a(this).parents(".wpacu_regex_rule_row");a(this).prop("checked")?b.addClass("wpacu_enabled"):b.removeClass("wpacu_enabled")}),a(".wpacu_restore_position").click(function(){var b=a(this).parents(".wpacu_restore_position_row");a(this).prop("checked")?b.addClass("wpacu_selected"):b.removeClass("wpacu_selected")}),a(".wpacu_remove_global_attr").click(function(){var b=a(this).parents(".wpacu_remove_global_attr_row");a(this).prop("checked")?b.addClass("wpacu_selected"):b.removeClass("wpacu_selected")}),a("#wpacu_wrap_assets").length>0&&setTimeout(function(){f.load()},200),a("#wpacu-plugins-load-manager-wrap").length>0&&setTimeout(function(){f.pluginLoadManager()},200),"undefined"==typeof wpacu_object||a("#wpacu_meta_box_content").length<1)return!1;("default"===wpacu_object.list_show_status||""===wpacu_object.list_show_status||wpacu_object.override_assets_list_load)&&b(),"fetch_on_click"===wpacu_object.list_show_status&&a("#wpacu_ajax_fetch_on_click_btn").click(function(c){c.preventDefault(),a(this).hide(),a("#wpacu_fetching_assets_list_wrap").show(),b()}),a(document).on("click",".wp-admin.post-php .edit-post-header__settings button.is-primary",function(){var c=function(){if(0===a(".edit-post-header__settings .is-saving").length){if(a("#wpacu_unload_assets_area_loaded").length>0&&a("#wpacu_unload_assets_area_loaded").val()){a("#wpacu-assets-reloading").remove();var c='<span id="wpacu-assets-reloading" class="editor-post-saved-state is-wpacu-reloading">'+wpacu_object.reload_icon+wpacu_object.reload_msg+"</span>";a(".wp-admin.post-php .edit-post-header__settings").prepend(c)}a(".wpacu_asset_row").addClass("wpacu-loading"),b(),wpacuAjaxClearCache(),clearInterval(d)}},d=setInterval(c,900)})}),""!==wpacu_object.clear_cache_on_page_load&&wpacuAjaxClearCache(),""!==wpacu_object.clear_other_caches&&setTimeout(function(){wpacuClearAutoptimizeCache()},150),jQuery(document).ready(function(a){try{var b;a('input[type="hidden"][name="_wp_http_referer"]').length>0&&(b=a('input[type="hidden"][name="_wp_http_referer"]').val(),b.includes("term.php?taxonomy=")&&b.includes("message=")&&wpacuAjaxClearCache(),b.includes("post.php?post=")&&b.includes("message=")&&wpacuAjaxClearCache())}catch(a){console.log(a)}});
|
classes/CleanUp.php
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp;
|
3 |
|
|
|
|
|
4 |
/**
|
5 |
* Class CleanUp
|
6 |
* @package WpAssetCleanUp
|
@@ -23,7 +25,7 @@ class CleanUp
|
|
23 |
*/
|
24 |
public function doClean()
|
25 |
{
|
26 |
-
if (Main::instance()->preventAssetsSettings()) {
|
27 |
return;
|
28 |
}
|
29 |
|
@@ -45,6 +47,10 @@ class CleanUp
|
|
45 |
if ($settings['remove_rest_api_link'] == 1) {
|
46 |
// <link rel='https://api.w.org/' href='https://yourwebsite.com/wp-json/' />
|
47 |
remove_action('wp_head', 'rest_output_link_wp_head');
|
|
|
|
|
|
|
|
|
48 |
}
|
49 |
|
50 |
// Remove "Shortlink"?
|
@@ -54,8 +60,7 @@ class CleanUp
|
|
54 |
|
55 |
// link: <https://yourdomainname.com/wp-json/>; rel="https://api.w.org/", <https://yourdomainname.com/?p=[post_id_here]>; rel=shortlink
|
56 |
remove_action('template_redirect', 'wp_shortlink_header', 11);
|
57 |
-
|
58 |
-
}
|
59 |
|
60 |
// Remove "Post's Relational Links"?
|
61 |
if ($settings['remove_posts_rel_links'] == 1) {
|
@@ -143,105 +148,128 @@ class CleanUp
|
|
143 |
*/
|
144 |
public static function removeMetaGenerators($htmlSource)
|
145 |
{
|
146 |
-
|
147 |
-
|
148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
|
150 |
-
|
151 |
-
|
|
|
|
|
|
|
|
|
152 |
|
153 |
-
|
154 |
-
&& function_exists('libxml_clear_errors')
|
155 |
-
&& class_exists('DOMDocument'))
|
156 |
-
{
|
157 |
-
$document = new \DOMDocument();
|
158 |
-
libxml_use_internal_errors(true);
|
159 |
|
160 |
-
|
|
|
|
|
161 |
|
162 |
-
$
|
163 |
|
164 |
-
foreach ($
|
165 |
-
$
|
|
|
|
|
|
|
166 |
|
167 |
-
|
168 |
-
|
|
|
169 |
|
170 |
-
|
171 |
-
|
172 |
-
|
|
|
|
|
|
|
173 |
|
174 |
-
|
175 |
-
$tagWithoutLastChar = substr($outerTag, 0, -1);
|
176 |
-
$outerTagRegExp = preg_quote($tagWithoutLastChar, '/').'(.*?)>';
|
177 |
-
}
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
|
|
|
|
184 |
|
185 |
-
|
186 |
-
|
|
|
187 |
|
188 |
-
if (
|
189 |
-
$
|
|
|
190 |
}
|
191 |
|
192 |
-
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
}
|
195 |
}
|
196 |
}
|
197 |
-
}
|
198 |
-
|
199 |
-
libxml_clear_errors();
|
200 |
-
|
201 |
-
if ($domUpdated) {
|
202 |
-
return $htmlSource;
|
203 |
-
}
|
204 |
-
}
|
205 |
|
206 |
-
|
207 |
-
preg_match_all('#<meta[^>]*name(\s+|)=(\s+|)("|\')generator("|\').*("|\'|\/)(\s+|)>#Usmi', $htmlSource, $matches);
|
208 |
|
209 |
-
|
210 |
-
foreach ($matches[0] as $metaTag) {
|
211 |
-
if (strip_tags($metaTag) === '') { // make sure the full tag was extracted
|
212 |
-
$htmlSource = str_replace($metaTag, '', $htmlSource);
|
213 |
-
}
|
214 |
}
|
215 |
}
|
216 |
|
|
|
|
|
|
|
217 |
return $htmlSource;
|
218 |
}
|
219 |
|
220 |
/**
|
221 |
* @param $htmlSource
|
|
|
|
|
222 |
*
|
223 |
-
* @return
|
224 |
*/
|
225 |
-
public static function removeHtmlComments($htmlSource)
|
226 |
{
|
227 |
// No comments? Do not continue
|
228 |
if (strpos($htmlSource, '<!--') === false) {
|
229 |
return $htmlSource;
|
230 |
}
|
231 |
|
232 |
-
if (! (function_exists('libxml_use_internal_errors')
|
233 |
-
&& function_exists('libxml_clear_errors')
|
234 |
-
&& class_exists('DOMDocument')))
|
235 |
-
{
|
236 |
return $htmlSource;
|
237 |
}
|
238 |
|
239 |
-
$
|
240 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
|
242 |
-
|
|
|
|
|
243 |
|
244 |
-
$xpathComments = new \DOMXPath($
|
245 |
$comments = $xpathComments->query('//comment()');
|
246 |
|
247 |
libxml_clear_errors();
|
@@ -278,18 +306,21 @@ class CleanUp
|
|
278 |
}
|
279 |
}
|
280 |
|
|
|
|
|
281 |
foreach ($comments as $comment) {
|
282 |
-
$entireComment =
|
283 |
|
284 |
// Do not strip MSIE conditional comments
|
285 |
-
if (strpos($entireComment, '<!--<![endif]-->') !== false ||
|
286 |
-
|
287 |
-
|
288 |
continue;
|
289 |
}
|
290 |
|
291 |
// Any exceptions set in "Strip HTML comments?" textarea?
|
292 |
-
|
|
|
293 |
$removeHtmlCommentsExceptions = trim(Main::instance()->settings['remove_html_comments_exceptions']);
|
294 |
|
295 |
if (strpos($removeHtmlCommentsExceptions, "\n") !== false) {
|
@@ -305,14 +336,15 @@ class CleanUp
|
|
305 |
}
|
306 |
}
|
307 |
|
308 |
-
$
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
|
|
316 |
}
|
317 |
|
318 |
if (! empty($commentsWithinQuotes)) {
|
@@ -332,7 +364,6 @@ class CleanUp
|
|
332 |
public static function getOuterHTML($e)
|
333 |
{
|
334 |
$doc = new \DOMDocument();
|
335 |
-
|
336 |
libxml_use_internal_errors( true );
|
337 |
|
338 |
$doc->appendChild($doc->importNode($e, true));
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp;
|
3 |
|
4 |
+
use WpAssetCleanUp\OptimiseAssets\OptimizeCommon;
|
5 |
+
|
6 |
/**
|
7 |
* Class CleanUp
|
8 |
* @package WpAssetCleanUp
|
25 |
*/
|
26 |
public function doClean()
|
27 |
{
|
28 |
+
if (Plugin::preventAnyChanges() || Main::instance()->preventAssetsSettings()) {
|
29 |
return;
|
30 |
}
|
31 |
|
47 |
if ($settings['remove_rest_api_link'] == 1) {
|
48 |
// <link rel='https://api.w.org/' href='https://yourwebsite.com/wp-json/' />
|
49 |
remove_action('wp_head', 'rest_output_link_wp_head');
|
50 |
+
|
51 |
+
// Removes the following printed within "Response headers":
|
52 |
+
// <https://yourwebsite.com/wp-json/>; rel="https://api.w.org/"
|
53 |
+
remove_action( 'template_redirect', 'rest_output_link_header', 11 );
|
54 |
}
|
55 |
|
56 |
// Remove "Shortlink"?
|
60 |
|
61 |
// link: <https://yourdomainname.com/wp-json/>; rel="https://api.w.org/", <https://yourdomainname.com/?p=[post_id_here]>; rel=shortlink
|
62 |
remove_action('template_redirect', 'wp_shortlink_header', 11);
|
63 |
+
}
|
|
|
64 |
|
65 |
// Remove "Post's Relational Links"?
|
66 |
if ($settings['remove_posts_rel_links'] == 1) {
|
148 |
*/
|
149 |
public static function removeMetaGenerators($htmlSource)
|
150 |
{
|
151 |
+
$fetchMethod = 'dom'; // 'regex' or 'dom'
|
152 |
+
|
153 |
+
if ($fetchMethod === 'regex') {
|
154 |
+
preg_match_all(
|
155 |
+
'/<meta.*name=(|\'|")generator(\\1).*content=(|\'|")(.*?)(|\'|").*?>/i',
|
156 |
+
$htmlSource,
|
157 |
+
$matchesSourcesFromTags,
|
158 |
+
PREG_SET_ORDER
|
159 |
+
);
|
160 |
|
161 |
+
preg_match_all(
|
162 |
+
'/<meta.*content=(|\'|")(.*?)(\\1).*name=(|\'|")generator(\\2).*?>/i',
|
163 |
+
$htmlSource,
|
164 |
+
$matchesSourcesFromTagsTwo,
|
165 |
+
PREG_SET_ORDER
|
166 |
+
);
|
167 |
|
168 |
+
$matchesSourcesFromTags = array_merge($matchesSourcesFromTags, $matchesSourcesFromTagsTwo);
|
|
|
|
|
|
|
|
|
|
|
169 |
|
170 |
+
if (empty($matchesSourcesFromTags)) {
|
171 |
+
return $htmlSource;
|
172 |
+
}
|
173 |
|
174 |
+
$metaTagsToStrip = array();
|
175 |
|
176 |
+
foreach ($matchesSourcesFromTags as $matchesResults) {
|
177 |
+
if (isset($matchesResults[0]) && ($matchedTag = $matchesResults[0])) {
|
178 |
+
if (strip_tags($matchedTag) !== '') { // Needs to be a proper match (very rare cases, but it can happen)
|
179 |
+
continue;
|
180 |
+
}
|
181 |
|
182 |
+
$metaTagsToStrip[$matchedTag] = '';
|
183 |
+
}
|
184 |
+
}
|
185 |
|
186 |
+
$htmlSource = strtr($htmlSource, $metaTagsToStrip);
|
187 |
+
} elseif ($fetchMethod === 'dom') {
|
188 |
+
if ( function_exists( 'libxml_use_internal_errors' ) && function_exists( 'libxml_clear_errors' ) && class_exists( '\DOMDocument' ) ) {
|
189 |
+
if ($htmlSource === '') {
|
190 |
+
return $htmlSource;
|
191 |
+
}
|
192 |
|
193 |
+
$domTag = OptimizeCommon::getDomLoadedTag($htmlSource, 'removeMetaGenerators');
|
|
|
|
|
|
|
194 |
|
195 |
+
$metaTagsToStrip = array();
|
196 |
+
|
197 |
+
foreach ( $domTag->getElementsByTagName( 'meta' ) as $tagObject ) {
|
198 |
+
$nameAttrValue = $tagObject->getAttribute( 'name' );
|
199 |
+
|
200 |
+
if ( $nameAttrValue === 'generator' ) {
|
201 |
+
$outerTag = $outerTagRegExp = trim( self::getOuterHTML( $tagObject ) );
|
202 |
|
203 |
+
// As DOMDocument doesn't retrieve the exact string, some alterations to the RegEx have to be made
|
204 |
+
// Leave no room for errors as all sort of characters can be within the "content" attribute
|
205 |
+
$last2Chars = substr( $outerTag, - 2 );
|
206 |
|
207 |
+
if ( $last2Chars === '">' || $last2Chars === "'>" ) {
|
208 |
+
$tagWithoutLastChar = substr( $outerTag, 0, - 1 );
|
209 |
+
$outerTagRegExp = preg_quote( $tagWithoutLastChar, '/' ) . '(.*?)>';
|
210 |
}
|
211 |
|
212 |
+
$outerTagRegExp = str_replace(
|
213 |
+
array( '"', '<', '>' ),
|
214 |
+
array( '("|\'|)', '(<|<)', '(>|>)' ),
|
215 |
+
$outerTagRegExp
|
216 |
+
);
|
217 |
+
|
218 |
+
if ( strpos( $outerTagRegExp, '<meta' ) !== false ) {
|
219 |
+
preg_match_all( '#' . $outerTagRegExp . '#si', $htmlSource, $matches );
|
220 |
+
|
221 |
+
if ( isset( $matches[0][0] ) && ! empty( $matches[0][0] ) && strip_tags( $matches[0][0] ) === '' ) {
|
222 |
+
$metaTagsToStrip[$matches[0][0]] = '';
|
223 |
+
}
|
224 |
}
|
225 |
}
|
226 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
228 |
+
$htmlSource = strtr($htmlSource, $metaTagsToStrip);
|
|
|
229 |
|
230 |
+
libxml_clear_errors();
|
|
|
|
|
|
|
|
|
231 |
}
|
232 |
}
|
233 |
|
234 |
+
/* [wpacu_timing] */
|
235 |
+
Misc::scriptExecTimer( 'alter_html_source_for_remove_meta_generators',
|
236 |
+
'end' ); /* [/wpacu_timing] */
|
237 |
return $htmlSource;
|
238 |
}
|
239 |
|
240 |
/**
|
241 |
* @param $htmlSource
|
242 |
+
* @param bool $ignoreExceptions
|
243 |
+
* @param $for
|
244 |
*
|
245 |
+
* @return string|string[]
|
246 |
*/
|
247 |
+
public static function removeHtmlComments($htmlSource, $ignoreExceptions = false, $for = 'cleaner_dom_to_fetch')
|
248 |
{
|
249 |
// No comments? Do not continue
|
250 |
if (strpos($htmlSource, '<!--') === false) {
|
251 |
return $htmlSource;
|
252 |
}
|
253 |
|
254 |
+
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('\DOMDocument'))) {
|
|
|
|
|
|
|
255 |
return $htmlSource;
|
256 |
}
|
257 |
|
258 |
+
$domTag = '';
|
259 |
+
|
260 |
+
if ($for === 'cleaner_dom_to_fetch') {
|
261 |
+
$domTag = OptimizeCommon::getDomLoadedTag($htmlSource, 'removeHtmlComments');
|
262 |
+
}
|
263 |
+
|
264 |
+
if ($for === 'final_output') {
|
265 |
+
$domTag = OptimizeCommon::getDomLoadedTag($htmlSource, 'removeHtmlCommentsFinal');
|
266 |
+
}
|
267 |
|
268 |
+
if (! $domTag) {
|
269 |
+
return $htmlSource;
|
270 |
+
}
|
271 |
|
272 |
+
$xpathComments = new \DOMXPath($domTag);
|
273 |
$comments = $xpathComments->query('//comment()');
|
274 |
|
275 |
libxml_clear_errors();
|
306 |
}
|
307 |
}
|
308 |
|
309 |
+
$stripCommentsList = array();
|
310 |
+
|
311 |
foreach ($comments as $comment) {
|
312 |
+
$entireComment = '<!--' . $comment->nodeValue . '-->';
|
313 |
|
314 |
// Do not strip MSIE conditional comments
|
315 |
+
if ( strpos( $entireComment, '<!--<![endif]-->' ) !== false ||
|
316 |
+
preg_match( '#<!--\[if(.*?)]>(.*?)<!-->#si', $entireComment ) ||
|
317 |
+
preg_match( '#<!--\[if(.*?)\[endif]-->#si', $entireComment ) ) {
|
318 |
continue;
|
319 |
}
|
320 |
|
321 |
// Any exceptions set in "Strip HTML comments?" textarea?
|
322 |
+
// $ignoreExceptions has to be set to false (as it is by default)
|
323 |
+
if (! $ignoreExceptions && Main::instance()->settings['remove_html_comments_exceptions']) {
|
324 |
$removeHtmlCommentsExceptions = trim(Main::instance()->settings['remove_html_comments_exceptions']);
|
325 |
|
326 |
if (strpos($removeHtmlCommentsExceptions, "\n") !== false) {
|
336 |
}
|
337 |
}
|
338 |
|
339 |
+
if (strlen($entireComment) < 200) {
|
340 |
+
$stripCommentsList[ $entireComment ] = '';
|
341 |
+
} else {
|
342 |
+
$htmlSource = str_replace($entireComment, '', $htmlSource);
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
if (! empty($stripCommentsList)) {
|
347 |
+
$htmlSource = strtr( $htmlSource, $stripCommentsList );
|
348 |
}
|
349 |
|
350 |
if (! empty($commentsWithinQuotes)) {
|
364 |
public static function getOuterHTML($e)
|
365 |
{
|
366 |
$doc = new \DOMDocument();
|
|
|
367 |
libxml_use_internal_errors( true );
|
368 |
|
369 |
$doc->appendChild($doc->importNode($e, true));
|
classes/Debug.php
CHANGED
@@ -18,11 +18,13 @@ class Debug
|
|
18 |
add_action('wp_footer', array($this, 'showDebugOptions'), PHP_INT_MAX);
|
19 |
}
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
|
|
|
|
26 |
}
|
27 |
|
28 |
/**
|
@@ -178,9 +180,7 @@ class Debug
|
|
178 |
<li>From CSS file to Inline: {wpacu_alter_html_source_for_inline_css_exec_time}</li>
|
179 |
<li>Update Original to Optimized: {wpacu_alter_html_source_original_to_optimized_css_exec_time}</li>
|
180 |
<li>Preloads: {wpacu_alter_html_source_for_preload_css_exec_time}</li>
|
181 |
-
<!--
|
182 |
-
<!--<li>Dynamic Loaded CSS (if any): {wpacu_alter_html_source_for_dynamic_loaded_css_exec_time}</li>-->
|
183 |
-
<!-- endRemoveIf(development) -->
|
184 |
<li>Combine: {wpacu_alter_html_source_for_combine_css_exec_time}</li>
|
185 |
<li>Minify Inline Tags: {wpacu_alter_html_source_for_minify_inline_style_tags_exec_time}</li>
|
186 |
<li>Unload (ignore dependencies): {wpacu_alter_html_source_unload_ignore_deps_css_exec_time}</li>
|
@@ -191,9 +191,7 @@ class Debug
|
|
191 |
<ul>
|
192 |
<li>Update Original to Optimized: {wpacu_alter_html_source_original_to_optimized_js_exec_time}</li>
|
193 |
<li>Preloads: {wpacu_alter_html_source_for_preload_js_exec_time}</li>
|
194 |
-
<!--
|
195 |
-
<!--<li>Dynamic Loaded JS (if any): {wpacu_alter_html_source_for_dynamic_loaded_js_exec_time}</li>-->
|
196 |
-
<!-- endRemoveIf(development) -->
|
197 |
<li>Combine: {wpacu_alter_html_source_for_combine_js_exec_time}</li>
|
198 |
<li>Unload (ignore dependencies): {wpacu_alter_html_source_unload_ignore_deps_js_exec_time}</li>
|
199 |
<li>Move any inline wih jQuery code after jQuery library: {wpacu_alter_html_source_move_inline_jquery_after_src_tag_exec_time}</li>
|
18 |
add_action('wp_footer', array($this, 'showDebugOptions'), PHP_INT_MAX);
|
19 |
}
|
20 |
|
21 |
+
foreach(array('wp', 'admin_init') as $wpacuActionHook) {
|
22 |
+
add_action( $wpacuActionHook, static function() {
|
23 |
+
if ( isset( $_GET['wpacu_get_cache_dir_size'] ) && Menu::userCanManageAssets() ) {
|
24 |
+
self::printCacheDirInfo();
|
25 |
+
}
|
26 |
+
});
|
27 |
+
}
|
28 |
}
|
29 |
|
30 |
/**
|
180 |
<li>From CSS file to Inline: {wpacu_alter_html_source_for_inline_css_exec_time}</li>
|
181 |
<li>Update Original to Optimized: {wpacu_alter_html_source_original_to_optimized_css_exec_time}</li>
|
182 |
<li>Preloads: {wpacu_alter_html_source_for_preload_css_exec_time}</li>
|
183 |
+
<!-- -->
|
|
|
|
|
184 |
<li>Combine: {wpacu_alter_html_source_for_combine_css_exec_time}</li>
|
185 |
<li>Minify Inline Tags: {wpacu_alter_html_source_for_minify_inline_style_tags_exec_time}</li>
|
186 |
<li>Unload (ignore dependencies): {wpacu_alter_html_source_unload_ignore_deps_css_exec_time}</li>
|
191 |
<ul>
|
192 |
<li>Update Original to Optimized: {wpacu_alter_html_source_original_to_optimized_js_exec_time}</li>
|
193 |
<li>Preloads: {wpacu_alter_html_source_for_preload_js_exec_time}</li>
|
194 |
+
<!-- -->
|
|
|
|
|
195 |
<li>Combine: {wpacu_alter_html_source_for_combine_js_exec_time}</li>
|
196 |
<li>Unload (ignore dependencies): {wpacu_alter_html_source_unload_ignore_deps_js_exec_time}</li>
|
197 |
<li>Move any inline wih jQuery code after jQuery library: {wpacu_alter_html_source_move_inline_jquery_after_src_tag_exec_time}</li>
|
classes/HardcodedAssets.php
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp;
|
3 |
|
4 |
-
use WpAssetCleanUp\OptimiseAssets\MinifyJs;
|
5 |
use WpAssetCleanUp\OptimiseAssets\OptimizeCommon;
|
6 |
use WpAssetCleanUp\OptimiseAssets\OptimizeJs;
|
7 |
|
@@ -83,7 +82,7 @@ class HardcodedAssets
|
|
83 |
*/
|
84 |
public static function addHardcodedAssetsForEditFrontEndView($htmlSource)
|
85 |
{
|
86 |
-
if ( ! ($anyHardCodedAssets =
|
87 |
$htmlSource = str_replace( '{wpacu_assets_collapsible_wrap_hardcoded_list}', '', $htmlSource);
|
88 |
return $htmlSource;
|
89 |
}
|
@@ -91,7 +90,7 @@ class HardcodedAssets
|
|
91 |
$jsonH = base64_decode($anyHardCodedAssets);
|
92 |
|
93 |
$wpacuPrintHardcodedManagementList = static function($jsonH) {
|
94 |
-
$data =
|
95 |
$data['do_not_print_list'] = true;
|
96 |
$data['all']['hardcoded'] = (array)json_decode($jsonH, ARRAY_A);
|
97 |
ob_start();
|
@@ -126,7 +125,7 @@ class HardcodedAssets
|
|
126 |
*/
|
127 |
public static function getAll($htmlSource, $encodeIt = true)
|
128 |
{
|
129 |
-
$htmlSourceAlt =
|
130 |
|
131 |
$collectLinkStyles = true; // default
|
132 |
$collectScripts = true; // default
|
@@ -140,7 +139,6 @@ class HardcodedAssets
|
|
140 |
/*
|
141 |
* [START] Collect Hardcoded LINK (stylesheet) & STYLE tags
|
142 |
*/
|
143 |
-
// Extract all the LINK tag that do not have "data-wpacu-debug-style-handle="
|
144 |
preg_match_all( '#(?=(?P<link_tag><link[^>]*stylesheet[^>]*(>)))|(?=(?P<style_tag><style[^>]*?>.*</style>))#Umsi',
|
145 |
$htmlSourceAlt, $matchesSourcesFromTags, PREG_SET_ORDER );
|
146 |
|
@@ -246,7 +244,6 @@ class HardcodedAssets
|
|
246 |
}
|
247 |
|
248 |
$allInlineAssocWithJsHandle = array_unique($allInlineAssocWithJsHandle);
|
249 |
-
|
250 |
}
|
251 |
|
252 |
// Go through the hardcoded SCRIPT tags
|
@@ -370,7 +367,7 @@ class HardcodedAssets
|
|
370 |
|
371 |
if (self::useBufferingForEditFrontEndView()) {
|
372 |
// Triggered within the front-end view (when admin is logged-in and manages the assets)
|
373 |
-
|
374 |
} elseif (Main::instance()->isGetAssetsCall) {
|
375 |
// AJAX call within the Dashboard
|
376 |
$hardCodedAssets['within_conditional_comments'] = $tagsWithinConditionalComments;
|
@@ -388,6 +385,7 @@ class HardcodedAssets
|
|
388 |
*
|
389 |
* @return mixed
|
390 |
*/
|
|
|
391 |
public static function removeHtmlCommentsExceptMSIE($htmlSource)
|
392 |
{
|
393 |
// No comments? Do not continue
|
@@ -395,29 +393,28 @@ class HardcodedAssets
|
|
395 |
return $htmlSource;
|
396 |
}
|
397 |
|
398 |
-
if (! (function_exists('libxml_use_internal_errors')
|
399 |
-
&& function_exists('libxml_clear_errors')
|
400 |
-
&& class_exists('DOMDocument')))
|
401 |
-
{
|
402 |
return $htmlSource;
|
403 |
}
|
404 |
|
405 |
-
|
406 |
-
libxml_use_internal_errors(true);
|
407 |
-
|
408 |
preg_match_all('#<!--\[if(.*?)]>(<!-->|-->|\s|)(.*?)(<!--<!|<!)\[endif]-->#si', $htmlSource, $matchedMSIEComments);
|
409 |
|
410 |
-
$
|
411 |
|
412 |
if (isset($matchedMSIEComments[0]) && ! empty($matchedMSIEComments[0])) {
|
413 |
foreach ($matchedMSIEComments[0] as $matchedMSIEComment) {
|
414 |
-
$
|
415 |
}
|
416 |
}
|
417 |
|
418 |
-
|
|
|
|
|
|
|
|
|
419 |
|
420 |
-
$xpathComments = new \DOMXPath($
|
421 |
$comments = $xpathComments->query('//comment()');
|
422 |
|
423 |
libxml_clear_errors();
|
@@ -475,6 +472,8 @@ class HardcodedAssets
|
|
475 |
|
476 |
return $htmlSource;
|
477 |
}
|
|
|
|
|
478 |
|
479 |
/**
|
480 |
* @param $htmlSource
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp;
|
3 |
|
|
|
4 |
use WpAssetCleanUp\OptimiseAssets\OptimizeCommon;
|
5 |
use WpAssetCleanUp\OptimiseAssets\OptimizeJs;
|
6 |
|
82 |
*/
|
83 |
public static function addHardcodedAssetsForEditFrontEndView($htmlSource)
|
84 |
{
|
85 |
+
if ( ! ($anyHardCodedAssets = ObjectCache::wpacu_cache_get('wpacu_hardcoded_assets_encoded')) ) {
|
86 |
$htmlSource = str_replace( '{wpacu_assets_collapsible_wrap_hardcoded_list}', '', $htmlSource);
|
87 |
return $htmlSource;
|
88 |
}
|
90 |
$jsonH = base64_decode($anyHardCodedAssets);
|
91 |
|
92 |
$wpacuPrintHardcodedManagementList = static function($jsonH) {
|
93 |
+
$data = ObjectCache::wpacu_cache_get('wpacu_settings_frontend_data') ?: array();
|
94 |
$data['do_not_print_list'] = true;
|
95 |
$data['all']['hardcoded'] = (array)json_decode($jsonH, ARRAY_A);
|
96 |
ob_start();
|
125 |
*/
|
126 |
public static function getAll($htmlSource, $encodeIt = true)
|
127 |
{
|
128 |
+
$htmlSourceAlt = CleanUp::removeHtmlComments($htmlSource, true);
|
129 |
|
130 |
$collectLinkStyles = true; // default
|
131 |
$collectScripts = true; // default
|
139 |
/*
|
140 |
* [START] Collect Hardcoded LINK (stylesheet) & STYLE tags
|
141 |
*/
|
|
|
142 |
preg_match_all( '#(?=(?P<link_tag><link[^>]*stylesheet[^>]*(>)))|(?=(?P<style_tag><style[^>]*?>.*</style>))#Umsi',
|
143 |
$htmlSourceAlt, $matchesSourcesFromTags, PREG_SET_ORDER );
|
144 |
|
244 |
}
|
245 |
|
246 |
$allInlineAssocWithJsHandle = array_unique($allInlineAssocWithJsHandle);
|
|
|
247 |
}
|
248 |
|
249 |
// Go through the hardcoded SCRIPT tags
|
367 |
|
368 |
if (self::useBufferingForEditFrontEndView()) {
|
369 |
// Triggered within the front-end view (when admin is logged-in and manages the assets)
|
370 |
+
ObjectCache::wpacu_cache_set( 'wpacu_hardcoded_content_within_conditional_comments', $tagsWithinConditionalComments );
|
371 |
} elseif (Main::instance()->isGetAssetsCall) {
|
372 |
// AJAX call within the Dashboard
|
373 |
$hardCodedAssets['within_conditional_comments'] = $tagsWithinConditionalComments;
|
385 |
*
|
386 |
* @return mixed
|
387 |
*/
|
388 |
+
/*
|
389 |
public static function removeHtmlCommentsExceptMSIE($htmlSource)
|
390 |
{
|
391 |
// No comments? Do not continue
|
393 |
return $htmlSource;
|
394 |
}
|
395 |
|
396 |
+
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('\DOMDocument'))) {
|
|
|
|
|
|
|
397 |
return $htmlSource;
|
398 |
}
|
399 |
|
400 |
+
// First, collect all MSIE comments
|
|
|
|
|
401 |
preg_match_all('#<!--\[if(.*?)]>(<!-->|-->|\s|)(.*?)(<!--<!|<!)\[endif]-->#si', $htmlSource, $matchedMSIEComments);
|
402 |
|
403 |
+
$allMSIEComments = array();
|
404 |
|
405 |
if (isset($matchedMSIEComments[0]) && ! empty($matchedMSIEComments[0])) {
|
406 |
foreach ($matchedMSIEComments[0] as $matchedMSIEComment) {
|
407 |
+
$allMSIEComments[] = $matchedMSIEComment;
|
408 |
}
|
409 |
}
|
410 |
|
411 |
+
if (! ($domTag = ObjectCache::wpacu_cache_get('wpacu_html_dom_tag'))) {
|
412 |
+
$domTag = new \DOMDocument();
|
413 |
+
libxml_use_internal_errors( true );
|
414 |
+
$domTag->loadHTML( $htmlSource );
|
415 |
+
}
|
416 |
|
417 |
+
$xpathComments = new \DOMXPath($domTag);
|
418 |
$comments = $xpathComments->query('//comment()');
|
419 |
|
420 |
libxml_clear_errors();
|
472 |
|
473 |
return $htmlSource;
|
474 |
}
|
475 |
+
*/
|
476 |
+
//endRemoveIf(development)
|
477 |
|
478 |
/**
|
479 |
* @param $htmlSource
|
classes/ImportExport.php
CHANGED
@@ -265,7 +265,7 @@ SQL;
|
|
265 |
|
266 |
if (! empty($importedList)) {
|
267 |
// After import was completed, clear all CSS/JS cache
|
268 |
-
OptimizeCommon::
|
269 |
|
270 |
set_transient('wpacu_import_done', json_encode($importedList), 30);
|
271 |
|
265 |
|
266 |
if (! empty($importedList)) {
|
267 |
// After import was completed, clear all CSS/JS cache
|
268 |
+
OptimizeCommon::clearCache();
|
269 |
|
270 |
set_transient('wpacu_import_done', json_encode($importedList), 30);
|
271 |
|
classes/Main.php
CHANGED
@@ -258,7 +258,7 @@ class Main
|
|
258 |
// "Direct" AJAX call or "WP Remote Post" method used?
|
259 |
// Do not trigger the admin bar as it's not relevant
|
260 |
if ($this->isAjaxCall || $this->isGetAssetsCall) {
|
261 |
-
|
262 |
}
|
263 |
|
264 |
// This is triggered AFTER "saveSettings" from 'Settings' class
|
@@ -315,6 +315,10 @@ class Main
|
|
315 |
);
|
316 |
}
|
317 |
|
|
|
|
|
|
|
|
|
318 |
// Alter for debugging purposes; triggers before anything else
|
319 |
// e.g. you're working on a website and there is no Dashboard access and you want to determine the handle name
|
320 |
// if the handle name is not showing up, then the LINK stylesheet has been hardcoded (not enqueued the WordPress way)
|
@@ -322,25 +326,15 @@ class Main
|
|
322 |
$styleTag = str_replace('<link ', '<link data-wpacu-debug-style-handle=\'' . $tagHandle . '\' ', $styleTag);
|
323 |
}
|
324 |
|
325 |
-
if (strpos($styleTag, 'data-wpacu-style-handle') === false
|
326 |
-
|
327 |
-
&& self::instance()->isFrontendEditView) {
|
328 |
-
$styleTag = str_replace('<script ', '<script data-wpacu-style-handle=\'' . $tagHandle . '\' ', $styleTag);
|
329 |
}
|
330 |
|
331 |
-
|
332 |
-
return $styleTag;
|
333 |
-
}
|
334 |
-
|
335 |
-
if (strpos($styleTag, 'data-wpacu-style-handle') === false) {
|
336 |
-
$styleTag = str_replace( '<link ', '<link data-wpacu-style-handle=\'' . $tagHandle . '\' ', $styleTag );
|
337 |
-
}
|
338 |
-
|
339 |
-
return $styleTag;
|
340 |
}, 10, 2);
|
341 |
|
342 |
add_filter('script_loader_tag', static function($scriptTag, $tagHandle) {
|
343 |
-
|
344 |
// e.g. you're working on a website and there is no Dashboard access and you want to determine the handle name
|
345 |
// if the handle name is not showing up, then the SCRIPT has been hardcoded (not enqueued the WordPress way)
|
346 |
if (array_key_exists('wpacu_show_handle_names', $_GET)) {
|
@@ -369,7 +363,7 @@ class Main
|
|
369 |
$scriptTag = str_replace('<script ', '<script data-wpacu-jquery-migrate-handle=1 ', $scriptTag);
|
370 |
}
|
371 |
|
372 |
-
|
373 |
}, 10, 2);
|
374 |
|
375 |
Preloads::instance()->init();
|
@@ -427,7 +421,7 @@ SQL;
|
|
427 |
// Fetch the page in the background to see what scripts/styles are already loading
|
428 |
if ($this->isGetAssetsCall || $this->frontendShow()) {
|
429 |
if ($this->isGetAssetsCall) {
|
430 |
-
|
431 |
}
|
432 |
|
433 |
// Save CSS handles list that is printed in the <HEAD>
|
@@ -577,21 +571,21 @@ SQL;
|
|
577 |
global $wp_styles;
|
578 |
|
579 |
if (current_action() === 'wp_print_styles') {
|
580 |
-
|
581 |
}
|
582 |
|
583 |
$list = array();
|
584 |
|
585 |
if (current_action() === 'wp_print_footer_scripts') {
|
586 |
-
$cachedWpStyles =
|
587 |
if (isset($cachedWpStyles->registered) && count($cachedWpStyles->registered) === count($wp_styles->registered)) {
|
588 |
// The list was already generated in "wp_print_styles" and the number of registered assets are the same
|
589 |
// Save resources and do not re-generate it
|
590 |
-
$list =
|
591 |
}
|
592 |
}
|
593 |
|
594 |
-
if ( empty($list) ) {
|
595 |
// [wpacu_lite]
|
596 |
$nonAssetConfigPage = ( ! $this->isUpdateable && ! Misc::getShowOnFront() );
|
597 |
// [/wpacu_lite]
|
@@ -616,6 +610,10 @@ SQL;
|
|
616 |
$list = (array) $jsonList->styles;
|
617 |
}
|
618 |
|
|
|
|
|
|
|
|
|
619 |
// Any global unloaded styles? Append them
|
620 |
if ( ! empty( $globalUnload['styles'] ) ) {
|
621 |
foreach ( $globalUnload['styles'] as $handleStyle ) {
|
@@ -672,7 +670,7 @@ SQL;
|
|
672 |
}
|
673 |
|
674 |
if ( isset( $this->wpAllStyles['registered'] ) && ! empty( $this->wpAllStyles['registered'] ) ) {
|
675 |
-
|
676 |
}
|
677 |
|
678 |
// e.g. for test/debug mode or AJAX calls (where all assets have to load)
|
@@ -728,7 +726,8 @@ SQL;
|
|
728 |
$handle = trim($handle);
|
729 |
|
730 |
// Ignore auto generated handles for the hardcoded CSS as they were added for reference purposes
|
731 |
-
|
|
|
732 |
continue;
|
733 |
}
|
734 |
|
@@ -746,7 +745,7 @@ SQL;
|
|
746 |
}
|
747 |
|
748 |
if (current_action() === 'wp_print_styles') {
|
749 |
-
|
750 |
}
|
751 |
|
752 |
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_styles', 'end' ); /* [/wpacu_timing] */
|
@@ -862,17 +861,17 @@ SQL;
|
|
862 |
global $wp_scripts;
|
863 |
|
864 |
if (current_action() === 'wp_print_scripts') {
|
865 |
-
|
866 |
}
|
867 |
|
868 |
$list = array();
|
869 |
|
870 |
if (current_action() === 'wp_print_footer_scripts') {
|
871 |
-
$cachedWpScripts =
|
872 |
if (isset($cachedWpScripts->registered) && count($cachedWpScripts->registered) === count($wp_scripts->registered)) {
|
873 |
// The list was already generated in "wp_print_scripts" and the number of registered assets are the same
|
874 |
// Save resources and do not re-generate it
|
875 |
-
$list =
|
876 |
}
|
877 |
}
|
878 |
|
@@ -983,7 +982,6 @@ SQL;
|
|
983 |
if ( empty( $list ) ) {
|
984 |
/* [wpacu_timing] */
|
985 |
Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
986 |
-
|
987 |
return;
|
988 |
}
|
989 |
|
@@ -991,7 +989,6 @@ SQL;
|
|
991 |
if ( array_key_exists( 'wpacu_no_js_unload', $_GET ) || $this->preventAssetsSettings() ) {
|
992 |
/* [wpacu_timing] */
|
993 |
Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
994 |
-
|
995 |
return;
|
996 |
}
|
997 |
}
|
@@ -1001,6 +998,10 @@ SQL;
|
|
1001 |
foreach ($list as $handle) {
|
1002 |
$handle = trim($handle);
|
1003 |
|
|
|
|
|
|
|
|
|
1004 |
// Special Action for 'jquery-migrate' handler as its tied to 'jquery'
|
1005 |
if ($handle === 'jquery-migrate' && isset($this->wpAllScripts['registered']['jquery'])) {
|
1006 |
$jQueryRegScript = $this->wpAllScripts['registered']['jquery'];
|
@@ -1016,10 +1017,6 @@ SQL;
|
|
1016 |
continue;
|
1017 |
}
|
1018 |
|
1019 |
-
if (array_key_exists('wpacu_debug', $_GET)) {
|
1020 |
-
$this->allUnloadedAssets['js'][] = $handle;
|
1021 |
-
}
|
1022 |
-
|
1023 |
if (isset($ignoreChildParentList['scripts'], $this->wpAllScripts['registered'][$handle]->src) && is_array($ignoreChildParentList['scripts']) && array_key_exists($handle, $ignoreChildParentList['scripts'])) {
|
1024 |
// Do not dequeue it as it's "children" will also be dequeued (ignore rule is applied)
|
1025 |
// It will be stripped by cleaning its SCRIPT tag from the HTML Source
|
@@ -1042,7 +1039,7 @@ SQL;
|
|
1042 |
}
|
1043 |
|
1044 |
if (current_action() === 'wp_print_scripts') {
|
1045 |
-
|
1046 |
}
|
1047 |
|
1048 |
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
@@ -1555,6 +1552,8 @@ SQL;
|
|
1555 |
return;
|
1556 |
}
|
1557 |
|
|
|
|
|
1558 |
// Prevent plugins from altering the DOM
|
1559 |
add_filter('w3tc_minify_enable', '__return_false');
|
1560 |
|
@@ -1834,7 +1833,7 @@ SQL;
|
|
1834 |
|
1835 |
$data['ignore_child'] = $this->getIgnoreChildren();
|
1836 |
|
1837 |
-
|
1838 |
$this->parseTemplate('settings-frontend', $data, true);
|
1839 |
} elseif ($isDashboardEditView) {
|
1840 |
// AJAX call (not the classic WP one) from the WP Dashboard
|
@@ -1863,6 +1862,8 @@ SQL;
|
|
1863 |
exit();
|
1864 |
});
|
1865 |
}
|
|
|
|
|
1866 |
}
|
1867 |
|
1868 |
/**
|
@@ -2000,17 +2001,11 @@ SQL;
|
|
2000 |
$data['all']['hardcoded'] = (array) json_decode( $jsonH, ARRAY_A );
|
2001 |
|
2002 |
if (isset($data['all']['hardcoded']['within_conditional_comments']) && ! empty($data['all']['hardcoded']['within_conditional_comments'])) {
|
2003 |
-
|
2004 |
}
|
2005 |
}
|
2006 |
// [END] Hardcoded (if any)
|
2007 |
|
2008 |
-
// [wpacu_pro]
|
2009 |
-
if (isset($data['all']['unloaded_plugins']) && ! empty($data['all']['unloaded_plugins'])) {
|
2010 |
-
wp_cache_add('wpacu_filtered_plugins', $data['all']['unloaded_plugins']);
|
2011 |
-
}
|
2012 |
-
// [/wpacu_pro]
|
2013 |
-
|
2014 |
if ($data['plugin_settings']['assets_list_layout'] === 'by-location') {
|
2015 |
$data['all'] = Sorting::appendLocation($data['all']);
|
2016 |
} else {
|
@@ -2241,7 +2236,7 @@ SQL;
|
|
2241 |
$data['all']['scripts'][$key]->wp = false;
|
2242 |
}
|
2243 |
|
2244 |
-
$initialScriptPos =
|
2245 |
|
2246 |
if ($initialScriptPos === 'body' || in_array($obj->handle, $this->assetsInFooter['scripts'])) {
|
2247 |
$data['all']['scripts'][$key]->position = 'body';
|
@@ -2411,7 +2406,7 @@ SQL;
|
|
2411 |
} else {
|
2412 |
if ($wooCommerceShopPageId > 0 && Misc::isHomePage() && strpos(get_site_url(), '://') !== false) {
|
2413 |
list($siteUrlAfterProtocol) = explode('://', get_site_url());
|
2414 |
-
$currentPageUrlAfterProtocol =
|
2415 |
|
2416 |
if ($siteUrlAfterProtocol != $currentPageUrlAfterProtocol && (strpos($siteUrlAfterProtocol,
|
2417 |
'/shop') !== false)
|
258 |
// "Direct" AJAX call or "WP Remote Post" method used?
|
259 |
// Do not trigger the admin bar as it's not relevant
|
260 |
if ($this->isAjaxCall || $this->isGetAssetsCall) {
|
261 |
+
add_filter('show_admin_bar', '__return_false');
|
262 |
}
|
263 |
|
264 |
// This is triggered AFTER "saveSettings" from 'Settings' class
|
315 |
);
|
316 |
}
|
317 |
|
318 |
+
if ( Plugin::preventAnyChanges() || self::isTestModeActive() ) {
|
319 |
+
return $styleTag;
|
320 |
+
}
|
321 |
+
|
322 |
// Alter for debugging purposes; triggers before anything else
|
323 |
// e.g. you're working on a website and there is no Dashboard access and you want to determine the handle name
|
324 |
// if the handle name is not showing up, then the LINK stylesheet has been hardcoded (not enqueued the WordPress way)
|
326 |
$styleTag = str_replace('<link ', '<link data-wpacu-debug-style-handle=\'' . $tagHandle . '\' ', $styleTag);
|
327 |
}
|
328 |
|
329 |
+
if (strpos($styleTag, 'data-wpacu-style-handle') === false) {
|
330 |
+
$styleTag = str_replace('<link ', '<link data-wpacu-style-handle=\'' . $tagHandle . '\' ', $styleTag);
|
|
|
|
|
331 |
}
|
332 |
|
333 |
+
return $styleTag;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
}, 10, 2);
|
335 |
|
336 |
add_filter('script_loader_tag', static function($scriptTag, $tagHandle) {
|
337 |
+
// Alter for debugging purposes; triggers before anything else
|
338 |
// e.g. you're working on a website and there is no Dashboard access and you want to determine the handle name
|
339 |
// if the handle name is not showing up, then the SCRIPT has been hardcoded (not enqueued the WordPress way)
|
340 |
if (array_key_exists('wpacu_show_handle_names', $_GET)) {
|
363 |
$scriptTag = str_replace('<script ', '<script data-wpacu-jquery-migrate-handle=1 ', $scriptTag);
|
364 |
}
|
365 |
|
366 |
+
return $scriptTag;
|
367 |
}, 10, 2);
|
368 |
|
369 |
Preloads::instance()->init();
|
421 |
// Fetch the page in the background to see what scripts/styles are already loading
|
422 |
if ($this->isGetAssetsCall || $this->frontendShow()) {
|
423 |
if ($this->isGetAssetsCall) {
|
424 |
+
add_filter('show_admin_bar', '__return_false');
|
425 |
}
|
426 |
|
427 |
// Save CSS handles list that is printed in the <HEAD>
|
571 |
global $wp_styles;
|
572 |
|
573 |
if (current_action() === 'wp_print_styles') {
|
574 |
+
ObjectCache::wpacu_cache_set('wpacu_styles_object_after_wp_print_styles', $wp_styles);
|
575 |
}
|
576 |
|
577 |
$list = array();
|
578 |
|
579 |
if (current_action() === 'wp_print_footer_scripts') {
|
580 |
+
$cachedWpStyles = ObjectCache::wpacu_cache_get('wpacu_styles_object_after_wp_print_styles');
|
581 |
if (isset($cachedWpStyles->registered) && count($cachedWpStyles->registered) === count($wp_styles->registered)) {
|
582 |
// The list was already generated in "wp_print_styles" and the number of registered assets are the same
|
583 |
// Save resources and do not re-generate it
|
584 |
+
$list = ObjectCache::wpacu_cache_get('wpacu_styles_handles_marked_for_unload');
|
585 |
}
|
586 |
}
|
587 |
|
588 |
+
if ( empty($list) || ! is_array($list) ) {
|
589 |
// [wpacu_lite]
|
590 |
$nonAssetConfigPage = ( ! $this->isUpdateable && ! Misc::getShowOnFront() );
|
591 |
// [/wpacu_lite]
|
610 |
$list = (array) $jsonList->styles;
|
611 |
}
|
612 |
|
613 |
+
if (! is_array($list)) {
|
614 |
+
$list = array();
|
615 |
+
}
|
616 |
+
|
617 |
// Any global unloaded styles? Append them
|
618 |
if ( ! empty( $globalUnload['styles'] ) ) {
|
619 |
foreach ( $globalUnload['styles'] as $handleStyle ) {
|
670 |
}
|
671 |
|
672 |
if ( isset( $this->wpAllStyles['registered'] ) && ! empty( $this->wpAllStyles['registered'] ) ) {
|
673 |
+
ObjectCache::wpacu_cache_set( 'wpacu_all_styles_handles', array_keys( $this->wpAllStyles['registered'] ) );
|
674 |
}
|
675 |
|
676 |
// e.g. for test/debug mode or AJAX calls (where all assets have to load)
|
726 |
$handle = trim($handle);
|
727 |
|
728 |
// Ignore auto generated handles for the hardcoded CSS as they were added for reference purposes
|
729 |
+
// They will get stripped later on via OptimizeCommon.php
|
730 |
+
if (strpos($handle, 'wpacu_hardcoded_link_') === 0) {
|
731 |
continue;
|
732 |
}
|
733 |
|
745 |
}
|
746 |
|
747 |
if (current_action() === 'wp_print_styles') {
|
748 |
+
ObjectCache::wpacu_cache_set( 'wpacu_styles_handles_marked_for_unload', $list );
|
749 |
}
|
750 |
|
751 |
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_styles', 'end' ); /* [/wpacu_timing] */
|
861 |
global $wp_scripts;
|
862 |
|
863 |
if (current_action() === 'wp_print_scripts') {
|
864 |
+
ObjectCache::wpacu_cache_set('wpacu_scripts_object_after_wp_print_scripts', $wp_scripts);
|
865 |
}
|
866 |
|
867 |
$list = array();
|
868 |
|
869 |
if (current_action() === 'wp_print_footer_scripts') {
|
870 |
+
$cachedWpScripts = ObjectCache::wpacu_cache_get('wpacu_scripts_object_after_wp_print_scripts');
|
871 |
if (isset($cachedWpScripts->registered) && count($cachedWpScripts->registered) === count($wp_scripts->registered)) {
|
872 |
// The list was already generated in "wp_print_scripts" and the number of registered assets are the same
|
873 |
// Save resources and do not re-generate it
|
874 |
+
$list = ObjectCache::wpacu_cache_get('wpacu_scripts_handles_marked_for_unload');
|
875 |
}
|
876 |
}
|
877 |
|
982 |
if ( empty( $list ) ) {
|
983 |
/* [wpacu_timing] */
|
984 |
Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
|
|
985 |
return;
|
986 |
}
|
987 |
|
989 |
if ( array_key_exists( 'wpacu_no_js_unload', $_GET ) || $this->preventAssetsSettings() ) {
|
990 |
/* [wpacu_timing] */
|
991 |
Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
|
|
992 |
return;
|
993 |
}
|
994 |
}
|
998 |
foreach ($list as $handle) {
|
999 |
$handle = trim($handle);
|
1000 |
|
1001 |
+
if (array_key_exists('wpacu_debug', $_GET)) {
|
1002 |
+
$this->allUnloadedAssets['js'][] = $handle;
|
1003 |
+
}
|
1004 |
+
|
1005 |
// Special Action for 'jquery-migrate' handler as its tied to 'jquery'
|
1006 |
if ($handle === 'jquery-migrate' && isset($this->wpAllScripts['registered']['jquery'])) {
|
1007 |
$jQueryRegScript = $this->wpAllScripts['registered']['jquery'];
|
1017 |
continue;
|
1018 |
}
|
1019 |
|
|
|
|
|
|
|
|
|
1020 |
if (isset($ignoreChildParentList['scripts'], $this->wpAllScripts['registered'][$handle]->src) && is_array($ignoreChildParentList['scripts']) && array_key_exists($handle, $ignoreChildParentList['scripts'])) {
|
1021 |
// Do not dequeue it as it's "children" will also be dequeued (ignore rule is applied)
|
1022 |
// It will be stripped by cleaning its SCRIPT tag from the HTML Source
|
1039 |
}
|
1040 |
|
1041 |
if (current_action() === 'wp_print_scripts') {
|
1042 |
+
ObjectCache::wpacu_cache_set( 'wpacu_scripts_handles_marked_for_unload', $list );
|
1043 |
}
|
1044 |
|
1045 |
/* [wpacu_timing] */ Misc::scriptExecTimer( 'filter_dequeue_scripts', 'end' ); /* [/wpacu_timing] */
|
1552 |
return;
|
1553 |
}
|
1554 |
|
1555 |
+
/* [wpacu_timing] */ $wpacuTimingName = 'output_css_js_manager'; Misc::scriptExecTimer($wpacuTimingName); /* [/wpacu_timing] */
|
1556 |
+
|
1557 |
// Prevent plugins from altering the DOM
|
1558 |
add_filter('w3tc_minify_enable', '__return_false');
|
1559 |
|
1833 |
|
1834 |
$data['ignore_child'] = $this->getIgnoreChildren();
|
1835 |
|
1836 |
+
ObjectCache::wpacu_cache_set('wpacu_settings_frontend_data', $data);
|
1837 |
$this->parseTemplate('settings-frontend', $data, true);
|
1838 |
} elseif ($isDashboardEditView) {
|
1839 |
// AJAX call (not the classic WP one) from the WP Dashboard
|
1862 |
exit();
|
1863 |
});
|
1864 |
}
|
1865 |
+
|
1866 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
1867 |
}
|
1868 |
|
1869 |
/**
|
2001 |
$data['all']['hardcoded'] = (array) json_decode( $jsonH, ARRAY_A );
|
2002 |
|
2003 |
if (isset($data['all']['hardcoded']['within_conditional_comments']) && ! empty($data['all']['hardcoded']['within_conditional_comments'])) {
|
2004 |
+
ObjectCache::wpacu_cache_set( 'wpacu_hardcoded_content_within_conditional_comments', $data['all']['hardcoded']['within_conditional_comments'] );
|
2005 |
}
|
2006 |
}
|
2007 |
// [END] Hardcoded (if any)
|
2008 |
|
|
|
|
|
|
|
|
|
|
|
|
|
2009 |
if ($data['plugin_settings']['assets_list_layout'] === 'by-location') {
|
2010 |
$data['all'] = Sorting::appendLocation($data['all']);
|
2011 |
} else {
|
2236 |
$data['all']['scripts'][$key]->wp = false;
|
2237 |
}
|
2238 |
|
2239 |
+
$initialScriptPos = ObjectCache::wpacu_cache_get($obj->handle, 'wpacu_scripts_initial_positions');
|
2240 |
|
2241 |
if ($initialScriptPos === 'body' || in_array($obj->handle, $this->assetsInFooter['scripts'])) {
|
2242 |
$data['all']['scripts'][$key]->position = 'body';
|
2406 |
} else {
|
2407 |
if ($wooCommerceShopPageId > 0 && Misc::isHomePage() && strpos(get_site_url(), '://') !== false) {
|
2408 |
list($siteUrlAfterProtocol) = explode('://', get_site_url());
|
2409 |
+
$currentPageUrlAfterProtocol = parse_url(site_url(), PHP_URL_HOST) . $_SERVER['REQUEST_URI'];
|
2410 |
|
2411 |
if ($siteUrlAfterProtocol != $currentPageUrlAfterProtocol && (strpos($siteUrlAfterProtocol,
|
2412 |
'/shop') !== false)
|
classes/Misc.php
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp;
|
3 |
|
|
|
|
|
4 |
/**
|
5 |
* Class Misc
|
6 |
* contains various common functions that are used by the plugin
|
@@ -31,16 +33,6 @@ class Misc
|
|
31 |
*/
|
32 |
public $activeCachePlugins = array();
|
33 |
|
34 |
-
/**
|
35 |
-
* Misc constructor.
|
36 |
-
*/
|
37 |
-
public function __construct()
|
38 |
-
{
|
39 |
-
if (isset($_REQUEST['wpacuNoAdminBar'])) {
|
40 |
-
self::noAdminBarLoad();
|
41 |
-
}
|
42 |
-
}
|
43 |
-
|
44 |
/**
|
45 |
* @var
|
46 |
*/
|
@@ -336,6 +328,50 @@ class Misc
|
|
336 |
return array();
|
337 |
}
|
338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
/**
|
340 |
* @return bool
|
341 |
*/
|
@@ -356,14 +392,6 @@ class Misc
|
|
356 |
return self::$showOnFront;
|
357 |
}
|
358 |
|
359 |
-
/**
|
360 |
-
*
|
361 |
-
*/
|
362 |
-
public static function noAdminBarLoad()
|
363 |
-
{
|
364 |
-
add_filter('show_admin_bar', '__return_false');
|
365 |
-
}
|
366 |
-
|
367 |
/**
|
368 |
* @param $plugin
|
369 |
*
|
@@ -418,12 +446,12 @@ class Misc
|
|
418 |
*/
|
419 |
public static function getW3tcMasterConfig()
|
420 |
{
|
421 |
-
if (!
|
422 |
$w3tcConfigMasterFile = WP_CONTENT_DIR . '/w3tc-config/master.php';
|
423 |
$w3tcMasterConfig = FileSystem::file_get_contents($w3tcConfigMasterFile);
|
424 |
-
|
425 |
} else {
|
426 |
-
$w3tcMasterConfig =
|
427 |
}
|
428 |
|
429 |
return $w3tcMasterConfig;
|
@@ -721,8 +749,8 @@ SQL;
|
|
721 |
|
722 |
$relSrc = str_replace( site_url(), '', $srcAlt );
|
723 |
|
724 |
-
if (strpos($relSrc, '/wp-content/plugins') !==
|
725 |
-
list (,$relSrc) =
|
726 |
}
|
727 |
|
728 |
if (strpos($relSrc, $relPluginsUrl) !== false) {
|
@@ -1071,16 +1099,10 @@ SQL;
|
|
1071 |
|
1072 |
if ($action === 'start') {
|
1073 |
$startTime = (microtime(true) * 1000);
|
1074 |
-
|
1075 |
-
// Do not overwrite it if it's already there (e.g. in a function called several times)
|
1076 |
-
if (wp_cache_get($wpacuStartTimeName, 'wpacu_exec_time')) {
|
1077 |
-
return '';
|
1078 |
-
}
|
1079 |
-
|
1080 |
-
wp_cache_set($wpacuStartTimeName, $startTime, 'wpacu_exec_time');
|
1081 |
}
|
1082 |
|
1083 |
-
if ($action === 'end' && ($startTime =
|
1084 |
// End clock time in seconds
|
1085 |
$endTime = (microtime(true) * 1000);
|
1086 |
$scriptExecTime = ($endTime !== $startTime && $endTime > $startTime) ? ($endTime - $startTime) : 0;
|
@@ -1088,11 +1110,11 @@ SQL;
|
|
1088 |
// Calculate script execution time
|
1089 |
// Is there an existing exec time (e.g. from a function called several times)?
|
1090 |
// Append it to the total execution time
|
1091 |
-
if ($scriptExecTimeExisting =
|
1092 |
$scriptExecTime += $scriptExecTimeExisting;
|
1093 |
}
|
1094 |
|
1095 |
-
|
1096 |
return $scriptExecTime;
|
1097 |
}
|
1098 |
|
@@ -1106,10 +1128,10 @@ SQL;
|
|
1106 |
*/
|
1107 |
public static function getTimingValues($wpacuCacheKey)
|
1108 |
{
|
1109 |
-
$wpacuExecTiming =
|
1110 |
|
1111 |
$wpacuTimingFormatMs = str_replace('.00', '', number_format($wpacuExecTiming, 2));
|
1112 |
-
$wpacuTimingFormatS = str_replace('.00', '', number_format(($wpacuExecTiming / 1000), 3));
|
1113 |
|
1114 |
return array('ms' => $wpacuTimingFormatMs, 's' => $wpacuTimingFormatS);
|
1115 |
}
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp;
|
3 |
|
4 |
+
use WpAssetCleanUp\OptimiseAssets\OptimizeCommon;
|
5 |
+
|
6 |
/**
|
7 |
* Class Misc
|
8 |
* contains various common functions that are used by the plugin
|
33 |
*/
|
34 |
public $activeCachePlugins = array();
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
/**
|
37 |
* @var
|
38 |
*/
|
328 |
return array();
|
329 |
}
|
330 |
|
331 |
+
/**
|
332 |
+
* @param bool $clean
|
333 |
+
*
|
334 |
+
* @return mixed|string
|
335 |
+
*/
|
336 |
+
public static function getCurrentPageUrl($clean = true)
|
337 |
+
{
|
338 |
+
$currentPageUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . '://' . parse_url(site_url(), PHP_URL_HOST) . $_SERVER['REQUEST_URI'];
|
339 |
+
|
340 |
+
if ($clean && strpos($currentPageUrl, '?') !== false) {
|
341 |
+
list($currentPageUrl) = explode('?', $currentPageUrl);
|
342 |
+
}
|
343 |
+
|
344 |
+
return $currentPageUrl;
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* @param $src
|
349 |
+
* @param $assetKey
|
350 |
+
*
|
351 |
+
* @return string|string[]
|
352 |
+
*/
|
353 |
+
public static function assetFromHrefToRelativeUri($src, $assetKey)
|
354 |
+
{
|
355 |
+
// Make the "src" relative in case the information will be imported from Staging to Live, it won't show the handle's link referencing to the staging URL in the "Overview" page and other similar pages as it's confusing
|
356 |
+
$localAssetPath = OptimizeCommon::getLocalAssetPath($src, (($assetKey === 'styles') ? 'css' : 'js'));
|
357 |
+
|
358 |
+
$relSrc = $src;
|
359 |
+
|
360 |
+
if ($localAssetPath) {
|
361 |
+
$relSrc = str_replace(ABSPATH, '', $relSrc);
|
362 |
+
}
|
363 |
+
|
364 |
+
$relSrc = str_replace(site_url(), '', $relSrc);
|
365 |
+
|
366 |
+
// Does it start with '//'? (protocol is missing) - the replacement above wasn't made
|
367 |
+
if (strpos($relSrc, '//') === 0) {
|
368 |
+
$siteUrlNoProtocol = str_replace(array('http:', 'https:'), '', site_url());
|
369 |
+
$relSrc = str_replace($siteUrlNoProtocol, '', $relSrc);
|
370 |
+
}
|
371 |
+
|
372 |
+
return $relSrc;
|
373 |
+
}
|
374 |
+
|
375 |
/**
|
376 |
* @return bool
|
377 |
*/
|
392 |
return self::$showOnFront;
|
393 |
}
|
394 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
/**
|
396 |
* @param $plugin
|
397 |
*
|
446 |
*/
|
447 |
public static function getW3tcMasterConfig()
|
448 |
{
|
449 |
+
if (! ObjectCache::wpacu_cache_get('wpacu_w3tc_master_config')) {
|
450 |
$w3tcConfigMasterFile = WP_CONTENT_DIR . '/w3tc-config/master.php';
|
451 |
$w3tcMasterConfig = FileSystem::file_get_contents($w3tcConfigMasterFile);
|
452 |
+
ObjectCache::wpacu_cache_set('wpacu_w3tc_master_config', trim($w3tcMasterConfig));
|
453 |
} else {
|
454 |
+
$w3tcMasterConfig = ObjectCache::wpacu_cache_get('wpacu_w3tc_master_config');
|
455 |
}
|
456 |
|
457 |
return $w3tcMasterConfig;
|
749 |
|
750 |
$relSrc = str_replace( site_url(), '', $srcAlt );
|
751 |
|
752 |
+
if (strpos($relSrc, '/wp-content/plugins') !== false) {
|
753 |
+
list (,$relSrc) = explode('/wp-content/plugins', $relSrc);
|
754 |
}
|
755 |
|
756 |
if (strpos($relSrc, $relPluginsUrl) !== false) {
|
1099 |
|
1100 |
if ($action === 'start') {
|
1101 |
$startTime = (microtime(true) * 1000);
|
1102 |
+
ObjectCache::wpacu_cache_set($wpacuStartTimeName, $startTime, 'wpacu_exec_time');
|
|
|
|
|
|
|
|
|
|
|
|
|
1103 |
}
|
1104 |
|
1105 |
+
if ($action === 'end' && ($startTime = ObjectCache::wpacu_cache_get($wpacuStartTimeName, 'wpacu_exec_time'))) {
|
1106 |
// End clock time in seconds
|
1107 |
$endTime = (microtime(true) * 1000);
|
1108 |
$scriptExecTime = ($endTime !== $startTime && $endTime > $startTime) ? ($endTime - $startTime) : 0;
|
1110 |
// Calculate script execution time
|
1111 |
// Is there an existing exec time (e.g. from a function called several times)?
|
1112 |
// Append it to the total execution time
|
1113 |
+
if ($scriptExecTimeExisting = ObjectCache::wpacu_cache_get($wpacuExecTimeName, 'wpacu_exec_time')) {
|
1114 |
$scriptExecTime += $scriptExecTimeExisting;
|
1115 |
}
|
1116 |
|
1117 |
+
ObjectCache::wpacu_cache_set($wpacuExecTimeName, $scriptExecTime, 'wpacu_exec_time');
|
1118 |
return $scriptExecTime;
|
1119 |
}
|
1120 |
|
1128 |
*/
|
1129 |
public static function getTimingValues($wpacuCacheKey)
|
1130 |
{
|
1131 |
+
$wpacuExecTiming = ObjectCache::wpacu_cache_get( $wpacuCacheKey, 'wpacu_exec_time' ) ?: 0;
|
1132 |
|
1133 |
$wpacuTimingFormatMs = str_replace('.00', '', number_format($wpacuExecTiming, 2));
|
1134 |
+
$wpacuTimingFormatS = str_replace(array('.00', ','), '', number_format(($wpacuExecTiming / 1000), 3));
|
1135 |
|
1136 |
return array('ms' => $wpacuTimingFormatMs, 's' => $wpacuTimingFormatS);
|
1137 |
}
|
classes/ObjectCache.php
ADDED
@@ -0,0 +1,750 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WpAssetCleanUp;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* NOTE: This is from the original core file located /wp-includes/class-wp-object-cache.php
|
6 |
+
* Avoid the WordPress core $wp_object_cache global variable which is sometimes altered by 3rd party plugins
|
7 |
+
* This would make this plugin compatible with plugins such as "Redis Object Cache"
|
8 |
+
*
|
9 |
+
* Object Cache API: ObjectCache class
|
10 |
+
*
|
11 |
+
* @package WordPress
|
12 |
+
* @subpackage Cache
|
13 |
+
* @since 5.4.0
|
14 |
+
*/
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Core class that implements an object cache.
|
18 |
+
*
|
19 |
+
* The WordPress Object Cache is used to save on trips to the database. The
|
20 |
+
* Object Cache stores all of the cache data to memory and makes the cache
|
21 |
+
* contents available by using a key, which is used to name and later retrieve
|
22 |
+
* the cache contents.
|
23 |
+
*
|
24 |
+
* The Object Cache can be replaced by other caching mechanisms by placing files
|
25 |
+
* in the wp-content folder which is looked at in wp-settings. If that file
|
26 |
+
* exists, then this file will not be included.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*/
|
30 |
+
class ObjectCache {
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Holds the cached objects.
|
34 |
+
*
|
35 |
+
* @since 2.0.0
|
36 |
+
* @var array
|
37 |
+
*/
|
38 |
+
private $cache = array();
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The amount of times the cache data was already stored in the cache.
|
42 |
+
*
|
43 |
+
* @since 2.5.0
|
44 |
+
* @var int
|
45 |
+
*/
|
46 |
+
public $cache_hits = 0;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Amount of times the cache did not have the request in cache.
|
50 |
+
*
|
51 |
+
* @since 2.0.0
|
52 |
+
* @var int
|
53 |
+
*/
|
54 |
+
public $cache_misses = 0;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* List of global cache groups.
|
58 |
+
*
|
59 |
+
* @since 3.0.0
|
60 |
+
* @var array
|
61 |
+
*/
|
62 |
+
protected $global_groups = array();
|
63 |
+
|
64 |
+
/**
|
65 |
+
* The blog prefix to prepend to keys in non-global groups.
|
66 |
+
*
|
67 |
+
* @since 3.5.0
|
68 |
+
* @var string
|
69 |
+
*/
|
70 |
+
private $blog_prefix;
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Holds the value of is_multisite().
|
74 |
+
*
|
75 |
+
* @since 3.5.0
|
76 |
+
* @var bool
|
77 |
+
*/
|
78 |
+
private $multisite;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Sets up object properties; PHP 5 style constructor.
|
82 |
+
*
|
83 |
+
* @since 2.0.8
|
84 |
+
*/
|
85 |
+
public function __construct() {
|
86 |
+
$this->multisite = is_multisite();
|
87 |
+
$this->blog_prefix = $this->multisite ? get_current_blog_id() . ':' : '';
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Makes private properties readable for backward compatibility.
|
92 |
+
*
|
93 |
+
* @since 4.0.0
|
94 |
+
*
|
95 |
+
* @param string $name Property to get.
|
96 |
+
* @return mixed Property.
|
97 |
+
*/
|
98 |
+
public function __get( $name ) {
|
99 |
+
return $this->$name;
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Makes private properties settable for backward compatibility.
|
104 |
+
*
|
105 |
+
* @since 4.0.0
|
106 |
+
*
|
107 |
+
* @param string $name Property to set.
|
108 |
+
* @param mixed $value Property value.
|
109 |
+
* @return mixed Newly-set property.
|
110 |
+
*/
|
111 |
+
public function __set( $name, $value ) {
|
112 |
+
return $this->$name = $value;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Makes private properties checkable for backward compatibility.
|
117 |
+
*
|
118 |
+
* @since 4.0.0
|
119 |
+
*
|
120 |
+
* @param string $name Property to check if set.
|
121 |
+
* @return bool Whether the property is set.
|
122 |
+
*/
|
123 |
+
public function __isset( $name ) {
|
124 |
+
return isset( $this->$name );
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Makes private properties un-settable for backward compatibility.
|
129 |
+
*
|
130 |
+
* @since 4.0.0
|
131 |
+
*
|
132 |
+
* @param string $name Property to unset.
|
133 |
+
*/
|
134 |
+
public function __unset( $name ) {
|
135 |
+
unset( $this->$name );
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Adds data to the cache if it doesn't already exist.
|
140 |
+
*
|
141 |
+
* @since 2.0.0
|
142 |
+
*
|
143 |
+
* @uses ObjectCache::_exists() Checks to see if the cache already has data.
|
144 |
+
* @uses ObjectCache::set() Sets the data after the checking the cache
|
145 |
+
* contents existence.
|
146 |
+
*
|
147 |
+
* @param int|string $key What to call the contents in the cache.
|
148 |
+
* @param mixed $data The contents to store in the cache.
|
149 |
+
* @param string $group Optional. Where to group the cache contents. Default 'default'.
|
150 |
+
* @param int $expire Optional. When to expire the cache contents. Default 0 (no expiration).
|
151 |
+
* @return bool True on success, false if cache key and group already exist.
|
152 |
+
*/
|
153 |
+
public function add( $key, $data, $group = 'default', $expire = 0 ) {
|
154 |
+
if ( wp_suspend_cache_addition() ) {
|
155 |
+
return false;
|
156 |
+
}
|
157 |
+
|
158 |
+
if ( empty( $group ) ) {
|
159 |
+
$group = 'default';
|
160 |
+
}
|
161 |
+
|
162 |
+
$id = $key;
|
163 |
+
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
|
164 |
+
$id = $this->blog_prefix . $key;
|
165 |
+
}
|
166 |
+
|
167 |
+
if ( $this->_exists( $id, $group ) ) {
|
168 |
+
return false;
|
169 |
+
}
|
170 |
+
|
171 |
+
return $this->set( $key, $data, $group, (int) $expire );
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Sets the list of global cache groups.
|
176 |
+
*
|
177 |
+
* @since 3.0.0
|
178 |
+
*
|
179 |
+
* @param array $groups List of groups that are global.
|
180 |
+
*/
|
181 |
+
public function add_global_groups( $groups ) {
|
182 |
+
$groups = (array) $groups;
|
183 |
+
|
184 |
+
$groups = array_fill_keys( $groups, true );
|
185 |
+
$this->global_groups = array_merge( $this->global_groups, $groups );
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Decrements numeric cache item's value.
|
190 |
+
*
|
191 |
+
* @since 3.3.0
|
192 |
+
*
|
193 |
+
* @param int|string $key The cache key to decrement.
|
194 |
+
* @param int $offset Optional. The amount by which to decrement the item's value. Default 1.
|
195 |
+
* @param string $group Optional. The group the key is in. Default 'default'.
|
196 |
+
* @return int|false The item's new value on success, false on failure.
|
197 |
+
*/
|
198 |
+
public function decr( $key, $offset = 1, $group = 'default' ) {
|
199 |
+
if ( empty( $group ) ) {
|
200 |
+
$group = 'default';
|
201 |
+
}
|
202 |
+
|
203 |
+
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
|
204 |
+
$key = $this->blog_prefix . $key;
|
205 |
+
}
|
206 |
+
|
207 |
+
if ( ! $this->_exists( $key, $group ) ) {
|
208 |
+
return false;
|
209 |
+
}
|
210 |
+
|
211 |
+
if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) {
|
212 |
+
$this->cache[ $group ][ $key ] = 0;
|
213 |
+
}
|
214 |
+
|
215 |
+
$offset = (int) $offset;
|
216 |
+
|
217 |
+
$this->cache[ $group ][ $key ] -= $offset;
|
218 |
+
|
219 |
+
if ( $this->cache[ $group ][ $key ] < 0 ) {
|
220 |
+
$this->cache[ $group ][ $key ] = 0;
|
221 |
+
}
|
222 |
+
|
223 |
+
return $this->cache[ $group ][ $key ];
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* Removes the contents of the cache key in the group.
|
228 |
+
*
|
229 |
+
* If the cache key does not exist in the group, then nothing will happen.
|
230 |
+
*
|
231 |
+
* @since 2.0.0
|
232 |
+
*
|
233 |
+
* @param int|string $key What the contents in the cache are called.
|
234 |
+
* @param string $group Optional. Where the cache contents are grouped. Default 'default'.
|
235 |
+
* @param bool $deprecated Optional. Unused. Default false.
|
236 |
+
* @return bool False if the contents weren't deleted and true on success.
|
237 |
+
*/
|
238 |
+
public function delete( $key, $group = 'default', $deprecated = false ) {
|
239 |
+
if ( empty( $group ) ) {
|
240 |
+
$group = 'default';
|
241 |
+
}
|
242 |
+
|
243 |
+
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
|
244 |
+
$key = $this->blog_prefix . $key;
|
245 |
+
}
|
246 |
+
|
247 |
+
if ( ! $this->_exists( $key, $group ) ) {
|
248 |
+
return false;
|
249 |
+
}
|
250 |
+
|
251 |
+
unset( $this->cache[ $group ][ $key ] );
|
252 |
+
return true;
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Clears the object cache of all data.
|
257 |
+
*
|
258 |
+
* @since 2.0.0
|
259 |
+
*
|
260 |
+
* @return true Always returns true.
|
261 |
+
*/
|
262 |
+
public function flush() {
|
263 |
+
$this->cache = array();
|
264 |
+
|
265 |
+
return true;
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Retrieves the cache contents, if it exists.
|
270 |
+
*
|
271 |
+
* The contents will be first attempted to be retrieved by searching by the
|
272 |
+
* key in the cache group. If the cache is hit (success) then the contents
|
273 |
+
* are returned.
|
274 |
+
*
|
275 |
+
* On failure, the number of cache misses will be incremented.
|
276 |
+
*
|
277 |
+
* @since 2.0.0
|
278 |
+
*
|
279 |
+
* @param int|string $key What the contents in the cache are called.
|
280 |
+
* @param string $group Optional. Where the cache contents are grouped. Default 'default'.
|
281 |
+
* @param bool $force Optional. Unused. Whether to force a refetch rather than relying on the local
|
282 |
+
* cache. Default false.
|
283 |
+
* @param bool $found Optional. Whether the key was found in the cache (passed by reference).
|
284 |
+
* Disambiguates a return of false, a storable value. Default null.
|
285 |
+
* @return mixed|false The cache contents on success, false on failure to retrieve contents.
|
286 |
+
*/
|
287 |
+
public function get( $key, $group = 'default', $force = false, &$found = null ) {
|
288 |
+
if ( empty( $group ) ) {
|
289 |
+
$group = 'default';
|
290 |
+
}
|
291 |
+
|
292 |
+
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
|
293 |
+
$key = $this->blog_prefix . $key;
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( $this->_exists( $key, $group ) ) {
|
297 |
+
$found = true;
|
298 |
+
$this->cache_hits += 1;
|
299 |
+
if ( is_object( $this->cache[ $group ][ $key ] ) ) {
|
300 |
+
return clone $this->cache[ $group ][ $key ];
|
301 |
+
} else {
|
302 |
+
return $this->cache[ $group ][ $key ];
|
303 |
+
}
|
304 |
+
}
|
305 |
+
|
306 |
+
$found = false;
|
307 |
+
$this->cache_misses += 1;
|
308 |
+
return false;
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Increments numeric cache item's value.
|
313 |
+
*
|
314 |
+
* @since 3.3.0
|
315 |
+
*
|
316 |
+
* @param int|string $key The cache key to increment
|
317 |
+
* @param int $offset Optional. The amount by which to increment the item's value. Default 1.
|
318 |
+
* @param string $group Optional. The group the key is in. Default 'default'.
|
319 |
+
* @return int|false The item's new value on success, false on failure.
|
320 |
+
*/
|
321 |
+
public function incr( $key, $offset = 1, $group = 'default' ) {
|
322 |
+
if ( empty( $group ) ) {
|
323 |
+
$group = 'default';
|
324 |
+
}
|
325 |
+
|
326 |
+
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
|
327 |
+
$key = $this->blog_prefix . $key;
|
328 |
+
}
|
329 |
+
|
330 |
+
if ( ! $this->_exists( $key, $group ) ) {
|
331 |
+
return false;
|
332 |
+
}
|
333 |
+
|
334 |
+
if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) {
|
335 |
+
$this->cache[ $group ][ $key ] = 0;
|
336 |
+
}
|
337 |
+
|
338 |
+
$offset = (int) $offset;
|
339 |
+
|
340 |
+
$this->cache[ $group ][ $key ] += $offset;
|
341 |
+
|
342 |
+
if ( $this->cache[ $group ][ $key ] < 0 ) {
|
343 |
+
$this->cache[ $group ][ $key ] = 0;
|
344 |
+
}
|
345 |
+
|
346 |
+
return $this->cache[ $group ][ $key ];
|
347 |
+
}
|
348 |
+
|
349 |
+
/**
|
350 |
+
* Replaces the contents in the cache, if contents already exist.
|
351 |
+
*
|
352 |
+
* @since 2.0.0
|
353 |
+
*
|
354 |
+
* @see ObjectCache::set()
|
355 |
+
*
|
356 |
+
* @param int|string $key What to call the contents in the cache.
|
357 |
+
* @param mixed $data The contents to store in the cache.
|
358 |
+
* @param string $group Optional. Where to group the cache contents. Default 'default'.
|
359 |
+
* @param int $expire Optional. When to expire the cache contents. Default 0 (no expiration).
|
360 |
+
* @return bool False if not exists, true if contents were replaced.
|
361 |
+
*/
|
362 |
+
public function replace( $key, $data, $group = 'default', $expire = 0 ) {
|
363 |
+
if ( empty( $group ) ) {
|
364 |
+
$group = 'default';
|
365 |
+
}
|
366 |
+
|
367 |
+
$id = $key;
|
368 |
+
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
|
369 |
+
$id = $this->blog_prefix . $key;
|
370 |
+
}
|
371 |
+
|
372 |
+
if ( ! $this->_exists( $id, $group ) ) {
|
373 |
+
return false;
|
374 |
+
}
|
375 |
+
|
376 |
+
return $this->set( $key, $data, $group, (int) $expire );
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Resets cache keys.
|
381 |
+
*
|
382 |
+
* @since 3.0.0
|
383 |
+
*
|
384 |
+
* @deprecated 3.5.0 Use switch_to_blog()
|
385 |
+
* @see switch_to_blog()
|
386 |
+
*/
|
387 |
+
public function reset() {
|
388 |
+
_deprecated_function( __FUNCTION__, '3.5.0', 'switch_to_blog()' );
|
389 |
+
|
390 |
+
// Clear out non-global caches since the blog ID has changed.
|
391 |
+
foreach ( array_keys( $this->cache ) as $group ) {
|
392 |
+
if ( ! isset( $this->global_groups[ $group ] ) ) {
|
393 |
+
unset( $this->cache[ $group ] );
|
394 |
+
}
|
395 |
+
}
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Sets the data contents into the cache.
|
400 |
+
*
|
401 |
+
* The cache contents are grouped by the $group parameter followed by the
|
402 |
+
* $key. This allows for duplicate ids in unique groups. Therefore, naming of
|
403 |
+
* the group should be used with care and should follow normal function
|
404 |
+
* naming guidelines outside of core WordPress usage.
|
405 |
+
*
|
406 |
+
* The $expire parameter is not used, because the cache will automatically
|
407 |
+
* expire for each time a page is accessed and PHP finishes. The method is
|
408 |
+
* more for cache plugins which use files.
|
409 |
+
*
|
410 |
+
* @since 2.0.0
|
411 |
+
*
|
412 |
+
* @param int|string $key What to call the contents in the cache.
|
413 |
+
* @param mixed $data The contents to store in the cache.
|
414 |
+
* @param string $group Optional. Where to group the cache contents. Default 'default'.
|
415 |
+
* @param int $expire Not Used.
|
416 |
+
* @return true Always returns true.
|
417 |
+
*/
|
418 |
+
public function set( $key, $data, $group = 'default', $expire = 0 ) {
|
419 |
+
if ( empty( $group ) ) {
|
420 |
+
$group = 'default';
|
421 |
+
}
|
422 |
+
|
423 |
+
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) {
|
424 |
+
$key = $this->blog_prefix . $key;
|
425 |
+
}
|
426 |
+
|
427 |
+
if ( is_object( $data ) ) {
|
428 |
+
$data = clone $data;
|
429 |
+
}
|
430 |
+
|
431 |
+
$this->cache[ $group ][ $key ] = $data;
|
432 |
+
return true;
|
433 |
+
}
|
434 |
+
|
435 |
+
/**
|
436 |
+
* Echoes the stats of the caching.
|
437 |
+
*
|
438 |
+
* Gives the cache hits, and cache misses. Also prints every cached group,
|
439 |
+
* key and the data.
|
440 |
+
*
|
441 |
+
* @since 2.0.0
|
442 |
+
*/
|
443 |
+
public function stats() {
|
444 |
+
echo '<p>';
|
445 |
+
echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />";
|
446 |
+
echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
|
447 |
+
echo '</p>';
|
448 |
+
echo '<ul>';
|
449 |
+
foreach ( $this->cache as $group => $cache ) {
|
450 |
+
echo "<li><strong>Group:</strong> $group - ( " . number_format( strlen( serialize( $cache ) ) / KB_IN_BYTES, 2 ) . 'k )</li>';
|
451 |
+
}
|
452 |
+
echo '</ul>';
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* Switches the internal blog ID.
|
457 |
+
*
|
458 |
+
* This changes the blog ID used to create keys in blog specific groups.
|
459 |
+
*
|
460 |
+
* @since 3.5.0
|
461 |
+
*
|
462 |
+
* @param int $blog_id Blog ID.
|
463 |
+
*/
|
464 |
+
public function switch_to_blog( $blog_id ) {
|
465 |
+
$blog_id = (int) $blog_id;
|
466 |
+
$this->blog_prefix = $this->multisite ? $blog_id . ':' : '';
|
467 |
+
}
|
468 |
+
|
469 |
+
/**
|
470 |
+
* Serves as a utility function to determine whether a key exists in the cache.
|
471 |
+
*
|
472 |
+
* @since 3.4.0
|
473 |
+
*
|
474 |
+
* @param int|string $key Cache key to check for existence.
|
475 |
+
* @param string $group Cache group for the key existence check.
|
476 |
+
* @return bool Whether the key exists in the cache for the given group.
|
477 |
+
*/
|
478 |
+
protected function _exists( $key, $group ) {
|
479 |
+
return isset( $this->cache[ $group ] ) && ( isset( $this->cache[ $group ][ $key ] ) || array_key_exists( $key, $this->cache[ $group ] ) );
|
480 |
+
}
|
481 |
+
|
482 |
+
/**
|
483 |
+
* [START] Functions to call (reference: /wp-includes/cache.php)
|
484 |
+
*/
|
485 |
+
/**
|
486 |
+
* Adds data to the cache, if the cache key doesn't already exist.
|
487 |
+
*
|
488 |
+
* @since 2.0.0
|
489 |
+
*
|
490 |
+
* @see ObjectCache::add()
|
491 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
492 |
+
*
|
493 |
+
* @param int|string $key The cache key to use for retrieval later.
|
494 |
+
* @param mixed $data The data to add to the cache.
|
495 |
+
* @param string $group Optional. The group to add the cache to. Enables the same key
|
496 |
+
* to be used across groups. Default empty.
|
497 |
+
* @param int $expire Optional. When the cache data should expire, in seconds.
|
498 |
+
* Default 0 (no expiration).
|
499 |
+
* @return bool True on success, false if cache key and group already exist.
|
500 |
+
*/
|
501 |
+
public static function wpacu_cache_add( $key, $data, $group = '', $expire = 0 ) {
|
502 |
+
global $wpacu_object_cache;
|
503 |
+
|
504 |
+
return $wpacu_object_cache->add( $key, $data, $group, (int) $expire );
|
505 |
+
}
|
506 |
+
|
507 |
+
/**
|
508 |
+
* Closes the cache.
|
509 |
+
*
|
510 |
+
* This function has ceased to do anything since WordPress 2.5. The
|
511 |
+
* functionality was removed along with the rest of the persistent cache.
|
512 |
+
*
|
513 |
+
* This does not mean that plugins can't implement this function when they need
|
514 |
+
* to make sure that the cache is cleaned up after WordPress no longer needs it.
|
515 |
+
*
|
516 |
+
* @since 2.0.0
|
517 |
+
*
|
518 |
+
* @return true Always returns true.
|
519 |
+
*/
|
520 |
+
public static function wpacu_cache_close() {
|
521 |
+
return true;
|
522 |
+
}
|
523 |
+
|
524 |
+
/**
|
525 |
+
* Decrements numeric cache item's value.
|
526 |
+
*
|
527 |
+
* @since 3.3.0
|
528 |
+
*
|
529 |
+
* @see ObjectCache::decr()
|
530 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
531 |
+
*
|
532 |
+
* @param int|string $key The cache key to decrement.
|
533 |
+
* @param int $offset Optional. The amount by which to decrement the item's value. Default 1.
|
534 |
+
* @param string $group Optional. The group the key is in. Default empty.
|
535 |
+
* @return int|false The item's new value on success, false on failure.
|
536 |
+
*/
|
537 |
+
public static function wpacu_cache_decr( $key, $offset = 1, $group = '' ) {
|
538 |
+
global $wpacu_object_cache;
|
539 |
+
|
540 |
+
return $wpacu_object_cache->decr( $key, $offset, $group );
|
541 |
+
}
|
542 |
+
|
543 |
+
/**
|
544 |
+
* Removes the cache contents matching key and group.
|
545 |
+
*
|
546 |
+
* @since 2.0.0
|
547 |
+
*
|
548 |
+
* @see ObjectCache::delete()
|
549 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
550 |
+
*
|
551 |
+
* @param int|string $key What the contents in the cache are called.
|
552 |
+
* @param string $group Optional. Where the cache contents are grouped. Default empty.
|
553 |
+
* @return bool True on successful removal, false on failure.
|
554 |
+
*/
|
555 |
+
public static function wpacu_cache_delete( $key, $group = '' ) {
|
556 |
+
global $wpacu_object_cache;
|
557 |
+
|
558 |
+
return $wpacu_object_cache->delete( $key, $group );
|
559 |
+
}
|
560 |
+
|
561 |
+
/**
|
562 |
+
* Removes all cache items.
|
563 |
+
*
|
564 |
+
* @since 2.0.0
|
565 |
+
*
|
566 |
+
* @see ObjectCache::flush()
|
567 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
568 |
+
*
|
569 |
+
* @return bool True on success, false on failure.
|
570 |
+
*/
|
571 |
+
public static function wpacu_cache_flush() {
|
572 |
+
global $wpacu_object_cache;
|
573 |
+
|
574 |
+
return $wpacu_object_cache->flush();
|
575 |
+
}
|
576 |
+
|
577 |
+
/**
|
578 |
+
* Retrieves the cache contents from the cache by key and group.
|
579 |
+
*
|
580 |
+
* @since 2.0.0
|
581 |
+
*
|
582 |
+
* @see ObjectCache::get()
|
583 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
584 |
+
*
|
585 |
+
* @param int|string $key The key under which the cache contents are stored.
|
586 |
+
* @param string $group Optional. Where the cache contents are grouped. Default empty.
|
587 |
+
* @param bool $force Optional. Whether to force an update of the local cache from the persistent
|
588 |
+
* cache. Default false.
|
589 |
+
* @param bool $found Optional. Whether the key was found in the cache (passed by reference).
|
590 |
+
* Disambiguates a return of false, a storable value. Default null.
|
591 |
+
* @return bool|mixed False on failure to retrieve contents or the cache
|
592 |
+
* contents on success
|
593 |
+
*/
|
594 |
+
public static function wpacu_cache_get( $key, $group = '', $force = false, &$found = null ) {
|
595 |
+
global $wpacu_object_cache;
|
596 |
+
|
597 |
+
return $wpacu_object_cache->get( $key, $group, $force, $found );
|
598 |
+
}
|
599 |
+
|
600 |
+
/**
|
601 |
+
* Increment numeric cache item's value
|
602 |
+
*
|
603 |
+
* @since 3.3.0
|
604 |
+
*
|
605 |
+
* @see ObjectCache::incr()
|
606 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
607 |
+
*
|
608 |
+
* @param int|string $key The key for the cache contents that should be incremented.
|
609 |
+
* @param int $offset Optional. The amount by which to increment the item's value. Default 1.
|
610 |
+
* @param string $group Optional. The group the key is in. Default empty.
|
611 |
+
* @return int|false The item's new value on success, false on failure.
|
612 |
+
*/
|
613 |
+
public static function wpacu_cache_incr( $key, $offset = 1, $group = '' ) {
|
614 |
+
global $wpacu_object_cache;
|
615 |
+
|
616 |
+
return $wpacu_object_cache->incr( $key, $offset, $group );
|
617 |
+
}
|
618 |
+
|
619 |
+
/**
|
620 |
+
* Sets up Object Cache Global and assigns it.
|
621 |
+
*
|
622 |
+
* @since 2.0.0
|
623 |
+
*
|
624 |
+
* @global ObjectCache $wpacu_object_cache
|
625 |
+
*/
|
626 |
+
public static function wpacu_cache_init() {
|
627 |
+
$GLOBALS['wpacu_object_cache'] = new ObjectCache();
|
628 |
+
}
|
629 |
+
|
630 |
+
/**
|
631 |
+
* Replaces the contents of the cache with new data.
|
632 |
+
*
|
633 |
+
* @since 2.0.0
|
634 |
+
*
|
635 |
+
* @see ObjectCache::replace()
|
636 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
637 |
+
*
|
638 |
+
* @param int|string $key The key for the cache data that should be replaced.
|
639 |
+
* @param mixed $data The new data to store in the cache.
|
640 |
+
* @param string $group Optional. The group for the cache data that should be replaced.
|
641 |
+
* Default empty.
|
642 |
+
* @param int $expire Optional. When to expire the cache contents, in seconds.
|
643 |
+
* Default 0 (no expiration).
|
644 |
+
* @return bool False if original value does not exist, true if contents were replaced
|
645 |
+
*/
|
646 |
+
public static function wpacu_cache_replace( $key, $data, $group = '', $expire = 0 ) {
|
647 |
+
global $wpacu_object_cache;
|
648 |
+
|
649 |
+
return $wpacu_object_cache->replace( $key, $data, $group, (int) $expire );
|
650 |
+
}
|
651 |
+
|
652 |
+
/**
|
653 |
+
* Saves the data to the cache.
|
654 |
+
*
|
655 |
+
* Differs from ObjectCache::wpacu_cache_add) and wp_cache_replace() in that it will always write data.
|
656 |
+
*
|
657 |
+
* @since 2.0.0
|
658 |
+
*
|
659 |
+
* @see ObjectCache::set()
|
660 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
661 |
+
*
|
662 |
+
* @param int|string $key The cache key to use for retrieval later.
|
663 |
+
* @param mixed $data The contents to store in the cache.
|
664 |
+
* @param string $group Optional. Where to group the cache contents. Enables the same key
|
665 |
+
* to be used across groups. Default empty.
|
666 |
+
* @param int $expire Optional. When to expire the cache contents, in seconds.
|
667 |
+
* Default 0 (no expiration).
|
668 |
+
* @return bool True on success, false on failure.
|
669 |
+
*/
|
670 |
+
public static function wpacu_cache_set( $key, $data, $group = '', $expire = 0 ) {
|
671 |
+
global $wpacu_object_cache;
|
672 |
+
|
673 |
+
return $wpacu_object_cache->set( $key, $data, $group, (int) $expire );
|
674 |
+
}
|
675 |
+
|
676 |
+
/**
|
677 |
+
* Switches the internal blog ID.
|
678 |
+
*
|
679 |
+
* This changes the blog id used to create keys in blog specific groups.
|
680 |
+
*
|
681 |
+
* @since 3.5.0
|
682 |
+
*
|
683 |
+
* @see ObjectCache::switch_to_blog()
|
684 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
685 |
+
*
|
686 |
+
* @param int $blog_id Site ID.
|
687 |
+
*/
|
688 |
+
public static function wpacu_cache_switch_to_blog( $blog_id ) {
|
689 |
+
global $wpacu_object_cache;
|
690 |
+
|
691 |
+
$wpacu_object_cache->switch_to_blog( $blog_id );
|
692 |
+
}
|
693 |
+
|
694 |
+
/**
|
695 |
+
* Adds a group or set of groups to the list of global groups.
|
696 |
+
*
|
697 |
+
* @since 2.6.0
|
698 |
+
*
|
699 |
+
* @see ObjectCache::add_global_groups()
|
700 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
701 |
+
*
|
702 |
+
* @param string|array $groups A group or an array of groups to add.
|
703 |
+
*/
|
704 |
+
public static function wpacu_cache_add_global_groups( $groups ) {
|
705 |
+
global $wpacu_object_cache;
|
706 |
+
|
707 |
+
$wpacu_object_cache->add_global_groups( $groups );
|
708 |
+
}
|
709 |
+
|
710 |
+
/**
|
711 |
+
* Adds a group or set of groups to the list of non-persistent groups.
|
712 |
+
*
|
713 |
+
* @since 2.6.0
|
714 |
+
*
|
715 |
+
* @param string|array $groups A group or an array of groups to add.
|
716 |
+
*/
|
717 |
+
public static function wpacu_cache_add_non_persistent_groups( $groups ) {
|
718 |
+
// Default cache doesn't persist so nothing to do here.
|
719 |
+
}
|
720 |
+
|
721 |
+
/**
|
722 |
+
* Reset internal cache keys and structures.
|
723 |
+
*
|
724 |
+
* If the cache back end uses global blog or site IDs as part of its cache keys,
|
725 |
+
* this function instructs the back end to reset those keys and perform any cleanup
|
726 |
+
* since blog or site IDs have changed since cache init.
|
727 |
+
*
|
728 |
+
* This function is deprecated. Use wp_cache_switch_to_blog() instead of this
|
729 |
+
* function when preparing the cache for a blog switch. For clearing the cache
|
730 |
+
* during unit tests, consider using wp_cache_init(). wp_cache_init() is not
|
731 |
+
* recommended outside of unit tests as the performance penalty for using it is
|
732 |
+
* high.
|
733 |
+
*
|
734 |
+
* @since 2.6.0
|
735 |
+
* @deprecated 3.5.0 ObjectCache::reset()
|
736 |
+
* @see ObjectCache::reset()
|
737 |
+
*
|
738 |
+
* @global ObjectCache $wpacu_object_cache Object cache global instance.
|
739 |
+
*/
|
740 |
+
public static function wpacu_cache_reset() {
|
741 |
+
_deprecated_function( __FUNCTION__, '3.5.0', 'ObjectCache::reset()' );
|
742 |
+
|
743 |
+
global $wpacu_object_cache;
|
744 |
+
|
745 |
+
$wpacu_object_cache->reset();
|
746 |
+
}
|
747 |
+
/**
|
748 |
+
* [END] Functions to call (reference: /wp-includes/cache.php)
|
749 |
+
*/
|
750 |
+
}
|
classes/OptimiseAssets/CombineCss.php
CHANGED
@@ -5,6 +5,8 @@ use WpAssetCleanUp\Main;
|
|
5 |
use WpAssetCleanUp\Menu;
|
6 |
use WpAssetCleanUp\FileSystem;
|
7 |
use WpAssetCleanUp\Misc;
|
|
|
|
|
8 |
|
9 |
/**
|
10 |
* Class CombineCss
|
@@ -24,7 +26,7 @@ class CombineCss
|
|
24 |
*/
|
25 |
public static function doCombine($htmlSource)
|
26 |
{
|
27 |
-
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('DOMDocument')) && class_exists('DOMXpath')) {
|
28 |
return $htmlSource;
|
29 |
}
|
30 |
|
@@ -32,6 +34,9 @@ class CombineCss
|
|
32 |
return $htmlSource;
|
33 |
}
|
34 |
|
|
|
|
|
|
|
35 |
// Speed up processing by getting the already existing final CSS file URI
|
36 |
// This will avoid parsing the HTML DOM and determine the combined URI paths for all the CSS files
|
37 |
$storageJsonContents = OptimizeCommon::getAssetCachedData(self::$jsonStorageFile, OptimizeCss::getRelPathCssCacheDir(), 'css');
|
@@ -39,7 +44,13 @@ class CombineCss
|
|
39 |
// $uriToFinalCssFile will always be relative ONLY within WP_CONTENT_DIR . self::getRelPathCssCacheDir()
|
40 |
// which is usually "wp-content/cache/asset-cleanup/css/"
|
41 |
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
$storageJsonContentsToSave = array();
|
44 |
|
45 |
/*
|
@@ -48,25 +59,20 @@ class CombineCss
|
|
48 |
// Nothing in the database records or the retrieved cached file does not exist?
|
49 |
OptimizeCommon::clearAssetCachedData(self::$jsonStorageFile);
|
50 |
|
51 |
-
// Fetch the DOM
|
52 |
-
$documentForCSS = new \DOMDocument();
|
53 |
-
|
54 |
-
libxml_use_internal_errors(true);
|
55 |
-
|
56 |
$storageJsonContents = array();
|
57 |
|
58 |
-
|
59 |
-
$htmlSourceAlt = preg_replace('@<(noscript)[^>]*?>.*?</\\1>@si', '', $htmlSource);
|
60 |
-
$documentForCSS->loadHTML($htmlSourceAlt);
|
61 |
|
62 |
foreach (array('head', 'body') as $docLocationTag) {
|
63 |
$combinedUriPathsGroup = $localAssetsPathsGroup = $linkHrefsGroup = array();
|
|
|
|
|
|
|
64 |
|
65 |
-
$docLocationElements = $documentForCSS->getElementsByTagName($docLocationTag)->item(0);
|
66 |
if ($docLocationElements === null) { continue; }
|
67 |
|
68 |
-
$xpath = new \DOMXpath($
|
69 |
-
$linkTags = $xpath->query('/html/'.$docLocationTag.'/link[@rel="stylesheet"]');
|
70 |
if ($linkTags === null) { continue; }
|
71 |
|
72 |
foreach ($linkTags as $tagObject) {
|
@@ -78,22 +84,35 @@ class CombineCss
|
|
78 |
if (isset($linkAttributes['rel'], $linkAttributes['href']) && $linkAttributes['href']) {
|
79 |
$href = (string) $linkAttributes['href'];
|
80 |
|
81 |
-
//
|
82 |
-
|
83 |
|
84 |
-
//
|
85 |
-
//
|
86 |
-
if (isset($linkAttributes['data-wpacu-
|
87 |
-
|
|
|
|
|
88 |
}
|
89 |
|
90 |
-
//
|
91 |
-
|
|
|
|
|
92 |
|
93 |
if (self::skipCombine($linkAttributes['href'])) {
|
94 |
continue;
|
95 |
}
|
96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
// Was it optimized and has the URL updated? Check the Source URL to determine if it should be skipped from combining
|
98 |
if (isset($linkAttributes['data-wpacu-link-rel-href-before']) && $linkAttributes['data-wpacu-link-rel-href-before'] && self::skipCombine($linkAttributes['data-wpacu-link-rel-href-before'])) {
|
99 |
continue;
|
@@ -108,9 +127,16 @@ class CombineCss
|
|
108 |
|
109 |
// It will skip external stylesheets (from a different domain)
|
110 |
if ( $localAssetPath ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
$combinedUriPathsGroup[$mediaValue][] = OptimizeCommon::getSourceRelPath($href);
|
112 |
$localAssetsPathsGroup[$mediaValue][$href] = $localAssetPath;
|
113 |
$linkHrefsGroup[$mediaValue][] = $href;
|
|
|
114 |
}
|
115 |
}
|
116 |
}
|
@@ -128,12 +154,14 @@ class CombineCss
|
|
128 |
|
129 |
$localAssetsPaths = $localAssetsPathsGroup[$mediaValue];
|
130 |
$linkHrefs = $linkHrefsGroup[$mediaValue];
|
|
|
131 |
|
132 |
-
$shaOneForCombinedCss = self::generateShaOneForCombinedCss($combinedUriPaths);
|
133 |
|
134 |
$maybeDoCssCombine = self::maybeDoCssCombine(
|
135 |
$shaOneForCombinedCss,
|
136 |
$localAssetsPaths, $linkHrefs,
|
|
|
137 |
$docLocationTag
|
138 |
);
|
139 |
|
@@ -197,12 +225,32 @@ class CombineCss
|
|
197 |
$finalTagUrl = OptimizeCommon::filterWpContentUrl($cdnUrlForCss) . OptimizeCss::getRelPathCssCacheDir() . $storageJsonContentLocation['uri_to_final_css_file'];
|
198 |
|
199 |
$finalCssTagAttrs = array();
|
200 |
-
$finalCssTagAttrs['rel'] = 'stylesheet';
|
201 |
-
$finalCssTagAttrs['media'] = $mediaValue;
|
202 |
|
203 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
<link rel='stylesheet' id='wpacu-combined-css-{$docLocationTag}-{$groupLocation}' href='{$finalTagUrl}' type='text/css' media='{$mediaValue}' />
|
205 |
HTML;
|
|
|
|
|
|
|
|
|
206 |
// In case one (e.g. usually a developer) needs to alter it
|
207 |
$finalCssTag = apply_filters(
|
208 |
'wpacu_combined_css_tag',
|
@@ -215,18 +263,23 @@ HTML;
|
|
215 |
)
|
216 |
);
|
217 |
|
|
|
|
|
|
|
218 |
$htmlSourceBeforeAnyLinkTagReplacement = $htmlSource;
|
219 |
|
220 |
// Detect first LINK tag from the <$locationTag> and replace it with the final combined LINK tag
|
221 |
$firstLinkTag = OptimizeCss::getFirstLinkTag($storageJsonContentLocation['link_hrefs'][0], $htmlSource);
|
222 |
|
223 |
if ($firstLinkTag) {
|
224 |
-
|
|
|
225 |
}
|
226 |
|
227 |
if ($htmlSource !== $htmlSourceBeforeAnyLinkTagReplacement) {
|
228 |
$htmlSource = self::stripJustCombinedLinkTags(
|
229 |
$storageJsonContentLocation['link_hrefs'],
|
|
|
230 |
$htmlSource
|
231 |
); // Strip the combined files to avoid duplicate code
|
232 |
|
@@ -247,11 +300,12 @@ HTML;
|
|
247 |
|
248 |
/**
|
249 |
* @param $filesSources
|
|
|
250 |
* @param $htmlSource
|
251 |
*
|
252 |
* @return mixed
|
253 |
*/
|
254 |
-
public static function stripJustCombinedLinkTags($filesSources, $htmlSource)
|
255 |
{
|
256 |
preg_match_all('#<link[^>]*(stylesheet|preload)[^>]*(>)#Umi', $htmlSource, $matchesSourcesFromTags, PREG_SET_ORDER);
|
257 |
|
@@ -271,7 +325,7 @@ HTML;
|
|
271 |
$domTag->loadHTML($matchedSourceFromTag);
|
272 |
|
273 |
foreach ($domTag->getElementsByTagName('link') as $tagObject) {
|
274 |
-
if (
|
275 |
|
276 |
foreach ($tagObject->attributes as $tagAttrs) {
|
277 |
if ($tagAttrs->nodeName === 'href') {
|
@@ -280,7 +334,7 @@ HTML;
|
|
280 |
if (in_array($relNodeValue, $filesSources)) {
|
281 |
$htmlSourceBeforeLinkTagReplacement = $htmlSource;
|
282 |
|
283 |
-
$htmlSource =
|
284 |
|
285 |
if ($htmlSource !== $htmlSourceBeforeLinkTagReplacement) {
|
286 |
$linkTagsStrippedNo++;
|
@@ -345,19 +399,15 @@ HTML;
|
|
345 |
* @param $shaOneForCombinedCss
|
346 |
* @param $localAssetsPaths
|
347 |
* @param $linkHrefs
|
|
|
348 |
* @param $docLocationTag
|
349 |
*
|
350 |
* @return array
|
351 |
*/
|
352 |
-
public static function maybeDoCssCombine($shaOneForCombinedCss, $localAssetsPaths, $linkHrefs, $docLocationTag)
|
353 |
{
|
354 |
-
$
|
355 |
-
$
|
356 |
-
|
357 |
-
$uriToFinalCssFile = $dirToUserCachedFile . $docLocationTag . '-' .$shaOneForCombinedCss . '.css';
|
358 |
-
|
359 |
-
$localFinalCssFile = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . $uriToFinalCssFile;
|
360 |
-
$localDirForCssFile = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . $dirToUserCachedFile;
|
361 |
|
362 |
// Only combine if $shaOneCombinedUriPaths.css does not exist
|
363 |
// If "?ver" value changes on any of the assets or the asset list changes in any way
|
@@ -379,6 +429,8 @@ HTML;
|
|
379 |
|
380 |
$finalCombinedCssContent .= '/*! '.str_replace(ABSPATH, '/', $localAssetsPath)." */\n";
|
381 |
$finalCombinedCssContent .= OptimizeCss::maybeFixCssContent($cssContent, $pathToAssetDir . '/') . "\n";
|
|
|
|
|
382 |
}
|
383 |
}
|
384 |
|
@@ -389,15 +441,9 @@ HTML;
|
|
389 |
$finalCombinedCssContent = FontsGoogleRemove::cleanFontFaceReferences($finalCombinedCssContent);
|
390 |
}
|
391 |
|
392 |
-
|
393 |
-
if ($dirToUserCachedFile !== '' && isset($current_user->ID) && $current_user->ID > 0 && ! is_dir($localDirForCssFile)) {
|
394 |
-
$makeLocalDirForCss = @mkdir($localDirForCssFile);
|
395 |
-
|
396 |
-
if (! $makeLocalDirForCss) {
|
397 |
-
return array('uri_final_css_file' => '', 'local_final_css_file' => '');
|
398 |
-
}
|
399 |
-
}
|
400 |
|
|
|
401 |
FileSystem::file_put_contents($localFinalCssFile, $finalCombinedCssContent);
|
402 |
}
|
403 |
}
|
@@ -411,12 +457,100 @@ HTML;
|
|
411 |
|
412 |
/**
|
413 |
* @param $combinedUriPaths
|
|
|
414 |
*
|
415 |
* @return string
|
416 |
*/
|
417 |
-
public static function generateShaOneForCombinedCss($combinedUriPaths)
|
418 |
{
|
419 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
}
|
421 |
|
422 |
/**
|
5 |
use WpAssetCleanUp\Menu;
|
6 |
use WpAssetCleanUp\FileSystem;
|
7 |
use WpAssetCleanUp\Misc;
|
8 |
+
use WpAssetCleanUp\ObjectCache;
|
9 |
+
use WpAssetCleanUp\Preloads;
|
10 |
|
11 |
/**
|
12 |
* Class CombineCss
|
26 |
*/
|
27 |
public static function doCombine($htmlSource)
|
28 |
{
|
29 |
+
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('\DOMDocument')) && class_exists('\DOMXpath')) {
|
30 |
return $htmlSource;
|
31 |
}
|
32 |
|
34 |
return $htmlSource;
|
35 |
}
|
36 |
|
37 |
+
global $wp_styles;
|
38 |
+
$wpacuRegisteredStyles = $wp_styles->registered;
|
39 |
+
|
40 |
// Speed up processing by getting the already existing final CSS file URI
|
41 |
// This will avoid parsing the HTML DOM and determine the combined URI paths for all the CSS files
|
42 |
$storageJsonContents = OptimizeCommon::getAssetCachedData(self::$jsonStorageFile, OptimizeCss::getRelPathCssCacheDir(), 'css');
|
44 |
// $uriToFinalCssFile will always be relative ONLY within WP_CONTENT_DIR . self::getRelPathCssCacheDir()
|
45 |
// which is usually "wp-content/cache/asset-cleanup/css/"
|
46 |
|
47 |
+
$skipCache = false; // default
|
48 |
+
|
49 |
+
if (isset($_GET['wpacu_no_cache'])) {
|
50 |
+
$skipCache = true;
|
51 |
+
}
|
52 |
+
|
53 |
+
if ( $skipCache || empty($storageJsonContents) ) {
|
54 |
$storageJsonContentsToSave = array();
|
55 |
|
56 |
/*
|
59 |
// Nothing in the database records or the retrieved cached file does not exist?
|
60 |
OptimizeCommon::clearAssetCachedData(self::$jsonStorageFile);
|
61 |
|
|
|
|
|
|
|
|
|
|
|
62 |
$storageJsonContents = array();
|
63 |
|
64 |
+
$domTag = OptimizeCommon::getDomLoadedTag($htmlSource, 'combineCss');
|
|
|
|
|
65 |
|
66 |
foreach (array('head', 'body') as $docLocationTag) {
|
67 |
$combinedUriPathsGroup = $localAssetsPathsGroup = $linkHrefsGroup = array();
|
68 |
+
$localAssetsExtraGroup = array();
|
69 |
+
|
70 |
+
$docLocationElements = $domTag->getElementsByTagName($docLocationTag)->item(0);
|
71 |
|
|
|
72 |
if ($docLocationElements === null) { continue; }
|
73 |
|
74 |
+
$xpath = new \DOMXpath($domTag);
|
75 |
+
$linkTags = $xpath->query('/html/'.$docLocationTag.'/link[@rel="stylesheet"] | /html/'.$docLocationTag.'/link[@rel="preload"]');
|
76 |
if ($linkTags === null) { continue; }
|
77 |
|
78 |
foreach ($linkTags as $tagObject) {
|
84 |
if (isset($linkAttributes['rel'], $linkAttributes['href']) && $linkAttributes['href']) {
|
85 |
$href = (string) $linkAttributes['href'];
|
86 |
|
87 |
+
// Separate each combined group by the "media" attribute; e.g. we don't want "all" and "print" mixed
|
88 |
+
$mediaValue = (array_key_exists('media', $linkAttributes) && $linkAttributes['media']) ? $linkAttributes['media'] : 'all';
|
89 |
|
90 |
+
// Check if there is any rel="preload" (Basic) connected to the rel="stylesheet"
|
91 |
+
// making sure the file is not added to the final CSS combined file
|
92 |
+
if (isset($linkAttributes['data-wpacu-style-handle']) &&
|
93 |
+
$linkAttributes['data-wpacu-style-handle'] &&
|
94 |
+
ObjectCache::wpacu_cache_get($linkAttributes['data-wpacu-style-handle'], 'wpacu_basic_preload_handles')) {
|
95 |
+
$mediaValue = 'wpacu_preload_basic_' . $mediaValue;
|
96 |
}
|
97 |
|
98 |
+
// Check if the CSS file has any 'data-wpacu-skip' attribute; if it does, do not alter it
|
99 |
+
if (isset($linkAttributes['data-wpacu-skip'])) {
|
100 |
+
continue;
|
101 |
+
}
|
102 |
|
103 |
if (self::skipCombine($linkAttributes['href'])) {
|
104 |
continue;
|
105 |
}
|
106 |
|
107 |
+
// Make the right reference for later use
|
108 |
+
if ($linkAttributes['rel'] === 'preload') {
|
109 |
+
if (isset($linkAttributes['data-wpacu-preload-css-basic'])) {
|
110 |
+
$mediaValue = 'wpacu_preload_basic_' . $mediaValue;
|
111 |
+
} else {
|
112 |
+
continue;
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
// Was it optimized and has the URL updated? Check the Source URL to determine if it should be skipped from combining
|
117 |
if (isset($linkAttributes['data-wpacu-link-rel-href-before']) && $linkAttributes['data-wpacu-link-rel-href-before'] && self::skipCombine($linkAttributes['data-wpacu-link-rel-href-before'])) {
|
118 |
continue;
|
127 |
|
128 |
// It will skip external stylesheets (from a different domain)
|
129 |
if ( $localAssetPath ) {
|
130 |
+
$styleExtra = array();
|
131 |
+
|
132 |
+
if (isset($linkAttributes['data-wpacu-style-handle'], $wpacuRegisteredStyles[$linkAttributes['data-wpacu-style-handle']]->extra)) {
|
133 |
+
$styleExtra = $wpacuRegisteredStyles[$linkAttributes['data-wpacu-style-handle']]->extra;
|
134 |
+
}
|
135 |
+
|
136 |
$combinedUriPathsGroup[$mediaValue][] = OptimizeCommon::getSourceRelPath($href);
|
137 |
$localAssetsPathsGroup[$mediaValue][$href] = $localAssetPath;
|
138 |
$linkHrefsGroup[$mediaValue][] = $href;
|
139 |
+
$localAssetsExtraGroup[$mediaValue][$href] = $styleExtra;
|
140 |
}
|
141 |
}
|
142 |
}
|
154 |
|
155 |
$localAssetsPaths = $localAssetsPathsGroup[$mediaValue];
|
156 |
$linkHrefs = $linkHrefsGroup[$mediaValue];
|
157 |
+
$localAssetsExtra = array_filter($localAssetsExtraGroup[$mediaValue]);
|
158 |
|
159 |
+
$shaOneForCombinedCss = self::generateShaOneForCombinedCss($combinedUriPaths, $localAssetsExtra);
|
160 |
|
161 |
$maybeDoCssCombine = self::maybeDoCssCombine(
|
162 |
$shaOneForCombinedCss,
|
163 |
$localAssetsPaths, $linkHrefs,
|
164 |
+
$localAssetsExtra,
|
165 |
$docLocationTag
|
166 |
);
|
167 |
|
225 |
$finalTagUrl = OptimizeCommon::filterWpContentUrl($cdnUrlForCss) . OptimizeCss::getRelPathCssCacheDir() . $storageJsonContentLocation['uri_to_final_css_file'];
|
226 |
|
227 |
$finalCssTagAttrs = array();
|
|
|
|
|
228 |
|
229 |
+
if (strpos($mediaValue, 'wpacu_preload_basic_') === 0) {
|
230 |
+
// Put the right "media" value after cleaning the reference
|
231 |
+
$mediaValueClean = str_replace('wpacu_preload_basic_', '', $mediaValue);
|
232 |
+
|
233 |
+
// Basic Preload
|
234 |
+
$finalCssTag = <<<HTML
|
235 |
+
<link rel='stylesheet' data-wpacu-to-be-preloaded-basic='1' id='wpacu-combined-css-{$docLocationTag}-{$groupLocation}-preload-it-basic' href='{$finalTagUrl}' type='text/css' media='{$mediaValueClean}' />
|
236 |
+
HTML;
|
237 |
+
$finalCssTagRelPreload = <<<HTML
|
238 |
+
<link rel='preload' as='style' data-wpacu-preload-it-basic='1' id='wpacu-combined-css-{$docLocationTag}-{$groupLocation}-preload-it-basic' href='{$finalTagUrl}' type='text/css' media='{$mediaValueClean}' />
|
239 |
+
HTML;
|
240 |
+
|
241 |
+
$finalCssTagAttrs['rel'] = 'preload';
|
242 |
+
$finalCssTagAttrs['media'] = $mediaValueClean;
|
243 |
+
|
244 |
+
$htmlSource = str_replace(Preloads::DEL_STYLES_PRELOADS, $finalCssTagRelPreload."\n" . Preloads::DEL_STYLES_PRELOADS, $htmlSource);
|
245 |
+
} else {
|
246 |
+
// Render-blocking CSS
|
247 |
+
$finalCssTag = <<<HTML
|
248 |
<link rel='stylesheet' id='wpacu-combined-css-{$docLocationTag}-{$groupLocation}' href='{$finalTagUrl}' type='text/css' media='{$mediaValue}' />
|
249 |
HTML;
|
250 |
+
$finalCssTagAttrs['rel'] = 'stylesheet';
|
251 |
+
$finalCssTagAttrs['media'] = $mediaValue;
|
252 |
+
}
|
253 |
+
|
254 |
// In case one (e.g. usually a developer) needs to alter it
|
255 |
$finalCssTag = apply_filters(
|
256 |
'wpacu_combined_css_tag',
|
263 |
)
|
264 |
);
|
265 |
|
266 |
+
// Reference: https://stackoverflow.com/questions/2368539/php-replacing-multiple-spaces-with-a-single-space
|
267 |
+
$finalCssTag = preg_replace('!\s+!', ' ', $finalCssTag);
|
268 |
+
|
269 |
$htmlSourceBeforeAnyLinkTagReplacement = $htmlSource;
|
270 |
|
271 |
// Detect first LINK tag from the <$locationTag> and replace it with the final combined LINK tag
|
272 |
$firstLinkTag = OptimizeCss::getFirstLinkTag($storageJsonContentLocation['link_hrefs'][0], $htmlSource);
|
273 |
|
274 |
if ($firstLinkTag) {
|
275 |
+
// This will also strip the tag (not just the inline code before/after it)
|
276 |
+
$htmlSource = self::maybeStripExtraInlineAfterAppended($firstLinkTag, $wpacuRegisteredStyles, $finalCssTag, $htmlSource);
|
277 |
}
|
278 |
|
279 |
if ($htmlSource !== $htmlSourceBeforeAnyLinkTagReplacement) {
|
280 |
$htmlSource = self::stripJustCombinedLinkTags(
|
281 |
$storageJsonContentLocation['link_hrefs'],
|
282 |
+
$wpacuRegisteredStyles,
|
283 |
$htmlSource
|
284 |
); // Strip the combined files to avoid duplicate code
|
285 |
|
300 |
|
301 |
/**
|
302 |
* @param $filesSources
|
303 |
+
* @param $wpacuRegisteredStyles
|
304 |
* @param $htmlSource
|
305 |
*
|
306 |
* @return mixed
|
307 |
*/
|
308 |
+
public static function stripJustCombinedLinkTags($filesSources, $wpacuRegisteredStyles, $htmlSource)
|
309 |
{
|
310 |
preg_match_all('#<link[^>]*(stylesheet|preload)[^>]*(>)#Umi', $htmlSource, $matchesSourcesFromTags, PREG_SET_ORDER);
|
311 |
|
325 |
$domTag->loadHTML($matchedSourceFromTag);
|
326 |
|
327 |
foreach ($domTag->getElementsByTagName('link') as $tagObject) {
|
328 |
+
if (empty($tagObject->attributes)) { continue; }
|
329 |
|
330 |
foreach ($tagObject->attributes as $tagAttrs) {
|
331 |
if ($tagAttrs->nodeName === 'href') {
|
334 |
if (in_array($relNodeValue, $filesSources)) {
|
335 |
$htmlSourceBeforeLinkTagReplacement = $htmlSource;
|
336 |
|
337 |
+
$htmlSource = self::maybeStripExtraInlineAfterAppended($matchedSourceFromTag, $wpacuRegisteredStyles, '', $htmlSource);
|
338 |
|
339 |
if ($htmlSource !== $htmlSourceBeforeLinkTagReplacement) {
|
340 |
$linkTagsStrippedNo++;
|
399 |
* @param $shaOneForCombinedCss
|
400 |
* @param $localAssetsPaths
|
401 |
* @param $linkHrefs
|
402 |
+
* @param $localAssetsExtra
|
403 |
* @param $docLocationTag
|
404 |
*
|
405 |
* @return array
|
406 |
*/
|
407 |
+
public static function maybeDoCssCombine($shaOneForCombinedCss, $localAssetsPaths, $linkHrefs, $localAssetsExtra, $docLocationTag)
|
408 |
{
|
409 |
+
$uriToFinalCssFile = $docLocationTag . '-' .$shaOneForCombinedCss . '.css';
|
410 |
+
$localFinalCssFile = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . $uriToFinalCssFile;
|
|
|
|
|
|
|
|
|
|
|
411 |
|
412 |
// Only combine if $shaOneCombinedUriPaths.css does not exist
|
413 |
// If "?ver" value changes on any of the assets or the asset list changes in any way
|
429 |
|
430 |
$finalCombinedCssContent .= '/*! '.str_replace(ABSPATH, '/', $localAssetsPath)." */\n";
|
431 |
$finalCombinedCssContent .= OptimizeCss::maybeFixCssContent($cssContent, $pathToAssetDir . '/') . "\n";
|
432 |
+
|
433 |
+
$finalCombinedCssContent = self::appendToCombineCss($localAssetsExtra, $assetHref, $pathToAssetDir, $finalCombinedCssContent);
|
434 |
}
|
435 |
}
|
436 |
|
441 |
$finalCombinedCssContent = FontsGoogleRemove::cleanFontFaceReferences($finalCombinedCssContent);
|
442 |
}
|
443 |
|
444 |
+
$finalCombinedCssContent = apply_filters('wpacu_local_fonts_display_css_output', $finalCombinedCssContent, Main::instance()->settings['local_fonts_display']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
445 |
|
446 |
+
if ($finalCombinedCssContent) {
|
447 |
FileSystem::file_put_contents($localFinalCssFile, $finalCombinedCssContent);
|
448 |
}
|
449 |
}
|
457 |
|
458 |
/**
|
459 |
* @param $combinedUriPaths
|
460 |
+
* @param $localAssetsExtra
|
461 |
*
|
462 |
* @return string
|
463 |
*/
|
464 |
+
public static function generateShaOneForCombinedCss($combinedUriPaths, $localAssetsExtra)
|
465 |
{
|
466 |
+
$finalShaOneContent = implode('', $combinedUriPaths);
|
467 |
+
|
468 |
+
// If it is not empty, it means " Add inline tag contents associated with a style (handle) to the combined group of files after the main style's contents"
|
469 |
+
// is turned ON within "Combine loaded CSS (Stylesheets) into fewer files" (inside "Settings" -> "Optimize CSS")
|
470 |
+
if ( ! empty($localAssetsExtra) ) {
|
471 |
+
$afterContentForAll = '';
|
472 |
+
|
473 |
+
foreach ($localAssetsExtra as $values) {
|
474 |
+
if (isset($values['after']) && $values['after']) {
|
475 |
+
$afterContentForAll .= $values['after'];
|
476 |
+
}
|
477 |
+
}
|
478 |
+
|
479 |
+
$finalShaOneContent .= $afterContentForAll;
|
480 |
+
}
|
481 |
+
|
482 |
+
return sha1($finalShaOneContent);
|
483 |
+
}
|
484 |
+
|
485 |
+
/**
|
486 |
+
* @param $localAssetsExtra
|
487 |
+
* @param $assetHref
|
488 |
+
* @param $pathToAssetDir
|
489 |
+
* @param $finalAssetsContents
|
490 |
+
*
|
491 |
+
* @return string
|
492 |
+
*/
|
493 |
+
public static function appendToCombineCss($localAssetsExtra, $assetHref, $pathToAssetDir, $finalAssetsContents)
|
494 |
+
{
|
495 |
+
if (isset($localAssetsExtra[$assetHref]['after']) && ! empty($localAssetsExtra[$assetHref]['after'])) {
|
496 |
+
$afterCssContent = '';
|
497 |
+
|
498 |
+
foreach ($localAssetsExtra[$assetHref]['after'] as $afterData) {
|
499 |
+
if (! is_bool($afterData)) {
|
500 |
+
$afterCssContent .= $afterData."\n";
|
501 |
+
}
|
502 |
+
}
|
503 |
+
|
504 |
+
if (trim($afterCssContent) && Main::instance()->settings['minify_loaded_css'] && Main::instance()->settings['minify_loaded_css_inline']) {
|
505 |
+
$afterCssContent = MinifyCss::applyMinification($afterCssContent);
|
506 |
+
}
|
507 |
+
|
508 |
+
$afterCssContent = OptimizeCss::maybeFixCssContent($afterCssContent, $pathToAssetDir . '/');
|
509 |
+
|
510 |
+
$finalAssetsContents .= '/* [inline: after] */'.$afterCssContent.'/* [/inline: after] */'."\n";
|
511 |
+
}
|
512 |
+
|
513 |
+
return $finalAssetsContents;
|
514 |
+
}
|
515 |
+
|
516 |
+
/**
|
517 |
+
* The targeted LINK tag (which was enqueued and has a handle) is replaced with $replaceWith
|
518 |
+
* along with any inline content that was added after it via wp_add_inline_style()
|
519 |
+
*
|
520 |
+
* @param $targetedLinkTag
|
521 |
+
* @param $wpacuRegisteredStyles
|
522 |
+
* @param $replaceWith
|
523 |
+
* @param $htmlSource
|
524 |
+
*
|
525 |
+
* @return mixed
|
526 |
+
*/
|
527 |
+
public static function maybeStripExtraInlineAfterAppended($targetedLinkTag, $wpacuRegisteredStyles, $replaceWith, $htmlSource)
|
528 |
+
{
|
529 |
+
$scriptExtrasHtml = OptimizeCss::getInlineAssociatedWithLinkHandle($targetedLinkTag, $wpacuRegisteredStyles, 'tag', 'html');
|
530 |
+
$scriptExtraAfterHtml = (isset($scriptExtrasHtml['after']) && $scriptExtrasHtml['after']) ? "\n".$scriptExtrasHtml['after'] : '';
|
531 |
+
|
532 |
+
|
533 |
+
if ($scriptExtraAfterHtml) {
|
534 |
+
$htmlSource = str_replace(
|
535 |
+
array(
|
536 |
+
$targetedLinkTag . $scriptExtraAfterHtml,
|
537 |
+
$targetedLinkTag . trim($scriptExtraAfterHtml)
|
538 |
+
),
|
539 |
+
$replaceWith,
|
540 |
+
$htmlSource
|
541 |
+
);
|
542 |
+
} else {
|
543 |
+
$htmlSource = str_replace(
|
544 |
+
array(
|
545 |
+
$targetedLinkTag."\n",
|
546 |
+
$targetedLinkTag
|
547 |
+
),
|
548 |
+
$replaceWith."\n",
|
549 |
+
$htmlSource
|
550 |
+
);
|
551 |
+
}
|
552 |
+
|
553 |
+
return $htmlSource;
|
554 |
}
|
555 |
|
556 |
/**
|
classes/OptimiseAssets/CombineCssImports.php
CHANGED
@@ -3,7 +3,6 @@ namespace WpAssetCleanUp\OptimiseAssets;
|
|
3 |
|
4 |
use MatthiasMullie\Minify\Minify;
|
5 |
|
6 |
-
use MatthiasMullie\Minify\Exceptions\FileImportException;
|
7 |
use MatthiasMullie\PathConverter\ConverterInterface;
|
8 |
use MatthiasMullie\PathConverter\Converter;
|
9 |
|
@@ -103,7 +102,6 @@ class CombineCssImports extends Minify
|
|
103 |
*
|
104 |
* @return string
|
105 |
*
|
106 |
-
* @throws FileImportException
|
107 |
*/
|
108 |
protected function combineImports($source, $content, $parents)
|
109 |
{
|
3 |
|
4 |
use MatthiasMullie\Minify\Minify;
|
5 |
|
|
|
6 |
use MatthiasMullie\PathConverter\ConverterInterface;
|
7 |
use MatthiasMullie\PathConverter\Converter;
|
8 |
|
102 |
*
|
103 |
* @return string
|
104 |
*
|
|
|
105 |
*/
|
106 |
protected function combineImports($source, $content, $parents)
|
107 |
{
|
classes/OptimiseAssets/CombineJs.php
CHANGED
@@ -5,6 +5,7 @@ use WpAssetCleanUp\Main;
|
|
5 |
use WpAssetCleanUp\Menu;
|
6 |
use WpAssetCleanUp\FileSystem;
|
7 |
use WpAssetCleanUp\Misc;
|
|
|
8 |
|
9 |
/**
|
10 |
* Class CombineJs
|
@@ -24,7 +25,7 @@ class CombineJs
|
|
24 |
*/
|
25 |
public static function doCombine($htmlSource)
|
26 |
{
|
27 |
-
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('DOMDocument'))) {
|
28 |
return $htmlSource;
|
29 |
}
|
30 |
|
@@ -32,12 +33,12 @@ class CombineJs
|
|
32 |
return $htmlSource;
|
33 |
}
|
34 |
|
35 |
-
|
36 |
-
|
37 |
|
38 |
$combineLevel = 2;
|
39 |
|
40 |
-
$isDeferAppliedOnBodyCombineGroupNo =
|
41 |
|
42 |
// Speed up processing by getting the already existing final CSS file URI
|
43 |
// This will avoid parsing the HTML DOM and determine the combined URI paths for all the CSS files
|
@@ -46,62 +47,101 @@ class CombineJs
|
|
46 |
// $uriToFinalJsFile will always be relative ONLY within WP_CONTENT_DIR . self::getRelPathJsCacheDir()
|
47 |
// which is usually "wp-content/cache/asset-cleanup/js/"
|
48 |
|
49 |
-
// "
|
50 |
// for DEV purposes ONLY as it uses more resources
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
/*
|
53 |
* NO CACHING TRANSIENT; Parse the DOM
|
54 |
*/
|
55 |
// Nothing in the database records or the retrieved cached file does not exist?
|
56 |
OptimizeCommon::clearAssetCachedData(self::$jsonStorageFile);
|
57 |
|
58 |
-
// Fetch the DOM
|
59 |
-
$documentForJS = new \DOMDocument();
|
60 |
-
libxml_use_internal_errors(true);
|
61 |
-
|
62 |
$combinableList = array();
|
63 |
|
64 |
$jQueryMigrateInBody = false;
|
65 |
$jQueryLibInBodyCount = 0;
|
66 |
|
67 |
-
|
68 |
-
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
// Only keep combinable JS files
|
72 |
foreach ( array( 'head', 'body' ) as $docLocationScript ) {
|
73 |
$groupIndex = 1;
|
74 |
|
75 |
-
$docLocationElements = $
|
76 |
if ($docLocationElements === null) { continue; }
|
77 |
|
78 |
// High accuracy (e.g. it ignores tags inside HTML comments, conditional or not)
|
79 |
$scriptTags = $docLocationElements->getElementsByTagName('script');
|
80 |
if ($scriptTags === null) { continue; }
|
81 |
|
82 |
-
|
83 |
-
|
|
|
84 |
|
|
|
85 |
$scriptAttributes = array();
|
86 |
|
87 |
-
|
88 |
-
$
|
|
|
|
|
89 |
}
|
90 |
|
91 |
-
$scriptNotCombinable = false;
|
|
|
|
|
|
|
|
|
|
|
92 |
|
93 |
$hasSrc = isset($scriptAttributes['src']) && trim($scriptAttributes['src']); // No valid SRC attribute? It's not combinable (e.g. an inline tag)
|
94 |
$isPluginScript = isset($scriptAttributes['data-wpacu-plugin-script']); // Only of the user is logged-in (skip it as it belongs to the Asset CleanUp (Pro) plugin)
|
95 |
|
96 |
-
if (! $hasSrc || $isPluginScript) {
|
97 |
// Inline tag? Skip it in the BODY
|
98 |
if ($docLocationScript === 'body') {
|
99 |
continue;
|
100 |
}
|
101 |
|
102 |
// Because of jQuery, we will not have the list of all inline scripts and then the combined files as it is in BODY
|
103 |
-
// Once an inline SCRIPT is stumbled upon, a new combined group in the HEAD tag will be formed
|
104 |
if ($docLocationScript === 'head') {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
$scriptNotCombinable = true;
|
106 |
}
|
107 |
}
|
@@ -109,7 +149,8 @@ class CombineJs
|
|
109 |
$isInGroupType = 'standard';
|
110 |
$isJQueryLib = $isJQueryMigrate = false;
|
111 |
|
112 |
-
|
|
|
113 |
$src = (string)$scriptAttributes['src'];
|
114 |
|
115 |
if (self::skipCombine($src)) {
|
@@ -145,6 +186,12 @@ class CombineJs
|
|
145 |
if ( ! $scriptNotCombinable ) {
|
146 |
// It also checks the domain name to make sure no external scripts would be added to the list
|
147 |
if ( $localAssetPath = OptimizeCommon::getLocalAssetPath( $src, 'js' ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
// Standard (could be multiple groups per $docLocationScript), Async & Defer, Async, Defer
|
149 |
$groupByType = ($isInGroupType === 'standard') ? $groupIndex : $isInGroupType;
|
150 |
|
@@ -165,7 +212,8 @@ class CombineJs
|
|
165 |
'info' => array(
|
166 |
'is_jquery' => $isJQueryLib,
|
167 |
'is_jquery_migrate' => $isJQueryMigrate
|
168 |
-
)
|
|
|
169 |
);
|
170 |
|
171 |
if ($docLocationScript === 'body' && $jQueryLibInBodyCount === 2) {
|
@@ -198,6 +246,7 @@ class CombineJs
|
|
198 |
}
|
199 |
|
200 |
$combinedUriPaths = $localAssetsPaths = $groupScriptSrcs = array();
|
|
|
201 |
$jQueryIsIncludedInGroup = false;
|
202 |
|
203 |
foreach ($groupFiles as $groupFileData) {
|
@@ -215,6 +264,7 @@ class CombineJs
|
|
215 |
$groupScriptSrcs[] = $src;
|
216 |
$combinedUriPaths[] = OptimizeCommon::getSourceRelPath($src);
|
217 |
$localAssetsPaths[$src] = $groupFileData['local'];
|
|
|
218 |
}
|
219 |
|
220 |
$shaOneForCombinedJs = self::generateShaOneForCombinedJs($combinedUriPaths, $localAssetsExtra);
|
@@ -222,6 +272,7 @@ class CombineJs
|
|
222 |
$maybeDoJsCombine = self::maybeDoJsCombine(
|
223 |
$shaOneForCombinedJs . '-' . $groupNo,
|
224 |
$localAssetsPaths,
|
|
|
225 |
$docLocationScript
|
226 |
);
|
227 |
|
@@ -261,7 +312,7 @@ class CombineJs
|
|
261 |
|
262 |
// Apply defer="defer" to combined JS files from the BODY tag (if enabled), except the combined jQuery & jQuery Migrate Group
|
263 |
if ($docLocationScript === 'body' && ! $jQueryIsIncludedInGroup && Main::instance()->settings['combine_loaded_js_defer_body']) {
|
264 |
-
if ($isDeferAppliedOnBodyCombineGroupNo ===
|
265 |
// Only record the first one
|
266 |
$isDeferAppliedOnBodyCombineGroupNo = $groupNo;
|
267 |
}
|
@@ -327,7 +378,7 @@ HTML;
|
|
327 |
$replaceWith = ($groupScriptTagIndex === $indexReplacement) ? $finalJsTag : '';
|
328 |
$htmlSourceBeforeTagReplacement = $htmlSource;
|
329 |
|
330 |
-
$htmlSource =
|
331 |
|
332 |
if ($htmlSource !== $htmlSourceBeforeTagReplacement) {
|
333 |
$scriptTagsStrippedNo ++;
|
@@ -339,40 +390,71 @@ HTML;
|
|
339 |
if (count($filesSources) !== $scriptTagsStrippedNo) {
|
340 |
$htmlSource = $htmlSourceBeforeGroupReplacement;
|
341 |
}
|
342 |
-
|
343 |
-
}
|
344 |
}
|
345 |
}
|
346 |
|
347 |
// Only relevant if "Defer loading JavaScript combined files from <body>"" in "Settings" - "Combine CSS & JS Files" - "Combine loaded JS (JavaScript) into fewer files"
|
348 |
// and there is at least one combined deferred tag
|
349 |
-
if ($isDeferAppliedOnBodyCombineGroupNo > 0) {
|
350 |
-
$strPart = "id='wpacu-combined-js-body-group-".$isDeferAppliedOnBodyCombineGroupNo."' type='text/javascript' ";
|
351 |
-
list(,$htmlAfterFirstCombinedDeferScript) = explode($strPart, $htmlSource);
|
352 |
-
$htmlAfterFirstCombinedDeferScriptMaybeChanged = $htmlAfterFirstCombinedDeferScript;
|
353 |
|
354 |
-
|
355 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
356 |
|
357 |
-
|
|
|
358 |
|
359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
|
361 |
-
|
362 |
-
if ($scriptTags === null) {
|
363 |
-
libxml_clear_errors();
|
364 |
return $htmlSource;
|
365 |
}
|
366 |
|
367 |
foreach ($scriptTags as $scriptTagIndex => $tagObject) {
|
368 |
-
if (
|
369 |
-
continue;
|
370 |
-
}
|
371 |
|
372 |
$scriptAttributes = array();
|
373 |
|
374 |
-
foreach ($tagObject->attributes as $attrObj) {
|
375 |
-
$scriptAttributes[$attrObj->nodeName] = trim($attrObj->nodeValue);
|
376 |
}
|
377 |
|
378 |
// No "src" attribute? Skip it (most likely an inline script tag)
|
@@ -400,8 +482,6 @@ HTML;
|
|
400 |
|
401 |
libxml_clear_errors();
|
402 |
|
403 |
-
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
404 |
-
|
405 |
// Finally, return the HTML source
|
406 |
return $htmlSource;
|
407 |
}
|
@@ -447,24 +527,19 @@ HTML;
|
|
447 |
/**
|
448 |
* @param $shaOneForCombinedJs
|
449 |
* @param $localAssetsPaths
|
|
|
450 |
* @param $docLocationScript
|
451 |
*
|
452 |
* @return array
|
453 |
*/
|
454 |
-
public static function maybeDoJsCombine($shaOneForCombinedJs, $localAssetsPaths, $docLocationScript)
|
455 |
{
|
456 |
-
$
|
457 |
-
$dirToUserCachedFile = ((isset($current_user->ID) && $current_user->ID > 0) ? 'logged-in/' : '');
|
458 |
-
|
459 |
-
$uriToFinalJsFile = $dirToUserCachedFile . $docLocationScript . '-' . $shaOneForCombinedJs . '.js';
|
460 |
-
|
461 |
$localFinalJsFile = WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir() . $uriToFinalJsFile;
|
462 |
-
$localDirForJsFile = WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir() . $dirToUserCachedFile;
|
463 |
|
464 |
// Only combine if $shaOneCombinedUriPaths.js does not exist
|
465 |
// If "?ver" value changes on any of the assets or the asset list changes in any way
|
466 |
// then $shaOneCombinedUriPaths will change too and a new JS file will be generated and loaded
|
467 |
-
|
468 |
$skipIfFileExists = true;
|
469 |
|
470 |
if ($skipIfFileExists || ! is_file($localFinalJsFile)) {
|
@@ -484,23 +559,18 @@ HTML;
|
|
484 |
|
485 |
$pathToAssetDir = OptimizeCommon::getPathToAssetDir($assetHref);
|
486 |
|
487 |
-
$contentToAddToCombinedFile = '/*!
|
488 |
|
|
|
|
|
489 |
$contentToAddToCombinedFile .= OptimizeJs::maybeDoJsFixes($jsContent, $pathToAssetDir . '/') . "\n";
|
|
|
490 |
|
491 |
$finalJsContents .= $contentToAddToCombinedFile;
|
492 |
}
|
493 |
}
|
494 |
|
495 |
if ($finalJsContents !== '') {
|
496 |
-
if ($dirToUserCachedFile !== '' && isset($current_user->ID) && $current_user->ID > 0 && ! is_dir($localDirForJsFile)) {
|
497 |
-
$makeLocalDirForJs = @mkdir($localDirForJsFile);
|
498 |
-
|
499 |
-
if (! $makeLocalDirForJs) {
|
500 |
-
return array('uri_final_js_file' => '', 'local_final_js_file' => '');
|
501 |
-
}
|
502 |
-
}
|
503 |
-
|
504 |
FileSystem::file_put_contents($localFinalJsFile, $finalJsContents);
|
505 |
}
|
506 |
}
|
@@ -519,7 +589,130 @@ HTML;
|
|
519 |
*/
|
520 |
public static function generateShaOneForCombinedJs($combinedUriPaths, $localAssetsExtra)
|
521 |
{
|
522 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
523 |
}
|
524 |
|
525 |
/**
|
5 |
use WpAssetCleanUp\Menu;
|
6 |
use WpAssetCleanUp\FileSystem;
|
7 |
use WpAssetCleanUp\Misc;
|
8 |
+
use WpAssetCleanUp\ObjectCache;
|
9 |
|
10 |
/**
|
11 |
* Class CombineJs
|
25 |
*/
|
26 |
public static function doCombine($htmlSource)
|
27 |
{
|
28 |
+
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('\DOMDocument'))) {
|
29 |
return $htmlSource;
|
30 |
}
|
31 |
|
33 |
return $htmlSource;
|
34 |
}
|
35 |
|
36 |
+
global $wp_scripts;
|
37 |
+
$wpacuRegisteredScripts = $wp_scripts->registered;
|
38 |
|
39 |
$combineLevel = 2;
|
40 |
|
41 |
+
$isDeferAppliedOnBodyCombineGroupNo = false;
|
42 |
|
43 |
// Speed up processing by getting the already existing final CSS file URI
|
44 |
// This will avoid parsing the HTML DOM and determine the combined URI paths for all the CSS files
|
47 |
// $uriToFinalJsFile will always be relative ONLY within WP_CONTENT_DIR . self::getRelPathJsCacheDir()
|
48 |
// which is usually "wp-content/cache/asset-cleanup/js/"
|
49 |
|
50 |
+
// "true" would make it avoid checking the cache and always use the DOM Parser / RegExp
|
51 |
// for DEV purposes ONLY as it uses more resources
|
52 |
+
$skipCache = false;
|
53 |
+
|
54 |
+
if (isset($_GET['wpacu_no_cache'])) {
|
55 |
+
$skipCache = true;
|
56 |
+
}
|
57 |
+
|
58 |
+
if ( $skipCache || empty($finalCacheList) ) {
|
59 |
/*
|
60 |
* NO CACHING TRANSIENT; Parse the DOM
|
61 |
*/
|
62 |
// Nothing in the database records or the retrieved cached file does not exist?
|
63 |
OptimizeCommon::clearAssetCachedData(self::$jsonStorageFile);
|
64 |
|
|
|
|
|
|
|
|
|
65 |
$combinableList = array();
|
66 |
|
67 |
$jQueryMigrateInBody = false;
|
68 |
$jQueryLibInBodyCount = 0;
|
69 |
|
70 |
+
$minifyJsInlineTagsIsNotEnabled = ! (MinifyJs::isMinifyJsEnabled() && Main::instance()->settings['minify_loaded_js_inline']);
|
71 |
+
|
72 |
+
if ($minifyJsInlineTagsIsNotEnabled) {
|
73 |
+
$domTag = new \DOMDocument();
|
74 |
+
libxml_use_internal_errors(true);
|
75 |
+
|
76 |
+
// Strip irrelevant tags to boost the speed of the parser (e.g. NOSCRIPT / SCRIPT(inline) / STYLE)
|
77 |
+
// Sometimes, inline CODE can be too large and it takes extra time for loadHTML() to parse
|
78 |
+
$htmlSourceAlt = preg_replace( '@<script(| (type=(\'|"|)text/(javascript|template|html)(\'|"|)))>.*?</script>@si', '', $htmlSource );
|
79 |
+
$htmlSourceAlt = preg_replace( '@<(style|noscript)[^>]*?>.*?</\\1>@si', '', $htmlSourceAlt );
|
80 |
+
$htmlSourceAlt = preg_replace( '#<link([^<>]+)/?>#iU', '', $htmlSourceAlt );
|
81 |
+
|
82 |
+
if (Main::instance()->isFrontendEditView) {
|
83 |
+
$htmlSourceAlt = preg_replace( '@<form action="#wpacu_wrap_assets" method="post">.*?</form>@si', '', $htmlSourceAlt );
|
84 |
+
}
|
85 |
+
|
86 |
+
$domTag->loadHTML( $htmlSourceAlt );
|
87 |
+
} else {
|
88 |
+
$domTag = OptimizeCommon::getDomLoadedTag($htmlSource, 'combineJs');
|
89 |
+
}
|
90 |
|
91 |
// Only keep combinable JS files
|
92 |
foreach ( array( 'head', 'body' ) as $docLocationScript ) {
|
93 |
$groupIndex = 1;
|
94 |
|
95 |
+
$docLocationElements = $domTag->getElementsByTagName($docLocationScript)->item(0);
|
96 |
if ($docLocationElements === null) { continue; }
|
97 |
|
98 |
// High accuracy (e.g. it ignores tags inside HTML comments, conditional or not)
|
99 |
$scriptTags = $docLocationElements->getElementsByTagName('script');
|
100 |
if ($scriptTags === null) { continue; }
|
101 |
|
102 |
+
if ($docLocationScript && Main::instance()->settings['combine_loaded_js_defer_body']) {
|
103 |
+
ObjectCache::wpacu_cache_set('wpacu_html_dom_body_tag_for_js', $docLocationElements);
|
104 |
+
}
|
105 |
|
106 |
+
foreach ($scriptTags as $scriptTagIndex => $tagObject) {
|
107 |
$scriptAttributes = array();
|
108 |
|
109 |
+
if ( isset($tagObject->attributes) && ! empty($tagObject->attributes) ) {
|
110 |
+
foreach ( $tagObject->attributes as $attrObj ) {
|
111 |
+
$scriptAttributes[ $attrObj->nodeName ] = trim( $attrObj->nodeValue );
|
112 |
+
}
|
113 |
}
|
114 |
|
115 |
+
$scriptNotCombinable = false; // default (usually, most of the SCRIPT tags can be optimized)
|
116 |
+
|
117 |
+
// Check if the CSS file has any 'data-wpacu-skip' attribute; if it does, do not alter it
|
118 |
+
if (isset($scriptAttributes['data-wpacu-skip'])) {
|
119 |
+
$scriptNotCombinable = true;
|
120 |
+
}
|
121 |
|
122 |
$hasSrc = isset($scriptAttributes['src']) && trim($scriptAttributes['src']); // No valid SRC attribute? It's not combinable (e.g. an inline tag)
|
123 |
$isPluginScript = isset($scriptAttributes['data-wpacu-plugin-script']); // Only of the user is logged-in (skip it as it belongs to the Asset CleanUp (Pro) plugin)
|
124 |
|
125 |
+
if (! $scriptNotCombinable && (! $hasSrc || $isPluginScript)) {
|
126 |
// Inline tag? Skip it in the BODY
|
127 |
if ($docLocationScript === 'body') {
|
128 |
continue;
|
129 |
}
|
130 |
|
131 |
// Because of jQuery, we will not have the list of all inline scripts and then the combined files as it is in BODY
|
|
|
132 |
if ($docLocationScript === 'head') {
|
133 |
+
// Once an inline SCRIPT (with few exceptions below), except the ones associated with an enqueued script tag (with "src") is stumbled upon, a new combined group in the HEAD tag will be formed
|
134 |
+
if (isset($scriptAttributes['data-wpacu-script-handle']) && $scriptAttributes['data-wpacu-script-handle']) {
|
135 |
+
$getInlineAssociatedWithHandle = OptimizeJs::getInlineAssociatedWithScriptHandle($scriptAttributes['data-wpacu-script-handle'], $wpacuRegisteredScripts, 'handle');
|
136 |
+
|
137 |
+
if ( in_array(trim($tagObject->nodeValue), array($getInlineAssociatedWithHandle['before'], $getInlineAssociatedWithHandle['after']))
|
138 |
+
|| (strpos(trim($tagObject->nodeValue), '/* <![CDATA[ */') === 0 && Misc::endsWith(trim($tagObject->nodeValue), '/* ]]> */')) ) {
|
139 |
+
// It's associated with the enqueued scripts or it's a (standalone) CDATA inline tag added via wp_localize_script()
|
140 |
+
// Skip it instead and if the CDATA is not standalone (e.g. not associated with any script tag), the loop will "stay" in the same combined group
|
141 |
+
continue;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
$scriptNotCombinable = true;
|
146 |
}
|
147 |
}
|
149 |
$isInGroupType = 'standard';
|
150 |
$isJQueryLib = $isJQueryMigrate = false;
|
151 |
|
152 |
+
// Has SRC and $isPluginScript is set to false OR it does not have "data-wpacu-skip" attribute
|
153 |
+
if (! $scriptNotCombinable) {
|
154 |
$src = (string)$scriptAttributes['src'];
|
155 |
|
156 |
if (self::skipCombine($src)) {
|
186 |
if ( ! $scriptNotCombinable ) {
|
187 |
// It also checks the domain name to make sure no external scripts would be added to the list
|
188 |
if ( $localAssetPath = OptimizeCommon::getLocalAssetPath( $src, 'js' ) ) {
|
189 |
+
$scriptExtra = array();
|
190 |
+
|
191 |
+
if (isset($scriptAttributes['data-wpacu-script-handle'], $wpacuRegisteredScripts[$scriptAttributes['data-wpacu-script-handle']]->extra)) {
|
192 |
+
$scriptExtra = $wpacuRegisteredScripts[$scriptAttributes['data-wpacu-script-handle']]->extra;
|
193 |
+
}
|
194 |
+
|
195 |
// Standard (could be multiple groups per $docLocationScript), Async & Defer, Async, Defer
|
196 |
$groupByType = ($isInGroupType === 'standard') ? $groupIndex : $isInGroupType;
|
197 |
|
212 |
'info' => array(
|
213 |
'is_jquery' => $isJQueryLib,
|
214 |
'is_jquery_migrate' => $isJQueryMigrate
|
215 |
+
),
|
216 |
+
'extra' => $scriptExtra
|
217 |
);
|
218 |
|
219 |
if ($docLocationScript === 'body' && $jQueryLibInBodyCount === 2) {
|
246 |
}
|
247 |
|
248 |
$combinedUriPaths = $localAssetsPaths = $groupScriptSrcs = array();
|
249 |
+
$localAssetsExtra = array();
|
250 |
$jQueryIsIncludedInGroup = false;
|
251 |
|
252 |
foreach ($groupFiles as $groupFileData) {
|
264 |
$groupScriptSrcs[] = $src;
|
265 |
$combinedUriPaths[] = OptimizeCommon::getSourceRelPath($src);
|
266 |
$localAssetsPaths[$src] = $groupFileData['local'];
|
267 |
+
$localAssetsExtra[$src] = $groupFileData['extra'];
|
268 |
}
|
269 |
|
270 |
$shaOneForCombinedJs = self::generateShaOneForCombinedJs($combinedUriPaths, $localAssetsExtra);
|
272 |
$maybeDoJsCombine = self::maybeDoJsCombine(
|
273 |
$shaOneForCombinedJs . '-' . $groupNo,
|
274 |
$localAssetsPaths,
|
275 |
+
$localAssetsExtra,
|
276 |
$docLocationScript
|
277 |
);
|
278 |
|
312 |
|
313 |
// Apply defer="defer" to combined JS files from the BODY tag (if enabled), except the combined jQuery & jQuery Migrate Group
|
314 |
if ($docLocationScript === 'body' && ! $jQueryIsIncludedInGroup && Main::instance()->settings['combine_loaded_js_defer_body']) {
|
315 |
+
if ($isDeferAppliedOnBodyCombineGroupNo === false) {
|
316 |
// Only record the first one
|
317 |
$isDeferAppliedOnBodyCombineGroupNo = $groupNo;
|
318 |
}
|
378 |
$replaceWith = ($groupScriptTagIndex === $indexReplacement) ? $finalJsTag : '';
|
379 |
$htmlSourceBeforeTagReplacement = $htmlSource;
|
380 |
|
381 |
+
$htmlSource = self::maybeStripExtraInlineAfterAppended($scriptTag, $wpacuRegisteredScripts, $replaceWith, $htmlSource);
|
382 |
|
383 |
if ($htmlSource !== $htmlSourceBeforeTagReplacement) {
|
384 |
$scriptTagsStrippedNo ++;
|
390 |
if (count($filesSources) !== $scriptTagsStrippedNo) {
|
391 |
$htmlSource = $htmlSourceBeforeGroupReplacement;
|
392 |
}
|
393 |
+
}
|
|
|
394 |
}
|
395 |
}
|
396 |
|
397 |
// Only relevant if "Defer loading JavaScript combined files from <body>"" in "Settings" - "Combine CSS & JS Files" - "Combine loaded JS (JavaScript) into fewer files"
|
398 |
// and there is at least one combined deferred tag
|
|
|
|
|
|
|
|
|
399 |
|
400 |
+
if (isset($finalCacheList['body']) && (! empty($finalCacheList['body'])) && Main::instance()->settings['combine_loaded_js_defer_body']) {
|
401 |
+
// CACHE RE-BUILT
|
402 |
+
if ($isDeferAppliedOnBodyCombineGroupNo > 0 && $domTag = ObjectCache::wpacu_cache_get('wpacu_html_dom_body_tag_for_js')) {
|
403 |
+
$strPart = "id='wpacu-combined-js-body-group-".$isDeferAppliedOnBodyCombineGroupNo."' type='text/javascript' ";
|
404 |
+
list(,$htmlAfterFirstCombinedDeferScript) = explode($strPart, $htmlSource);
|
405 |
+
$htmlAfterFirstCombinedDeferScriptMaybeChanged = $htmlAfterFirstCombinedDeferScript;
|
406 |
+
$scriptTags = $domTag->getElementsByTagName('script');
|
407 |
+
} else {
|
408 |
+
// FROM THE CACHE
|
409 |
+
foreach ($finalCacheList['body'] as $bodyCombineGroupNo => $values) {
|
410 |
+
if (isset($values['extra_attributes']) && in_array('defer', $values['extra_attributes'])) {
|
411 |
+
$isDeferAppliedOnBodyCombineGroupNo = $bodyCombineGroupNo;
|
412 |
+
break;
|
413 |
+
}
|
414 |
+
}
|
415 |
+
|
416 |
+
if (! $isDeferAppliedOnBodyCombineGroupNo) {
|
417 |
+
// Not applicable to any combined group
|
418 |
+
return $htmlSource;
|
419 |
+
}
|
420 |
+
|
421 |
+
$strPart = "id='wpacu-combined-js-body-group-".$isDeferAppliedOnBodyCombineGroupNo."' type='text/javascript' ";
|
422 |
+
list(,$htmlAfterFirstCombinedDeferScript) = explode($strPart, $htmlSource);
|
423 |
+
$htmlAfterFirstCombinedDeferScriptMaybeChanged = $htmlAfterFirstCombinedDeferScript;
|
424 |
|
425 |
+
$domTag = new \DOMDocument();
|
426 |
+
libxml_use_internal_errors(true);
|
427 |
|
428 |
+
// Strip irrelevant tags to boost the speed of the parser (e.g. NOSCRIPT / SCRIPT(inline) / STYLE)
|
429 |
+
// Sometimes, inline CODE can be too large and it takes extra time for loadHTML() to parse
|
430 |
+
$htmlSourceAlt = preg_replace( '@<script(| type=\'text/javascript\'| type="text/javascript")>.*?</script>@si', '', $htmlAfterFirstCombinedDeferScript );
|
431 |
+
$htmlSourceAlt = preg_replace( '@<(style|noscript)[^>]*?>.*?</\\1>@si', '', $htmlSourceAlt );
|
432 |
+
$htmlSourceAlt = preg_replace( '#<link([^<>]+)/?>#iU', '', $htmlSourceAlt );
|
433 |
+
|
434 |
+
if (Main::instance()->isFrontendEditView) {
|
435 |
+
$htmlSourceAlt = preg_replace( '@<form action="#wpacu_wrap_assets" method="post">.*?</form>@si', '', $htmlSourceAlt );
|
436 |
+
}
|
437 |
+
|
438 |
+
// It could no other SCRIPT left, stop here in this case
|
439 |
+
if (strpos($htmlSource, '<script') !== false) {
|
440 |
+
return $htmlSource;
|
441 |
+
}
|
442 |
+
|
443 |
+
$domTag->loadHTML( $htmlSourceAlt );
|
444 |
+
$scriptTags = $domTag->getElementsByTagName('script');
|
445 |
+
}
|
446 |
|
447 |
+
if ( $scriptTags === null ) {
|
|
|
|
|
448 |
return $htmlSource;
|
449 |
}
|
450 |
|
451 |
foreach ($scriptTags as $scriptTagIndex => $tagObject) {
|
452 |
+
if (empty($tagObject->attributes)) { continue; }
|
|
|
|
|
453 |
|
454 |
$scriptAttributes = array();
|
455 |
|
456 |
+
foreach ( $tagObject->attributes as $attrObj ) {
|
457 |
+
$scriptAttributes[ $attrObj->nodeName ] = trim( $attrObj->nodeValue );
|
458 |
}
|
459 |
|
460 |
// No "src" attribute? Skip it (most likely an inline script tag)
|
482 |
|
483 |
libxml_clear_errors();
|
484 |
|
|
|
|
|
485 |
// Finally, return the HTML source
|
486 |
return $htmlSource;
|
487 |
}
|
527 |
/**
|
528 |
* @param $shaOneForCombinedJs
|
529 |
* @param $localAssetsPaths
|
530 |
+
* @param $localAssetsExtra
|
531 |
* @param $docLocationScript
|
532 |
*
|
533 |
* @return array
|
534 |
*/
|
535 |
+
public static function maybeDoJsCombine($shaOneForCombinedJs, $localAssetsPaths, $localAssetsExtra, $docLocationScript)
|
536 |
{
|
537 |
+
$uriToFinalJsFile = $docLocationScript . '-' . $shaOneForCombinedJs . '.js';
|
|
|
|
|
|
|
|
|
538 |
$localFinalJsFile = WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir() . $uriToFinalJsFile;
|
|
|
539 |
|
540 |
// Only combine if $shaOneCombinedUriPaths.js does not exist
|
541 |
// If "?ver" value changes on any of the assets or the asset list changes in any way
|
542 |
// then $shaOneCombinedUriPaths will change too and a new JS file will be generated and loaded
|
|
|
543 |
$skipIfFileExists = true;
|
544 |
|
545 |
if ($skipIfFileExists || ! is_file($localFinalJsFile)) {
|
559 |
|
560 |
$pathToAssetDir = OptimizeCommon::getPathToAssetDir($assetHref);
|
561 |
|
562 |
+
$contentToAddToCombinedFile = '/*!'.str_replace(ABSPATH, '/', $localAssetsPath)."*/\n";
|
563 |
|
564 |
+
// This includes the extra from 'data' (CDATA added via wp_localize_script()) & 'before' as they are both printed BEFORE the tag
|
565 |
+
$contentToAddToCombinedFile .= self::appendToCombineScript('before', $localAssetsExtra, $assetHref, $pathToAssetDir);
|
566 |
$contentToAddToCombinedFile .= OptimizeJs::maybeDoJsFixes($jsContent, $pathToAssetDir . '/') . "\n";
|
567 |
+
$contentToAddToCombinedFile .= self::appendToCombineScript('after', $localAssetsExtra, $assetHref, $pathToAssetDir);
|
568 |
|
569 |
$finalJsContents .= $contentToAddToCombinedFile;
|
570 |
}
|
571 |
}
|
572 |
|
573 |
if ($finalJsContents !== '') {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
574 |
FileSystem::file_put_contents($localFinalJsFile, $finalJsContents);
|
575 |
}
|
576 |
}
|
589 |
*/
|
590 |
public static function generateShaOneForCombinedJs($combinedUriPaths, $localAssetsExtra)
|
591 |
{
|
592 |
+
$finalShaOneContent = implode('', $combinedUriPaths);
|
593 |
+
|
594 |
+
// If it is not empty, it means " Add inline tag contents associated with a style (handle) to the combined group of files after the main style's contents"
|
595 |
+
// is turned ON within "Combine loaded JS (JavaScript) into fewer files" (inside "Settings" -> "Optimize JavaScript")
|
596 |
+
if ( ! empty($localAssetsExtra) ) {
|
597 |
+
$afterContentForAll = '';
|
598 |
+
|
599 |
+
foreach ( $localAssetsExtra as $values ) {
|
600 |
+
foreach ( array('data', 'before', 'after') as $keyToCheck ) {
|
601 |
+
if ( isset( $values[$keyToCheck] ) && $values[$keyToCheck] ) {
|
602 |
+
$afterContentForAll .= $values[$keyToCheck];
|
603 |
+
}
|
604 |
+
}
|
605 |
+
}
|
606 |
+
|
607 |
+
$finalShaOneContent .= $afterContentForAll;
|
608 |
+
}
|
609 |
+
|
610 |
+
return sha1($finalShaOneContent);
|
611 |
+
}
|
612 |
+
|
613 |
+
/**
|
614 |
+
* @param $addItLocation
|
615 |
+
* @param $localAssetsExtra
|
616 |
+
* @param $assetHref
|
617 |
+
* @param $pathToAssetDir
|
618 |
+
*
|
619 |
+
* @return string
|
620 |
+
*/
|
621 |
+
public static function appendToCombineScript($addItLocation, $localAssetsExtra, $assetHref, $pathToAssetDir)
|
622 |
+
{
|
623 |
+
$extraContentToAppend = '';
|
624 |
+
$doJsMinifyInline = Main::instance()->settings['minify_loaded_js'] && Main::instance()->settings['minify_loaded_js_inline'];
|
625 |
+
|
626 |
+
if ($addItLocation === 'before') {
|
627 |
+
// [Before JS Content]
|
628 |
+
if (isset($localAssetsExtra[$assetHref]['data'])) {
|
629 |
+
$cData = $doJsMinifyInline
|
630 |
+
? MinifyJs::applyMinification($localAssetsExtra[$assetHref]['data'])
|
631 |
+
: $localAssetsExtra[$assetHref]['data'];
|
632 |
+
$cData = OptimizeJs::maybeDoJsFixes($cData, $pathToAssetDir . '/');
|
633 |
+
$extraContentToAppend .= '/* [inline: cdata] */' . $cData . '/* [/inline: cdata] */' . "\n";
|
634 |
+
}
|
635 |
+
|
636 |
+
if (isset($localAssetsExtra[$assetHref]['before']) && ! empty($localAssetsExtra[$assetHref]['before'])) {
|
637 |
+
$inlineBeforeJsData = '';
|
638 |
+
|
639 |
+
foreach ($localAssetsExtra[$assetHref]['before'] as $beforeData) {
|
640 |
+
if (! is_bool($beforeData)) {
|
641 |
+
$inlineBeforeJsData .= $beforeData . "\n";
|
642 |
+
}
|
643 |
+
}
|
644 |
+
|
645 |
+
$inlineBeforeJsData = OptimizeJs::maybeAlterContentForInlineScriptTag($inlineBeforeJsData, $doJsMinifyInline);
|
646 |
+
$inlineBeforeJsData = OptimizeJs::maybeDoJsFixes($inlineBeforeJsData, $pathToAssetDir . '/');
|
647 |
+
|
648 |
+
$extraContentToAppend .= '/* [inline: before] */' . $inlineBeforeJsData . '/* [/inline: before] */' . "\n";
|
649 |
+
}
|
650 |
+
// [/Before JS Content]
|
651 |
+
} elseif ($addItLocation === 'after') {
|
652 |
+
// [After JS Content]
|
653 |
+
if (isset($localAssetsExtra[$assetHref]['after']) && ! empty($localAssetsExtra[$assetHref]['after'])) {
|
654 |
+
$inlineAfterJsData = '';
|
655 |
+
|
656 |
+
foreach ($localAssetsExtra[$assetHref]['after'] as $afterData) {
|
657 |
+
if (! is_bool($afterData)) {
|
658 |
+
$inlineAfterJsData .= $afterData."\n";
|
659 |
+
}
|
660 |
+
}
|
661 |
+
|
662 |
+
$inlineAfterJsData = OptimizeJs::maybeAlterContentForInlineScriptTag($inlineAfterJsData, $doJsMinifyInline);
|
663 |
+
$inlineAfterJsData = OptimizeJs::maybeDoJsFixes($inlineAfterJsData, $pathToAssetDir . '/');
|
664 |
+
|
665 |
+
$extraContentToAppend .= '/* [inline: after] */'.$inlineAfterJsData.'/* [/inline: after] */'."\n";
|
666 |
+
}
|
667 |
+
// [/After JS Content]
|
668 |
+
}
|
669 |
+
|
670 |
+
return $extraContentToAppend;
|
671 |
+
}
|
672 |
+
|
673 |
+
/**
|
674 |
+
* @param $scriptTag
|
675 |
+
* @param $wpacuRegisteredScripts
|
676 |
+
* @param $replaceWith
|
677 |
+
* @param $htmlSource
|
678 |
+
*
|
679 |
+
* @return mixed
|
680 |
+
*/
|
681 |
+
public static function maybeStripExtraInlineAfterAppended($scriptTag, $wpacuRegisteredScripts, $replaceWith, $htmlSource)
|
682 |
+
{
|
683 |
+
$scriptExtrasValue = OptimizeJs::getInlineAssociatedWithScriptHandle($scriptTag, $wpacuRegisteredScripts, 'tag', 'value');
|
684 |
+
|
685 |
+
$scriptExtraCdataValue = (isset($scriptExtrasValue['data']) && $scriptExtrasValue['data']) ? $scriptExtrasValue['data'] : '';
|
686 |
+
$scriptExtraBeforeValue = (isset($scriptExtrasValue['before']) && $scriptExtrasValue['before']) ? $scriptExtrasValue['before'] : '';
|
687 |
+
$scriptExtraAfterValue = (isset($scriptExtrasValue['after']) && $scriptExtrasValue['after']) ? $scriptExtrasValue['after'] : '';
|
688 |
+
|
689 |
+
$scriptExtrasHtml = OptimizeJs::getInlineAssociatedWithScriptHandle($scriptTag, $wpacuRegisteredScripts, 'tag', 'html');
|
690 |
+
|
691 |
+
$scriptExtraCdataHtml = (isset($scriptExtrasHtml['data']) && $scriptExtrasHtml['data']) ? $scriptExtrasHtml['data'] : '';
|
692 |
+
$scriptExtraBeforeHtml = (isset($scriptExtrasHtml['before']) && $scriptExtrasHtml['before']) ? $scriptExtrasHtml['before'] : '';
|
693 |
+
$scriptExtraAfterHtml = (isset($scriptExtrasHtml['after']) && $scriptExtrasHtml['after']) ? $scriptExtrasHtml['after'] : '';
|
694 |
+
|
695 |
+
if ($scriptExtraCdataValue || $scriptExtraBeforeValue || $scriptExtraAfterValue) {
|
696 |
+
if ($scriptExtraCdataValue) {
|
697 |
+
$htmlSource = str_replace($scriptExtraCdataHtml, '', $htmlSource );
|
698 |
+
}
|
699 |
+
|
700 |
+
if ($scriptExtraBeforeValue) {
|
701 |
+
$repsBefore = array($scriptExtraBeforeHtml => '', '>'."\n".$scriptExtraBeforeValue."\n".'</script>' => '></script>');
|
702 |
+
$htmlSource = str_replace(array_keys($repsBefore), array_values($repsBefore), $htmlSource );
|
703 |
+
}
|
704 |
+
|
705 |
+
if ($scriptExtraAfterValue) {
|
706 |
+
$repsBefore = array($scriptExtraAfterHtml => '', '>'."\n".$scriptExtraAfterValue."\n".'</script>' => '></script>');
|
707 |
+
$htmlSource = str_replace(array_keys($repsBefore), array_values($repsBefore), $htmlSource );
|
708 |
+
}
|
709 |
+
|
710 |
+
$htmlSource = str_replace($scriptTag, $replaceWith, $htmlSource);
|
711 |
+
} else {
|
712 |
+
$htmlSource = OptimizeJs::strReplaceOnce($scriptTag, $replaceWith, $htmlSource);
|
713 |
+
}
|
714 |
+
|
715 |
+
return $htmlSource;
|
716 |
}
|
717 |
|
718 |
/**
|
classes/OptimiseAssets/FontsGoogle.php
CHANGED
@@ -47,6 +47,11 @@ class FontsGoogle
|
|
47 |
echo self::NOSCRIPT_WEB_FONT_LOADER;
|
48 |
}, PHP_INT_MAX);
|
49 |
|
|
|
|
|
|
|
|
|
|
|
50 |
add_action('init', function() {
|
51 |
// don't apply any changes if not in the front-end view (e.g. Dashboard view)
|
52 |
// or test mode is enabled and a guest user is accessing the page
|
@@ -185,6 +190,11 @@ class FontsGoogle
|
|
185 |
continue;
|
186 |
}
|
187 |
|
|
|
|
|
|
|
|
|
|
|
188 |
preg_match_all('#href=(["\'])' . '(.*)' . '(["\'])#Usmi', $linkTag, $outputMatches);
|
189 |
$linkHrefOriginal = $finalLinkHref = trim($outputMatches[2][0], '"\'');
|
190 |
|
@@ -229,6 +239,8 @@ class FontsGoogle
|
|
229 |
}
|
230 |
}
|
231 |
|
|
|
|
|
232 |
// Only proceed with the optimization/combine if there's obviously at least 2 combinable URL requests to Google Fonts
|
233 |
// OR the loading type is different than render-blocking
|
234 |
if (Main::instance()->settings['google_fonts_combine'] && (Main::instance()->settings['google_fonts_combine_type'] || count($finalCombinableLinks) > 1)) {
|
@@ -313,6 +325,11 @@ class FontsGoogle
|
|
313 |
foreach ($styleMatches as $styleInlineArray) {
|
314 |
list($styleInlineTag, $styleInlineContent) = $styleInlineArray;
|
315 |
|
|
|
|
|
|
|
|
|
|
|
316 |
// Is the content relevant?
|
317 |
if (! preg_match('/@import(\s+|)(url|\(|\'|")/i', $styleInlineContent)
|
318 |
|| stripos($styleInlineContent, 'fonts.googleapis.com') === false) {
|
@@ -600,18 +617,14 @@ HTML;
|
|
600 |
|
601 |
// Any types? e.g. 400, 400italic, bold, etc.
|
602 |
$hasTypes = false;
|
603 |
-
if (isset($fontValues['types']) &&
|
604 |
-
$wfConfigGoogleFamily .= ':'
|
605 |
$hasTypes = true;
|
606 |
}
|
607 |
|
608 |
if ($subSetsStr) {
|
609 |
-
//
|
610 |
-
|
611 |
-
$wfConfigGoogleFamily .= ':regular';
|
612 |
-
}
|
613 |
-
|
614 |
-
$wfConfigGoogleFamily .= ':' . $subSetsStr;
|
615 |
}
|
616 |
|
617 |
// Append extra parameters to the last family from the list
|
47 |
echo self::NOSCRIPT_WEB_FONT_LOADER;
|
48 |
}, PHP_INT_MAX);
|
49 |
|
50 |
+
add_filter('wpacu_html_source_after_optimization', static function($htmlSource) {
|
51 |
+
// Is the mark still there and wasn't replaced? Strip it
|
52 |
+
return str_replace(FontsGoogle::NOSCRIPT_WEB_FONT_LOADER, '', $htmlSource);
|
53 |
+
});
|
54 |
+
|
55 |
add_action('init', function() {
|
56 |
// don't apply any changes if not in the front-end view (e.g. Dashboard view)
|
57 |
// or test mode is enabled and a guest user is accessing the page
|
190 |
continue;
|
191 |
}
|
192 |
|
193 |
+
// Check if the CSS has any 'data-wpacu-skip' attribute; if it does, do not continue and leave it as it is (non-combined)
|
194 |
+
if (preg_match('#data-wpacu-skip([=>/ ])#i', $linkTag)) {
|
195 |
+
continue;
|
196 |
+
}
|
197 |
+
|
198 |
preg_match_all('#href=(["\'])' . '(.*)' . '(["\'])#Usmi', $linkTag, $outputMatches);
|
199 |
$linkHrefOriginal = $finalLinkHref = trim($outputMatches[2][0], '"\'');
|
200 |
|
239 |
}
|
240 |
}
|
241 |
|
242 |
+
$finalCombinableLinks = array_values($finalCombinableLinks);
|
243 |
+
|
244 |
// Only proceed with the optimization/combine if there's obviously at least 2 combinable URL requests to Google Fonts
|
245 |
// OR the loading type is different than render-blocking
|
246 |
if (Main::instance()->settings['google_fonts_combine'] && (Main::instance()->settings['google_fonts_combine_type'] || count($finalCombinableLinks) > 1)) {
|
325 |
foreach ($styleMatches as $styleInlineArray) {
|
326 |
list($styleInlineTag, $styleInlineContent) = $styleInlineArray;
|
327 |
|
328 |
+
// Check if the STYLE tag has any 'data-wpacu-skip' attribute; if it does, do not continue
|
329 |
+
if (preg_match('#data-wpacu-skip([=>/ ])#i', $styleInlineTag)) {
|
330 |
+
continue;
|
331 |
+
}
|
332 |
+
|
333 |
// Is the content relevant?
|
334 |
if (! preg_match('/@import(\s+|)(url|\(|\'|")/i', $styleInlineContent)
|
335 |
|| stripos($styleInlineContent, 'fonts.googleapis.com') === false) {
|
617 |
|
618 |
// Any types? e.g. 400, 400italic, bold, etc.
|
619 |
$hasTypes = false;
|
620 |
+
if (isset($fontValues['types']) && $fontValues['types']) {
|
621 |
+
$wfConfigGoogleFamily .= ':'.$fontValues['types'];
|
622 |
$hasTypes = true;
|
623 |
}
|
624 |
|
625 |
if ($subSetsStr) {
|
626 |
+
// If there are types, continue to use the comma delimiter
|
627 |
+
$wfConfigGoogleFamily .= ($hasTypes ? ',' : ':') . $subSetsStr;
|
|
|
|
|
|
|
|
|
628 |
}
|
629 |
|
630 |
// Append extra parameters to the last family from the list
|
classes/OptimiseAssets/FontsGoogleRemove.php
CHANGED
@@ -47,12 +47,8 @@ class FontsGoogleRemove
|
|
47 |
*/
|
48 |
public static function cleanLinkTags($htmlSource)
|
49 |
{
|
50 |
-
// Cleaner HTML Source
|
51 |
-
$altHtmlSource = preg_replace('@<(script|style)[^>]*?>.*?</\\1>@si', '', $htmlSource);
|
52 |
-
$altHtmlSource = preg_replace('/<!--(.|\s)*?-->/', '', $altHtmlSource);
|
53 |
-
|
54 |
// Do not continue if there is no single reference to the string we look for in the clean HTML source
|
55 |
-
if (stripos($
|
56 |
return $htmlSource;
|
57 |
}
|
58 |
|
@@ -63,14 +59,28 @@ class FontsGoogleRemove
|
|
63 |
|
64 |
$strContainsFormat = implode('|', $strContainsArray);
|
65 |
|
66 |
-
preg_match_all('#<link[^>]*(' . $strContainsFormat . ').*(>)#Usmi', $
|
|
|
|
|
67 |
|
68 |
// Needs to match at least one to carry on with the replacements
|
69 |
if (isset($matchesFromLinkTags[0]) && ! empty($matchesFromLinkTags[0])) {
|
70 |
foreach ($matchesFromLinkTags as $linkIndex => $linkTagArray) {
|
71 |
$linkTag = trim(trim($linkTagArray[0], '"\''));
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
}
|
|
|
|
|
74 |
}
|
75 |
|
76 |
return $htmlSource;
|
@@ -97,6 +107,11 @@ class FontsGoogleRemove
|
|
97 |
foreach ($styleMatches as $styleInlineArray) {
|
98 |
list($styleInlineTag, $styleInlineContent) = $styleInlineArray;
|
99 |
|
|
|
|
|
|
|
|
|
|
|
100 |
$newStyleInlineTag = $styleInlineTag;
|
101 |
$newStyleInlineContent = $styleInlineContent;
|
102 |
|
47 |
*/
|
48 |
public static function cleanLinkTags($htmlSource)
|
49 |
{
|
|
|
|
|
|
|
|
|
50 |
// Do not continue if there is no single reference to the string we look for in the clean HTML source
|
51 |
+
if (stripos($htmlSource, FontsGoogle::$containsStr) === false) {
|
52 |
return $htmlSource;
|
53 |
}
|
54 |
|
59 |
|
60 |
$strContainsFormat = implode('|', $strContainsArray);
|
61 |
|
62 |
+
preg_match_all('#<link[^>]*(' . $strContainsFormat . ').*(>)#Usmi', $htmlSource, $matchesFromLinkTags, PREG_SET_ORDER);
|
63 |
+
|
64 |
+
$stripLinksList = array();
|
65 |
|
66 |
// Needs to match at least one to carry on with the replacements
|
67 |
if (isset($matchesFromLinkTags[0]) && ! empty($matchesFromLinkTags[0])) {
|
68 |
foreach ($matchesFromLinkTags as $linkIndex => $linkTagArray) {
|
69 |
$linkTag = trim(trim($linkTagArray[0], '"\''));
|
70 |
+
|
71 |
+
if (strip_tags($linkTag) !== '') {
|
72 |
+
continue; // Something might be funny there, make sure the tag is valid
|
73 |
+
}
|
74 |
+
|
75 |
+
// Check if the Google Fonts CSS has any 'data-wpacu-skip' attribute; if it does, do not remove it
|
76 |
+
if (preg_match('#data-wpacu-skip([=>/ ])#i', $linkTag)) {
|
77 |
+
continue;
|
78 |
+
}
|
79 |
+
|
80 |
+
$stripLinksList[$linkTag] = '';
|
81 |
}
|
82 |
+
|
83 |
+
$htmlSource = strtr($htmlSource, $stripLinksList);
|
84 |
}
|
85 |
|
86 |
return $htmlSource;
|
107 |
foreach ($styleMatches as $styleInlineArray) {
|
108 |
list($styleInlineTag, $styleInlineContent) = $styleInlineArray;
|
109 |
|
110 |
+
// Check if the STYLE tag has any 'data-wpacu-skip' attribute; if it does, do not continue
|
111 |
+
if (preg_match('#data-wpacu-skip([=>/ ])#i', $styleInlineTag)) {
|
112 |
+
continue;
|
113 |
+
}
|
114 |
+
|
115 |
$newStyleInlineTag = $styleInlineTag;
|
116 |
$newStyleInlineContent = $styleInlineContent;
|
117 |
|
classes/OptimiseAssets/MinifyCss.php
CHANGED
@@ -21,6 +21,17 @@ class MinifyCss
|
|
21 |
public static function applyMinification($cssContent, $forInlineStyle = false)
|
22 |
{
|
23 |
if (class_exists('\MatthiasMullie\Minify\CSS')) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
$minifier = new \MatthiasMullie\Minify\CSS( $cssContent );
|
25 |
|
26 |
if ( $forInlineStyle ) {
|
@@ -29,7 +40,18 @@ class MinifyCss
|
|
29 |
$minifier->setImportExtensions( array() );
|
30 |
}
|
31 |
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
}
|
34 |
|
35 |
return $cssContent;
|
@@ -111,61 +133,127 @@ class MinifyCss
|
|
111 |
return $htmlSource; // no STYLE tags
|
112 |
}
|
113 |
|
114 |
-
// DOMDocument extension has to be enabled, otherwise return the HTML source as was (no changes)
|
115 |
-
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('\DOMDocument'))) {
|
116 |
-
return $htmlSource;
|
117 |
-
}
|
118 |
-
|
119 |
-
$domTag = new \DOMDocument();
|
120 |
-
libxml_use_internal_errors(true);
|
121 |
-
$domTag->loadHTML($htmlSource);
|
122 |
-
|
123 |
-
$styleTagsObj = $domTag->getElementsByTagName( 'style' );
|
124 |
-
|
125 |
-
if ($styleTagsObj === null) {
|
126 |
-
return $htmlSource;
|
127 |
-
}
|
128 |
-
|
129 |
$skipTagsContaining = array(
|
|
|
130 |
'astra-theme-css-inline-css',
|
131 |
'astra-edd-inline-css',
|
132 |
'et-builder-module-design-cached-inline-styles',
|
133 |
'fusion-stylesheet-inline-css',
|
134 |
'woocommerce-general-inline-css',
|
135 |
'woocommerce-inline-inline-css',
|
136 |
-
'data-wpacu-own-inline-style',
|
137 |
-
|
|
|
|
|
138 |
);
|
139 |
|
140 |
-
|
141 |
-
$originalTag = CleanUp::getOuterHTML($styleTagObj);
|
142 |
|
143 |
-
|
144 |
-
|
145 |
-
|
|
|
146 |
}
|
147 |
|
148 |
-
$
|
149 |
|
150 |
-
|
151 |
-
$newTagContents = OptimizeCss::maybeAlterCssContent($originalTagContents, true, true, array('just_minify'));
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
|
157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
|
159 |
-
|
160 |
-
|
161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
}
|
163 |
-
} else {
|
164 |
-
// It has content; do the replacement
|
165 |
-
$htmlSource = str_ireplace( '>' . $originalTagContents . '</style',
|
166 |
-
'>' . $newTagContents . '</style', $htmlSource );
|
167 |
}
|
168 |
-
libxml_clear_errors();
|
169 |
}
|
170 |
}
|
171 |
|
21 |
public static function applyMinification($cssContent, $forInlineStyle = false)
|
22 |
{
|
23 |
if (class_exists('\MatthiasMullie\Minify\CSS')) {
|
24 |
+
$sha1OriginalContent = sha1($cssContent);
|
25 |
+
|
26 |
+
// Let's check if the content is already minified
|
27 |
+
// Save resources as the minify process can take time if the content is very large
|
28 |
+
if (OptimizeCommon::originalContentIsAlreadyMarkedAsMinified($sha1OriginalContent, 'styles')) {
|
29 |
+
return $cssContent;
|
30 |
+
}
|
31 |
+
|
32 |
+
// Minify it
|
33 |
+
$alreadyMinified = false; // default
|
34 |
+
|
35 |
$minifier = new \MatthiasMullie\Minify\CSS( $cssContent );
|
36 |
|
37 |
if ( $forInlineStyle ) {
|
40 |
$minifier->setImportExtensions( array() );
|
41 |
}
|
42 |
|
43 |
+
$minifiedContent = trim( $minifier->minify() );
|
44 |
+
|
45 |
+
if ($minifiedContent === $cssContent) {
|
46 |
+
$alreadyMinified = true;
|
47 |
+
}
|
48 |
+
|
49 |
+
// If the resulting content is the same, mark it as minified to avoid the minify process next time
|
50 |
+
if ($alreadyMinified) {
|
51 |
+
OptimizeCommon::originalContentMarkAsAlreadyMinified( $sha1OriginalContent, 'styles' );
|
52 |
+
}
|
53 |
+
|
54 |
+
return $minifiedContent;
|
55 |
}
|
56 |
|
57 |
return $cssContent;
|
133 |
return $htmlSource; // no STYLE tags
|
134 |
}
|
135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
$skipTagsContaining = array(
|
137 |
+
'data-wpacu-skip',
|
138 |
'astra-theme-css-inline-css',
|
139 |
'astra-edd-inline-css',
|
140 |
'et-builder-module-design-cached-inline-styles',
|
141 |
'fusion-stylesheet-inline-css',
|
142 |
'woocommerce-general-inline-css',
|
143 |
'woocommerce-inline-inline-css',
|
144 |
+
'data-wpacu-own-inline-style',
|
145 |
+
// Only shown to the admin, irrelevant for any optimization (save resources)
|
146 |
+
'data-wpacu-inline-css-file'
|
147 |
+
// already minified/optimized since the INLINE was generated from the cached file
|
148 |
);
|
149 |
|
150 |
+
$fetchType = 'regex';
|
|
|
151 |
|
152 |
+
if ($fetchType === 'dom') {
|
153 |
+
// DOMDocument extension has to be enabled, otherwise return the HTML source as was (no changes)
|
154 |
+
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('\DOMDocument'))) {
|
155 |
+
return $htmlSource;
|
156 |
}
|
157 |
|
158 |
+
$domTag = OptimizeCommon::getDomLoadedTag($htmlSource, 'minifyInlineStyleTags');
|
159 |
|
160 |
+
$styleTagsObj = $domTag->getElementsByTagName( 'style' );
|
|
|
161 |
|
162 |
+
if ( $styleTagsObj === null ) {
|
163 |
+
return $htmlSource;
|
164 |
+
}
|
165 |
|
166 |
+
foreach ( $styleTagsObj as $styleTagObj ) {
|
167 |
+
$originalTag = CleanUp::getOuterHTML( $styleTagObj );
|
168 |
+
|
169 |
+
// No need to use extra resources as the tag is already minified
|
170 |
+
if ( preg_match( '(' . implode( '|', $skipTagsContaining ) . ')', $originalTag ) ) {
|
171 |
+
continue;
|
172 |
+
}
|
173 |
+
|
174 |
+
$originalTagContents = ( isset( $styleTagObj->nodeValue ) && trim( $styleTagObj->nodeValue ) !== '' ) ? $styleTagObj->nodeValue : false;
|
175 |
+
|
176 |
+
if ( $originalTagContents ) {
|
177 |
+
$newTagContents = OptimizeCss::maybeAlterContentForInlineStyleTag( $originalTagContents, true, array( 'just_minify' ) );
|
178 |
+
|
179 |
+
// Only comments or no content added to the inline STYLE tag? Strip it completely to reduce the number of DOM elements
|
180 |
+
if ( $newTagContents === '/**/' || ! $newTagContents ) {
|
181 |
+
$htmlSource = str_ireplace( '>' . $originalTagContents . '</style', '></style', $htmlSource );
|
182 |
+
|
183 |
+
preg_match( '#<style.*?>#si', $originalTag, $matchFromStyle );
|
184 |
+
|
185 |
+
if ( isset( $matchFromStyle[0] ) && $styleTagWithoutContent = $matchFromStyle[0] ) {
|
186 |
+
$styleTagWithoutContentAlt = str_replace( '"', '\'', $styleTagWithoutContent );
|
187 |
+
$htmlSource = str_ireplace( array(
|
188 |
+
$styleTagWithoutContent . '</style>',
|
189 |
+
$styleTagWithoutContentAlt . '</style>'
|
190 |
+
), '', $htmlSource );
|
191 |
+
}
|
192 |
+
} else {
|
193 |
+
// It has content; do the replacement
|
194 |
+
$htmlSource = str_ireplace(
|
195 |
+
'>' . $originalTagContents . '</style>',
|
196 |
+
'>' . $newTagContents . '</style>',
|
197 |
+
$htmlSource
|
198 |
+
);
|
199 |
+
}
|
200 |
+
libxml_clear_errors();
|
201 |
+
}
|
202 |
+
}
|
203 |
+
} elseif ($fetchType === 'regex') {
|
204 |
+
preg_match_all( '@(<style[^>]*?>).*?</style>@si', $htmlSource, $matchesStyleTags, PREG_SET_ORDER );
|
205 |
+
|
206 |
+
if ( $matchesStyleTags === null ) {
|
207 |
+
return $htmlSource;
|
208 |
+
}
|
209 |
+
|
210 |
+
foreach ($matchesStyleTags as $matchedStyle) {
|
211 |
+
if ( ! (isset($matchedStyle[0]) && $matchedStyle[0]) ) {
|
212 |
+
continue;
|
213 |
+
}
|
214 |
+
|
215 |
+
$originalTag = $matchedStyle[0];
|
216 |
+
|
217 |
+
if (substr($originalTag, -strlen('></style>')) === strtolower('></style>')) {
|
218 |
+
// No empty STYLE tags
|
219 |
+
continue;
|
220 |
+
}
|
221 |
+
|
222 |
+
// No need to use extra resources as the tag is already minified
|
223 |
+
if ( preg_match( '(' . implode( '|', $skipTagsContaining ) . ')', $originalTag ) ) {
|
224 |
+
continue;
|
225 |
+
}
|
226 |
|
227 |
+
$tagOpen = $matchedStyle[1];
|
228 |
+
|
229 |
+
$withTagOpenStripped = substr($originalTag, strlen($tagOpen));
|
230 |
+
$originalTagContents = substr($withTagOpenStripped, 0, -strlen('</style>'));
|
231 |
+
|
232 |
+
if ( $originalTagContents ) {
|
233 |
+
$newTagContents = OptimizeCss::maybeAlterContentForInlineStyleTag( $originalTagContents, true, array( 'just_minify' ) );
|
234 |
+
|
235 |
+
// Only comments or no content added to the inline STYLE tag? Strip it completely to reduce the number of DOM elements
|
236 |
+
if ( $newTagContents === '/**/' || ! $newTagContents ) {
|
237 |
+
$htmlSource = str_replace( '>' . $originalTagContents . '</', '></', $htmlSource );
|
238 |
+
|
239 |
+
preg_match( '#<style.*?>#si', $originalTag, $matchFromStyle );
|
240 |
+
|
241 |
+
if ( isset( $matchFromStyle[0] ) && $styleTagWithoutContent = $matchFromStyle[0] ) {
|
242 |
+
$styleTagWithoutContentAlt = str_ireplace( '"', '\'', $styleTagWithoutContent );
|
243 |
+
$htmlSource = str_ireplace( array(
|
244 |
+
$styleTagWithoutContent . '</style>',
|
245 |
+
$styleTagWithoutContentAlt . '</style>'
|
246 |
+
), '', $htmlSource );
|
247 |
+
}
|
248 |
+
} else {
|
249 |
+
// It has content; do the replacement
|
250 |
+
$htmlSource = str_replace(
|
251 |
+
'>' . $originalTagContents . '</style>',
|
252 |
+
'>' . $newTagContents . '</style>',
|
253 |
+
$htmlSource
|
254 |
+
);
|
255 |
}
|
|
|
|
|
|
|
|
|
256 |
}
|
|
|
257 |
}
|
258 |
}
|
259 |
|
classes/OptimiseAssets/MinifyJs.php
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp\OptimiseAssets;
|
3 |
|
|
|
4 |
use WpAssetCleanUp\Main;
|
5 |
use WpAssetCleanUp\Menu;
|
6 |
use WpAssetCleanUp\MetaBoxes;
|
@@ -19,8 +20,31 @@ class MinifyJs
|
|
19 |
public static function applyMinification($jsContent)
|
20 |
{
|
21 |
if (class_exists('\MatthiasMullie\Minify\JS')) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
$minifier = new \MatthiasMullie\Minify\JS($jsContent);
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
}
|
25 |
|
26 |
return $jsContent;
|
@@ -88,6 +112,128 @@ class MinifyJs
|
|
88 |
return false;
|
89 |
}
|
90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
/**
|
92 |
* @return bool
|
93 |
*/
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp\OptimiseAssets;
|
3 |
|
4 |
+
use WpAssetCleanUp\CleanUp;
|
5 |
use WpAssetCleanUp\Main;
|
6 |
use WpAssetCleanUp\Menu;
|
7 |
use WpAssetCleanUp\MetaBoxes;
|
20 |
public static function applyMinification($jsContent)
|
21 |
{
|
22 |
if (class_exists('\MatthiasMullie\Minify\JS')) {
|
23 |
+
$sha1OriginalContent = sha1($jsContent);
|
24 |
+
|
25 |
+
// Let's check if the content is already minified
|
26 |
+
// Save resources as the minify process can take time if the content is very large
|
27 |
+
if (OptimizeCommon::originalContentIsAlreadyMarkedAsMinified($sha1OriginalContent, 'scripts')) {
|
28 |
+
return $jsContent; // return the already minified content, saving resources
|
29 |
+
}
|
30 |
+
|
31 |
+
// Minify it
|
32 |
+
$alreadyMinified = false; // default
|
33 |
+
|
34 |
$minifier = new \MatthiasMullie\Minify\JS($jsContent);
|
35 |
+
$minifiedContent = trim($minifier->minify());
|
36 |
+
|
37 |
+
if (trim($minifiedContent) === trim(trim($jsContent, ';'))) {
|
38 |
+
$minifiedContent = $jsContent; // consider them the same if only the ; at the end was stripped (it doesn't worth the resources that would be used)
|
39 |
+
$alreadyMinified = true;
|
40 |
+
}
|
41 |
+
|
42 |
+
// If the resulting content is the same, mark it as minified to avoid the minify process next time
|
43 |
+
if ($alreadyMinified) {
|
44 |
+
OptimizeCommon::originalContentMarkAsAlreadyMinified($sha1OriginalContent, 'scripts');
|
45 |
+
}
|
46 |
+
|
47 |
+
return $minifiedContent;
|
48 |
}
|
49 |
|
50 |
return $jsContent;
|
112 |
return false;
|
113 |
}
|
114 |
|
115 |
+
/**
|
116 |
+
* @param $htmlSource
|
117 |
+
*
|
118 |
+
* @return mixed|string
|
119 |
+
*/
|
120 |
+
public static function minifyInlineScriptTags($htmlSource)
|
121 |
+
{
|
122 |
+
if (stripos($htmlSource, '<script') === false) {
|
123 |
+
return $htmlSource; // no SCRIPT tags, hmm
|
124 |
+
}
|
125 |
+
|
126 |
+
$skipTagsContaining = array_map( static function ( $toMatch ) {
|
127 |
+
return preg_quote($toMatch, '/');
|
128 |
+
}, array(
|
129 |
+
'data-wpacu-skip',
|
130 |
+
'/* <![CDATA[ */', // added via wp_localize_script()
|
131 |
+
'wpacu-google-fonts-async-load',
|
132 |
+
'wpacu-preload-async-css-fallback',
|
133 |
+
/* [wpacu_pro] */'data-wpacu-inline-js-file',/* [/wpacu_pro] */
|
134 |
+
'document.body.prepend(wpacuLinkTag',
|
135 |
+
'var wc_product_block_data = JSON.parse( decodeURIComponent(',
|
136 |
+
'/(^|\s)(no-)?customize-support(?=\s|$)/', // WP Core
|
137 |
+
'b[c] += ( window.postMessage && request ? \' \' : \' no-\' ) + cs;', // WP Core
|
138 |
+
'data-wpacu-own-inline-script', // Only shown to the admin, irrelevant for any optimization (save resources)
|
139 |
+
// [wpacu_pro]
|
140 |
+
'data-wpacu-inline-js-file', // already minified/optimized since the INLINE was generated from the cached file
|
141 |
+
// [/wpacu_pro]
|
142 |
+
));
|
143 |
+
|
144 |
+
// Do not perform another \DOMDocument call if it was done already somewhere else (e.g. CombineJs)
|
145 |
+
$fetchType = 'regex'; // 'regex' or 'dom'
|
146 |
+
|
147 |
+
if ( $fetchType === 'dom' ) {
|
148 |
+
// DOMDocument extension has to be enabled, otherwise return the HTML source as was (no changes)
|
149 |
+
if ( ! ( function_exists( 'libxml_use_internal_errors' ) && function_exists( 'libxml_clear_errors' ) && class_exists( '\DOMDocument' ) ) ) {
|
150 |
+
return $htmlSource;
|
151 |
+
}
|
152 |
+
|
153 |
+
$domTag = OptimizeCommon::getDomLoadedTag($htmlSource, 'minifyInlineScriptTags');
|
154 |
+
|
155 |
+
$scriptTagsObj = $domTag->getElementsByTagName( 'script' );
|
156 |
+
|
157 |
+
if ( $scriptTagsObj === null ) {
|
158 |
+
return $htmlSource;
|
159 |
+
}
|
160 |
+
|
161 |
+
foreach ( $scriptTagsObj as $scriptTagObj ) {
|
162 |
+
// Does it have the "src" attribute? Skip it as it's not an inline SCRIPT tag
|
163 |
+
if ( isset( $scriptTagObj->attributes ) && $scriptTagObj->attributes !== null ) {
|
164 |
+
foreach ( $scriptTagObj->attributes as $attrObj ) {
|
165 |
+
if ( $attrObj->nodeName === 'src' ) {
|
166 |
+
continue 2;
|
167 |
+
}
|
168 |
+
|
169 |
+
if ( $attrObj->nodeName === 'type' && $attrObj->nodeValue !== 'text/javascript' ) {
|
170 |
+
// If a "type" parameter exists (otherwise it defaults to "text/javascript"
|
171 |
+
// and the value of "type" is not "text/javascript", do not proceed with any optimization (including minification)
|
172 |
+
continue 2;
|
173 |
+
}
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
$originalTag = CleanUp::getOuterHTML( $scriptTagObj );
|
178 |
+
|
179 |
+
// No need to use extra resources as the tag is already minified
|
180 |
+
if ( preg_match( '/(' . implode( '|', $skipTagsContaining ) . ')/', $originalTag ) ) {
|
181 |
+
continue;
|
182 |
+
}
|
183 |
+
|
184 |
+
$originalTagContents = ( isset( $scriptTagObj->nodeValue ) && trim( $scriptTagObj->nodeValue ) !== '' ) ? $scriptTagObj->nodeValue : false;
|
185 |
+
|
186 |
+
if ( $originalTagContents ) {
|
187 |
+
$newTagContents = OptimizeJs::maybeAlterContentForInlineScriptTag( $originalTagContents, true );
|
188 |
+
|
189 |
+
if ( $newTagContents !== $originalTagContents ) {
|
190 |
+
$htmlSource = str_ireplace(
|
191 |
+
'>' . $originalTagContents . '</script',
|
192 |
+
'>' . $newTagContents . '</script',
|
193 |
+
$htmlSource
|
194 |
+
);
|
195 |
+
}
|
196 |
+
|
197 |
+
libxml_clear_errors();
|
198 |
+
}
|
199 |
+
}
|
200 |
+
} elseif ($fetchType === 'regex') {
|
201 |
+
preg_match_all( '@(<script[^>]*?>).*?</script>@si', $htmlSource, $matchesScriptTags, PREG_SET_ORDER );
|
202 |
+
|
203 |
+
if ( $matchesScriptTags === null ) {
|
204 |
+
return $htmlSource;
|
205 |
+
}
|
206 |
+
|
207 |
+
foreach ($matchesScriptTags as $matchedScript) {
|
208 |
+
if (isset($matchedScript[0]) && $matchedScript[0]) {
|
209 |
+
$originalTag = $matchedScript[0];
|
210 |
+
|
211 |
+
if (strpos($originalTag, 'src=') && strtolower(substr($originalTag, -strlen('></script>'))) === strtolower('></script>')) {
|
212 |
+
// Only inline SCRIPT tags allowed
|
213 |
+
continue;
|
214 |
+
}
|
215 |
+
|
216 |
+
// No need to use extra resources as the tag is already minified
|
217 |
+
if ( preg_match( '/(' . implode( '|', $skipTagsContaining ) . ')/', $originalTag ) ) {
|
218 |
+
continue;
|
219 |
+
}
|
220 |
+
|
221 |
+
$tagOpen = $matchedScript[1];
|
222 |
+
$withTagOpenStripped = substr($originalTag, strlen($tagOpen));
|
223 |
+
$originalTagContents = substr($withTagOpenStripped, 0, -strlen('</script>'));
|
224 |
+
|
225 |
+
$newTagContents = OptimizeJs::maybeAlterContentForInlineScriptTag( $originalTagContents, true );
|
226 |
+
|
227 |
+
if ( $newTagContents !== $originalTagContents ) {
|
228 |
+
$htmlSource = str_ireplace( '>' . $originalTagContents . '</script', '>' . $newTagContents . '</script', $htmlSource );
|
229 |
+
}
|
230 |
+
}
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
+
return $htmlSource;
|
235 |
+
}
|
236 |
+
|
237 |
/**
|
238 |
* @return bool
|
239 |
*/
|
classes/OptimiseAssets/OptimizeCommon.php
CHANGED
@@ -7,7 +7,9 @@ use WpAssetCleanUp\HardcodedAssets;
|
|
7 |
use WpAssetCleanUp\Main;
|
8 |
use WpAssetCleanUp\Menu;
|
9 |
use WpAssetCleanUp\Misc;
|
|
|
10 |
use WpAssetCleanUp\Plugin;
|
|
|
11 |
use WpAssetCleanUp\Settings;
|
12 |
use WpAssetCleanUp\Tools;
|
13 |
|
@@ -47,20 +49,20 @@ class OptimizeCommon
|
|
47 |
*/
|
48 |
public function init()
|
49 |
{
|
50 |
-
add_action('switch_theme', array($this, '
|
51 |
-
add_action('after_switch_theme', array($this, '
|
52 |
|
53 |
// Is WP Rocket's page cache cleared? Clear Asset CleanUp's CSS cache files too
|
54 |
if (array_key_exists('action', $_GET) && $_GET['action'] === 'purge_cache') {
|
55 |
// Leave its default parameters, no redirect needed
|
56 |
add_action('init', static function() {
|
57 |
-
OptimizeCommon::
|
58 |
}, PHP_INT_MAX);
|
59 |
}
|
60 |
|
61 |
add_action('admin_post_assetcleanup_clear_assets_cache', static function() {
|
62 |
set_transient('wpacu_clear_assets_cache_via_link', true);
|
63 |
-
self::
|
64 |
});
|
65 |
|
66 |
// When a post is moved to the trash / deleted
|
@@ -155,18 +157,21 @@ class OptimizeCommon
|
|
155 |
return $htmlSource;
|
156 |
}
|
157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
// This is useful to avoid changing the DOM via wp_loaded action hook
|
159 |
// In order to check how fast the page loads without the DOM changes (for debugging purposes)
|
160 |
$wpacuNoHtmlChanges = array_key_exists( 'wpacu_no_html_changes', $_GET );
|
161 |
|
162 |
if ( $wpacuNoHtmlChanges || Plugin::preventAnyChanges() ) {
|
|
|
163 |
return $htmlSource;
|
164 |
}
|
165 |
|
166 |
-
// [wpacu_timing]
|
167 |
-
Misc::scriptExecTimer( 'alter_html_source' );
|
168 |
-
// [/wpacu_timing]
|
169 |
-
|
170 |
$htmlSource = apply_filters( 'wpacu_html_source_before_optimization', $htmlSource );
|
171 |
|
172 |
// For the admin
|
@@ -174,14 +179,26 @@ class OptimizeCommon
|
|
174 |
|
175 |
// The admin is editing the CSS/JS list within the front-end view
|
176 |
if (HardcodedAssets::useBufferingForEditFrontEndView()) {
|
177 |
-
|
178 |
}
|
179 |
|
180 |
$htmlSource = OptimizeCss::alterHtmlSource( $htmlSource );
|
181 |
$htmlSource = OptimizeJs::alterHtmlSource( $htmlSource );
|
182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
$htmlSource = Main::instance()->settings['remove_generator_tag'] ? CleanUp::removeMetaGenerators( $htmlSource ) : $htmlSource;
|
184 |
-
|
|
|
|
|
|
|
|
|
|
|
185 |
|
186 |
if ( in_array( Main::instance()->settings['disable_xmlrpc'], array( 'disable_all', 'disable_pingback' ) ) ) {
|
187 |
// Also clean it up from the <head> in case it's hardcoded
|
@@ -190,16 +207,22 @@ class OptimizeCommon
|
|
190 |
|
191 |
$htmlSource = apply_filters( 'wpacu_html_source', $htmlSource ); // legacy
|
192 |
|
193 |
-
|
194 |
-
Misc::scriptExecTimer( 'alter_html_source', 'end' );
|
195 |
-
// [/wpacu_timing]
|
196 |
|
197 |
// [wpacu_debug]
|
198 |
if (array_key_exists('wpacu_debug', $_GET)) {
|
199 |
$timingKeys = array(
|
|
|
|
|
|
|
200 |
// All HTML alteration via "wp_loaded" action hook
|
201 |
'alter_html_source',
|
202 |
|
|
|
|
|
|
|
|
|
|
|
203 |
// CSS
|
204 |
'alter_html_source_for_optimize_css',
|
205 |
'alter_html_source_unload_ignore_deps_css',
|
@@ -219,7 +242,13 @@ class OptimizeCommon
|
|
219 |
'alter_html_source_for_preload_js',
|
220 |
'alter_html_source_for_combine_js',
|
221 |
|
222 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
);
|
224 |
|
225 |
foreach ( $timingKeys as $timingKey ) {
|
@@ -231,6 +260,80 @@ class OptimizeCommon
|
|
231 |
return apply_filters( 'wpacu_html_source_after_optimization', $htmlSource );
|
232 |
}
|
233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
/**
|
235 |
* @return string
|
236 |
*/
|
@@ -245,64 +348,37 @@ class OptimizeCommon
|
|
245 |
}
|
246 |
|
247 |
/**
|
248 |
-
*
|
249 |
-
* and not combined with other JavaScript files in case the method is called from CombineJs.php
|
250 |
-
*
|
251 |
-
* The following output is used only for fetching purposes
|
252 |
* It will not be part of the final output
|
253 |
*
|
254 |
-
* @param $
|
255 |
* @param $params
|
256 |
*
|
257 |
* @return string|string[]|null
|
258 |
*/
|
259 |
-
public static function cleanerHtmlSource($
|
260 |
{
|
261 |
-
|
|
|
|
|
|
|
|
|
|
|
262 |
|
263 |
// Case: Return the HTML source without any conditional comments and the content within them
|
264 |
if (in_array('strip_content_between_conditional_comments', $params)) {
|
265 |
-
preg_match_all('#<!--\[if(.*?)]>(<!-->|-->|\s|)(.*?)(<!--<!|<!)\[endif]-->#si', $
|
266 |
|
267 |
if (isset($matchedContent[0]) && ! empty($matchedContent[0])) {
|
268 |
foreach ($matchedContent[0] as $conditionalHtmlContent) {
|
269 |
-
$
|
270 |
}
|
271 |
-
return $htmlSourceBeforeAlt;
|
272 |
-
}
|
273 |
-
}
|
274 |
-
|
275 |
-
$sourceHasComments = strpos($htmlSource, '<!--') !== false && strpos($htmlSource, '-->') !== false;
|
276 |
-
|
277 |
-
if (! $sourceHasComments) {
|
278 |
-
return $htmlSource; // nothing to clean
|
279 |
-
}
|
280 |
-
|
281 |
-
if (function_exists('libxml_use_internal_errors') && class_exists('\DOMDocument') && class_exists('\DOMXPath')) {
|
282 |
-
// Highest accuracy
|
283 |
-
$dom = new \DOMDocument();
|
284 |
-
libxml_use_internal_errors(true);
|
285 |
-
$dom->loadHtml($htmlSource);
|
286 |
|
287 |
-
|
288 |
-
libxml_use_internal_errors(true);
|
289 |
-
foreach ($xpath->query('//comment()') as $comment) {
|
290 |
-
if (isset($comment->nodeValue) && $comment->nodeValue) {
|
291 |
-
$htmlSource = str_replace( '<!--' . $comment->nodeValue . '-->', '', $htmlSource );
|
292 |
-
}
|
293 |
}
|
294 |
-
|
295 |
-
return $htmlSource; // altered via DOMDocument
|
296 |
}
|
297 |
|
298 |
-
|
299 |
-
$htmlSource = trim(preg_replace('/<!--(.|\s)*?-->/', '', $htmlSource));
|
300 |
-
|
301 |
-
if (! $htmlSource) {
|
302 |
-
return $htmlSourceBeforeAlt; // It returned null (rare cases with some pages, possible bug, return the source as it is)
|
303 |
-
}
|
304 |
-
|
305 |
-
return $htmlSource; // altered via RegEx (fallback)
|
306 |
}
|
307 |
|
308 |
/**
|
@@ -844,9 +920,9 @@ class OptimizeCommon
|
|
844 |
*
|
845 |
* @param bool $redirectAfter
|
846 |
*/
|
847 |
-
public static function
|
848 |
{
|
849 |
-
if (self::
|
850 |
return;
|
851 |
}
|
852 |
|
@@ -1027,6 +1103,38 @@ SQL;
|
|
1027 |
@rmdir(WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir().'one');
|
1028 |
@rmdir(WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir().'one');
|
1029 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1030 |
/*
|
1031 |
* STEP 2: Remove all transients related to the Minify CSS/JS files feature
|
1032 |
*/
|
@@ -1058,6 +1166,16 @@ SQL;
|
|
1058 |
}
|
1059 |
}
|
1060 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1061 |
/**
|
1062 |
* This is usually done when the plugin is deactivated
|
1063 |
* e.g. if you use Autoptimize and it remains active, you will likely want to have its caching cleared with traces from Asset CleanUp
|
@@ -1121,7 +1239,7 @@ SQL;
|
|
1121 |
*
|
1122 |
* @return bool
|
1123 |
*/
|
1124 |
-
public static function
|
1125 |
{
|
1126 |
// WooCommerce GET or AJAX call
|
1127 |
if (array_key_exists('wc-ajax', $_GET) && $_GET['wc-ajax']) {
|
@@ -1197,7 +1315,7 @@ SQL;
|
|
1197 |
*/
|
1198 |
public static function stripSourceMap($assetContent)
|
1199 |
{
|
1200 |
-
return str_replace('# sourceMappingURL=', '#
|
1201 |
}
|
1202 |
|
1203 |
/**
|
@@ -1213,7 +1331,7 @@ SQL;
|
|
1213 |
|
1214 |
$ignoreQueryStrings = array(
|
1215 |
'wpacu_do_combine', // show the CSS/JS as combined IF the option is enabled despite the query string (for debugging purposes)
|
1216 |
-
'wpacu_no_css_minify', 'wpacu_no_js_minify', 'wpacu_no_css_combine', 'wpacu_no_js_combine', 'wpacu_debug', 'wpacu_skip_test_mode',
|
1217 |
'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_expid', 'utm_referrer', // Google Analytics
|
1218 |
'gclid', // Google Click ID
|
1219 |
'fbclick', 'fbclid', 'fb_action_ids', 'fb_action_types', 'fb_source', // Facebook
|
@@ -1437,4 +1555,49 @@ SQL;
|
|
1437 |
@rmdir($targetDir);
|
1438 |
}
|
1439 |
}
|
1440 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
use WpAssetCleanUp\Main;
|
8 |
use WpAssetCleanUp\Menu;
|
9 |
use WpAssetCleanUp\Misc;
|
10 |
+
use WpAssetCleanUp\ObjectCache;
|
11 |
use WpAssetCleanUp\Plugin;
|
12 |
+
use WpAssetCleanUp\Preloads;
|
13 |
use WpAssetCleanUp\Settings;
|
14 |
use WpAssetCleanUp\Tools;
|
15 |
|
49 |
*/
|
50 |
public function init()
|
51 |
{
|
52 |
+
add_action('switch_theme', array($this, 'clearCache' ));
|
53 |
+
add_action('after_switch_theme', array($this, 'clearCache' ));
|
54 |
|
55 |
// Is WP Rocket's page cache cleared? Clear Asset CleanUp's CSS cache files too
|
56 |
if (array_key_exists('action', $_GET) && $_GET['action'] === 'purge_cache') {
|
57 |
// Leave its default parameters, no redirect needed
|
58 |
add_action('init', static function() {
|
59 |
+
OptimizeCommon::clearCache();
|
60 |
}, PHP_INT_MAX);
|
61 |
}
|
62 |
|
63 |
add_action('admin_post_assetcleanup_clear_assets_cache', static function() {
|
64 |
set_transient('wpacu_clear_assets_cache_via_link', true);
|
65 |
+
self::clearCache(true);
|
66 |
});
|
67 |
|
68 |
// When a post is moved to the trash / deleted
|
157 |
return $htmlSource;
|
158 |
}
|
159 |
|
160 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'alter_html_source' ); /* [/wpacu_timing] */
|
161 |
+
|
162 |
+
// Front-end View
|
163 |
+
// The printing of the hardcoded assets is made via "wpacu_final_frontend_output" filter hook
|
164 |
+
// located within "shutdown" action hook only if the user is logged-in and has the right permissions
|
165 |
+
|
166 |
// This is useful to avoid changing the DOM via wp_loaded action hook
|
167 |
// In order to check how fast the page loads without the DOM changes (for debugging purposes)
|
168 |
$wpacuNoHtmlChanges = array_key_exists( 'wpacu_no_html_changes', $_GET );
|
169 |
|
170 |
if ( $wpacuNoHtmlChanges || Plugin::preventAnyChanges() ) {
|
171 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'alter_html_source', 'end' ); /* [/wpacu_timing] */
|
172 |
return $htmlSource;
|
173 |
}
|
174 |
|
|
|
|
|
|
|
|
|
175 |
$htmlSource = apply_filters( 'wpacu_html_source_before_optimization', $htmlSource );
|
176 |
|
177 |
// For the admin
|
179 |
|
180 |
// The admin is editing the CSS/JS list within the front-end view
|
181 |
if (HardcodedAssets::useBufferingForEditFrontEndView()) {
|
182 |
+
ObjectCache::wpacu_cache_set('wpacu_hardcoded_assets_encoded', base64_encode( json_encode($anyHardCodedAssetsList) ));
|
183 |
}
|
184 |
|
185 |
$htmlSource = OptimizeCss::alterHtmlSource( $htmlSource );
|
186 |
$htmlSource = OptimizeJs::alterHtmlSource( $htmlSource );
|
187 |
|
188 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'alter_html_source_cleanup' ); /* [/wpacu_timing] */
|
189 |
+
|
190 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer('alter_html_source_for_remove_html_comments'); /* [/wpacu_timing] */
|
191 |
+
$htmlSource = Main::instance()->settings['remove_html_comments'] ? CleanUp::removeHtmlComments( $htmlSource, false, 'final_output' ) : $htmlSource;
|
192 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer('alter_html_source_for_remove_html_comments', 'end'); /* [/wpacu_timing] */
|
193 |
+
|
194 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer('alter_html_source_for_remove_meta_generators'); /* [/wpacu_timing] */
|
195 |
$htmlSource = Main::instance()->settings['remove_generator_tag'] ? CleanUp::removeMetaGenerators( $htmlSource ) : $htmlSource;
|
196 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer('alter_html_source_for_remove_meta_generators', 'end'); /* [/wpacu_timing] */
|
197 |
+
|
198 |
+
$htmlSource = preg_replace('#<link(.*)data-wpacu-style-handle=\'(.*)\'#Umi', '<link \\1', $htmlSource);
|
199 |
+
$htmlSource = str_replace(Preloads::DEL_STYLES_PRELOADS, '', $htmlSource);
|
200 |
+
|
201 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'alter_html_source_cleanup', 'end' ); /* [/wpacu_timing] */
|
202 |
|
203 |
if ( in_array( Main::instance()->settings['disable_xmlrpc'], array( 'disable_all', 'disable_pingback' ) ) ) {
|
204 |
// Also clean it up from the <head> in case it's hardcoded
|
207 |
|
208 |
$htmlSource = apply_filters( 'wpacu_html_source', $htmlSource ); // legacy
|
209 |
|
210 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'alter_html_source', 'end' ); /* [/wpacu_timing] */
|
|
|
|
|
211 |
|
212 |
// [wpacu_debug]
|
213 |
if (array_key_exists('wpacu_debug', $_GET)) {
|
214 |
$timingKeys = array(
|
215 |
+
'prepare_optimize_files_css',
|
216 |
+
'prepare_optimize_files_js',
|
217 |
+
|
218 |
// All HTML alteration via "wp_loaded" action hook
|
219 |
'alter_html_source',
|
220 |
|
221 |
+
// HTML CleanUp
|
222 |
+
'alter_html_source_cleanup',
|
223 |
+
'alter_html_source_for_remove_html_comments',
|
224 |
+
'alter_html_source_for_remove_meta_generators',
|
225 |
+
|
226 |
// CSS
|
227 |
'alter_html_source_for_optimize_css',
|
228 |
'alter_html_source_unload_ignore_deps_css',
|
242 |
'alter_html_source_for_preload_js',
|
243 |
'alter_html_source_for_combine_js',
|
244 |
|
245 |
+
'fetch_strip_hardcoded_assets',
|
246 |
+
'fetch_all_hardcoded_assets',
|
247 |
+
|
248 |
+
'output_css_js_manager',
|
249 |
+
|
250 |
+
'style_loader_tag',
|
251 |
+
'script_loader_tag'
|
252 |
);
|
253 |
|
254 |
foreach ( $timingKeys as $timingKey ) {
|
260 |
return apply_filters( 'wpacu_html_source_after_optimization', $htmlSource );
|
261 |
}
|
262 |
|
263 |
+
/**
|
264 |
+
* @param $htmlSource
|
265 |
+
* @param $for
|
266 |
+
*
|
267 |
+
* @return bool|\DOMDocument|mixed
|
268 |
+
*/
|
269 |
+
public static function getDomLoadedTag($htmlSource, $for = '')
|
270 |
+
{
|
271 |
+
$htmlSourceBefore = $htmlSource;
|
272 |
+
|
273 |
+
$domTag = new \DOMDocument();
|
274 |
+
libxml_use_internal_errors( true );
|
275 |
+
|
276 |
+
$cleanerDomRegEx = '';
|
277 |
+
|
278 |
+
// [HTML CleanUp]
|
279 |
+
if ($for === 'removeHtmlComments') {
|
280 |
+
// Strip them to get a cleaner DOM that will be fetched for something else
|
281 |
+
$cleanerDomRegEx = '';
|
282 |
+
}
|
283 |
+
|
284 |
+
if ($for === 'removeHtmlCommentsFinal') {
|
285 |
+
$cleanerDomRegEx = array('@<(script|style)[^>]*?>.*?</\\1>@si', '#<(meta|link|img)([^<>]+)/?>#iU');
|
286 |
+
}
|
287 |
+
|
288 |
+
if ($for === 'removeMetaGenerators') {
|
289 |
+
$cleanerDomRegEx = array('@<(noscript|style|script)[^>]*?>.*?</\\1>@si', '#<(link|img)([^<>]+)/?>#iU');
|
290 |
+
}
|
291 |
+
// [/HTML CleanUp]
|
292 |
+
|
293 |
+
// [CSS Optimisation]
|
294 |
+
if ($for === 'combineCss') {
|
295 |
+
$cleanerDomRegEx = array('@<(noscript|style|script)[^>]*?>.*?</\\1>@si', '#<(meta|img)([^<>]+)/?>#iU');
|
296 |
+
}
|
297 |
+
|
298 |
+
if ($for === 'minifyInlineStyleTags') {
|
299 |
+
$cleanerDomRegEx = array('@<(noscript|script)[^>]*?>.*?</\\1>@si', '#<(meta|link|img)([^<>]+)/?>#iU');
|
300 |
+
}
|
301 |
+
// [/CSS Optimisation]
|
302 |
+
|
303 |
+
// [JS Optimisation]
|
304 |
+
if ($for === 'moveInlinejQueryAfterjQuerySrc') {
|
305 |
+
$cleanerDomRegEx = '@<(noscript|style)[^>]*?>.*?</\\1>@si';
|
306 |
+
}
|
307 |
+
|
308 |
+
if ($for === 'minifyInlineScriptTags') {
|
309 |
+
$cleanerDomRegEx = array('@<(noscript|style)[^>]*?>.*?</\\1>@si', '#<(meta|link|img)([^<>]+)/?>#iU');
|
310 |
+
}
|
311 |
+
|
312 |
+
if ($for === 'combineJs') {
|
313 |
+
$cleanerDomRegEx = '@<(noscript|style)[^>]*?>.*?</\\1>@si';
|
314 |
+
}
|
315 |
+
// [/JS Optimisation]
|
316 |
+
|
317 |
+
// Default: Strip just the NOSCRIPT tags
|
318 |
+
if ($cleanerDomRegEx !== '') {
|
319 |
+
$htmlSource = preg_replace( $cleanerDomRegEx, '', $htmlSource );
|
320 |
+
}
|
321 |
+
|
322 |
+
if (Main::instance()->isFrontendEditView) {
|
323 |
+
$htmlSource = preg_replace( '@<form action="#wpacu_wrap_assets" method="post">.*?</form>@si', '', $htmlSource );
|
324 |
+
}
|
325 |
+
|
326 |
+
// Avoid "Warning: DOMDocument::loadHTML(): Empty string supplied as input"
|
327 |
+
// Just in case $htmlSource has been altered incorrectly for any reason, fallback to the original $htmlSource value ($htmlSourceBefore)
|
328 |
+
if (! $htmlSource) {
|
329 |
+
$domTag->loadHTML($htmlSourceBefore);
|
330 |
+
return $domTag;
|
331 |
+
}
|
332 |
+
|
333 |
+
$domTag->loadHTML($htmlSource);
|
334 |
+
return $domTag;
|
335 |
+
}
|
336 |
+
|
337 |
/**
|
338 |
* @return string
|
339 |
*/
|
348 |
}
|
349 |
|
350 |
/**
|
351 |
+
* The following output is ONLY used for fetching purposes
|
|
|
|
|
|
|
352 |
* It will not be part of the final output
|
353 |
*
|
354 |
+
* @param $htmlSourceToFetchFrom
|
355 |
* @param $params
|
356 |
*
|
357 |
* @return string|string[]|null
|
358 |
*/
|
359 |
+
public static function cleanerHtmlSource($htmlSourceToFetchFrom, $params = array('strip_content_between_conditional_comments'))
|
360 |
{
|
361 |
+
if (in_array('for_fetching_link_tags', $params)) {
|
362 |
+
$htmlSourceToFetchFrom = preg_replace( array('@<(style|script|noscript)[^>]*?>.*?</\\1>@si', '#<(meta|img)([^<>]+)/?>#iU'), '', $htmlSourceToFetchFrom );
|
363 |
+
} else {
|
364 |
+
// Strip NOSCRIPT tags
|
365 |
+
$htmlSourceToFetchFrom = preg_replace( '@<(noscript)[^>]*?>.*?</\\1>@si', '', $htmlSourceToFetchFrom );
|
366 |
+
}
|
367 |
|
368 |
// Case: Return the HTML source without any conditional comments and the content within them
|
369 |
if (in_array('strip_content_between_conditional_comments', $params)) {
|
370 |
+
preg_match_all('#<!--\[if(.*?)]>(<!-->|-->|\s|)(.*?)(<!--<!|<!)\[endif]-->#si', $htmlSourceToFetchFrom, $matchedContent);
|
371 |
|
372 |
if (isset($matchedContent[0]) && ! empty($matchedContent[0])) {
|
373 |
foreach ($matchedContent[0] as $conditionalHtmlContent) {
|
374 |
+
$htmlSourceToFetchFrom = str_replace($conditionalHtmlContent, '', $htmlSourceToFetchFrom);
|
375 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
|
377 |
+
return $htmlSourceToFetchFrom;
|
|
|
|
|
|
|
|
|
|
|
378 |
}
|
|
|
|
|
379 |
}
|
380 |
|
381 |
+
return $htmlSourceToFetchFrom;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
382 |
}
|
383 |
|
384 |
/**
|
920 |
*
|
921 |
* @param bool $redirectAfter
|
922 |
*/
|
923 |
+
public static function clearCache($redirectAfter = false)
|
924 |
{
|
925 |
+
if (self::doNotClearCache()) {
|
926 |
return;
|
927 |
}
|
928 |
|
1103 |
@rmdir(WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir().'one');
|
1104 |
@rmdir(WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir().'one');
|
1105 |
|
1106 |
+
|
1107 |
+
/*
|
1108 |
+
* Special Case: Any CSS/JS files from /wp-content/cache//asset-cleanup/(css|js)/item/inline/
|
1109 |
+
* These files are never loaded as static, externally (from LINK or SCRIPT tag);
|
1110 |
+
* Their content is just pulled (if not expired) into the STYLE/SCRIPT inline tag
|
1111 |
+
* If there are any expired files there, remove them
|
1112 |
+
*/
|
1113 |
+
foreach (array('.css', '.js') as $assetExt) {
|
1114 |
+
$assetTypeDir = ($assetExt === '.css') ? OptimizeCss::getRelPathCssCacheDir() : OptimizeJs::getRelPathJsCacheDir();
|
1115 |
+
|
1116 |
+
$assetsInlineTagsContentDir = WP_CONTENT_DIR . $assetTypeDir . self::$optimizedSingleFilesDir . '/inline/';
|
1117 |
+
|
1118 |
+
if ( is_dir( $assetsInlineTagsContentDir ) ) {
|
1119 |
+
$assetInlineTagsContentDirFiles = scandir( $assetsInlineTagsContentDir );
|
1120 |
+
|
1121 |
+
foreach ( $assetInlineTagsContentDirFiles as $assetFile ) {
|
1122 |
+
if ( strpos( $assetFile, $assetExt ) === false ) {
|
1123 |
+
continue;
|
1124 |
+
}
|
1125 |
+
|
1126 |
+
$fullPathToFile = $assetsInlineTagsContentDir . $assetFile;
|
1127 |
+
|
1128 |
+
$isExpired = ( filemtime( $fullPathToFile ) < ( time() - 1 * self::$cachedAssetFileExpiresIn ) );
|
1129 |
+
|
1130 |
+
if ( $isExpired ) {
|
1131 |
+
@unlink( $fullPathToFile );
|
1132 |
+
}
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
}
|
1136 |
+
}
|
1137 |
+
|
1138 |
/*
|
1139 |
* STEP 2: Remove all transients related to the Minify CSS/JS files feature
|
1140 |
*/
|
1166 |
}
|
1167 |
}
|
1168 |
|
1169 |
+
/**
|
1170 |
+
* Alias for clearCache() - some developers might have implemented clearAllCache()
|
1171 |
+
*
|
1172 |
+
* @param bool $redirectAfter
|
1173 |
+
*/
|
1174 |
+
public static function clearAllCache($redirectAfter = false)
|
1175 |
+
{
|
1176 |
+
self::clearCache($redirectAfter);
|
1177 |
+
}
|
1178 |
+
|
1179 |
/**
|
1180 |
* This is usually done when the plugin is deactivated
|
1181 |
* e.g. if you use Autoptimize and it remains active, you will likely want to have its caching cleared with traces from Asset CleanUp
|
1239 |
*
|
1240 |
* @return bool
|
1241 |
*/
|
1242 |
+
public static function doNotClearCache()
|
1243 |
{
|
1244 |
// WooCommerce GET or AJAX call
|
1245 |
if (array_key_exists('wc-ajax', $_GET) && $_GET['wc-ajax']) {
|
1315 |
*/
|
1316 |
public static function stripSourceMap($assetContent)
|
1317 |
{
|
1318 |
+
return str_replace('# sourceMappingURL=', '# Original Source Map: ', $assetContent);
|
1319 |
}
|
1320 |
|
1321 |
/**
|
1331 |
|
1332 |
$ignoreQueryStrings = array(
|
1333 |
'wpacu_do_combine', // show the CSS/JS as combined IF the option is enabled despite the query string (for debugging purposes)
|
1334 |
+
'wpacu_no_css_minify', 'wpacu_no_js_minify', 'wpacu_no_css_combine', 'wpacu_no_js_combine', 'wpacu_debug', 'wpacu_preload', 'wpacu_skip_test_mode',
|
1335 |
'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_expid', 'utm_referrer', // Google Analytics
|
1336 |
'gclid', // Google Click ID
|
1337 |
'fbclick', 'fbclid', 'fb_action_ids', 'fb_action_types', 'fb_source', // Facebook
|
1555 |
@rmdir($targetDir);
|
1556 |
}
|
1557 |
}
|
1558 |
+
|
1559 |
+
/**
|
1560 |
+
* @param $assetContentSha1
|
1561 |
+
* @param $assetType
|
1562 |
+
*
|
1563 |
+
* @return bool
|
1564 |
+
*/
|
1565 |
+
public static function originalContentIsAlreadyMarkedAsMinified($assetContentSha1, $assetType)
|
1566 |
+
{
|
1567 |
+
$optionToCheck = WPACU_PLUGIN_ID . '_global_data';
|
1568 |
+
$globalKey = 'already_minified'; // HEAD or BODY
|
1569 |
+
|
1570 |
+
$existingListEmpty = array('styles' => array($globalKey => array()), 'scripts' => array($globalKey => array()));
|
1571 |
+
$existingListJson = get_option($optionToCheck);
|
1572 |
+
|
1573 |
+
$existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
|
1574 |
+
$existingList = $existingListData['list'];
|
1575 |
+
|
1576 |
+
return isset( $existingList[ $assetType ]['already_minified'] ) && in_array( $assetContentSha1, $existingList[ $assetType ]['already_minified'] );
|
1577 |
+
}
|
1578 |
+
|
1579 |
+
/**
|
1580 |
+
* @param $assetContentSha1
|
1581 |
+
* @param $assetType
|
1582 |
+
*/
|
1583 |
+
public static function originalContentMarkAsAlreadyMinified($assetContentSha1, $assetType)
|
1584 |
+
{
|
1585 |
+
$optionToUpdate = WPACU_PLUGIN_ID . '_global_data';
|
1586 |
+
$globalKey = 'already_minified'; // HEAD or BODY
|
1587 |
+
|
1588 |
+
$existingListEmpty = array('styles' => array($globalKey => array()), 'scripts' => array($globalKey => array()));
|
1589 |
+
$existingListJson = get_option($optionToUpdate);
|
1590 |
+
|
1591 |
+
$existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
|
1592 |
+
$existingList = $existingListData['list'];
|
1593 |
+
|
1594 |
+
if (! isset($existingList[$assetType]['already_minified'])) {
|
1595 |
+
$existingList[$assetType]['already_minified'] = array();
|
1596 |
+
}
|
1597 |
+
|
1598 |
+
$existingList[$assetType]['already_minified'][] = $assetContentSha1;
|
1599 |
+
|
1600 |
+
update_option($optionToUpdate, json_encode(Misc::filterList($existingList)));
|
1601 |
+
}
|
1602 |
+
|
1603 |
+
}
|
classes/OptimiseAssets/OptimizeCss.php
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp\OptimiseAssets;
|
3 |
|
|
|
4 |
use WpAssetCleanUp\Plugin;
|
5 |
use WpAssetCleanUp\Preloads;
|
6 |
use WpAssetCleanUp\FileSystem;
|
@@ -26,7 +27,11 @@ class OptimizeCss
|
|
26 |
public function init()
|
27 |
{
|
28 |
add_action('init', array($this, 'triggersAfterInit'));
|
29 |
-
add_action('wp_footer',
|
|
|
|
|
|
|
|
|
30 |
|
31 |
add_action('wp_footer', static function() {
|
32 |
if ( Plugin::preventAnyChanges() || Main::isTestModeActive() ) {
|
@@ -95,7 +100,7 @@ class OptimizeCss
|
|
95 |
/**
|
96 |
*
|
97 |
*/
|
98 |
-
public function prepareOptimizeList()
|
99 |
{
|
100 |
if ( ! self::isWorthCheckingForOptimization() || Plugin::preventAnyChanges() ) {
|
101 |
return;
|
@@ -103,7 +108,7 @@ class OptimizeCss
|
|
103 |
|
104 |
global $wp_styles;
|
105 |
|
106 |
-
$allStylesHandles =
|
107 |
if (empty($allStylesHandles)) {
|
108 |
return;
|
109 |
}
|
@@ -138,7 +143,7 @@ class OptimizeCss
|
|
138 |
$cssOptimizeList = array();
|
139 |
|
140 |
foreach ($wpStylesDone as $handle) {
|
141 |
-
if (! isset($wpStylesRegistered[$handle])) {
|
142 |
continue;
|
143 |
}
|
144 |
|
@@ -150,6 +155,7 @@ class OptimizeCss
|
|
150 |
}
|
151 |
|
152 |
$optimizeValues = self::maybeOptimizeIt($value);
|
|
|
153 |
|
154 |
if (! empty($optimizeValues)) {
|
155 |
$cssOptimizeList[] = $optimizeValues;
|
@@ -160,8 +166,8 @@ class OptimizeCss
|
|
160 |
return;
|
161 |
}
|
162 |
|
163 |
-
|
164 |
-
|
165 |
// [End] Collect for caching
|
166 |
}
|
167 |
|
@@ -172,6 +178,10 @@ class OptimizeCss
|
|
172 |
*/
|
173 |
public static function maybeOptimizeIt($value)
|
174 |
{
|
|
|
|
|
|
|
|
|
175 |
global $wp_version;
|
176 |
|
177 |
$src = isset($value->src) ? $value->src : false;
|
@@ -188,13 +198,20 @@ class OptimizeCss
|
|
188 |
$doFileMinify = false;
|
189 |
}
|
190 |
|
191 |
-
$
|
192 |
|
193 |
$handleDbStr = md5($value->handle);
|
194 |
|
195 |
$transientName = 'wpacu_css_optimize_'.$handleDbStr;
|
196 |
|
197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
if ( ! isset( $GLOBALS['wpacu_from_location_inc'] ) ) {
|
199 |
$GLOBALS['wpacu_from_location_inc'] = 1;
|
200 |
}
|
@@ -222,7 +239,8 @@ class OptimizeCss
|
|
222 |
return array(
|
223 |
$savedValuesArray['source_uri'],
|
224 |
$savedValuesArray['optimize_uri'],
|
225 |
-
$value->src
|
|
|
226 |
);
|
227 |
}
|
228 |
|
@@ -230,6 +248,8 @@ class OptimizeCss
|
|
230 |
OptimizeCommon::deleteTransient($transientName);
|
231 |
}
|
232 |
}
|
|
|
|
|
233 |
// Check if it starts without "/" or a protocol; e.g. "wp-content/theme/style.css"
|
234 |
if (strpos($src, '/') !== 0 &&
|
235 |
strpos($src, '//') !== 0 &&
|
@@ -285,42 +305,67 @@ class OptimizeCss
|
|
285 |
$sourceBeforeOptimization = str_replace(ABSPATH, '/', $localAssetPath);
|
286 |
}
|
287 |
|
|
|
|
|
288 |
/*
|
289 |
* [START] CSS Content Optimization
|
290 |
*/
|
291 |
-
|
292 |
-
|
293 |
|
294 |
-
|
|
|
295 |
// Any "font-display" enabled in "Settings" - "Google Fonts"?
|
296 |
-
$cssContent = FontsGoogle::alterGoogleFontUrlFromCssContent($cssContent);
|
297 |
}
|
298 |
|
299 |
// Move any @imports to top; This also strips any @imports to Google Fonts if the option is chosen
|
300 |
-
$cssContent = self::importsUpdate($cssContent);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
|
302 |
-
if ($
|
303 |
-
//
|
304 |
-
$
|
305 |
}
|
|
|
306 |
|
307 |
-
|
308 |
-
|
|
|
|
|
|
|
309 |
}
|
310 |
|
311 |
// No changes were made, thus, there's no point in changing the original file location
|
312 |
-
if ($isCssFile && trim($cssContentBefore) === trim($cssContent)) {
|
313 |
// There's no point in changing the original CSS (static) file location
|
314 |
return false;
|
315 |
}
|
316 |
|
317 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
/*
|
319 |
* [END] CSS Content Optimization
|
320 |
*/
|
321 |
|
322 |
// Relative path to the new file
|
323 |
// Save it to /wp-content/cache/css/{OptimizeCommon::$optimizedSingleFilesDir}/
|
|
|
324 |
if ($fileVer !== $wp_version) {
|
325 |
if (is_array($fileVer)) {
|
326 |
// Convert to string if it's an array (rare cases)
|
@@ -329,24 +374,26 @@ class OptimizeCss
|
|
329 |
$fileVer = trim(str_replace(' ', '_', preg_replace('/\s+/', ' ', $fileVer)));
|
330 |
$fileVer = (strlen($fileVer) > 50) ? substr(md5($fileVer), 0, 20) : $fileVer; // don't end up with too long filenames
|
331 |
}
|
|
|
|
|
332 |
|
333 |
$newFilePathUri = self::getRelPathCssCacheDir() . OptimizeCommon::$optimizedSingleFilesDir . '/' . $value->handle . '-v' . $fileVer;
|
|
|
334 |
|
335 |
-
if (
|
336 |
-
$
|
337 |
-
|
338 |
-
if ($sha1File) {
|
339 |
-
$newFilePathUri .= '-' . $sha1File;
|
340 |
-
}
|
341 |
}
|
342 |
|
343 |
-
$
|
|
|
|
|
|
|
344 |
|
345 |
$newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
|
346 |
$newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
|
347 |
|
348 |
-
if ($cssContent) {
|
349 |
-
$cssContent = '/*!
|
350 |
}
|
351 |
|
352 |
$saveFile = FileSystem::file_put_contents($newLocalPath, $cssContent);
|
@@ -368,7 +415,8 @@ class OptimizeCss
|
|
368 |
return array(
|
369 |
OptimizeCommon::getSourceRelPath($src), // Original SRC (Relative path)
|
370 |
OptimizeCommon::getSourceRelPath($newLocalPathUrl), // New SRC (Relative path)
|
371 |
-
$value->src // SRC (as it is)
|
|
|
372 |
);
|
373 |
}
|
374 |
|
@@ -440,7 +488,7 @@ class OptimizeCss
|
|
440 |
|
441 |
// Final cleanups
|
442 |
$htmlSource = preg_replace('#<link(\s+|)data-wpacu-link-rel-href-before=(["\'])' . '(.*)' . '(\1)#Usmi', '<link ', $htmlSource);
|
443 |
-
|
444 |
|
445 |
/* [wpacu_timing] */ $wpacuTimingName = 'alter_html_source_for_google_fonts_optimization_removal'; Misc::scriptExecTimer($wpacuTimingName); /* [/wpacu_timing] */
|
446 |
// Alter HTML Source for Google Fonts Optimization / Removal
|
@@ -452,7 +500,6 @@ class OptimizeCss
|
|
452 |
$htmlSource = apply_filters('wpacu_add_async_preloads_noscript', $htmlSource);
|
453 |
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
454 |
|
455 |
-
// Final timing (for the whole HTML source)
|
456 |
/* [wpacu_timing] */ Misc::scriptExecTimer('alter_html_source_for_optimize_css', 'end'); /* [/wpacu_timing] */
|
457 |
|
458 |
return $htmlSource;
|
@@ -474,7 +521,7 @@ class OptimizeCss
|
|
474 |
*/
|
475 |
public static function getFirstLinkTag($firstLinkHref, $htmlSource)
|
476 |
{
|
477 |
-
preg_match_all('#<link[^>]*stylesheet[^>]*(>)#
|
478 |
foreach ($matches[0] as $matchTag) {
|
479 |
if (strpos($matchTag, $firstLinkHref) !== false) {
|
480 |
return trim($matchTag);
|
@@ -580,53 +627,64 @@ class OptimizeCss
|
|
580 |
*/
|
581 |
public static function updateHtmlSourceOriginalToOptimizedCss($htmlSource)
|
582 |
{
|
583 |
-
$cssOptimizeList =
|
584 |
-
|
|
|
|
|
|
|
|
|
|
|
585 |
|
586 |
$cdnUrls = OptimizeCommon::getAnyCdnUrls();
|
587 |
$cdnUrlForCss = isset($cdnUrls['css']) ? $cdnUrls['css'] : false;
|
588 |
|
589 |
-
preg_match_all('#<link[^>]*(stylesheet|(as(\s+|)=(\s+|)(|"|\')style(|"|\')))[^>]
|
590 |
|
591 |
if (empty($matchesSourcesFromTags)) {
|
592 |
return $htmlSource;
|
593 |
}
|
594 |
|
|
|
|
|
595 |
foreach ($matchesSourcesFromTags as $matches) {
|
596 |
$linkSourceTag = $matches[0];
|
597 |
|
598 |
-
if (strip_tags($linkSourceTag) !== '') {
|
599 |
// Hmm? Not a valid tag... Skip it...
|
600 |
continue;
|
601 |
}
|
602 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
603 |
// Is it a local CSS? Check if it's hardcoded (not enqueued the WordPress way)
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
)
|
|
|
616 |
|
617 |
-
|
|
|
618 |
|
619 |
-
|
620 |
-
|
621 |
-
}
|
622 |
}
|
623 |
}
|
624 |
|
625 |
-
|
626 |
-
continue;
|
627 |
-
}
|
628 |
-
|
629 |
-
foreach ($cssOptimizeList as $listValues) {
|
630 |
// Index 0: Source URL (relative)
|
631 |
// Index 1: New Optimized URL (relative)
|
632 |
// Index 2: Source URL (as it is)
|
@@ -635,7 +693,9 @@ class OptimizeCss
|
|
635 |
|
636 |
// If the minified files are deleted (e.g. /wp-content/cache/ is cleared)
|
637 |
// do not replace the CSS file path to avoid breaking the website
|
638 |
-
|
|
|
|
|
639 |
continue;
|
640 |
}
|
641 |
|
@@ -667,14 +727,33 @@ class OptimizeCss
|
|
667 |
// If no CDN is set, it will return site_url() as a prefix
|
668 |
$optimizeUrl = OptimizeCommon::cdnToUrlFormat($cdnUrlForCss, 'raw') . $listValues[1]; // string
|
669 |
|
670 |
-
if ($linkSourceTag !==
|
671 |
-
|
672 |
-
$
|
673 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
674 |
}
|
675 |
}
|
676 |
}
|
677 |
|
|
|
|
|
678 |
return $htmlSource;
|
679 |
}
|
680 |
|
@@ -724,6 +803,8 @@ class OptimizeCss
|
|
724 |
}
|
725 |
|
726 |
/**
|
|
|
|
|
727 |
* @param $htmlSource
|
728 |
*
|
729 |
* @return mixed
|
@@ -733,9 +814,13 @@ class OptimizeCss
|
|
733 |
$allPatterns = self::getAllInlineChosenPatterns();
|
734 |
|
735 |
// Skip any LINK tags within conditional comments (e.g. Internet Explorer ones)
|
736 |
-
|
737 |
-
|
738 |
-
|
|
|
|
|
|
|
|
|
739 |
// In case automatic inlining is used
|
740 |
$belowSizeInput = (int)Main::instance()->settings['inline_css_files_below_size_input'];
|
741 |
|
@@ -750,9 +835,12 @@ class OptimizeCss
|
|
750 |
foreach ($matchesSourcesFromTags as $matchList) {
|
751 |
$matchedTag = $matchList[0];
|
752 |
|
|
|
|
|
|
|
|
|
753 |
// They were preloaded for a reason, leave them
|
754 |
-
if (strpos($matchedTag, 'data-wpacu-preload-it-async=') !== false
|
755 |
-
|| strpos($matchedTag, 'data-wpacu-to-be-preloaded-basic=') !== false) {
|
756 |
continue;
|
757 |
}
|
758 |
|
@@ -761,8 +849,7 @@ class OptimizeCss
|
|
761 |
}
|
762 |
|
763 |
// Condition #1: Only chosen (via textarea) CSS get inlined
|
764 |
-
$chosenInlineCssMatches = (! empty($allPatterns) &&
|
765 |
-
preg_match('/(' . implode('|', $allPatterns) . ')/i', $matchedTag));
|
766 |
|
767 |
// Is auto inline disabled and the chosen CSS does not match? Continue to the next LINK tag
|
768 |
if (! $chosenInlineCssMatches && ! self::isAutoInlineEnabled()) {
|
@@ -802,7 +889,7 @@ class OptimizeCss
|
|
802 |
// The CSS file is read from its original plugin/theme/cache location
|
803 |
// If minify was enabled, then it's already minified, no point in re-minify it to save resources
|
804 |
// Changing paths (relative) to fonts, images, etc. are relevant in this case
|
805 |
-
$cssContent = self::
|
806 |
|
807 |
if ($cssContent && $cssContent !== '/**/') {
|
808 |
$htmlSource = str_replace(
|
@@ -826,32 +913,113 @@ class OptimizeCss
|
|
826 |
*
|
827 |
* @param $cssContent
|
828 |
* @param bool $doCssMinify (false by default as it could be already minified or non-minify type)
|
829 |
-
* @param bool $forInlineStyle - (false by default - this param is relevant only for inline tags that are altered "on the fly")
|
830 |
-
*
|
831 |
* @param array $extraParams
|
832 |
*
|
833 |
* @return mixed|string|string[]|null
|
834 |
*/
|
835 |
-
public static function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
836 |
{
|
837 |
if (! trim($cssContent)) {
|
838 |
return $cssContent;
|
839 |
}
|
840 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
841 |
if ( $doCssMinify && in_array('just_minify', $extraParams) ) {
|
842 |
-
$cssContent = MinifyCss::applyMinification( $cssContent, $
|
843 |
} else {
|
844 |
// Move any @imports to top; This also strips any @imports to Google Fonts if the option is chosen
|
845 |
$cssContent = self::importsUpdate( $cssContent );
|
846 |
|
847 |
if ( $doCssMinify ) {
|
848 |
-
$cssContent = MinifyCss::applyMinification( $cssContent, $
|
849 |
}
|
850 |
|
851 |
if ( Main::instance()->settings['google_fonts_remove'] ) {
|
852 |
$cssContent = FontsGoogleRemove::cleanFontFaceReferences( $cssContent );
|
853 |
}
|
854 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
855 |
|
856 |
return $cssContent;
|
857 |
}
|
@@ -1079,6 +1247,11 @@ class OptimizeCss
|
|
1079 |
|
1080 |
if (isset($ignoreChild['styles']) && ! empty($ignoreChild['styles'])) {
|
1081 |
foreach (array_keys($ignoreChild['styles']) as $styleHandle) {
|
|
|
|
|
|
|
|
|
|
|
1082 |
if (isset(Main::instance()->wpAllStyles['registered'][$styleHandle]->src, Main::instance()->ignoreChildren['styles'][$styleHandle.'_has_unload_rule']) && Main::instance()->wpAllStyles['registered'][$styleHandle]->src && Main::instance()->ignoreChildren['styles'][$styleHandle.'_has_unload_rule']) {
|
1083 |
if ($scriptExtraAfterHtml = self::generateInlineAssocHtmlForHandle($styleHandle)) {
|
1084 |
$htmlSource = str_replace($scriptExtraAfterHtml, '', $htmlSource);
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp\OptimiseAssets;
|
3 |
|
4 |
+
use WpAssetCleanUp\ObjectCache;
|
5 |
use WpAssetCleanUp\Plugin;
|
6 |
use WpAssetCleanUp\Preloads;
|
7 |
use WpAssetCleanUp\FileSystem;
|
27 |
public function init()
|
28 |
{
|
29 |
add_action('init', array($this, 'triggersAfterInit'));
|
30 |
+
add_action('wp_footer', static function() {
|
31 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'prepare_optimize_files_css' ); /* [/wpacu_timing] */
|
32 |
+
self::prepareOptimizeList();
|
33 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'prepare_optimize_files_css', 'end' ); /* [/wpacu_timing] */
|
34 |
+
}, PHP_INT_MAX);
|
35 |
|
36 |
add_action('wp_footer', static function() {
|
37 |
if ( Plugin::preventAnyChanges() || Main::isTestModeActive() ) {
|
100 |
/**
|
101 |
*
|
102 |
*/
|
103 |
+
public static function prepareOptimizeList()
|
104 |
{
|
105 |
if ( ! self::isWorthCheckingForOptimization() || Plugin::preventAnyChanges() ) {
|
106 |
return;
|
108 |
|
109 |
global $wp_styles;
|
110 |
|
111 |
+
$allStylesHandles = ObjectCache::wpacu_cache_get('wpacu_all_styles_handles');
|
112 |
if (empty($allStylesHandles)) {
|
113 |
return;
|
114 |
}
|
143 |
$cssOptimizeList = array();
|
144 |
|
145 |
foreach ($wpStylesDone as $handle) {
|
146 |
+
if (! isset($wpStylesRegistered[$handle]->src)) {
|
147 |
continue;
|
148 |
}
|
149 |
|
155 |
}
|
156 |
|
157 |
$optimizeValues = self::maybeOptimizeIt($value);
|
158 |
+
ObjectCache::wpacu_cache_set('wpacu_maybe_optimize_it_css_'.$handle, $optimizeValues);
|
159 |
|
160 |
if (! empty($optimizeValues)) {
|
161 |
$cssOptimizeList[] = $optimizeValues;
|
166 |
return;
|
167 |
}
|
168 |
|
169 |
+
ObjectCache::wpacu_cache_add('wpacu_css_enqueued_hrefs', $allEnqueuedCleanLinkHrefs);
|
170 |
+
ObjectCache::wpacu_cache_add('wpacu_css_optimize_list', $cssOptimizeList);
|
171 |
// [End] Collect for caching
|
172 |
}
|
173 |
|
178 |
*/
|
179 |
public static function maybeOptimizeIt($value)
|
180 |
{
|
181 |
+
if ($optimizeValues = ObjectCache::wpacu_cache_get('wpacu_maybe_optimize_it_css_'.$value->handle)) {
|
182 |
+
return $optimizeValues;
|
183 |
+
}
|
184 |
+
|
185 |
global $wp_version;
|
186 |
|
187 |
$src = isset($value->src) ? $value->src : false;
|
198 |
$doFileMinify = false;
|
199 |
}
|
200 |
|
201 |
+
$dbVer = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
|
202 |
|
203 |
$handleDbStr = md5($value->handle);
|
204 |
|
205 |
$transientName = 'wpacu_css_optimize_'.$handleDbStr;
|
206 |
|
207 |
+
$skipCache = false;
|
208 |
+
|
209 |
+
if (isset($_GET['wpacu_no_cache'])) {
|
210 |
+
$skipCache = true;
|
211 |
+
}
|
212 |
+
|
213 |
+
if (! $skipCache) {
|
214 |
+
if (Main::instance()->settings['fetch_cached_files_details_from'] === 'db_disk') {
|
215 |
if ( ! isset( $GLOBALS['wpacu_from_location_inc'] ) ) {
|
216 |
$GLOBALS['wpacu_from_location_inc'] = 1;
|
217 |
}
|
239 |
return array(
|
240 |
$savedValuesArray['source_uri'],
|
241 |
$savedValuesArray['optimize_uri'],
|
242 |
+
$value->src,
|
243 |
+
$value->handle
|
244 |
);
|
245 |
}
|
246 |
|
248 |
OptimizeCommon::deleteTransient($transientName);
|
249 |
}
|
250 |
}
|
251 |
+
}
|
252 |
+
|
253 |
// Check if it starts without "/" or a protocol; e.g. "wp-content/theme/style.css"
|
254 |
if (strpos($src, '/') !== 0 &&
|
255 |
strpos($src, '//') !== 0 &&
|
305 |
$sourceBeforeOptimization = str_replace(ABSPATH, '/', $localAssetPath);
|
306 |
}
|
307 |
|
308 |
+
$cssContent = trim($cssContent);
|
309 |
+
|
310 |
/*
|
311 |
* [START] CSS Content Optimization
|
312 |
*/
|
313 |
+
// If there are no changes from this point, do not optimize (keep the file where it is)
|
314 |
+
$cssContentBefore = $cssContent;
|
315 |
|
316 |
+
if ($cssContent) { // only proceed with extra alterations if there is some content there (save resources)
|
317 |
+
if ( Main::instance()->settings['google_fonts_display'] ) {
|
318 |
// Any "font-display" enabled in "Settings" - "Google Fonts"?
|
319 |
+
$cssContent = FontsGoogle::alterGoogleFontUrlFromCssContent( $cssContent );
|
320 |
}
|
321 |
|
322 |
// Move any @imports to top; This also strips any @imports to Google Fonts if the option is chosen
|
323 |
+
$cssContent = self::importsUpdate( $cssContent );
|
324 |
+
}
|
325 |
+
|
326 |
+
// If it stays like this, it means there is content there, even if only comments
|
327 |
+
$cssContentBecomesEmptyAfterMin = false;
|
328 |
+
|
329 |
+
if ($doFileMinify && $cssContent) { // only bother to minify it if it has any content, save resources
|
330 |
+
// Minify this file?
|
331 |
+
$cssContentBeforeMin = trim($cssContent);
|
332 |
+
$cssContentAfterMin = MinifyCss::applyMinification($cssContent);
|
333 |
+
|
334 |
+
$cssContent = $cssContentAfterMin;
|
335 |
|
336 |
+
if ($cssContentBeforeMin && $cssContentAfterMin === '') {
|
337 |
+
// It had content, but became empty after minification, most likely it had only comments (e.g. a default child theme's style)
|
338 |
+
$cssContentBecomesEmptyAfterMin = true;
|
339 |
}
|
340 |
+
}
|
341 |
|
342 |
+
if ($cssContentBecomesEmptyAfterMin || $cssContent === '') {
|
343 |
+
$cssContent = '/**/';
|
344 |
+
} else {
|
345 |
+
if ( Main::instance()->settings['google_fonts_remove'] ) {
|
346 |
+
$cssContent = FontsGoogleRemove::cleanFontFaceReferences( $cssContent );
|
347 |
}
|
348 |
|
349 |
// No changes were made, thus, there's no point in changing the original file location
|
350 |
+
if ( $isCssFile && ! $cssContentBecomesEmptyAfterMin && trim( $cssContentBefore ) === trim( $cssContent ) ) {
|
351 |
// There's no point in changing the original CSS (static) file location
|
352 |
return false;
|
353 |
}
|
354 |
|
355 |
+
// Does it have a source map? Strip it
|
356 |
+
if (strpos($cssContent, 'sourceMappingURL') !== false) {
|
357 |
+
$cssContent = OptimizeCommon::stripSourceMap($cssContent);
|
358 |
+
}
|
359 |
+
|
360 |
+
$cssContent = self::maybeFixCssContent( $cssContent, $pathToAssetDir . '/' ); // Path
|
361 |
+
}
|
362 |
/*
|
363 |
* [END] CSS Content Optimization
|
364 |
*/
|
365 |
|
366 |
// Relative path to the new file
|
367 |
// Save it to /wp-content/cache/css/{OptimizeCommon::$optimizedSingleFilesDir}/
|
368 |
+
/*
|
369 |
if ($fileVer !== $wp_version) {
|
370 |
if (is_array($fileVer)) {
|
371 |
// Convert to string if it's an array (rare cases)
|
374 |
$fileVer = trim(str_replace(' ', '_', preg_replace('/\s+/', ' ', $fileVer)));
|
375 |
$fileVer = (strlen($fileVer) > 50) ? substr(md5($fileVer), 0, 20) : $fileVer; // don't end up with too long filenames
|
376 |
}
|
377 |
+
*/
|
378 |
+
$fileVer = sha1($cssContent);
|
379 |
|
380 |
$newFilePathUri = self::getRelPathCssCacheDir() . OptimizeCommon::$optimizedSingleFilesDir . '/' . $value->handle . '-v' . $fileVer;
|
381 |
+
$newFilePathUri .= '.css';
|
382 |
|
383 |
+
if ($cssContent === '') {
|
384 |
+
$cssContent = '/**/';
|
|
|
|
|
|
|
|
|
385 |
}
|
386 |
|
387 |
+
if ($cssContent === '/**/') {
|
388 |
+
// Leave a signature that the file is empty, thus it would be faster to take further actions upon it later on, saving resources)
|
389 |
+
$newFilePathUri = str_replace('.css', '-wpacu-empty-file.css', $newFilePathUri);
|
390 |
+
}
|
391 |
|
392 |
$newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
|
393 |
$newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
|
394 |
|
395 |
+
if ($cssContent && $cssContent !== '/**/') {
|
396 |
+
$cssContent = '/*!' . $sourceBeforeOptimization . '*/' . $cssContent;
|
397 |
}
|
398 |
|
399 |
$saveFile = FileSystem::file_put_contents($newLocalPath, $cssContent);
|
415 |
return array(
|
416 |
OptimizeCommon::getSourceRelPath($src), // Original SRC (Relative path)
|
417 |
OptimizeCommon::getSourceRelPath($newLocalPathUrl), // New SRC (Relative path)
|
418 |
+
$value->src, // SRC (as it is)
|
419 |
+
$value->handle
|
420 |
);
|
421 |
}
|
422 |
|
488 |
|
489 |
// Final cleanups
|
490 |
$htmlSource = preg_replace('#<link(\s+|)data-wpacu-link-rel-href-before=(["\'])' . '(.*)' . '(\1)#Usmi', '<link ', $htmlSource);
|
491 |
+
//$htmlSource = preg_replace('#<link(.*)data-wpacu-style-handle=\'(.*)\'#Umi', '<link \\1', $htmlSource);
|
492 |
|
493 |
/* [wpacu_timing] */ $wpacuTimingName = 'alter_html_source_for_google_fonts_optimization_removal'; Misc::scriptExecTimer($wpacuTimingName); /* [/wpacu_timing] */
|
494 |
// Alter HTML Source for Google Fonts Optimization / Removal
|
500 |
$htmlSource = apply_filters('wpacu_add_async_preloads_noscript', $htmlSource);
|
501 |
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
502 |
|
|
|
503 |
/* [wpacu_timing] */ Misc::scriptExecTimer('alter_html_source_for_optimize_css', 'end'); /* [/wpacu_timing] */
|
504 |
|
505 |
return $htmlSource;
|
521 |
*/
|
522 |
public static function getFirstLinkTag($firstLinkHref, $htmlSource)
|
523 |
{
|
524 |
+
preg_match_all('#<link[^>]*stylesheet[^>]*(>)#Umi', $htmlSource, $matches);
|
525 |
foreach ($matches[0] as $matchTag) {
|
526 |
if (strpos($matchTag, $firstLinkHref) !== false) {
|
527 |
return trim($matchTag);
|
627 |
*/
|
628 |
public static function updateHtmlSourceOriginalToOptimizedCss($htmlSource)
|
629 |
{
|
630 |
+
$cssOptimizeList = ObjectCache::wpacu_cache_get('wpacu_css_optimize_list') ?: array();
|
631 |
+
|
632 |
+
if (empty($cssOptimizeList)) {
|
633 |
+
return $htmlSource;
|
634 |
+
}
|
635 |
+
|
636 |
+
$allEnqueuedCleanLinkHrefs = ObjectCache::wpacu_cache_get('wpacu_css_enqueued_hrefs') ?: array();
|
637 |
|
638 |
$cdnUrls = OptimizeCommon::getAnyCdnUrls();
|
639 |
$cdnUrlForCss = isset($cdnUrls['css']) ? $cdnUrls['css'] : false;
|
640 |
|
641 |
+
preg_match_all('#<link[^>]*(stylesheet|(as(\s+|)=(\s+|)(|"|\')style(|"|\')))[^>]*>#Umi', OptimizeCommon::cleanerHtmlSource( $htmlSource, array( 'for_fetching_link_tags' ) ), $matchesSourcesFromTags, PREG_SET_ORDER);
|
642 |
|
643 |
if (empty($matchesSourcesFromTags)) {
|
644 |
return $htmlSource;
|
645 |
}
|
646 |
|
647 |
+
$linkTagsToUpdate = array();
|
648 |
+
|
649 |
foreach ($matchesSourcesFromTags as $matches) {
|
650 |
$linkSourceTag = $matches[0];
|
651 |
|
652 |
+
if ($linkSourceTag === '' || strip_tags($linkSourceTag) !== '') {
|
653 |
// Hmm? Not a valid tag... Skip it...
|
654 |
continue;
|
655 |
}
|
656 |
|
657 |
+
$cleanLinkHrefFromTagArray = OptimizeCommon::getLocalCleanSourceFromTag($linkSourceTag, 'href');
|
658 |
+
|
659 |
+
// Skip external links, no point in carrying on
|
660 |
+
if (! $cleanLinkHrefFromTagArray || ! is_array($cleanLinkHrefFromTagArray)) {
|
661 |
+
continue;
|
662 |
+
}
|
663 |
+
|
664 |
// Is it a local CSS? Check if it's hardcoded (not enqueued the WordPress way)
|
665 |
+
$cleanLinkHrefFromTag = $cleanLinkHrefFromTagArray['source'];
|
666 |
+
$afterQuestionMark = $cleanLinkHrefFromTagArray['after_question_mark'];
|
667 |
+
|
668 |
+
if (! in_array($cleanLinkHrefFromTag, $allEnqueuedCleanLinkHrefs)) {
|
669 |
+
// Not in the final enqueued list? Most likely hardcoded (not added via wp_enqueue_scripts())
|
670 |
+
// Emulate the object value (as the enqueued styles)
|
671 |
+
$generatedHandle = md5($cleanLinkHrefFromTag);
|
672 |
+
|
673 |
+
$value = (object)array(
|
674 |
+
'handle' => $generatedHandle,
|
675 |
+
'src' => $cleanLinkHrefFromTag,
|
676 |
+
'ver' => md5($afterQuestionMark)
|
677 |
+
);
|
678 |
|
679 |
+
$optimizeValues = self::maybeOptimizeIt($value);
|
680 |
+
ObjectCache::wpacu_cache_set('wpacu_maybe_optimize_it_css_'.$generatedHandle, $optimizeValues);
|
681 |
|
682 |
+
if (! empty($optimizeValues)) {
|
683 |
+
$cssOptimizeList[] = $optimizeValues;
|
|
|
684 |
}
|
685 |
}
|
686 |
|
687 |
+
foreach ($cssOptimizeList as $cssItemIndex => $listValues) {
|
|
|
|
|
|
|
|
|
688 |
// Index 0: Source URL (relative)
|
689 |
// Index 1: New Optimized URL (relative)
|
690 |
// Index 2: Source URL (as it is)
|
693 |
|
694 |
// If the minified files are deleted (e.g. /wp-content/cache/ is cleared)
|
695 |
// do not replace the CSS file path to avoid breaking the website
|
696 |
+
$localPathOptimizedFile = rtrim(ABSPATH, '/') . $listValues[1];
|
697 |
+
|
698 |
+
if (! is_file($localPathOptimizedFile)) {
|
699 |
continue;
|
700 |
}
|
701 |
|
727 |
// If no CDN is set, it will return site_url() as a prefix
|
728 |
$optimizeUrl = OptimizeCommon::cdnToUrlFormat($cdnUrlForCss, 'raw') . $listValues[1]; // string
|
729 |
|
730 |
+
if ($linkSourceTag !== str_replace($sourceUrlList, $optimizeUrl, $linkSourceTag)) {
|
731 |
+
// Extra measure: Check the file size which should be 4 bytes, but add some margin error in case some environments will report less
|
732 |
+
$isEmptyOptimizedFile = (strpos($localPathOptimizedFile, '-wpacu-empty-file.css') !== false && filesize($localPathOptimizedFile) < 10);
|
733 |
+
|
734 |
+
// Strip it as its content (after optimization, for instance) is empty; no point in having extra HTTP requests
|
735 |
+
if ($isEmptyOptimizedFile) {
|
736 |
+
$htmlSourceBefore = $htmlSource;
|
737 |
+
$htmlSource = str_replace($linkSourceTag, '', $htmlSource);
|
738 |
+
$htmlSourceAfter = $htmlSource;
|
739 |
+
|
740 |
+
if ( ( $htmlSourceAfter !== $htmlSourceBefore ) && $scriptExtraAfterHtml = self::generateInlineAssocHtmlForHandle( $listValues[3] ) ) {
|
741 |
+
$htmlSource = str_replace( $scriptExtraAfterHtml, '', $htmlSource );
|
742 |
+
}
|
743 |
+
} else {
|
744 |
+
// Do the replacement
|
745 |
+
$newLinkSourceTag = self::updateOriginalToOptimizedTag( $linkSourceTag, $sourceUrlList, $optimizeUrl );
|
746 |
+
$linkTagsToUpdate[$linkSourceTag] = $newLinkSourceTag;
|
747 |
+
}
|
748 |
+
|
749 |
+
unset($cssOptimizeList[$cssItemIndex]); // item from the array is not needed anymore
|
750 |
+
break; // there was a match, stop here
|
751 |
}
|
752 |
}
|
753 |
}
|
754 |
|
755 |
+
$htmlSource = strtr($htmlSource, $linkTagsToUpdate);
|
756 |
+
|
757 |
return $htmlSource;
|
758 |
}
|
759 |
|
803 |
}
|
804 |
|
805 |
/**
|
806 |
+
* From LINK to STYLE tag: it processes the contents of the LINK stylesheet and replaces the tag with a STYLE tag having the content inlined
|
807 |
+
*
|
808 |
* @param $htmlSource
|
809 |
*
|
810 |
* @return mixed
|
814 |
$allPatterns = self::getAllInlineChosenPatterns();
|
815 |
|
816 |
// Skip any LINK tags within conditional comments (e.g. Internet Explorer ones)
|
817 |
+
preg_match_all(
|
818 |
+
'#<link[^>]*rel=([\'"])stylesheet([\'"])[^>]*href.*>#Usmi',
|
819 |
+
OptimizeCommon::cleanerHtmlSource( $htmlSource, array( 'strip_content_between_conditional_comments', 'for_fetching_link_tags' ) ),
|
820 |
+
$matchesSourcesFromTags,
|
821 |
+
PREG_SET_ORDER
|
822 |
+
);
|
823 |
+
|
824 |
// In case automatic inlining is used
|
825 |
$belowSizeInput = (int)Main::instance()->settings['inline_css_files_below_size_input'];
|
826 |
|
835 |
foreach ($matchesSourcesFromTags as $matchList) {
|
836 |
$matchedTag = $matchList[0];
|
837 |
|
838 |
+
if ($matchedTag === '') {
|
839 |
+
continue;
|
840 |
+
}
|
841 |
+
|
842 |
// They were preloaded for a reason, leave them
|
843 |
+
if (strpos($matchedTag, 'data-wpacu-preload-it-async=') !== false || strpos($matchedTag, 'data-wpacu-to-be-preloaded-basic=') !== false) {
|
|
|
844 |
continue;
|
845 |
}
|
846 |
|
849 |
}
|
850 |
|
851 |
// Condition #1: Only chosen (via textarea) CSS get inlined
|
852 |
+
$chosenInlineCssMatches = (! empty($allPatterns) && preg_match('/(' . implode('|', $allPatterns) . ')/i', $matchedTag));
|
|
|
853 |
|
854 |
// Is auto inline disabled and the chosen CSS does not match? Continue to the next LINK tag
|
855 |
if (! $chosenInlineCssMatches && ! self::isAutoInlineEnabled()) {
|
889 |
// The CSS file is read from its original plugin/theme/cache location
|
890 |
// If minify was enabled, then it's already minified, no point in re-minify it to save resources
|
891 |
// Changing paths (relative) to fonts, images, etc. are relevant in this case
|
892 |
+
$cssContent = self::maybeAlterContentForCssFile($cssContent, false);
|
893 |
|
894 |
if ($cssContent && $cssContent !== '/**/') {
|
895 |
$htmlSource = str_replace(
|
913 |
*
|
914 |
* @param $cssContent
|
915 |
* @param bool $doCssMinify (false by default as it could be already minified or non-minify type)
|
|
|
|
|
916 |
* @param array $extraParams
|
917 |
*
|
918 |
* @return mixed|string|string[]|null
|
919 |
*/
|
920 |
+
public static function maybeAlterContentForCssFile($cssContent, $doCssMinify = false, $extraParams = array())
|
921 |
+
{
|
922 |
+
if (! trim($cssContent)) {
|
923 |
+
return $cssContent;
|
924 |
+
}
|
925 |
+
|
926 |
+
/* [START] Change CSS Content */
|
927 |
+
if ( $doCssMinify && in_array('just_minify', $extraParams) ) {
|
928 |
+
$cssContent = MinifyCss::applyMinification( $cssContent, $doCssMinify );
|
929 |
+
} else {
|
930 |
+
// Move any @imports to top; This also strips any @imports to Google Fonts if the option is chosen
|
931 |
+
$cssContent = self::importsUpdate( $cssContent );
|
932 |
+
|
933 |
+
if ( $doCssMinify ) {
|
934 |
+
$cssContent = MinifyCss::applyMinification( $cssContent, $doCssMinify );
|
935 |
+
}
|
936 |
+
|
937 |
+
if ( Main::instance()->settings['google_fonts_remove'] ) {
|
938 |
+
$cssContent = FontsGoogleRemove::cleanFontFaceReferences( $cssContent );
|
939 |
+
}
|
940 |
+
|
941 |
+
// Does it have a source map? Strip it
|
942 |
+
if (strpos($cssContent, 'sourceMappingURL') !== false) {
|
943 |
+
$cssContent = OptimizeCommon::stripSourceMap($cssContent);
|
944 |
+
}
|
945 |
+
}
|
946 |
+
/* [END] Change CSS Content */
|
947 |
+
|
948 |
+
return $cssContent;
|
949 |
+
}
|
950 |
+
|
951 |
+
/**
|
952 |
+
* @param $cssContent
|
953 |
+
* @param bool $doCssMinify
|
954 |
+
* @param array $extraParams
|
955 |
+
*
|
956 |
+
* @return mixed|string
|
957 |
+
*/
|
958 |
+
public static function maybeAlterContentForInlineStyleTag($cssContent, $doCssMinify = false, $extraParams = array())
|
959 |
{
|
960 |
if (! trim($cssContent)) {
|
961 |
return $cssContent;
|
962 |
}
|
963 |
|
964 |
+
$useCacheForInlineStyle = true;
|
965 |
+
|
966 |
+
if (mb_strlen($cssContent) > 500000) { // Bigger then ~500KB? Skip alteration
|
967 |
+
return $cssContent;
|
968 |
+
}
|
969 |
+
|
970 |
+
if (mb_strlen($cssContent) < 40000) { // Smaller than than ~40KB? Do not cache it
|
971 |
+
$useCacheForInlineStyle = false;
|
972 |
+
}
|
973 |
+
|
974 |
+
// For debugging purposes
|
975 |
+
if (isset($_GET['wpacu_no_cache'])) { $useCacheForInlineStyle = false; }
|
976 |
+
|
977 |
+
if ($useCacheForInlineStyle) {
|
978 |
+
// Anything in the cache? Take it from there and don't spend resources with the minification
|
979 |
+
// (which in some environments uses the CPU, depending on the complexity of the JavaScript code) and any other alteration
|
980 |
+
$cssContentBeforeHash = sha1( $cssContent );
|
981 |
+
|
982 |
+
$pathToInlineCssOptimizedItem = WP_CONTENT_DIR . self::getRelPathCssCacheDir() . '/item/inline/' . $cssContentBeforeHash . '.css';
|
983 |
+
|
984 |
+
// Check if the file exists before moving forward
|
985 |
+
if ( is_file( $pathToInlineCssOptimizedItem ) ) {
|
986 |
+
$cachedCssFileExpiresIn = OptimizeCommon::$cachedAssetFileExpiresIn;
|
987 |
+
|
988 |
+
if ( filemtime( $pathToInlineCssOptimizedItem ) < ( time() - 1 * $cachedCssFileExpiresIn ) ) {
|
989 |
+
// Has the caching period expired? Remove the file as a new one has to be generated
|
990 |
+
@unlink( $pathToInlineCssOptimizedItem );
|
991 |
+
} else {
|
992 |
+
// Not expired / Return its content from the cache in a faster way
|
993 |
+
$inlineCssStorageItemJsonContent = trim( FileSystem::file_get_contents( $pathToInlineCssOptimizedItem ) );
|
994 |
+
|
995 |
+
if ( $inlineCssStorageItemJsonContent !== '' ) {
|
996 |
+
return $inlineCssStorageItemJsonContent;
|
997 |
+
}
|
998 |
+
}
|
999 |
+
}
|
1000 |
+
}
|
1001 |
+
|
1002 |
+
/* [START] Change CSS Content */
|
1003 |
if ( $doCssMinify && in_array('just_minify', $extraParams) ) {
|
1004 |
+
$cssContent = MinifyCss::applyMinification( $cssContent, $useCacheForInlineStyle );
|
1005 |
} else {
|
1006 |
// Move any @imports to top; This also strips any @imports to Google Fonts if the option is chosen
|
1007 |
$cssContent = self::importsUpdate( $cssContent );
|
1008 |
|
1009 |
if ( $doCssMinify ) {
|
1010 |
+
$cssContent = MinifyCss::applyMinification( $cssContent, $useCacheForInlineStyle );
|
1011 |
}
|
1012 |
|
1013 |
if ( Main::instance()->settings['google_fonts_remove'] ) {
|
1014 |
$cssContent = FontsGoogleRemove::cleanFontFaceReferences( $cssContent );
|
1015 |
}
|
1016 |
}
|
1017 |
+
/* [END] Change CSS Content */
|
1018 |
+
|
1019 |
+
if ($useCacheForInlineStyle && isset($pathToInlineCssOptimizedItem)) {
|
1020 |
+
// Store the optimized content to the cached CSS file which would be read quicker
|
1021 |
+
FileSystem::file_put_contents( $pathToInlineCssOptimizedItem, $cssContent );
|
1022 |
+
}
|
1023 |
|
1024 |
return $cssContent;
|
1025 |
}
|
1247 |
|
1248 |
if (isset($ignoreChild['styles']) && ! empty($ignoreChild['styles'])) {
|
1249 |
foreach (array_keys($ignoreChild['styles']) as $styleHandle) {
|
1250 |
+
// Always load the Dashicons if the top admin bar (toolbar) is shown
|
1251 |
+
if ($styleHandle === 'dashicons' && is_admin_bar_showing()) {
|
1252 |
+
continue;
|
1253 |
+
}
|
1254 |
+
|
1255 |
if (isset(Main::instance()->wpAllStyles['registered'][$styleHandle]->src, Main::instance()->ignoreChildren['styles'][$styleHandle.'_has_unload_rule']) && Main::instance()->wpAllStyles['registered'][$styleHandle]->src && Main::instance()->ignoreChildren['styles'][$styleHandle.'_has_unload_rule']) {
|
1256 |
if ($scriptExtraAfterHtml = self::generateInlineAssocHtmlForHandle($styleHandle)) {
|
1257 |
$htmlSource = str_replace($scriptExtraAfterHtml, '', $htmlSource);
|
classes/OptimiseAssets/OptimizeJs.php
CHANGED
@@ -6,6 +6,7 @@ use WpAssetCleanUp\CleanUp;
|
|
6 |
use WpAssetCleanUp\Main;
|
7 |
use WpAssetCleanUp\MetaBoxes;
|
8 |
use WpAssetCleanUp\Misc;
|
|
|
9 |
use WpAssetCleanUp\Preloads;
|
10 |
|
11 |
/**
|
@@ -19,21 +20,20 @@ class OptimizeJs
|
|
19 |
*/
|
20 |
public function init()
|
21 |
{
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
add_action( 'wp_print_footer_scripts', array( $this, 'prepareOptimizeList' ), PHP_INT_MAX );
|
28 |
}
|
29 |
|
30 |
/**
|
31 |
*
|
32 |
*/
|
33 |
-
public function prepareOptimizeList()
|
34 |
{
|
35 |
// Are both Minify and Cache Dynamic JS disabled? No point in continuing and using extra resources as there is nothing to change
|
36 |
-
if (! self::isWorthCheckingForOptimization()) {
|
37 |
return;
|
38 |
}
|
39 |
|
@@ -68,7 +68,9 @@ class OptimizeJs
|
|
68 |
|
69 |
// [Start] Collect for caching
|
70 |
foreach ($wpScriptsList as $handle) {
|
71 |
-
if (! isset($wp_scripts->registered[$handle])) {
|
|
|
|
|
72 |
|
73 |
$value = $wp_scripts->registered[$handle];
|
74 |
|
@@ -78,6 +80,7 @@ class OptimizeJs
|
|
78 |
}
|
79 |
|
80 |
$optimizeValues = self::maybeOptimizeIt($value);
|
|
|
81 |
|
82 |
if ( ! empty( $optimizeValues ) ) {
|
83 |
$jsOptimizeList[] = $optimizeValues;
|
@@ -96,6 +99,10 @@ class OptimizeJs
|
|
96 |
*/
|
97 |
public static function maybeOptimizeIt($value)
|
98 |
{
|
|
|
|
|
|
|
|
|
99 |
global $wp_version;
|
100 |
|
101 |
$src = isset($value->src) ? $value->src : false;
|
@@ -112,13 +119,20 @@ class OptimizeJs
|
|
112 |
$doFileMinify = false;
|
113 |
}
|
114 |
|
115 |
-
$
|
116 |
|
117 |
$handleDbStr = md5($value->handle);
|
118 |
|
119 |
$transientName = 'wpacu_js_optimize_'.$handleDbStr;
|
120 |
|
121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
if ( ! isset( $GLOBALS['wpacu_from_location_inc'] ) ) {
|
123 |
$GLOBALS['wpacu_from_location_inc'] = 1;
|
124 |
}
|
@@ -148,11 +162,13 @@ class OptimizeJs
|
|
148 |
return array(
|
149 |
$savedValuesArray['source_uri'],
|
150 |
$savedValuesArray['optimize_uri'],
|
151 |
-
$value->src
|
|
|
152 |
);
|
153 |
}
|
154 |
}
|
155 |
}
|
|
|
156 |
|
157 |
// Check if it starts without "/" or a protocol; e.g. "wp-content/theme/script.js"
|
158 |
if (strpos($src, '/') !== 0 &&
|
@@ -168,6 +184,9 @@ class OptimizeJs
|
|
168 |
$src = site_url() . $src;
|
169 |
}
|
170 |
|
|
|
|
|
|
|
171 |
$isJsFile = $jsContentBefore = false;
|
172 |
|
173 |
if (Main::instance()->settings['cache_dynamic_loaded_js'] &&
|
@@ -195,43 +214,61 @@ class OptimizeJs
|
|
195 |
$jsContent = $jsContentBefore = FileSystem::file_get_contents($localAssetPath);
|
196 |
}
|
197 |
|
198 |
-
$jsContent =
|
199 |
|
200 |
-
|
201 |
-
|
202 |
-
return array();
|
203 |
-
}
|
204 |
|
205 |
-
$
|
|
|
|
|
|
|
206 |
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
$fileVer = implode('-', $fileVer);
|
213 |
}
|
214 |
-
$fileVer = trim(str_replace(' ', '_', preg_replace('/\s+/', ' ', $fileVer)));
|
215 |
-
$fileVer = (strlen($fileVer) > 50) ? substr(md5($fileVer), 0, 20) : $fileVer; // don't end up with too long filenames
|
216 |
}
|
217 |
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
$
|
222 |
|
223 |
-
if ($
|
224 |
-
|
|
|
225 |
}
|
|
|
|
|
226 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
|
|
228 |
$newFilePathUri .= '.js';
|
229 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
230 |
$newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
|
231 |
$newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
|
232 |
|
233 |
-
if ($jsContent) {
|
234 |
-
$jsContent = '/*!
|
235 |
}
|
236 |
|
237 |
$saveFile = FileSystem::file_put_contents($newLocalPath, $jsContent);
|
@@ -253,7 +290,8 @@ class OptimizeJs
|
|
253 |
return array(
|
254 |
OptimizeCommon::getSourceRelPath($value->src), // Original SRC (Relative path)
|
255 |
OptimizeCommon::getSourceRelPath($newLocalPathUrl), // New SRC (Relative path)
|
256 |
-
$value->src // SRC (as it is)
|
|
|
257 |
);
|
258 |
}
|
259 |
|
@@ -265,12 +303,13 @@ class OptimizeJs
|
|
265 |
*
|
266 |
* @return mixed|string|string[]|null
|
267 |
*/
|
268 |
-
public static function
|
269 |
{
|
270 |
-
if (! trim($jsContent)) {
|
271 |
return $jsContent;
|
272 |
}
|
273 |
|
|
|
274 |
if ($doJsMinify) {
|
275 |
$jsContent = MinifyJs::applyMinification($jsContent);
|
276 |
}
|
@@ -281,6 +320,83 @@ class OptimizeJs
|
|
281 |
// Perhaps "display" parameter has to be applied to Google Font Links if they are active
|
282 |
$jsContent = FontsGoogle::alterGoogleFontUrlFromJsContent($jsContent);
|
283 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
284 |
|
285 |
return $jsContent;
|
286 |
}
|
@@ -298,7 +414,9 @@ class OptimizeJs
|
|
298 |
$cdnUrls = OptimizeCommon::getAnyCdnUrls();
|
299 |
$cdnUrlForJs = isset($cdnUrls['js']) ? $cdnUrls['js'] : false;
|
300 |
|
301 |
-
preg_match_all('#(<script[^>]*src(|\s+)=(|\s+)[^>]
|
|
|
|
|
302 |
|
303 |
foreach ($matchesSourcesFromTags as $matches) {
|
304 |
$scriptSourceTag = $matches[0];
|
@@ -316,25 +434,33 @@ class OptimizeJs
|
|
316 |
$forAttr = 'href';
|
317 |
}
|
318 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
319 |
// Is it a local JS? Check if it's hardcoded (not enqueued the WordPress way)
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
)
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
|
|
338 |
}
|
339 |
}
|
340 |
|
@@ -342,14 +468,16 @@ class OptimizeJs
|
|
342 |
continue;
|
343 |
}
|
344 |
|
345 |
-
foreach ($jsOptimizeList as $listValues) {
|
346 |
// Index 0: Source URL (relative)
|
347 |
// Index 1: New Optimized URL (relative)
|
348 |
// Index 2: Source URL (as it is)
|
349 |
|
350 |
// If the minified files are deleted (e.g. /wp-content/cache/ is cleared)
|
351 |
// do not replace the JS file path to avoid breaking the website
|
352 |
-
|
|
|
|
|
353 |
continue;
|
354 |
}
|
355 |
|
@@ -380,13 +508,36 @@ class OptimizeJs
|
|
380 |
$optimizeUrl = OptimizeCommon::cdnToUrlFormat($cdnUrlForJs, 'raw') . $listValues[1]; // string
|
381 |
|
382 |
if ($scriptSourceTag !== str_ireplace($sourceUrlList, $optimizeUrl, $scriptSourceTag)) {
|
383 |
-
|
384 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
break;
|
386 |
}
|
387 |
}
|
388 |
}
|
389 |
|
|
|
|
|
390 |
return $htmlSource;
|
391 |
}
|
392 |
|
@@ -478,6 +629,9 @@ class OptimizeJs
|
|
478 |
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
479 |
}
|
480 |
|
|
|
|
|
|
|
481 |
$proceedWithCombineOnThisPage = true;
|
482 |
|
483 |
// If "Do not combine JS on this page" is checked in "Asset CleanUp Options" side meta box
|
@@ -495,110 +649,24 @@ class OptimizeJs
|
|
495 |
/* [wpacu_timing] */ // Note: Load timing is checked within the method /* [/wpacu_timing] */
|
496 |
$htmlSource = CombineJs::doCombine($htmlSource);
|
497 |
}
|
|
|
498 |
|
499 |
-
if (self::isWorthCheckingForOptimization() && ! Main::instance()->preventAssetsSettings()) {
|
500 |
/* [wpacu_timing] */ $wpacuTimingName = 'alter_html_source_for_minify_inline_script_tags'; Misc::scriptExecTimer($wpacuTimingName); /* [/wpacu_timing] */
|
501 |
-
$htmlSource =
|
502 |
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
503 |
}
|
504 |
|
505 |
// Final cleanups
|
506 |
-
$htmlSource = preg_replace('#(\s+|)(data-wpacu-jquery-core-handle=1|data-wpacu-jquery-migrate-handle=1)(\s+|)#Umi', '', $htmlSource);
|
507 |
|
508 |
-
$htmlSource = preg_replace('#(\s+|)data-wpacu-script-rel-src-before=(["\'])' . '(.*)' . '(\1)(\s+|)#Usmi', '', $htmlSource);
|
509 |
$htmlSource = preg_replace('#<script(.*)data-wpacu-script-handle=\'(.*)\'#Umi', '<script \\1', $htmlSource);
|
510 |
|
511 |
// Clear possible empty SCRIPT tags (e.g. left from associated 'before' and 'after' tags after their content was stripped)
|
512 |
$htmlSource = preg_replace('#<script(\s+| )(type=\'text/javascript\'|)(\s+|)></script>#Umi', '', $htmlSource);
|
513 |
|
514 |
/* [wpacu_timing] */ Misc::scriptExecTimer('alter_html_source_for_optimize_js', 'end'); /* [/wpacu_timing] */
|
515 |
-
|
516 |
-
return $htmlSource;
|
517 |
-
}
|
518 |
-
|
519 |
-
/**
|
520 |
-
* @param $htmlSource
|
521 |
-
*
|
522 |
-
* @return mixed|string
|
523 |
-
*/
|
524 |
-
public static function minifyInlineScriptTags($htmlSource)
|
525 |
-
{
|
526 |
-
if (stripos($htmlSource, '<script') === false) {
|
527 |
-
return $htmlSource; // no SCRIPT tags, hmm
|
528 |
-
}
|
529 |
-
|
530 |
-
// DOMDocument extension has to be enabled, otherwise return the HTML source as was (no changes)
|
531 |
-
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('DOMDocument'))) {
|
532 |
-
return $htmlSource;
|
533 |
-
}
|
534 |
-
|
535 |
-
$domTag = new \DOMDocument();
|
536 |
-
libxml_use_internal_errors(true);
|
537 |
-
$domTag->loadHTML($htmlSource);
|
538 |
-
|
539 |
-
$scriptTagsObj = $domTag->getElementsByTagName( 'script' );
|
540 |
-
|
541 |
-
if ($scriptTagsObj === null) {
|
542 |
-
return $htmlSource;
|
543 |
-
}
|
544 |
-
|
545 |
-
$doJsMinifyInline = MinifyJs::isMinifyJsEnabled() && Main::instance()->settings['minify_loaded_js_inline'];
|
546 |
-
|
547 |
-
$skipTagsContaining = array_map( static function ( $toMatch ) {
|
548 |
-
return preg_quote($toMatch, '/');
|
549 |
-
}, array(
|
550 |
-
'/* <![CDATA[ */', // added via wp_localize_script()
|
551 |
-
'window._wpemojiSettings', // Emoji
|
552 |
-
'wpacu-google-fonts-async-load',
|
553 |
-
'wpacu-preload-async-css-fallback',
|
554 |
-
/* [wpacu_pro] */'data-wpacu-inline-js-file',/* [/wpacu_pro] */
|
555 |
-
'document.body.prepend(wpacuLinkTag',
|
556 |
-
'var wc_product_block_data = JSON.parse( decodeURIComponent(',
|
557 |
-
'/(^|\s)(no-)?customize-support(?=\s|$)/', // WP Core
|
558 |
-
'b[c] += ( window.postMessage && request ? \' \' : \' no-\' ) + cs;', // WP Core
|
559 |
-
'data-wpacu-own-inline-script' // Only shown to the admin, irrelevant for any optimization (save resources)
|
560 |
-
));
|
561 |
-
|
562 |
-
foreach ($scriptTagsObj as $scriptTagObj) {
|
563 |
-
// Does it have the "src" attribute? Skip it as it's not an inline SCRIPT tag
|
564 |
-
if (isset($scriptTagObj->attributes) && $scriptTagObj->attributes !== null) {
|
565 |
-
foreach ($scriptTagObj->attributes as $attrObj) {
|
566 |
-
if ($attrObj->nodeName === 'src') {
|
567 |
-
continue 2;
|
568 |
-
}
|
569 |
-
|
570 |
-
if ($attrObj->nodeName === 'type' && $attrObj->nodeValue !== 'text/javascript') {
|
571 |
-
// If a "type" parameter exists (otherwise it defaults to "text/javascript"
|
572 |
-
// and the value of "type" is not "text/javascript", do not proceed with any optimization (including minification)
|
573 |
-
continue 2;
|
574 |
-
}
|
575 |
-
}
|
576 |
-
}
|
577 |
-
|
578 |
-
$originalTag = CleanUp::getOuterHTML($scriptTagObj);
|
579 |
-
|
580 |
-
// No need to use extra resources as the tag is already minified
|
581 |
-
if (preg_match('/('.implode('|', $skipTagsContaining).')/', $originalTag)) {
|
582 |
-
continue;
|
583 |
-
}
|
584 |
-
|
585 |
-
$originalTagContents = (isset($scriptTagObj->nodeValue) && trim($scriptTagObj->nodeValue) !== '') ? $scriptTagObj->nodeValue : false;
|
586 |
-
|
587 |
-
if ($originalTagContents) {
|
588 |
-
$newTagContents = self::maybeAlterJsContent($originalTagContents, $doJsMinifyInline);
|
589 |
-
|
590 |
-
if ($newTagContents !== $originalTagContents) {
|
591 |
-
$htmlSource = str_ireplace(
|
592 |
-
'>' . $originalTagContents . '</script',
|
593 |
-
'>' . $newTagContents . '</script',
|
594 |
-
$htmlSource
|
595 |
-
);
|
596 |
-
}
|
597 |
-
|
598 |
-
libxml_clear_errors();
|
599 |
-
}
|
600 |
-
}
|
601 |
-
|
602 |
return $htmlSource;
|
603 |
}
|
604 |
|
@@ -700,13 +768,11 @@ class OptimizeJs
|
|
700 |
return $htmlSource; // no SCRIPT tags, hmm
|
701 |
}
|
702 |
|
703 |
-
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('DOMDocument')) && class_exists('DOMXpath')) {
|
704 |
return $htmlSource; // DOMDocument has to be enabled
|
705 |
}
|
706 |
|
707 |
-
$domTag =
|
708 |
-
libxml_use_internal_errors(true);
|
709 |
-
$domTag->loadHTML($htmlSource);
|
710 |
|
711 |
$scriptTagsObj = $domTag->getElementsByTagName( 'script' );
|
712 |
|
@@ -1037,6 +1103,10 @@ class OptimizeJs
|
|
1037 |
if ( $type === 'data' ) {
|
1038 |
if ( $inlineScriptContent === '' ) {
|
1039 |
$inlineScriptContent = $wp_scripts->get_data( $handle, 'data' );
|
|
|
|
|
|
|
|
|
1040 |
}
|
1041 |
|
1042 |
$output .= "<script{$typeAttr}>\n";
|
@@ -1058,10 +1128,14 @@ class OptimizeJs
|
|
1058 |
if ( $type === 'before' || $type === 'after' ) {
|
1059 |
if ( $inlineScriptContent === '' ) {
|
1060 |
$inlineScriptContent = $wp_scripts->print_inline_script( $handle, $type, false );
|
|
|
|
|
|
|
|
|
1061 |
}
|
1062 |
|
1063 |
if ( $inlineScriptContent ) {
|
1064 |
-
$output = sprintf( "<script%s>\n%s\n</script
|
1065 |
}
|
1066 |
}
|
1067 |
|
6 |
use WpAssetCleanUp\Main;
|
7 |
use WpAssetCleanUp\MetaBoxes;
|
8 |
use WpAssetCleanUp\Misc;
|
9 |
+
use WpAssetCleanUp\Plugin;
|
10 |
use WpAssetCleanUp\Preloads;
|
11 |
|
12 |
/**
|
20 |
*/
|
21 |
public function init()
|
22 |
{
|
23 |
+
add_action( 'wp_print_footer_scripts', static function() {
|
24 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'prepare_optimize_files_js' ); /* [/wpacu_timing] */
|
25 |
+
self::prepareOptimizeList();
|
26 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer( 'prepare_optimize_files_js', 'end' ); /* [/wpacu_timing] */
|
27 |
+
}, PHP_INT_MAX );
|
|
|
28 |
}
|
29 |
|
30 |
/**
|
31 |
*
|
32 |
*/
|
33 |
+
public static function prepareOptimizeList()
|
34 |
{
|
35 |
// Are both Minify and Cache Dynamic JS disabled? No point in continuing and using extra resources as there is nothing to change
|
36 |
+
if ( ! self::isWorthCheckingForOptimization() || Plugin::preventAnyChanges() ) {
|
37 |
return;
|
38 |
}
|
39 |
|
68 |
|
69 |
// [Start] Collect for caching
|
70 |
foreach ($wpScriptsList as $handle) {
|
71 |
+
if (! isset($wp_scripts->registered[$handle]->src)) {
|
72 |
+
continue;
|
73 |
+
}
|
74 |
|
75 |
$value = $wp_scripts->registered[$handle];
|
76 |
|
80 |
}
|
81 |
|
82 |
$optimizeValues = self::maybeOptimizeIt($value);
|
83 |
+
wp_cache_set('wpacu_maybe_optimize_it_js_'.$handle, $optimizeValues);
|
84 |
|
85 |
if ( ! empty( $optimizeValues ) ) {
|
86 |
$jsOptimizeList[] = $optimizeValues;
|
99 |
*/
|
100 |
public static function maybeOptimizeIt($value)
|
101 |
{
|
102 |
+
if ($optimizeValues = wp_cache_get('wpacu_maybe_optimize_it_js_'.$value->handle)) {
|
103 |
+
return $optimizeValues;
|
104 |
+
}
|
105 |
+
|
106 |
global $wp_version;
|
107 |
|
108 |
$src = isset($value->src) ? $value->src : false;
|
119 |
$doFileMinify = false;
|
120 |
}
|
121 |
|
122 |
+
$dbVer = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
|
123 |
|
124 |
$handleDbStr = md5($value->handle);
|
125 |
|
126 |
$transientName = 'wpacu_js_optimize_'.$handleDbStr;
|
127 |
|
128 |
+
$skipCache = false;
|
129 |
+
|
130 |
+
if (isset($_GET['wpacu_no_cache'])) {
|
131 |
+
$skipCache = true;
|
132 |
+
}
|
133 |
+
|
134 |
+
if (! $skipCache) {
|
135 |
+
if (Main::instance()->settings['fetch_cached_files_details_from'] === 'db_disk') {
|
136 |
if ( ! isset( $GLOBALS['wpacu_from_location_inc'] ) ) {
|
137 |
$GLOBALS['wpacu_from_location_inc'] = 1;
|
138 |
}
|
162 |
return array(
|
163 |
$savedValuesArray['source_uri'],
|
164 |
$savedValuesArray['optimize_uri'],
|
165 |
+
$value->src,
|
166 |
+
$value->handle
|
167 |
);
|
168 |
}
|
169 |
}
|
170 |
}
|
171 |
+
}
|
172 |
|
173 |
// Check if it starts without "/" or a protocol; e.g. "wp-content/theme/script.js"
|
174 |
if (strpos($src, '/') !== 0 &&
|
184 |
$src = site_url() . $src;
|
185 |
}
|
186 |
|
187 |
+
/*
|
188 |
+
* [START] JS Content Optimization
|
189 |
+
*/
|
190 |
$isJsFile = $jsContentBefore = false;
|
191 |
|
192 |
if (Main::instance()->settings['cache_dynamic_loaded_js'] &&
|
214 |
$jsContent = $jsContentBefore = FileSystem::file_get_contents($localAssetPath);
|
215 |
}
|
216 |
|
217 |
+
$jsContent = trim($jsContent);
|
218 |
|
219 |
+
// If it stays like this, it means there is content there, even if only comments
|
220 |
+
$jsContentBecomesEmptyAfterMin = false;
|
|
|
|
|
221 |
|
222 |
+
if ($doFileMinify && $jsContent) { // only bother to minify it if it has any content, save resources
|
223 |
+
// Minify this file?
|
224 |
+
$jsContentBeforeMin = $jsContent;
|
225 |
+
$jsContentAfterMin = MinifyJs::applyMinification($jsContentBeforeMin);
|
226 |
|
227 |
+
$jsContent = $jsContentAfterMin;
|
228 |
+
|
229 |
+
if ($jsContentBeforeMin && $jsContentAfterMin === '') {
|
230 |
+
// It had content, but became empty after minification, most likely it had only comments (e.g. a default child theme's style)
|
231 |
+
$jsContentBecomesEmptyAfterMin = true;
|
|
|
232 |
}
|
|
|
|
|
233 |
}
|
234 |
|
235 |
+
if ($jsContentBecomesEmptyAfterMin || $jsContent === '') {
|
236 |
+
$jsContent = '/**/';
|
237 |
+
} else {
|
238 |
+
$jsContent = self::maybeAlterContentForJsFile( $jsContent, false );
|
239 |
|
240 |
+
if ( $isJsFile && trim( $jsContent, '; ' ) === trim( $jsContentBefore, '; ' ) ) {
|
241 |
+
// The (static) JS file is already minified / No need to copy it in to the cache (save disk space)
|
242 |
+
return array();
|
243 |
}
|
244 |
+
|
245 |
+
$jsContent = self::maybeDoJsFixes( $jsContent, $pathToAssetDir . '/' ); // Minify it and save it to /wp-content/cache/js/min/
|
246 |
}
|
247 |
+
/*
|
248 |
+
* [END] JS Content Optimization
|
249 |
+
*/
|
250 |
+
|
251 |
+
// Relative path to the new file
|
252 |
+
// Save it to /wp-content/cache/js/{OptimizeCommon::$optimizedSingleFilesDir}/
|
253 |
+
$fileVer = sha1($jsContent);
|
254 |
|
255 |
+
$newFilePathUri = self::getRelPathJsCacheDir() . OptimizeCommon::$optimizedSingleFilesDir . '/' . $value->handle . '-v' . $fileVer;
|
256 |
$newFilePathUri .= '.js';
|
257 |
|
258 |
+
if ($jsContent === '') {
|
259 |
+
$jsContent = '/**/';
|
260 |
+
}
|
261 |
+
|
262 |
+
if ($jsContent === '/**/') {
|
263 |
+
// Leave a signature that the file is empty, thus it would be faster to take further actions upon it later on, saving resources)
|
264 |
+
$newFilePathUri = str_replace('.js', '-wpacu-empty-file.js', $newFilePathUri);
|
265 |
+
}
|
266 |
+
|
267 |
$newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
|
268 |
$newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
|
269 |
|
270 |
+
if ($jsContent && $jsContent !== '/**/') {
|
271 |
+
$jsContent = '/*!' . $sourceBeforeOptimization . '*/' . "\n" . $jsContent;
|
272 |
}
|
273 |
|
274 |
$saveFile = FileSystem::file_put_contents($newLocalPath, $jsContent);
|
290 |
return array(
|
291 |
OptimizeCommon::getSourceRelPath($value->src), // Original SRC (Relative path)
|
292 |
OptimizeCommon::getSourceRelPath($newLocalPathUrl), // New SRC (Relative path)
|
293 |
+
$value->src, // SRC (as it is)
|
294 |
+
$value->handle
|
295 |
);
|
296 |
}
|
297 |
|
303 |
*
|
304 |
* @return mixed|string|string[]|null
|
305 |
*/
|
306 |
+
public static function maybeAlterContentForJsFile($jsContent, $doJsMinify = false)
|
307 |
{
|
308 |
+
if (! trim($jsContent)) { // No Content! Return it as it, no point in doing extra checks
|
309 |
return $jsContent;
|
310 |
}
|
311 |
|
312 |
+
/* [START] Change JS Content */
|
313 |
if ($doJsMinify) {
|
314 |
$jsContent = MinifyJs::applyMinification($jsContent);
|
315 |
}
|
320 |
// Perhaps "display" parameter has to be applied to Google Font Links if they are active
|
321 |
$jsContent = FontsGoogle::alterGoogleFontUrlFromJsContent($jsContent);
|
322 |
}
|
323 |
+
/* [END] Change JS Content */
|
324 |
+
|
325 |
+
// Does it have a source map? Strip it
|
326 |
+
if (strpos($jsContent, 'sourceMappingURL') !== false) {
|
327 |
+
$jsContent = OptimizeCommon::stripSourceMap($jsContent);
|
328 |
+
}
|
329 |
+
|
330 |
+
return $jsContent;
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* @param $jsContent
|
335 |
+
* @param $doJsMinify
|
336 |
+
*
|
337 |
+
* @return false|mixed|string|string[]|null
|
338 |
+
*/
|
339 |
+
public static function maybeAlterContentForInlineScriptTag($jsContent, $doJsMinify)
|
340 |
+
{
|
341 |
+
if (! trim($jsContent)) { // No Content! Return it as it, no point in doing extra checks
|
342 |
+
return $jsContent;
|
343 |
+
}
|
344 |
+
|
345 |
+
if (mb_strlen($jsContent) > 500000) { // Bigger then ~500KB? Skip alteration for this inline SCRIPT
|
346 |
+
return $jsContent;
|
347 |
+
}
|
348 |
+
|
349 |
+
$useCacheForInlineScript = true;
|
350 |
+
|
351 |
+
if (mb_strlen($jsContent) < 40000) { // Smaller than ~40KB? Do not cache it
|
352 |
+
$useCacheForInlineScript = false;
|
353 |
+
}
|
354 |
+
|
355 |
+
// For debugging purposes
|
356 |
+
if (isset($_GET['wpacu_no_cache'])) { $useCacheForInlineScript = false; }
|
357 |
+
|
358 |
+
if ($useCacheForInlineScript) {
|
359 |
+
// Anything in the cache? Take it from there and don't spend resources with the minification
|
360 |
+
// (which in some environments uses the CPU, depending on the complexity of the JavaScript code) and any other alteration
|
361 |
+
$jsContentBeforeHash = sha1( $jsContent );
|
362 |
+
|
363 |
+
$pathToInlineJsOptimizedItem = WP_CONTENT_DIR . self::getRelPathJsCacheDir() . '/item/inline/' . $jsContentBeforeHash . '.js';
|
364 |
+
|
365 |
+
// Check if the file exists before moving forward
|
366 |
+
if ( is_file( $pathToInlineJsOptimizedItem ) ) {
|
367 |
+
$cachedJsFileExpiresIn = OptimizeCommon::$cachedAssetFileExpiresIn;
|
368 |
+
|
369 |
+
if ( filemtime( $pathToInlineJsOptimizedItem ) < ( time() - 1 * $cachedJsFileExpiresIn ) ) {
|
370 |
+
// Has the caching period expired? Remove the file as a new one has to be generated
|
371 |
+
@unlink( $pathToInlineJsOptimizedItem );
|
372 |
+
} else {
|
373 |
+
// Not expired / Return its content from the cache in a faster way
|
374 |
+
$inlineJsStorageItemJsonContent = FileSystem::file_get_contents( $pathToInlineJsOptimizedItem );
|
375 |
+
|
376 |
+
if ( $inlineJsStorageItemJsonContent !== '' ) {
|
377 |
+
return $inlineJsStorageItemJsonContent;
|
378 |
+
}
|
379 |
+
}
|
380 |
+
}
|
381 |
+
}
|
382 |
+
|
383 |
+
/* [START] Change JS Content */
|
384 |
+
if ($doJsMinify) {
|
385 |
+
$jsContent = MinifyJs::applyMinification($jsContent);
|
386 |
+
}
|
387 |
+
|
388 |
+
if (Main::instance()->settings['google_fonts_remove']) {
|
389 |
+
$jsContent = FontsGoogleRemove::stripReferencesFromJsCode($jsContent);
|
390 |
+
} elseif (Main::instance()->settings['google_fonts_display']) {
|
391 |
+
// Perhaps "display" parameter has to be applied to Google Font Links if they are active
|
392 |
+
$jsContent = FontsGoogle::alterGoogleFontUrlFromJsContent($jsContent);
|
393 |
+
}
|
394 |
+
/* [END] Change JS Content */
|
395 |
+
|
396 |
+
if ( $useCacheForInlineScript && isset($pathToInlineJsOptimizedItem)) {
|
397 |
+
// Store the optimized content to the cached JS file which would be read quicker
|
398 |
+
FileSystem::file_put_contents( $pathToInlineJsOptimizedItem, $jsContent );
|
399 |
+
}
|
400 |
|
401 |
return $jsContent;
|
402 |
}
|
414 |
$cdnUrls = OptimizeCommon::getAnyCdnUrls();
|
415 |
$cdnUrlForJs = isset($cdnUrls['js']) ? $cdnUrls['js'] : false;
|
416 |
|
417 |
+
preg_match_all('#(<script[^>]*src(|\s+)=(|\s+)[^>]*>)|(<link[^>]*(as(\s+|)=(\s+|)(|"|\')script(|"|\'))[^>]*>)#Umi', $htmlSource, $matchesSourcesFromTags, PREG_SET_ORDER);
|
418 |
+
|
419 |
+
$scriptTagsToUpdate = array();
|
420 |
|
421 |
foreach ($matchesSourcesFromTags as $matches) {
|
422 |
$scriptSourceTag = $matches[0];
|
434 |
$forAttr = 'href';
|
435 |
}
|
436 |
|
437 |
+
$cleanScriptSrcFromTagArray = OptimizeCommon::getLocalCleanSourceFromTag($scriptSourceTag, $forAttr);
|
438 |
+
|
439 |
+
// Skip external links, no point in carrying on
|
440 |
+
if (! $cleanScriptSrcFromTagArray || ! is_array($cleanScriptSrcFromTagArray)) {
|
441 |
+
continue;
|
442 |
+
}
|
443 |
+
|
444 |
// Is it a local JS? Check if it's hardcoded (not enqueued the WordPress way)
|
445 |
+
$cleanScriptSrcFromTag = $cleanScriptSrcFromTagArray['source'];
|
446 |
+
$afterQuestionMark = $cleanScriptSrcFromTagArray['after_question_mark'];
|
447 |
+
|
448 |
+
if (! in_array($cleanScriptSrcFromTag, $allEnqueuedCleanScriptSrcs)) {
|
449 |
+
// Not in the final enqueued list? Most likely hardcoded (not added via wp_enqueue_scripts())
|
450 |
+
// Emulate the object value (as the enqueued styles)
|
451 |
+
$generatedHandle = md5($cleanScriptSrcFromTag);
|
452 |
+
|
453 |
+
$value = (object)array(
|
454 |
+
'handle' => $generatedHandle,
|
455 |
+
'src' => $cleanScriptSrcFromTag,
|
456 |
+
'ver' => md5($afterQuestionMark)
|
457 |
+
);
|
458 |
+
|
459 |
+
$optimizeValues = self::maybeOptimizeIt($value);
|
460 |
+
wp_cache_set('wpacu_maybe_optimize_it_js_'.$generatedHandle, $optimizeValues);
|
461 |
+
|
462 |
+
if (! empty($optimizeValues)) {
|
463 |
+
$jsOptimizeList[] = $optimizeValues;
|
464 |
}
|
465 |
}
|
466 |
|
468 |
continue;
|
469 |
}
|
470 |
|
471 |
+
foreach ($jsOptimizeList as $jsItemIndex => $listValues) {
|
472 |
// Index 0: Source URL (relative)
|
473 |
// Index 1: New Optimized URL (relative)
|
474 |
// Index 2: Source URL (as it is)
|
475 |
|
476 |
// If the minified files are deleted (e.g. /wp-content/cache/ is cleared)
|
477 |
// do not replace the JS file path to avoid breaking the website
|
478 |
+
$localPathOptimizedFile = rtrim(ABSPATH, '/') . $listValues[1];
|
479 |
+
|
480 |
+
if (! is_file($localPathOptimizedFile)) {
|
481 |
continue;
|
482 |
}
|
483 |
|
508 |
$optimizeUrl = OptimizeCommon::cdnToUrlFormat($cdnUrlForJs, 'raw') . $listValues[1]; // string
|
509 |
|
510 |
if ($scriptSourceTag !== str_ireplace($sourceUrlList, $optimizeUrl, $scriptSourceTag)) {
|
511 |
+
// Extra measure: Check the file size which should be 4 bytes, but add some margin error in case some environments will report less
|
512 |
+
$isEmptyOptimizedFile = (strpos($localPathOptimizedFile, '-wpacu-empty-file.js') !== false && filesize($localPathOptimizedFile) < 10);
|
513 |
+
|
514 |
+
if ($isEmptyOptimizedFile) {
|
515 |
+
// Strip it as its content (after optimization, for instance) is empty; no point in having extra HTTP requests
|
516 |
+
$scriptTagsToUpdate[$scriptSourceTag.'</script>'] = '';
|
517 |
+
|
518 |
+
// Any SCRIPT inline associated with the tag? Strip it
|
519 |
+
foreach (array('data', 'before', 'after') as $inlineType) {
|
520 |
+
if ( $scriptExtraAfterHtml = self::generateInlineAssocHtmlForHandle( $listValues[3], $inlineType ) ) {
|
521 |
+
if (strlen($scriptExtraAfterHtml) < 200) { // strtr() does better with smaller keys
|
522 |
+
$scriptTagsToUpdate[ $scriptExtraAfterHtml ] = '';
|
523 |
+
} else {
|
524 |
+
$htmlSource = str_replace( $scriptExtraAfterHtml, '', $htmlSource );
|
525 |
+
}
|
526 |
+
}
|
527 |
+
}
|
528 |
+
} else {
|
529 |
+
$newScriptSourceTag = self::updateOriginalToOptimizedTag( $scriptSourceTag, $sourceUrlList, $optimizeUrl );
|
530 |
+
$scriptTagsToUpdate[$scriptSourceTag] = $newScriptSourceTag;
|
531 |
+
}
|
532 |
+
|
533 |
+
unset($jsOptimizeList[$jsItemIndex]); // item from the array is not needed anymore
|
534 |
break;
|
535 |
}
|
536 |
}
|
537 |
}
|
538 |
|
539 |
+
$htmlSource = strtr($htmlSource, $scriptTagsToUpdate);
|
540 |
+
|
541 |
return $htmlSource;
|
542 |
}
|
543 |
|
629 |
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
630 |
}
|
631 |
|
632 |
+
/* [wpacu_timing] */ $wpacuTimingName = 'alter_html_source_for_combine_js';
|
633 |
+
|
634 |
+
Misc::scriptExecTimer($wpacuTimingName); /* [/wpacu_timing] */
|
635 |
$proceedWithCombineOnThisPage = true;
|
636 |
|
637 |
// If "Do not combine JS on this page" is checked in "Asset CleanUp Options" side meta box
|
649 |
/* [wpacu_timing] */ // Note: Load timing is checked within the method /* [/wpacu_timing] */
|
650 |
$htmlSource = CombineJs::doCombine($htmlSource);
|
651 |
}
|
652 |
+
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
653 |
|
654 |
+
if (self::isWorthCheckingForOptimization() && ! Main::instance()->preventAssetsSettings() && (MinifyJs::isMinifyJsEnabled() && Main::instance()->settings['minify_loaded_js_inline'])) {
|
655 |
/* [wpacu_timing] */ $wpacuTimingName = 'alter_html_source_for_minify_inline_script_tags'; Misc::scriptExecTimer($wpacuTimingName); /* [/wpacu_timing] */
|
656 |
+
$htmlSource = MinifyJs::minifyInlineScriptTags($htmlSource);
|
657 |
/* [wpacu_timing] */ Misc::scriptExecTimer($wpacuTimingName, 'end'); /* [/wpacu_timing] */
|
658 |
}
|
659 |
|
660 |
// Final cleanups
|
661 |
+
$htmlSource = preg_replace('#(\s+|)(data-wpacu-jquery-core-handle=1|data-wpacu-jquery-migrate-handle=1)(\s+|)#Umi', ' ', $htmlSource);
|
662 |
|
663 |
+
$htmlSource = preg_replace('#(\s+|)data-wpacu-script-rel-src-before=(["\'])' . '(.*)' . '(\1)(\s+|)#Usmi', ' ', $htmlSource);
|
664 |
$htmlSource = preg_replace('#<script(.*)data-wpacu-script-handle=\'(.*)\'#Umi', '<script \\1', $htmlSource);
|
665 |
|
666 |
// Clear possible empty SCRIPT tags (e.g. left from associated 'before' and 'after' tags after their content was stripped)
|
667 |
$htmlSource = preg_replace('#<script(\s+| )(type=\'text/javascript\'|)(\s+|)></script>#Umi', '', $htmlSource);
|
668 |
|
669 |
/* [wpacu_timing] */ Misc::scriptExecTimer('alter_html_source_for_optimize_js', 'end'); /* [/wpacu_timing] */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
670 |
return $htmlSource;
|
671 |
}
|
672 |
|
768 |
return $htmlSource; // no SCRIPT tags, hmm
|
769 |
}
|
770 |
|
771 |
+
if (! (function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('\DOMDocument')) && class_exists('\DOMXpath')) {
|
772 |
return $htmlSource; // DOMDocument has to be enabled
|
773 |
}
|
774 |
|
775 |
+
$domTag = OptimizeCommon::getDomLoadedTag($htmlSource, 'moveInlinejQueryAfterjQuerySrc');
|
|
|
|
|
776 |
|
777 |
$scriptTagsObj = $domTag->getElementsByTagName( 'script' );
|
778 |
|
1103 |
if ( $type === 'data' ) {
|
1104 |
if ( $inlineScriptContent === '' ) {
|
1105 |
$inlineScriptContent = $wp_scripts->get_data( $handle, 'data' );
|
1106 |
+
|
1107 |
+
if (! $inlineScriptContent) {
|
1108 |
+
return '';
|
1109 |
+
}
|
1110 |
}
|
1111 |
|
1112 |
$output .= "<script{$typeAttr}>\n";
|
1128 |
if ( $type === 'before' || $type === 'after' ) {
|
1129 |
if ( $inlineScriptContent === '' ) {
|
1130 |
$inlineScriptContent = $wp_scripts->print_inline_script( $handle, $type, false );
|
1131 |
+
|
1132 |
+
if (! $inlineScriptContent) {
|
1133 |
+
return '';
|
1134 |
+
}
|
1135 |
}
|
1136 |
|
1137 |
if ( $inlineScriptContent ) {
|
1138 |
+
$output = sprintf( "<script%s>\n%s\n</script>\n", $typeAttr, $inlineScriptContent );
|
1139 |
}
|
1140 |
}
|
1141 |
|
classes/OwnAssets.php
CHANGED
@@ -43,6 +43,13 @@ class OwnAssets
|
|
43 |
$wpacu_object_data['source_load_error_msg'] = __('It looks like the source is not reachable', 'wp-asset-clean-up');
|
44 |
$wpacu_object_data['plugin_id'] = WPACU_PLUGIN_ID;
|
45 |
$wpacu_object_data['ajax_url'] = admin_url('admin-ajax.php');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
$wpacu_object_data['jquery_unload_alert'] = 'jQuery library is a WordPress library that it is used in WordPress plugins/themes most of the time.'."\n\n".
|
48 |
'There are currently other JavaScript "children" files connected to it, that will stop working, if this library is unloaded'."\n\n".
|
@@ -95,6 +102,12 @@ class OwnAssets
|
|
95 |
* [End] Trigger ONLY other plugins'/system caches
|
96 |
*/
|
97 |
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
return $wpacu_object_data;
|
99 |
});
|
100 |
}
|
@@ -362,48 +375,38 @@ HTML;
|
|
362 |
</div>
|
363 |
HTML;
|
364 |
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
'wp-asset-clean-up') . "\n\n" .
|
398 |
-
__('This is an irreversible action.', 'wp-asset-clean-up') . "\n\n" .
|
399 |
-
__('Please confirm to continue or "Cancel" to abort it.', 'wp-asset-clean-up');
|
400 |
-
|
401 |
-
// "Tools" - "Import & Export"
|
402 |
-
$wpacuObjectData['import_confirm_msg'] =
|
403 |
-
__('This process is NOT reversible.', 'wp-asset-clean-up') . "\n\n" .
|
404 |
-
__('Please make sure you have a backup (e.g. an exported JSON file) before proceeding.',
|
405 |
-
'wp-asset-clean-up') . "\n\n" .
|
406 |
-
__('Please confirm to continue or "Cancel" to abort it.', 'wp-asset-clean-up');
|
407 |
|
408 |
wp_localize_script(
|
409 |
WPACU_PLUGIN_ID . '-script',
|
43 |
$wpacu_object_data['source_load_error_msg'] = __('It looks like the source is not reachable', 'wp-asset-clean-up');
|
44 |
$wpacu_object_data['plugin_id'] = WPACU_PLUGIN_ID;
|
45 |
$wpacu_object_data['ajax_url'] = admin_url('admin-ajax.php');
|
46 |
+
$wpacu_object_data['is_frontend_view'] = false;
|
47 |
+
|
48 |
+
// Current Page URL (for preloading) in the front-end view
|
49 |
+
if (! is_admin()) {
|
50 |
+
$wpacu_object_data['page_url'] = Misc::getCurrentPageUrl();
|
51 |
+
$wpacu_object_data['is_frontend_view'] = true;
|
52 |
+
}
|
53 |
|
54 |
$wpacu_object_data['jquery_unload_alert'] = 'jQuery library is a WordPress library that it is used in WordPress plugins/themes most of the time.'."\n\n".
|
55 |
'There are currently other JavaScript "children" files connected to it, that will stop working, if this library is unloaded'."\n\n".
|
102 |
* [End] Trigger ONLY other plugins'/system caches
|
103 |
*/
|
104 |
|
105 |
+
$wpacu_object_data['server_returned_404_not_found'] = sprintf(
|
106 |
+
__('When accessing this page the server responded with a status of %s404 (Not Found)%s. If this page is meant to return this status, you can ignore this message, otherwise you might have a problem with this page if it is meant to return a standard 200 OK status.', 'wp-asset-clean-up'),
|
107 |
+
'<strong>',
|
108 |
+
'</strong>'
|
109 |
+
);
|
110 |
+
|
111 |
return $wpacu_object_data;
|
112 |
});
|
113 |
}
|
375 |
</div>
|
376 |
HTML;
|
377 |
|
378 |
+
$wpacuObjectData['jquery_migration_disable_confirm_msg'] =
|
379 |
+
__('Make sure to properly test your website if you unload the jQuery migration library.', 'wp-asset-clean-up')."\n\n".
|
380 |
+
__('In some cases, due to old jQuery code triggered from plugins or the theme, unloading this migration library could cause those scripts not to function anymore and break some of the front-end functionality.', 'wp-asset-clean-up')."\n\n".
|
381 |
+
__('If you are not sure about whether activating this option is right or not, it is better to leave it as it is (to be loaded by default) and consult with a developer.', 'wp-asset-clean-up')."\n\n".
|
382 |
+
__('Confirm this action to enable the unloading or cancel to leave it loaded by default.', 'wp-asset-clean-up');
|
383 |
+
|
384 |
+
$wpacuObjectData['comment_reply_disable_confirm_msg'] =
|
385 |
+
__('This is worth disabling if you are NOT using the default WordPress comment system (e.g. you are using the website for business purposes, to showcase your products and you are not using it as a blog where people leave comments to your posts).', 'wp-asset-clean-up')."\n\n".
|
386 |
+
__('If you are not sure about whether activating this option is right or not, it is better to leave it as it is (to be loaded by default).', 'wp-asset-clean-up')."\n\n".
|
387 |
+
__('Confirm this action to enable the unloading or cancel to leave it loaded by default.', 'wp-asset-clean-up');
|
388 |
+
|
389 |
+
// "Tools" - "Reset"
|
390 |
+
$wpacuObjectData['reset_settings_confirm_msg'] =
|
391 |
+
__('Are you sure you want to reset the settings to their default values?', 'wp-asset-clean-up')."\n\n".
|
392 |
+
__('This is an irreversible action.', 'wp-asset-clean-up')."\n\n".
|
393 |
+
__('Please confirm to continue or "Cancel" to abort it', 'wp-asset-clean-up');
|
394 |
+
|
395 |
+
$wpacuObjectData['reset_everything_except_settings_confirm_msg'] =
|
396 |
+
__('Are you sure you want to reset everything (unloads, load exceptions etc.) except settings?', 'wp-asset-clean-up')."\n\n".
|
397 |
+
__('This is an irreversible action.', 'wp-asset-clean-up')."\n\n".
|
398 |
+
__('Please confirm to continue or "Cancel" to abort it.', 'wp-asset-clean-up');
|
399 |
+
|
400 |
+
$wpacuObjectData['reset_everything_confirm_msg'] =
|
401 |
+
__('Are you sure you want to reset everything (settings, unloads, load exceptions etc.) to the same point it was when you first activated the plugin?', 'wp-asset-clean-up')."\n\n".
|
402 |
+
__('This is an irreversible action.', 'wp-asset-clean-up')."\n\n".
|
403 |
+
__('Please confirm to continue or "Cancel" to abort it.', 'wp-asset-clean-up');
|
404 |
+
|
405 |
+
// "Tools" - "Import & Export"
|
406 |
+
$wpacuObjectData['import_confirm_msg'] =
|
407 |
+
__('This process is NOT reversible.', 'wp-asset-clean-up')."\n\n".
|
408 |
+
__('Please make sure you have a backup (e.g. an exported JSON file) before proceeding.', 'wp-asset-clean-up')."\n\n".
|
409 |
+
__('Please confirm to continue or "Cancel" to abort it.', 'wp-asset-clean-up');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
|
411 |
wp_localize_script(
|
412 |
WPACU_PLUGIN_ID . '-script',
|
classes/Plugin.php
CHANGED
@@ -17,8 +17,6 @@ class Plugin
|
|
17 |
const RATE_URL = 'https://wordpress.org/support/plugin/wp-asset-clean-up/reviews/?filter=5#new-post';
|
18 |
|
19 |
/**
|
20 |
-
* The functions below are only called within the Dashboard
|
21 |
-
*
|
22 |
* Plugin constructor.
|
23 |
*/
|
24 |
public function __construct()
|
@@ -109,14 +107,10 @@ class Plugin
|
|
109 |
* /wp-content/cache/asset-cleanup/css/
|
110 |
* /wp-content/cache/asset-cleanup/css/item/
|
111 |
* /wp-content/cache/asset-cleanup/css/index.php
|
112 |
-
* /wp-content/cache/asset-cleanup/css/logged-in/
|
113 |
-
* /wp-content/cache/asset-cleanup/css/logged-in/index.php
|
114 |
*
|
115 |
* /wp-content/cache/asset-cleanup/js/
|
116 |
* /wp-content/cache/asset-cleanup/js/item/
|
117 |
* /wp-content/cache/asset-cleanup/js/index.php
|
118 |
-
* /wp-content/cache/asset-cleanup/js/logged-in/
|
119 |
-
* /wp-content/cache/asset-cleanup/js/logged-in/index.php
|
120 |
*
|
121 |
*/
|
122 |
self::createCacheFoldersFiles(array('css','js'));
|
@@ -192,6 +186,11 @@ SQL;
|
|
192 |
public static function removeCacheDirWithoutAssets()
|
193 |
{
|
194 |
$pathToCacheDir = WP_CONTENT_DIR . OptimizeCommon::getRelPathPluginCacheDir();
|
|
|
|
|
|
|
|
|
|
|
195 |
$pathToCacheDirCss = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir();
|
196 |
$pathToCacheDirJs = WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir();
|
197 |
|
@@ -255,21 +254,24 @@ HTACCESS;
|
|
255 |
}
|
256 |
|
257 |
if ( ! is_file( $cacheDir . 'index.php' ) ) {
|
258 |
-
// /wp-content/cache/asset-cleanup/cache/
|
259 |
FileSystem::file_put_contents( $cacheDir . 'index.php', $emptyPhpFileContents );
|
260 |
}
|
261 |
|
262 |
-
if ( ! is_dir( $cacheDir . 'logged-in' ) ) {
|
263 |
-
@mkdir( $cacheDir . 'logged-in', 0755 );
|
264 |
-
}
|
265 |
-
|
266 |
if ( ! is_dir( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir ) ) {
|
|
|
267 |
@mkdir( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir, 0755 );
|
268 |
}
|
269 |
|
270 |
-
|
271 |
-
|
272 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
}
|
274 |
|
275 |
$htAccessFilePath = dirname( $cacheDir ) . '/.htaccess';
|
@@ -357,7 +359,8 @@ HTACCESS;
|
|
357 |
}
|
358 |
|
359 |
/**
|
360 |
-
* This works like /?
|
|
|
361 |
* It needs to be triggered through a very early 'init' action hook after all plugins are loaded, thus it can't be used in /early-triggers.php
|
362 |
* e.g. in situations when the page is an AMP one, prevent any changes to the HTML source by Asset CleanUp Pro
|
363 |
*
|
@@ -371,6 +374,12 @@ HTACCESS;
|
|
371 |
return false;
|
372 |
}
|
373 |
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
if (defined('WPACU_PREVENT_ANY_CHANGES')) {
|
375 |
return WPACU_PREVENT_ANY_CHANGES;
|
376 |
}
|
@@ -388,6 +397,7 @@ HTACCESS;
|
|
388 |
}
|
389 |
|
390 |
if (array_key_exists('wpacu_clean_load', $_GET)) {
|
|
|
391 |
return true;
|
392 |
}
|
393 |
|
17 |
const RATE_URL = 'https://wordpress.org/support/plugin/wp-asset-clean-up/reviews/?filter=5#new-post';
|
18 |
|
19 |
/**
|
|
|
|
|
20 |
* Plugin constructor.
|
21 |
*/
|
22 |
public function __construct()
|
107 |
* /wp-content/cache/asset-cleanup/css/
|
108 |
* /wp-content/cache/asset-cleanup/css/item/
|
109 |
* /wp-content/cache/asset-cleanup/css/index.php
|
|
|
|
|
110 |
*
|
111 |
* /wp-content/cache/asset-cleanup/js/
|
112 |
* /wp-content/cache/asset-cleanup/js/item/
|
113 |
* /wp-content/cache/asset-cleanup/js/index.php
|
|
|
|
|
114 |
*
|
115 |
*/
|
116 |
self::createCacheFoldersFiles(array('css','js'));
|
186 |
public static function removeCacheDirWithoutAssets()
|
187 |
{
|
188 |
$pathToCacheDir = WP_CONTENT_DIR . OptimizeCommon::getRelPathPluginCacheDir();
|
189 |
+
|
190 |
+
if (! is_dir($pathToCacheDir)) {
|
191 |
+
return;
|
192 |
+
}
|
193 |
+
|
194 |
$pathToCacheDirCss = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir();
|
195 |
$pathToCacheDirJs = WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir();
|
196 |
|
254 |
}
|
255 |
|
256 |
if ( ! is_file( $cacheDir . 'index.php' ) ) {
|
257 |
+
// /wp-content/cache/asset-cleanup/cache/(css|js)/index.php
|
258 |
FileSystem::file_put_contents( $cacheDir . 'index.php', $emptyPhpFileContents );
|
259 |
}
|
260 |
|
|
|
|
|
|
|
|
|
261 |
if ( ! is_dir( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir ) ) {
|
262 |
+
// /wp-content/cache/asset-cleanup/cache/(css|js)/item/
|
263 |
@mkdir( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir, 0755 );
|
264 |
}
|
265 |
|
266 |
+
// For large inline STYLE & SCRIPT tags
|
267 |
+
if ( ! is_dir( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir.'/inline' ) ) {
|
268 |
+
// /wp-content/cache/asset-cleanup/cache/(css|js)/item/inline/
|
269 |
+
@mkdir( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir.'/inline', 0755 );
|
270 |
+
}
|
271 |
+
|
272 |
+
if ( ! is_file( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir.'/inline/index.php' ) ) {
|
273 |
+
// /wp-content/cache/asset-cleanup/cache/(css|js)/item/inline/index.php
|
274 |
+
FileSystem::file_put_contents( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir.'/inline/index.php', $emptyPhpFileContents );
|
275 |
}
|
276 |
|
277 |
$htAccessFilePath = dirname( $cacheDir ) . '/.htaccess';
|
359 |
}
|
360 |
|
361 |
/**
|
362 |
+
* This works like /?wpacu_no_lo
|
363 |
+
* ad with a fundamental difference:
|
364 |
* It needs to be triggered through a very early 'init' action hook after all plugins are loaded, thus it can't be used in /early-triggers.php
|
365 |
* e.g. in situations when the page is an AMP one, prevent any changes to the HTML source by Asset CleanUp Pro
|
366 |
*
|
374 |
return false;
|
375 |
}
|
376 |
|
377 |
+
// Perhaps the editor from "Pro" (theme.co) is on
|
378 |
+
if (apply_filters('wpacu_prevent_any_changes', false)) {
|
379 |
+
define('WPACU_PREVENT_ANY_CHANGES', true);
|
380 |
+
return true;
|
381 |
+
}
|
382 |
+
|
383 |
if (defined('WPACU_PREVENT_ANY_CHANGES')) {
|
384 |
return WPACU_PREVENT_ANY_CHANGES;
|
385 |
}
|
397 |
}
|
398 |
|
399 |
if (array_key_exists('wpacu_clean_load', $_GET)) {
|
400 |
+
define('WPACU_PREVENT_ANY_CHANGES', true);
|
401 |
return true;
|
402 |
}
|
403 |
|
classes/Preloads.php
CHANGED
@@ -92,7 +92,7 @@ class Preloads
|
|
92 |
$preloads = $this->getPreloads();
|
93 |
|
94 |
if (isset($preloads['styles']) && ! empty($preloads['styles'])) {
|
95 |
-
$htmlSource = self::appendPreloadsForStylesToHead($htmlSource);
|
96 |
}
|
97 |
|
98 |
$htmlSource = str_replace(self::DEL_STYLES_PRELOADS, '', $htmlSource);
|
@@ -229,7 +229,8 @@ class Preloads
|
|
229 |
}
|
230 |
|
231 |
if (array_key_exists($handle, $this->preloads['styles']) && $this->preloads['styles'][$handle]) {
|
232 |
-
|
|
|
233 |
}
|
234 |
|
235 |
return $htmlTag;
|
@@ -269,25 +270,51 @@ class Preloads
|
|
269 |
|
270 |
/**
|
271 |
* @param $htmlSource
|
|
|
272 |
*
|
273 |
* @return mixed
|
274 |
*/
|
275 |
-
public static function appendPreloadsForStylesToHead($htmlSource)
|
276 |
{
|
277 |
-
//
|
278 |
-
if (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
$documentForCSS = new \DOMDocument();
|
280 |
libxml_use_internal_errors(true);
|
281 |
|
282 |
-
$
|
|
|
|
|
283 |
$linkTags = $documentForCSS->getElementsByTagName( 'link' );
|
284 |
|
285 |
-
$matchesSourcesFromLinkTags = array();
|
286 |
|
287 |
foreach ( $linkTags as $tagObject ) {
|
288 |
-
if (
|
289 |
-
continue;
|
290 |
-
}
|
291 |
|
292 |
$linkAttributes = array();
|
293 |
|
@@ -301,10 +328,7 @@ class Preloads
|
|
301 |
}
|
302 |
|
303 |
libxml_clear_errors();
|
304 |
-
}
|
305 |
-
$strContainsFormat = preg_quote('data-wpacu-to-be-preloaded-basic=\'1\'', '/');
|
306 |
-
preg_match_all('#<link[^>]'.$strContainsFormat.'[^>]*' . 'href=([\'"])(.*)([\'"])' . '.*(>)#Usmi', $htmlSource, $matchesSourcesFromLinkTags, PREG_SET_ORDER);
|
307 |
-
}
|
308 |
|
309 |
foreach ($matchesSourcesFromLinkTags as $linkTagArray) {
|
310 |
$linkHref = isset($linkTagArray[2]) ? $linkTagArray[2] : false;
|
92 |
$preloads = $this->getPreloads();
|
93 |
|
94 |
if (isset($preloads['styles']) && ! empty($preloads['styles'])) {
|
95 |
+
$htmlSource = self::appendPreloadsForStylesToHead($htmlSource, array_keys($preloads['styles']));
|
96 |
}
|
97 |
|
98 |
$htmlSource = str_replace(self::DEL_STYLES_PRELOADS, '', $htmlSource);
|
229 |
}
|
230 |
|
231 |
if (array_key_exists($handle, $this->preloads['styles']) && $this->preloads['styles'][$handle]) {
|
232 |
+
ObjectCache::wpacu_cache_set($handle, 1, 'wpacu_basic_preload_handles');
|
233 |
+
return str_replace('<link ', '<link data-wpacu-to-be-preloaded-basic=\'1\' ', $htmlTag);
|
234 |
}
|
235 |
|
236 |
return $htmlTag;
|
270 |
|
271 |
/**
|
272 |
* @param $htmlSource
|
273 |
+
* @param $preloadedHandles
|
274 |
*
|
275 |
* @return mixed
|
276 |
*/
|
277 |
+
public static function appendPreloadsForStylesToHead($htmlSource, $preloadedHandles)
|
278 |
{
|
279 |
+
// Perhaps it's not applicable in the current page (no LINK tags are loaded that should be preloaded)
|
280 |
+
if (strpos($htmlSource, 'data-wpacu-to-be-preloaded-basic') === false) {
|
281 |
+
return $htmlSource;
|
282 |
+
}
|
283 |
+
|
284 |
+
// Use the RegEx as it's much faster and very accurate in this situation
|
285 |
+
// If there are issues, fallback to DOMDocument
|
286 |
+
$strContainsFormat = preg_quote('data-wpacu-to-be-preloaded-basic', '/');
|
287 |
+
preg_match_all('#<link[^>]'.$strContainsFormat.'[^>]*' . 'href=(\'|"|)(.*)(\\1?\s)' . '.*(>)#Usmi', $htmlSource, $matchesSourcesFromLinkTags, PREG_SET_ORDER);
|
288 |
+
|
289 |
+
$stickToRegEx = true; // default
|
290 |
+
|
291 |
+
foreach ($matchesSourcesFromLinkTags as $linkTagArray) {
|
292 |
+
$linkTag = $linkTagArray[0];
|
293 |
+
|
294 |
+
preg_match_all('#id=([\'"])(.*?)(\\1)#', $linkTag, $matchId);
|
295 |
+
$matchedCssId = isset($matchId[2][0]) ? $matchId[2][0] : '';
|
296 |
+
$matchedCssHandle = substr($matchedCssId, 0, -4);
|
297 |
+
|
298 |
+
if (! in_array($matchedCssHandle, $preloadedHandles)) {
|
299 |
+
$stickToRegEx = false;
|
300 |
+
break;
|
301 |
+
}
|
302 |
+
}
|
303 |
+
|
304 |
+
// Something might not be right with the RegEx; Fallback to DOMDocument, more accurate, but slower
|
305 |
+
if (! $stickToRegEx && function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('\DOMDocument')) {
|
306 |
$documentForCSS = new \DOMDocument();
|
307 |
libxml_use_internal_errors(true);
|
308 |
|
309 |
+
$htmlSourceAlt = preg_replace( '@<(noscript|style|script)[^>]*?>.*?</\\1>@si', '', $htmlSource );
|
310 |
+
$documentForCSS->loadHTML($htmlSourceAlt);
|
311 |
+
|
312 |
$linkTags = $documentForCSS->getElementsByTagName( 'link' );
|
313 |
|
314 |
+
$matchesSourcesFromLinkTags = array(); // reset its value; new fetch method was used
|
315 |
|
316 |
foreach ( $linkTags as $tagObject ) {
|
317 |
+
if (empty($tagObject->attributes)) { continue; }
|
|
|
|
|
318 |
|
319 |
$linkAttributes = array();
|
320 |
|
328 |
}
|
329 |
|
330 |
libxml_clear_errors();
|
331 |
+
}
|
|
|
|
|
|
|
332 |
|
333 |
foreach ($matchesSourcesFromLinkTags as $linkTagArray) {
|
334 |
$linkHref = isset($linkTagArray[2]) ? $linkTagArray[2] : false;
|
classes/Settings.php
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp;
|
3 |
|
4 |
-
use WpAssetCleanUp\OptimiseAssets\OptimizeCommon;
|
5 |
use WpAssetCleanUp\OptimiseAssets\OptimizeCss;
|
6 |
use WpAssetCleanUp\OptimiseAssets\OptimizeJs;
|
7 |
|
@@ -55,7 +54,6 @@ class Settings
|
|
55 |
'combine_loaded_css_for_admin_only', // Since v1.1.1.4 (Pro) & v1.3.1.1 (Lite)
|
56 |
|
57 |
// [wpacu_pro]
|
58 |
-
'combine_loaded_css_append_handle_extra', // Adds any associated inline STYLE tags content to the combined files
|
59 |
'defer_css_loaded_body',
|
60 |
// [/wpacu_pro]
|
61 |
|
@@ -85,10 +83,6 @@ class Settings
|
|
85 |
'combine_loaded_js_for_admin_only',
|
86 |
'combine_loaded_js_defer_body', // Applies defer="defer" to the combined file(s) within BODY tag
|
87 |
|
88 |
-
// [wpacu_pro]
|
89 |
-
'combine_loaded_js_append_handle_extra', // Adds any CDATA and other associated inline SCRIPT tags content to the combined files
|
90 |
-
// [/wpacu_pro]
|
91 |
-
|
92 |
// Minify each loaded CSS (remaining ones after unloading the useless ones)
|
93 |
'minify_loaded_css',
|
94 |
'minify_loaded_css_inline',
|
@@ -233,12 +227,7 @@ class Settings
|
|
233 |
// [/wpacu_pro]
|
234 |
|
235 |
'combine_loaded_css_exceptions' => '/plugins/wd-instagram-feed/(.*?).css',
|
236 |
-
'
|
237 |
-
|
238 |
-
'combine_loaded_js_exceptions' => '/plugins/wd-instagram-feed/(.*?).js',
|
239 |
-
// [wpacu_pro]
|
240 |
-
'combine_loaded_js_append_handle_extra' => '1',
|
241 |
-
// [/wpacu_pro]
|
242 |
|
243 |
// [wpacu_pro]
|
244 |
'defer_css_loaded_body' => 'moved',
|
@@ -254,7 +243,7 @@ class Settings
|
|
254 |
|
255 |
'fetch_cached_files_details_from' => 'disk', // Do not add more rows to the database by default (options table can become quite large)
|
256 |
|
257 |
-
'clear_cached_files_after' => '
|
258 |
);
|
259 |
}
|
260 |
|
1 |
<?php
|
2 |
namespace WpAssetCleanUp;
|
3 |
|
|
|
4 |
use WpAssetCleanUp\OptimiseAssets\OptimizeCss;
|
5 |
use WpAssetCleanUp\OptimiseAssets\OptimizeJs;
|
6 |
|
54 |
'combine_loaded_css_for_admin_only', // Since v1.1.1.4 (Pro) & v1.3.1.1 (Lite)
|
55 |
|
56 |
// [wpacu_pro]
|
|
|
57 |
'defer_css_loaded_body',
|
58 |
// [/wpacu_pro]
|
59 |
|
83 |
'combine_loaded_js_for_admin_only',
|
84 |
'combine_loaded_js_defer_body', // Applies defer="defer" to the combined file(s) within BODY tag
|
85 |
|
|
|
|
|
|
|
|
|
86 |
// Minify each loaded CSS (remaining ones after unloading the useless ones)
|
87 |
'minify_loaded_css',
|
88 |
'minify_loaded_css_inline',
|
227 |
// [/wpacu_pro]
|
228 |
|
229 |
'combine_loaded_css_exceptions' => '/plugins/wd-instagram-feed/(.*?).css',
|
230 |
+
'combine_loaded_js_exceptions' => '/plugins/wd-instagram-feed/(.*?).js',
|
|
|
|
|
|
|
|
|
|
|
231 |
|
232 |
// [wpacu_pro]
|
233 |
'defer_css_loaded_body' => 'moved',
|
243 |
|
244 |
'fetch_cached_files_details_from' => 'disk', // Do not add more rows to the database by default (options table can become quite large)
|
245 |
|
246 |
+
'clear_cached_files_after' => '7'
|
247 |
);
|
248 |
}
|
249 |
|
classes/Update.php
CHANGED
@@ -66,6 +66,9 @@ HTML;
|
|
66 |
|
67 |
// Clear cache (via AJAX) only if the user is logged-in (with the right privileges)
|
68 |
add_action('wp_ajax_' . WPACU_PLUGIN_ID . '_clear_cache', array($this, 'ajaxClearCache'), PHP_INT_MAX);
|
|
|
|
|
|
|
69 |
}
|
70 |
|
71 |
/**
|
@@ -136,6 +139,12 @@ HTML;
|
|
136 |
|
137 |
// Form submitted from a Singular Page
|
138 |
// e.g. post, page, custom post type such as 'product' page from WooCommerce, home page (static page selected as front page)
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
if ($postId > 0) {
|
140 |
$post = get_post($postId);
|
141 |
$this->savePost($post->ID, $post);
|
@@ -976,7 +985,43 @@ HTML;
|
|
976 |
foreach ($assetDataHandleList as $assetObj) {
|
977 |
$assetArray = (array)$assetObj;
|
978 |
$assetHandle = $assetArray['handle'];
|
979 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
980 |
$existingList[$assetKey][$globalKey][$assetHandle] = $assetArray;
|
981 |
}
|
982 |
}
|
@@ -1003,8 +1048,35 @@ HTML;
|
|
1003 |
exit();
|
1004 |
}
|
1005 |
|
1006 |
-
OptimizeCommon::
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1007 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1008 |
exit();
|
1009 |
-
|
1010 |
}
|
66 |
|
67 |
// Clear cache (via AJAX) only if the user is logged-in (with the right privileges)
|
68 |
add_action('wp_ajax_' . WPACU_PLUGIN_ID . '_clear_cache', array($this, 'ajaxClearCache'), PHP_INT_MAX);
|
69 |
+
|
70 |
+
// After an update, preload the page for the guest view (the preload for the admin is done within script.min.js own plugin file)
|
71 |
+
add_action('wp_ajax_' . WPACU_PLUGIN_ID . '_preload', array($this, 'ajaxPreloadGuest'), PHP_INT_MAX);
|
72 |
}
|
73 |
|
74 |
/**
|
139 |
|
140 |
// Form submitted from a Singular Page
|
141 |
// e.g. post, page, custom post type such as 'product' page from WooCommerce, home page (static page selected as front page)
|
142 |
+
|
143 |
+
// Sometimes, there's a singular page set as 404 page (e.g. via "404page – your smart custom 404 error page" plugin)
|
144 |
+
if (is_404() && Misc::getVar('post', 'wpacu_is_singular_page')) {
|
145 |
+
$postId = (int)$_POST['wpacu_is_singular_page'];
|
146 |
+
}
|
147 |
+
|
148 |
if ($postId > 0) {
|
149 |
$post = get_post($postId);
|
150 |
$this->savePost($post->ID, $post);
|
985 |
foreach ($assetDataHandleList as $assetObj) {
|
986 |
$assetArray = (array)$assetObj;
|
987 |
$assetHandle = $assetArray['handle'];
|
988 |
+
|
989 |
+
// Strip other unused information including the 'handle' (no need to have it twice as it's already in one of the array's keys)
|
990 |
+
unset( $assetArray['handle'], $assetArray['textdomain'], $assetArray['translations_path'] );
|
991 |
+
|
992 |
+
// Some handles don't have an "src" value such as "woocommerce-inline"
|
993 |
+
if (isset($assetArray['src']) && $assetArray['src']) {
|
994 |
+
$assetArray['src'] = Misc::assetFromHrefToRelativeUri( $assetArray['src'], $assetKey );
|
995 |
+
}
|
996 |
+
|
997 |
+
// [wpacu_pro]
|
998 |
+
if (isset($assetArray['output'])) { // hardcoded assets have an 'output' value
|
999 |
+
// Is there already an entry for the same handle with a value set for 'output' and 'output_min'
|
1000 |
+
if (isset($existingList[$assetKey][$globalKey][$assetHandle]['output'], $existingList[$assetKey][$globalKey][$assetHandle]['output_min'])) {
|
1001 |
+
// Save resources: do not update the same values and skip the minification (good to avoid large inline content)
|
1002 |
+
continue;
|
1003 |
+
}
|
1004 |
+
|
1005 |
+
if ( ! isset( $assetArray['output_min'] ) ) {
|
1006 |
+
$assetArray['output_min'] = '';
|
1007 |
+
|
1008 |
+
// Reference: $wpacuHardcodedInfoToStoreAfterSubmit from _assets-hardcoded-list.php
|
1009 |
+
if ( strpos( $assetHandle, 'wpacu_hardcoded_script_' ) === 0 ) {
|
1010 |
+
$outputMin = \WpAssetCleanUp\OptimiseAssets\MinifyJs::applyMinification( $assetArray['output'] );
|
1011 |
+
if ( $assetArray['output'] !== $outputMin ) {
|
1012 |
+
$assetArray['output_min'] = $outputMin;
|
1013 |
+
}
|
1014 |
+
} elseif ( ( strpos( $assetHandle, 'wpacu_hardcoded_link_' ) === 0 ) || ( strpos( $assetHandle,
|
1015 |
+
'wpacu_hardcoded_style_' ) === 0 ) ) {
|
1016 |
+
$outputMin = \WpAssetCleanUp\OptimiseAssets\MinifyCss::applyMinification( $assetArray['output'] );
|
1017 |
+
if ( $assetArray['output'] !== $outputMin ) {
|
1018 |
+
$assetArray['output_min'] = $outputMin;
|
1019 |
+
}
|
1020 |
+
}
|
1021 |
+
}
|
1022 |
+
}
|
1023 |
+
// [/wpacu_pro]
|
1024 |
+
|
1025 |
$existingList[$assetKey][$globalKey][$assetHandle] = $assetArray;
|
1026 |
}
|
1027 |
}
|
1048 |
exit();
|
1049 |
}
|
1050 |
|
1051 |
+
OptimizeCommon::clearCache();
|
1052 |
+
exit();
|
1053 |
+
}
|
1054 |
+
|
1055 |
+
/**
|
1056 |
+
* This is triggered when /admin/admin-ajax.php is called (default WordPress AJAX handler)
|
1057 |
+
*/
|
1058 |
+
public function ajaxPreloadGuest()
|
1059 |
+
{
|
1060 |
+
if (! Menu::userCanManageAssets()) {
|
1061 |
+
echo 'Error: Not enough privileges to perform this action.';
|
1062 |
+
exit();
|
1063 |
+
}
|
1064 |
+
|
1065 |
+
$pageUrl = isset($_POST['page_url']) ? $_POST['page_url'] : false;
|
1066 |
+
|
1067 |
+
$pageUrlPreload = add_query_arg( array(
|
1068 |
+
'wpacu_preload' => 1
|
1069 |
+
), $pageUrl );
|
1070 |
|
1071 |
+
if (! filter_var($pageUrlPreload, FILTER_VALIDATE_URL)) {
|
1072 |
+
echo 'The URL `'.$pageUrlPreload.'` is not valid.';
|
1073 |
+
exit();
|
1074 |
+
}
|
1075 |
+
|
1076 |
+
$response = wp_remote_get($pageUrlPreload);
|
1077 |
+
|
1078 |
+
echo 'Page URL (preload): '.$pageUrlPreload."\n\n";
|
1079 |
+
echo $response['body'];
|
1080 |
exit();
|
1081 |
+
}
|
1082 |
}
|
early-triggers.php
CHANGED
@@ -5,7 +5,17 @@ if (! defined('ABSPATH')) {
|
|
5 |
}
|
6 |
|
7 |
if (array_key_exists('wpacu_clean_load', $_GET)) {
|
8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
}
|
10 |
|
11 |
if (! function_exists('assetCleanUpHasNoLoadMatches')) {
|
@@ -198,6 +208,21 @@ if (! function_exists('assetCleanUpNoLoad')) {
|
|
198 |
return true;
|
199 |
}
|
200 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
// Perfmatters: Script Manager
|
202 |
if (isset($_GET['perfmatters'])) {
|
203 |
return true;
|
@@ -256,22 +281,22 @@ if (! function_exists('assetCleanUpNoLoad')) {
|
|
256 |
}
|
257 |
|
258 |
// Stop triggering Asset CleanUp (completely) on specific front-end pages
|
259 |
-
// Do the trigger here
|
260 |
if (assetCleanUpHasNoLoadMatches()) {
|
261 |
// Only use exit() when "wpassetcleanup_load" is used
|
262 |
if (isset($_REQUEST['wpassetcleanup_load']) && $_REQUEST['wpassetcleanup_load']) {
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
}
|
275 |
}
|
276 |
|
277 |
return true;
|
@@ -285,3 +310,27 @@ if (! function_exists('assetCleanUpNoLoad')) {
|
|
285 |
if (! defined('JSON_ERROR_NONE')) {
|
286 |
define('JSON_ERROR_NONE', 0);
|
287 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
}
|
6 |
|
7 |
if (array_key_exists('wpacu_clean_load', $_GET)) {
|
8 |
+
// Autoptimize
|
9 |
+
$_GET['ao_noptimize'] = $_REQUEST['ao_noptimize'] = '1';
|
10 |
+
|
11 |
+
// LiteSpeed Cache
|
12 |
+
if ( ! defined( 'LITESPEED_DISABLE_ALL' ) ) {
|
13 |
+
define('LITESPEED_DISABLE_ALL', true);
|
14 |
+
}
|
15 |
+
|
16 |
+
add_action( 'litespeed_disable_all', static function($reason) {
|
17 |
+
do_action( 'litespeed_debug', '[API] Disabled_all due to: A clean load of the page was requested via '. WPACU_PLUGIN_TITLE );
|
18 |
+
} );
|
19 |
}
|
20 |
|
21 |
if (! function_exists('assetCleanUpHasNoLoadMatches')) {
|
208 |
return true;
|
209 |
}
|
210 |
|
211 |
+
// "Pro" (theme.co) (iFrame)
|
212 |
+
if (isset($_POST['_cs_nonce'], $_POST['cs_preview_state']) && $_POST['_cs_nonce'] && $_POST['cs_preview_state']) {
|
213 |
+
return true;
|
214 |
+
}
|
215 |
+
|
216 |
+
// "Page Builder: Live Composer" plugin
|
217 |
+
if (defined('DS_LIVE_COMPOSER_ACTIVE') && DS_LIVE_COMPOSER_ACTIVE) {
|
218 |
+
return true;
|
219 |
+
}
|
220 |
+
|
221 |
+
// "WP Page Builder" plugin (By Themeum.com)
|
222 |
+
if (isset($_GET['load_for']) && $_GET['load_for'] === 'wppb_editor_iframe') {
|
223 |
+
return true;
|
224 |
+
}
|
225 |
+
|
226 |
// Perfmatters: Script Manager
|
227 |
if (isset($_GET['perfmatters'])) {
|
228 |
return true;
|
281 |
}
|
282 |
|
283 |
// Stop triggering Asset CleanUp (completely) on specific front-end pages
|
284 |
+
// Do the trigger here and if necessary exit as early as possible to save resources via "registered_taxonomy" action hook)
|
285 |
if (assetCleanUpHasNoLoadMatches()) {
|
286 |
// Only use exit() when "wpassetcleanup_load" is used
|
287 |
if (isset($_REQUEST['wpassetcleanup_load']) && $_REQUEST['wpassetcleanup_load']) {
|
288 |
+
add_action('registered_taxonomy', function() {
|
289 |
+
if ( current_user_can( 'manage_options' ) ) {
|
290 |
+
$msg = sprintf(
|
291 |
+
__(
|
292 |
+
'This page\'s URL is matched by one of the RegEx rules you have in <em>"Settings"</em> -> <em>"Plugin Usage Preferences"</em> -> <em>"Do not load the plugin on certain pages"</em>, thus %s is not loaded on that page and no CSS/JS are to be managed. If you wish to view the CSS/JS manager, please remove the matching RegEx rule and the list of CSS/JS will be fetched.',
|
293 |
+
'wp-asset-clean-up'
|
294 |
+
),
|
295 |
+
WPACU_PLUGIN_TITLE
|
296 |
+
);
|
297 |
+
exit( $msg );
|
298 |
+
}
|
299 |
+
});
|
300 |
}
|
301 |
|
302 |
return true;
|
310 |
if (! defined('JSON_ERROR_NONE')) {
|
311 |
define('JSON_ERROR_NONE', 0);
|
312 |
}
|
313 |
+
|
314 |
+
// Make sure the plugin doesn't load when the editor of either "X" theme or "Pro" website creator (theme.co) is ON
|
315 |
+
add_action('init', static function() {
|
316 |
+
if (is_admin()) {
|
317 |
+
return; // Not relevant for the Dashboard view, stop here!
|
318 |
+
}
|
319 |
+
|
320 |
+
if (class_exists('\WpAssetCleanUp\Menu') && \WpAssetCleanUp\Menu::userCanManageAssets() && method_exists('Cornerstone_Common', 'get_app_slug') && in_array(get_stylesheet(), array('x', 'pro'))) {
|
321 |
+
$customAppSlug = get_stylesheet(); // default one ('x' or 'pro')
|
322 |
+
|
323 |
+
// Is there any custom slug set in "/wp-admin/admin.php?page=cornerstone-settings"?
|
324 |
+
// "Settings" -> "Custom Path" (check it out below)
|
325 |
+
$cornerStoneSettings = get_option('cornerstone_settings');
|
326 |
+
if (isset($cornerStoneSettings['custom_app_slug']) && $cornerStoneSettings['custom_app_slug'] !== '') {
|
327 |
+
$customAppSlug = $cornerStoneSettings['custom_app_slug'];
|
328 |
+
}
|
329 |
+
|
330 |
+
$lengthToUse = strlen($customAppSlug) + 2; // add the slashes to the count
|
331 |
+
|
332 |
+
if (substr($_SERVER['REQUEST_URI'], -$lengthToUse) === '/'.$customAppSlug.'/') {
|
333 |
+
add_filter( 'wpacu_prevent_any_changes', '__return_true' );
|
334 |
+
}
|
335 |
+
}
|
336 |
+
});
|
readme.txt
CHANGED
@@ -3,8 +3,8 @@ Contributors: gabelivan
|
|
3 |
Tags: minify css, minify javascript, defer css javascript, page speed, dequeue, performance
|
4 |
Donate link: https://www.gabelivan.com/items/wp-asset-cleanup-pro/?utm_source=wp_org_lite&utm_medium=donate
|
5 |
Requires at least: 4.5
|
6 |
-
Tested up to: 5.4
|
7 |
-
Stable tag: 1.3.6.
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl.html
|
10 |
|
@@ -179,6 +179,30 @@ With the recently released "Test Mode" feature, you can safely unload assets on
|
|
179 |
4. Homepage CSS & JS Management (List sorted by location)
|
180 |
|
181 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
= 1.3.6.1 =
|
183 |
* Increased the speed of unloading (dequeueing) styles & scripts by ~40ms (caching is used to avoid calling the same PHP code during several action hooks)
|
184 |
* Higher accuracy in stripping 'before' and 'after' associated inline SCRIPT after adding the content to the JS combined file
|
@@ -196,6 +220,7 @@ With the recently released "Test Mode" feature, you can safely unload assets on
|
|
196 |
* Trigger certain actions (to save database & disk space) when the plugin is deactivated: Clear all its transients from the database & Remove the caching directory if it doesn't have any more CSS/JS; If all the plugin's changes were cleared via "Tools" -> "Reset", then deactivating the plugin will completely clear any of its traces
|
197 |
* The plugin's own files that are needed for the plugin's functionality (they are only loading for the logged-in admin), are loaded asynchronously (CSS) and deferred (JS) to ensure the admin doesn't load them as render-blocking especially when managing the pages in the front-end view
|
198 |
* The combined CSS tags can now be altered for any reason via add_filter() through the 'wpacu_combined_css_tag' tag name, just like the combined JS tags are via 'wpacu_combined_js_tag'
|
|
|
199 |
* Fix: Remove request to non-existent CSS file within the Dashboard that generated a 404 Not Found error in the browser's console (harmless, but confusing)
|
200 |
|
201 |
= 1.3.6.0 =
|
3 |
Tags: minify css, minify javascript, defer css javascript, page speed, dequeue, performance
|
4 |
Donate link: https://www.gabelivan.com/items/wp-asset-cleanup-pro/?utm_source=wp_org_lite&utm_medium=donate
|
5 |
Requires at least: 4.5
|
6 |
+
Tested up to: 5.4.1
|
7 |
+
Stable tag: 1.3.6.2
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl.html
|
10 |
|
179 |
4. Homepage CSS & JS Management (List sorted by location)
|
180 |
|
181 |
== Changelog ==
|
182 |
+
= 1.3.6.2 =
|
183 |
+
* Once a page is updated, the plugin preloads that page for both the admin and the guest visitor, making sure any new changes would take effect, saving the admin's time and making sure any first visitor coming to that page will access it faster (not having to wait for the caching to re-built)
|
184 |
+
* If the attribute "data-wpacu-skip" is applied to any CSS/JS, then no alteration (e.g. no minify and no addition to any combine list) will be applied to that file (apart from the actual unload or attributes such as async/defer)
|
185 |
+
* 'Remove All "generator" meta tags?' improvement: Higher accuracy in stripping META tag generators if the option is enabled in case some of their attributes have no quotes around them (rare cases)
|
186 |
+
* If 'Remove "REST API" link tag?' is enabled, the /wp-json/ reference is also removed from the "Response headers" when accessing the page via remove_action()
|
187 |
+
* Compatibility with extra page builders: "X" & "PRO" themes (Theme.co), "WP Page Builder" & "Page Builder: Live Composer" plugins: whenever their editor is ON, no unloads or any other changes to the HTML source (including minification) are performed to make sure the editor is loading its files and works smoothly
|
188 |
+
* Compatibility with "Redis Object Cache" plugin: The global variable $wp_object_cache from the WordPress core is no longer used and it's replaced with a custom solution
|
189 |
+
* Compatibility with "404page – your smart custom 404 error page" plugin and similar plugins that are making pages as 404 customizable ones
|
190 |
+
* For debugging purposes, the admin can use /?wpacu_no_cache to view how the website would load without the CSS/JS cache applied (the files will still be referenced from the caching directory but they will be dynamically generated instead)
|
191 |
+
* Sometimes, large inline STYLE/SCRIPT tags' content has to be minified; if it's between 40KB and 500 KB it will be cached; any tags' content over 500KB will not be minified as it would use too many resources; it's advisable to put very large tag content into a .js external file as it would affect the TTFB (time to the first byte) when the page is loaded
|
192 |
+
* Any inline CSS/JS associated with a handle (generated via wp_add_inline_style() and wp_add_inline_script() respectively) are automatically added to the combined file
|
193 |
+
* Combined CSS/JS files are all stored in /wp-content/cache/asset-cleanup/("css" or "js")/ to avoid duplicated files that used to be stored in "logged-in" directory which is no longer created; This reduces the total disk space especially when the same CSS/JS is created (sometimes these files are quite large) for both guests & logged-in users
|
194 |
+
* If "Combine loaded CSS (Stylesheets) into fewer files" is enabled, the LINK tags that are preloaded (at least two of them) will also be combined, thus reducing the number of HTTP requests
|
195 |
+
* The method loadHTML() from DOMDocument is processing tags faster as the initial HTML source passed to it as a parameter goes through several filters, making it much smaller which makes a different in page speed when it comes to large HTML sources
|
196 |
+
* Prevent certain DOMDocument calls (which can be slow on large HTML documents) when they are not necessary (e.g. when preloading CSS stylesheets and the RegEx which is faster can do the same task with the same accuracy)
|
197 |
+
* Strip LINK tags that are pointing to empty content (including any inline code associated with the enqueued style added via wp_add_inline_style() function) if "CSS Files Minification" is enabled, making sure any empty tags are also stripped when "Inline CSS Files" is enabled, this saving HTTP requests and having less DOM elements
|
198 |
+
* In some cases, the PHP function strtr() has proven to be faster than str_replace() to make replacements, thus it has been applied to some methods that are dealing with the alteration of the HTML source
|
199 |
+
* Notify the admin that unloading 'jquery-migrate' won't unload it's "child" as well, 'jquery' (as it's a special case)
|
200 |
+
* Fix: In rare cases, URLs to the assets are starting with ../ (it's not the best practice as this would only work depending on the page's URL structure); Make sure the file's size is calculated correctly and the right URL for the file is checked in the background to determine if it returns a 200 OK response or not
|
201 |
+
* Fix: Store the assets info (which are shown only within the Dashboard for reference purposes) with the relative location (UR) to the asset, in case the data is later imported from a Staging to Live environment, it won't show any Staging URLs on the Live website on pages such as "Overview", thus avoiding any confusion the admin might have
|
202 |
+
* Fix: Make sure the time dequeueing CSS/JS is calculated correctly
|
203 |
+
* Fix: If "Asynchronous via Web Font Loader (webfont.js)" was chosen for "Combine Multiple Requests Into Fewer Ones", the font weights weren't added to the final generated SCRIPT tag
|
204 |
+
* Fix: Make sure when the handle information is saved, there are no PHP notice errors if the 'src' index is missing as some handles do not have an "src"
|
205 |
+
|
206 |
= 1.3.6.1 =
|
207 |
* Increased the speed of unloading (dequeueing) styles & scripts by ~40ms (caching is used to avoid calling the same PHP code during several action hooks)
|
208 |
* Higher accuracy in stripping 'before' and 'after' associated inline SCRIPT after adding the content to the JS combined file
|
220 |
* Trigger certain actions (to save database & disk space) when the plugin is deactivated: Clear all its transients from the database & Remove the caching directory if it doesn't have any more CSS/JS; If all the plugin's changes were cleared via "Tools" -> "Reset", then deactivating the plugin will completely clear any of its traces
|
221 |
* The plugin's own files that are needed for the plugin's functionality (they are only loading for the logged-in admin), are loaded asynchronously (CSS) and deferred (JS) to ensure the admin doesn't load them as render-blocking especially when managing the pages in the front-end view
|
222 |
* The combined CSS tags can now be altered for any reason via add_filter() through the 'wpacu_combined_css_tag' tag name, just like the combined JS tags are via 'wpacu_combined_js_tag'
|
223 |
+
* While the CSS/JS assets are fetched prevent extra performance plugins from triggering their optimisation for CSS/JS/HTML as the action is irrelevant and uses resources during the fetching of the assets for the admin
|
224 |
* Fix: Remove request to non-existent CSS file within the Dashboard that generated a 404 Not Found error in the browser's console (harmless, but confusing)
|
225 |
|
226 |
= 1.3.6.0 =
|
templates/_admin-page-settings-plugin-areas/_optimize-css.php
CHANGED
@@ -160,16 +160,9 @@ $availableForPro = '<a class="go-pro-link-no-style" target="_blank" href="' . WP
|
|
160 |
</label>
|
161 |
</p>
|
162 |
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
<input id="combine_loaded_css_append_handle_extra_checkbox"
|
167 |
-
disabled="disabled"
|
168 |
-
type="checkbox" />
|
169 |
-
<label for="combine_loaded_css_append_handle_extra_checkbox">Add inline tag contents associated with a style (handle) to the combined group of files before/after the main script's contents</label>
|
170 |
-
<p style="margin-top: 10px;"><small>When a file is added to a combined group of files, any other inline content (e.g. added via <code style="font-size: inherit;">wp_add_inline_style()</code>) associated with it, will also be added to the combined files. This reduces the number of DOM elements as well makes sure the CSS code will load in the right (set) order.</small></p>
|
171 |
-
</div>
|
172 |
-
<!-- [/wpacu_lite] -->
|
173 |
|
174 |
<div id="wpacu_combine_loaded_css_exceptions_area">
|
175 |
<div style="margin: 8px 0 6px;"><?php _e('Do not combine the CSS files matching the patterns below', 'wp-asset-clean-up'); ?> (<?php _e('one per line', 'wp-asset-clean-up'); ?>):</div>
|
@@ -185,10 +178,7 @@ $availableForPro = '<a class="go-pro-link-no-style" target="_blank" href="' . WP
|
|
185 |
</div>
|
186 |
|
187 |
<p>This scans the remaining CSS files (left after cleaning up the unnecessary ones) from the <code><head></code> and <code><body></code> locations and combines them into ~2 files (one in each location). To be 100% sure everything works fine after activation, consider enabling this feature only for logged-in administrator, so only you can see the updated page. If all looks good, you can later uncheck the option to apply the feature to everyone else.</p>
|
188 |
-
|
189 |
-
<ul style="list-style: disc; margin-top: 0; margin-left: 35px; margin-bottom: 0;">
|
190 |
-
<li style="margin-bottom: 0;">Have any <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content">preloading added to them</a> via <code>rel="preload"</code> will not be combined as they have priority in loading and shouldn't be mixed with the rest of the CSS.</li>
|
191 |
-
</ul>
|
192 |
<hr />
|
193 |
<p style="margin: 8px 0 4px;"><span style="color: #ffc107;" class="dashicons dashicons-lightbulb"></span> This feature will not work <strong>IF</strong>:</p>
|
194 |
<ul style="margin-top: 0; margin-left: 35px; list-style: disc;">
|
160 |
</label>
|
161 |
</p>
|
162 |
|
163 |
+
<p style="margin-top: 10px;"><strong>Note:</strong> When a stylesheet is added to a combined group of files, any other inline content (e.g. added via <code style="font-size: inherit;">wp_add_inline_style()</code>) associated with it, will also be added to the combined files. This reduces the number of DOM elements as well makes sure the CSS code will load in the right (set) order.</p>
|
164 |
+
|
165 |
+
<hr />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
|
167 |
<div id="wpacu_combine_loaded_css_exceptions_area">
|
168 |
<div style="margin: 8px 0 6px;"><?php _e('Do not combine the CSS files matching the patterns below', 'wp-asset-clean-up'); ?> (<?php _e('one per line', 'wp-asset-clean-up'); ?>):</div>
|
178 |
</div>
|
179 |
|
180 |
<p>This scans the remaining CSS files (left after cleaning up the unnecessary ones) from the <code><head></code> and <code><body></code> locations and combines them into ~2 files (one in each location). To be 100% sure everything works fine after activation, consider enabling this feature only for logged-in administrator, so only you can see the updated page. If all looks good, you can later uncheck the option to apply the feature to everyone else.</p>
|
181 |
+
|
|
|
|
|
|
|
182 |
<hr />
|
183 |
<p style="margin: 8px 0 4px;"><span style="color: #ffc107;" class="dashicons dashicons-lightbulb"></span> This feature will not work <strong>IF</strong>:</p>
|
184 |
<ul style="margin-top: 0; margin-left: 35px; list-style: disc;">
|
templates/_admin-page-settings-plugin-areas/_optimize-js.php
CHANGED
@@ -153,16 +153,7 @@ $availableForProMoveScriptsToBody = '<a class="go-pro-link-no-style" target="_bl
|
|
153 |
</label>
|
154 |
</p>
|
155 |
|
156 |
-
|
157 |
-
<?php echo $availableForProAppendInlineJs; ?>
|
158 |
-
<input style="opacity: 0.4;" id="combine_loaded_js_append_handle_extra_checkbox"
|
159 |
-
<?php echo (($data['combine_loaded_js_append_handle_extra'] == 1) ? 'checked="checked"' : ''); ?>
|
160 |
-
type="checkbox"
|
161 |
-
name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[combine_loaded_js_append_handle_extra]"
|
162 |
-
value="1" />
|
163 |
-
<label for="combine_loaded_js_append_handle_extra_checkbox">Add inline tag contents associated with a script (handle) to the combined group of files before/after the main script's contents</label>
|
164 |
-
<p style="margin-top: 10px;"><small>When a file is added to a combined group of files, the CDATA as well as any other inline content (e.g. added via <code style="font-size: inherit;">wp_add_inline_script()</code>) associated with it will also be added to the combined files. This reduces the number of DOM elements as well makes sure that, in case, the combined file is deferred, the code from the inline tags is triggered at the same time as the one from the file</small></p>
|
165 |
-
</div>
|
166 |
|
167 |
<p style="padding: 10px; background: #f2faf2;">
|
168 |
<label for="wpacu_combine_loaded_js_defer_body_checkbox">
|
@@ -261,7 +252,7 @@ $availableForProMoveScriptsToBody = '<a class="go-pro-link-no-style" target="_bl
|
|
261 |
}
|
262 |
?>
|
263 |
|
264 |
-
<div id="wpacu_inline_js_files_info_area" style="opacity: 0.4;"
|
265 |
<p class="wpacu-warning" style="margin: 10px 0; font-size: 13px; padding: 4px 9px;">
|
266 |
<small><strong style="color: orange;"><span class="dashicons dashicons-warning"></span></strong> Please be extra careful if you decide to use this feature as inlining JavaScript files can be trickier than inlining CSS ones due to the more complex syntax and various attributes that might set to the external JS file such as "async" and "defer" (files having this attribute will be called via <em>DOMContentLoaded</em> event).</small>
|
267 |
</p>
|
@@ -324,6 +315,7 @@ $availableForProMoveScriptsToBody = '<a class="go-pro-link-no-style" target="_bl
|
|
324 |
</td>
|
325 |
</tr>
|
326 |
|
|
|
327 |
<tr valign="top">
|
328 |
<th scope="row" class="setting_title">
|
329 |
<label for="wpacu_move_scripts_to_body_enable"><?php _e('Move All <code><SCRIPT></code> tags From HEAD to BODY', 'wp-asset-clean-up'); ?> <?php echo $availableForProMoveScriptsToBody; ?></label>
|
@@ -361,6 +353,7 @@ $availableForProMoveScriptsToBody = '<a class="go-pro-link-no-style" target="_bl
|
|
361 |
</div>
|
362 |
</td>
|
363 |
</tr>
|
|
|
364 |
|
365 |
<tr valign="top">
|
366 |
<th scope="row" class="setting_title">
|
@@ -450,8 +443,8 @@ $availableForProMoveScriptsToBody = '<a class="go-pro-link-no-style" target="_bl
|
|
450 |
<code><script type="text/javascript" src="/wp-includes/js/jquery.js"></script></code><br />
|
451 |
<code><script type="text/javascript" src="/wp-includes/js/jquery-migrate.min.js"></script></code><br />
|
452 |
<code><script type="text/javascript">jQuery(document).ready(function($) { /* code here */ });</script></code><br />
|
453 |
-
<code><script type="text/javascript">$(document).ready(function() { /* another code here */ });</script></code>
|
454 |
-
|
455 |
</div>
|
456 |
</div>
|
457 |
|
@@ -461,7 +454,7 @@ $availableForProMoveScriptsToBody = '<a class="go-pro-link-no-style" target="_bl
|
|
461 |
<h2 style="margin-top: 5px;"><?php _e('Examples of SCRIPTS moved from HEAD to BODY', 'wp-asset-clean-up'); ?></h2>
|
462 |
|
463 |
<span><strong>FROM</strong></span>
|
464 |
-
<pre style="margin-top: 4px; margin-bottom: 8px;">
|
465 |
<code><head></code>
|
466 |
<code><title>Your page title here</title></code>
|
467 |
<code>...</code>
|
@@ -477,7 +470,7 @@ $availableForProMoveScriptsToBody = '<a class="go-pro-link-no-style" target="_bl
|
|
477 |
<div style="margin-top: -6px; margin-bottom: 14px;"><hr /></div>
|
478 |
|
479 |
<span><strong>TO</strong></span>
|
480 |
-
<pre style="margin-top: 4px; margin-bottom: 0;">
|
481 |
<code><head></code>
|
482 |
<code><title>Your page title here</title></code>
|
483 |
<code>...</code>
|
153 |
</label>
|
154 |
</p>
|
155 |
|
156 |
+
<p style="margin-top: 10px;"><strong>Note:</strong> When a file is added to a combined group of files, the CDATA as well as any other inline content (e.g. added via <code style="font-size: inherit;">wp_add_inline_script()</code>) associated with it will also be added to the combined files. This reduces the number of DOM elements as well makes sure that, in case, the combined file is deferred, the code from the inline tags is triggered at the same time as the one from the file</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
|
158 |
<p style="padding: 10px; background: #f2faf2;">
|
159 |
<label for="wpacu_combine_loaded_js_defer_body_checkbox">
|
252 |
}
|
253 |
?>
|
254 |
|
255 |
+
<div id="wpacu_inline_js_files_info_area" <?php if (empty($data['is_optimize_css_enabled_by_other_party']) && $data['inline_js_files'] == 1) { ?> style="opacity: 1;" <?php } else { ?>style="opacity: 0.4;"<?php } ?>>
|
256 |
<p class="wpacu-warning" style="margin: 10px 0; font-size: 13px; padding: 4px 9px;">
|
257 |
<small><strong style="color: orange;"><span class="dashicons dashicons-warning"></span></strong> Please be extra careful if you decide to use this feature as inlining JavaScript files can be trickier than inlining CSS ones due to the more complex syntax and various attributes that might set to the external JS file such as "async" and "defer" (files having this attribute will be called via <em>DOMContentLoaded</em> event).</small>
|
258 |
</p>
|
315 |
</td>
|
316 |
</tr>
|
317 |
|
318 |
+
<!-- [wpacu_pro] -->
|
319 |
<tr valign="top">
|
320 |
<th scope="row" class="setting_title">
|
321 |
<label for="wpacu_move_scripts_to_body_enable"><?php _e('Move All <code><SCRIPT></code> tags From HEAD to BODY', 'wp-asset-clean-up'); ?> <?php echo $availableForProMoveScriptsToBody; ?></label>
|
353 |
</div>
|
354 |
</td>
|
355 |
</tr>
|
356 |
+
<!-- [/wpacu_pro] -->
|
357 |
|
358 |
<tr valign="top">
|
359 |
<th scope="row" class="setting_title">
|
443 |
<code><script type="text/javascript" src="/wp-includes/js/jquery.js"></script></code><br />
|
444 |
<code><script type="text/javascript" src="/wp-includes/js/jquery-migrate.min.js"></script></code><br />
|
445 |
<code><script type="text/javascript">jQuery(document).ready(function($) { /* code here */ });</script></code><br />
|
446 |
+
<code><script type="text/javascript">$(document).ready(function() { /* another code here */ });</script></code>
|
447 |
+
</p>
|
448 |
</div>
|
449 |
</div>
|
450 |
|
454 |
<h2 style="margin-top: 5px;"><?php _e('Examples of SCRIPTS moved from HEAD to BODY', 'wp-asset-clean-up'); ?></h2>
|
455 |
|
456 |
<span><strong>FROM</strong></span>
|
457 |
+
<pre style="margin-top: 4px; margin-bottom: 8px; white-space: pre;">
|
458 |
<code><head></code>
|
459 |
<code><title>Your page title here</title></code>
|
460 |
<code>...</code>
|
470 |
<div style="margin-top: -6px; margin-bottom: 14px;"><hr /></div>
|
471 |
|
472 |
<span><strong>TO</strong></span>
|
473 |
+
<pre style="margin-top: 4px; margin-bottom: 0; white-space: pre;">
|
474 |
<code><head></code>
|
475 |
<code><title>Your page title here</title></code>
|
476 |
<code>...</code>
|
templates/_admin-page-settings-plugin-areas/_plugin-usage-settings.php
CHANGED
@@ -455,19 +455,4 @@ foreach (\WpAssetCleanUp\MetaBoxes::$noMetaBoxesForPostTypes as $noMetaBoxesForP
|
|
455 |
</div>
|
456 |
</div>
|
457 |
|
458 |
-
<!--
|
459 |
-
<!-- [wpacu_lite] -->
|
460 |
-
<!--
|
461 |
-
<div id="wpacu-deactivate-modal-info" class="wpacu-modal" style="padding-top: 60px;">
|
462 |
-
<div class="wpacu-modal-content" style="max-width: 650px;">
|
463 |
-
<span class="wpacu-close">×</span>
|
464 |
-
<h2 style="margin-top: 5px;"><?php _e('Asset CleanUp: Deactivation Modal', 'wp-asset-clean-up'); ?></h2>
|
465 |
-
<p>When you use the "Deactivate" link for "Asset CleanUp: Page Speed Booster" plugin from "Plugins" -> "Installed Plugins", a popup like the one in the below example shows up allowing you the option to <em>Skip & Deactivate</em> or select an uninstall reason, sending your feedback and deactivate it. Collecting feedback is very useful to understand why you decided to deactivate the plugin so we can further improve it based on the overall feedback.</p>
|
466 |
-
<p>However, there are times when you might do debugging on your website and you have to often deactivate the plugin. You can disable the feedback modal and you will not be asked for any uninstall reason anytime you use the "Deactivate" link.</p>
|
467 |
-
<hr />
|
468 |
-
<img style="margin: 0 auto; width: 100%; max-width: 500px; display: table;" src="<?php echo WPACU_PLUGIN_URL. '/assets/images/wpacu-deactivate-modal.jpg'; ?>" alt="" />
|
469 |
-
</div>
|
470 |
-
</div>
|
471 |
-
-->
|
472 |
-
<!-- [/wpacu_lite] -->
|
473 |
-
<!-- endRemoveIf(development) -->
|
455 |
</div>
|
456 |
</div>
|
457 |
|
458 |
+
<!-- -->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/meta-box-loaded-assets/_asset-script-single-row/_handle.php
CHANGED
@@ -31,21 +31,39 @@ if ( ! isset($data, $isCoreFile, $hideCoreFiles, $jqueryIconHtmlHandle, $childHa
|
|
31 |
if (! empty($childHandles)) {
|
32 |
$ignoreChild = (isset($data['ignore_child']['scripts'][$data['row']['obj']->handle]) && $data['ignore_child']['scripts'][$data['row']['obj']->handle]);
|
33 |
?>
|
34 |
-
<
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
31 |
if (! empty($childHandles)) {
|
32 |
$ignoreChild = (isset($data['ignore_child']['scripts'][$data['row']['obj']->handle]) && $data['ignore_child']['scripts'][$data['row']['obj']->handle]);
|
33 |
?>
|
34 |
+
<div class="wpacu_dependency_notice_area">
|
35 |
+
<?php
|
36 |
+
if ($data['row']['obj']->handle === 'jquery-migrate') {
|
37 |
+
?>
|
38 |
+
<em style="font-size: 85%;">Special Case: If jQuery Migrate is marked for unload (which often is good if you don't need it), its official "child" (as it's mentioned in the WordPress core), jQuery, will not be unloaded. However, if there are other JS scripts from the plugins or the theme that are linked to jQuery Migrate, then it's better to keep it loaded.</em>
|
39 |
+
<?php
|
40 |
+
}
|
41 |
+
|
42 |
+
// If not 'jquery-migrate' show it
|
43 |
+
// If it's 'jquery-migrate' and has more than one "child" (apart from jQuery) show it
|
44 |
+
$showDependencyNotice = ($data['row']['obj']->handle === 'jquery-migrate' && count($childHandles) > 1) || ($data['row']['obj']->handle !== 'jquery-migrate');
|
45 |
+
|
46 |
+
if ($showDependencyNotice) {
|
47 |
+
?>
|
48 |
+
<em style="font-size: 85%;">
|
49 |
+
<span style="color: #0073aa; width: 19px; height: 19px; vertical-align: middle;" class="dashicons dashicons-info"></span>
|
50 |
+
There are JS "children" files depending on this file. By unloading it, the following will also be unloaded:
|
51 |
+
<span style="color: green; font-weight: 600;">
|
52 |
+
<?php echo implode('<span style="color: black;">,</span> ', $childHandles); ?>
|
53 |
+
</span>
|
54 |
+
</em>
|
55 |
+
<div class="wpacu_hide_if_handle_row_contracted">
|
56 |
+
<label for="script_<?php echo $data['row']['obj']->handle; ?>_ignore_children">
|
57 |
+
⟶ <input id="script_<?php echo $data['row']['obj']->handle; ?>_ignore_children"
|
58 |
+
type="checkbox"
|
59 |
+
<?php if ($ignoreChild) { ?>checked="checked"<?php } ?>
|
60 |
+
name="wpacu_ignore_child[scripts][<?php echo $data['row']['obj']->handle; ?>]"
|
61 |
+
value="1" /> <small><?php _e('Ignore dependency rule and keep the "children" loaded', 'wp-asset-clean-up'); ?></small>
|
62 |
+
</label>
|
63 |
+
</div>
|
64 |
+
<?php
|
65 |
+
}
|
66 |
+
?>
|
67 |
+
</div>
|
68 |
+
<?php
|
69 |
}
|
templates/meta-box-loaded-assets/_hardcoded/_asset-script-single-row-hardcoded/_source.php
CHANGED
@@ -17,6 +17,19 @@ if (isset($data['row']['obj']->src, $data['row']['obj']->srcHref) && $data['row'
|
|
17 |
$isExternalSrc = false;
|
18 |
}
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
$relSrc = str_replace(site_url(), '', $data['row']['obj']->src);
|
21 |
|
22 |
if (isset($data['row']['obj']->baseUrl)) {
|
@@ -26,7 +39,7 @@ if (isset($data['row']['obj']->src, $data['row']['obj']->srcHref) && $data['row'
|
|
26 |
<div class="wpacu-source-row">
|
27 |
<?php _e( 'Source:', 'wp-asset-clean-up' ); ?>
|
28 |
<a target="_blank"
|
29 |
-
style="color: green;" <?php if ( $isExternalSrc ) { ?> data-wpacu-external-source="<?php echo $
|
30 |
href="<?php echo $data['row']['obj']->src; ?>"><?php echo $relSrc; ?></a>
|
31 |
<?php if ( $isExternalSrc ) { ?><span data-wpacu-external-source-status></span><?php } ?>
|
32 |
</div>
|
17 |
$isExternalSrc = false;
|
18 |
}
|
19 |
|
20 |
+
$srcHref = $data['row']['obj']->srcHref;
|
21 |
+
|
22 |
+
// If the source starts with ../ mark it as external to be checked via the AJAX call (special case)
|
23 |
+
if (strpos($data['row']['obj']->srcHref, '../') === 0) {
|
24 |
+
$currentPageUrl = \WpAssetCleanUp\Misc::getCurrentPageUrl();
|
25 |
+
$currentPageUrl = trim($currentPageUrl, '/');
|
26 |
+
|
27 |
+
$srcHref = $currentPageUrl . '/'. $data['row']['obj']->srcHref;
|
28 |
+
|
29 |
+
$isExternalSrc = true; // simulation
|
30 |
+
}
|
31 |
+
|
32 |
+
|
33 |
$relSrc = str_replace(site_url(), '', $data['row']['obj']->src);
|
34 |
|
35 |
if (isset($data['row']['obj']->baseUrl)) {
|
39 |
<div class="wpacu-source-row">
|
40 |
<?php _e( 'Source:', 'wp-asset-clean-up' ); ?>
|
41 |
<a target="_blank"
|
42 |
+
style="color: green;" <?php if ( $isExternalSrc ) { ?> data-wpacu-external-source="<?php echo $srcHref; ?>" <?php } ?>
|
43 |
href="<?php echo $data['row']['obj']->src; ?>"><?php echo $relSrc; ?></a>
|
44 |
<?php if ( $isExternalSrc ) { ?><span data-wpacu-external-source-status></span><?php } ?>
|
45 |
</div>
|
templates/meta-box-loaded-assets/_hardcoded/_asset-style-single-row-hardcoded/_source.php
CHANGED
@@ -16,6 +16,18 @@ if (isset($data['row']['obj']->src, $data['row']['obj']->srcHref) && $data['row'
|
|
16 |
$isExternalSrc = false;
|
17 |
}
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
$relSrc = str_replace(site_url(), '', $data['row']['obj']->src);
|
20 |
|
21 |
if (isset($data['row']['obj']->baseUrl)) {
|
@@ -25,7 +37,7 @@ if (isset($data['row']['obj']->src, $data['row']['obj']->srcHref) && $data['row'
|
|
25 |
<div class="wpacu-source-row">
|
26 |
<?php _e( 'Source:', 'wp-asset-clean-up' ); ?>
|
27 |
<a target="_blank"
|
28 |
-
style="color: green;" <?php if ( $isExternalSrc ) { ?> data-wpacu-external-source="<?php echo $
|
29 |
href="<?php echo $data['row']['obj']->src; ?>"><?php echo $relSrc; ?></a>
|
30 |
<?php if ( $isExternalSrc ) { ?><span data-wpacu-external-source-status></span><?php } ?>
|
31 |
</div>
|
16 |
$isExternalSrc = false;
|
17 |
}
|
18 |
|
19 |
+
$srcHref = $data['row']['obj']->srcHref;
|
20 |
+
|
21 |
+
// If the source starts with ../ mark it as external to be checked via the AJAX call (special case)
|
22 |
+
if (strpos($data['row']['obj']->srcHref, '../') === 0) {
|
23 |
+
$currentPageUrl = \WpAssetCleanUp\Misc::getCurrentPageUrl();
|
24 |
+
$currentPageUrl = trim($currentPageUrl, '/');
|
25 |
+
|
26 |
+
$srcHref = $currentPageUrl . '/'. $data['row']['obj']->srcHref;
|
27 |
+
|
28 |
+
$isExternalSrc = true; // simulation
|
29 |
+
}
|
30 |
+
|
31 |
$relSrc = str_replace(site_url(), '', $data['row']['obj']->src);
|
32 |
|
33 |
if (isset($data['row']['obj']->baseUrl)) {
|
37 |
<div class="wpacu-source-row">
|
38 |
<?php _e( 'Source:', 'wp-asset-clean-up' ); ?>
|
39 |
<a target="_blank"
|
40 |
+
style="color: green;" <?php if ( $isExternalSrc ) { ?> data-wpacu-external-source="<?php echo $srcHref; ?>" <?php } ?>
|
41 |
href="<?php echo $data['row']['obj']->src; ?>"><?php echo $relSrc; ?></a>
|
42 |
<?php if ( $isExternalSrc ) { ?><span data-wpacu-external-source-status></span><?php } ?>
|
43 |
</div>
|
templates/meta-box-loaded.php
CHANGED
@@ -148,6 +148,13 @@ if ($data['plugin_settings']['assets_list_layout'] === 'by-loaded-unloaded') {
|
|
148 |
$data['page_unload_text'] = __('Unload on this page', 'wp-asset-clean-up');
|
149 |
wp_cache_set('wpacu_data_page_unload_text', $data['page_unload_text']);
|
150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
// Assets List Layout - added here to convenience - to avoid going to "Settings"
|
152 |
// it could make debugging faster
|
153 |
ob_start();
|
148 |
$data['page_unload_text'] = __('Unload on this page', 'wp-asset-clean-up');
|
149 |
wp_cache_set('wpacu_data_page_unload_text', $data['page_unload_text']);
|
150 |
|
151 |
+
if (is_singular()) {
|
152 |
+
global $post;
|
153 |
+
?>
|
154 |
+
<input type="hidden" name="wpacu_is_singular_page" value="<?php echo $post->ID; ?>" />
|
155 |
+
<?php
|
156 |
+
}
|
157 |
+
|
158 |
// Assets List Layout - added here to convenience - to avoid going to "Settings"
|
159 |
// it could make debugging faster
|
160 |
ob_start();
|
wpacu-load.php
CHANGED
@@ -21,13 +21,15 @@ function includeWpAssetCleanUpClassesAutoload($class)
|
|
21 |
|
22 |
$pathToClass = WPACU_PLUGIN_CLASSES_PATH.$classFilter.'.php';
|
23 |
|
24 |
-
if (
|
25 |
include_once $pathToClass;
|
26 |
}
|
27 |
}
|
28 |
|
29 |
spl_autoload_register('includeWpAssetCleanUpClassesAutoload');
|
30 |
|
|
|
|
|
31 |
// Main Class
|
32 |
\WpAssetCleanUp\Main::instance();
|
33 |
|
@@ -45,9 +47,6 @@ $wpacuOwnAssets->init();
|
|
45 |
$wpacuUpdate = new \WpAssetCleanUp\Update;
|
46 |
$wpacuUpdate->init();
|
47 |
|
48 |
-
// Various functions
|
49 |
-
new \WpAssetCleanUp\Misc;
|
50 |
-
|
51 |
// Menu
|
52 |
new \WpAssetCleanUp\Menu;
|
53 |
|
21 |
|
22 |
$pathToClass = WPACU_PLUGIN_CLASSES_PATH.$classFilter.'.php';
|
23 |
|
24 |
+
if (is_file($pathToClass)) {
|
25 |
include_once $pathToClass;
|
26 |
}
|
27 |
}
|
28 |
|
29 |
spl_autoload_register('includeWpAssetCleanUpClassesAutoload');
|
30 |
|
31 |
+
\WpAssetCleanUp\ObjectCache::wpacu_cache_init();
|
32 |
+
|
33 |
// Main Class
|
34 |
\WpAssetCleanUp\Main::instance();
|
35 |
|
47 |
$wpacuUpdate = new \WpAssetCleanUp\Update;
|
48 |
$wpacuUpdate->init();
|
49 |
|
|
|
|
|
|
|
50 |
// Menu
|
51 |
new \WpAssetCleanUp\Menu;
|
52 |
|
wpacu.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/*
|
3 |
* Plugin Name: Asset CleanUp: Page Speed Booster
|
4 |
* Plugin URI: https://wordpress.org/plugins/wp-asset-clean-up/
|
5 |
-
* Version: 1.3.6.
|
6 |
* Description: Unload Chosen Scripts & Styles from Posts/Pages to reduce HTTP Requests, Combine/Minify CSS/JS files
|
7 |
* Author: Gabriel Livan
|
8 |
* Author URI: http://gabelivan.com/
|
@@ -12,7 +12,7 @@
|
|
12 |
|
13 |
// Is the Pro version triggered before the Lite one and are both plugins active?
|
14 |
if (! defined('WPACU_PLUGIN_VERSION')) {
|
15 |
-
define('WPACU_PLUGIN_VERSION', '1.3.6.
|
16 |
}
|
17 |
|
18 |
// Exit if accessed directly
|
2 |
/*
|
3 |
* Plugin Name: Asset CleanUp: Page Speed Booster
|
4 |
* Plugin URI: https://wordpress.org/plugins/wp-asset-clean-up/
|
5 |
+
* Version: 1.3.6.2
|
6 |
* Description: Unload Chosen Scripts & Styles from Posts/Pages to reduce HTTP Requests, Combine/Minify CSS/JS files
|
7 |
* Author: Gabriel Livan
|
8 |
* Author URI: http://gabelivan.com/
|
12 |
|
13 |
// Is the Pro version triggered before the Lite one and are both plugins active?
|
14 |
if (! defined('WPACU_PLUGIN_VERSION')) {
|
15 |
+
define('WPACU_PLUGIN_VERSION', '1.3.6.2');
|
16 |
}
|
17 |
|
18 |
// Exit if accessed directly
|