Fast Velocity Minify - Version 2.4.4

Version Description

[2018.12.03] * added option to inline CSS in the footer, while still preserving the merged file in the header * improvements for the google fonts merging option * fixed double notification, when purging caches without a cache plugin

Download this release

Release Info

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

Code changes from version 2.4.1 to 2.4.4

fvm.css CHANGED
@@ -14,7 +14,7 @@
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; }
@@ -22,6 +22,8 @@ h3.hndle { background: #F7F7F7; color: #000;}
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}
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; cursor: default !important; }
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; }
22
.fvm-label-pad { line-height: 21px; }
23
.fvm-rowintro { padding-bottom: 10px; }
24
25
+
26
+
27
@media screen and (max-width:520px) {
28
#fastvelocity-min .processed li .filename{width: 100%;float:none;}
29
#fastvelocity-min .processed li .actions{text-align: left;margin-top: 4px}
fvm.js CHANGED
@@ -1,135 +1,59 @@
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
- // disable some checkboxes when some other is on or off
50
- $('#fastvelocity_min_fvm_removecss').bind('click init', function() {
51
- if( $(this).is(':checked')) {
52
- $("#fastvelocity_min_send_css_to_footer, #fastvelocity_min_critical_path_visibility").prop("disabled", true);
53
- $("#fastvelocity_min_critical_css_tester").prop("disabled", true);
54
- } else {
55
- $("#fastvelocity_min_send_css_to_footer, #fastvelocity_min_critical_path_visibility").prop("disabled", false);
56
- $("#fastvelocity_min_critical_css_tester").prop("disabled", false);
57
- }
58
- }).trigger('init');
59
-
60
- // disable collapse
61
- $('.postbox h3, .postbox .handlediv').unbind('click.postboxes');
62
63
- // variables
64
- var $fastvelocity_min_processed = $('#fastvelocity_min_processed'),
65
- $fastvelocity_min_jsprocessed = $('#fastvelocity_min_jsprocessed',$fastvelocity_min_processed),
66
- $fastvelocity_min_jsprocessed_ul = $('ul',$fastvelocity_min_jsprocessed),
67
- $fastvelocity_min_cssprocessed = $('#fastvelocity_min_cssprocessed',$fastvelocity_min_processed),
68
- $fastvelocity_min_cssprocessed_ul = $('ul',$fastvelocity_min_cssprocessed),
69
- $fastvelocity_min_noprocessed = $('#fastvelocity_min_noprocessed'),
70
- timeout = null,
71
- stamp = null;
72
73
- $($fastvelocity_min_processed).on('click','.log',function(e){
74
- e.preventDefault();
75
- $(this).parent().nextAll('pre').slideToggle();
76
- });
77
-
78
- function getFiles(extra) {
79
- stamp = new Date().getTime();
80
- var data = {
81
- 'action': 'fastvelocity_min_files',
82
- 'stamp': stamp
83
- };
84
- if(extra) {
85
- for (var attrname in extra) { data[attrname] = extra[attrname]; }
86
}
87
-
88
89
- $.post(ajaxurl, data, function(response) {
90
-
91
- if(response.cachesize.length > 0) {
92
- $("#fvm_cache_size").html(response.cachesize);
93
}
94
-
95
- if(stamp == response.stamp) {
96
- if(response.js.length > 0) {
97
- $fastvelocity_min_jsprocessed.show();
98
-
99
- $(response.js).each(function(){
100
- var $li = $fastvelocity_min_jsprocessed_ul.find('li.'+this.hash);
101
- if($li.length > 0) {
102
- if($li.find('pre').html() != this.log) {
103
- $li.find('pre').html(this.log);
104
- }
105
- } else {
106
- $fastvelocity_min_jsprocessed_ul.append('<li class="'+this.hash+'"><span class="filename">'+this.filename+' ('+this.fsize+')</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
107
- }
108
- });
109
-
110
- }
111
- if(response.css.length > 0) {
112
-
113
- $(response.css).each(function(){
114
- var $li = $fastvelocity_min_cssprocessed_ul.find('li.'+this.hash);
115
- if($li.length > 0) {
116
- if($li.find('pre').html() != this.log) {
117
- $li.find('pre').html(this.log);
118
- }
119
- } else {
120
- $fastvelocity_min_cssprocessed_ul.append('<li class="'+this.hash+'"><span class="filename">'+this.filename+' ('+this.fsize+')</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
121
- }
122
- });
123
- }
124
-
125
- // check for new files
126
- timeout = setTimeout(getFiles, 4000);
127
}
128
});
129
- }
130
-
131
- getFiles();
132
-
133
- });
134
135
- })(jQuery);
1
+ jQuery( document ).ready(function() {
2
+
3
+ // disable collapse
4
+ jQuery('.postbox h3, .postbox .handlediv').unbind('click.postboxes');
5
+
6
+ // show logs
7
+ jQuery('#fastvelocity_min_processed').on('click','.log',function(e){
8
+ e.preventDefault();
9
+ jQuery(this).parent().nextAll('pre').slideToggle();
10
+ });
11
+
12
+ function getFiles() {
13
+ stamp = new Date().getTime();
14
+ var data = { 'action': 'fastvelocity_min_files' };
15
16
+ jQuery.post(ajaxurl, data, function(response) {
17
18
+ if(response.cachesize.length > 0) {
19
+ jQuery("#fvm_cache_size").html(response.cachesize);
20
}
21
22
+ // reset
23
+ var fvmarr = [];
24
+
25
+ // js
26
+ if(response.js.length > 0) {
27
+ jQuery(response.js).each(function(){
28
+ fvmarr.push(this.uid);
29
+ if(jQuery('#'+this.uid).length == 0) {
30
+ jQuery('#fastvelocity_min_jsprocessed ul').append('<li id="'+this.uid+'"><span class="filename">'+this.filename+' ('+this.fsize+')</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
31
}
32
+ });
33
+ }
34
+
35
+ // css
36
+ if(response.css.length > 0) {
37
+ jQuery(response.css).each(function(){
38
+ fvmarr.push(this.uid);
39
+ if(jQuery('#'+this.uid).length == 0) {
40
+ jQuery('#fastvelocity_min_cssprocessed ul').append('<li id="'+this.uid+'"><span class="filename">'+this.filename+' ('+this.fsize+')</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
41
}
42
});
43
+ }
44
+
45
+ // remove li, if not set (JS)
46
+ jQuery('#fastvelocity_min_jsprocessed ul li, #fastvelocity_min_cssprocessed ul li').each(function(){
47
+ if(jQuery.inArray(jQuery(this).attr('id'), fvmarr) == -1) {
48
+ jQuery('#' + jQuery(this).attr('id')).remove();
49
+ }
50
+ });
51
+
52
+ // check for new files
53
+ timeout = setTimeout(getFiles, 4000);
54
+ });
55
+ }
56
+
57
+ getFiles();
58
59
+ });
fvm.php CHANGED
@@ -5,7 +5,7 @@ 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.4.1
9
License: GPL2
10
11
------------------------------------------------------------------------
@@ -61,7 +61,8 @@ add_action('admin_init', 'fvm_compat_checker');
61
62
63
# get plugin version
64
- $fastvelocity_plugin_version = get_file_data(__FILE__, array('Version' => 'Version'), false)['Version'];
65
66
# get the plugin directory
67
$plugindir = plugin_dir_path( __FILE__ ); # prints with trailing slash
@@ -96,6 +97,8 @@ closedir($handle);
96
# default globals
97
$fastvelocity_min_global_js_done = array();
98
$fvm_collect_google_fonts = array();
99
$fvm_debug = get_option('fastvelocity_fvm_debug');
100
101
###########################################
@@ -124,6 +127,7 @@ $fvm_clean_header_one = get_option('fastvelocity_fvm_clean_header_one');
124
$enable_defer_js = get_option('fastvelocity_min_enable_defer_js');
125
$exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
126
$force_inline_css = get_option('fastvelocity_min_force_inline_css');
127
$remove_googlefonts = get_option('fastvelocity_min_remove_googlefonts');
128
$defer_for_pagespeed = get_option('fastvelocity_min_defer_for_pagespeed');
129
$defer_for_pagespeed_optimize = get_option('fastvelocity_min_defer_for_pagespeed_optimize');
@@ -132,6 +136,9 @@ $fvm_fix_editor = get_option('fastvelocity_min_fvm_fix_editor');
132
$fvmloadcss = get_option('fastvelocity_min_loadcss');
133
$fvm_remove_css = get_option('fastvelocity_min_fvm_removecss');
134
$fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
135
136
# default options
137
$used_css_files = array();
@@ -223,15 +230,14 @@ if(is_admin()) {
223
add_action('template_redirect', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
224
}
225
226
- # add the CSS async polyfil
227
- if ($min_async_googlefonts == true || $fvmloadcss !== false) {
228
- add_action('wp_footer', 'fvm_add_loadcss', PHP_INT_MAX);
229
- }
230
-
231
# remove query from static assets and process defering (if enabled)
232
add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
233
add_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
234
- add_filter('script_loader_tag', 'fastvelocity_min_excludejslist_optimize', 10, 3);
235
236
}
237
}
@@ -250,7 +256,7 @@ global $fvm_fix_editor, $disable_js_merge, $disable_css_merge, $skip_emoji_remov
250
remove_action('template_redirect', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
251
remove_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
252
remove_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
253
- remove_filter('script_loader_tag', 'fastvelocity_min_excludejslist_optimize', 10, 3);
254
}
255
}
256
@@ -274,7 +280,7 @@ function fastvelocity_admintoolbar() {
274
$wp_admin_bar->add_node(array(
275
'id' => 'fvm',
276
'title' => '<span class="ab-icon"></span><span class="ab-label">' . __("FVM Purge",'fvm') . '</span>',
277
- 'href' => admin_url( '/options-general.php?page=fastvelocity-min&fvm_flush=1' )
278
));
279
280
}
@@ -284,10 +290,10 @@ function fastvelocity_admintoolbar() {
284
# function to list all cache files
285
function fastvelocity_min_files_callback() {
286
global $cachedir;
287
-
288
# default
289
$size = fastvelocity_get_cachestats();
290
- $return = array('js' => array(), 'css' => array(), 'stamp' => $_POST['stamp'], 'cachesize'=> $size);
291
292
# inspect directory with opendir, since glob might not be available in some systems
293
clearstatcache();
@@ -295,27 +301,24 @@ function fastvelocity_min_files_callback() {
295
while (false !== ($file = readdir($handle))) {
296
$file = $cachedir.'/'.$file;
297
$ext = pathinfo($file, PATHINFO_EXTENSION);
298
- if (in_array($ext, array('js', 'css'))) {
299
- $log = file_get_contents($file.'.txt');
300
- $mincss = substr($file, 0, -4).'.min.css';
301
- $minjs = substr($file, 0, -3).'.min.js';
302
- $filename = basename($file);
303
- if ($ext == 'css' && file_exists($mincss)) { $filename = basename($mincss); }
304
- if ($ext == 'js' && file_exists($minjs)) { $filename = basename($minjs); }
305
$fsize = fastvelocity_format_filesize(filesize($file));
306
-
307
- # get location, hash, log
308
- $info = explode('-', $filename);
309
- $hash = $info['1'];
310
- array_push($return[$ext], array('hash' => $hash, 'filename' => $filename, 'log' => $log, 'fsize' => $fsize));
311
- }
312
}
313
closedir($handle);
314
}
315
-
316
- header('Content-Type: application/json');
317
- echo json_encode($return);
318
- wp_die();
319
}
320
321
@@ -348,8 +351,10 @@ function fastvelocity_min_register_settings() {
348
register_setting('fvm-group', 'fastvelocity_min_enable_defer_js');
349
register_setting('fvm-group', 'fastvelocity_min_exclude_defer_jquery');
350
register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
351
register_setting('fvm-group', 'fastvelocity_min_remove_googlefonts');
352
register_setting('fvm-group', 'fastvelocity_gfonts_method');
353
register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
354
register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed_optimize');
355
register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
@@ -369,6 +374,8 @@ function fastvelocity_min_register_settings() {
369
370
# dev tab
371
register_setting('fvm-group-dev', 'fastvelocity_fvm_debug');
372
register_setting('fvm-group-dev', 'fastvelocity_min_hpreload');
373
register_setting('fvm-group-dev', 'fastvelocity_min_hpreconnect');
374
register_setting('fvm-group-dev', 'fastvelocity_min_loadcss');
@@ -393,6 +400,63 @@ return $links;
393
add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
394
395
396
397
# manage settings page
398
function fastvelocity_min_settings() {
@@ -408,19 +472,6 @@ $active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'status';
408
<div class="wrap">
409
<h1>Fast Velocity Minify</h1>
410
411
- <?php
412
-
413
- # purge all caches
414
- if(isset($_GET['page']) && $_GET['page'] == 'fastvelocity-min') {
415
- if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['fvm_flush']) && $_GET['fvm_flush'] == 1) {
416
- fvm_purge_all(); # purge all
417
- echo __('<div class="notice notice-success is-dismissible"><p>All caches from <strong>FVM</strong> have been purged!</p></div>');
418
- echo fastvelocity_purge_others(); # purge third party caches
419
- }
420
- }
421
-
422
- ?>
423
-
424
<h2 class="nav-tab-wrapper wp-clearfix">
425
<a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
426
<a href="?page=fastvelocity-min&tab=set" class="nav-tab <?php echo $active_tab == 'set' ? 'nav-tab-active' : ''; ?>">Settings</a>
@@ -565,7 +616,7 @@ Cleanup Header <span class="note-info">[ Remove resource hints, generator tag, s
565
566
567
<tr>
568
- <th scope="row">Fonts Options</th>
569
<td>
570
<p class="fvm-bold-green fvm-rowintro">The default options are usually good for performance.</p>
571
<fieldset>
@@ -598,15 +649,35 @@ $a = ''; if($sel == 1 || empty($sel)) { $a = ' checked="checked"'; }
598
$b = ''; if($sel == 2) { $b = ' checked="checked"'; }
599
$c = ''; if($sel == 3) { $c = ' checked="checked"'; }
600
?>
601
- <p class="fvm-bold-green fvm-rowintro">Choose how to include your Google Fonts CSS on your pages:</p>
602
<fieldset>
603
- <label><input type="radio" name="fastvelocity_gfonts_method" value="1" <?php echo $a; ?>> Inline Google Fonts CSS</label> <span class="note-info">[ Will inline in the <a target="_blank" href="https://caniuse.com/#feat=woff">woof</a> format only ]</span><br>
604
<label><input type="radio" name="fastvelocity_gfonts_method" value="2"<?php echo $b; ?>> Async Google Fonts CSS files</label> <span class="note-info">[ Will use <a target="_blank" href="https://caniuse.com/#feat=link-rel-preload">preload</a> with <a href="https://github.com/filamentgroup/loadCSS">LoadCSS</a> polyfill ]</span><br>
605
- <label><input type="radio" name="fastvelocity_gfonts_method" value="3"<?php echo $c; ?>> Async and exclude CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
606
</fieldset>
607
</td>
608
</tr>
609
610
<tr>
611
<th scope="row">CSS Options</th>
612
<td>
@@ -629,9 +700,13 @@ Preserve the order of CSS files <span class="note-info">[ If selected, you will
629
<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); ?> >
630
Remove the "Print" related stylesheets <span class="note-info">[ If selected, CSS files of mediatype "print" will be removed from the site ]</span></label>
631
<br />
632
<label for="fastvelocity_min_force_inline_css">
633
<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); ?>>
634
- Inline all CSS files <span class="note-info">[ If selected, CSS will be inlined to avoid the "render blocking" on PSI ]</span></label>
635
<br />
636
</fieldset></td>
637
</tr>
@@ -640,7 +715,7 @@ Inline all CSS files <span class="note-info">[ If selected, CSS will be inlined
640
<tr>
641
<th scope="row">JavaScript Options</th>
642
<td>
643
- <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>
644
<fieldset>
645
<label for="fastvelocity_min_disable_js_merge">
646
<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); ?> >
@@ -765,7 +840,8 @@ I know what I'm doing... <span class="note-info">[ Load my JS files from the CDN
765
766
<div style="height: 20px;"></div>
767
<h2 class="title">Special JS and CSS Exceptions</h2>
768
- <p class="fvm-bold-green">You can use this section to edit or change our default exclusions, as well as to add your own.<br />It's recommeded that you use the Ignore List before touching these settings.</p>
769
770
<div style="height: 20px;"></div>
771
<table class="form-table fvm-settings">
@@ -807,7 +883,7 @@ I know what I'm doing... <span class="note-info">[ Load my JS files from the CDN
807
<p>
808
<textarea name="fastvelocity_min_excludejslist" rows="7" cols="50" id="fastvelocity_min_excludejslist" class="large-text code" placeholder="ex: /pixelyoursite/js/public.js"><?php echo get_option('fastvelocity_min_excludejslist'); ?></textarea>
809
</p>
810
- <p class="description">[ Any JS file that can load Async and independently from the rest, such as analytics or pixel scripts ]</p>
811
812
</fieldset></td>
813
</tr>
@@ -823,8 +899,7 @@ I know what I'm doing... <span class="note-info">[ Load my JS files from the CDN
823
<p>
824
<textarea name="fastvelocity_min_excludecsslist" rows="7" cols="50" id="fastvelocity_min_excludecsslist" class="large-text code" placeholder="ex: /wp-content/themes/my-theme/css/fontawesome.css"><?php echo get_option('fastvelocity_min_excludecsslist'); ?></textarea>
825
</p>
826
- <p class="description">[ Any CSS file that can load independently from the rest, such as fontawesome or other icons ]</p>
827
- <p class="description">[ Note: Under development, currently only works when "Inline all CSS files" is enabled ]</p>
828
829
</fieldset></td>
830
</tr>
@@ -876,26 +951,40 @@ if( $active_tab == 'dev' ) { ?>
876
<?php settings_fields('fvm-group-dev'); do_settings_sections('fvm-group-dev'); ?>
877
878
<div style="height: 20px;"></div>
879
- <h2 class="title">Debug</h2>
880
- <p class="fvm-bold-green">This will print some debug info on the status page log files, as well as some HTML comments on the frontend for certain actions and situations. This is still experimental and under developement!</p>
881
882
<table class="form-table fvm-settings">
883
<tbody>
884
<tr>
885
- <th scope="row">Enable FVM Debug Mode</th>
886
<td><fieldset>
887
<label for="fastvelocity_fvm_debug">
888
<input name="fastvelocity_fvm_debug" type="checkbox" id="fastvelocity_fvm_debug" value="1" <?php echo checked(1 == get_option('fastvelocity_fvm_debug'), true, false); ?>>
889
- Enable FVM Debug Mode<span class="note-info">[ Add debug info to the status page logs as well as some comments on the HTML frontend (beta) ]</span></label>
890
891
</fieldset>
892
</td>
893
</tr>
894
-
895
</tbody></table>
896
897
898
899
<div style="height: 20px;"></div>
900
<h2 class="title">HTTP Headers</h2>
901
<p class="fvm-bold-green">Preconnect Headers: This will add link headers to your http response to instruct the browser to preconnect to other domains (ex: fonts, images, videos, etc)</p>
@@ -1081,7 +1170,7 @@ if( $active_tab == 'help' ) { ?>
1081
# process header javascript ###############
1082
###########################################
1083
function fastvelocity_min_merge_header_scripts() {
1084
- 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, $fvm_debug;
1085
if(!is_object($wp_scripts)) { return false; }
1086
$scripts = wp_clone($wp_scripts);
1087
$scripts->all_deps($scripts->queue);
@@ -1106,6 +1195,24 @@ $is_footer = 0; if (isset($wp_scripts->registered[$handle]->extra["group"]) || i
1106
# get full url
1107
$hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1108
1109
# IE only files don't increment things
1110
$ieonly = fastvelocity_ie_blacklist($hurl);
1111
if($ieonly == true) { continue; }
@@ -1221,8 +1328,7 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1221
if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1222
1223
# enqueue file, if not empty
1224
- $check = ''; $check = trim(file_get_contents($file));
1225
- if(file_exists($file) && (!empty($check) || count($data) > 0)) {
1226
wp_enqueue_script("fvm-header-$i");
1227
}
1228
@@ -1244,7 +1350,7 @@ $wp_scripts->done = $done;
1244
# process js in the footer ################
1245
###########################################
1246
function fastvelocity_min_merge_footer_scripts() {
1247
- 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, $fvm_debug;
1248
if(!is_object($wp_scripts)) { return false; }
1249
$ctime = get_option('fvm-last-cache-update', '0');
1250
$scripts = wp_clone($wp_scripts);
@@ -1264,6 +1370,24 @@ foreach( $scripts->to_do as $handle ) :
1264
# get full url
1265
$hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1266
1267
# IE only files don't increment things
1268
$ieonly = fastvelocity_ie_blacklist($hurl);
1269
if($ieonly == true) { continue; }
@@ -1370,8 +1494,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1370
if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1371
1372
# enqueue file, if not empty
1373
- $check = ''; $check = trim(file_get_contents($file));
1374
- if(file_exists($file) && (!empty($check) || count($data) > 0)) {
1375
wp_enqueue_script("fvm-footer-$i");
1376
}
1377
@@ -1434,11 +1557,13 @@ if($enable_defer_js == true) { return $tagdefer; }
1434
# return if no defer, and there's no defer for pagespeed... else pagespeed processing
1435
if ($defer_for_pagespeed != true) { return $tag; } else {
1436
1437
# return if external script url https://www.chromestatus.com/feature/5718547946799104
1438
if (fvm_is_local_domain($src) !== true) { return $tag; }
1439
1440
- # return if there are linebreaks (will break document.write)
1441
- if (stripos($tag, PHP_EOL) !== false) { return $tag; }
1442
1443
# print code if there are no linebreaks, or return
1444
if(!empty($tagdefer)) {
@@ -1459,7 +1584,7 @@ return $tag;
1459
# process header css ######################
1460
###########################################
1461
function fastvelocity_min_merge_header_css() {
1462
- 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_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_min_excludecsslist, $fvm_debug;
1463
if(!is_object($wp_styles)) { return false; }
1464
$ctime = get_option('fvm-last-cache-update', '0');
1465
$styles = wp_clone($wp_styles);
@@ -1494,8 +1619,9 @@ foreach( $styles->to_do as $handle):
1494
}
1495
1496
# mediatype
1497
- $mediatype = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all'; # such as all, print, mobile, etc
1498
- if ($mediatype == 'screen' || $mediatype == 'screen, print') { $mediatype = 'all'; }
1499
1500
# full url or empty
1501
$hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
@@ -1506,6 +1632,32 @@ foreach( $styles->to_do as $handle):
1506
if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
1507
}
1508
1509
# array of info to save
1510
$arr = array('handle'=>$handle, 'url'=>$hurl, 'conditional'=>$conditional, 'mediatype'=>$mediatype);
1511
@@ -1581,6 +1733,12 @@ if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts
1581
1582
# inline css or fail
1583
if($res['code'] !== false) {
1584
echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
1585
} else {
1586
echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
@@ -1614,8 +1772,10 @@ $mediatype = $process[$handle]['mediatype'];
1614
$ieonly = fastvelocity_ie_blacklist($hurl);
1615
if($ieonly == true) { continue; }
1616
1617
- # skip ignore list, conditional css, external css
1618
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1619
1620
# colect inline css for this handle
1621
if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
@@ -1639,7 +1799,6 @@ $mediatype = $process[$handle]['mediatype'];
1639
}
1640
endforeach;
1641
1642
-
1643
# reorder CSS by mediatypes
1644
if(!$skip_cssorder) {
1645
if(count($header) > 0) {
@@ -1649,12 +1808,12 @@ if(!$skip_cssorder) {
1649
foreach($header as $array) {
1650
if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1651
}
1652
-
1653
# extract handles by mediatype
1654
$grouphandles = array();
1655
foreach ($allmedia as $md=>$var) {
1656
foreach($header as $array) {
1657
- if (isset($array['media']) && $array['media'] == $md) {
1658
foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1659
}
1660
}
@@ -1758,10 +1917,16 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1758
1759
# enqueue file, if not empty
1760
} else {
1761
- $check = ''; $check = trim(file_get_contents($file));
1762
- if(file_exists($file) && !empty($check)) {
1763
- wp_register_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
1764
- wp_enqueue_style("fvm-header-$i");
1765
}
1766
}
1767
}
@@ -1784,7 +1949,7 @@ $wp_styles->done = $done;
1784
# process css in the footer ###############
1785
###########################################
1786
function fastvelocity_min_merge_footer_css() {
1787
- 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_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_debug;
1788
1789
if(!is_object($wp_styles)) { return false; }
1790
$ctime = get_option('fvm-last-cache-update', '0');
@@ -1812,8 +1977,10 @@ $ignore = fastvelocity_default_ignore($ignore);
1812
1813
# google fonts to the top
1814
foreach( $styles->to_do as $handle ) :
1815
# dequeue and get a list of google fonts, or requeue external
1816
$hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1817
if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1818
wp_dequeue_style($handle);
1819
if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
@@ -1825,6 +1992,7 @@ foreach( $styles->to_do as $handle ) :
1825
} else {
1826
wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
1827
}
1828
endforeach;
1829
1830
@@ -1902,28 +2070,66 @@ if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts
1902
1903
1904
# get groups of handles
1905
foreach( $styles->to_do as $handle ) :
1906
1907
# skip already processed google fonts
1908
if(isset($google_fonts[$handle])) { continue; }
1909
-
1910
# get full url
1911
$hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1912
-
1913
- # media type
1914
- $media = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
1915
1916
# IE only files don't increment things
1917
$ieonly = fastvelocity_ie_blacklist($hurl);
1918
if($ieonly == true) { continue; }
1919
1920
- # conditionals
1921
- $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
1922
- $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
1923
}
1924
1925
- # skip ignore list, conditional css, external css
1926
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1927
1928
# colect inline css for this handle
1929
if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
@@ -1933,7 +2139,7 @@ foreach( $styles->to_do as $handle ) :
1933
1934
# process
1935
if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0 || $footer[count($footer)-1]['media'] != $wp_styles->registered[$handle]->args) {
1936
- array_push($footer, array('handles'=>array(),'media'=>$media));
1937
}
1938
1939
# push it to the array get latest modified time
@@ -1962,7 +2168,7 @@ if(!$skip_cssorder) {
1962
$grouphandles = array();
1963
foreach ($allmedia as $md=>$var) {
1964
foreach($footer as $array) {
1965
- if (isset($array['media']) && $array['media'] == $md) {
1966
foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1967
}
1968
}
@@ -2053,7 +2259,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
2053
}
2054
2055
# register and enqueue minified file, consider excluding of mediatype "print" and inline css
2056
- if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $header[$i]['media'] != 'print')) {
2057
2058
# the developers tab, takes precedence
2059
@@ -2066,10 +2272,15 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
2066
2067
# enqueue file, if not empty
2068
} else {
2069
- $check = ''; $check = trim(file_get_contents($file));
2070
- if(file_exists($file) && !empty($check)) {
2071
- wp_register_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
2072
- wp_enqueue_style("fvm-footer-$i");
2073
}
2074
}
2075
}
@@ -2103,6 +2314,14 @@ EOF;
2103
2104
}
2105
2106
2107
2108
@@ -2156,15 +2375,26 @@ if(is_array($preconnect) && count($preconnect) > 0) {
2156
}
2157
}
2158
2159
}
2160
2161
2162
2163
###########################################
2164
- # optimize the ignore list for pagespeed insights
2165
###########################################
2166
- function fastvelocity_min_excludejslist_optimize($tag, $handle, $src) {
2167
- global $fvm_min_excludejslist, $fvm_fix_editor, $fvmualist, $fvm_debug;
2168
2169
# return if there are linebreaks (will break document.write)
2170
if (stripos($tag, PHP_EOL) !== false) { return $tag; }
@@ -2172,21 +2402,35 @@ if (stripos($tag, PHP_EOL) !== false) { return $tag; }
2172
# fix page editors
2173
if($fvm_fix_editor == true && is_user_logged_in()) { return $tag; }
2174
2175
- # return if the exclude JS files from PSI option is empty
2176
- if($fvm_min_excludejslist == false || !is_array($fvm_min_excludejslist)) {
2177
- return $tag;
2178
}
2179
2180
- # check for string match
2181
- foreach($fvm_min_excludejslist as $l) {
2182
- if (stripos($src, $l) !== false) {
2183
-
2184
- # print code if there are no linebreaks, or return
2185
- echo '<script type="text/javascript" async>if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2186
- echo "loadAsync('$src', null);";
2187
- echo '}</script>';
2188
- return false;
2189
}
2190
}
2191
2192
# fallback
@@ -2194,17 +2438,9 @@ return $tag;
2194
}
2195
2196
2197
-
2198
-
2199
-
2200
-
2201
-
2202
-
2203
-
2204
-
2205
# inline css in place, instead of inlining the large file
2206
function fastvelocity_optimizecss($html, $handle, $href, $media){
2207
- global $fvm_debug, $wp_domain, $wp_home, $force_inline_css, $fvmualist, $fvm_collect_google_fonts, $force_inline_googlefonts, $min_async_googlefonts, $remove_googlefonts, $skip_google_fonts, $css_hide_googlefonts, $remove_print_mediatypes, $ignore, $blacklist, $ignorelist, $wp_home, $fvmloadcss, $fvm_remove_css, $fvm_cdn_url, $disable_minification, $fvm_min_excludecsslist, $disable_css_minification, $fvm_fix_editor;
2208
2209
# current timestamp
2210
$ctime = get_option('fvm-last-cache-update', '0');
@@ -2236,7 +2472,7 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2236
}
2237
2238
# mediatype fix for some plugins + remove print mediatypes
2239
- if ($media == 'screen' || $media == 'screen, print') { $media = 'all'; }
2240
if($remove_print_mediatypes != false && $media == 'print') {
2241
return false;
2242
}
@@ -2261,7 +2497,6 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2261
return false;
2262
}
2263
2264
-
2265
# handle google fonts here, when merging is disabled
2266
if(stripos($href, 'fonts.googleapis.com') !== false && $skip_google_fonts != false) {
2267
@@ -2283,6 +2518,52 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2283
}
2284
}
2285
2286
# inline google fonts, do not collect
2287
if(stripos($href, 'fonts.googleapis.com') !== false && $force_inline_googlefonts != false && $css_hide_googlefonts != true && $min_async_googlefonts != true) {
2288
@@ -2298,6 +2579,10 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2298
# decode
2299
$res = json_decode($json, true);
2300
2301
# inline css or fail
2302
if($res['status'] != false) {
2303
echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
@@ -2314,7 +2599,6 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2314
return false;
2315
}
2316
2317
-
2318
# skip external scripts that are not specifically allowed
2319
if (fvm_internal_url($href, $wp_home) === false || empty($href)) {
2320
if($fvm_debug == true) { echo "<!-- FVM DEBUG: Skipped the next external enqueued CSS -->" . PHP_EOL; }
@@ -2422,3 +2706,150 @@ function fastvelocity_add_google_fonts_merged() {
2422
2423
}
2424
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.4.4
9
License: GPL2
10
11
------------------------------------------------------------------------
61
62
63
# get plugin version
64
+ $fastvelocity_plugin_version_get_data = get_file_data(__FILE__, array('Version' => 'Version'), false);
65
+ $fastvelocity_plugin_version = $fastvelocity_plugin_version_get_data['Version'];
66
67
# get the plugin directory
68
$plugindir = plugin_dir_path( __FILE__ ); # prints with trailing slash
97
# default globals
98
$fastvelocity_min_global_js_done = array();
99
$fvm_collect_google_fonts = array();
100
+ $collect_preload_css = array();
101
+ $collect_preload_js = array();
102
$fvm_debug = get_option('fastvelocity_fvm_debug');
103
104
###########################################
127
$enable_defer_js = get_option('fastvelocity_min_enable_defer_js');
128
$exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
129
$force_inline_css = get_option('fastvelocity_min_force_inline_css');
130
+ $force_inline_css_footer = get_option('fastvelocity_min_force_inline_css_footer');
131
$remove_googlefonts = get_option('fastvelocity_min_remove_googlefonts');
132
$defer_for_pagespeed = get_option('fastvelocity_min_defer_for_pagespeed');
133
$defer_for_pagespeed_optimize = get_option('fastvelocity_min_defer_for_pagespeed_optimize');
136
$fvmloadcss = get_option('fastvelocity_min_loadcss');
137
$fvm_remove_css = get_option('fastvelocity_min_fvm_removecss');
138
$fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
139
+ $fvm_enabled_css_preload = get_option('fastvelocity_enabled_css_preload');
140
+ $fvm_enabled_js_preload = get_option('fastvelocity_enabled_css_preload');
141
+ $fvm_fawesome_method = get_option("fastvelocity_fontawesome_method");
142
143
# default options
144
$used_css_files = array();
230
add_action('template_redirect', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
231
}
232
233
+ # add the CSS async polyfil + LoadAsync JavaScript functions
234
+ add_action('wp_footer', 'fvm_add_loadcss', PHP_INT_MAX);
235
+ add_action('wp_head', 'fvm_add_loadasync', 0);
236
+
237
# remove query from static assets and process defering (if enabled)
238
add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
239
add_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
240
+ add_filter('script_loader_tag', 'fastvelocity_min_defer_js_optimize', PHP_INT_MAX, 3);
241
242
}
243
}
256
remove_action('template_redirect', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
257
remove_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
258
remove_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
259
+ remove_filter('script_loader_tag', 'fastvelocity_min_defer_js_optimize', 10, 3);
260
}
261
}
262
280
$wp_admin_bar->add_node(array(
281
'id' => 'fvm',
282
'title' => '<span class="ab-icon"></span><span class="ab-label">' . __("FVM Purge",'fvm') . '</span>',
283
+ 'href' => wp_nonce_url( add_query_arg('_fvmcache', 'clear'), 'fvm_clear_nonce')
284
));
285
286
}
290
# function to list all cache files
291
function fastvelocity_min_files_callback() {
292
global $cachedir;
293
+
294
# default
295
$size = fastvelocity_get_cachestats();
296
+ $return = array('js' => array(), 'css' => array(), 'stamp' => $_POST['stamp'], 'cachesize'=> $size);
297
298
# inspect directory with opendir, since glob might not be available in some systems
299
clearstatcache();
301
while (false !== ($file = readdir($handle))) {
302
$file = $cachedir.'/'.$file;
303
$ext = pathinfo($file, PATHINFO_EXTENSION);
304
+ if (in_array($ext, array('js', 'css'))) {
305
+ $log = file_get_contents($file.'.txt');
306
+ $mincss = substr($file, 0, -4).'.min.css';
307
+ $minjs = substr($file, 0, -3).'.min.js';
308
+ $filename = basename($file);
309
+ if ($ext == 'css' && file_exists($mincss)) { $filename = basename($mincss); }
310
+ if ($ext == 'js' && file_exists($minjs)) { $filename = basename($minjs); }
311
$fsize = fastvelocity_format_filesize(filesize($file));
312
+ $uid = hash('adler32', $filename);
313
+ array_push($return[$ext], array('uid'=>$uid, 'filename' => $filename, 'log' => $log, 'fsize' => $fsize));
314
+ }
315
}
316
closedir($handle);
317
}
318
+
319
+ header('Content-Type: application/json');
320
+ echo json_encode($return);
321
+ wp_die();
322
}
323
324
351
register_setting('fvm-group', 'fastvelocity_min_enable_defer_js');
352
register_setting('fvm-group', 'fastvelocity_min_exclude_defer_jquery');
353
register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
354
+ register_setting('fvm-group', 'fastvelocity_min_force_inline_css_footer');
355
register_setting('fvm-group', 'fastvelocity_min_remove_googlefonts');
356
register_setting('fvm-group', 'fastvelocity_gfonts_method');
357
+ register_setting('fvm-group', 'fastvelocity_fontawesome_method');
358
register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
359
register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed_optimize');
360
register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
374
375
# dev tab
376
register_setting('fvm-group-dev', 'fastvelocity_fvm_debug');
377
+ register_setting('fvm-group-dev', 'fastvelocity_enabled_css_preload');
378
+ register_setting('fvm-group-dev', 'fastvelocity_enabled_js_preload');
379
register_setting('fvm-group-dev', 'fastvelocity_min_hpreload');
380
register_setting('fvm-group-dev', 'fastvelocity_min_hpreconnect');
381
register_setting('fvm-group-dev', 'fastvelocity_min_loadcss');
400
add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
401
402
403
+ # purge all caches by request
404
+ add_action('init','fastvelocity_process_cache_purge_request');
405
+ function fastvelocity_process_cache_purge_request(){
406
+ if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['_fvmcache'])) {
407
+
408
+ # must be able to cleanup cache
409
+ if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
410
+
411
+ # validate nonce
412
+ if(isset($_GET['wordpress_fvmcache']) && (empty($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'fvm_clear_nonce'))) {
413
+ wp_die( __('Invalid or expired request... please go back and refresh before trying again!'));
414
+ }
415
+
416
+ if(is_admin()) {
417
+ fvm_purge_all(); # purge all
418
+ fastvelocity_purge_others(); # purge third party caches
419
+ $others = fastvelocity_purge_others(); # purge third party caches
420
+ $notice = array('All caches from <strong>FVM</strong> have been purged!', strip_tags($others, '<strong>'));
421
+ $notice = array_filter($notice);
422
+ $notice = base64_encode(json_encode($notice)); # encode
423
+ setcookie('wordpress_fvmcache', $notice, time()+60, COOKIEPATH, COOKIE_DOMAIN );
424
+ wp_safe_redirect(remove_query_arg('_wpnonce', remove_query_arg('_fvmcache', wp_get_referer())));
425
+ } else {
426
+ fvm_purge_all(); # purge all
427
+ fastvelocity_purge_others(); # purge third party caches
428
+ wp_safe_redirect(remove_query_arg('_wpnonce', remove_query_arg('_fvmcache', wp_get_referer())));
429
+ }
430
+ }
431
+ }
432
+
433
+ # print admin notices after purging caches, if on wp-admin
434
+ add_action( 'admin_notices', 'fastvelocity_admin_notices' );
435
+ function fastvelocity_admin_notices() {
436
+
437
+ # cache purge notices
438
+ if(isset($_COOKIE['wordpress_fvmcache']) && !empty($_COOKIE['wordpress_fvmcache'])) {
439
+
440
+ # decode to array or null
441
+ $jsonarr = json_decode(base64_decode($_COOKIE['wordpress_fvmcache']), true);
442
+ if(!is_null($jsonarr) && is_array($jsonarr)){
443
+
444
+ # must be able to cleanup cache
445
+ if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
446
+
447
+ # print notices
448
+ foreach ($jsonarr as $notice) {
449
+ echo __('<div class="notice notice-success is-dismissible"><p>'.$notice.'</p></div>');
450
+ }
451
+ }
452
+
453
+ # remove
454
+ setcookie('wordpress_fvmcache', $notice, time()-3600, COOKIEPATH, COOKIE_DOMAIN );
455
+ }
456
+ }
457
+
458
+
459
+
460
461
# manage settings page
462
function fastvelocity_min_settings() {
472
<div class="wrap">
473
<h1>Fast Velocity Minify</h1>
474
475
<h2 class="nav-tab-wrapper wp-clearfix">
476
<a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
477
<a href="?page=fastvelocity-min&tab=set" class="nav-tab <?php echo $active_tab == 'set' ? 'nav-tab-active' : ''; ?>">Settings</a>
616
617
618
<tr>
619
+ <th scope="row">Font Options</th>
620
<td>
621
<p class="fvm-bold-green fvm-rowintro">The default options are usually good for performance.</p>
622
<fieldset>
649
$b = ''; if($sel == 2) { $b = ' checked="checked"'; }
650
$c = ''; if($sel == 3) { $c = ' checked="checked"'; }
651
?>
652
+ <p class="fvm-bold-green fvm-rowintro">Choose how to include Google Fonts on your pages, when available:</p>
653
<fieldset>
654
+ <label><input type="radio" name="fastvelocity_gfonts_method" value="1" <?php echo $a; ?>> Inline Google Fonts CSS</label> <span class="note-info">[ Will inline the <a target="_blank" href="https://caniuse.com/#feat=woff">woof</a> format only (with font hinting) ]</span><br>
655
<label><input type="radio" name="fastvelocity_gfonts_method" value="2"<?php echo $b; ?>> Async Google Fonts CSS files</label> <span class="note-info">[ Will use <a target="_blank" href="https://caniuse.com/#feat=link-rel-preload">preload</a> with <a href="https://github.com/filamentgroup/loadCSS">LoadCSS</a> polyfill ]</span><br>
656
+ <label><input type="radio" name="fastvelocity_gfonts_method" value="3"<?php echo $c; ?>> Async and exclude Google Fonts CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
657
+ </fieldset>
658
+ </td>
659
+ </tr>
660
+
661
+ <tr>
662
+ <th scope="row">Font Awesome</th>
663
+ <td>
664
+ <?php
665
+ # what to select
666
+ $sel = get_option('fastvelocity_fontawesome_method');
667
+ $a = ''; if($sel == 1 || empty($sel)) { $a = ' checked="checked"'; }
668
+ $b = ''; if($sel == 2) { $b = ' checked="checked"'; }
669
+ $c = ''; if($sel == 3) { $c = ' checked="checked"'; }
670
+ ?>
671
+ <p class="fvm-bold-green fvm-rowintro">Only if available and if it has "font-awesome" in the url:</p>
672
+ <fieldset>
673
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="1" <?php echo $a; ?>> Merge or Inline Font Awesome CSS</label> <span class="note-info">[ Depends on if you have the Inline CSS option enabled or not ]</span><br>
674
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="2"<?php echo $b; ?>> Async Font Awesome CSS file</label> <span class="note-info">[ Will use <a target="_blank" href="https://caniuse.com/#feat=link-rel-preload">preload</a> with <a href="https://github.com/filamentgroup/loadCSS">LoadCSS</a> polyfill ]</span><br>
675
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="3"<?php echo $c; ?>> Async and exclude Font Awesome CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
676
</fieldset>
677
</td>
678
</tr>
679
680
+
681
<tr>
682
<th scope="row">CSS Options</th>
683
<td>
700
<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); ?> >
701
Remove the "Print" related stylesheets <span class="note-info">[ If selected, CSS files of mediatype "print" will be removed from the site ]</span></label>
702
<br />
703
+ <label for="fastvelocity_min_force_inline_css_footer">
704
+ <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); ?>>
705
+ Inline CSS in the footer <span class="note-info">[ If selected, any FVM generated CSS files in the footer, will be inlined ]</span></label>
706
+ <br />
707
<label for="fastvelocity_min_force_inline_css">
708
<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); ?>>
709
+ Inline all FVM generated CSS files <span class="note-info">[ If selected, any FVM generated CSS files (header + footer) will be inlined ]</span></label>
710
<br />
711
</fieldset></td>
712
</tr>
715
<tr>
716
<th scope="row">JavaScript Options</th>
717
<td>
718
+ <p class="fvm-bold-green fvm-rowintro">Try to disable minification (and purge the cache) first, if you have trouble with JavaScript in the frontend.</p>
719
<fieldset>
720
<label for="fastvelocity_min_disable_js_merge">
721
<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); ?> >
840
841
<div style="height: 20px;"></div>
842
<h2 class="title">Special JS and CSS Exceptions</h2>
843
+ <p class="fvm-bold-green">You can use this section to edit or change our default exclusions, as well as to add your own.<br />Make sure you understand the difference between Defer and Async.</p>
844
+ <p class="fvm-bold-green">When you use an option here that uses "Async", styles and scripts load "out of order" and completely independent from the others. That means, the files that end up loading later, will overwrite any previously loaded code. On the other hand, when you use the "ignore list" or when you select an option to "defer", the order of scripts and styles is preserved and should not overwrite previously loaded code, unless there is an higher specificy somewhere else.</p>
845
846
<div style="height: 20px;"></div>
847
<table class="form-table fvm-settings">
883
<p>
884
<textarea name="fastvelocity_min_excludejslist" rows="7" cols="50" id="fastvelocity_min_excludejslist" class="large-text code" placeholder="ex: /pixelyoursite/js/public.js"><?php echo get_option('fastvelocity_min_excludejslist'); ?></textarea>
885
</p>
886
+ <p class="description">[ Any JS file that can load Async and completely independent, such as analytics or pixel scripts ]</p>
887
888
</fieldset></td>
889
</tr>
899
<p>
900
<textarea name="fastvelocity_min_excludecsslist" rows="7" cols="50" id="fastvelocity_min_excludecsslist" class="large-text code" placeholder="ex: /wp-content/themes/my-theme/css/fontawesome.css"><?php echo get_option('fastvelocity_min_excludecsslist'); ?></textarea>
901
</p>
902
+ <p class="description">[ Any CSS file that can load completely independent, such as fontawesome or other icons ]</p>
903
904
</fieldset></td>
905
</tr>
951
<?php settings_fields('fvm-group-dev'); do_settings_sections('fvm-group-dev'); ?>
952
953
<div style="height: 20px;"></div>
954
+ <h2 class="title">Development</h2>
955
+ <p class="fvm-bold-green">This are handy things for the plugin author, but may be of use to you if you are looking to debug some issue.</p>
956
+ <p class="fvm-bold-green">Please note that the automatic headers, are only available after the first, uncached pageview (you may need to purge your cache to see them, or your server may not support this at all).</p>
957
958
<table class="form-table fvm-settings">
959
<tbody>
960
<tr>
961
+ <th scope="row">Dev Options</th>
962
<td><fieldset>
963
<label for="fastvelocity_fvm_debug">
964
<input name="fastvelocity_fvm_debug" type="checkbox" id="fastvelocity_fvm_debug" value="1" <?php echo checked(1 == get_option('fastvelocity_fvm_debug'), true, false); ?>>
965
+ Enable FVM Debug Mode<span class="note-info">[ Add extra info to the "status page" logs as well as some comments on the HTML frontend (beta) ]</span></label>
966
+
967
+ <br />
968
+ <label for="fastvelocity_enabled_css_preload">
969
+ <input name="fastvelocity_enabled_css_preload" type="checkbox" id="fastvelocity_enabled_css_preload" value="1" <?php echo checked(1 == get_option('fastvelocity_enabled_css_preload'), true, false); ?>>
970
+ Enable FVM CSS files Preload<span class="note-info">[ Automatically create http headers for FVM generated CSS files, when enqueued ]</span></label>
971
+
972
+ <br />
973
+ <label for="fastvelocity_enabled_js_preload">
974
+ <input name="fastvelocity_enabled_js_preload" type="checkbox" id="fastvelocity_enabled_js_preload" value="1" <?php echo checked(1 == get_option('fastvelocity_enabled_js_preload'), true, false); ?>>
975
+ Enable FVM JS files Preload<span class="note-info">[ Automatically create http headers for FVM generated JS files, when enqueued ]</span></label>
976
+
977
978
</fieldset>
979
</td>
980
</tr>
981
</tbody></table>
982
983
984
985
+
986
+
987
+
988
<div style="height: 20px;"></div>
989
<h2 class="title">HTTP Headers</h2>
990
<p class="fvm-bold-green">Preconnect Headers: This will add link headers to your http response to instruct the browser to preconnect to other domains (ex: fonts, images, videos, etc)</p>
1170
# process header javascript ###############
1171
###########################################
1172
function fastvelocity_min_merge_header_scripts() {
1173
+ 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, $fvm_debug, $fvm_min_excludejslist, $fvmualist;
1174
if(!is_object($wp_scripts)) { return false; }
1175
$scripts = wp_clone($wp_scripts);
1176
$scripts->all_deps($scripts->queue);
1195
# get full url
1196
$hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1197
1198
+ # Exclude JS files from PSI (Async) takes priority over the ignore list
1199
+ if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
1200
+
1201
+ # check for string match
1202
+ $skipjs = false;
1203
+ foreach($fvm_min_excludejslist as $l) {
1204
+ if (stripos($hurl, $l) !== false) {
1205
+ # print code if there are no linebreaks, or return
1206
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1207
+ echo "loadAsync('$hurl', null);";
1208
+ echo '}</script>';
1209
+ $skipjs = true;
1210
+ break;
1211
+ }
1212
+ }
1213
+ if($skipjs != false) { continue; }
1214
+ }
1215
+
1216
# IE only files don't increment things
1217
$ieonly = fastvelocity_ie_blacklist($hurl);
1218
if($ieonly == true) { continue; }
1328
if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1329
1330
# enqueue file, if not empty
1331
+ if(file_exists($file) && (filesize($file) > 0 || count($data) > 0)) {
1332
wp_enqueue_script("fvm-header-$i");
1333
}
1334
1350
# process js in the footer ################
1351
###########################################
1352
function fastvelocity_min_merge_footer_scripts() {
1353
+ 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, $fvm_debug, $fvm_min_excludejslist, $fvmualist;
1354
if(!is_object($wp_scripts)) { return false; }
1355
$ctime = get_option('fvm-last-cache-update', '0');
1356
$scripts = wp_clone($wp_scripts);
1370
# get full url
1371
$hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1372
1373
+ # Exclude JS files from PSI (Async) takes priority over the ignore list
1374
+ if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
1375
+
1376
+ # check for string match
1377
+ $skipjs = false;
1378
+ foreach($fvm_min_excludejslist as $l) {
1379
+ if (stripos($hurl, $l) !== false) {
1380
+ # print code if there are no linebreaks, or return
1381
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1382
+ echo "loadAsync('$hurl', null);";
1383
+ echo '}</script>';
1384
+ $skipjs = true;
1385
+ break;
1386
+ }
1387
+ }
1388
+ if($skipjs != false) { continue; }
1389
+ }
1390
+
1391
# IE only files don't increment things
1392
$ieonly = fastvelocity_ie_blacklist($hurl);
1393
if($ieonly == true) { continue; }
1494
if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1495
1496
# enqueue file, if not empty
1497
+ if(file_exists($file) && (filesize($file) > 0 || count($data) > 0)) {
1498
wp_enqueue_script("fvm-footer-$i");
1499
}
1500
1557
# return if no defer, and there's no defer for pagespeed... else pagespeed processing
1558
if ($defer_for_pagespeed != true) { return $tag; } else {
1559
1560
+ # return if there are linebreaks (will break document.write)
1561
+ if (stripos($tag, PHP_EOL) !== false) { return $tag; }
1562
+
1563
# return if external script url https://www.chromestatus.com/feature/5718547946799104
1564
if (fvm_is_local_domain($src) !== true) { return $tag; }
1565
1566
+
1567
1568
# print code if there are no linebreaks, or return
1569
if(!empty($tagdefer)) {
1584
# process header css ######################
1585
###########################################
1586
function fastvelocity_min_merge_header_css() {
1587
+ 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_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_min_excludecsslist, $fvm_debug, $fvm_min_excludecsslist, $fvm_fawesome_method;
1588
if(!is_object($wp_styles)) { return false; }
1589
$ctime = get_option('fvm-last-cache-update', '0');
1590
$styles = wp_clone($wp_styles);
1619
}
1620
1621
# mediatype
1622
+ $mt = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
1623
+ if ($mt == 'screen' || $mt == 'screen, print' || empty($mt) || is_null($mt) || $mt == false) { $mt = 'all'; }
1624
+ $mediatype = $mt;
1625
1626
# full url or empty
1627
$hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1632
if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
1633
}
1634
1635
+ # Exclude specific CSS files from PSI?
1636
+ if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($hurl, $fvm_min_excludecsslist)) {
1637
+ $cssguid = 'fvm'.hash('adler32', $hurl);
1638
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1639
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1640
+ echo '}</script>';
1641
+ $done = array_merge($done, array($handle)); continue;
1642
+ }
1643
+
1644
+ # font awesome processing, async css
1645
+ if($fvm_fawesome_method == 2 && stripos($hurl, 'font-awesome') !== false) {
1646
+ echo '<link rel="preload" href="'.$hurl.'" as="style" media="'.$mediatype.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1647
+ echo '<noscript><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /></noscript>';
1648
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /><![endif]-->';
1649
+ $done = array_merge($done, array($handle)); continue;
1650
+ }
1651
+
1652
+ # font awesome processing, async and exclude from PSI
1653
+ if($fvm_fawesome_method == 3 && stripos($hurl, 'font-awesome') !== false) {
1654
+ $cssguid = 'fvm'.hash('adler32', $hurl);
1655
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1656
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1657
+ echo '}</script>';
1658
+ $done = array_merge($done, array($handle)); continue;
1659
+ }
1660
+
1661
# array of info to save
1662
$arr = array('handle'=>$handle, 'url'=>$hurl, 'conditional'=>$conditional, 'mediatype'=>$mediatype);
1663
1733
1734
# inline css or fail
1735
if($res['code'] !== false) {
1736
+
1737
+ # add font-display
1738
+ # https://developers.google.com/web/updates/2016/02/font-display
1739
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
1740
+
1741
+ # inline
1742
echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
1743
} else {
1744
echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
1772
$ieonly = fastvelocity_ie_blacklist($hurl);
1773
if($ieonly == true) { continue; }
1774
1775
+ # skip ignore list, conditional css, external css, font-awesome merge
1776
+ if ( (!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home))
1777
+ || empty($hurl)
1778
+ || ($fvm_fawesome_method == 1 && stripos($href, 'font-awesome') !== false)) {
1779
1780
# colect inline css for this handle
1781
if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
1799
}
1800
endforeach;
1801
1802
# reorder CSS by mediatypes
1803
if(!$skip_cssorder) {
1804
if(count($header) > 0) {
1808
foreach($header as $array) {
1809
if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1810
}
1811
+
1812
# extract handles by mediatype
1813
$grouphandles = array();
1814
foreach ($allmedia as $md=>$var) {
1815
foreach($header as $array) {
1816
+ if (isset($array['media']) && $array['media'] === $md) {
1817
foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1818
}
1819
}
1917
1918
# enqueue file, if not empty
1919
} else {
1920
+ if(file_exists($file) && filesize($file) > 0) {
1921
+
1922
+ # inline CSS if mediatype is not of type "all" (such as mobile only), if the file is smaller than 20KB
1923
+ if(filesize($file) < 20000 && $header[$i]['media'] != 'all') {
1924
+ echo '<style id="fvm-header-'.$i.'" media="'.$header[$i]['media'].'">'.file_get_contents($file).'</style>';
1925
+ } else {
1926
+ # enqueue it
1927
+ wp_enqueue_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
1928
+ }
1929
+
1930
}
1931
}
1932
}
1949
# process css in the footer ###############
1950
###########################################
1951
function fastvelocity_min_merge_footer_css() {
1952
+ 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_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_debug, $fvm_fawesome_method, $fvm_min_excludecsslist, $force_inline_css_footer;
1953
1954
if(!is_object($wp_styles)) { return false; }
1955
$ctime = get_option('fvm-last-cache-update', '0');
1977
1978
# google fonts to the top
1979
foreach( $styles->to_do as $handle ) :
1980
+
1981
# dequeue and get a list of google fonts, or requeue external
1982
$hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1983
+
1984
if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1985
wp_dequeue_style($handle);
1986
if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
1992
} else {
1993
wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
1994
}
1995
+
1996
endforeach;
1997
1998
2070
2071
2072
# get groups of handles
2073
+ $uniq = array();
2074
foreach( $styles->to_do as $handle ) :
2075
2076
# skip already processed google fonts
2077
if(isset($google_fonts[$handle])) { continue; }
2078
+
2079
+ # conditionals
2080
+ $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
2081
+ $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
2082
+ }
2083
+
2084
+ # mediatype
2085
+ $mt = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
2086
+ if ($mt == 'screen' || $mt == 'screen, print' || empty($mt) || is_null($mt) || $mt == false) { $mt = 'all'; }
2087
+ $mediatype = $mt;
2088
+
2089
# get full url
2090
$hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2091
+
2092
+ # mark duplicates as done and remove from the queue
2093
+ if(!empty($hurl)) {
2094
+ $key = hash('adler32', $hurl);
2095
+ if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
2096
+ }
2097
2098
# IE only files don't increment things
2099
$ieonly = fastvelocity_ie_blacklist($hurl);
2100
if($ieonly == true) { continue; }
2101
2102
+
2103
+ # Exclude specific CSS files from PSI?
2104
+ if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($hurl, $fvm_min_excludecsslist)) {
2105
+ $cssguid = 'fvm'.hash('adler32', $hurl);
2106
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2107
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2108
+ echo '}</script>';
2109
+ $done = array_merge($done, array($handle)); continue;
2110
+ }
2111
+
2112
+ # font awesome processing, async css
2113
+ if($fvm_fawesome_method == 2 && stripos($hurl, 'font-awesome') !== false) {
2114
+ echo '<link rel="preload" href="'.$hurl.'" as="style" media="'.$mediatype.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2115
+ echo '<noscript><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /></noscript>';
2116
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /><![endif]-->';
2117
+ $done = array_merge($done, array($handle)); continue;
2118
+ }
2119
+
2120
+ # font awesome processing, async and exclude from PSI
2121
+ if($fvm_fawesome_method == 3 && stripos($hurl, 'font-awesome') !== false) {
2122
+ $cssguid = 'fvm'.hash('adler32', $hurl);
2123
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2124
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2125
+ echo '}</script>';
2126
+ $done = array_merge($done, array($handle)); continue;
2127
}
2128
2129
+ # skip ignore list, conditional css, external css, font-awesome merge
2130
+ if ( (!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home))
2131
+ || empty($hurl)
2132
+ || ($fvm_fawesome_method == 1 && stripos($href, 'font-awesome') !== false)) {
2133
2134
# colect inline css for this handle
2135
if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
2139
2140
# process
2141
if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0 || $footer[count($footer)-1]['media'] != $wp_styles->registered[$handle]->args) {
2142
+ array_push($footer, array('handles'=>array(),'media'=>$mediatype));
2143
}
2144
2145
# push it to the array get latest modified time
2168
$grouphandles = array();
2169
foreach ($allmedia as $md=>$var) {
2170
foreach($footer as $array) {
2171
+ if (isset($array['media']) && $array['media'] === $md) {
2172
foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
2173
}
2174
}
2259
}
2260
2261
# register and enqueue minified file, consider excluding of mediatype "print" and inline css
2262
+ if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $footer[$i]['media'] != 'print')) {
2263
2264
# the developers tab, takes precedence
2265
2272
2273
# enqueue file, if not empty
2274
} else {
2275
+ if(file_exists($file) && filesize($file) > 0) {
2276
+
2277
+ # inline if the file is smaller than 20KB or option has been enabled
2278
+ if(filesize($file) < 20000 || $force_inline_css_footer != false) {
2279
+ echo '<style id="fvm-footer-'.$i.'" media="'.$footer[$i]['media'].'">'.file_get_contents($file).'</style>';
2280
+ } else {
2281
+ # enqueue it
2282
+ wp_enqueue_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
2283
+ }
2284
}
2285
}
2286
}
2314
2315
}
2316
2317
+ # fvm load async scripts with callback
2318
+ function fvm_add_loadasync() {
2319
+
2320
+ echo <<<EOF
2321
+ <script>function loadAsync(e,a){var t=document.createElement("script");t.src=e,null!==a&&(t.readyState?t.onreadystatechange=function(){"loaded"!=t.readyState&&"complete"!=t.readyState||(t.onreadystatechange=null,a())}:t.onload=function(){a()}),document.getElementsByTagName("head")[0].appendChild(t)}</script>
2322
+ EOF;
2323
+
2324
+ }
2325
2326
2327
2375
}
2376
}
2377
2378
+ # fvm css and js generated files
2379
+ $fvm_headers = fastvelocity_get_preload_headers();
2380
+ if($fvm_headers != false) {
2381
+ $nh = array_map('trim', explode(PHP_EOL, $fvm_headers));
2382
+ foreach ($nh as $h) {
2383
+ if(!empty($h)) {
2384
+ header($h, false);
2385
+ }
2386
+ }
2387
+ }
2388
+
2389
}
2390
2391
2392
2393
###########################################
2394
+ # optimize the ignore list for pagespeed insights + Exclude JS files from PSI (Async)
2395
###########################################
2396
+ function fastvelocity_min_defer_js_optimize($tag, $handle, $src) {
2397
+ global $defer_for_pagespeed, $defer_for_pagespeed_optimize, $fvm_fix_editor, $fvmualist;
2398
2399
# return if there are linebreaks (will break document.write)
2400
if (stripos($tag, PHP_EOL) !== false) { return $tag; }
2402
# fix page editors
2403
if($fvm_fix_editor == true && is_user_logged_in()) { return $tag; }
2404
2405
+ # return if external script url https://www.chromestatus.com/feature/5718547946799104
2406
+ if (fvm_is_local_domain($src) !== true) { return $tag; }
2407
+
2408
+ # filter src for extra atributes
2409
+ if (stripos($src, '?ver') !== false) {
2410
+ $src = stristr($src, '?ver', true);
2411
}
2412
2413
+ # exclude ignored scripts
2414
+ if(substr($handle, 0, 4) != "fvm-" && $defer_for_pagespeed == true && $defer_for_pagespeed_optimize == true) {
2415
+
2416
+ # get available nodes and add create with defer tag (if not async)
2417
+ $dom = new DOMDocument();
2418
+ libxml_use_internal_errors(true);
2419
+ @$dom->loadHTML($tag);
2420
+ $nodes = $dom->getElementsByTagName('script');
2421
+ $tagdefer = '';
2422
+ if ($nodes->length != 0) {
2423
+ $node = $dom->getElementsByTagName('script')->item(0);
2424
+ if (!$node->hasAttribute('async')) { $node->setAttribute('defer','defer'); };
2425
+ $tagdefer = $dom->saveHTML($node);
2426
+ }
2427
+
2428
+ # print code if there are no linebreaks, or return
2429
+ if(!empty($tagdefer)) {
2430
+ $deferinsights = '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){document.write('.json_encode($tag).');}</script>';
2431
+ return preg_replace('#<script(.*?)>(.*?)</script>#is', $deferinsights, $tag);
2432
}
2433
+
2434
}
2435
2436
# fallback
2438
}
2439
2440
2441
# inline css in place, instead of inlining the large file
2442
function fastvelocity_optimizecss($html, $handle, $href, $media){
2443
+ global $fvm_debug, $wp_domain, $wp_home, $force_inline_css, $fvmualist, $fvm_collect_google_fonts, $force_inline_googlefonts, $min_async_googlefonts, $remove_googlefonts, $skip_google_fonts, $css_hide_googlefonts, $remove_print_mediatypes, $ignore, $blacklist, $ignorelist, $wp_home, $fvmloadcss, $fvm_remove_css, $fvm_cdn_url, $disable_minification, $fvm_min_excludecsslist, $disable_css_minification, $fvm_fix_editor, $fvm_fawesome_method;
2444
2445
# current timestamp
2446
$ctime = get_option('fvm-last-cache-update', '0');
2472
}
2473
2474
# mediatype fix for some plugins + remove print mediatypes
2475
+ if ($media == 'screen' || $media == 'screen, print' || empty($media) || is_null($media) || $media == false) { $media = 'all'; }
2476
if($remove_print_mediatypes != false && $media == 'print') {
2477
return false;
2478
}
2497
return false;
2498
}
2499
2500
# handle google fonts here, when merging is disabled
2501
if(stripos($href, 'fonts.googleapis.com') !== false && $skip_google_fonts != false) {
2502
2518
}
2519
}
2520
2521
+ # font awesome processing, async css
2522
+ if($fvm_fawesome_method == 2 && stripos($href, 'font-awesome') !== false) {
2523
+ echo '<link rel="preload" href="'.$href.'" as="style" media="'.$media.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2524
+ echo '<noscript><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /></noscript>';
2525
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /><![endif]-->';
2526
+ return false;
2527
+ }
2528
+
2529
+ # font awesome processing, async and exclude from PSI
2530
+ if($fvm_fawesome_method == 3 && stripos($href, 'font-awesome') !== false) {
2531
+ $cssguid = 'fvm'.hash('adler32', $href);
2532
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2533
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$href.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$media.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2534
+ echo '}</script>';
2535
+ return false;
2536
+ }
2537
+
2538
+ # font awesome processing, inline
2539
+ if($fvm_fawesome_method == 1 && stripos($href, 'font-awesome') !== false) {
2540
+
2541
+ # download, minify, cache
2542
+ $tkey = 'css-'.$ctime.'-'.hash('adler32', $handle.$href).'.css';
2543
+ $json = false; $json = fvm_get_transient($tkey);
2544
+ if ( $json === false) {
2545
+ $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2546
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2547
+ fvm_set_transient($tkey, $json);
2548
+ }
2549
+
2550
+ # decode
2551
+ $res = json_decode($json, true);
2552
+
2553
+ # add font-display
2554
+ # https://developers.google.com/web/updates/2016/02/font-display
2555
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
2556
+
2557
+ # inline css or fail
2558
+ if($res['status'] != false) {
2559
+ echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2560
+ return false;
2561
+ } else {
2562
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Font Awesome request failed for $href -->" . PHP_EOL; }
2563
+ return $html;
2564
+ }
2565
+ }
2566
+
2567
# inline google fonts, do not collect
2568
if(stripos($href, 'fonts.googleapis.com') !== false && $force_inline_googlefonts != false && $css_hide_googlefonts != true && $min_async_googlefonts != true) {
2569
2579
# decode
2580
$res = json_decode($json, true);
2581
2582
+ # add font-display
2583
+ # https://developers.google.com/web/updates/2016/02/font-display
2584
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
2585
+
2586
# inline css or fail
2587
if($res['status'] != false) {
2588
echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2599
return false;
2600
}
2601
2602
# skip external scripts that are not specifically allowed
2603
if (fvm_internal_url($href, $wp_home) === false || empty($href)) {
2604
if($fvm_debug == true) { echo "<!-- FVM DEBUG: Skipped the next external enqueued CSS -->" . PHP_EOL; }
2706
2707
}
2708
2709
+
2710
+
2711
+ # collect all fvm CSS files and save them to an headers file
2712
+ add_filter('style_loader_tag', 'fastvelocity_collect_css_preload_headers', PHP_INT_MAX, 4 );
2713
+ function fastvelocity_collect_css_preload_headers($html, $handle, $href, $media){
2714
+ global $collect_preload_css, $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2715
+
2716
+ # return if disabled
2717
+ if ($fvm_enabled_css_preload != true) {
2718
+ return $html;
2719
+ }
2720
+
2721
+ # collect
2722
+ if (stripos($href, '/fvm/out/') !== false) {
2723
+ $collect_preload_css[] = $href;
2724
+ }
2725
+ return $html;
2726
+ }
2727
+
2728
+ add_filter('script_loader_tag', 'fastvelocity_collect_js_preload_headers', PHP_INT_MAX, 3 );
2729
+ function fastvelocity_collect_js_preload_headers($html, $handle, $src){
2730
+ global $collect_preload_js, $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2731
+
2732
+ # return if disabled
2733
+ if ($fvm_enabled_js_preload != true) {
2734
+ return $html;
2735
+ }
2736
+
2737
+ # collect
2738
+ if (stripos($src, '/fvm/out/') !== false) {
2739
+ $collect_preload_js[] = $src;
2740
+ }
2741
+ return $html;
2742
+ }
2743
+
2744
+ # generate css headers file
2745
+ add_action('wp_footer', 'fastvelocity_generate_preload_headers', PHP_INT_MAX);
2746
+ function fastvelocity_generate_preload_headers(){
2747
+ global $collect_preload_css, $collect_preload_js, $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2748
+
2749
+ # return if disabled
2750
+ if ($fvm_enabled_css_preload != true && $fvm_enabled_js_preload != true) {
2751
+ return false;
2752
+ }
2753
+
2754
+ # get host with multisite support and query strings
2755
+ $host = htmlentities($_SERVER['SERVER_NAME']);
2756
+ if(empty($hosts)) { $host = htmlentities($_SERVER['HTTP_HOST']); }
2757
+ $request_query = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY);
2758
+ $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
2759
+ $is_admin = strpos( $request_uri, '/wp-admin/' );
2760
+
2761
+ # always false for admin pages
2762
+ if( false !== $is_admin){
2763
+ return false;
2764
+ }
2765
+
2766
+ # initialize headers
2767
+ $headers = array();
2768
+
2769
+ # css headers
2770
+ if ($fvm_enabled_css_preload != false && is_array($collect_preload_css) && count($collect_preload_css) > 0) {
2771
+ foreach($collect_preload_css as $u) {
2772
+ $headers[] = "Link: <$u>; rel=preload; as=style";
2773
+ }
2774
+ }
2775
+
2776
+ # js headers
2777
+ if ($fvm_enabled_js_preload != false && is_array($collect_preload_js) && count($collect_preload_js) > 0) {
2778
+ foreach($collect_preload_js as $u) {
2779
+ $headers[] = "Link: <$u>; rel=preload; as=script";
2780
+ }
2781
+ }
2782
+
2783
+ # must have something
2784
+ if(count($headers) == 0) {
2785
+ return false;
2786
+ } else {
2787
+ $headers = implode(PHP_EOL, $headers);
2788
+ }
2789
+
2790
+ # get cache path
2791
+ $cachepath = fvm_cachepath();
2792
+ $headerdir = $cachepath['headerdir'];
2793
+ $cachefilebase = $headerdir.'/';
2794
+
2795
+ # possible cache file locations
2796
+ $b = $cachefilebase . md5($host.'-'.$request_uri).'.header';
2797
+ $a = $cachefilebase . md5($host.'-'.$request_uri.$request_query).'.header';
2798
+
2799
+ # reset file cache
2800
+ clearstatcache();
2801
+
2802
+ # if there are no query strings
2803
+ if($b == $a) {
2804
+ if(!file_exists($a)) { file_put_contents($a, $headers); }
2805
+ return false;
2806
+ }
2807
+
2808
+ # b fallback
2809
+ if($b != $a && !file_exists($b)) {
2810
+ file_put_contents($b, $headers);
2811
+ }
2812
+
2813
+ return false;
2814
+ }
2815
+
2816
+
2817
+ # get current headers file for the url
2818
+ function fastvelocity_get_preload_headers(){
2819
+ global $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2820
+
2821
+ # return if disabled
2822
+ if ($fvm_enabled_css_preload != true && $fvm_enabled_js_preload != true) {
2823
+ return false;
2824
+ }
2825
+
2826
+ # get host with multisite support and query strings
2827
+ $host = htmlentities($_SERVER['SERVER_NAME']);
2828
+ if(empty($hosts)) { $host = htmlentities($_SERVER['HTTP_HOST']); }
2829
+ $request_query = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY);
2830
+ $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
2831
+ $is_admin = strpos( $request_uri, '/wp-admin/' );
2832
+
2833
+ # always false for admin pages
2834
+ if( false !== $is_admin){
2835
+ return false;
2836
+ }
2837
+
2838
+ # get cache path
2839
+ $cachepath = fvm_cachepath();
2840
+ $headerdir = $cachepath['headerdir'];
2841
+ $cachefilebase = $headerdir.'/';
2842
+
2843
+ # possible cache file locations
2844
+ $b = $cachefilebase . md5($host.'-'.$request_uri).'.header';
2845
+ $a = $cachefilebase . md5($host.'-'.$request_uri.$request_query).'.header';
2846
+
2847
+ # reset file cache
2848
+ clearstatcache();
2849
+
2850
+ # return header files or fallback
2851
+ if($b == $a && file_exists($a)) { return file_get_contents($a); }
2852
+ if($b != $a && file_exists($b)) { return file_get_contents($b); }
2853
+
2854
+ return false;
2855
+ }
inc/functions.php CHANGED
@@ -7,7 +7,7 @@ if(function_exists('mb_internal_encoding')) { mb_internal_encoding('UTF-8'); }
7
@ini_set('pcre.backtrack_limit',5000000);
8
@ini_set('pcre.recursion_limit',5000000);
9
10
- # Consider fallback to PHP Minify [2017.12.17] from https://github.com/matthiasmullie/minify (must be defined on the outer scope)
11
$path = $plugindir . 'libs/matthiasmullie';
12
require_once $path . '/minify/src/Minify.php';
13
require_once $path . '/minify/src/CSS.php';
@@ -42,12 +42,14 @@ $cachebase = rtrim($upload['basedir'], '/').'/fvm';
42
$cachedir = rtrim($upload['basedir'], '/').'/fvm/out';
43
$tmpdir = rtrim($upload['basedir'], '/').'/fvm/tmp';
44
$cachedirurl = rtrim($upload['baseurl'], '/').'/fvm/out';
45
if(!is_dir($cachebase)) { mkdir($cachebase, 0755, true); }
46
if(!is_dir($cachedir)) { mkdir($cachedir, 0755, true); }
47
if(!is_dir($tmpdir)) { mkdir($tmpdir, 0755, true); }
48
49
# return
50
- return array('cachebase'=>$cachebase,'tmpdir'=>$tmpdir, 'cachedir'=>$cachedir, 'cachedirurl'=>$cachedirurl);
51
}
52
53
@@ -64,7 +66,7 @@ function fastvelocity_plugin_activate() {
64
fvm_cache_increment();
65
66
# default blacklist
67
- $exc = array('/html5shiv.js', '/html5shiv-printshiv.min.js', '/excanvas.js', '/avada-ie9.js', '/respond.js', '/respond.min.js', '/selectivizr.js', '/Avada/assets/css/ie.css', '/html5.js', '/IE9.js', '/fusion-ie9.js', '/vc_lte_ie9.min.css', '/old-ie.css', '/ie.css', '/vc-ie8.min.css', '/mailchimp-for-wp/assets/js/third-party/placeholders.min.js', '/assets/js/plugins/wp-enqueue/min/webfontloader.js', '/a.optnmstr.com/app/js/api.min.js', '/pixelyoursite/js/public.js');
68
update_option('fastvelocity_min_blacklist', implode(PHP_EOL, $exc));
69
70
# default ignore list
@@ -255,6 +257,7 @@ function fvm_server_is_windows() {
255
256
# minify js on demand (one file at one time, for compatibility)
257
function fastvelocity_min_get_js($url, $js, $disable_js_minification) {
258
259
# exclude minification on already minified files + jquery (because minification might break those)
260
$excl = array('jquery.js', '.min.js', '-min.js', '/uploads/fusion-scripts/', '/min/', '.packed.js');
@@ -270,28 +273,35 @@ if(!$disable_js_minification) {
270
$js = fvm_compat_urls($js);
271
}
272
273
# needed when merging js files
274
$js = trim($js);
275
if(substr($js, -1) != ';'){ $js = $js.';'; }
276
- $js = '/* info: ' . $url . ' */' . PHP_EOL . $js . PHP_EOL;
277
278
# return html
279
- return $js;
280
}
281
282
283
# minify JS string with PHP Minify or YUI Compressors
284
function fastvelocity_min_minify_js_string($js) {
285
global $tmpdir, $plugindir;
286
-
287
- # PHP Minify [2016.08.01] from https://github.com/matthiasmullie/minify
288
- $minifier = new Minify\JS($js);
289
- $min = $minifier->minify();
290
- if($min !== false && (strlen(trim($js)) == strlen(trim($min)) || strlen(trim($min)) > 0)) { return fvm_compat_urls($min); }
291
-
292
- # if we are here, something went wrong and minification didn't work
293
- $js = "\n/*! Fast Velocity Minify: Minification of the following section has failed, so it has been merged instead. */\n".$js;
294
- return fvm_compat_urls($js);
295
}
296
297
# functions, minify html
@@ -355,7 +365,7 @@ function fastvelocity_get_cachestats() {
355
356
# minify css on demand (one file at one time, for compatibility)
357
function fastvelocity_min_get_css($url, $css, $disable_css_minification) {
358
- global $wp_domain;
359
360
# remove BOM
361
$css = fastvelocity_min_remove_utf8_bom($css);
@@ -384,7 +394,8 @@ if(!empty($fvm_cdn_url)) {
384
}
385
386
# add css comment
387
- $css = '/* info: ' . $url . ' */' . PHP_EOL . trim($css) . PHP_EOL;
388
389
# return html
390
return $css;
@@ -565,79 +576,112 @@ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $
565
# Concatenate Google Fonts tags (http://fonts.googleapis.com/css?...)
566
function fastvelocity_min_concatenate_google_fonts($array) {
567
568
- # extract unique font families
569
- $families = array(); foreach ($array as $font) {
570
-
571
- # get fonts name, type and subset, remove wp query strings
572
- $font = explode('family=', htmlspecialchars_decode(rawurldecode(urldecode($font))));
573
- $a = explode('&v', end($font)); $font = trim(trim(trim(current($a)), ','));
574
-
575
- # reprocess if fonts are already concatenated in this url
576
- if(stristr($font, '|') !== FALSE) {
577
- $multiple = explode('|', $font); if (count($multiple) > 0) { foreach ($multiple as $f) { $families[] = trim($f); } }
578
- } else { $families[] = $font; }
579
- }
580
-
581
- # process types, subsets, merge, etc
582
- $fonts = array();
583
- foreach ($families as $font) {
584
585
- # if no type or subset
586
- if(stristr($font, ':') === FALSE) {
587
- $fonts[] = array('name'=>$font, 'type'=>'', 'sub'=>'');
588
- } else {
589
-
590
- # get type and subset
591
- $name = stristr($font, ':', true); # font name, before :
592
- $ftype = trim(stristr($font, ':'), ':'); # second part of the string, after :
593
-
594
- # get font types and subset
595
- if(stristr($ftype, '&subset=') === FALSE) {
596
- $fonts[] = array('name'=>$name, 'type'=>$ftype, 'sub'=>'');
597
- } else {
598
- $newftype = stristr($ftype, '&', true); # font type, before &
599
- $subset = trim(str_ireplace('&subset=', '', stristr($ftype, '&'))); # second part of the string, after &
600
- $fonts[] = array('name'=>$name, 'type'=>$newftype, 'sub'=>$subset);
601
}
602
603
- }
604
- }
605
-
606
- # make sure we have unique font names, types and subsets
607
- $ufonts = array(); foreach ($fonts as $f) { $ufonts[$f['name']] = $f['name']; } # unique font names
608
- $usubsets = array(); foreach ($fonts as $f) { if(!empty($f['sub'])) { $usubsets[$f['sub']] = $f['sub']; } } # unique subsets
609
-
610
- # prepare
611
- $fonts_and_types = $ufonts;
612
-
613
- # get unique types and subsets for each unique font name
614
- foreach ($ufonts as $uf) {
615
-
616
- # types
617
- $utypes = array();
618
- foreach ($fonts as $f) {
619
- if($f['name'] == $uf && !empty($f['type'])) { $utypes = array_merge($utypes, explode(',', $f['type'])); }
620
}
621
-
622
- # filter types
623
- $utypes = array_unique($utypes);
624
- sort($utypes);
625
- $ntype = ''; if(count($utypes) > 0) { $ntype = ':'.implode(',', $utypes); } # types to append to the font name
626
-
627
- # generate font url queries
628
- $fonts_and_types[$uf] = str_ireplace(' ', '+', $uf).$ntype;
629
- }
630
631
- # concat fonts, generate unique google fonts url
632
- if(count($fonts_and_types) > 0) {
633
- $msubsets = ''; if(count($usubsets) > 0 && implode(',', $usubsets) != 'latin') { $msubsets = "&subset=".implode(',', $usubsets); } # merge subsets
634
- return trim('https://fonts.googleapis.com/css?family='.implode('|', $fonts_and_types).$msubsets); # process
635
- }
636
637
- return false;
638
}
639
640
-
641
# remove emoji support
642
function fastvelocity_min_disable_wp_emojicons() {
643
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
7
@ini_set('pcre.backtrack_limit',5000000);
8
@ini_set('pcre.recursion_limit',5000000);
9
10
+ # Consider fallback to PHP Minify [2018.12.03] from https://github.com/matthiasmullie/minify (must be defined on the outer scope)
11
$path = $plugindir . 'libs/matthiasmullie';
12
require_once $path . '/minify/src/Minify.php';
13
require_once $path . '/minify/src/CSS.php';
42
$cachedir = rtrim($upload['basedir'], '/').'/fvm/out';
43
$tmpdir = rtrim($upload['basedir'], '/').'/fvm/tmp';
44
$cachedirurl = rtrim($upload['baseurl'], '/').'/fvm/out';
45
+ $headerdir = rtrim($upload['basedir'], '/').'/fvm/header';
46
if(!is_dir($cachebase)) { mkdir($cachebase, 0755, true); }
47
if(!is_dir($cachedir)) { mkdir($cachedir, 0755, true); }
48
if(!is_dir($tmpdir)) { mkdir($tmpdir, 0755, true); }
49
+ if(!is_dir($headerdir)) { mkdir($headerdir, 0755, true); }
50
51
# return
52
+ return array('cachebase'=>$cachebase,'tmpdir'=>$tmpdir, 'cachedir'=>$cachedir, 'cachedirurl'=>$cachedirurl, 'headerdir'=>$headerdir);
53
}
54
55
66
fvm_cache_increment();
67
68
# default blacklist
69
+ $exc = array('/html5shiv.js', '/html5shiv-printshiv.min.js', '/excanvas.js', '/avada-ie9.js', '/respond.js', '/respond.min.js', '/selectivizr.js', '/Avada/assets/css/ie.css', '/html5.js', '/IE9.js', '/fusion-ie9.js', '/vc_lte_ie9.min.css', '/old-ie.css', '/ie.css', '/vc-ie8.min.css', '/mailchimp-for-wp/assets/js/third-party/placeholders.min.js', '/assets/js/plugins/wp-enqueue/min/webfontloader.js', '/a.optnmstr.com/app/js/api.min.js', '/pixelyoursite/js/public.js', '/assets/js/wcdrip-drip.js');
70
update_option('fastvelocity_min_blacklist', implode(PHP_EOL, $exc));
71
72
# default ignore list
257
258
# minify js on demand (one file at one time, for compatibility)
259
function fastvelocity_min_get_js($url, $js, $disable_js_minification) {
260
+ global $fvm_debug;
261
262
# exclude minification on already minified files + jquery (because minification might break those)
263
$excl = array('jquery.js', '.min.js', '-min.js', '/uploads/fusion-scripts/', '/min/', '.packed.js');
273
$js = fvm_compat_urls($js);
274
}
275
276
+ # try to remove source mapping files
277
+ $filename = basename($url);
278
+ $remove = array("//# sourceMappingURL=$filename.map", "//# sourceMappingURL = $filename.map");
279
+ $js = str_ireplace($remove, '', $js);
280
+
281
# needed when merging js files
282
$js = trim($js);
283
if(substr($js, -1) != ';'){ $js = $js.';'; }
284
+ if($fvm_debug == true) { $js = '/* info: ' . $url . ' */' . PHP_EOL . $js; }
285
286
# return html
287
+ return $js . PHP_EOL;
288
}
289
290
291
# minify JS string with PHP Minify or YUI Compressors
292
function fastvelocity_min_minify_js_string($js) {
293
global $tmpdir, $plugindir;
294
+
295
+ # PHP Minify from https://github.com/matthiasmullie/minify
296
+ $minifier = new Minify\JS($js);
297
+ $min = $minifier->minify();
298
+ if($min !== false && (strlen(trim($js)) == strlen(trim($min)) || strlen(trim($min)) > 0)) {
299
+ return fvm_compat_urls($min);
300
+ }
301
+
302
+ # if we are here, something went wrong and minification didn't work
303
+ $js = "\n/*! FVM: Minification of the following section failed, so it has been merged instead. */\n".$js;
304
+ return fvm_compat_urls($js);
305
}
306
307
# functions, minify html
365
366
# minify css on demand (one file at one time, for compatibility)
367
function fastvelocity_min_get_css($url, $css, $disable_css_minification) {
368
+ global $wp_domain, $fvm_debug;
369
370
# remove BOM
371
$css = fastvelocity_min_remove_utf8_bom($css);
394
}
395
396
# add css comment
397
+ $css = trim($css);
398
+ if($fvm_debug == true) { $css = '/* info: ' . $url . ' */' . PHP_EOL . trim($css); }
399
400
# return html
401
return $css;
576
# Concatenate Google Fonts tags (http://fonts.googleapis.com/css?...)
577
function fastvelocity_min_concatenate_google_fonts($array) {
578
579
+ # extract unique font families
580
+ $families = array();
581
+ foreach ($array as $font) {
582
+
583
+ # get fonts name, type and subset, remove wp query strings
584
+ $font = explode('family=', htmlspecialchars_decode(rawurldecode(urldecode($font))));
585
+ $a = explode('&v', end($font));
586
+ $font = trim(trim(trim(current($a)), ','));
587
+
588
+ # reprocess if fonts are already concatenated in this url
589
+ if(stristr($font, '|') !== FALSE) {
590
+ $multiple = explode('|', $font);
591
+ if (count($multiple) > 0) {
592
+ foreach ($multiple as $f) {
593
+ $families[] = trim($f);
594
+ }
595
+ }
596
+ } else {
597
+ $families[] = $font;
598
+ }
599
+ }
600
+
601
+ # process names, types, subsets
602
+ $fonts = array();
603
+ $subsets = array();
604
+ foreach ($families as $font) {
605
+
606
+ # extract the subsets
607
+ if (stripos($font, 'subset') !== false) {
608
+ $sub = trim(str_ireplace('&subset=', '', stristr($font, '&'))); # second part of the string, after &
609
+ $font = stristr($font, '&', true); # font name, before &
610
+
611
+ # subsets to array, unique, trim
612
+ if (stripos($sub, ',') !== false) {
613
+ $ft = explode(',', $sub);
614
+ $ft = array_filter(array_map('trim', array_unique($ft)));
615
+ foreach ($ft as $s) {
616
+ $subsets[$s] = $s;
617
+ }
618
+ } else {
619
+ if (!empty($sub)) {
620
+ $subsets[$sub] = $sub;
621
+ }
622
+ }
623
+
624
+ }
625
+
626
+ # check for font name and weights
627
+ $ftypes = array();
628
+ $name = $font;
629
+ if (stripos($font, ':') !== false) {
630
+ $name = stristr($font, ':', true); # font name, before :
631
+ $fwe = trim(stristr($font, ':'), ':'); # second part of the string, after :
632
+
633
+ # ftypes to array, unique, trim
634
+ if (stripos($font, ',') !== false) {
635
+ $ft = explode(',', $fwe);
636
+ $ftypes = array_filter(array_map('trim', array_unique($ft)));
637
+ } else {
638
+ if (!empty($fwe)) {
639
+ $ftypes[] = $fwe;
640
+ }
641
+ }
642
+
643
+ }
644
+
645
+ # name filter
646
+ $name = str_ireplace(' ', '+', trim($name));
647
+
648
+ # save fonts list, merge fontweights
649
+ if(!isset($fonts[$name])) {
650
+ $fonts[$name] = array('name'=>$name, 'type'=>$ftypes);
651
+ } else {
652
+ $ftypes = array_merge($ftypes, $fonts[$name]['type']);
653
+ $fonts[$name] = array('name'=>$name, 'type'=>$ftypes);
654
+ }
655
656
}
657
658
+ # build font names with font weights
659
+ $build = array();
660
+ foreach($fonts as $farr) {
661
+ $f = $farr['name'];
662
+ if(count($farr['type']) > 0) {
663
+ $f.= ':'. implode(',', $farr['type']);
664
+ }
665
+ $build[] = $f;
666
}
667
668
+ # merge, append subsets
669
+ $merge = '';
670
+ if(count($build) > 0) {
671
+ $merge = implode('|', $build);
672
+ if(count($subsets) > 0) {
673
+ $merge.= '&subset='.implode(',', $subsets);
674
+ }
675
+ }
676
677
+ # return
678
+ if(!empty($merge)) {
679
+ return 'https://fonts.googleapis.com/css?family='.$merge;
680
+ } else {
681
+ return false;
682
+ }
683
}
684
685
# remove emoji support
686
function fastvelocity_min_disable_wp_emojicons() {
687
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
libs/matthiasmullie/minify/src/CSS.php CHANGED
@@ -307,10 +307,11 @@ class CSS extends Minify
307
*/
308
$this->extractStrings();
309
$this->stripComments();
310
$css = $this->replace($css);
311
312
$css = $this->stripWhitespace($css);
313
- $css = $this->shortenHex($css);
314
$css = $this->shortenZeroes($css);
315
$css = $this->shortenFontWeights($css);
316
$css = $this->stripEmptyTags($css);
@@ -481,12 +482,16 @@ class CSS extends Minify
481
*
482
* @return string
483
*/
484
- protected function shortenHex($content)
485
{
486
- $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content);
487
488
- // we can shorten some even more by replacing them with their color name
489
$colors = array(
490
'#F0FFFF' => 'azure',
491
'#F5F5DC' => 'beige',
492
'#A52A2A' => 'brown',
@@ -514,6 +519,9 @@ class CSS extends Minify
514
'#FF6347' => 'tomato',
515
'#EE82EE' => 'violet',
516
'#F5DEB3' => 'wheat',
517
);
518
519
return preg_replace_callback(
@@ -559,11 +567,7 @@ class CSS extends Minify
559
// `5px - 0px` is valid, but `5px - 0` is not
560
// `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
561
// `10 * 0` is invalid
562
- // best to just leave `calc()`s alone, even if they could be optimized
563
- // (which is a whole other undertaking, where units & order of
564
- // operations all need to be considered...)
565
- $calcs = $this->findCalcs($content);
566
- $content = str_replace($calcs, array_keys($calcs), $content);
567
568
// reusable bits of code throughout these regexes:
569
// before & after are used to make sure we don't match lose unintended
@@ -600,9 +604,6 @@ class CSS extends Minify
600
$content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content);
601
$content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
602
603
- // restore `calc()` expressions
604
- $content = str_replace(array_keys($calcs), $calcs, $content);
605
-
606
return $content;
607
}
608
@@ -626,6 +627,17 @@ class CSS extends Minify
626
*/
627
protected function stripComments()
628
{
629
$this->registerPattern('/\/\*.*?\*\//s', '');
630
}
631
@@ -648,8 +660,8 @@ class CSS extends Minify
648
// remove whitespace around meta characters
649
// inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
650
$content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
651
- $content = preg_replace('/([\[(:])\s+/', '$1', $content);
652
- $content = preg_replace('/\s+([\]\)])/', '$1', $content);
653
$content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
654
655
// whitespace around + and - can only be stripped inside some pseudo-
@@ -666,18 +678,13 @@ class CSS extends Minify
666
}
667
668
/**
669
- * Find all `calc()` occurrences.
670
- *
671
- * @param string $content The CSS content to find `calc()`s in.
672
- *
673
- * @return string[]
674
*/
675
- protected function findCalcs($content)
676
{
677
- $results = array();
678
- preg_match_all('/calc(\(.+?)(?=$|;|calc\()/', $content, $matches, PREG_SET_ORDER);
679
-
680
- foreach ($matches as $match) {
681
$length = strlen($match[1]);
682
$expr = '';
683
$opened = 0;
@@ -691,11 +698,17 @@ class CSS extends Minify
691
break;
692
}
693
}
694
695
- $results['calc('.count($results).')'] = 'calc'.$expr;
696
- }
697
698
- return $results;
699
}
700
701
/**
307
*/
308
$this->extractStrings();
309
$this->stripComments();
310
+ $this->extractCalcs();
311
$css = $this->replace($css);
312
313
$css = $this->stripWhitespace($css);
314
+ $css = $this->shortenColors($css);
315
$css = $this->shortenZeroes($css);
316
$css = $this->shortenFontWeights($css);
317
$css = $this->stripEmptyTags($css);
482
*
483
* @return string
484
*/
485
+ protected function shortenColors($content)
486
{
487
+ $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?:([0-9a-z])\\4)?(?=[; }])/i', '#$1$2$3$4', $content);
488
+
489
+ // remove alpha channel if it's pointless...
490
+ $content = preg_replace('/(?<=[: ])#([0-9a-z]{6})ff?(?=[; }])/i', '#$1', $content);
491
+ $content = preg_replace('/(?<=[: ])#([0-9a-z]{3})f?(?=[; }])/i', '#$1', $content);
492
493
$colors = array(
494
+ // we can shorten some even more by replacing them with their color name
495
'#F0FFFF' => 'azure',
496
'#F5F5DC' => 'beige',
497
'#A52A2A' => 'brown',
519
'#FF6347' => 'tomato',
520
'#EE82EE' => 'violet',
521
'#F5DEB3' => 'wheat',
522
+ // or the other way around
523
+ 'WHITE' => '#fff',
524
+ 'BLACK' => '#000',
525
);
526
527
return preg_replace_callback(
567
// `5px - 0px` is valid, but `5px - 0` is not
568
// `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
569
// `10 * 0` is invalid
570
+ // we've extracted calcs earlier, so we don't need to worry about this
571
572
// reusable bits of code throughout these regexes:
573
// before & after are used to make sure we don't match lose unintended
604
$content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content);
605
$content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
606
607
return $content;
608
}
609
627
*/
628
protected function stripComments()
629
{
630
+ // PHP only supports $this inside anonymous functions since 5.4
631
+ $minifier = $this;
632
+ $callback = function ($match) use ($minifier) {
633
+ $count = count($minifier->extracted);
634
+ $placeholder = '/*'.$count.'*/';
635
+ $minifier->extracted[$placeholder] = $match[0];
636
+
637
+ return $placeholder;
638
+ };
639
+ $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback);
640
+
641
$this->registerPattern('/\/\*.*?\*\//s', '');
642
}
643
660
// remove whitespace around meta characters
661
// inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
662
$content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
663
+ $content = preg_replace('/([\[(:>\+])\s+/', '$1', $content);
664
+ $content = preg_replace('/\s+([\]\)>\+])/', '$1', $content);
665
$content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
666
667
// whitespace around + and - can only be stripped inside some pseudo-
678
}
679
680
/**
681
+ * Replace all `calc()` occurrences.
682
*/
683
+ protected function extractCalcs()
684
{
685
+ // PHP only supports $this inside anonymous functions since 5.4
686
+ $minifier = $this;
687
+ $callback = function ($match) use ($minifier) {
688
$length = strlen($match[1]);
689
$expr = '';
690
$opened = 0;
698
break;
699
}
700
}
701
+ $rest = str_replace($expr, '', $match[1]);
702
+ $expr = trim(substr($expr, 1, -1));
703
704
+ $count = count($minifier->extracted);
705
+ $placeholder = 'calc('.$count.')';
706
+ $minifier->extracted[$placeholder] = 'calc('.$expr.')';
707
+
708
+ return $placeholder.$rest;
709
+ };
710
711
+ $this->registerPattern('/calc(\(.+?)(?=$|;|calc\()/', $callback);
712
}
713
714
/**
libs/matthiasmullie/minify/src/JS.php CHANGED
@@ -195,11 +195,21 @@ class JS extends Minify
195
*/
196
protected function stripComments()
197
{
198
- // single-line comments
199
- $this->registerPattern('/\/\/.*#x2F;m', '');
200
201
// multi-line comments
202
$this->registerPattern('/\/\*.*?\*\//s', '');
203
}
204
205
/**
@@ -238,7 +248,7 @@ class JS extends Minify
238
// closing the regex)
239
// then also ignore bare `/` inside `[]`, where they don't need to be
240
// escaped: anything inside `[]` can be ignored safely
241
- $pattern = '\\/(?:[^\\[\\/\\\\\n\r]+|(?:\\\\.)+|(?:\\[(?:[^\\]\\\\\n\r]+|(?:\\\\.)+)+\\])+)++\\/[gimuy]*';
242
243
// a regular expression can only be followed by a few operators or some
244
// of the RegExp methods (a `\` followed by a variable or value is
@@ -335,7 +345,9 @@ class JS extends Minify
335
array(
336
'/('.implode('|', $operatorsBefore).')\s+/',
337
'/\s+('.implode('|', $operatorsAfter).')/',
338
- ), '\\1', $content
339
);
340
341
// make sure + and - can't be mistaken for, or joined into ++ and --
@@ -343,7 +355,9 @@ class JS extends Minify
343
array(
344
'/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
345
'/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
346
- ), '\\1', $content
347
);
348
349
// collapse whitespace around reserved words into single space
195
*/
196
protected function stripComments()
197
{
198
+ // PHP only supports $this inside anonymous functions since 5.4
199
+ $minifier = $this;
200
+ $callback = function ($match) use ($minifier) {
201
+ $count = count($minifier->extracted);
202
+ $placeholder = '/*'.$count.'*/';
203
+ $minifier->extracted[$placeholder] = $match[0];
204
205
+ return $placeholder;
206
+ };
207
// multi-line comments
208
+ $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback);
209
$this->registerPattern('/\/\*.*?\*\//s', '');
210
+
211
+ // single-line comments
212
+ $this->registerPattern('/\/\/.*#x2F;m', '');
213
}
214
215
/**
248
// closing the regex)
249
// then also ignore bare `/` inside `[]`, where they don't need to be
250
// escaped: anything inside `[]` can be ignored safely
251
+ $pattern = '\\/(?!\*)(?:[^\\[\\/\\\\\n\r]++|(?:\\\\.)++|(?:\\[(?:[^\\]\\\\\n\r]++|(?:\\\\.)++)++\\])++)++\\/[gimuy]*';
252
253
// a regular expression can only be followed by a few operators or some
254
// of the RegExp methods (a `\` followed by a variable or value is
345
array(
346
'/('.implode('|', $operatorsBefore).')\s+/',
347
'/\s+('.implode('|', $operatorsAfter).')/',
348
+ ),
349
+ '\\1',
350
+ $content
351
);
352
353
// make sure + and - can't be mistaken for, or joined into ++ and --
355
array(
356
'/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
357
'/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
358
+ ),
359
+ '\\1',
360
+ $content
361
);
362
363
// collapse whitespace around reserved words into single space
libs/matthiasmullie/minify/src/Minify.php CHANGED
@@ -241,7 +241,7 @@ abstract class Minify
241
242
// we can safely ignore patterns for positions we've unset earlier,
243
// because we know these won't show up anymore
244
- if (!isset($positions[$i])) {
245
continue;
246
}
247
241
242
// we can safely ignore patterns for positions we've unset earlier,
243
// because we know these won't show up anymore
244
+ if (array_key_exists($i, $positions) == false) {
245
continue;
246
}
247
libs/matthiasmullie/path-converter/src/Converter.php CHANGED
@@ -31,16 +31,17 @@ class Converter implements ConverterInterface
31
/**
32
* @param string $from The original base path (directory, not file!)
33
* @param string $to The new base path (directory, not file!)
34
*/
35
- public function __construct($from, $to)
36
{
37
$shared = $this->shared($from, $to);
38
if ($shared === '') {
39
// when both paths have nothing in common, one of them is probably
40
// absolute while the other is relative
41
- $cwd = getcwd();
42
- $from = strpos($from, $cwd) === 0 ? $from : $cwd.'/'.$from;
43
- $to = strpos($to, $cwd) === 0 ? $to : $cwd.'/'.$to;
44
45
// or traveling the tree via `..`
46
// attempt to resolve path, or assume it's fine if it doesn't exist
@@ -155,7 +156,7 @@ class Converter implements ConverterInterface
155
$to = mb_substr($this->to, mb_strlen($shared));
156
157
// add .. for every directory that needs to be traversed to new path
158
- $to = str_repeat('../', mb_substr_count($to, '/'));
159
160
return $to.ltrim($path, '/');
161
}
31
/**
32
* @param string $from The original base path (directory, not file!)
33
* @param string $to The new base path (directory, not file!)
34
+ * @param string $root Root directory (defaults to `getcwd`)
35
*/
36
+ public function __construct($from, $to, $root = '')
37
{
38
$shared = $this->shared($from, $to);
39
if ($shared === '') {
40
// when both paths have nothing in common, one of them is probably
41
// absolute while the other is relative
42
+ $root = $root ?: getcwd();
43
+ $from = strpos($from, $root) === 0 ? $from : preg_replace('/\/+/', '/', $root.'/'.$from);
44
+ $to = strpos($to, $root) === 0 ? $to : preg_replace('/\/+/', '/', $root.'/'.$to);
45
46
// or traveling the tree via `..`
47
// attempt to resolve path, or assume it's fine if it doesn't exist
156
$to = mb_substr($this->to, mb_strlen($shared));
157
158
// add .. for every directory that needs to be traversed to new path
159
+ $to = str_repeat('../', count(array_filter(explode('/', $to))));
160
161
return $to.ltrim($path, '/');
162
}
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
Contributors: Alignak
3
Tags: PHP Minify, Lighthouse, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance, Optimization, Speed, Fast
4
Requires at least: 4.5
5
- Stable tag: 2.4.1
6
Tested up to: 5.0
7
License: GPLv3 or later
8
License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -111,6 +111,9 @@ The ignore list "is" working, just try to use partial paths (see wildcard help a
111
112
Please note, you must disable any features on your theme or cache plugins, which perform minification of css, html and js. Double minification not only slows the whole process, but also has the high potential of causing conflicts in javascript. The plugin will try to automatically purge several popular cache plugins, however if you have a cache on the server side (some hosting services have this) you may need to purge it manually, after you purge FVM. The automatic purge is active for the following plugins and hosting: W3 Total Cache, WP Supercache, WP Rocket, Wp Fastest Cache, Cachify, Comet Cache, Zen Cache, LiteSpeed Cache, Cache Enabler, SG Optimizer, Godaddy Managed WordPress Hosting and WP Engine
113
114
115
= Is it resource intensive, or will it use too much CPU on my shared hosting plan? =
116
@@ -199,6 +202,27 @@ If you would like to donate any amount to the plugin author (thank you in advanc
199
200
== Changelog ==
201
202
= 2.4.1 [2018.11.27] =
203
* better FVM default settings
204
2
Contributors: Alignak
3
Tags: PHP Minify, Lighthouse, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance, Optimization, Speed, Fast
4
Requires at least: 4.5
5
+ Stable tag: 2.4.4
6
Tested up to: 5.0
7
License: GPLv3 or later
8
License URI: http://www.gnu.org/licenses/gpl-3.0.html
111
112
Please note, you must disable any features on your theme or cache plugins, which perform minification of css, html and js. Double minification not only slows the whole process, but also has the high potential of causing conflicts in javascript. The plugin will try to automatically purge several popular cache plugins, however if you have a cache on the server side (some hosting services have this) you may need to purge it manually, after you purge FVM. The automatic purge is active for the following plugins and hosting: W3 Total Cache, WP Supercache, WP Rocket, Wp Fastest Cache, Cachify, Comet Cache, Zen Cache, LiteSpeed Cache, Cache Enabler, SG Optimizer, Godaddy Managed WordPress Hosting and WP Engine
113
114
+ = Do you recommend a specific Cache Plugin? =
115
+ Yes! Currently FVM recommends the "Cache Enabler" plugin, for it's simplicity, compatibility with most systems and performance.
116
+
117
118
= Is it resource intensive, or will it use too much CPU on my shared hosting plan? =
119
202
203
== Changelog ==
204
205
+ = 2.4.4 [2018.12.03]
206
+ * added option to inline CSS in the footer, while still preserving the merged file in the header
207
+ * improvements for the google fonts merging option
208
+ * fixed double notification, when purging caches without a cache plugin
209
+
210
+ = 2.4.3 [2018.12.03] =
211
+ * added font-display, to ensure text remains visible during webfont load for inlined google fonts and font-awesome
212
+ * added automatic removal of "source mappings" from JS files during merging or minification
213
+ * added font awesome async and exclusion from PSI options, as well as merging and inlining when the url matches "font-awesome" (ie: cdnjs)
214
+ * added automatically inline of small CSS code (up to 20KB) for any FVM CSS files in the footer (requests reduction)
215
+ * added automatically inline of small CSS code (up to 20KB) for any FVM CSS files in the header, which are not of mediatype "all"
216
+ * improved the cache purge button (no more redirect from frontend to backend)
217
+ * updated PHP Minify and Path Converter from master
218
+ * bug fixes related to "Exclude JS files from PSI" option
219
+
220
+ = 2.4.2 [2018.11.29] =
221
+ * fixed a bug with the "Exclude JS files in the ignore list from PSI" option (it wasn't excluding properly)
222
+ * improved functionality with the "Exclude CSS files from PSI" option (now works with both inline and link stylesheets)
223
+ * added an option to automatically preload the CSS and JS files generated by FVM (beware that some server caches like Pantheon may push old css and js files even after purging caches on FVM)
224
+ * improved JavaScript minification
225
+
226
= 2.4.1 [2018.11.27] =
227
* better FVM default settings
228