Fast Velocity Minify - Version 2.2.1

Version Description

[2017.08.21] = * added unicode support to the alternative html minification option * improved some options description

Download this release

Release Info

Developer Alignak
Plugin Icon 128x128 Fast Velocity Minify
Version 2.2.1
Comparing to
See all releases

Code changes from version 2.2.0 to 2.2.1

Files changed (6) hide show
  1. fvm.css +31 -30
  2. fvm.js +121 -121
  3. fvm.php +1783 -1771
  4. inc/functions.php +4 -3
  5. libs/mrclay/HTML.php +241 -241
  6. readme.txt +5 -1
fvm.css CHANGED
@@ -1,30 +1,31 @@
1
- #fastvelocity-min{margin-top:10px;}
2
- #fastvelocity-min .processed{ min-height: 20px; margin: -4px 0 -2px 0; border: none !important; }
3
- #fastvelocity-min .processed li{margin:0; padding:10px 0; border: none !important; }
4
- #fastvelocity-min .processed > li:last-of-type { border: 0; }
5
- #fastvelocity-min .processed li .filename{width: 50%;float:left;font-family:monospace;display:block;word-wrap:break-word;line-height:30px;}
6
- #fastvelocity-min .processed li .accessed{display:block;}
7
- #fastvelocity-min .processed li .error{color:red}
8
- #fastvelocity-min .processed li .actions{display:block; padding:0; margin:0; text-align: right;}
9
- #fastvelocity-min .processed li a{margin-left:10px}
10
- #fastvelocity-min .processed pre{background:#EEE;max-height:300px;overflow:auto;display:none;margin-top:18px;margin-bottom:7px;padding:5px}
11
- #fastvelocity-min .clear { clear:both; }
12
- #fastvelocity-min #purgeall-row { padding-bottom: 2px; }
13
- .fvm-settings label { font-size: 14px; color: #222; padding-top: 1px; }
14
- .fvm-settings span.note-info { font-size: 14px; margin-left: 8px; color: #666; font-style: italic; }
15
- .fvm-settings p.description { font-size: 14px; color: #666; font-style: italic; font-size: 14px; }
16
- #tab-info h4{font-size: 14px; margin-bottom:-10px; }
17
- h3.hndle { background: #F7F7F7; color: #000;}
18
- .fvm-hide { max-height: 1px; overflow: none; position: absolute; top: -9999px; left: -9999px; visibility: hidden; }
19
- .fvm-warning { font-weight: 600; color: #AA0000; }
20
- .fvm-bold-green { font-weight: 600; color: #1196A3; }
21
- .fvm-label-special { line-height: 38px; }
22
- .fvm-label-pad { line-height: 21px; }
23
-
24
- @media screen and (max-width:520px) {
25
- #fastvelocity-min .processed li .filename{width: 100%;float:none;}
26
- #fastvelocity-min .processed li .actions{text-align: left;margin-top: 4px}
27
- #fastvelocity-min .processed li a{margin-left:0;margin-right:10px}
28
- #fastvelocity-min .processed pre{margin-top:12px;margin-bottom:5px;}
29
- .fvm-label-special { line-height: inherit; }
30
- }
 
1
+ #fastvelocity-min{margin-top:10px;}
2
+ #fastvelocity-min .processed{ min-height: 20px; margin: -4px 0 -2px 0; border: none !important; }
3
+ #fastvelocity-min .processed li{margin:0; padding:10px 0; border: none !important; }
4
+ #fastvelocity-min .processed > li:last-of-type { border: 0; }
5
+ #fastvelocity-min .processed li .filename{width: 50%;float:left;font-family:monospace;display:block;word-wrap:break-word;line-height:30px;}
6
+ #fastvelocity-min .processed li .accessed{display:block;}
7
+ #fastvelocity-min .processed li .error{color:red}
8
+ #fastvelocity-min .processed li .actions{display:block; padding:0; margin:0; text-align: right;}
9
+ #fastvelocity-min .processed li a{margin-left:10px}
10
+ #fastvelocity-min .processed pre{background:#EEE;max-height:300px;overflow:auto;display:none;margin-top:18px;margin-bottom:7px;padding:5px}
11
+ #fastvelocity-min .clear { clear:both; }
12
+ #fastvelocity-min #purgeall-row { padding-bottom: 2px; }
13
+ .fvm-settings label { font-size: 14px; color: #222; padding-top: 1px; }
14
+ .fvm-settings span.note-info { font-size: 14px; margin-left: 8px; color: #666; font-style: italic; }
15
+ .fvm-settings p.description { font-size: 14px; color: #666; font-style: italic; font-size: 14px; }
16
+ #tab-info h4{font-size: 14px; margin-bottom:-10px; }
17
+ h3.hndle { background: #F7F7F7; color: #000;}
18
+ .fvm-hide { max-height: 1px; overflow: none; position: absolute; top: -9999px; left: -9999px; visibility: hidden; }
19
+ .fvm-warning { font-weight: 600; color: #AA0000; }
20
+ .fvm-bold-green { font-weight: 600; color: #1196A3; }
21
+ .fvm-label-special { line-height: 38px; }
22
+ .fvm-label-pad { line-height: 21px; }
23
+ .fvm-rowintro { padding-bottom: 10px; }
24
+
25
+ @media screen and (max-width:520px) {
26
+ #fastvelocity-min .processed li .filename{width: 100%;float:none;}
27
+ #fastvelocity-min .processed li .actions{text-align: left;margin-top: 4px}
28
+ #fastvelocity-min .processed li a{margin-left:0;margin-right:10px}
29
+ #fastvelocity-min .processed pre{margin-top:12px;margin-bottom:5px;}
30
+ .fvm-label-special { line-height: inherit; }
31
+ }
fvm.js CHANGED
@@ -1,122 +1,122 @@
1
- (function($){
2
-
3
- $(function(){
4
-
5
- // disable some checkboxes when some other is on or off
6
- $('#fastvelocity_min_enable_defer_js').bind('click init', function() {
7
- if( $(this).is(':checked')) {
8
- $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", false);
9
- } else {
10
- $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", true);
11
- }
12
- }).trigger('init');
13
-
14
- // disable some checkboxes when some other is on or off
15
- $('#fastvelocity_min_skip_html_minification').bind('click init', function() {
16
- if( $(this).is(':checked')) {
17
- $("#fastvelocity_min_strip_htmlcomments").prop("disabled", true).prop('checked', false);
18
- } else {
19
- $("#fastvelocity_min_strip_htmlcomments").prop("disabled", false);
20
- }
21
- }).trigger('init');
22
-
23
- // disable some checkboxes when some other is on or off
24
- $('#fastvelocity_min_disable_css_merge').bind('click init', function() {
25
- if( $(this).is(':checked')) {
26
- $("#fastvelocity_min_disable_css_minification, #fastvelocity_min_force_inline_css").prop("disabled", true);
27
- $("#fastvelocity_min_force_inline_css_footer").prop("disabled", true);
28
- $("#fastvelocity_min_skip_cssorder, #fastvelocity_min_remove_print_mediatypes").prop("disabled", true);
29
- } else {
30
- $("#fastvelocity_min_disable_css_minification, #fastvelocity_min_force_inline_css").prop("disabled", false);
31
- $("#fastvelocity_min_force_inline_css_footer").prop("disabled", false);
32
- $("#fastvelocity_min_skip_cssorder, #fastvelocity_min_remove_print_mediatypes").prop("disabled", false);
33
- }
34
- }).trigger('init');
35
-
36
- // disable some checkboxes when some other is on or off
37
- $('#fastvelocity_min_disable_js_merge').bind('click init', function() {
38
- if( $(this).is(':checked')) {
39
- $("#fastvelocity_min_use_yui, #fastvelocity_min_disable_js_minification").prop("disabled", true);
40
- $("#fastvelocity_min_enable_defer_js, #fastvelocity_min_defer_for_pagespeed").prop("disabled", true);
41
- $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", true);
42
- } else {
43
- $("#fastvelocity_min_use_yui, #fastvelocity_min_disable_js_minification").prop("disabled", false);
44
- $("#fastvelocity_min_enable_defer_js, #fastvelocity_min_defer_for_pagespeed").prop("disabled", false);
45
- $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", false);
46
- }
47
- }).trigger('init');
48
-
49
-
50
-
51
- // disable collapse
52
- $('.postbox h3, .postbox .handlediv').unbind('click.postboxes');
53
-
54
- // variables
55
- var $fastvelocity_min_processed = $('#fastvelocity_min_processed'),
56
- $fastvelocity_min_jsprocessed = $('#fastvelocity_min_jsprocessed',$fastvelocity_min_processed),
57
- $fastvelocity_min_jsprocessed_ul = $('ul',$fastvelocity_min_jsprocessed),
58
- $fastvelocity_min_cssprocessed = $('#fastvelocity_min_cssprocessed',$fastvelocity_min_processed),
59
- $fastvelocity_min_cssprocessed_ul = $('ul',$fastvelocity_min_cssprocessed),
60
- $fastvelocity_min_noprocessed = $('#fastvelocity_min_noprocessed'),
61
- timeout = null,
62
- stamp = null;
63
-
64
- $($fastvelocity_min_processed).on('click','.log',function(e){
65
- e.preventDefault();
66
- $(this).parent().nextAll('pre').slideToggle();
67
- });
68
-
69
- function getFiles(extra) {
70
- stamp = new Date().getTime();
71
- var data = {
72
- 'action': 'fastvelocity_min_files',
73
- 'stamp': stamp
74
- };
75
- if(extra) {
76
- for (var attrname in extra) { data[attrname] = extra[attrname]; }
77
- }
78
-
79
-
80
- $.post(ajaxurl, data, function(response) {
81
-
82
- if(stamp == response.stamp) {
83
- if(response.js.length > 0) {
84
- $fastvelocity_min_jsprocessed.show();
85
-
86
- $(response.js).each(function(){
87
- var $li = $fastvelocity_min_jsprocessed_ul.find('li.'+this.hash);
88
- if($li.length > 0) {
89
- if($li.find('pre').html() != this.log) {
90
- $li.find('pre').html(this.log);
91
- }
92
- } else {
93
- $fastvelocity_min_jsprocessed_ul.append('<li class="'+this.hash+'"><span class="filename">'+this.filename+'</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
94
- }
95
- });
96
-
97
- }
98
- if(response.css.length > 0) {
99
-
100
- $(response.css).each(function(){
101
- var $li = $fastvelocity_min_cssprocessed_ul.find('li.'+this.hash);
102
- if($li.length > 0) {
103
- if($li.find('pre').html() != this.log) {
104
- $li.find('pre').html(this.log);
105
- }
106
- } else {
107
- $fastvelocity_min_cssprocessed_ul.append('<li class="'+this.hash+'"><span class="filename">'+this.filename+'</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
108
- }
109
- });
110
- }
111
-
112
- // check for new files
113
- timeout = setTimeout(getFiles, 2500);
114
- }
115
- });
116
- }
117
-
118
- getFiles();
119
-
120
- });
121
-
122
  })(jQuery);
1
+ (function($){
2
+
3
+ $(function(){
4
+
5
+ // disable some checkboxes when some other is on or off
6
+ $('#fastvelocity_min_enable_defer_js').bind('click init', function() {
7
+ if( $(this).is(':checked')) {
8
+ $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", false);
9
+ } else {
10
+ $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", true);
11
+ }
12
+ }).trigger('init');
13
+
14
+ // disable some checkboxes when some other is on or off
15
+ $('#fastvelocity_min_skip_html_minification').bind('click init', function() {
16
+ if( $(this).is(':checked')) {
17
+ $("#fastvelocity_min_strip_htmlcomments").prop("disabled", true).prop('checked', false);
18
+ } else {
19
+ $("#fastvelocity_min_strip_htmlcomments").prop("disabled", false);
20
+ }
21
+ }).trigger('init');
22
+
23
+ // disable some checkboxes when some other is on or off
24
+ $('#fastvelocity_min_disable_css_merge').bind('click init', function() {
25
+ if( $(this).is(':checked')) {
26
+ $("#fastvelocity_min_disable_css_minification, #fastvelocity_min_force_inline_css").prop("disabled", true);
27
+ $("#fastvelocity_min_force_inline_css_footer").prop("disabled", true);
28
+ $("#fastvelocity_min_skip_cssorder, #fastvelocity_min_remove_print_mediatypes").prop("disabled", true);
29
+ } else {
30
+ $("#fastvelocity_min_disable_css_minification, #fastvelocity_min_force_inline_css").prop("disabled", false);
31
+ $("#fastvelocity_min_force_inline_css_footer").prop("disabled", false);
32
+ $("#fastvelocity_min_skip_cssorder, #fastvelocity_min_remove_print_mediatypes").prop("disabled", false);
33
+ }
34
+ }).trigger('init');
35
+
36
+ // disable some checkboxes when some other is on or off
37
+ $('#fastvelocity_min_disable_js_merge').bind('click init', function() {
38
+ if( $(this).is(':checked')) {
39
+ $("#fastvelocity_min_use_yui, #fastvelocity_min_disable_js_minification").prop("disabled", true);
40
+ $("#fastvelocity_min_enable_defer_js, #fastvelocity_min_defer_for_pagespeed").prop("disabled", true);
41
+ $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", true);
42
+ } else {
43
+ $("#fastvelocity_min_use_yui, #fastvelocity_min_disable_js_minification").prop("disabled", false);
44
+ $("#fastvelocity_min_enable_defer_js, #fastvelocity_min_defer_for_pagespeed").prop("disabled", false);
45
+ $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", false);
46
+ }
47
+ }).trigger('init');
48
+
49
+
50
+
51
+ // disable collapse
52
+ $('.postbox h3, .postbox .handlediv').unbind('click.postboxes');
53
+
54
+ // variables
55
+ var $fastvelocity_min_processed = $('#fastvelocity_min_processed'),
56
+ $fastvelocity_min_jsprocessed = $('#fastvelocity_min_jsprocessed',$fastvelocity_min_processed),
57
+ $fastvelocity_min_jsprocessed_ul = $('ul',$fastvelocity_min_jsprocessed),
58
+ $fastvelocity_min_cssprocessed = $('#fastvelocity_min_cssprocessed',$fastvelocity_min_processed),
59
+ $fastvelocity_min_cssprocessed_ul = $('ul',$fastvelocity_min_cssprocessed),
60
+ $fastvelocity_min_noprocessed = $('#fastvelocity_min_noprocessed'),
61
+ timeout = null,
62
+ stamp = null;
63
+
64
+ $($fastvelocity_min_processed).on('click','.log',function(e){
65
+ e.preventDefault();
66
+ $(this).parent().nextAll('pre').slideToggle();
67
+ });
68
+
69
+ function getFiles(extra) {
70
+ stamp = new Date().getTime();
71
+ var data = {
72
+ 'action': 'fastvelocity_min_files',
73
+ 'stamp': stamp
74
+ };
75
+ if(extra) {
76
+ for (var attrname in extra) { data[attrname] = extra[attrname]; }
77
+ }
78
+
79
+
80
+ $.post(ajaxurl, data, function(response) {
81
+
82
+ if(stamp == response.stamp) {
83
+ if(response.js.length > 0) {
84
+ $fastvelocity_min_jsprocessed.show();
85
+
86
+ $(response.js).each(function(){
87
+ var $li = $fastvelocity_min_jsprocessed_ul.find('li.'+this.hash);
88
+ if($li.length > 0) {
89
+ if($li.find('pre').html() != this.log) {
90
+ $li.find('pre').html(this.log);
91
+ }
92
+ } else {
93
+ $fastvelocity_min_jsprocessed_ul.append('<li class="'+this.hash+'"><span class="filename">'+this.filename+'</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
94
+ }
95
+ });
96
+
97
+ }
98
+ if(response.css.length > 0) {
99
+
100
+ $(response.css).each(function(){
101
+ var $li = $fastvelocity_min_cssprocessed_ul.find('li.'+this.hash);
102
+ if($li.length > 0) {
103
+ if($li.find('pre').html() != this.log) {
104
+ $li.find('pre').html(this.log);
105
+ }
106
+ } else {
107
+ $fastvelocity_min_cssprocessed_ul.append('<li class="'+this.hash+'"><span class="filename">'+this.filename+'</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
108
+ }
109
+ });
110
+ }
111
+
112
+ // check for new files
113
+ timeout = setTimeout(getFiles, 2500);
114
+ }
115
+ });
116
+ }
117
+
118
+ getFiles();
119
+
120
+ });
121
+
122
  })(jQuery);
fvm.php CHANGED
@@ -1,1771 +1,1783 @@
1
- <?php
2
- /*
3
- Plugin Name: Fast Velocity Minify
4
- Plugin URI: http://fastvelocity.com
5
- Description: Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS and JavaScript files into groups, compressing HTML and other speed optimizations.
6
- Author: Raul Peixoto
7
- Author URI: http://fastvelocity.com
8
- Version: 2.2.0
9
- License: GPL2
10
-
11
- ------------------------------------------------------------------------
12
- This program is free software; you can redistribute it and/or modify
13
- it under the terms of the GNU General Public License as published by
14
- the Free Software Foundation; either version 2 of the License, or
15
- (at your option) any later version.
16
-
17
- This program is distributed in the hope that it will be useful,
18
- but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
- GNU General Public License for more details.
21
-
22
- You should have received a copy of the GNU General Public License
23
- along with this program; if not, write to the Free Software
24
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
- */
26
-
27
-
28
- # check for minimum requirements and prevent activation or disable if not fully compatible
29
- function fvm_compat_checker() {
30
- global $wp_version;
31
-
32
- # defaults
33
- $error = '';
34
- $nwpv = implode('.', array_slice(explode('.', $wp_version), 0, 2)); # get 2 p only
35
-
36
- # php version requirements
37
- if (version_compare( PHP_VERSION, '5.4', '<' )) {
38
- $error = 'Fast Velocity Minify requires PHP 5.4 or higher. You’re still on '. PHP_VERSION;
39
- }
40
-
41
- # php extension requirements
42
- if (!extension_loaded('mbstring')) {
43
- $error = 'Fast Velocity Minify requires the PHP mbstring module to be installed on the server.';
44
- }
45
-
46
- # wp version requirements
47
- if ( $nwpv < '4.5' ) {
48
- $error = 'Fast Velocity Minify requires WP 4.5 or higher. You’re still on ' . $wp_version;
49
- }
50
-
51
-
52
- if ((is_plugin_active(plugin_basename( __FILE__ )) && !empty($error)) || !empty($error)) {
53
- if (isset($_GET['activate'])) { unset($_GET['activate']); }
54
- deactivate_plugins( plugin_basename( __FILE__ ));
55
- add_action('admin_notices', function() use ($error){
56
- echo '<div class="notice notice-error is-dismissible"><p><strong>'.$error.'</strong></p></div>';
57
- });
58
- }
59
- }
60
- add_action('admin_init', 'fvm_compat_checker');
61
-
62
-
63
- # get the plugin directory and include functions
64
- $plugindir = plugin_dir_path( __FILE__ ); # with trailing slash
65
- include($plugindir.'inc/functions.php');
66
- include($plugindir.'inc/functions-serverinfo.php');
67
-
68
- # get cache directories and urls
69
- $cachepath = fvm_cachepath();
70
- $tmpdir = $cachepath['tmpdir'];
71
- $cachedir = $cachepath['cachedir'];
72
- $cachedirurl = $cachepath['cachedirurl'];
73
-
74
- # get the current wordpress installation url and path
75
- $wp_home = site_url(); # get the current wordpress installation url
76
- $wp_domain = trim(str_ireplace(array('http://', 'https://'), '', trim($wp_home, '/')));
77
- $wp_home_path = ABSPATH;
78
-
79
- # cleanup, delete any minification files older than 45 days (most probably unused files)
80
- if ($handle = opendir($cachedir.'/')) {
81
- while (false !== ($file = readdir($handle))) { $file = $cachedir.'/'.$file; if (is_file($file) && time() - filemtime($file) >= 86400 * 45) { unlink($file); } }
82
- closedir($handle);
83
- }
84
-
85
- # default globals
86
- $fastvelocity_min_global_js_done = array();
87
-
88
-
89
- ###########################################
90
- # build control panel pages ###############
91
- ###########################################
92
-
93
- # default options
94
- $ignore = array(); # urls to exclude for merging and minification
95
- $default_protocol = 'dynamic'; # use dynamic "//" protocols by default
96
- $disable_js_merge = false; # disable JS merging? Default: false (if true, minification is also disabled)
97
- $disable_css_merge = false; # disable CSS merging? Default: false (if true, minification is also disabled)
98
- $disable_js_minification = false; # disable JS minification? Default: false
99
- $disable_css_minification = false; # disable CSS minification? Default: false
100
- $use_yui = false; # Use the YUI processor instead of PHP Minify? Default false
101
- $remove_print_mediatypes = false; # remove CSS files of "print" mediatype
102
- $skip_html_minification = false; # skip HTML minification? Default: false
103
- $use_alt_html_minification = false; # use alt HTML minification? Default: false
104
- $strip_htmlcomments = false; # whether to remove html comments on html minification
105
- $skip_cssorder = false; # skip reordering CSS files by mediatype
106
- $skip_google_fonts = false; # skip google fonts optimization? Default: false
107
- $skip_emoji_removal = false; # skip removing emoji support? Default: false
108
- $enable_defer_js = false; # Defer parsing of JavaScript? Default false
109
- $exclude_defer_jquery = false; # Disable defer for jquery on the home
110
- $use_google_closure = false; # Use Google closure (slower) instead of YUI processor? Default false
111
- $use_php_minify = false; # Use PHP Minify instead of YUI or Closure? Default false
112
- $force_inline_css = false; # Don't inline all css by default
113
- $force_inline_css_footer = false; # Don't inline all css by default
114
- $force_inline_googlefonts = false; # Don't inline all google fonts by default
115
- $defer_for_pagespeed = false; # force defer for when we are being tested by pagespeed insights
116
- $exclude_defer_login = false; # Disable defer js on the login page
117
- $preload = array(); # urls to preload before anything else
118
- $preconnect = array(); # domains to preconnect to
119
- $fvm_fix_editor = false; # enable production mode by default?
120
-
121
- # extra
122
- $send_css_to_footer = false; # force defer for css
123
- $critical_path_css = false; # critical path for homepage
124
- $critical_css_tester = false; # will remove all css, except the critical path code
125
- $generate_gulp_files = false; # will generate gulp files for gulp-uncss (spider the site first to generate the fvm cache files)
126
- $generate_gulp_path = false; # path to working directory where gulp-uncss is installed
127
- $used_css_files = array();
128
-
129
- # add admin page and rewrite defaults
130
- if(is_admin()) {
131
- add_action('admin_menu', 'fastvelocity_min_admin_menu');
132
- add_action('admin_enqueue_scripts', 'fastvelocity_min_load_admin_jscss');
133
- add_action('wp_ajax_fastvelocity_min_files', 'fastvelocity_min_files_callback');
134
- add_action('admin_init', 'fastvelocity_min_register_settings');
135
- register_deactivation_hook( __FILE__, 'fastvelocity_min_plugin_deactivate');
136
- } else {
137
- # overwrite options from the database, false if not set
138
- $ignore = array_map('trim', explode("\n", get_option('fastvelocity_min_ignore', '')));
139
- $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
140
- $disable_js_merge = get_option('fastvelocity_min_disable_js_merge');
141
- $disable_css_merge = get_option('fastvelocity_min_disable_css_merge');
142
- $disable_js_minification = get_option('fastvelocity_min_disable_js_minification');
143
- $disable_css_minification = get_option('fastvelocity_min_disable_css_minification');
144
- $use_yui = get_option('fastvelocity_min_use_yui');
145
- $remove_print_mediatypes = get_option('fastvelocity_min_remove_print_mediatypes');
146
- $skip_html_minification = get_option('fastvelocity_min_skip_html_minification');
147
- $use_alt_html_minification = get_option('fastvelocity_min_use_alt_html_minification');
148
- $strip_htmlcomments = get_option('fastvelocity_min_strip_htmlcomments');
149
- $skip_cssorder = get_option('fastvelocity_min_skip_cssorder');
150
- $skip_google_fonts = get_option('fastvelocity_min_skip_google_fonts');
151
- $skip_emoji_removal = get_option('fastvelocity_min_skip_emoji_removal');
152
- $enable_defer_js = get_option('fastvelocity_min_enable_defer_js');
153
- $exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
154
- $force_inline_css = get_option('fastvelocity_min_force_inline_css');
155
- $force_inline_css_footer = get_option('fastvelocity_min_force_inline_css_footer');
156
- $force_inline_googlefonts = get_option('fastvelocity_min_force_inline_googlefonts');
157
- $defer_for_pagespeed = get_option('fastvelocity_min_defer_for_pagespeed');
158
- $exclude_defer_login = get_option('fastvelocity_min_exclude_defer_login');
159
- $preload = array_map('trim', explode("\n", get_option('fastvelocity_min_preload')));
160
- $preconnect = array_map('trim', explode("\n", get_option('fastvelocity_min_preconnect')));
161
- $fvm_fix_editor = get_option('fastvelocity_min_fvm_fix_editor');
162
- $send_css_to_footer = get_option('fastvelocity_min_send_css_to_footer');
163
- $critical_css_tester = get_option('fastvelocity_min_critical_css_tester');
164
- $critical_path_css = get_option('fastvelocity_min_critical_path_css');
165
- $generate_gulp_files = get_option('fastvelocity_min_generate_gulp_files');
166
- $generate_gulp_path = get_option('fastvelocity_min_generate_gulp_path');
167
-
168
-
169
- # skip on certain post_types or if there are specific keys on the url or if editor or admin
170
- if(!fastvelocity_exclude_contents()) {
171
-
172
- # actions for frontend only
173
- if(!$disable_js_merge) {
174
- add_action( 'wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
175
- add_action( 'wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
176
- }
177
- if(!$disable_css_merge) {
178
- add_action('wp_head', 'fvm_buffer_placeholder_top', 0);
179
- add_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
180
- add_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
181
- }
182
- if(!$skip_emoji_removal) {
183
- add_action( 'init', 'fastvelocity_min_disable_wp_emojicons' );
184
- }
185
-
186
- }
187
- }
188
-
189
-
190
-
191
- # exclude processing for editors and administrators (fix editors)
192
- add_action( 'plugins_loaded', 'fastvelocity_fix_editor' );
193
- function fastvelocity_fix_editor() {
194
- global $fvm_fix_editor, $disable_js_merge, $disable_css_merge, $skip_emoji_removal;
195
- if($fvm_fix_editor == true && is_user_logged_in() && (current_user_can('editor') || current_user_can('administrator'))) {
196
- if(!$disable_js_merge) {
197
- remove_action( 'wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
198
- remove_action( 'wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
199
- }
200
- if(!$disable_css_merge) {
201
- remove_action('wp_head', 'fvm_buffer_placeholder_top', 0);
202
- remove_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
203
- remove_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
204
- }
205
- if(!$skip_emoji_removal) {
206
- remove_action( 'init', 'fastvelocity_min_disable_wp_emojicons' );
207
- }
208
- }
209
- }
210
-
211
-
212
- # delete the cache when we deactivate the plugin
213
- function fastvelocity_min_plugin_deactivate() { fvm_purge_all(); }
214
-
215
-
216
- # create admin menu
217
- function fastvelocity_min_admin_menu() {
218
- add_options_page('Fast Velocity Minify Settings', 'Fast Velocity Minify', 'manage_options', 'fastvelocity-min', 'fastvelocity_min_settings');
219
- }
220
-
221
-
222
- # function to list all cache files
223
- function fastvelocity_min_files_callback() {
224
- global $cachedir;
225
-
226
- # default
227
- $return = array('js' => array(), 'css' => array(), 'stamp' => $_POST['stamp']);
228
-
229
- # inspect directory with opendir, since glob might not be available in some systems
230
- if ($handle = opendir($cachedir.'/')) {
231
- while (false !== ($file = readdir($handle))) {
232
- $file = $cachedir.'/'.$file;
233
- $ext = pathinfo($file, PATHINFO_EXTENSION);
234
- if (in_array($ext, array('js', 'css'))) {
235
- $log = file_get_contents($file.'.txt');
236
- $mincss = substr($file, 0, -4).'.min.css';
237
- $minjs = substr($file, 0, -3).'.min.js';
238
- $filename = basename($file);
239
- if ($ext == 'css' && file_exists($mincss)) { $filename = basename($mincss); }
240
- if ($ext == 'js' && file_exists($minjs)) { $filename = basename($minjs); }
241
-
242
- # get location, hash, modified date
243
- $info = explode('-', $filename);
244
- $hash = $info['1'];
245
- array_push($return[$ext], array('hash' => $hash, 'filename' => $filename, 'log' => $log));
246
- }
247
- }
248
- closedir($handle);
249
- }
250
-
251
- header('Content-Type: application/json');
252
- echo json_encode($return);
253
- wp_die();
254
- }
255
-
256
-
257
- # load wp-admin css and js files
258
- function fastvelocity_min_load_admin_jscss($hook) {
259
- if ('settings_page_fastvelocity-min' != $hook) { return; }
260
- wp_enqueue_script('postbox');
261
- wp_enqueue_style('fastvelocity-min', plugins_url('fvm.css', __FILE__), array(), filemtime(plugin_dir_path( __FILE__).'fvm.css'));
262
- wp_enqueue_script('fastvelocity-min', plugins_url('fvm.js', __FILE__), array('jquery'), filemtime(plugin_dir_path( __FILE__).'fvm.js'), true);
263
- }
264
-
265
-
266
- # register plugin settings
267
- function fastvelocity_min_register_settings() {
268
- register_setting('fvm-group', 'fastvelocity_min_ignore');
269
- register_setting('fvm-group', 'fastvelocity_min_default_protocol');
270
- register_setting('fvm-group', 'fastvelocity_min_disable_js_merge');
271
- register_setting('fvm-group', 'fastvelocity_min_disable_css_merge');
272
- register_setting('fvm-group', 'fastvelocity_min_disable_js_minification');
273
- register_setting('fvm-group', 'fastvelocity_min_disable_css_minification');
274
- register_setting('fvm-group', 'fastvelocity_min_use_yui');
275
- register_setting('fvm-group', 'fastvelocity_min_remove_print_mediatypes');
276
- register_setting('fvm-group', 'fastvelocity_min_skip_html_minification');
277
- register_setting('fvm-group', 'fastvelocity_min_use_alt_html_minification');
278
- register_setting('fvm-group', 'fastvelocity_min_strip_htmlcomments');
279
- register_setting('fvm-group', 'fastvelocity_min_skip_cssorder');
280
- register_setting('fvm-group', 'fastvelocity_min_skip_google_fonts');
281
- register_setting('fvm-group', 'fastvelocity_min_skip_fontawesome_fonts');
282
- register_setting('fvm-group', 'fastvelocity_min_skip_emoji_removal');
283
- register_setting('fvm-group', 'fastvelocity_min_enable_defer_js');
284
- register_setting('fvm-group', 'fastvelocity_min_exclude_defer_jquery');
285
- register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
286
- register_setting('fvm-group', 'fastvelocity_min_force_inline_css_footer');
287
- register_setting('fvm-group', 'fastvelocity_min_force_inline_googlefonts');
288
- register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
289
- register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
290
- register_setting('fvm-group', 'fastvelocity_min_preload');
291
- register_setting('fvm-group', 'fastvelocity_min_preconnect');
292
- register_setting('fvm-group', 'fastvelocity_min_fvm_fix_editor');
293
- register_setting('fvm-group', 'fastvelocity_min_fvm_enable_cdn');
294
- register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_url');
295
-
296
- # pro version (for private usage... or if you know what you're doing)
297
- register_setting('fvm-group-pro', 'fastvelocity_min_send_css_to_footer');
298
- register_setting('fvm-group-pro', 'fastvelocity_min_critical_css_tester');
299
- register_setting('fvm-group-pro', 'fastvelocity_min_critical_path_css');
300
- register_setting('fvm-group-pro', 'fastvelocity_min_generate_gulp_files');
301
- register_setting('fvm-group-pro', 'fastvelocity_min_generate_gulp_path');
302
- register_setting('fvm-group-license', 'fastvelocity_min_license_code');
303
- }
304
-
305
-
306
-
307
- # add settings link on plugin page
308
- function fastvelocity_min_settings_link($links) {
309
- if (is_plugin_active(plugin_basename( __FILE__ ))) {
310
- $settings_link = '<a href="options-general.php?page=fastvelocity-min">Settings</a>';
311
- array_unshift($links, $settings_link);
312
- }
313
- return $links;
314
- }
315
- add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
316
-
317
-
318
-
319
- # manage settings page
320
- function fastvelocity_min_settings() {
321
- if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
322
-
323
- # tmp folder
324
- global $tmpdir, $cachedir, $plugindir;
325
-
326
- # get active tab, set default
327
- $active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'status';
328
-
329
- ?>
330
- <div class="wrap">
331
- <h1>Fast Velocity Minify</h1>
332
-
333
- <?php
334
-
335
- # purge all caches
336
- if(isset($_POST['purgeall']) && $_POST['purgeall'] == 1) {
337
- fvm_purge_all(); # purge all
338
- echo __('<div class="notice notice-success is-dismissible"><p>The <strong>CSS and JS</strong> files have been purged!</p></div>');
339
- echo fastvelocity_purge_others(); # purge third party caches
340
- }
341
- ?>
342
-
343
- <h2 class="nav-tab-wrapper wp-clearfix">
344
- <a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
345
- <a href="?page=fastvelocity-min&tab=settings" class="nav-tab <?php echo $active_tab == 'settings' ? 'nav-tab-active' : ''; ?>">Settings</a>
346
- <?php
347
- # this is still under development
348
- $fvm_license = get_option('fastvelocity_min_license_code');
349
- if($fvm_license != false && mb_strlen($fvm_license, 'UTF-8') == 32) {
350
- ?>
351
- <a href="?page=fastvelocity-min&tab=pro" class="nav-tab <?php echo $active_tab == 'pro' ? 'nav-tab-active' : ''; ?>">Extra</a>
352
- <?php
353
- }
354
- ?>
355
- <a href="?page=fastvelocity-min&tab=server" class="nav-tab <?php echo $active_tab == 'server' ? 'nav-tab-active' : ''; ?>">Server Info</a>
356
- <a href="?page=fastvelocity-min&tab=help" class="nav-tab <?php echo $active_tab == 'help' ? 'nav-tab-active' : ''; ?>">Help</a>
357
- </h2>
358
-
359
-
360
- <?php if( $active_tab == 'status' ) { ?>
361
-
362
- <div id="fastvelocity-min">
363
- <div id="poststuff">
364
- <div id="fastvelocity_min_processed" class="postbox-container">
365
- <div class="meta-box">
366
-
367
- <div class="postbox" id="tab-purge">
368
- <h3 class="hndle"><span>Purge processed files</span></h3>
369
- <div class="inside" id="fastvelocity_min_topbtns">
370
- <ul class="processed">
371
- <li id="purgeall-row">
372
- <span class="filename">Purge processed CSS and JS files</span>
373
- <span class="actions">
374
- <form method="post" id="fastvelocity_min_clearall" action="<?php echo admin_url('options-general.php?page=fastvelocity-min&tab=status'); ?>">
375
- <input type="hidden" name="purgeall" value="1" />
376
- <?php submit_button('Delete', 'button-secondary', 'submit', false); ?>
377
- </form>
378
- </li>
379
- </ul>
380
- </div>
381
- </div>
382
-
383
- <div class="postbox" id="tab-js">
384
- <h3 class="hndle"><span>List of processed JS files</span></h3>
385
- <div class="inside" id="fastvelocity_min_jsprocessed">
386
- <ul class="processed"></ul>
387
- </div>
388
- </div>
389
-
390
- <div class="postbox" id="tab-css">
391
- <h3 class="hndle"><span>List of processed CSS files</span></h3>
392
- <div class="inside" id="fastvelocity_min_cssprocessed">
393
- <ul class="processed"></ul>
394
- </div>
395
- </div>
396
-
397
- </div>
398
- </div>
399
- </div>
400
- </div>
401
- <?php } ?>
402
-
403
- <?php if( $active_tab == 'settings' ) { ?>
404
- <form method="post" action="options.php">
405
- <?php settings_fields('fvm-group'); do_settings_sections('fvm-group'); ?>
406
-
407
- <div style="height: 20px;"></div>
408
- <h2 class="title">Basic Options</h2>
409
- <p class="fvm-bold-green">These options are generaly safe to edit as needed. If you use a cache plugin, kindly purge all your caches once you're done with the changes.</p>
410
-
411
- <table class="form-table fvm-settings">
412
- <tbody>
413
-
414
- <tr>
415
- <th scope="row">Troubleshooting</th>
416
- <td><fieldset><legend class="screen-reader-text"><span>Troubleshooting</span></legend>
417
- <label for="fastvelocity_min_fvm_fix_editor">
418
- <input name="fastvelocity_min_fvm_fix_editor" type="checkbox" id="fastvelocity_min_fvm_fix_editor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_fvm_fix_editor'), true, false); ?>>
419
- Fix Page Editors <span class="note-info">[ If selected, logged in users with the "editor" role (and above) will bypass all optimizations ]</span></label>
420
- </fieldset></td>
421
- </tr>
422
-
423
-
424
- <tr>
425
- <th scope="row">URL Options</th>
426
- <td>
427
- <?php
428
- # what to select
429
- $sel = get_option('fastvelocity_min_default_protocol');
430
- $a = ''; if($sel == 'dynamic' || empty($sel)) { $a = ' checked="checked"'; }
431
- $b = ''; if($sel == 'http') { $b = ' checked="checked"'; }
432
- $c = ''; if($sel == 'https') { $c = ' checked="checked"'; }
433
- ?>
434
- <fieldset><legend class="screen-reader-text"><span>URL Options</span></legend>
435
- <label><input type="radio" name="fastvelocity_min_default_protocol" value="dynamic" <?php echo $a; ?>> Use the default dynamic "//" protocol</label><br>
436
- <label><input type="radio" name="fastvelocity_min_default_protocol" value="http"<?php echo $b; ?>> Force HTTP urls</label><br>
437
- <label><input type="radio" name="fastvelocity_min_default_protocol" value="https"<?php echo $c; ?>> Force HTTPS urls</span></label><br>
438
- </fieldset>
439
- </td>
440
- </tr>
441
-
442
- <tr>
443
- <th scope="row">HTML Options</th>
444
- <td><fieldset><legend class="screen-reader-text"><span>HTML Options</span></legend>
445
- <label for="fastvelocity_min_skip_html_minification">
446
- <input name="fastvelocity_min_skip_html_minification" type="checkbox" id="fastvelocity_min_skip_html_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_html_minification'), true, false); ?>>
447
- Disable minification on HTML <span class="note-info">[ Normally, it's safe to leave HTML minification enabled ]</span></label>
448
- <br />
449
-
450
- <label for="fastvelocity_min_use_alt_html_minification">
451
- <input name="fastvelocity_min_use_alt_html_minification" type="checkbox" id="fastvelocity_min_use_alt_html_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_use_alt_html_minification'), true, false); ?>>
452
- Use the alternative HTML minification <span class="note-info">[ Select this, if you have some problem with some spaces disappearing ]</span></label>
453
- <br />
454
-
455
- <label for="fastvelocity_min_strip_htmlcomments">
456
- <input name="fastvelocity_min_strip_htmlcomments" type="checkbox" id="fastvelocity_min_strip_htmlcomments" value="1" <?php echo checked(1 == get_option('fastvelocity_min_strip_htmlcomments'), true, false); ?>>
457
- Strip HTML comments <span class="note-info">[ Some plugins need HTML comments to work properly ]</span></label>
458
- <br />
459
-
460
- </fieldset></td>
461
- </tr>
462
-
463
-
464
- <tr>
465
- <th scope="row">Fonts Options</th>
466
- <td><fieldset><legend class="screen-reader-text"><span>Fonts Options</span></legend>
467
- <label for="fastvelocity_min_skip_emoji_removal">
468
- <input name="fastvelocity_min_skip_emoji_removal" type="checkbox" id="fastvelocity_min_skip_emoji_removal" class="jsprocessor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_emoji_removal'), true, false); ?> >
469
- Stop removing Emojis and smileys <span class="note-info">[ If selected, Emojis will be left alone and won't be removed from wordpress ]</span></label>
470
- <br />
471
-
472
- <label for="fastvelocity_min_skip_google_fonts">
473
- <input name="fastvelocity_min_skip_google_fonts" type="checkbox" id="fastvelocity_min_skip_google_fonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_google_fonts'), true, false); ?> >
474
- Disable Google Fonts merging <span class="note-info">[ If selected, Google Fonts will no longer be merged into one request ]</span></label>
475
- <br />
476
-
477
- <label for="fastvelocity_min_force_inline_googlefonts">
478
- <input name="fastvelocity_min_force_inline_googlefonts" type="checkbox" id="fastvelocity_min_force_inline_googlefonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_googlefonts'), true, false); ?> >
479
- Inline Google Fonts CSS <span class="note-info">[ If selected, Google Fonts CSS code will be inlined using "*.woof" format - NOTE: IE9+ and <a target="_blank" href="http://caniuse.com/#feat=woff">modern browsers</a> only]</span></label>
480
- <br />
481
-
482
- </fieldset></td>
483
- </tr>
484
-
485
-
486
-
487
-
488
- <tr>
489
- <th scope="row">CSS Options</th>
490
- <td><fieldset><legend class="screen-reader-text"><span>CSS Options</span></legend>
491
-
492
- <label for="fastvelocity_min_disable_css_merge">
493
- <input name="fastvelocity_min_disable_css_merge" type="checkbox" id="fastvelocity_min_disable_css_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_css_merge'), true, false); ?>>
494
- Disable CSS processing<span class="note-info">[ If selected, this plugin will ignore CSS files completely ]</span></label>
495
- <br />
496
- <label for="fastvelocity_min_disable_css_minification">
497
- <input name="fastvelocity_min_disable_css_minification" type="checkbox" id="fastvelocity_min_disable_css_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_css_minification'), true, false); ?>>
498
- Disable minification on CSS files <span class="note-info">[ If selected, CSS files will be merged but not minified ]</span></label>
499
- <br />
500
- <label for="fastvelocity_min_skip_cssorder">
501
- <input name="fastvelocity_min_skip_cssorder" type="checkbox" id="fastvelocity_min_skip_cssorder" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_cssorder'), true, false); ?> >
502
- Preserve the order of CSS files <span class="note-info">[ If selected, you will have better CSS compatibility but possibly more CSS files]</span></label>
503
- <br />
504
- <label for="fastvelocity_min_remove_print_mediatypes">
505
- <input name="fastvelocity_min_remove_print_mediatypes" type="checkbox" id="fastvelocity_min_remove_print_mediatypes" value="1" <?php echo checked(1 == get_option('fastvelocity_min_remove_print_mediatypes'), true, false); ?> >
506
- Remove the "Print" related stylesheets <span class="note-info">[ If selected, CSS files of mediatype "print" will be removed from the site ]</span></label>
507
- <br />
508
- <label for="fastvelocity_min_force_inline_css">
509
- <input name="fastvelocity_min_force_inline_css" type="checkbox" id="fastvelocity_min_force_inline_css" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_css'), true, false); ?>>
510
- Inline all header CSS files <span class="note-info">[ If selected, the header CSS will be inlined to avoid the "render blocking" on pagespeed insights tests ]</span></label>
511
- <br />
512
- <label for="fastvelocity_min_force_inline_css_footer">
513
- <input name="fastvelocity_min_force_inline_css_footer" type="checkbox" id="fastvelocity_min_force_inline_css_footer" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_css_footer'), true, false); ?>>
514
- Inline all footer CSS files <span class="note-info">[ If selected, the footer CSS will be inlined to avoid the "render blocking" on pagespeed insights tests ]</span></label>
515
- <br />
516
- </fieldset></td>
517
- </tr>
518
-
519
-
520
- <tr>
521
- <th scope="row">JavaScript Options</th>
522
- <td><fieldset><legend class="screen-reader-text"><span>JavaScript Options</span></legend>
523
- <label for="fastvelocity_min_disable_js_merge">
524
- <input name="fastvelocity_min_disable_js_merge" type="checkbox" id="fastvelocity_min_disable_js_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_merge'), true, false); ?> >
525
- Disable JavaScript processing <span class="note-info">[ If selected, this plugin will ignore JS files completely ]</span></label>
526
- <br />
527
-
528
- <?php
529
- # check for exec + a supported java version
530
- if(function_exists('exec') && exec('command -v java >/dev/null && echo "yes" || echo "no"') == 'yes') {
531
- ?>
532
- <label for="fastvelocity_min_use_yui">
533
- <input name="fastvelocity_min_use_yui" type="checkbox" id="fastvelocity_min_use_yui" class="jsprocessor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_use_yui'), true, false); ?> >
534
- Minify with YUI Compressor <span class="note-info">[ If selected, it will try to use the YUI Compressor to minify JS files ]</span></label>
535
- <br />
536
- <?php } ?>
537
-
538
- <label for="fastvelocity_min_disable_js_minification">
539
- <input name="fastvelocity_min_disable_js_minification" type="checkbox" id="fastvelocity_min_disable_js_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_minification'), true, false); ?> >
540
- Disable minification on JS files <span class="note-info">[ If selected, JS files will be merged but not minified ]</span></label>
541
- <br />
542
- </fieldset></td>
543
- </tr>
544
- </tbody></table>
545
-
546
-
547
- <div style="height: 20px;"></div>
548
- <h2 class="title">JS Advanced Options</h2>
549
- <p class="fvm-bold-green">It's highly recommended that you only select the options below if you're an advanced user or developer and understand what these options mean.</p>
550
-
551
- <table class="form-table fvm-settings">
552
- <tbody>
553
- <tr>
554
- <th scope="row">Render-blocking JS</th>
555
- <td><fieldset><legend class="screen-reader-text"><span>Render-blocking</span></legend>
556
- <label for="fastvelocity_min_enable_defer_js">
557
- <input name="fastvelocity_min_enable_defer_js" type="checkbox" id="fastvelocity_min_enable_defer_js" value="1" <?php echo checked(1 == get_option('fastvelocity_min_enable_defer_js'), true, false); ?>>
558
- Enable defer parsing of JS files globally <span class="note-info">[ Not all browsers, themes or plugins support this. Beware of broken functionality and design ]</span></label>
559
- <br />
560
- <label for="fastvelocity_min_defer_for_pagespeed">
561
- <input name="fastvelocity_min_defer_for_pagespeed" type="checkbox" id="fastvelocity_min_defer_for_pagespeed" value="1" <?php echo checked(1 == get_option('fastvelocity_min_defer_for_pagespeed'), true, false); ?>>
562
- Enable defer of JS for Pagespeed Insights <span class="note-info">[ This will defer JS files for Pagespeed Insights only, <a target="_blank" href="https://www.chromestatus.com/feature/5718547946799104">except external scripts</a> loaded from other domains ]</span></label>
563
- <br />
564
-
565
- <label for="fastvelocity_min_exclude_defer_jquery">
566
- <input name="fastvelocity_min_exclude_defer_jquery" type="checkbox" id="fastvelocity_min_exclude_defer_jquery" value="1" <?php echo checked(1 == get_option('fastvelocity_min_exclude_defer_jquery'), true, false); ?> >
567
- Skip deferring the jQuery library <span class="note-info">[ Will fix "undefined jQuery" errors on the Google Chrome console log ]</span></label>
568
- <br />
569
- <label for="fastvelocity_min_exclude_defer_login">
570
- <input name="fastvelocity_min_exclude_defer_login" type="checkbox" id="fastvelocity_min_exclude_defer_login" value="1" <?php echo checked(1 == get_option('fastvelocity_min_exclude_defer_login'), true, false); ?> >
571
- Skip deferring completely on the login page <span class="note-info">[ If selected, will disable JS deferring on your login page ]</span></label>
572
- <br />
573
-
574
-
575
- </fieldset></td>
576
- </tr>
577
- </tbody></table>
578
-
579
-
580
-
581
- <div style="height: 20px;"></div>
582
- <h2 class="title">JS and CSS Exceptions</h2>
583
- <p class="fvm-bold-green">You can use this section to exclude certain CSS or JS files from being processed in case of conflicts while merging.</p>
584
-
585
- <table class="form-table fvm-settings">
586
- <tbody>
587
- <tr>
588
- <th scope="row">Ignore List</th>
589
- <td><fieldset><legend class="screen-reader-text"><span>Ignore List</span></legend>
590
- <p><label for="blacklist_keys"><span class="fvm-label-pad">Ignore the following CSS and JS paths below:</span></label></p>
591
- <p>
592
- <textarea name="fastvelocity_min_ignore" rows="10" cols="50" id="fastvelocity_min_ignore" class="large-text code" placeholder="ex: /wp-includes/js/jquery/jquery.js"><?php echo get_option('fastvelocity_min_ignore'); ?></textarea>
593
- </p>
594
- <p class="description">[ Remove all query strings and use only relative or partial urls, ex: /wp-includes/js/jquery/jquery.js ]</p>
595
- <br />
596
- </fieldset></td>
597
- </tr>
598
- </tbody></table>
599
-
600
-
601
- <div style="height: 20px;"></div>
602
- <h2 class="title">CDN Options</h2>
603
- <p class="fvm-bold-green">This rewrite our generated CSS and JS urls to use your cdn domain name.</p>
604
-
605
- <table class="form-table fvm-settings">
606
- <tbody>
607
- <tr>
608
- <th scope="row"><span class="fvm-label-special">CDN URL</span></th>
609
- <td><fieldset><legend class="screen-reader-text"><span>CDN URL</span></legend>
610
- <label for="fastvelocity_min_fvm_cdn_url">
611
- <p><input type="text" name="fastvelocity_min_fvm_cdn_url" id="fastvelocity_min_fvm_cdn_url" value="<?php echo get_option('fastvelocity_min_fvm_cdn_url', ''); ?>" size="80" /></p>
612
- <p class="description">[ Leave empty, or enter your CDN URL domain name here ]</p></label>
613
- </fieldset></td>
614
- </tr>
615
- </tbody></table>
616
-
617
-
618
- <div style="height: 20px;"></div>
619
- <h2 class="title">Preconnect Optimization</h2>
620
- <p class="fvm-bold-green">Please make sure you understand these options before using them.</p>
621
-
622
- <table class="form-table fvm-settings">
623
- <tbody>
624
- <tr>
625
- <th scope="row">Preconnect Headers</th>
626
- <td><fieldset><legend class="screen-reader-text"><span>Preconnect</span></legend>
627
- <label for="fastvelocity_min_preconnect"><span class="fvm-label-pad">Insert one domain name url per line:</span></label>
628
- <p>
629
- <textarea name="fastvelocity_min_preconnect" rows="10" cols="50" id="fastvelocity_min_preconnect" class="large-text code" placeholder="ex: //fonts.gstatic.com"><?php echo get_option('fastvelocity_min_preconnect'); ?></textarea>
630
- </p>
631
- <p class="description">[ Use only the necessary domain names, such as remote font domain names, ex: //fonts.gstatic.com ]</p>
632
- </fieldset></td>
633
- </tr>
634
-
635
- </tbody></table>
636
-
637
-
638
- <div style="height: 20px;"></div>
639
- <h2 class="title">Homepage Optimization</h2>
640
- <p class="fvm-bold-green">Prioritize visible content by preloading images with high priority, such as the first image on a slider that is shown above the folder.</p>
641
-
642
- <table class="form-table fvm-settings">
643
- <tbody>
644
- <tr>
645
- <th scope="row">Preload Images</th>
646
- <td><fieldset><legend class="screen-reader-text"><span>Preload Images</span></legend>
647
- <label for="fastvelocity_min_preload"><span class="fvm-label-pad">Insert one image url per line:</span></label>
648
- <p>
649
- <textarea name="fastvelocity_min_preload" rows="10" cols="50" id="fastvelocity_min_preload" class="large-text code" placeholder="ex: //yoursite.com/wp-content/plugins/some-slider/large.img"><?php echo get_option('fastvelocity_min_preload'); ?></textarea>
650
- </p>
651
- <p class="description">[ Use only for large images that first load above the fold. Read the Help section for more details. ]</p>
652
- </fieldset></td>
653
- </tr>
654
- </tbody></table>
655
-
656
-
657
- <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
658
- </form>
659
- <?php } ?>
660
-
661
-
662
- <?php if( $active_tab == 'pro' ) {
663
-
664
- # this is still under development
665
- $fvm_license = get_option('fastvelocity_min_license_code');
666
- if($fvm_license != false && mb_strlen($fvm_license, 'UTF-8') == 32) {
667
- ?>
668
-
669
- <form method="post" action="options.php">
670
- <?php settings_fields('fvm-group-pro'); do_settings_sections('fvm-group-pro'); ?>
671
-
672
- <div style="height: 20px;"></div>
673
- <h2 class="title">Extra Optimization</h2>
674
- <p class="fvm-bold-green">These options are available for the professional version only.<br />
675
- When deferring all generated css files, you must enqueue any inline css code that was supposed to load after the generated files.</p>
676
-
677
-
678
- <table class="form-table fvm-settings">
679
- <tbody>
680
-
681
- <tr>
682
- <th scope="row">Extra CSS Options</th>
683
- <td><fieldset><legend class="screen-reader-text"><span>Extra CSS Options</span></legend>
684
- <label for="fastvelocity_min_send_css_to_footer">
685
- <input name="fastvelocity_min_send_css_to_footer" type="checkbox" id="fastvelocity_min_send_css_to_footer" value="1" <?php echo checked(1 == get_option('fastvelocity_min_send_css_to_footer'), true, false); ?>>
686
- Async CSS with LoadCSS<span class="note-info">[ If selected, you will need a Critical Path CSS to Optimize CSS Delivery ]</span></label>
687
- <br />
688
- <label for="fastvelocity_min_critical_css_tester">
689
- <input name="fastvelocity_min_critical_css_tester" type="checkbox" id="fastvelocity_min_critical_css_tester" value="1" <?php echo checked(1 == get_option('fastvelocity_min_critical_css_tester'), true, false); ?>>
690
- Critical Path Tester<span class="note-info">[ If selected, only the critical path code will be shown and no css files will be enqueued ]</span></label>
691
- </fieldset>
692
- </td>
693
- </tr>
694
-
695
- <tr>
696
- <th scope="row">Global Critical CSS</th>
697
- <td>
698
- <p>
699
- <textarea name="fastvelocity_min_critical_path_css" rows="20" cols="50" id="fastvelocity_min_critical_path_css" class="large-text code" placeholder="your css code here"><?php echo get_option('fastvelocity_min_critical_path_css'); ?></textarea>
700
- </p>
701
- <p class="description">[ Please minify your CSS code manually and insert your Global Critical CSS here ]</p>
702
- </td>
703
- </tr>
704
-
705
-
706
- <tr>
707
- <th scope="row">Gulp Options</th>
708
- <td><fieldset>
709
- <label for="fastvelocity_min_generate_gulp_files">
710
- <input name="fastvelocity_min_generate_gulp_files" type="checkbox" id="fastvelocity_min_generate_gulp_files" value="1" <?php echo checked(1 == get_option('fastvelocity_min_generate_gulp_files'), true, false); ?>>
711
- Generate gulp-uncss files<span class="note-info">[ If selected, it will try to generate one gulp-uncss per pageview ]</span></label>
712
- </fieldset>
713
- </td>
714
- </tr>
715
-
716
- <tr>
717
- <th scope="row">Gulp Directory</th>
718
- <td>
719
- <label for="fastvelocity_min_generate_gulp_path">
720
- <input name="fastvelocity_min_generate_gulp_path" type="text" id="fastvelocity_min_generate_gulp_path" value="<?php echo get_option('fastvelocity_min_generate_gulp_path'); ?>" class="regular-text code">
721
- <p class="description">The absolute path to your local "Gulp" working directory</p>
722
- </td>
723
- </tr>
724
-
725
-
726
- </tbody></table>
727
-
728
- <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
729
- </form>
730
-
731
- <?php
732
- } else {
733
-
734
- ?>
735
-
736
- <form method="post" action="options.php">
737
- <?php settings_fields('fvm-group-license'); do_settings_sections('fvm-group-license'); ?>
738
-
739
- <div style="height: 20px;"></div>
740
- <h2 class="title">Extra Optimization</h2>
741
- <p class="fvm-bold-green">These options are available for the professional version only.</p>
742
-
743
- <table class="form-table fvm-settings">
744
- <tbody>
745
-
746
- <tr>
747
- <th scope="row">License Code</th>
748
- <td>
749
- <input name="fastvelocity_min_license_code" type="text" id="fastvelocity_min_license_code" value="<?php echo get_option('fastvelocity_min_license_code'); ?>" class="regular-text">
750
- <p class="description">Please insert the license code that has been provided.</p>
751
- </td>
752
- </tr>
753
-
754
- </tbody></table>
755
-
756
- <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
757
- </form>
758
-
759
- <?php
760
- }
761
- }
762
- ?>
763
-
764
-
765
- <?php
766
- if( $active_tab == 'server' ) {
767
- fvm_get_generalinfo();
768
- }
769
- ?>
770
-
771
- <?php if( $active_tab == 'help' ) { ?>
772
-
773
- <div class="wrap" id="fastvelocity-min">
774
- <div id="poststuff">
775
- <div id="fastvelocity_min_processed" class="postbox-container">
776
- <div class="meta-box-sortables ui-sortable">
777
-
778
-
779
-
780
-
781
- <div class="postbox" id="tab-info">
782
- <h3 class="hndle"><span>Frequently Asked Questions</span></h3>
783
- <div class="inside"><? echo fastvelocity_min_readme($plugindir.'readme.txt'); ?></div>
784
- </div>
785
-
786
- </div>
787
- </div>
788
- </div>
789
- </div>
790
- <?php } ?>
791
-
792
-
793
-
794
- </div>
795
-
796
- <div class="clear"></div>
797
-
798
- <?php
799
- }
800
-
801
-
802
- ###########################################
803
- # process header javascript ###############
804
- ###########################################
805
- function fastvelocity_min_merge_header_scripts() {
806
- global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery;
807
- if(!is_object($wp_scripts)) { return false; }
808
- $scripts = wp_clone($wp_scripts);
809
- $scripts->all_deps($scripts->queue);
810
- $ctime = get_option('fvm-last-cache-update', '0');
811
- $header = array();
812
-
813
- # mark as done (as we go)
814
- $done = $scripts->done;
815
-
816
- # add defaults to ignore list
817
- $ignore = fastvelocity_default_ignore($ignore);
818
-
819
- # get groups of handles
820
- foreach( $scripts->to_do as $handle ) :
821
-
822
- # is it a footer script?
823
- $is_footer = 0; if (isset($wp_scripts->registered[$handle]->extra["group"]) || isset($wp_scripts->registered[$handle]->args)) { $is_footer = 1; }
824
-
825
- # skip footer scripts for now
826
- if($is_footer != 1) {
827
-
828
- # get full url
829
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
830
-
831
- # IE only files don't increment things
832
- $ieonly = fastvelocity_ie_blacklist($hurl);
833
- if($ieonly == true) { continue; }
834
-
835
- # skip ignore list, scripts with conditionals, external scripts
836
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
837
-
838
- # process
839
- if(isset($header[count($header)-1]['handle']) || count($header) == 0) {
840
- array_push($header, array('handles'=>array()));
841
- }
842
-
843
- # push it to the array
844
- array_push($header[count($header)-1]['handles'], $handle);
845
-
846
- # external and ignored scripts
847
- } else {
848
- array_push($header, array('handle'=>$handle));
849
- }
850
-
851
- # make sure that the scripts skipped here, show up in the footer
852
- } else {
853
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
854
- wp_enqueue_script($handle, $hurl, array(), null, true);
855
- }
856
- endforeach;
857
-
858
-
859
- # loop through header scripts and merge
860
- for($i=0,$l=count($header);$i<$l;$i++) {
861
- if(!isset($header[$i]['handle'])) {
862
-
863
- # static cache file info + done
864
- $done = array_merge($done, $header[$i]['handles']);
865
- $hash = 'header-'.hash('adler32',implode('',$header[$i]['handles']));
866
-
867
- # create cache files and urls
868
- $file = $cachedir.'/'.$hash.'-'.$ctime.'.min.js';
869
- $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'-'.$ctime.'.min.js');
870
-
871
- # generate a new cache file
872
- if (!file_exists($file)) {
873
-
874
- # code and log initialization
875
- $log = '';
876
- $code = '';
877
-
878
- # minify and write to file
879
- foreach($header[$i]['handles'] as $handle) :
880
- if(!empty($wp_scripts->registered[$handle]->src)) {
881
-
882
- # get hurl per handle
883
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
884
- $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
885
-
886
- # get css from hurl, if available and valid
887
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
888
- $newcode = false; $newcode = get_transient($tkey);
889
- if ( $newcode === false) {
890
- $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js');
891
- if(is_array($res)) {
892
- $newcode = $res['code'];
893
- $newlog = $res['log'];
894
- }
895
- } else {
896
- $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
897
- }
898
-
899
- # append
900
- if($newcode !== false) {
901
- $code.= $newcode;
902
- $log.= $newlog;
903
- }
904
-
905
- # consider dependencies on handles with an empty src
906
- } else {
907
- wp_dequeue_script($handle); wp_enqueue_script($handle);
908
- }
909
- endforeach;
910
-
911
- # prepare log
912
- $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
913
-
914
- # generate cache, write log
915
- file_put_contents($file.'.txt', $log);
916
- file_put_contents($file, $code);
917
- file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
918
- }
919
-
920
- # register minified file
921
- wp_register_script("fvm-header-$i", $file_url, array(), null, false);
922
-
923
- # add all extra data from wp_localize_script
924
- $data = array();
925
- foreach($header[$i]['handles'] as $handle) {
926
- if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
927
- }
928
- if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode("\n", $data); }
929
-
930
- # enqueue file
931
- wp_enqueue_script("fvm-header-$i");
932
-
933
- # other scripts need to be requeued for the order of files to be kept
934
- } else {
935
- wp_dequeue_script($header[$i]['handle']); wp_enqueue_script($header[$i]['handle']);
936
- }
937
- }
938
-
939
- # remove from queue
940
- $wp_scripts->done = $done;
941
- }
942
- ###########################################
943
-
944
-
945
-
946
- ###########################################
947
- # process js in the footer ################
948
- ###########################################
949
- function fastvelocity_min_merge_footer_scripts() {
950
- global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery;
951
- if(!is_object($wp_scripts)) { return false; }
952
- $ctime = get_option('fvm-last-cache-update', '0');
953
- $scripts = wp_clone($wp_scripts);
954
- $scripts->all_deps($scripts->queue);
955
- $footer = array();
956
-
957
- # mark as done (as we go)
958
- $done = $scripts->done;
959
-
960
- # add defaults to ignore list
961
- $ignore = fastvelocity_default_ignore($ignore);
962
-
963
-
964
- # get groups of handles
965
- foreach( $scripts->to_do as $handle ) :
966
-
967
- # get full url
968
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
969
-
970
- # IE only files don't increment things
971
- $ieonly = fastvelocity_ie_blacklist($hurl);
972
- if($ieonly == true) { continue; }
973
-
974
- # skip ignore list, scripts with conditionals, external scripts
975
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
976
-
977
- # process
978
- if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0) {
979
- array_push($footer, array('handles'=>array()));
980
- }
981
-
982
- # push it to the array
983
- array_push($footer[count($footer)-1]['handles'], $handle);
984
-
985
- # external and ignored scripts
986
- } else {
987
- array_push($footer, array('handle'=>$handle));
988
- }
989
- endforeach;
990
-
991
- # loop through footer scripts and merge
992
- for($i=0,$l=count($footer);$i<$l;$i++) {
993
- if(!isset($footer[$i]['handle'])) {
994
-
995
- # static cache file info + done
996
- $done = array_merge($done, $footer[$i]['handles']);
997
- $hash = 'footer-'.hash('adler32',implode('',$footer[$i]['handles']));
998
-
999
- # create cache files and urls
1000
- $file = $cachedir.'/'.$hash.'-'.$ctime.'.min.js';
1001
- $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'-'.$ctime.'.min.js');
1002
-
1003
- # generate a new cache file
1004
- if (!file_exists($file)) {
1005
-
1006
- # code and log initialization
1007
- $log = '';
1008
- $code = '';
1009
-
1010
- # minify and write to file
1011
- foreach($footer[$i]['handles'] as $handle) :
1012
- if(!empty($wp_scripts->registered[$handle]->src)) {
1013
-
1014
- # get hurl per handle
1015
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1016
- $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1017
-
1018
- # get css from hurl, if available and valid
1019
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1020
- $newcode = false; $newcode = get_transient($tkey);
1021
- if ( $newcode === false) {
1022
- $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js');
1023
- if(is_array($res)) {
1024
- $newcode = $res['code'];
1025
- $newlog = $res['log'];
1026
- }
1027
- } else {
1028
- $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1029
- }
1030
-
1031
- # append
1032
- if($newcode !== false) {
1033
- $code.= $newcode;
1034
- $log.= $newlog;
1035
- }
1036
-
1037
- # consider dependencies on handles with an empty src
1038
- } else {
1039
- wp_dequeue_script($handle); wp_enqueue_script($handle);
1040
- }
1041
- endforeach;
1042
-
1043
- # prepare log
1044
- $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1045
-
1046
- # generate cache, write log
1047
- file_put_contents($file.'.txt', $log);
1048
- file_put_contents($file, $code);
1049
- file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1050
- }
1051
-
1052
- # register minified file
1053
- wp_register_script("fvm-footer-$i", $file_url, array(), null, false);
1054
-
1055
- # add all extra data from wp_localize_script
1056
- $data = array();
1057
- foreach($footer[$i]['handles'] as $handle) {
1058
- if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1059
- }
1060
- if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode("\n", $data); }
1061
-
1062
- # enqueue file
1063
- wp_enqueue_script("fvm-footer-$i");
1064
-
1065
- # other scripts need to be requeued for the order of files to be kept
1066
- } else {
1067
- wp_dequeue_script($footer[$i]['handle']); wp_enqueue_script($footer[$i]['handle']);
1068
- }
1069
- }
1070
-
1071
- # remove from queue
1072
- $wp_scripts->done = $done;
1073
- }
1074
- ##############################
1075
-
1076
-
1077
-
1078
- ###########################################
1079
- # enable defer for JavaScript (WP 4.1 and above) and remove query strings for ignored files
1080
- ###########################################
1081
- function fastvelocity_min_defer_js($tag, $handle, $src) {
1082
- global $ignore, $enable_defer_js, $defer_for_pagespeed, $wp_domain, $exclude_defer_login;
1083
-
1084
- # no query strings
1085
- if (stripos($src, '?ver') !== false) {
1086
- $srcf = stristr($src, '?ver', true);
1087
- $tag = str_ireplace($src, $srcf, $tag);
1088
- $src = $srcf;
1089
- }
1090
-
1091
- # should we exclude defer on the login page?
1092
- if($exclude_defer_login == true && stripos($_SERVER["SCRIPT_NAME"], strrchr(wp_login_url(), '/')) !== false){ return $tag; }
1093
-
1094
- # reprocess the ignore list to remove the /fvm/cache/ from the list (else won't defer)
1095
- if(is_array($ignore)) { $nignore = array(); foreach ($ignore as $i) { if($i != '/fvm/cache/') { $nignore[] = $i; } } }
1096
-
1097
- # when to defer, order matters
1098
- $defer = 0; if($enable_defer_js == true) { $defer = 1; }
1099
- if (fastvelocity_min_in_arrayi($src, $nignore)) { $defer = 0; }
1100
-
1101
- # get available nodes and add create with defer tag (if not async)
1102
- $dom = new DOMDocument();
1103
- libxml_use_internal_errors(true);
1104
- @$dom->loadHTML($tag);
1105
- $nodes = $dom->getElementsByTagName('script');
1106
- $tagdefer = '';
1107
- if ($nodes->length != 0) {
1108
- $node = $dom->getElementsByTagName('script')->item(0);
1109
- if (!$node->hasAttribute('async')) { $node->setAttribute('defer','defer'); };
1110
- $tagdefer = $dom->saveHTML($node);
1111
- }
1112
-
1113
- # skip the nignore list by default, defer the rest
1114
- if ($defer == 0) {
1115
-
1116
- # no defer
1117
- if ($defer_for_pagespeed != true) { return $tag; } else {
1118
-
1119
- # return if external script url https://www.chromestatus.com/feature/5718547946799104
1120
- if (stripos($src, $wp_domain) === false) { return $tag; }
1121
-
1122
- # print code or return
1123
- if(!empty($tagdefer)) {
1124
- $deferinsights = '<script type="text/javascript">if(navigator.userAgent.match(/speed|gtmetrix|x11.*firefox\/53|x11.*chrome\/39/i)){document.write('.json_encode($tagdefer).');}else{document.write('.json_encode($tag).');}</script>';
1125
- return preg_replace('#<script(.*?)>(.*?)</script>#is', $deferinsights, $tag);
1126
- }
1127
-
1128
- return $tag;
1129
- }
1130
-
1131
- # normal defer enabled
1132
- } else { return $tagdefer; }
1133
- }
1134
- ###########################################
1135
-
1136
-
1137
-
1138
-
1139
- ###########################################
1140
- # process header css ######################
1141
- ###########################################
1142
- function fastvelocity_min_merge_header_css() {
1143
- global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_css, $force_inline_googlefonts, $send_css_to_footer, $critical_path_css, $critical_css_tester;
1144
- if(!is_object($wp_styles)) { return false; }
1145
- $ctime = get_option('fvm-last-cache-update', '0');
1146
- $styles = wp_clone($wp_styles);
1147
- $styles->all_deps($styles->queue);
1148
- $done = $styles->done;
1149
- $header = array();
1150
- $google_fonts = array();
1151
- $process = array();
1152
- $inline_css = array();
1153
-
1154
- # add defaults to ignore list
1155
- $ignore = fastvelocity_default_ignore($ignore);
1156
-
1157
-
1158
- # get list of handles to process, dequeue duplicate css urls and keep empty source handles (for dependencies)
1159
- $uniq = array(); $gfonts = array();
1160
- foreach( $styles->to_do as $handle):
1161
-
1162
- # conditionals
1163
- $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
1164
- $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
1165
- }
1166
-
1167
- # mediatype
1168
- $mediatype = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all'; # such as all, print, mobile, etc
1169
- if ($mediatype == 'screen' || $mediatype == 'screen, print') { $mediatype = 'all'; }
1170
-
1171
- # full url or empty
1172
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1173
-
1174
- # mark duplicates as done and remove from the queue
1175
- if(!empty($hurl)) {
1176
- $key = hash('adler32', $hurl);
1177
- if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
1178
- }
1179
-
1180
- # array of info to save
1181
- $arr = array('handle'=>$handle, 'url'=>$hurl, 'conditional'=>$conditional, 'mediatype'=>$mediatype);
1182
-
1183
- # google fonts to the top (collect and skip process array)
1184
- if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1185
- if(!$skip_google_fonts) { $google_fonts[$handle] = $hurl; } else { wp_enqueue_style($handle); } # skip google fonts optimization?
1186
- continue;
1187
- }
1188
-
1189
- # all else
1190
- $process[$handle] = $arr;
1191
-
1192
- endforeach;
1193
-
1194
-
1195
- # concat google fonts, if enabled
1196
- if(!$skip_google_fonts && count($google_fonts) > 0) {
1197
- $concat_google_fonts = fastvelocity_min_concatenate_google_fonts($google_fonts);
1198
- foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1199
- if($force_inline_googlefonts == false) {
1200
- wp_enqueue_style('header-fvm-fonts', fvm_get_protocol($concat_google_fonts), array(), null, 'all');
1201
- } else {
1202
-
1203
- # google fonts download and inlining, ignore logs
1204
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1205
- $newcode = false; $newcode = get_transient($tkey);
1206
- if ( $newcode === false) {
1207
- $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_minification, 'css');
1208
- if(is_array($res)) { $newcode = $res['code']; }
1209
- }
1210
-
1211
- # inline css or fail
1212
- if($newcode !== false) {
1213
- echo '<style type="text/css" media="all">'.$newcode.'</style>'."\n";
1214
- } else {
1215
- echo "<!-- GOOGLE FONTS REQUEST FAILED for $concat_google_fonts -->\n"; # log if failed
1216
- }
1217
- }
1218
- }
1219
-
1220
-
1221
-
1222
-
1223
- # get groups of handles
1224
- foreach( $styles->to_do as $handle ) :
1225
-
1226
- # skip already processed google fonts and empty dependencies
1227
- if(isset($google_fonts[$handle])) { continue; } # skip google fonts
1228
- if(empty($wp_styles->registered[$handle]->src)) { continue; } # skip empty src
1229
- if (fastvelocity_min_in_arrayi($handle, $done)) { continue; } # skip if marked as done before
1230
- if (!isset($process[$handle])) { continue; } # skip if not on our unique process list
1231
-
1232
- # get full url
1233
- $hurl = $process[$handle]['url'];
1234
- $conditional = $process[$handle]['conditional'];
1235
- $mediatype = $process[$handle]['mediatype'];
1236
-
1237
- # IE only files don't increment things
1238
- $ieonly = fastvelocity_ie_blacklist($hurl);
1239
- if($ieonly == true) { continue; }
1240
-
1241
- # skip ignore list, conditional css, external css
1242
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1243
-
1244
- # colect inline css for this handle
1245
- if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
1246
- $inline_css[$handle] = fastvelocity_min_minify_css_string(implode('', $wp_styles->registered[$handle]->extra['after'])); # save
1247
- $wp_styles->registered[$handle]->extra['after'] = null; # dequeue
1248
- }
1249
-
1250
- # process
1251
- if(isset($header[count($header)-1]['handle']) || count($header) == 0 || $header[count($header)-1]['media'] != $mediatype) {
1252
- array_push($header, array('handles'=>array(), 'media'=>$mediatype));
1253
- }
1254
-
1255
- # push it to the array
1256
- array_push($header[count($header)-1]['handles'], $handle);
1257
-
1258
- # collect generated file urls, except print
1259
- if ($mediatype != 'print') { $GLOBALS['used_css_files'][] = $hurl; }
1260
-
1261
- # external and ignored css
1262
- } else {
1263
-
1264
- # collect generated file urls for gulp, except print and conditionals
1265
- if ($mediatype != 'print' && !isset($conditional)) { $GLOBALS['used_css_files'][] = $hurl; }
1266
-
1267
- # normal enqueuing
1268
- array_push($header, array('handle'=>$handle));
1269
- }
1270
- endforeach;
1271
-
1272
-
1273
- # reorder CSS by mediatypes
1274
- if(!$skip_cssorder) {
1275
- if(count($header) > 0) {
1276
-
1277
- # get unique mediatypes
1278
- $allmedia = array();
1279
- foreach($header as $array) {
1280
- if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1281
- }
1282
-
1283
- # extract handles by mediatype
1284
- $grouphandles = array();
1285
- foreach ($allmedia as $md=>$var) {
1286
- foreach($header as $array) {
1287
- if (isset($array['media']) && $array['media'] == $md) {
1288
- foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1289
- }
1290
- }
1291
- }
1292
-
1293
- # reset and reorder header by mediatypes
1294
- $newheader = array();
1295
- foreach ($allmedia as $md=>$var) { $newheader[] = array('handles' => $grouphandles[$md], 'media'=>$md); }
1296
- if(count($newheader) > 0) { $header = $newheader; }
1297
- }
1298
- }
1299
-
1300
-
1301
- # critical path
1302
- if(!empty($critical_path_css) && $critical_path_css != false) {
1303
- if($send_css_to_footer != false) {
1304
- echo '<style id="critical-path-global" type="text/css" media="all">'.$critical_path_css.'</style>'."\n";
1305
- }
1306
- }
1307
-
1308
-
1309
- # loop through header css and merge
1310
- for($i=0,$l=count($header);$i<$l;$i++) {
1311
- if(!isset($header[$i]['handle'])) {
1312
-
1313
- # get has for the inline css in this group
1314
- $inline_css_group = array();
1315
- foreach($header[$i]['handles'] as $h) { if(isset($inline_css[$h]) && !empty($inline_css[$h])) { $inline_css_group[] = $inline_css[$h]; } }
1316
- $inline_css_hash = md5(implode('',$inline_css_group));
1317
-
1318
- # static cache file info + done
1319
- $done = array_merge($done, $header[$i]['handles']);
1320
- $hash = 'header-'.hash('adler32',implode('',$header[$i]['handles']).$inline_css_hash);
1321
-
1322
- # create cache files and urls
1323
- $file = $cachedir.'/'.$hash.'-'.$ctime.'.min.css';
1324
- $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'-'.$ctime.'.min.css');
1325
-
1326
- # generate a new cache file
1327
- if (!file_exists($file)) {
1328
-
1329
- # code and log initialization
1330
- $log = '';
1331
- $code = '';
1332
-
1333
- # minify and write to file
1334
- foreach($header[$i]['handles'] as $handle) :
1335
- if(!empty($wp_styles->registered[$handle]->src)) {
1336
-
1337
- # get hurl per handle
1338
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1339
- $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1340
-
1341
- # get css from hurl, if available and valid
1342
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1343
- $newcode = false; $newcode = get_transient($tkey);
1344
- if ( $newcode === false) {
1345
- $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css');
1346
- if(is_array($res)) {
1347
- $newcode = $res['code'];
1348
- $newlog = $res['log'];
1349
- }
1350
- } else {
1351
- $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1352
- }
1353
-
1354
- # append
1355
- if($newcode !== false) {
1356
- $code.= $newcode;
1357
- if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) { $code.= $inline_css[$handle]; } # add inline css on the fly
1358
- $log.= $newlog;
1359
- }
1360
-
1361
- # consider dependencies on handles with an empty src
1362
- } else {
1363
- wp_dequeue_script($handle); wp_enqueue_script($handle);
1364
- }
1365
- endforeach;
1366
-
1367
- # prepare log
1368
- $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1369
-
1370
- # generate cache, write log
1371
- file_put_contents($file.'.txt', $log);
1372
- file_put_contents($file, $code);
1373
- file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1374
-
1375
- }
1376
-
1377
- # register and enqueue minified file, consider excluding of mediatype "print" and inline css
1378
- if ($remove_print_mediatypes != 1 || ($remove_print_mediatypes == 1 && $header[$i]['media'] != 'print')) {
1379
- if($force_inline_css != false) {
1380
- echo '<style type="text/css" media="'.$header[$i]['media'].'">'.file_get_contents($file).'</style>';
1381
- } else {
1382
-
1383
- # move CSS to footer ?
1384
- if($send_css_to_footer != false) {
1385
- if($critical_css_tester != true) {
1386
- echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$header[$i]['media'].'" onload="this.rel=\'stylesheet\'">';
1387
- echo '<noscript><link rel="stylesheet" type="text/css" media="'.$header[$i]['media'].'" href="'.$file_url.'"></noscript>';
1388
- echo '<!--[if IE]><link rel="stylesheet" type="text/css" media="'.$header[$i]['media'].'" href="'.$file_url.'"><![endif]-->';
1389
- }
1390
- } else {
1391
-
1392
- # default
1393
- wp_register_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
1394
- wp_enqueue_style("fvm-header-$i");
1395
-
1396
- }
1397
- }
1398
- }
1399
-
1400
- # other css need to be requeued for the order of files to be kept
1401
- } else {
1402
- wp_dequeue_style($header[$i]['handle']); wp_enqueue_style($header[$i]['handle']);
1403
- }
1404
- }
1405
-
1406
- # remove from queue
1407
- $wp_styles->done = $done;
1408
-
1409
- }
1410
- ###########################################
1411
-
1412
-
1413
- ###########################################
1414
- # process css in the footer ###############
1415
- ###########################################
1416
- function fastvelocity_min_merge_footer_css() {
1417
- global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_css_footer, $force_inline_googlefonts, $send_css_to_footer, $critical_css_tester;
1418
- if(!is_object($wp_styles)) { return false; }
1419
- $ctime = get_option('fvm-last-cache-update', '0');
1420
- $styles = wp_clone($wp_styles);
1421
- $styles->all_deps($styles->queue);
1422
- $done = $styles->done;
1423
- $footer = array();
1424
- $google_fonts = array();
1425
- $inline_css = array();
1426
-
1427
- # add defaults to ignore list
1428
- $ignore = fastvelocity_default_ignore($ignore);
1429
-
1430
-
1431
- # google fonts to the top
1432
- foreach( $styles->to_do as $handle ) :
1433
- # dequeue and get a list of google fonts, or requeue external
1434
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1435
- if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1436
- wp_dequeue_style($handle);
1437
- if(!$skip_google_fonts) { $google_fonts[$handle] = $hurl; } else { wp_enqueue_style($handle); } # skip google fonts optimization?
1438
- } else {
1439
- wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
1440
- }
1441
- endforeach;
1442
-
1443
-
1444
- # concat google fonts, if enabled
1445
- if(!$skip_google_fonts && count($google_fonts) > 0) {
1446
- $concat_google_fonts = fastvelocity_min_concatenate_google_fonts($google_fonts);
1447
- foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1448
- if($force_inline_googlefonts == false) {
1449
- wp_enqueue_style('footer-fvm-fonts', fvm_get_protocol($concat_google_fonts), array(), null, 'all');
1450
- } else {
1451
-
1452
- # google fonts download and inlining, ignore logs
1453
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1454
- $newcode = false; $newcode = get_transient($tkey);
1455
- if ( $newcode === false) {
1456
- $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
1457
- if(is_array($res)) { $newcode = $res['code']; }
1458
- }
1459
-
1460
- # inline css or fail
1461
- if($newcode !== false) {
1462
- echo '<style type="text/css" media="all">'.$newcode.'</style>';
1463
- } else {
1464
- echo "<!-- GOOGLE FONTS REQUEST FAILED for $concat_google_fonts -->\n"; # log if failed
1465
- }
1466
- }
1467
- }
1468
-
1469
-
1470
- # get groups of handles
1471
- foreach( $styles->to_do as $handle ) :
1472
-
1473
- # skip already processed google fonts
1474
- if(isset($google_fonts[$handle])) { continue; }
1475
-
1476
- # get full url
1477
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1478
-
1479
- # media type
1480
- $media = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
1481
-
1482
- # IE only files don't increment things
1483
- $ieonly = fastvelocity_ie_blacklist($hurl);
1484
- if($ieonly == true) { continue; }
1485
-
1486
- # conditionals
1487
- $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
1488
- $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
1489
- }
1490
-
1491
- # skip ignore list, conditional css, external css
1492
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1493
-
1494
- # colect inline css for this handle
1495
- if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
1496
- $inline_css[$handle] = fastvelocity_min_minify_css_string(implode('', $wp_styles->registered[$handle]->extra['after'])); # save
1497
- $wp_styles->registered[$handle]->extra['after'] = null; # dequeue
1498
- }
1499
-
1500
- # process
1501
- if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0 || $footer[count($footer)-1]['media'] != $wp_styles->registered[$handle]->args) {
1502
- array_push($footer, array('handles'=>array(),'media'=>$media));
1503
- }
1504
-
1505
- # push it to the array get latest modified time
1506
- array_push($footer[count($footer)-1]['handles'], $handle);
1507
-
1508
- # collect generated file urls for gulp, except print
1509
- if ($media != 'print') { $GLOBALS['used_css_files'][] = $hurl; }
1510
-
1511
- # external and ignored css
1512
- } else {
1513
-
1514
- # collect generated file urls for gulp, except print and conditionals
1515
- if ($media != 'print' && !isset($conditional)) { $GLOBALS['used_css_files'][] = $hurl; }
1516
-
1517
- # normal enqueueing
1518
- array_push($footer, array('handle'=>$handle));
1519
- }
1520
- endforeach;
1521
-
1522
-
1523
- # reorder CSS by mediatypes
1524
- if(!$skip_cssorder) {
1525
- if(count($footer) > 0) {
1526
-
1527
- # get unique mediatypes
1528
- $allmedia = array();
1529
- foreach($footer as $key=>$array) {
1530
- if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1531
- }
1532
-
1533
- # extract handles by mediatype
1534
- $grouphandles = array();
1535
- foreach ($allmedia as $md=>$var) {
1536
- foreach($footer as $array) {
1537
- if (isset($array['media']) && $array['media'] == $md) {
1538
- foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1539
- }
1540
- }
1541
- }
1542
-
1543
- # reset and reorder footer by mediatypes
1544
- $newfooter = array();
1545
- foreach ($allmedia as $md=>$var) { $newfooter[] = array('handles' => $grouphandles[$md], 'media'=>$md); }
1546
- if(count($newfooter) > 0) { $footer = $newfooter; }
1547
- }
1548
- }
1549
-
1550
- # loop through footer css and merge
1551
- for($i=0,$l=count($footer);$i<$l;$i++) {
1552
- if(!isset($footer[$i]['handle'])) {
1553
-
1554
- # get has for the inline css in this group
1555
- $inline_css_group = array();
1556
- foreach($footer[$i]['handles'] as $h) { if(isset($inline_css[$h]) && !empty($inline_css[$h])) { $inline_css_group[] = $inline_css[$h]; } }
1557
- $inline_css_hash = md5(implode('',$inline_css_group));
1558
-
1559
- # static cache file info + done
1560
- $done = array_merge($done, $footer[$i]['handles']);
1561
- $hash = 'footer-'.hash('adler32',implode('',$footer[$i]['handles']).$inline_css_hash);
1562
-
1563
- # create cache files and urls
1564
- $file = $cachedir.'/'.$hash.'-'.$ctime.'.min.css';
1565
- $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'-'.$ctime.'.min.css');
1566
-
1567
- # generate a new cache file
1568
- if (!file_exists($file)) {
1569
-
1570
- # code and log initialization
1571
- $log = '';
1572
- $code = '';
1573
-
1574
- # minify and write to file
1575
- foreach($footer[$i]['handles'] as $handle) :
1576
- if(!empty($wp_styles->registered[$handle]->src)) {
1577
-
1578
- # get hurl per handle
1579
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1580
- $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1581
-
1582
- # get css from hurl, if available and valid
1583
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1584
- $newcode = false; $newcode = get_transient($tkey);
1585
- if ( $newcode === false) {
1586
- $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css');
1587
- if(is_array($res)) {
1588
- $newcode = $res['code'];
1589
- $newlog = $res['log'];
1590
- }
1591
- } else {
1592
- $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1593
- }
1594
-
1595
- # append
1596
- if($newcode !== false) {
1597
- $code.= $newcode;
1598
- if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) { $code.= $inline_css[$handle]; } # add inline css on the fly
1599
- $log.= $newlog;
1600
- }
1601
-
1602
- # consider dependencies on handles with an empty src
1603
- } else {
1604
- wp_dequeue_script($handle); wp_enqueue_script($handle);
1605
- }
1606
- endforeach;
1607
-
1608
- # prepare log
1609
- $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1610
-
1611
- # generate cache, add inline css, write log
1612
- file_put_contents($file.'.txt', $log);
1613
- file_put_contents($file, $code); # preserve style tags
1614
- file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1615
-
1616
- }
1617
-
1618
- # register and enqueue minified file, consider excluding of mediatype "print" and inline css
1619
- if ($remove_print_mediatypes != 1 || ($remove_print_mediatypes == 1 && $footer[$i]['media'] != 'print')) {
1620
- if($force_inline_css_footer != false) {
1621
- echo '<style type="text/css" media="'.$footer[$i]['media'].'">'.file_get_contents($file).'</style>';
1622
- } else {
1623
-
1624
- # move CSS to footer
1625
- if($send_css_to_footer != false) {
1626
-
1627
- if($critical_css_tester != true) {
1628
- echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$footer[$i]['media'].'" onload="this.rel=\'stylesheet\'">';
1629
- echo '<noscript><link rel="stylesheet" type="text/css" media="'.$footer[$i]['media'].'" href="'.$file_url.'"></noscript>';
1630
- echo '<!--[if IE]><link rel="stylesheet" type="text/css" media="'.$footer[$i]['media'].'" href="'.$file_url.'"><![endif]-->';
1631
- }
1632
-
1633
- } else {
1634
-
1635
- # default
1636
- wp_register_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
1637
- wp_enqueue_style("fvm-footer-$i");
1638
-
1639
- }
1640
- }
1641
- }
1642
-
1643
- # other css need to be requeued for the order of files to be kept
1644
- } else {
1645
- wp_dequeue_style($footer[$i]['handle']); wp_enqueue_style($footer[$i]['handle']);
1646
- }
1647
- }
1648
-
1649
- # remove from queue
1650
- $wp_styles->done = $done;
1651
- }
1652
- ###########################################
1653
-
1654
-
1655
-
1656
-
1657
- ###########################################
1658
- # defer CSS globally from the header (order matters)
1659
- ###########################################
1660
- function fvm_movecss_to_footer_header() {
1661
- global $send_css_to_footer;
1662
- if($send_css_to_footer != false) {
1663
-
1664
- # echo LoadCSS scripts
1665
- echo '<script>
1666
- /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
1667
- !function(a){"use strict";var b=function(b,c,d){function e(a){return h.body?a():void setTimeout(function(){e(a)})}function f(){i.addEventListener&&i.removeEventListener("load",f),i.media=d||"all"}var g,h=a.document,i=h.createElement("link");if(c)g=c;else{var j=(h.body||h.getElementsByTagName("head")[0]).childNodes;g=j[j.length-1]}var k=h.styleSheets;i.rel="stylesheet",i.href=b,i.media="only x",e(function(){g.parentNode.insertBefore(i,c?g:g.nextSibling)});var l=function(a){for(var b=i.href,c=k.length;c--;)if(k[c].href===b)return a();setTimeout(function(){l(a)})};return i.addEventListener&&i.addEventListener("load",f),i.onloadcssdefined=l,l(f),i};"undefined"!=typeof exports?exports.loadCSS=b:a.loadCSS=b}("undefined"!=typeof global?global:this);
1668
- /*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
1669
- !function(a){if(a.loadCSS){var b=loadCSS.relpreload={};if(b.support=function(){try{return a.document.createElement("link").relList.supports("preload")}catch(b){return!1}},b.poly=function(){for(var b=a.document.getElementsByTagName("link"),c=0;c<b.length;c++){var d=b[c];"preload"===d.rel&&"style"===d.getAttribute("as")&&(a.loadCSS(d.href,d,d.getAttribute("media")),d.rel=null)}},!b.support()){b.poly();var c=a.setInterval(b.poly,300);a.addEventListener&&a.addEventListener("load",function(){b.poly(),a.clearInterval(c)}),a.attachEvent&&a.attachEvent("onload",function(){a.clearInterval(c)})}}}(this);
1670
- </script>';
1671
-
1672
- } }
1673
-
1674
- if (!is_admin()) { add_action('wp_head', 'fvm_movecss_to_footer_header', PHP_INT_MAX); }
1675
- ###########################################
1676
-
1677
-
1678
-
1679
- ###########################################
1680
- # generate gulp-uncss files for this page (dev only)
1681
- ###########################################
1682
- function fvm_generate_gulp_uncss() {
1683
- global $wp, $generate_gulp_files, $generate_gulp_path;
1684
-
1685
- if(isset($GLOBALS['used_css_files']) && $generate_gulp_files != false && !empty($generate_gulp_path)) {
1686
-
1687
- # some paths and urls
1688
- $currenturl = fvm_get_protocol($_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]);
1689
- $file = sanitize_title($currenturl);
1690
- $save = get_stylesheet_directory().'/criticalcss/css/'.$file.'.css';
1691
- $generate_gulp_path = rtrim(trim($generate_gulp_path), '/');
1692
- $generate_gulp_path_out = $generate_gulp_path.'/out/';
1693
- if(!is_dir($generate_gulp_path_out) && is_writable($generate_gulp_path_out)) { mkdir($generate_gulp_path_out); }
1694
- $gulpfile = "$generate_gulp_path/$file.js";
1695
-
1696
- # process
1697
- if(!file_exists($save) && !file_exists($gulpfile) && is_dir($generate_gulp_path_out)) {
1698
-
1699
- $cssfiles = json_encode($GLOBALS['used_css_files'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
1700
-
1701
- # gulp tasks
1702
- $gulptask = <<<EOF
1703
- var gulp = require('gulp');
1704
- var uncss = require('gulp-uncss');
1705
- var concat = require('gulp-concat');
1706
- var nano = require('gulp-cssnano');
1707
- var remoteSrc = require('gulp-remote-src');
1708
- gulp.task('uncss', function() {
1709
- remoteSrc($cssfiles, { base: null })
1710
- .pipe(concat('$file.css'))
1711
- .pipe(uncss({ html: ['$currenturl'] }))
1712
- .pipe(nano())
1713
- .pipe(gulp.dest('$generate_gulp_path/out/'));
1714
- });
1715
- EOF;
1716
-
1717
- # write gulp file
1718
- file_put_contents($gulpfile, $gulptask);
1719
-
1720
- }
1721
- }
1722
- }
1723
-
1724
- if (!is_admin()) { add_action('wp_footer', 'fvm_generate_gulp_uncss', PHP_INT_MAX); }
1725
-
1726
-
1727
-
1728
- ###########################################
1729
- # add preconnect and preload headers
1730
- ###########################################
1731
- function fvm_buffer_placeholder_top() {
1732
- global $preload, $preconnect;
1733
-
1734
- # defaults
1735
- $meta = array();
1736
-
1737
- # preconnect resources
1738
- # https://css-tricks.com/prefetching-preloading-prebrowsing/
1739
- if(count($preconnect) > 0) {
1740
- $a = array(); foreach ($preconnect as $b) {
1741
- if(!empty($b)) { $a[] = '<link href="'.str_ireplace(array('http://', 'https://'), '//', $b).'" rel="preconnect">'; }
1742
- }
1743
- if(count($a) > 0) { $meta[] = implode('', $a); }
1744
- }
1745
-
1746
- # preload resources (beta: homepage only)
1747
- # https://css-tricks.com/prefetching-preloading-prebrowsing/
1748
- if((is_home() || is_front_page()) && count($preload) > 0) {
1749
- $a = array();
1750
- foreach ($preload as $b) {
1751
- if(!empty($b)) {
1752
- $meta[] = '<link rel="preload" as="image" href="'.str_ireplace(array('http://', 'https://'), '//', $b).'">';
1753
- }
1754
- }
1755
- }
1756
-
1757
- # output on top
1758
- echo implode('', $meta);
1759
- }
1760
-
1761
- # remove query from static assets and process defering (if enabled)
1762
- if (!is_admin()) {
1763
- add_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
1764
- add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
1765
- }
1766
-
1767
- # enable html minification
1768
- if(!$skip_html_minification && !is_admin()) {
1769
- add_action('get_header', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
1770
- }
1771
-
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Fast Velocity Minify
4
+ Plugin URI: http://fastvelocity.com
5
+ Description: Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS and JavaScript files into groups, compressing HTML and other speed optimizations.
6
+ Author: Raul Peixoto
7
+ Author URI: http://fastvelocity.com
8
+ Version: 2.2.1
9
+ License: GPL2
10
+
11
+ ------------------------------------------------------------------------
12
+ This program is free software; you can redistribute it and/or modify
13
+ it under the terms of the GNU General Public License as published by
14
+ the Free Software Foundation; either version 2 of the License, or
15
+ (at your option) any later version.
16
+
17
+ This program is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ GNU General Public License for more details.
21
+
22
+ You should have received a copy of the GNU General Public License
23
+ along with this program; if not, write to the Free Software
24
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
+ */
26
+
27
+
28
+ # check for minimum requirements and prevent activation or disable if not fully compatible
29
+ function fvm_compat_checker() {
30
+ global $wp_version;
31
+
32
+ # defaults
33
+ $error = '';
34
+ $nwpv = implode('.', array_slice(explode('.', $wp_version), 0, 2)); # get 2 p only
35
+
36
+ # php version requirements
37
+ if (version_compare( PHP_VERSION, '5.4', '<' )) {
38
+ $error = 'Fast Velocity Minify requires PHP 5.4 or higher. You’re still on '. PHP_VERSION;
39
+ }
40
+
41
+ # php extension requirements
42
+ if (!extension_loaded('mbstring')) {
43
+ $error = 'Fast Velocity Minify requires the PHP mbstring module to be installed on the server.';
44
+ }
45
+
46
+ # wp version requirements
47
+ if ( $nwpv < '4.5' ) {
48
+ $error = 'Fast Velocity Minify requires WP 4.5 or higher. You’re still on ' . $wp_version;
49
+ }
50
+
51
+
52
+ if ((is_plugin_active(plugin_basename( __FILE__ )) && !empty($error)) || !empty($error)) {
53
+ if (isset($_GET['activate'])) { unset($_GET['activate']); }
54
+ deactivate_plugins( plugin_basename( __FILE__ ));
55
+ add_action('admin_notices', function() use ($error){
56
+ echo '<div class="notice notice-error is-dismissible"><p><strong>'.$error.'</strong></p></div>';
57
+ });
58
+ }
59
+ }
60
+ add_action('admin_init', 'fvm_compat_checker');
61
+
62
+
63
+ # get the plugin directory and include functions
64
+ $plugindir = plugin_dir_path( __FILE__ ); # with trailing slash
65
+ include($plugindir.'inc/functions.php');
66
+ include($plugindir.'inc/functions-serverinfo.php');
67
+
68
+ # get cache directories and urls
69
+ $cachepath = fvm_cachepath();
70
+ $tmpdir = $cachepath['tmpdir'];
71
+ $cachedir = $cachepath['cachedir'];
72
+ $cachedirurl = $cachepath['cachedirurl'];
73
+
74
+ # get the current wordpress installation url and path
75
+ $wp_home = site_url(); # get the current wordpress installation url
76
+ $wp_domain = trim(str_ireplace(array('http://', 'https://'), '', trim($wp_home, '/')));
77
+ $wp_home_path = ABSPATH;
78
+
79
+ # cleanup, delete any minification files older than 45 days (most probably unused files)
80
+ if ($handle = opendir($cachedir.'/')) {
81
+ while (false !== ($file = readdir($handle))) { $file = $cachedir.'/'.$file; if (is_file($file) && time() - filemtime($file) >= 86400 * 45) { unlink($file); } }
82
+ closedir($handle);
83
+ }
84
+
85
+ # default globals
86
+ $fastvelocity_min_global_js_done = array();
87
+
88
+
89
+ ###########################################
90
+ # build control panel pages ###############
91
+ ###########################################
92
+
93
+ # default options
94
+ $ignore = array(); # urls to exclude for merging and minification
95
+ $default_protocol = 'dynamic'; # use dynamic "//" protocols by default
96
+ $disable_js_merge = false; # disable JS merging? Default: false (if true, minification is also disabled)
97
+ $disable_css_merge = false; # disable CSS merging? Default: false (if true, minification is also disabled)
98
+ $disable_js_minification = false; # disable JS minification? Default: false
99
+ $disable_css_minification = false; # disable CSS minification? Default: false
100
+ $use_yui = false; # Use the YUI processor instead of PHP Minify? Default false
101
+ $remove_print_mediatypes = false; # remove CSS files of "print" mediatype
102
+ $skip_html_minification = false; # skip HTML minification? Default: false
103
+ $use_alt_html_minification = false; # use alt HTML minification? Default: false
104
+ $strip_htmlcomments = false; # whether to remove html comments on html minification
105
+ $skip_cssorder = false; # skip reordering CSS files by mediatype
106
+ $skip_google_fonts = false; # skip google fonts optimization? Default: false
107
+ $skip_emoji_removal = false; # skip removing emoji support? Default: false
108
+ $enable_defer_js = false; # Defer parsing of JavaScript? Default false
109
+ $exclude_defer_jquery = false; # Disable defer for jquery on the home
110
+ $use_google_closure = false; # Use Google closure (slower) instead of YUI processor? Default false
111
+ $use_php_minify = false; # Use PHP Minify instead of YUI or Closure? Default false
112
+ $force_inline_css = false; # Don't inline all css by default
113
+ $force_inline_css_footer = false; # Don't inline all css by default
114
+ $force_inline_googlefonts = false; # Don't inline all google fonts by default
115
+ $defer_for_pagespeed = false; # force defer for when we are being tested by pagespeed insights
116
+ $exclude_defer_login = false; # Disable defer js on the login page
117
+ $preload = array(); # urls to preload before anything else
118
+ $preconnect = array(); # domains to preconnect to
119
+ $fvm_fix_editor = false; # enable production mode by default?
120
+
121
+ # extra
122
+ $send_css_to_footer = false; # force defer for css
123
+ $critical_path_css = false; # critical path for homepage
124
+ $critical_css_tester = false; # will remove all css, except the critical path code
125
+ $generate_gulp_files = false; # will generate gulp files for gulp-uncss (spider the site first to generate the fvm cache files)
126
+ $generate_gulp_path = false; # path to working directory where gulp-uncss is installed
127
+ $used_css_files = array();
128
+
129
+ # add admin page and rewrite defaults
130
+ if(is_admin()) {
131
+ add_action('admin_menu', 'fastvelocity_min_admin_menu');
132
+ add_action('admin_enqueue_scripts', 'fastvelocity_min_load_admin_jscss');
133
+ add_action('wp_ajax_fastvelocity_min_files', 'fastvelocity_min_files_callback');
134
+ add_action('admin_init', 'fastvelocity_min_register_settings');
135
+ register_deactivation_hook( __FILE__, 'fastvelocity_min_plugin_deactivate');
136
+ } else {
137
+ # overwrite options from the database, false if not set
138
+ $ignore = array_map('trim', explode("\n", get_option('fastvelocity_min_ignore', '')));
139
+ $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
140
+ $disable_js_merge = get_option('fastvelocity_min_disable_js_merge');
141
+ $disable_css_merge = get_option('fastvelocity_min_disable_css_merge');
142
+ $disable_js_minification = get_option('fastvelocity_min_disable_js_minification');
143
+ $disable_css_minification = get_option('fastvelocity_min_disable_css_minification');
144
+ $use_yui = get_option('fastvelocity_min_use_yui');
145
+ $remove_print_mediatypes = get_option('fastvelocity_min_remove_print_mediatypes');
146
+ $skip_html_minification = get_option('fastvelocity_min_skip_html_minification');
147
+ $use_alt_html_minification = get_option('fastvelocity_min_use_alt_html_minification');
148
+ $strip_htmlcomments = get_option('fastvelocity_min_strip_htmlcomments');
149
+ $skip_cssorder = get_option('fastvelocity_min_skip_cssorder');
150
+ $skip_google_fonts = get_option('fastvelocity_min_skip_google_fonts');
151
+ $skip_emoji_removal = get_option('fastvelocity_min_skip_emoji_removal');
152
+ $enable_defer_js = get_option('fastvelocity_min_enable_defer_js');
153
+ $exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
154
+ $force_inline_css = get_option('fastvelocity_min_force_inline_css');
155
+ $force_inline_css_footer = get_option('fastvelocity_min_force_inline_css_footer');
156
+ $force_inline_googlefonts = get_option('fastvelocity_min_force_inline_googlefonts');
157
+ $defer_for_pagespeed = get_option('fastvelocity_min_defer_for_pagespeed');
158
+ $exclude_defer_login = get_option('fastvelocity_min_exclude_defer_login');
159
+ $preload = array_map('trim', explode("\n", get_option('fastvelocity_min_preload')));
160
+ $preconnect = array_map('trim', explode("\n", get_option('fastvelocity_min_preconnect')));
161
+ $fvm_fix_editor = get_option('fastvelocity_min_fvm_fix_editor');
162
+ $send_css_to_footer = get_option('fastvelocity_min_send_css_to_footer');
163
+ $critical_css_tester = get_option('fastvelocity_min_critical_css_tester');
164
+ $critical_path_css = get_option('fastvelocity_min_critical_path_css');
165
+ $generate_gulp_files = get_option('fastvelocity_min_generate_gulp_files');
166
+ $generate_gulp_path = get_option('fastvelocity_min_generate_gulp_path');
167
+
168
+
169
+ # skip on certain post_types or if there are specific keys on the url or if editor or admin
170
+ if(!fastvelocity_exclude_contents()) {
171
+
172
+ # actions for frontend only
173
+ if(!$disable_js_merge) {
174
+ add_action( 'wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
175
+ add_action( 'wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
176
+ }
177
+ if(!$disable_css_merge) {
178
+ add_action('wp_head', 'fvm_buffer_placeholder_top', 0);
179
+ add_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
180
+ add_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
181
+ }
182
+ if(!$skip_emoji_removal) {
183
+ add_action( 'init', 'fastvelocity_min_disable_wp_emojicons' );
184
+ }
185
+
186
+ }
187
+ }
188
+
189
+
190
+
191
+ # exclude processing for editors and administrators (fix editors)
192
+ add_action( 'plugins_loaded', 'fastvelocity_fix_editor' );
193
+ function fastvelocity_fix_editor() {
194
+ global $fvm_fix_editor, $disable_js_merge, $disable_css_merge, $skip_emoji_removal;
195
+ if($fvm_fix_editor == true && is_user_logged_in() && (current_user_can('editor') || current_user_can('administrator'))) {
196
+ if(!$disable_js_merge) {
197
+ remove_action( 'wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
198
+ remove_action( 'wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
199
+ }
200
+ if(!$disable_css_merge) {
201
+ remove_action('wp_head', 'fvm_buffer_placeholder_top', 0);
202
+ remove_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
203
+ remove_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
204
+ }
205
+ if(!$skip_emoji_removal) {
206
+ remove_action( 'init', 'fastvelocity_min_disable_wp_emojicons' );
207
+ }
208
+ }
209
+ }
210
+
211
+
212
+ # delete the cache when we deactivate the plugin
213
+ function fastvelocity_min_plugin_deactivate() { fvm_purge_all(); }
214
+
215
+
216
+ # create admin menu
217
+ function fastvelocity_min_admin_menu() {
218
+ add_options_page('Fast Velocity Minify Settings', 'Fast Velocity Minify', 'manage_options', 'fastvelocity-min', 'fastvelocity_min_settings');
219
+ }
220
+
221
+
222
+ # function to list all cache files
223
+ function fastvelocity_min_files_callback() {
224
+ global $cachedir;
225
+
226
+ # default
227
+ $return = array('js' => array(), 'css' => array(), 'stamp' => $_POST['stamp']);
228
+
229
+ # inspect directory with opendir, since glob might not be available in some systems
230
+ if ($handle = opendir($cachedir.'/')) {
231
+ while (false !== ($file = readdir($handle))) {
232
+ $file = $cachedir.'/'.$file;
233
+ $ext = pathinfo($file, PATHINFO_EXTENSION);
234
+ if (in_array($ext, array('js', 'css'))) {
235
+ $log = file_get_contents($file.'.txt');
236
+ $mincss = substr($file, 0, -4).'.min.css';
237
+ $minjs = substr($file, 0, -3).'.min.js';
238
+ $filename = basename($file);
239
+ if ($ext == 'css' && file_exists($mincss)) { $filename = basename($mincss); }
240
+ if ($ext == 'js' && file_exists($minjs)) { $filename = basename($minjs); }
241
+
242
+ # get location, hash, modified date
243
+ $info = explode('-', $filename);
244
+ $hash = $info['1'];
245
+ array_push($return[$ext], array('hash' => $hash, 'filename' => $filename, 'log' => $log));
246
+ }
247
+ }
248
+ closedir($handle);
249
+ }
250
+
251
+ header('Content-Type: application/json');
252
+ echo json_encode($return);
253
+ wp_die();
254
+ }
255
+
256
+
257
+ # load wp-admin css and js files
258
+ function fastvelocity_min_load_admin_jscss($hook) {
259
+ if ('settings_page_fastvelocity-min' != $hook) { return; }
260
+ wp_enqueue_script('postbox');
261
+ wp_enqueue_style('fastvelocity-min', plugins_url('fvm.css', __FILE__), array(), filemtime(plugin_dir_path( __FILE__).'fvm.css'));
262
+ wp_enqueue_script('fastvelocity-min', plugins_url('fvm.js', __FILE__), array('jquery'), filemtime(plugin_dir_path( __FILE__).'fvm.js'), true);
263
+ }
264
+
265
+
266
+ # register plugin settings
267
+ function fastvelocity_min_register_settings() {
268
+ register_setting('fvm-group', 'fastvelocity_min_ignore');
269
+ register_setting('fvm-group', 'fastvelocity_min_default_protocol');
270
+ register_setting('fvm-group', 'fastvelocity_min_disable_js_merge');
271
+ register_setting('fvm-group', 'fastvelocity_min_disable_css_merge');
272
+ register_setting('fvm-group', 'fastvelocity_min_disable_js_minification');
273
+ register_setting('fvm-group', 'fastvelocity_min_disable_css_minification');
274
+ register_setting('fvm-group', 'fastvelocity_min_use_yui');
275
+ register_setting('fvm-group', 'fastvelocity_min_remove_print_mediatypes');
276
+ register_setting('fvm-group', 'fastvelocity_min_skip_html_minification');
277
+ register_setting('fvm-group', 'fastvelocity_min_use_alt_html_minification');
278
+ register_setting('fvm-group', 'fastvelocity_min_strip_htmlcomments');
279
+ register_setting('fvm-group', 'fastvelocity_min_skip_cssorder');
280
+ register_setting('fvm-group', 'fastvelocity_min_skip_google_fonts');
281
+ register_setting('fvm-group', 'fastvelocity_min_skip_fontawesome_fonts');
282
+ register_setting('fvm-group', 'fastvelocity_min_skip_emoji_removal');
283
+ register_setting('fvm-group', 'fastvelocity_min_enable_defer_js');
284
+ register_setting('fvm-group', 'fastvelocity_min_exclude_defer_jquery');
285
+ register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
286
+ register_setting('fvm-group', 'fastvelocity_min_force_inline_css_footer');
287
+ register_setting('fvm-group', 'fastvelocity_min_force_inline_googlefonts');
288
+ register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
289
+ register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
290
+ register_setting('fvm-group', 'fastvelocity_min_preload');
291
+ register_setting('fvm-group', 'fastvelocity_min_preconnect');
292
+ register_setting('fvm-group', 'fastvelocity_min_fvm_fix_editor');
293
+ register_setting('fvm-group', 'fastvelocity_min_fvm_enable_cdn');
294
+ register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_url');
295
+
296
+ # pro version (for private usage... or if you know what you're doing)
297
+ register_setting('fvm-group-pro', 'fastvelocity_min_send_css_to_footer');
298
+ register_setting('fvm-group-pro', 'fastvelocity_min_critical_css_tester');
299
+ register_setting('fvm-group-pro', 'fastvelocity_min_critical_path_css');
300
+ register_setting('fvm-group-pro', 'fastvelocity_min_generate_gulp_files');
301
+ register_setting('fvm-group-pro', 'fastvelocity_min_generate_gulp_path');
302
+ register_setting('fvm-group-license', 'fastvelocity_min_license_code');
303
+ }
304
+
305
+
306
+
307
+ # add settings link on plugin page
308
+ function fastvelocity_min_settings_link($links) {
309
+ if (is_plugin_active(plugin_basename( __FILE__ ))) {
310
+ $settings_link = '<a href="options-general.php?page=fastvelocity-min&tab=settings">Settings</a>';
311
+ array_unshift($links, $settings_link);
312
+ }
313
+ return $links;
314
+ }
315
+ add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
316
+
317
+
318
+
319
+ # manage settings page
320
+ function fastvelocity_min_settings() {
321
+ if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
322
+
323
+ # tmp folder
324
+ global $tmpdir, $cachedir, $plugindir;
325
+
326
+ # get active tab, set default
327
+ $active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'status';
328
+
329
+ ?>
330
+ <div class="wrap">
331
+ <h1>Fast Velocity Minify</h1>
332
+
333
+ <?php
334
+
335
+ # purge all caches
336
+ if(isset($_POST['purgeall']) && $_POST['purgeall'] == 1) {
337
+ fvm_purge_all(); # purge all
338
+ echo __('<div class="notice notice-success is-dismissible"><p>The <strong>CSS and JS</strong> files have been purged!</p></div>');
339
+ echo fastvelocity_purge_others(); # purge third party caches
340
+ }
341
+ ?>
342
+
343
+ <h2 class="nav-tab-wrapper wp-clearfix">
344
+ <a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
345
+ <a href="?page=fastvelocity-min&tab=settings" class="nav-tab <?php echo $active_tab == 'settings' ? 'nav-tab-active' : ''; ?>">Settings</a>
346
+ <?php
347
+ # this is still under development
348
+ $fvm_license = get_option('fastvelocity_min_license_code');
349
+ if($fvm_license != false && mb_strlen($fvm_license, 'UTF-8') == 32) {
350
+ ?>
351
+ <a href="?page=fastvelocity-min&tab=pro" class="nav-tab <?php echo $active_tab == 'pro' ? 'nav-tab-active' : ''; ?>">Extra</a>
352
+ <?php
353
+ }
354
+ ?>
355
+ <a href="?page=fastvelocity-min&tab=server" class="nav-tab <?php echo $active_tab == 'server' ? 'nav-tab-active' : ''; ?>">Server Info</a>
356
+ <a href="?page=fastvelocity-min&tab=help" class="nav-tab <?php echo $active_tab == 'help' ? 'nav-tab-active' : ''; ?>">Help</a>
357
+ </h2>
358
+
359
+
360
+ <?php if( $active_tab == 'status' ) { ?>
361
+
362
+ <div id="fastvelocity-min">
363
+ <div id="poststuff">
364
+ <div id="fastvelocity_min_processed" class="postbox-container">
365
+ <div class="meta-box">
366
+
367
+ <div class="postbox" id="tab-purge">
368
+ <h3 class="hndle"><span>Purge processed files</span></h3>
369
+ <div class="inside" id="fastvelocity_min_topbtns">
370
+ <ul class="processed">
371
+ <li id="purgeall-row">
372
+ <span class="filename">Purge processed CSS and JS files</span>
373
+ <span class="actions">
374
+ <form method="post" id="fastvelocity_min_clearall" action="<?php echo admin_url('options-general.php?page=fastvelocity-min&tab=status'); ?>">
375
+ <input type="hidden" name="purgeall" value="1" />
376
+ <?php submit_button('Delete', 'button-secondary', 'submit', false); ?>
377
+ </form>
378
+ </li>
379
+ </ul>
380
+ </div>
381
+ </div>
382
+
383
+ <div class="postbox" id="tab-js">
384
+ <h3 class="hndle"><span>List of processed JS files</span></h3>
385
+ <div class="inside" id="fastvelocity_min_jsprocessed">
386
+ <ul class="processed"></ul>
387
+ </div>
388
+ </div>
389
+
390
+ <div class="postbox" id="tab-css">
391
+ <h3 class="hndle"><span>List of processed CSS files</span></h3>
392
+ <div class="inside" id="fastvelocity_min_cssprocessed">
393
+ <ul class="processed"></ul>
394
+ </div>
395
+ </div>
396
+
397
+ </div>
398
+ </div>
399
+ </div>
400
+ </div>
401
+ <?php } ?>
402
+
403
+ <?php if( $active_tab == 'settings' ) { ?>
404
+ <form method="post" action="options.php">
405
+ <?php settings_fields('fvm-group'); do_settings_sections('fvm-group'); ?>
406
+
407
+ <div style="height: 20px;"></div>
408
+ <h2 class="title">Basic Options</h2>
409
+ <p class="fvm-bold-green">These options are generaly safe to edit as needed. If you use a cache plugin, kindly purge all your caches once you're done with the changes.</p>
410
+
411
+ <table class="form-table fvm-settings">
412
+ <tbody>
413
+
414
+ <tr>
415
+ <th scope="row">Troubleshooting</th>
416
+ <td>
417
+ <p class="fvm-bold-green fvm-rowintro">It's recommended that you enable this, if your theme comes with some sort of visual frontend editor.</p>
418
+ <fieldset>
419
+ <label for="fastvelocity_min_fvm_fix_editor">
420
+ <input name="fastvelocity_min_fvm_fix_editor" type="checkbox" id="fastvelocity_min_fvm_fix_editor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_fvm_fix_editor'), true, false); ?>>
421
+ Fix Page Editors <span class="note-info">[ If selected, logged in users with the "editor" role (and above) will bypass all optimizations ]</span></label>
422
+ </fieldset></td>
423
+ </tr>
424
+
425
+
426
+ <tr>
427
+ <th scope="row">URL Options</th>
428
+ <td>
429
+ <?php
430
+ # what to select
431
+ $sel = get_option('fastvelocity_min_default_protocol');
432
+ $a = ''; if($sel == 'dynamic' || empty($sel)) { $a = ' checked="checked"'; }
433
+ $b = ''; if($sel == 'http') { $b = ' checked="checked"'; }
434
+ $c = ''; if($sel == 'https') { $c = ' checked="checked"'; }
435
+ ?>
436
+ <p class="fvm-bold-green fvm-rowintro">You may need to force http or https, for some CDN plugins to work:</p>
437
+ <fieldset>
438
+ <label><input type="radio" name="fastvelocity_min_default_protocol" value="dynamic" <?php echo $a; ?>> Use the dynamic "//" protocol</label><br>
439
+ <label><input type="radio" name="fastvelocity_min_default_protocol" value="http"<?php echo $b; ?>> Force HTTP urls</label><br>
440
+ <label><input type="radio" name="fastvelocity_min_default_protocol" value="https"<?php echo $c; ?>> Force HTTPS urls</span></label><br>
441
+ </fieldset>
442
+ </td>
443
+ </tr>
444
+
445
+ <tr>
446
+ <th scope="row">HTML Options</th>
447
+ <td>
448
+ <p class="fvm-bold-green fvm-rowintro">The HTML minification is ON by default, but you can:</p>
449
+
450
+ <fieldset>
451
+ <label for="fastvelocity_min_skip_html_minification">
452
+ <input name="fastvelocity_min_skip_html_minification" type="checkbox" id="fastvelocity_min_skip_html_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_html_minification'), true, false); ?>>
453
+ Disable HTML Minification <span class="note-info">[ This will disable HTML minification ]</span></label>
454
+ <br />
455
+
456
+ <label for="fastvelocity_min_strip_htmlcomments">
457
+ <input name="fastvelocity_min_strip_htmlcomments" type="checkbox" id="fastvelocity_min_strip_htmlcomments" value="1" <?php echo checked(1 == get_option('fastvelocity_min_strip_htmlcomments'), true, false); ?>>
458
+ Strip HTML comments <span class="note-info">[ Only works with the default HTML minification, but note that some plugins need HTML comments to work properly ]</span></label>
459
+ <br />
460
+
461
+ <label for="fastvelocity_min_use_alt_html_minification">
462
+ <input name="fastvelocity_min_use_alt_html_minification" type="checkbox" id="fastvelocity_min_use_alt_html_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_use_alt_html_minification'), true, false); ?>>
463
+ Use the alternative HTML minification <span class="note-info">[ Select this, ONLY if you have trouble with the default HTML minification ]</span></label>
464
+ <br />
465
+
466
+ </fieldset></td>
467
+ </tr>
468
+
469
+
470
+ <tr>
471
+ <th scope="row">Fonts Options</th>
472
+ <td>
473
+ <p class="fvm-bold-green fvm-rowintro">It's recommended that you enable the "Inline Google Fonts CSS" option.</p>
474
+ <fieldset>
475
+ <label for="fastvelocity_min_skip_emoji_removal">
476
+ <input name="fastvelocity_min_skip_emoji_removal" type="checkbox" id="fastvelocity_min_skip_emoji_removal" class="jsprocessor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_emoji_removal'), true, false); ?> >
477
+ Stop removing Emojis and smileys <span class="note-info">[ If selected, Emojis will be left alone and won't be removed from wordpress ]</span></label>
478
+ <br />
479
+
480
+ <label for="fastvelocity_min_skip_google_fonts">
481
+ <input name="fastvelocity_min_skip_google_fonts" type="checkbox" id="fastvelocity_min_skip_google_fonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_google_fonts'), true, false); ?> >
482
+ Disable Google Fonts merging <span class="note-info">[ If selected, Google Fonts will no longer be merged into one request ]</span></label>
483
+ <br />
484
+
485
+ <label for="fastvelocity_min_force_inline_googlefonts">
486
+ <input name="fastvelocity_min_force_inline_googlefonts" type="checkbox" id="fastvelocity_min_force_inline_googlefonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_googlefonts'), true, false); ?> >
487
+ Inline Google Fonts CSS <span class="note-info">[ If selected, Google Fonts CSS code will be inlined using "*.woof" format - NOTE: IE9+ and <a target="_blank" href="http://caniuse.com/#feat=woff">modern browsers</a> only]</span></label>
488
+ <br />
489
+
490
+ </fieldset></td>
491
+ </tr>
492
+
493
+
494
+
495
+
496
+ <tr>
497
+ <th scope="row">CSS Options</th>
498
+ <td>
499
+ <p class="fvm-bold-green fvm-rowintro">It's recommended that you Inline all CSS files, if they are small enough.</p>
500
+
501
+ <fieldset>
502
+ <label for="fastvelocity_min_disable_css_merge">
503
+ <input name="fastvelocity_min_disable_css_merge" type="checkbox" id="fastvelocity_min_disable_css_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_css_merge'), true, false); ?>>
504
+ Disable CSS processing<span class="note-info">[ If selected, this plugin will ignore CSS files completely ]</span></label>
505
+ <br />
506
+ <label for="fastvelocity_min_disable_css_minification">
507
+ <input name="fastvelocity_min_disable_css_minification" type="checkbox" id="fastvelocity_min_disable_css_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_css_minification'), true, false); ?>>
508
+ Disable minification on CSS files <span class="note-info">[ If selected, CSS files will be merged but not minified ]</span></label>
509
+ <br />
510
+ <label for="fastvelocity_min_skip_cssorder">
511
+ <input name="fastvelocity_min_skip_cssorder" type="checkbox" id="fastvelocity_min_skip_cssorder" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_cssorder'), true, false); ?> >
512
+ Preserve the order of CSS files <span class="note-info">[ If selected, you will have better CSS compatibility but possibly more CSS files]</span></label>
513
+ <br />
514
+ <label for="fastvelocity_min_remove_print_mediatypes">
515
+ <input name="fastvelocity_min_remove_print_mediatypes" type="checkbox" id="fastvelocity_min_remove_print_mediatypes" value="1" <?php echo checked(1 == get_option('fastvelocity_min_remove_print_mediatypes'), true, false); ?> >
516
+ Remove the "Print" related stylesheets <span class="note-info">[ If selected, CSS files of mediatype "print" will be removed from the site ]</span></label>
517
+ <br />
518
+ <label for="fastvelocity_min_force_inline_css">
519
+ <input name="fastvelocity_min_force_inline_css" type="checkbox" id="fastvelocity_min_force_inline_css" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_css'), true, false); ?>>
520
+ Inline all header CSS files <span class="note-info">[ If selected, the header CSS will be inlined to avoid the "render blocking" on pagespeed insights tests ]</span></label>
521
+ <br />
522
+ <label for="fastvelocity_min_force_inline_css_footer">
523
+ <input name="fastvelocity_min_force_inline_css_footer" type="checkbox" id="fastvelocity_min_force_inline_css_footer" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_css_footer'), true, false); ?>>
524
+ Inline all footer CSS files <span class="note-info">[ If selected, the footer CSS will be inlined to avoid the "render blocking" on pagespeed insights tests ]</span></label>
525
+ <br />
526
+ </fieldset></td>
527
+ </tr>
528
+
529
+
530
+ <tr>
531
+ <th scope="row">JavaScript Options</th>
532
+ <td>
533
+ <p class="fvm-bold-green fvm-rowintro">Try to disable minification (and purge the cache), if you have trouble with JavaScript in the frontend.</p>
534
+ <fieldset>
535
+ <label for="fastvelocity_min_disable_js_merge">
536
+ <input name="fastvelocity_min_disable_js_merge" type="checkbox" id="fastvelocity_min_disable_js_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_merge'), true, false); ?> >
537
+ Disable JavaScript processing <span class="note-info">[ If selected, this plugin will ignore JS files completely ]</span></label>
538
+ <br />
539
+
540
+ <?php
541
+ # check for exec + a supported java version
542
+ if(function_exists('exec') && exec('command -v java >/dev/null && echo "yes" || echo "no"') == 'yes') {
543
+ ?>
544
+ <label for="fastvelocity_min_use_yui">
545
+ <input name="fastvelocity_min_use_yui" type="checkbox" id="fastvelocity_min_use_yui" class="jsprocessor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_use_yui'), true, false); ?> >
546
+ Minify with YUI Compressor <span class="note-info">[ If selected, it will try to use the YUI Compressor to minify JS files ]</span></label>
547
+ <br />
548
+ <?php } ?>
549
+
550
+ <label for="fastvelocity_min_disable_js_minification">
551
+ <input name="fastvelocity_min_disable_js_minification" type="checkbox" id="fastvelocity_min_disable_js_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_minification'), true, false); ?> >
552
+ Disable minification on JS files <span class="note-info">[ If selected, JS files will be merged but not minified ]</span></label>
553
+ <br />
554
+ </fieldset></td>
555
+ </tr>
556
+ </tbody></table>
557
+
558
+
559
+ <div style="height: 20px;"></div>
560
+ <h2 class="title">JS Advanced Options</h2>
561
+ <p class="fvm-bold-green">It's highly recommended that you only select the options below if you're an advanced user or developer and understand what these options mean.</p>
562
+
563
+ <table class="form-table fvm-settings">
564
+ <tbody>
565
+ <tr>
566
+ <th scope="row">Render-blocking JS</th>
567
+ <td><fieldset><legend class="screen-reader-text"><span>Render-blocking</span></legend>
568
+ <label for="fastvelocity_min_enable_defer_js">
569
+ <input name="fastvelocity_min_enable_defer_js" type="checkbox" id="fastvelocity_min_enable_defer_js" value="1" <?php echo checked(1 == get_option('fastvelocity_min_enable_defer_js'), true, false); ?>>
570
+ Enable defer parsing of JS files globally <span class="note-info">[ Not all browsers, themes or plugins support this. Beware of broken functionality and design ]</span></label>
571
+ <br />
572
+ <label for="fastvelocity_min_defer_for_pagespeed">
573
+ <input name="fastvelocity_min_defer_for_pagespeed" type="checkbox" id="fastvelocity_min_defer_for_pagespeed" value="1" <?php echo checked(1 == get_option('fastvelocity_min_defer_for_pagespeed'), true, false); ?>>
574
+ Enable defer of JS for Pagespeed Insights <span class="note-info">[ This will defer JS files for Pagespeed Insights only, <a target="_blank" href="https://www.chromestatus.com/feature/5718547946799104">except external scripts</a> loaded from other domains ]</span></label>
575
+ <br />
576
+
577
+ <label for="fastvelocity_min_exclude_defer_jquery">
578
+ <input name="fastvelocity_min_exclude_defer_jquery" type="checkbox" id="fastvelocity_min_exclude_defer_jquery" value="1" <?php echo checked(1 == get_option('fastvelocity_min_exclude_defer_jquery'), true, false); ?> >
579
+ Skip deferring the jQuery library <span class="note-info">[ Will fix "undefined jQuery" errors on the Google Chrome console log ]</span></label>
580
+ <br />
581
+ <label for="fastvelocity_min_exclude_defer_login">
582
+ <input name="fastvelocity_min_exclude_defer_login" type="checkbox" id="fastvelocity_min_exclude_defer_login" value="1" <?php echo checked(1 == get_option('fastvelocity_min_exclude_defer_login'), true, false); ?> >
583
+ Skip deferring completely on the login page <span class="note-info">[ If selected, will disable JS deferring on your login page ]</span></label>
584
+ <br />
585
+
586
+
587
+ </fieldset></td>
588
+ </tr>
589
+ </tbody></table>
590
+
591
+
592
+
593
+ <div style="height: 20px;"></div>
594
+ <h2 class="title">JS and CSS Exceptions</h2>
595
+ <p class="fvm-bold-green">You can use this section to exclude certain CSS or JS files from being processed in case of conflicts while merging.</p>
596
+
597
+ <table class="form-table fvm-settings">
598
+ <tbody>
599
+ <tr>
600
+ <th scope="row">Ignore List</th>
601
+ <td><fieldset><legend class="screen-reader-text"><span>Ignore List</span></legend>
602
+ <p><label for="blacklist_keys"><span class="fvm-label-pad">Ignore the following CSS and JS paths below:</span></label></p>
603
+ <p>
604
+ <textarea name="fastvelocity_min_ignore" rows="10" cols="50" id="fastvelocity_min_ignore" class="large-text code" placeholder="ex: /wp-includes/js/jquery/jquery.js"><?php echo get_option('fastvelocity_min_ignore'); ?></textarea>
605
+ </p>
606
+ <p class="description">[ Remove all query strings and use only relative or partial urls, ex: /wp-includes/js/jquery/jquery.js ]</p>
607
+ <br />
608
+ </fieldset></td>
609
+ </tr>
610
+ </tbody></table>
611
+
612
+
613
+ <div style="height: 20px;"></div>
614
+ <h2 class="title">CDN Options</h2>
615
+ <p class="fvm-bold-green">This rewrite our generated CSS and JS urls to use your cdn domain name.</p>
616
+
617
+ <table class="form-table fvm-settings">
618
+ <tbody>
619
+ <tr>
620
+ <th scope="row"><span class="fvm-label-special">CDN URL</span></th>
621
+ <td><fieldset><legend class="screen-reader-text"><span>CDN URL</span></legend>
622
+ <label for="fastvelocity_min_fvm_cdn_url">
623
+ <p><input type="text" name="fastvelocity_min_fvm_cdn_url" id="fastvelocity_min_fvm_cdn_url" value="<?php echo get_option('fastvelocity_min_fvm_cdn_url', ''); ?>" size="80" /></p>
624
+ <p class="description">[ Leave empty, or enter your CDN URL domain name here ]</p></label>
625
+ </fieldset></td>
626
+ </tr>
627
+ </tbody></table>
628
+
629
+
630
+ <div style="height: 20px;"></div>
631
+ <h2 class="title">Preconnect Optimization</h2>
632
+ <p class="fvm-bold-green">Please make sure you understand these options before using them.</p>
633
+
634
+ <table class="form-table fvm-settings">
635
+ <tbody>
636
+ <tr>
637
+ <th scope="row">Preconnect Headers</th>
638
+ <td><fieldset><legend class="screen-reader-text"><span>Preconnect</span></legend>
639
+ <label for="fastvelocity_min_preconnect"><span class="fvm-label-pad">Insert one domain name url per line:</span></label>
640
+ <p>
641
+ <textarea name="fastvelocity_min_preconnect" rows="10" cols="50" id="fastvelocity_min_preconnect" class="large-text code" placeholder="ex: //fonts.gstatic.com"><?php echo get_option('fastvelocity_min_preconnect'); ?></textarea>
642
+ </p>
643
+ <p class="description">[ Use only the necessary domain names, such as remote font domain names, ex: //fonts.gstatic.com ]</p>
644
+ </fieldset></td>
645
+ </tr>
646
+
647
+ </tbody></table>
648
+
649
+
650
+ <div style="height: 20px;"></div>
651
+ <h2 class="title">Homepage Optimization</h2>
652
+ <p class="fvm-bold-green">Prioritize visible content by preloading images with high priority, such as the first image on a slider that is shown above the folder.</p>
653
+
654
+ <table class="form-table fvm-settings">
655
+ <tbody>
656
+ <tr>
657
+ <th scope="row">Preload Images</th>
658
+ <td><fieldset><legend class="screen-reader-text"><span>Preload Images</span></legend>
659
+ <label for="fastvelocity_min_preload"><span class="fvm-label-pad">Insert one image url per line:</span></label>
660
+ <p>
661
+ <textarea name="fastvelocity_min_preload" rows="10" cols="50" id="fastvelocity_min_preload" class="large-text code" placeholder="ex: //yoursite.com/wp-content/plugins/some-slider/large.img"><?php echo get_option('fastvelocity_min_preload'); ?></textarea>
662
+ </p>
663
+ <p class="description">[ Use only for large images that first load above the fold. Read the Help section for more details. ]</p>
664
+ </fieldset></td>
665
+ </tr>
666
+ </tbody></table>
667
+
668
+
669
+ <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
670
+ </form>
671
+ <?php } ?>
672
+
673
+
674
+ <?php if( $active_tab == 'pro' ) {
675
+
676
+ # this is still under development
677
+ $fvm_license = get_option('fastvelocity_min_license_code');
678
+ if($fvm_license != false && mb_strlen($fvm_license, 'UTF-8') == 32) {
679
+ ?>
680
+
681
+ <form method="post" action="options.php">
682
+ <?php settings_fields('fvm-group-pro'); do_settings_sections('fvm-group-pro'); ?>
683
+
684
+ <div style="height: 20px;"></div>
685
+ <h2 class="title">Extra Optimization</h2>
686
+ <p class="fvm-bold-green">These options are available for the professional version only.<br />
687
+ When deferring all generated css files, you must enqueue any inline css code that was supposed to load after the generated files.</p>
688
+
689
+
690
+ <table class="form-table fvm-settings">
691
+ <tbody>
692
+
693
+ <tr>
694
+ <th scope="row">Extra CSS Options</th>
695
+ <td><fieldset><legend class="screen-reader-text"><span>Extra CSS Options</span></legend>
696
+ <label for="fastvelocity_min_send_css_to_footer">
697
+ <input name="fastvelocity_min_send_css_to_footer" type="checkbox" id="fastvelocity_min_send_css_to_footer" value="1" <?php echo checked(1 == get_option('fastvelocity_min_send_css_to_footer'), true, false); ?>>
698
+ Async CSS with LoadCSS<span class="note-info">[ If selected, you will need a Critical Path CSS to Optimize CSS Delivery ]</span></label>
699
+ <br />
700
+ <label for="fastvelocity_min_critical_css_tester">
701
+ <input name="fastvelocity_min_critical_css_tester" type="checkbox" id="fastvelocity_min_critical_css_tester" value="1" <?php echo checked(1 == get_option('fastvelocity_min_critical_css_tester'), true, false); ?>>
702
+ Critical Path Tester<span class="note-info">[ If selected, only the critical path code will be shown and no css files will be enqueued ]</span></label>
703
+ </fieldset>
704
+ </td>
705
+ </tr>
706
+
707
+ <tr>
708
+ <th scope="row">Global Critical CSS</th>
709
+ <td>
710
+ <p>
711
+ <textarea name="fastvelocity_min_critical_path_css" rows="20" cols="50" id="fastvelocity_min_critical_path_css" class="large-text code" placeholder="your css code here"><?php echo get_option('fastvelocity_min_critical_path_css'); ?></textarea>
712
+ </p>
713
+ <p class="description">[ Please minify your CSS code manually and insert your Global Critical CSS here ]</p>
714
+ </td>
715
+ </tr>
716
+
717
+
718
+ <tr>
719
+ <th scope="row">Gulp Options</th>
720
+ <td><fieldset>
721
+ <label for="fastvelocity_min_generate_gulp_files">
722
+ <input name="fastvelocity_min_generate_gulp_files" type="checkbox" id="fastvelocity_min_generate_gulp_files" value="1" <?php echo checked(1 == get_option('fastvelocity_min_generate_gulp_files'), true, false); ?>>
723
+ Generate gulp-uncss files<span class="note-info">[ If selected, it will try to generate one gulp-uncss per pageview ]</span></label>
724
+ </fieldset>
725
+ </td>
726
+ </tr>
727
+
728
+ <tr>
729
+ <th scope="row">Gulp Directory</th>
730
+ <td>
731
+ <label for="fastvelocity_min_generate_gulp_path">
732
+ <input name="fastvelocity_min_generate_gulp_path" type="text" id="fastvelocity_min_generate_gulp_path" value="<?php echo get_option('fastvelocity_min_generate_gulp_path'); ?>" class="regular-text code">
733
+ <p class="description">The absolute path to your local "Gulp" working directory</p>
734
+ </td>
735
+ </tr>
736
+
737
+
738
+ </tbody></table>
739
+
740
+ <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
741
+ </form>
742
+
743
+ <?php
744
+ } else {
745
+
746
+ ?>
747
+
748
+ <form method="post" action="options.php">
749
+ <?php settings_fields('fvm-group-license'); do_settings_sections('fvm-group-license'); ?>
750
+
751
+ <div style="height: 20px;"></div>
752
+ <h2 class="title">Extra Optimization</h2>
753
+ <p class="fvm-bold-green">These options are available for the professional version only.</p>
754
+
755
+ <table class="form-table fvm-settings">
756
+ <tbody>
757
+
758
+ <tr>
759
+ <th scope="row">License Code</th>
760
+ <td>
761
+ <input name="fastvelocity_min_license_code" type="text" id="fastvelocity_min_license_code" value="<?php echo get_option('fastvelocity_min_license_code'); ?>" class="regular-text">
762
+ <p class="description">Please insert the license code that has been provided.</p>
763
+ </td>
764
+ </tr>
765
+
766
+ </tbody></table>
767
+
768
+ <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
769
+ </form>
770
+
771
+ <?php
772
+ }
773
+ }
774
+ ?>
775
+
776
+
777
+ <?php
778
+ if( $active_tab == 'server' ) {
779
+ fvm_get_generalinfo();
780
+ }
781
+ ?>
782
+
783
+ <?php if( $active_tab == 'help' ) { ?>
784
+
785
+ <div class="wrap" id="fastvelocity-min">
786
+ <div id="poststuff">
787
+ <div id="fastvelocity_min_processed" class="postbox-container">
788
+ <div class="meta-box-sortables ui-sortable">
789
+
790
+
791
+
792
+
793
+ <div class="postbox" id="tab-info">
794
+ <h3 class="hndle"><span>Frequently Asked Questions</span></h3>
795
+ <div class="inside"><? echo fastvelocity_min_readme($plugindir.'readme.txt'); ?></div>
796
+ </div>
797
+
798
+ </div>
799
+ </div>
800
+ </div>
801
+ </div>
802
+ <?php } ?>
803
+
804
+
805
+
806
+ </div>
807
+
808
+ <div class="clear"></div>
809
+
810
+ <?php
811
+ }
812
+
813
+
814
+ ###########################################
815
+ # process header javascript ###############
816
+ ###########################################
817
+ function fastvelocity_min_merge_header_scripts() {
818
+ global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery;
819
+ if(!is_object($wp_scripts)) { return false; }
820
+ $scripts = wp_clone($wp_scripts);
821
+ $scripts->all_deps($scripts->queue);
822
+ $ctime = get_option('fvm-last-cache-update', '0');
823
+ $header = array();
824
+
825
+ # mark as done (as we go)
826
+ $done = $scripts->done;
827
+
828
+ # add defaults to ignore list
829
+ $ignore = fastvelocity_default_ignore($ignore);
830
+
831
+ # get groups of handles
832
+ foreach( $scripts->to_do as $handle ) :
833
+
834
+ # is it a footer script?
835
+ $is_footer = 0; if (isset($wp_scripts->registered[$handle]->extra["group"]) || isset($wp_scripts->registered[$handle]->args)) { $is_footer = 1; }
836
+
837
+ # skip footer scripts for now
838
+ if($is_footer != 1) {
839
+
840
+ # get full url
841
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
842
+
843
+ # IE only files don't increment things
844
+ $ieonly = fastvelocity_ie_blacklist($hurl);
845
+ if($ieonly == true) { continue; }
846
+
847
+ # skip ignore list, scripts with conditionals, external scripts
848
+ if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
849
+
850
+ # process
851
+ if(isset($header[count($header)-1]['handle']) || count($header) == 0) {
852
+ array_push($header, array('handles'=>array()));
853
+ }
854
+
855
+ # push it to the array
856
+ array_push($header[count($header)-1]['handles'], $handle);
857
+
858
+ # external and ignored scripts
859
+ } else {
860
+ array_push($header, array('handle'=>$handle));
861
+ }
862
+
863
+ # make sure that the scripts skipped here, show up in the footer
864
+ } else {
865
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
866
+ wp_enqueue_script($handle, $hurl, array(), null, true);
867
+ }
868
+ endforeach;
869
+
870
+
871
+ # loop through header scripts and merge
872
+ for($i=0,$l=count($header);$i<$l;$i++) {
873
+ if(!isset($header[$i]['handle'])) {
874
+
875
+ # static cache file info + done
876
+ $done = array_merge($done, $header[$i]['handles']);
877
+ $hash = 'header-'.hash('adler32',implode('',$header[$i]['handles']));
878
+
879
+ # create cache files and urls
880
+ $file = $cachedir.'/'.$hash.'-'.$ctime.'.min.js';
881
+ $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'-'.$ctime.'.min.js');
882
+
883
+ # generate a new cache file
884
+ if (!file_exists($file)) {
885
+
886
+ # code and log initialization
887
+ $log = '';
888
+ $code = '';
889
+
890
+ # minify and write to file
891
+ foreach($header[$i]['handles'] as $handle) :
892
+ if(!empty($wp_scripts->registered[$handle]->src)) {
893
+
894
+ # get hurl per handle
895
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
896
+ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
897
+
898
+ # get css from hurl, if available and valid
899
+ $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
900
+ $newcode = false; $newcode = get_transient($tkey);
901
+ if ( $newcode === false) {
902
+ $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js');
903
+ if(is_array($res)) {
904
+ $newcode = $res['code'];
905
+ $newlog = $res['log'];
906
+ }
907
+ } else {
908
+ $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
909
+ }
910
+
911
+ # append
912
+ if($newcode !== false) {
913
+ $code.= $newcode;
914
+ $log.= $newlog;
915
+ }
916
+
917
+ # consider dependencies on handles with an empty src
918
+ } else {
919
+ wp_dequeue_script($handle); wp_enqueue_script($handle);
920
+ }
921
+ endforeach;
922
+
923
+ # prepare log
924
+ $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
925
+
926
+ # generate cache, write log
927
+ file_put_contents($file.'.txt', $log);
928
+ file_put_contents($file, $code);
929
+ file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
930
+ }
931
+
932
+ # register minified file
933
+ wp_register_script("fvm-header-$i", $file_url, array(), null, false);
934
+
935
+ # add all extra data from wp_localize_script
936
+ $data = array();
937
+ foreach($header[$i]['handles'] as $handle) {
938
+ if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
939
+ }
940
+ if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode("\n", $data); }
941
+
942
+ # enqueue file
943
+ wp_enqueue_script("fvm-header-$i");
944
+
945
+ # other scripts need to be requeued for the order of files to be kept
946
+ } else {
947
+ wp_dequeue_script($header[$i]['handle']); wp_enqueue_script($header[$i]['handle']);
948
+ }
949
+ }
950
+
951
+ # remove from queue
952
+ $wp_scripts->done = $done;
953
+ }
954
+ ###########################################
955
+
956
+
957
+
958
+ ###########################################
959
+ # process js in the footer ################
960
+ ###########################################
961
+ function fastvelocity_min_merge_footer_scripts() {
962
+ global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery;
963
+ if(!is_object($wp_scripts)) { return false; }
964
+ $ctime = get_option('fvm-last-cache-update', '0');
965
+ $scripts = wp_clone($wp_scripts);
966
+ $scripts->all_deps($scripts->queue);
967
+ $footer = array();
968
+
969
+ # mark as done (as we go)
970
+ $done = $scripts->done;
971
+
972
+ # add defaults to ignore list
973
+ $ignore = fastvelocity_default_ignore($ignore);
974
+
975
+
976
+ # get groups of handles
977
+ foreach( $scripts->to_do as $handle ) :
978
+
979
+ # get full url
980
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
981
+
982
+ # IE only files don't increment things
983
+ $ieonly = fastvelocity_ie_blacklist($hurl);
984
+ if($ieonly == true) { continue; }
985
+
986
+ # skip ignore list, scripts with conditionals, external scripts
987
+ if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
988
+
989
+ # process
990
+ if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0) {
991
+ array_push($footer, array('handles'=>array()));
992
+ }
993
+
994
+ # push it to the array
995
+ array_push($footer[count($footer)-1]['handles'], $handle);
996
+
997
+ # external and ignored scripts
998
+ } else {
999
+ array_push($footer, array('handle'=>$handle));
1000
+ }
1001
+ endforeach;
1002
+
1003
+ # loop through footer scripts and merge
1004
+ for($i=0,$l=count($footer);$i<$l;$i++) {
1005
+ if(!isset($footer[$i]['handle'])) {
1006
+
1007
+ # static cache file info + done
1008
+ $done = array_merge($done, $footer[$i]['handles']);
1009
+ $hash = 'footer-'.hash('adler32',implode('',$footer[$i]['handles']));
1010
+
1011
+ # create cache files and urls
1012
+ $file = $cachedir.'/'.$hash.'-'.$ctime.'.min.js';
1013
+ $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'-'.$ctime.'.min.js');
1014
+
1015
+ # generate a new cache file
1016
+ if (!file_exists($file)) {
1017
+
1018
+ # code and log initialization
1019
+ $log = '';
1020
+ $code = '';
1021
+
1022
+ # minify and write to file
1023
+ foreach($footer[$i]['handles'] as $handle) :
1024
+ if(!empty($wp_scripts->registered[$handle]->src)) {
1025
+
1026
+ # get hurl per handle
1027
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1028
+ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1029
+
1030
+ # get css from hurl, if available and valid
1031
+ $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1032
+ $newcode = false; $newcode = get_transient($tkey);
1033
+ if ( $newcode === false) {
1034
+ $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js');
1035
+ if(is_array($res)) {
1036
+ $newcode = $res['code'];
1037
+ $newlog = $res['log'];
1038
+ }
1039
+ } else {
1040
+ $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1041
+ }
1042
+
1043
+ # append
1044
+ if($newcode !== false) {
1045
+ $code.= $newcode;
1046
+ $log.= $newlog;
1047
+ }
1048
+
1049
+ # consider dependencies on handles with an empty src
1050
+ } else {
1051
+ wp_dequeue_script($handle); wp_enqueue_script($handle);
1052
+ }
1053
+ endforeach;
1054
+
1055
+ # prepare log
1056
+ $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1057
+
1058
+ # generate cache, write log
1059
+ file_put_contents($file.'.txt', $log);
1060
+ file_put_contents($file, $code);
1061
+ file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1062
+ }
1063
+
1064
+ # register minified file
1065
+ wp_register_script("fvm-footer-$i", $file_url, array(), null, false);
1066
+
1067
+ # add all extra data from wp_localize_script
1068
+ $data = array();
1069
+ foreach($footer[$i]['handles'] as $handle) {
1070
+ if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1071
+ }
1072
+ if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode("\n", $data); }
1073
+
1074
+ # enqueue file
1075
+ wp_enqueue_script("fvm-footer-$i");
1076
+
1077
+ # other scripts need to be requeued for the order of files to be kept
1078
+ } else {
1079
+ wp_dequeue_script($footer[$i]['handle']); wp_enqueue_script($footer[$i]['handle']);
1080
+ }
1081
+ }
1082
+
1083
+ # remove from queue
1084
+ $wp_scripts->done = $done;
1085
+ }
1086
+ ##############################
1087
+
1088
+
1089
+
1090
+ ###########################################
1091
+ # enable defer for JavaScript (WP 4.1 and above) and remove query strings for ignored files
1092
+ ###########################################
1093
+ function fastvelocity_min_defer_js($tag, $handle, $src) {
1094
+ global $ignore, $enable_defer_js, $defer_for_pagespeed, $wp_domain, $exclude_defer_login;
1095
+
1096
+ # no query strings
1097
+ if (stripos($src, '?ver') !== false) {
1098
+ $srcf = stristr($src, '?ver', true);
1099
+ $tag = str_ireplace($src, $srcf, $tag);
1100
+ $src = $srcf;
1101
+ }
1102
+
1103
+ # should we exclude defer on the login page?
1104
+ if($exclude_defer_login == true && stripos($_SERVER["SCRIPT_NAME"], strrchr(wp_login_url(), '/')) !== false){ return $tag; }
1105
+
1106
+ # reprocess the ignore list to remove the /fvm/cache/ from the list (else won't defer)
1107
+ if(is_array($ignore)) { $nignore = array(); foreach ($ignore as $i) { if($i != '/fvm/cache/') { $nignore[] = $i; } } }
1108
+
1109
+ # when to defer, order matters
1110
+ $defer = 0; if($enable_defer_js == true) { $defer = 1; }
1111
+ if (fastvelocity_min_in_arrayi($src, $nignore)) { $defer = 0; }
1112
+
1113
+ # get available nodes and add create with defer tag (if not async)
1114
+ $dom = new DOMDocument();
1115
+ libxml_use_internal_errors(true);
1116
+ @$dom->loadHTML($tag);
1117
+ $nodes = $dom->getElementsByTagName('script');
1118
+ $tagdefer = '';
1119
+ if ($nodes->length != 0) {
1120
+ $node = $dom->getElementsByTagName('script')->item(0);
1121
+ if (!$node->hasAttribute('async')) { $node->setAttribute('defer','defer'); };
1122
+ $tagdefer = $dom->saveHTML($node);
1123
+ }
1124
+
1125
+ # skip the nignore list by default, defer the rest
1126
+ if ($defer == 0) {
1127
+
1128
+ # no defer
1129
+ if ($defer_for_pagespeed != true) { return $tag; } else {
1130
+
1131
+ # return if external script url https://www.chromestatus.com/feature/5718547946799104
1132
+ if (stripos($src, $wp_domain) === false) { return $tag; }
1133
+
1134
+ # print code or return
1135
+ if(!empty($tagdefer)) {
1136
+ $deferinsights = '<script type="text/javascript">if(navigator.userAgent.match(/speed|gtmetrix|x11.*firefox\/53|x11.*chrome\/39/i)){document.write('.json_encode($tagdefer).');}else{document.write('.json_encode($tag).');}</script>';
1137
+ return preg_replace('#<script(.*?)>(.*?)</script>#is', $deferinsights, $tag);
1138
+ }
1139
+
1140
+ return $tag;
1141
+ }
1142
+
1143
+ # normal defer enabled
1144
+ } else { return $tagdefer; }
1145
+ }
1146
+ ###########################################
1147
+
1148
+
1149
+
1150
+
1151
+ ###########################################
1152
+ # process header css ######################
1153
+ ###########################################
1154
+ function fastvelocity_min_merge_header_css() {
1155
+ global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_css, $force_inline_googlefonts, $send_css_to_footer, $critical_path_css, $critical_css_tester;
1156
+ if(!is_object($wp_styles)) { return false; }
1157
+ $ctime = get_option('fvm-last-cache-update', '0');
1158
+ $styles = wp_clone($wp_styles);
1159
+ $styles->all_deps($styles->queue);
1160
+ $done = $styles->done;
1161
+ $header = array();
1162
+ $google_fonts = array();
1163
+ $process = array();
1164
+ $inline_css = array();
1165
+
1166
+ # add defaults to ignore list
1167
+ $ignore = fastvelocity_default_ignore($ignore);
1168
+
1169
+
1170
+ # get list of handles to process, dequeue duplicate css urls and keep empty source handles (for dependencies)
1171
+ $uniq = array(); $gfonts = array();
1172
+ foreach( $styles->to_do as $handle):
1173
+
1174
+ # conditionals
1175
+ $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
1176
+ $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
1177
+ }
1178
+
1179
+ # mediatype
1180
+ $mediatype = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all'; # such as all, print, mobile, etc
1181
+ if ($mediatype == 'screen' || $mediatype == 'screen, print') { $mediatype = 'all'; }
1182
+
1183
+ # full url or empty
1184
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1185
+
1186
+ # mark duplicates as done and remove from the queue
1187
+ if(!empty($hurl)) {
1188
+ $key = hash('adler32', $hurl);
1189
+ if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
1190
+ }
1191
+
1192
+ # array of info to save
1193
+ $arr = array('handle'=>$handle, 'url'=>$hurl, 'conditional'=>$conditional, 'mediatype'=>$mediatype);
1194
+
1195
+ # google fonts to the top (collect and skip process array)
1196
+ if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1197
+ if(!$skip_google_fonts) { $google_fonts[$handle] = $hurl; } else { wp_enqueue_style($handle); } # skip google fonts optimization?
1198
+ continue;
1199
+ }
1200
+
1201
+ # all else
1202
+ $process[$handle] = $arr;
1203
+
1204
+ endforeach;
1205
+
1206
+
1207
+ # concat google fonts, if enabled
1208
+ if(!$skip_google_fonts && count($google_fonts) > 0) {
1209
+ $concat_google_fonts = fastvelocity_min_concatenate_google_fonts($google_fonts);
1210
+ foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1211
+ if($force_inline_googlefonts == false) {
1212
+ wp_enqueue_style('header-fvm-fonts', fvm_get_protocol($concat_google_fonts), array(), null, 'all');
1213
+ } else {
1214
+
1215
+ # google fonts download and inlining, ignore logs
1216
+ $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1217
+ $newcode = false; $newcode = get_transient($tkey);
1218
+ if ( $newcode === false) {
1219
+ $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_minification, 'css');
1220
+ if(is_array($res)) { $newcode = $res['code']; }
1221
+ }
1222
+
1223
+ # inline css or fail
1224
+ if($newcode !== false) {
1225
+ echo '<style type="text/css" media="all">'.$newcode.'</style>'."\n";
1226
+ } else {
1227
+ echo "<!-- GOOGLE FONTS REQUEST FAILED for $concat_google_fonts -->\n"; # log if failed
1228
+ }
1229
+ }
1230
+ }
1231
+
1232
+
1233
+
1234
+
1235
+ # get groups of handles
1236
+ foreach( $styles->to_do as $handle ) :
1237
+
1238
+ # skip already processed google fonts and empty dependencies
1239
+ if(isset($google_fonts[$handle])) { continue; } # skip google fonts
1240
+ if(empty($wp_styles->registered[$handle]->src)) { continue; } # skip empty src
1241
+ if (fastvelocity_min_in_arrayi($handle, $done)) { continue; } # skip if marked as done before
1242
+ if (!isset($process[$handle])) { continue; } # skip if not on our unique process list
1243
+
1244
+ # get full url
1245
+ $hurl = $process[$handle]['url'];
1246
+ $conditional = $process[$handle]['conditional'];
1247
+ $mediatype = $process[$handle]['mediatype'];
1248
+
1249
+ # IE only files don't increment things
1250
+ $ieonly = fastvelocity_ie_blacklist($hurl);
1251
+ if($ieonly == true) { continue; }
1252
+
1253
+ # skip ignore list, conditional css, external css
1254
+ if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1255
+
1256
+ # colect inline css for this handle
1257
+ if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
1258
+ $inline_css[$handle] = fastvelocity_min_minify_css_string(implode('', $wp_styles->registered[$handle]->extra['after'])); # save
1259
+ $wp_styles->registered[$handle]->extra['after'] = null; # dequeue
1260
+ }
1261
+
1262
+ # process
1263
+ if(isset($header[count($header)-1]['handle']) || count($header) == 0 || $header[count($header)-1]['media'] != $mediatype) {
1264
+ array_push($header, array('handles'=>array(), 'media'=>$mediatype));
1265
+ }
1266
+
1267
+ # push it to the array
1268
+ array_push($header[count($header)-1]['handles'], $handle);
1269
+
1270
+ # collect generated file urls, except print
1271
+ if ($mediatype != 'print') { $GLOBALS['used_css_files'][] = $hurl; }
1272
+
1273
+ # external and ignored css
1274
+ } else {
1275
+
1276
+ # collect generated file urls for gulp, except print and conditionals
1277
+ if ($mediatype != 'print' && !isset($conditional)) { $GLOBALS['used_css_files'][] = $hurl; }
1278
+
1279
+ # normal enqueuing
1280
+ array_push($header, array('handle'=>$handle));
1281
+ }
1282
+ endforeach;
1283
+
1284
+
1285
+ # reorder CSS by mediatypes
1286
+ if(!$skip_cssorder) {
1287
+ if(count($header) > 0) {
1288
+
1289
+ # get unique mediatypes
1290
+ $allmedia = array();
1291
+ foreach($header as $array) {
1292
+ if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1293
+ }
1294
+
1295
+ # extract handles by mediatype
1296
+ $grouphandles = array();
1297
+ foreach ($allmedia as $md=>$var) {
1298
+ foreach($header as $array) {
1299
+ if (isset($array['media']) && $array['media'] == $md) {
1300
+ foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1301
+ }
1302
+ }
1303
+ }
1304
+
1305
+ # reset and reorder header by mediatypes
1306
+ $newheader = array();
1307
+ foreach ($allmedia as $md=>$var) { $newheader[] = array('handles' => $grouphandles[$md], 'media'=>$md); }
1308
+ if(count($newheader) > 0) { $header = $newheader; }
1309
+ }
1310
+ }
1311
+
1312
+
1313
+ # critical path
1314
+ if(!empty($critical_path_css) && $critical_path_css != false) {
1315
+ if($send_css_to_footer != false) {
1316
+ echo '<style id="critical-path-global" type="text/css" media="all">'.$critical_path_css.'</style>'."\n";
1317
+ }
1318
+ }
1319
+
1320
+
1321
+ # loop through header css and merge
1322
+ for($i=0,$l=count($header);$i<$l;$i++) {
1323
+ if(!isset($header[$i]['handle'])) {
1324
+
1325
+ # get has for the inline css in this group
1326
+ $inline_css_group = array();
1327
+ foreach($header[$i]['handles'] as $h) { if(isset($inline_css[$h]) && !empty($inline_css[$h])) { $inline_css_group[] = $inline_css[$h]; } }
1328
+ $inline_css_hash = md5(implode('',$inline_css_group));
1329
+
1330
+ # static cache file info + done
1331
+ $done = array_merge($done, $header[$i]['handles']);
1332
+ $hash = 'header-'.hash('adler32',implode('',$header[$i]['handles']).$inline_css_hash);
1333
+
1334
+ # create cache files and urls
1335
+ $file = $cachedir.'/'.$hash.'-'.$ctime.'.min.css';
1336
+ $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'-'.$ctime.'.min.css');
1337
+
1338
+ # generate a new cache file
1339
+ if (!file_exists($file)) {
1340
+
1341
+ # code and log initialization
1342
+ $log = '';
1343
+ $code = '';
1344
+
1345
+ # minify and write to file
1346
+ foreach($header[$i]['handles'] as $handle) :
1347
+ if(!empty($wp_styles->registered[$handle]->src)) {
1348
+
1349
+ # get hurl per handle
1350
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1351
+ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1352
+
1353
+ # get css from hurl, if available and valid
1354
+ $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1355
+ $newcode = false; $newcode = get_transient($tkey);
1356
+ if ( $newcode === false) {
1357
+ $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css');
1358
+ if(is_array($res)) {
1359
+ $newcode = $res['code'];
1360
+ $newlog = $res['log'];
1361
+ }
1362
+ } else {
1363
+ $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1364
+ }
1365
+
1366
+ # append
1367
+ if($newcode !== false) {
1368
+ $code.= $newcode;
1369
+ if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) { $code.= $inline_css[$handle]; } # add inline css on the fly
1370
+ $log.= $newlog;
1371
+ }
1372
+
1373
+ # consider dependencies on handles with an empty src
1374
+ } else {
1375
+ wp_dequeue_script($handle); wp_enqueue_script($handle);
1376
+ }
1377
+ endforeach;
1378
+
1379
+ # prepare log
1380
+ $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1381
+
1382
+ # generate cache, write log
1383
+ file_put_contents($file.'.txt', $log);
1384
+ file_put_contents($file, $code);
1385
+ file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1386
+
1387
+ }
1388
+
1389
+ # register and enqueue minified file, consider excluding of mediatype "print" and inline css
1390
+ if ($remove_print_mediatypes != 1 || ($remove_print_mediatypes == 1 && $header[$i]['media'] != 'print')) {
1391
+ if($force_inline_css != false) {
1392
+ echo '<style type="text/css" media="'.$header[$i]['media'].'">'.file_get_contents($file).'</style>';
1393
+ } else {
1394
+
1395
+ # move CSS to footer ?
1396
+ if($send_css_to_footer != false) {
1397
+ if($critical_css_tester != true) {
1398
+ echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$header[$i]['media'].'" onload="this.rel=\'stylesheet\'">';
1399
+ echo '<noscript><link rel="stylesheet" type="text/css" media="'.$header[$i]['media'].'" href="'.$file_url.'"></noscript>';
1400
+ echo '<!--[if IE]><link rel="stylesheet" type="text/css" media="'.$header[$i]['media'].'" href="'.$file_url.'"><![endif]-->';
1401
+ }
1402
+ } else {
1403
+
1404
+ # default
1405
+ wp_register_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
1406
+ wp_enqueue_style("fvm-header-$i");
1407
+
1408
+ }
1409
+ }
1410
+ }
1411
+
1412
+ # other css need to be requeued for the order of files to be kept
1413
+ } else {
1414
+ wp_dequeue_style($header[$i]['handle']); wp_enqueue_style($header[$i]['handle']);
1415
+ }
1416
+ }
1417
+
1418
+ # remove from queue
1419
+ $wp_styles->done = $done;
1420
+
1421
+ }
1422
+ ###########################################
1423
+
1424
+
1425
+ ###########################################
1426
+ # process css in the footer ###############
1427
+ ###########################################
1428
+ function fastvelocity_min_merge_footer_css() {
1429
+ global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_css_footer, $force_inline_googlefonts, $send_css_to_footer, $critical_css_tester;
1430
+ if(!is_object($wp_styles)) { return false; }
1431
+ $ctime = get_option('fvm-last-cache-update', '0');
1432
+ $styles = wp_clone($wp_styles);
1433
+ $styles->all_deps($styles->queue);
1434
+ $done = $styles->done;
1435
+ $footer = array();
1436
+ $google_fonts = array();
1437
+ $inline_css = array();
1438
+
1439
+ # add defaults to ignore list
1440
+ $ignore = fastvelocity_default_ignore($ignore);
1441
+
1442
+
1443
+ # google fonts to the top
1444
+ foreach( $styles->to_do as $handle ) :
1445
+ # dequeue and get a list of google fonts, or requeue external
1446
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1447
+ if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1448
+ wp_dequeue_style($handle);
1449
+ if(!$skip_google_fonts) { $google_fonts[$handle] = $hurl; } else { wp_enqueue_style($handle); } # skip google fonts optimization?
1450
+ } else {
1451
+ wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
1452
+ }
1453
+ endforeach;
1454
+
1455
+
1456
+ # concat google fonts, if enabled
1457
+ if(!$skip_google_fonts && count($google_fonts) > 0) {
1458
+ $concat_google_fonts = fastvelocity_min_concatenate_google_fonts($google_fonts);
1459
+ foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1460
+ if($force_inline_googlefonts == false) {
1461
+ wp_enqueue_style('footer-fvm-fonts', fvm_get_protocol($concat_google_fonts), array(), null, 'all');
1462
+ } else {
1463
+
1464
+ # google fonts download and inlining, ignore logs
1465
+ $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1466
+ $newcode = false; $newcode = get_transient($tkey);
1467
+ if ( $newcode === false) {
1468
+ $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
1469
+ if(is_array($res)) { $newcode = $res['code']; }
1470
+ }
1471
+
1472
+ # inline css or fail
1473
+ if($newcode !== false) {
1474
+ echo '<style type="text/css" media="all">'.$newcode.'</style>';
1475
+ } else {
1476
+ echo "<!-- GOOGLE FONTS REQUEST FAILED for $concat_google_fonts -->\n"; # log if failed
1477
+ }
1478
+ }
1479
+ }
1480
+
1481
+
1482
+ # get groups of handles
1483
+ foreach( $styles->to_do as $handle ) :
1484
+
1485
+ # skip already processed google fonts
1486
+ if(isset($google_fonts[$handle])) { continue; }
1487
+
1488
+ # get full url
1489
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1490
+
1491
+ # media type
1492
+ $media = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
1493
+
1494
+ # IE only files don't increment things
1495
+ $ieonly = fastvelocity_ie_blacklist($hurl);
1496
+ if($ieonly == true) { continue; }
1497
+
1498
+ # conditionals
1499
+ $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
1500
+ $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
1501
+ }
1502
+
1503
+ # skip ignore list, conditional css, external css
1504
+ if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1505
+
1506
+ # colect inline css for this handle
1507
+ if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
1508
+ $inline_css[$handle] = fastvelocity_min_minify_css_string(implode('', $wp_styles->registered[$handle]->extra['after'])); # save
1509
+ $wp_styles->registered[$handle]->extra['after'] = null; # dequeue
1510
+ }
1511
+
1512
+ # process
1513
+ if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0 || $footer[count($footer)-1]['media'] != $wp_styles->registered[$handle]->args) {
1514
+ array_push($footer, array('handles'=>array(),'media'=>$media));
1515
+ }
1516
+
1517
+ # push it to the array get latest modified time
1518
+ array_push($footer[count($footer)-1]['handles'], $handle);
1519
+
1520
+ # collect generated file urls for gulp, except print
1521
+ if ($media != 'print') { $GLOBALS['used_css_files'][] = $hurl; }
1522
+
1523
+ # external and ignored css
1524
+ } else {
1525
+
1526
+ # collect generated file urls for gulp, except print and conditionals
1527
+ if ($media != 'print' && !isset($conditional)) { $GLOBALS['used_css_files'][] = $hurl; }
1528
+
1529
+ # normal enqueueing
1530
+ array_push($footer, array('handle'=>$handle));
1531
+ }
1532
+ endforeach;
1533
+
1534
+
1535
+ # reorder CSS by mediatypes
1536
+ if(!$skip_cssorder) {
1537
+ if(count($footer) > 0) {
1538
+
1539
+ # get unique mediatypes
1540
+ $allmedia = array();
1541
+ foreach($footer as $key=>$array) {
1542
+ if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1543
+ }
1544
+
1545
+ # extract handles by mediatype
1546
+ $grouphandles = array();
1547
+ foreach ($allmedia as $md=>$var) {
1548
+ foreach($footer as $array) {
1549
+ if (isset($array['media']) && $array['media'] == $md) {
1550
+ foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1551
+ }
1552
+ }
1553
+ }
1554
+
1555
+ # reset and reorder footer by mediatypes
1556
+ $newfooter = array();
1557
+ foreach ($allmedia as $md=>$var) { $newfooter[] = array('handles' => $grouphandles[$md], 'media'=>$md); }
1558
+ if(count($newfooter) > 0) { $footer = $newfooter; }
1559
+ }
1560
+ }
1561
+
1562
+ # loop through footer css and merge
1563
+ for($i=0,$l=count($footer);$i<$l;$i++) {
1564
+ if(!isset($footer[$i]['handle'])) {
1565
+
1566
+ # get has for the inline css in this group
1567
+ $inline_css_group = array();
1568
+ foreach($footer[$i]['handles'] as $h) { if(isset($inline_css[$h]) && !empty($inline_css[$h])) { $inline_css_group[] = $inline_css[$h]; } }
1569
+ $inline_css_hash = md5(implode('',$inline_css_group));
1570
+
1571
+ # static cache file info + done
1572
+ $done = array_merge($done, $footer[$i]['handles']);
1573
+ $hash = 'footer-'.hash('adler32',implode('',$footer[$i]['handles']).$inline_css_hash);
1574
+
1575
+ # create cache files and urls
1576
+ $file = $cachedir.'/'.$hash.'-'.$ctime.'.min.css';
1577
+ $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'-'.$ctime.'.min.css');
1578
+
1579
+ # generate a new cache file
1580
+ if (!file_exists($file)) {
1581
+
1582
+ # code and log initialization
1583
+ $log = '';
1584
+ $code = '';
1585
+
1586
+ # minify and write to file
1587
+ foreach($footer[$i]['handles'] as $handle) :
1588
+ if(!empty($wp_styles->registered[$handle]->src)) {
1589
+
1590
+ # get hurl per handle
1591
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1592
+ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1593
+
1594
+ # get css from hurl, if available and valid
1595
+ $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1596
+ $newcode = false; $newcode = get_transient($tkey);
1597
+ if ( $newcode === false) {
1598
+ $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css');
1599
+ if(is_array($res)) {
1600
+ $newcode = $res['code'];
1601
+ $newlog = $res['log'];
1602
+ }
1603
+ } else {
1604
+ $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1605
+ }
1606
+
1607
+ # append
1608
+ if($newcode !== false) {
1609
+ $code.= $newcode;
1610
+ if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) { $code.= $inline_css[$handle]; } # add inline css on the fly
1611
+ $log.= $newlog;
1612
+ }
1613
+
1614
+ # consider dependencies on handles with an empty src
1615
+ } else {
1616
+ wp_dequeue_script($handle); wp_enqueue_script($handle);
1617
+ }
1618
+ endforeach;
1619
+
1620
+ # prepare log
1621
+ $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1622
+
1623
+ # generate cache, add inline css, write log
1624
+ file_put_contents($file.'.txt', $log);
1625
+ file_put_contents($file, $code); # preserve style tags
1626
+ file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1627
+
1628
+ }
1629
+
1630
+ # register and enqueue minified file, consider excluding of mediatype "print" and inline css
1631
+ if ($remove_print_mediatypes != 1 || ($remove_print_mediatypes == 1 && $footer[$i]['media'] != 'print')) {
1632
+ if($force_inline_css_footer != false) {
1633
+ echo '<style type="text/css" media="'.$footer[$i]['media'].'">'.file_get_contents($file).'</style>';
1634
+ } else {
1635
+
1636
+ # move CSS to footer
1637
+ if($send_css_to_footer != false) {
1638
+
1639
+ if($critical_css_tester != true) {
1640
+ echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$footer[$i]['media'].'" onload="this.rel=\'stylesheet\'">';
1641
+ echo '<noscript><link rel="stylesheet" type="text/css" media="'.$footer[$i]['media'].'" href="'.$file_url.'"></noscript>';
1642
+ echo '<!--[if IE]><link rel="stylesheet" type="text/css" media="'.$footer[$i]['media'].'" href="'.$file_url.'"><![endif]-->';
1643
+ }
1644
+
1645
+ } else {
1646
+
1647
+ # default
1648
+ wp_register_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
1649
+ wp_enqueue_style("fvm-footer-$i");
1650
+
1651
+ }
1652
+ }
1653
+ }
1654
+
1655
+ # other css need to be requeued for the order of files to be kept
1656
+ } else {
1657
+ wp_dequeue_style($footer[$i]['handle']); wp_enqueue_style($footer[$i]['handle']);
1658
+ }
1659
+ }
1660
+
1661
+ # remove from queue
1662
+ $wp_styles->done = $done;
1663
+ }
1664
+ ###########################################
1665
+
1666
+
1667
+
1668
+
1669
+ ###########################################
1670
+ # defer CSS globally from the header (order matters)
1671
+ ###########################################
1672
+ function fvm_movecss_to_footer_header() {
1673
+ global $send_css_to_footer;
1674
+ if($send_css_to_footer != false) {
1675
+
1676
+ # echo LoadCSS scripts
1677
+ echo '<script>
1678
+ /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
1679
+ !function(a){"use strict";var b=function(b,c,d){function e(a){return h.body?a():void setTimeout(function(){e(a)})}function f(){i.addEventListener&&i.removeEventListener("load",f),i.media=d||"all"}var g,h=a.document,i=h.createElement("link");if(c)g=c;else{var j=(h.body||h.getElementsByTagName("head")[0]).childNodes;g=j[j.length-1]}var k=h.styleSheets;i.rel="stylesheet",i.href=b,i.media="only x",e(function(){g.parentNode.insertBefore(i,c?g:g.nextSibling)});var l=function(a){for(var b=i.href,c=k.length;c--;)if(k[c].href===b)return a();setTimeout(function(){l(a)})};return i.addEventListener&&i.addEventListener("load",f),i.onloadcssdefined=l,l(f),i};"undefined"!=typeof exports?exports.loadCSS=b:a.loadCSS=b}("undefined"!=typeof global?global:this);
1680
+ /*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
1681
+ !function(a){if(a.loadCSS){var b=loadCSS.relpreload={};if(b.support=function(){try{return a.document.createElement("link").relList.supports("preload")}catch(b){return!1}},b.poly=function(){for(var b=a.document.getElementsByTagName("link"),c=0;c<b.length;c++){var d=b[c];"preload"===d.rel&&"style"===d.getAttribute("as")&&(a.loadCSS(d.href,d,d.getAttribute("media")),d.rel=null)}},!b.support()){b.poly();var c=a.setInterval(b.poly,300);a.addEventListener&&a.addEventListener("load",function(){b.poly(),a.clearInterval(c)}),a.attachEvent&&a.attachEvent("onload",function(){a.clearInterval(c)})}}}(this);
1682
+ </script>';
1683
+
1684
+ } }
1685
+
1686
+ if (!is_admin()) { add_action('wp_head', 'fvm_movecss_to_footer_header', PHP_INT_MAX); }
1687
+ ###########################################
1688
+
1689
+
1690
+
1691
+ ###########################################
1692
+ # generate gulp-uncss files for this page (dev only)
1693
+ ###########################################
1694
+ function fvm_generate_gulp_uncss() {
1695
+ global $wp, $generate_gulp_files, $generate_gulp_path;
1696
+
1697
+ if(isset($GLOBALS['used_css_files']) && $generate_gulp_files != false && !empty($generate_gulp_path)) {
1698
+
1699
+ # some paths and urls
1700
+ $currenturl = fvm_get_protocol($_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]);
1701
+ $file = sanitize_title($currenturl);
1702
+ $save = get_stylesheet_directory().'/criticalcss/css/'.$file.'.css';
1703
+ $generate_gulp_path = rtrim(trim($generate_gulp_path), '/');
1704
+ $generate_gulp_path_out = $generate_gulp_path.'/out/';
1705
+ if(!is_dir($generate_gulp_path_out) && is_writable($generate_gulp_path_out)) { mkdir($generate_gulp_path_out); }
1706
+ $gulpfile = "$generate_gulp_path/$file.js";
1707
+
1708
+ # process
1709
+ if(!file_exists($save) && !file_exists($gulpfile) && is_dir($generate_gulp_path_out)) {
1710
+
1711
+ $cssfiles = json_encode($GLOBALS['used_css_files'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
1712
+
1713
+ # gulp tasks
1714
+ $gulptask = <<<EOF
1715
+ var gulp = require('gulp');
1716
+ var uncss = require('gulp-uncss');
1717
+ var concat = require('gulp-concat');
1718
+ var nano = require('gulp-cssnano');
1719
+ var remoteSrc = require('gulp-remote-src');
1720
+ gulp.task('uncss', function() {
1721
+ remoteSrc($cssfiles, { base: null })
1722
+ .pipe(concat('$file.css'))
1723
+ .pipe(uncss({ html: ['$currenturl'] }))
1724
+ .pipe(nano())
1725
+ .pipe(gulp.dest('$generate_gulp_path/out/'));
1726
+ });
1727
+ EOF;
1728
+
1729
+ # write gulp file
1730
+ file_put_contents($gulpfile, $gulptask);
1731
+
1732
+ }
1733
+ }
1734
+ }
1735
+
1736
+ if (!is_admin()) { add_action('wp_footer', 'fvm_generate_gulp_uncss', PHP_INT_MAX); }
1737
+
1738
+
1739
+
1740
+ ###########################################
1741
+ # add preconnect and preload headers
1742
+ ###########################################
1743
+ function fvm_buffer_placeholder_top() {
1744
+ global $preload, $preconnect;
1745
+
1746
+ # defaults
1747
+ $meta = array();
1748
+
1749
+ # preconnect resources
1750
+ # https://css-tricks.com/prefetching-preloading-prebrowsing/
1751
+ if(count($preconnect) > 0) {
1752
+ $a = array(); foreach ($preconnect as $b) {
1753
+ if(!empty($b)) { $a[] = '<link href="'.str_ireplace(array('http://', 'https://'), '//', $b).'" rel="preconnect">'; }
1754
+ }
1755
+ if(count($a) > 0) { $meta[] = implode('', $a); }
1756
+ }
1757
+
1758
+ # preload resources (beta: homepage only)
1759
+ # https://css-tricks.com/prefetching-preloading-prebrowsing/
1760
+ if((is_home() || is_front_page()) && count($preload) > 0) {
1761
+ $a = array();
1762
+ foreach ($preload as $b) {
1763
+ if(!empty($b)) {
1764
+ $meta[] = '<link rel="preload" as="image" href="'.str_ireplace(array('http://', 'https://'), '//', $b).'">';
1765
+ }
1766
+ }
1767
+ }
1768
+
1769
+ # output on top
1770
+ echo implode('', $meta);
1771
+ }
1772
+
1773
+ # remove query from static assets and process defering (if enabled)
1774
+ if (!is_admin()) {
1775
+ add_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
1776
+ add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
1777
+ }
1778
+
1779
+ # enable html minification
1780
+ if(!$skip_html_minification && !is_admin()) {
1781
+ add_action('get_header', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
1782
+ }
1783
+
inc/functions.php CHANGED
@@ -221,12 +221,13 @@ else { ob_start('fastvelocity_min_html_compression_finish'); }
221
 
222
  # alternative html minification, minimal
223
  function fastvelocity_min_minify_alt_html($html) {
224
- $html = trim(preg_replace('/\v(?:[\t\v\h]+)/', "\n", $html));
225
- $html = trim(preg_replace('/\t(?:[\t\v\h]+)/', ' ', $html));
226
- $html = trim(preg_replace('/\h(?:[\t\v\h]+)/', ' ', $html));
227
  return $html;
228
  }
229
 
 
230
  # remove all cache files
231
  function fastvelocity_rrmdir($dir) {
232
  if(is_dir(rtrim($dir, '/'))) {
221
 
222
  # alternative html minification, minimal
223
  function fastvelocity_min_minify_alt_html($html) {
224
+ $html = trim(preg_replace('/\v(?:[\t\v\h]+)/iu', "\n", $html));
225
+ $html = trim(preg_replace('/\t(?:[\t\v\h]+)/iu', ' ', $html));
226
+ $html = trim(preg_replace('/\h(?:[\t\v\h]+)/iu', ' ', $html));
227
  return $html;
228
  }
229
 
230
+
231
  # remove all cache files
232
  function fastvelocity_rrmdir($dir) {
233
  if(is_dir(rtrim($dir, '/'))) {
libs/mrclay/HTML.php CHANGED
@@ -1,241 +1,241 @@
1
- <?php
2
-
3
- /* https://github.com/mrclay/minify/blob/2.x/min/lib/Minify/HTML.php - same as WP ROCKET v2.91 + custom changes */
4
- # line:
5
-
6
- class fastvelocity_min_Minify_HTML {
7
- protected $_jsCleanComments = true;
8
-
9
- /**
10
- * "Minify" an HTML page
11
- *
12
- * @param string $html
13
- *
14
- * @param array $options
15
- *
16
- * 'cssMinifier' : (optional) callback function to process content of STYLE
17
- * elements.
18
- *
19
- * 'jsMinifier' : (optional) callback function to process content of SCRIPT
20
- * elements. Note: the type attribute is ignored.
21
- *
22
- * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
23
- * unset, minify will sniff for an XHTML doctype.
24
- *
25
- * @return string
26
- */
27
- public static function minify($html, $options = array()) {
28
- $min = new self($html, $options);
29
- return $min->process();
30
- }
31
-
32
-
33
- /**
34
- * Create a minifier object
35
- *
36
- * @param string $html
37
- *
38
- * @param array $options
39
- *
40
- * 'cssMinifier' : (optional) callback function to process content of STYLE
41
- * elements.
42
- *
43
- * 'jsMinifier' : (optional) callback function to process content of SCRIPT
44
- * elements. Note: the type attribute is ignored.
45
- *
46
- * 'jsCleanComments' : (optional) whether to remove HTML comments beginning and end of script block
47
- *
48
- * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
49
- * unset, minify will sniff for an XHTML doctype.
50
- */
51
- public function __construct($html, $options = array())
52
- {
53
- $this->_html = str_replace("\r\n", "\n", trim($html));
54
- if (isset($options['xhtml'])) {
55
- $this->_isXhtml = (bool)$options['xhtml'];
56
- }
57
- if (isset($options['cssMinifier'])) {
58
- $this->_cssMinifier = $options['cssMinifier'];
59
- }
60
- if (isset($options['jsMinifier'])) {
61
- $this->_jsMinifier = $options['jsMinifier'];
62
- }
63
- if (isset($options['jsCleanComments'])) {
64
- $this->_jsCleanComments = (bool)$options['jsCleanComments'];
65
- }
66
- }
67
-
68
-
69
- /**
70
- * Minify the markeup given in the constructor
71
- *
72
- * @return string
73
- */
74
- public function process()
75
- {
76
- if ($this->_isXhtml === null) {
77
- $this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
78
- }
79
-
80
- $this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
81
- $this->_placeholders = array();
82
-
83
- // replace SCRIPTs (and minify) with placeholders
84
- $this->_html = preg_replace_callback(
85
- '/(\\s*)<script(\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
86
- ,array($this, '_removeScriptCB')
87
- ,$this->_html);
88
-
89
- // replace STYLEs (and minify) with placeholders
90
- $this->_html = preg_replace_callback(
91
- '/\\s*<style(\\b[^>]*>)([\\s\\S]*?)<\\/style>\\s*/i'
92
- ,array($this, '_removeStyleCB')
93
- ,$this->_html);
94
-
95
- // remove HTML comments (not containing IE conditional comments).
96
- global $strip_htmlcomments;
97
- if($strip_htmlcomments) {
98
- $this->_html = preg_replace_callback('/<!--([\\s\\S]*?)-->/' ,array($this, '_commentCB') ,$this->_html);
99
- }
100
-
101
- // replace PREs with placeholders
102
- $this->_html = preg_replace_callback('/\\s*<pre(\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
103
- ,array($this, '_removePreCB')
104
- ,$this->_html);
105
-
106
- // replace TEXTAREAs with placeholders
107
- $this->_html = preg_replace_callback(
108
- '/\\s*<textarea(\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
109
- ,array($this, '_removeTextareaCB')
110
- ,$this->_html);
111
-
112
- // trim each line.
113
- // @todo take into account attribute values that span multiple lines.
114
- $this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
115
-
116
- // remove ws around block/undisplayed elements
117
- $this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
118
- .'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
119
- .'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
120
- .'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
121
- .'|ul)\\b[^>]*>)/i', '$1', $this->_html);
122
-
123
- // remove ws outside of all elements
124
- $this->_html = preg_replace_callback(
125
- '/>([^<]+)</'
126
- ,array($this, '_outsideTagCB')
127
- ,$this->_html);
128
-
129
- // use newlines before 1st attribute in open tags (to limit line lengths)
130
- //$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
131
-
132
- // fill placeholders
133
- $this->_html = str_replace(
134
- array_keys($this->_placeholders)
135
- ,array_values($this->_placeholders)
136
- ,$this->_html
137
- );
138
- // issue 229: multi-pass to catch scripts that didn't get replaced in textareas
139
- $this->_html = str_replace(
140
- array_keys($this->_placeholders)
141
- ,array_values($this->_placeholders)
142
- ,$this->_html
143
- );
144
- return $this->_html;
145
- }
146
-
147
- protected function _commentCB($m)
148
- {
149
- return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<![') || 0 === strpos($m[1], 'esi')) ? $m[0] : '';
150
- }
151
-
152
- protected function _reservePlace($content)
153
- {
154
- $placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
155
- $this->_placeholders[$placeholder] = $content;
156
- return $placeholder;
157
- }
158
-
159
- protected $_isXhtml = null;
160
- protected $_replacementHash = null;
161
- protected $_placeholders = array();
162
- protected $_cssMinifier = null;
163
- protected $_jsMinifier = null;
164
-
165
- protected function _outsideTagCB($m)
166
- {
167
- return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
168
- }
169
-
170
- protected function _removePreCB($m)
171
- {
172
- return $this->_reservePlace("<pre{$m[1]}");
173
- }
174
-
175
- protected function _removeTextareaCB($m)
176
- {
177
- return $this->_reservePlace("<textarea{$m[1]}");
178
- }
179
-
180
- protected function _removeStyleCB($m)
181
- {
182
- $openStyle = "<style{$m[1]}";
183
- $css = $m[2];
184
- // remove css comments
185
- $css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
186
-
187
- // remove CDATA section markers
188
- $css = $this->_removeCdata($css);
189
-
190
- // minify
191
- $minifier = $this->_cssMinifier ? $this->_cssMinifier : 'trim';
192
- $css = call_user_func($minifier, $css);
193
- $css = preg_replace('/\s+/', ' ', $css);
194
-
195
- return $this->_reservePlace($this->_needsCdata($css)
196
- ? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
197
- : "{$openStyle}{$css}</style>"
198
- );
199
- }
200
-
201
- protected function _removeScriptCB($m)
202
- {
203
- $openScript = "<script{$m[2]}";
204
- $js = $m[3];
205
-
206
- // whitespace surrounding? preserve at least one space
207
- $ws1 = ($m[1] === '') ? '' : ' ';
208
- $ws2 = ($m[4] === '') ? '' : ' ';
209
-
210
- // remove HTML comments (and ending "//" if present)
211
- if ($this->_jsCleanComments) {
212
- $js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
213
- }
214
-
215
- // remove CDATA section markers
216
- $js = $this->_removeCdata($js);
217
-
218
- // minify
219
- $minifier = $this->_jsMinifier
220
- ? $this->_jsMinifier
221
- : 'trim';
222
- $js = call_user_func($minifier, $js);
223
-
224
- return $this->_reservePlace($this->_needsCdata($js)
225
- ? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
226
- : "{$ws1}{$openScript}{$js}</script>{$ws2}"
227
- );
228
- }
229
-
230
- protected function _removeCdata($str)
231
- {
232
- return (false !== strpos($str, '<![CDATA['))
233
- ? str_replace(array('<![CDATA[', ']]>'), '', $str)
234
- : $str;
235
- }
236
-
237
- protected function _needsCdata($str)
238
- {
239
- return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
240
- }
241
- }
1
+ <?php
2
+
3
+ /* https://github.com/mrclay/minify/blob/2.x/min/lib/Minify/HTML.php - same as WP ROCKET v2.91 + custom changes */
4
+ # line:
5
+
6
+ class fastvelocity_min_Minify_HTML {
7
+ protected $_jsCleanComments = true;
8
+
9
+ /**
10
+ * "Minify" an HTML page
11
+ *
12
+ * @param string $html
13
+ *
14
+ * @param array $options
15
+ *
16
+ * 'cssMinifier' : (optional) callback function to process content of STYLE
17
+ * elements.
18
+ *
19
+ * 'jsMinifier' : (optional) callback function to process content of SCRIPT
20
+ * elements. Note: the type attribute is ignored.
21
+ *
22
+ * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
23
+ * unset, minify will sniff for an XHTML doctype.
24
+ *
25
+ * @return string
26
+ */
27
+ public static function minify($html, $options = array()) {
28
+ $min = new self($html, $options);
29
+ return $min->process();
30
+ }
31
+
32
+
33
+ /**
34
+ * Create a minifier object
35
+ *
36
+ * @param string $html
37
+ *
38
+ * @param array $options
39
+ *
40
+ * 'cssMinifier' : (optional) callback function to process content of STYLE
41
+ * elements.
42
+ *
43
+ * 'jsMinifier' : (optional) callback function to process content of SCRIPT
44
+ * elements. Note: the type attribute is ignored.
45
+ *
46
+ * 'jsCleanComments' : (optional) whether to remove HTML comments beginning and end of script block
47
+ *
48
+ * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
49
+ * unset, minify will sniff for an XHTML doctype.
50
+ */
51
+ public function __construct($html, $options = array())
52
+ {
53
+ $this->_html = str_replace("\r\n", "\n", trim($html));
54
+ if (isset($options['xhtml'])) {
55
+ $this->_isXhtml = (bool)$options['xhtml'];
56
+ }
57
+ if (isset($options['cssMinifier'])) {
58
+ $this->_cssMinifier = $options['cssMinifier'];
59
+ }
60
+ if (isset($options['jsMinifier'])) {
61
+ $this->_jsMinifier = $options['jsMinifier'];
62
+ }
63
+ if (isset($options['jsCleanComments'])) {
64
+ $this->_jsCleanComments = (bool)$options['jsCleanComments'];
65
+ }
66
+ }
67
+
68
+
69
+ /**
70
+ * Minify the markeup given in the constructor
71
+ *
72
+ * @return string
73
+ */
74
+ public function process()
75
+ {
76
+ if ($this->_isXhtml === null) {
77
+ $this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
78
+ }
79
+
80
+ $this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
81
+ $this->_placeholders = array();
82
+
83
+ // replace SCRIPTs (and minify) with placeholders
84
+ $this->_html = preg_replace_callback(
85
+ '/(\\s*)<script(\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
86
+ ,array($this, '_removeScriptCB')
87
+ ,$this->_html);
88
+
89
+ // replace STYLEs (and minify) with placeholders
90
+ $this->_html = preg_replace_callback(
91
+ '/\\s*<style(\\b[^>]*>)([\\s\\S]*?)<\\/style>\\s*/i'
92
+ ,array($this, '_removeStyleCB')
93
+ ,$this->_html);
94
+
95
+ // remove HTML comments (not containing IE conditional comments).
96
+ global $strip_htmlcomments;
97
+ if($strip_htmlcomments) {
98
+ $this->_html = preg_replace_callback('/<!--([\\s\\S]*?)-->/' ,array($this, '_commentCB') ,$this->_html);
99
+ }
100
+
101
+ // replace PREs with placeholders
102
+ $this->_html = preg_replace_callback('/\\s*<pre(\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
103
+ ,array($this, '_removePreCB')
104
+ ,$this->_html);
105
+
106
+ // replace TEXTAREAs with placeholders
107
+ $this->_html = preg_replace_callback(
108
+ '/\\s*<textarea(\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
109
+ ,array($this, '_removeTextareaCB')
110
+ ,$this->_html);
111
+
112
+ // trim each line.
113
+ // @todo take into account attribute values that span multiple lines.
114
+ $this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
115
+
116
+ // remove ws around block/undisplayed elements
117
+ $this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
118
+ .'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
119
+ .'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
120
+ .'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
121
+ .'|ul)\\b[^>]*>)/i', '$1', $this->_html);
122
+
123
+ // remove ws outside of all elements
124
+ $this->_html = preg_replace_callback(
125
+ '/>([^<]+)</'
126
+ ,array($this, '_outsideTagCB')
127
+ ,$this->_html);
128
+
129
+ // use newlines before 1st attribute in open tags (to limit line lengths)
130
+ //$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
131
+
132
+ // fill placeholders
133
+ $this->_html = str_replace(
134
+ array_keys($this->_placeholders)
135
+ ,array_values($this->_placeholders)
136
+ ,$this->_html
137
+ );
138
+ // issue 229: multi-pass to catch scripts that didn't get replaced in textareas
139
+ $this->_html = str_replace(
140
+ array_keys($this->_placeholders)
141
+ ,array_values($this->_placeholders)
142
+ ,$this->_html
143
+ );
144
+ return $this->_html;
145
+ }
146
+
147
+ protected function _commentCB($m)
148
+ {
149
+ return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<![') || 0 === strpos($m[1], 'esi')) ? $m[0] : '';
150
+ }
151
+
152
+ protected function _reservePlace($content)
153
+ {
154
+ $placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
155
+ $this->_placeholders[$placeholder] = $content;
156
+ return $placeholder;
157
+ }
158
+
159
+ protected $_isXhtml = null;
160
+ protected $_replacementHash = null;
161
+ protected $_placeholders = array();
162
+ protected $_cssMinifier = null;
163
+ protected $_jsMinifier = null;
164
+
165
+ protected function _outsideTagCB($m)
166
+ {
167
+ return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
168
+ }
169
+
170
+ protected function _removePreCB($m)
171
+ {
172
+ return $this->_reservePlace("<pre{$m[1]}");
173
+ }
174
+
175
+ protected function _removeTextareaCB($m)
176
+ {
177
+ return $this->_reservePlace("<textarea{$m[1]}");
178
+ }
179
+
180
+ protected function _removeStyleCB($m)
181
+ {
182
+ $openStyle = "<style{$m[1]}";
183
+ $css = $m[2];
184
+ // remove css comments
185
+ $css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
186
+
187
+ // remove CDATA section markers
188
+ $css = $this->_removeCdata($css);
189
+
190
+ // minify
191
+ $minifier = $this->_cssMinifier ? $this->_cssMinifier : 'trim';
192
+ $css = call_user_func($minifier, $css);
193
+ $css = preg_replace('/\s+/', ' ', $css);
194
+
195
+ return $this->_reservePlace($this->_needsCdata($css)
196
+ ? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
197
+ : "{$openStyle}{$css}</style>"
198
+ );
199
+ }
200
+
201
+ protected function _removeScriptCB($m)
202
+ {
203
+ $openScript = "<script{$m[2]}";
204
+ $js = $m[3];
205
+
206
+ // whitespace surrounding? preserve at least one space
207
+ $ws1 = ($m[1] === '') ? '' : ' ';
208
+ $ws2 = ($m[4] === '') ? '' : ' ';
209
+
210
+ // remove HTML comments (and ending "//" if present)
211
+ if ($this->_jsCleanComments) {
212
+ $js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
213
+ }
214
+
215
+ // remove CDATA section markers
216
+ $js = $this->_removeCdata($js);
217
+
218
+ // minify
219
+ $minifier = $this->_jsMinifier
220
+ ? $this->_jsMinifier
221
+ : 'trim';
222
+ $js = call_user_func($minifier, $js);
223
+
224
+ return $this->_reservePlace($this->_needsCdata($js)
225
+ ? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
226
+ : "{$ws1}{$openScript}{$js}</script>{$ws2}"
227
+ );
228
+ }
229
+
230
+ protected function _removeCdata($str)
231
+ {
232
+ return (false !== strpos($str, '<![CDATA['))
233
+ ? str_replace(array('<![CDATA[', ']]>'), '', $str)
234
+ : $str;
235
+ }
236
+
237
+ protected function _needsCdata($str)
238
+ {
239
+ return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
240
+ }
241
+ }
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: Alignak
3
  Tags: merge, combine, concatenate, PHP Minify, YUI Compressor, CSS, javascript, JS, minification, minify, optimization, optimize, stylesheet, aggregate, cache, CSS, html, minimize, pagespeed, performance, speed, GTmetrix, pingdom
4
  Requires at least: 4.5
5
- Stable tag: 2.2.0
6
  Tested up to: 4.8.1
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -274,6 +274,10 @@ Note: Kindly purge the plugin cache as well as your server /plugin cache after u
274
 
275
  == Changelog ==
276
 
 
 
 
 
277
  = 2.2.0 [2017.08.13] =
278
  * fixed some debug notices
279
  * fixed the alternative html minification option
2
  Contributors: Alignak
3
  Tags: merge, combine, concatenate, PHP Minify, YUI Compressor, CSS, javascript, JS, minification, minify, optimization, optimize, stylesheet, aggregate, cache, CSS, html, minimize, pagespeed, performance, speed, GTmetrix, pingdom
4
  Requires at least: 4.5
5
+ Stable tag: 2.2.1
6
  Tested up to: 4.8.1
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
274
 
275
  == Changelog ==
276
 
277
+ = 2.2.1 [2017.08.21] =
278
+ * added unicode support to the alternative html minification option
279
+ * improved some options description
280
+
281
  = 2.2.0 [2017.08.13] =
282
  * fixed some debug notices
283
  * fixed the alternative html minification option