Fast Velocity Minify - Version 2.4.0

Version Description

[2018.11.26] = * bug fixes related to the inline css option * changed a few options and added better descriptions to the admin options

Download this release

Release Info

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

Code changes from version 2.3.5 to 2.4.0

fvm.php CHANGED
@@ -3,9 +3,9 @@
3
  Plugin Name: Fast Velocity Minify
4
  Plugin URI: http://fastvelocity.com
5
  Description: Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS and JavaScript files into groups, compressing HTML and other speed optimizations.
6
- Author: Raul Peixoto
7
  Author URI: http://fastvelocity.com
8
- Version: 2.3.5
9
  License: GPL2
10
 
11
  ------------------------------------------------------------------------
@@ -60,12 +60,16 @@ function fvm_compat_checker() {
60
  add_action('admin_init', 'fvm_compat_checker');
61
 
62
 
 
 
 
63
  # get the plugin directory
64
  $plugindir = plugin_dir_path( __FILE__ ); # prints with trailing slash
65
 
66
  # reusable functions
67
  include($plugindir.'inc/functions.php');
68
  include($plugindir.'inc/functions-serverinfo.php');
 
69
 
70
  # wp-cli support
71
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
@@ -91,59 +95,69 @@ closedir($handle);
91
 
92
  # default globals
93
  $fastvelocity_min_global_js_done = array();
94
-
 
95
 
96
  ###########################################
97
  # build control panel pages ###############
98
  ###########################################
99
 
100
  # options from the database, false if not set
101
- $ignore = array_map('trim', explode("\n", get_option('fastvelocity_min_ignore', '')));
102
- $blacklist = array_map('trim', explode("\n", get_option('fastvelocity_min_blacklist', '')));
103
- $ignorelist = array_map('trim', explode("\n", get_option('fastvelocity_min_ignorelist', '')));
104
- $merge_allowed_urls = array_map('trim', explode("\n", get_option('fastvelocity_min_merge_allowed_urls', '')));
 
105
  $fvm_enable_purgemenu = get_option('fastvelocity_min_enable_purgemenu');
106
  $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
107
  $disable_js_merge = get_option('fastvelocity_min_disable_js_merge');
108
  $disable_css_merge = get_option('fastvelocity_min_disable_css_merge');
109
  $disable_js_minification = get_option('fastvelocity_min_disable_js_minification');
110
  $disable_css_minification = get_option('fastvelocity_min_disable_css_minification');
111
- $use_yui = get_option('fastvelocity_min_use_yui');
112
  $remove_print_mediatypes = get_option('fastvelocity_min_remove_print_mediatypes');
113
  $skip_html_minification = get_option('fastvelocity_min_skip_html_minification');
114
  $strip_htmlcomments = get_option('fastvelocity_min_strip_htmlcomments');
115
  $skip_cssorder = get_option('fastvelocity_min_skip_cssorder');
116
  $skip_google_fonts = get_option('fastvelocity_min_skip_google_fonts');
117
  $skip_emoji_removal = get_option('fastvelocity_min_skip_emoji_removal');
 
118
  $enable_defer_js = get_option('fastvelocity_min_enable_defer_js');
119
  $exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
120
  $force_inline_css = get_option('fastvelocity_min_force_inline_css');
121
- $force_inline_css_footer = get_option('fastvelocity_min_force_inline_css_footer');
122
- $force_inline_googlefonts = get_option('fastvelocity_min_force_inline_googlefonts');
123
  $remove_googlefonts = get_option('fastvelocity_min_remove_googlefonts');
124
  $defer_for_pagespeed = get_option('fastvelocity_min_defer_for_pagespeed');
125
  $defer_for_pagespeed_optimize = get_option('fastvelocity_min_defer_for_pagespeed_optimize');
126
  $exclude_defer_login = get_option('fastvelocity_min_exclude_defer_login');
127
- $preload = array_map('trim', explode("\n", get_option('fastvelocity_min_preload')));
128
- $preconnect = array_map('trim', explode("\n", get_option('fastvelocity_min_preconnect')));
129
  $fvm_fix_editor = get_option('fastvelocity_min_fvm_fix_editor');
130
- $loadcss = get_option('fastvelocity_min_loadcss');
131
  $fvm_remove_css = get_option('fastvelocity_min_fvm_removecss');
132
- $critical_path_css = get_option('fastvelocity_min_critical_path_css');
133
  $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
134
 
135
-
136
  # default options
137
  $used_css_files = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
- # default blacklist
140
- $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');
141
- if(!is_array($blacklist) || strlen(implode($blacklist)) == 0) { update_option('fastvelocity_min_blacklist', implode("\n", $exc)); }
142
-
143
- # default ignore list
144
- $exc = array('/Avada/assets/js/main.min.js', '/woocommerce-product-search/js/product-search.js', '/includes/builder/scripts/frontend-builder-scripts.js', '/assets/js/jquery.themepunch.tools.min.js', '/js/TweenMax.min.js', '/jupiter/assets/js/min/full-scripts', '/wp-content/themes/Divi/core/admin/js/react-dom.production.min.js');
145
- if(!is_array($ignorelist) || strlen(implode($ignorelist)) == 0) { update_option('fastvelocity_min_ignorelist', implode("\n", $exc)); }
146
 
 
 
147
 
148
 
149
  # add admin page and rewrite defaults
@@ -152,24 +166,56 @@ if(is_admin()) {
152
  add_action('admin_enqueue_scripts', 'fastvelocity_min_load_admin_jscss');
153
  add_action('wp_ajax_fastvelocity_min_files', 'fastvelocity_min_files_callback');
154
  add_action('admin_init', 'fastvelocity_min_register_settings');
155
- register_deactivation_hook( __FILE__, 'fastvelocity_min_plugin_deactivate');
 
 
 
 
 
 
 
 
 
 
156
  } else {
157
 
158
  # skip on certain post_types or if there are specific keys on the url or if editor or admin
159
- if(!fastvelocity_exclude_contents()) {
160
 
161
  # actions for frontend only
162
  if(!$disable_js_merge) {
163
  add_action( 'wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
164
  add_action( 'wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
165
  }
166
- if(!$disable_css_merge) {
167
- add_action('wp_head', 'fvm_buffer_placeholder_top', 0);
168
- add_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
169
- add_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
 
 
 
 
 
 
 
 
 
170
  }
171
  if(!$skip_emoji_removal) {
172
  add_action( 'init', 'fastvelocity_min_disable_wp_emojicons' );
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  }
174
 
175
  # enable html minification
@@ -177,14 +223,15 @@ if(is_admin()) {
177
  add_action('template_redirect', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
178
  }
179
 
180
- # when css async is on
181
- add_action('wp_footer', 'fvm_add_loadcss', PHP_INT_MAX);
182
-
 
183
 
184
  # remove query from static assets and process defering (if enabled)
185
  add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
186
  add_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
187
- add_filter('script_loader_tag', 'fastvelocity_min_defer_js_optimize', 10, 3);
188
 
189
  }
190
  }
@@ -197,25 +244,16 @@ global $fvm_fix_editor, $disable_js_merge, $disable_css_merge, $skip_emoji_remov
197
  if($fvm_fix_editor == true && is_user_logged_in()) {
198
  remove_action('wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
199
  remove_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
200
- remove_action('wp_head', 'fvm_buffer_placeholder_top', 0);
201
  remove_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
202
  remove_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
203
  remove_action('init', 'fastvelocity_min_disable_wp_emojicons');
204
  remove_action('template_redirect', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
205
- remove_action('wp_head', 'fvm_add_loadcss', PHP_INT_MAX);
206
  remove_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
207
  remove_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
208
- remove_filter('script_loader_tag', 'fastvelocity_min_defer_js_optimize', 10, 3);
209
  }
210
  }
211
 
212
-
213
- # delete the cache when we deactivate the plugin
214
- function fastvelocity_min_plugin_deactivate() {
215
- fvm_purge_all();
216
- }
217
-
218
-
219
  # create admin menu
220
  function fastvelocity_min_admin_menu() {
221
  add_options_page('Fast Velocity Minify Settings', 'Fast Velocity Minify', 'manage_options', 'fastvelocity-min', 'fastvelocity_min_settings');
@@ -292,14 +330,13 @@ function fastvelocity_min_load_admin_jscss($hook) {
292
 
293
  # register plugin settings
294
  function fastvelocity_min_register_settings() {
295
- register_setting('fvm-group', 'fastvelocity_min_ignore');
296
- register_setting('fvm-group', 'fastvelocity_min_enable_purgemenu');
297
  register_setting('fvm-group', 'fastvelocity_min_default_protocol');
298
  register_setting('fvm-group', 'fastvelocity_min_disable_js_merge');
299
  register_setting('fvm-group', 'fastvelocity_min_disable_css_merge');
300
  register_setting('fvm-group', 'fastvelocity_min_disable_js_minification');
301
  register_setting('fvm-group', 'fastvelocity_min_disable_css_minification');
302
- register_setting('fvm-group', 'fastvelocity_min_use_yui');
303
  register_setting('fvm-group', 'fastvelocity_min_remove_print_mediatypes');
304
  register_setting('fvm-group', 'fastvelocity_min_skip_html_minification');
305
  register_setting('fvm-group', 'fastvelocity_min_strip_htmlcomments');
@@ -307,30 +344,40 @@ function fastvelocity_min_register_settings() {
307
  register_setting('fvm-group', 'fastvelocity_min_skip_google_fonts');
308
  register_setting('fvm-group', 'fastvelocity_min_skip_fontawesome_fonts');
309
  register_setting('fvm-group', 'fastvelocity_min_skip_emoji_removal');
 
310
  register_setting('fvm-group', 'fastvelocity_min_enable_defer_js');
311
  register_setting('fvm-group', 'fastvelocity_min_exclude_defer_jquery');
312
  register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
313
- register_setting('fvm-group', 'fastvelocity_min_force_inline_css_footer');
314
- register_setting('fvm-group', 'fastvelocity_min_force_inline_googlefonts');
315
  register_setting('fvm-group', 'fastvelocity_min_remove_googlefonts');
 
316
  register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
317
  register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed_optimize');
318
  register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
319
- register_setting('fvm-group', 'fastvelocity_min_preload');
320
- register_setting('fvm-group', 'fastvelocity_min_preconnect');
321
  register_setting('fvm-group', 'fastvelocity_min_fvm_fix_editor');
322
  register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_url');
323
  register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_force');
 
 
324
 
325
- # pro version (for private usage... or if you know what you're doing)
326
- register_setting('fvm-group-pro', 'fastvelocity_min_loadcss');
327
- register_setting('fvm-group-pro', 'fastvelocity_min_fvm_removecss');
328
- register_setting('fvm-group-pro', 'fastvelocity_min_critical_path_css');
329
  register_setting('fvm-group-pro', 'fastvelocity_min_ignorelist');
 
 
330
  register_setting('fvm-group-pro', 'fastvelocity_min_blacklist');
331
  register_setting('fvm-group-pro', 'fastvelocity_min_merge_allowed_urls');
332
- register_setting('fvm-group-pro', 'fastvelocity_min_change_cache_path');
333
- register_setting('fvm-group-pro', 'fastvelocity_min_change_cache_base_url');
 
 
 
 
 
 
 
 
 
 
334
  }
335
 
336
 
@@ -338,7 +385,7 @@ function fastvelocity_min_register_settings() {
338
  # add settings link on plugin page
339
  function fastvelocity_min_settings_link($links) {
340
  if (is_plugin_active(plugin_basename( __FILE__ ))) {
341
- $settings_link = '<a href="options-general.php?page=fastvelocity-min&tab=settings">Settings</a>';
342
  array_unshift($links, $settings_link);
343
  }
344
  return $links;
@@ -376,8 +423,9 @@ if(isset($_GET['page']) && $_GET['page'] == 'fastvelocity-min') {
376
 
377
  <h2 class="nav-tab-wrapper wp-clearfix">
378
  <a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
379
- <a href="?page=fastvelocity-min&tab=settings" class="nav-tab <?php echo $active_tab == 'settings' ? 'nav-tab-active' : ''; ?>">Settings</a>
380
  <a href="?page=fastvelocity-min&tab=pro" class="nav-tab <?php echo $active_tab == 'pro' ? 'nav-tab-active' : ''; ?>">Pro</a>
 
381
  <a href="?page=fastvelocity-min&tab=server" class="nav-tab <?php echo $active_tab == 'server' ? 'nav-tab-active' : ''; ?>">Server Info</a>
382
  <a href="?page=fastvelocity-min&tab=help" class="nav-tab <?php echo $active_tab == 'help' ? 'nav-tab-active' : ''; ?>">Help</a>
383
  </h2>
@@ -395,7 +443,7 @@ if(isset($_GET['page']) && $_GET['page'] == 'fastvelocity-min') {
395
  <div class="inside" id="fastvelocity_min_topbtns">
396
  <ul class="processed">
397
  <li id="purgeall-row">
398
- <span class="filename">Purge FVM cache directory (<span id="fvm_cache_size"><?php echo fastvelocity_get_cachestats(); ?></span>)</span>
399
  <span class="actions">
400
  <form method="post" id="fastvelocity_min_clearall" action="<?php echo admin_url('options-general.php?page=fastvelocity-min&tab=status'); ?>">
401
  <input type="hidden" name="purgeall" value="1" />
@@ -416,7 +464,15 @@ if(isset($_GET['page']) && $_GET['page'] == 'fastvelocity-min') {
416
  <div class="postbox" id="tab-css">
417
  <h3 class="hndle"><span>List of processed CSS files</span></h3>
418
  <div class="inside" id="fastvelocity_min_cssprocessed">
419
- <ul class="processed"></ul>
 
 
 
 
 
 
 
 
420
  </div>
421
  </div>
422
 
@@ -426,37 +482,40 @@ if(isset($_GET['page']) && $_GET['page'] == 'fastvelocity-min') {
426
  </div>
427
  <?php } ?>
428
 
429
- <?php if( $active_tab == 'settings' ) { ?>
430
  <form method="post" action="options.php">
431
  <?php settings_fields('fvm-group'); do_settings_sections('fvm-group'); ?>
432
 
433
 
434
  <div style="height: 20px;"></div>
435
- <h2 class="title">Basic Options</h2>
436
  <p class="fvm-bold-green">These options are generaly safe to edit as needed. If you use a cache plugin, kindly purge all your caches once you're done with the changes.</p>
437
 
438
  <table class="form-table fvm-settings">
439
  <tbody>
440
 
 
441
  <tr>
442
- <th scope="row">Admin Toolbar</th>
443
  <td>
444
- <p class="fvm-bold-green fvm-rowintro">Enable the "FVM purge" button on the admin bar.</p>
 
445
  <fieldset>
446
  <label for="fastvelocity_min_enable_purgemenu">
447
  <input name="fastvelocity_min_enable_purgemenu" type="checkbox" id="fastvelocity_min_enable_purgemenu" value="1" <?php echo checked(1 == get_option('fastvelocity_min_enable_purgemenu'), true, false); ?>>
448
- Admin Bar Purge <span class="note-info">[ If selected, a new option to purge FVM cache from the admin bar will show up. ]</span></label>
449
- </fieldset></td>
450
- </tr>
 
 
 
 
451
 
452
- <tr>
453
- <th scope="row">Troubleshooting</th>
454
- <td>
455
- <p class="fvm-bold-green fvm-rowintro">It's recommended that you enable this, if your theme comes with some sort of visual frontend editor.</p>
456
- <fieldset>
457
  <label for="fastvelocity_min_fvm_fix_editor">
458
  <input name="fastvelocity_min_fvm_fix_editor" type="checkbox" id="fastvelocity_min_fvm_fix_editor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_fvm_fix_editor'), true, false); ?>>
459
- Fix Page Editors <span class="note-info">[ If selected, logged in users will bypass all optimizations ]</span></label>
 
 
460
  </fieldset></td>
461
  </tr>
462
 
@@ -473,9 +532,9 @@ $c = ''; if($sel == 'https') { $c = ' checked="checked"'; }
473
  ?>
474
  <p class="fvm-bold-green fvm-rowintro">You may need to force http or https, for some CDN plugins to work:</p>
475
  <fieldset>
476
- <label><input type="radio" name="fastvelocity_min_default_protocol" value="dynamic" <?php echo $a; ?>> Use the dynamic "//" protocol</label><br>
477
- <label><input type="radio" name="fastvelocity_min_default_protocol" value="http"<?php echo $b; ?>> Force HTTP urls</label><br>
478
- <label><input type="radio" name="fastvelocity_min_default_protocol" value="https"<?php echo $c; ?>> Force HTTPS urls</span></label><br>
479
  </fieldset>
480
  </td>
481
  </tr>
@@ -496,6 +555,11 @@ Disable HTML Minification <span class="note-info">[ This will disable HTML minif
496
  Strip HTML comments <span class="note-info">[ Only works with the default HTML minification, but note that some plugins need HTML comments to work properly ]</span></label>
497
  <br />
498
 
 
 
 
 
 
499
  </fieldset></td>
500
  </tr>
501
 
@@ -503,7 +567,7 @@ Strip HTML comments <span class="note-info">[ Only works with the default HTML m
503
  <tr>
504
  <th scope="row">Fonts Options</th>
505
  <td>
506
- <p class="fvm-bold-green fvm-rowintro">It's recommended that you enable the "Inline Google Fonts CSS" option.</p>
507
  <fieldset>
508
  <label for="fastvelocity_min_skip_emoji_removal">
509
  <input name="fastvelocity_min_skip_emoji_removal" type="checkbox" id="fastvelocity_min_skip_emoji_removal" class="jsprocessor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_emoji_removal'), true, false); ?> >
@@ -515,21 +579,33 @@ Stop removing Emojis and smileys <span class="note-info">[ If selected, Emojis w
515
  Disable Google Fonts merging <span class="note-info">[ If selected, Google Fonts will no longer be merged into one request ]</span></label>
516
  <br />
517
 
518
- <label for="fastvelocity_min_force_inline_googlefonts">
519
- <input name="fastvelocity_min_force_inline_googlefonts" type="checkbox" id="fastvelocity_min_force_inline_googlefonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_googlefonts'), true, false); ?> >
520
- Inline Google Fonts CSS <span class="note-info">[ If selected, Google Fonts CSS code will be inlined using "*.woof" format - NOTE: IE9+ and <a target="_blank" href="http://caniuse.com/#feat=woff">modern browsers</a> only]</span></label>
521
- <br />
522
-
523
  <label for="fastvelocity_min_remove_googlefonts">
524
  <input name="fastvelocity_min_remove_googlefonts" type="checkbox" id="fastvelocity_min_remove_googlefonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_remove_googlefonts'), true, false); ?> >
525
- Remove Google Fonts <span class="note-info">[ If selected, all enqueued Google Fonts will be removed from the site ]</span></label>
526
  <br />
527
 
528
  </fieldset></td>
529
  </tr>
530
 
531
 
532
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
 
534
  <tr>
535
  <th scope="row">CSS Options</th>
@@ -547,7 +623,7 @@ Disable minification on CSS files <span class="note-info">[ If selected, CSS fil
547
  <br />
548
  <label for="fastvelocity_min_skip_cssorder">
549
  <input name="fastvelocity_min_skip_cssorder" type="checkbox" id="fastvelocity_min_skip_cssorder" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_cssorder'), true, false); ?> >
550
- Preserve the order of CSS files <span class="note-info">[ If selected, you will have better CSS compatibility but possibly more CSS files]</span></label>
551
  <br />
552
  <label for="fastvelocity_min_remove_print_mediatypes">
553
  <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); ?> >
@@ -555,11 +631,7 @@ Remove the "Print" related stylesheets <span class="note-info">[ If selected, CS
555
  <br />
556
  <label for="fastvelocity_min_force_inline_css">
557
  <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); ?>>
558
- Inline all header CSS files <span class="note-info">[ If selected, the header CSS will be inlined to avoid the "render blocking" on pagespeed insights tests ]</span></label>
559
- <br />
560
- <label for="fastvelocity_min_force_inline_css_footer">
561
- <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); ?>>
562
- Inline all footer CSS files <span class="note-info">[ If selected, the footer CSS will be inlined to avoid the "render blocking" on pagespeed insights tests ]</span></label>
563
  <br />
564
  </fieldset></td>
565
  </tr>
@@ -575,31 +647,13 @@ Inline all footer CSS files <span class="note-info">[ If selected, the footer CS
575
  Disable JavaScript processing <span class="note-info">[ If selected, this plugin will ignore JS files completely ]</span></label>
576
  <br />
577
 
578
- <?php
579
- # check for exec + a supported java version
580
- if(function_exists('exec') && exec('command -v java >/dev/null && echo "yes" || echo "no"') == 'yes') {
581
- ?>
582
- <label for="fastvelocity_min_use_yui">
583
- <input name="fastvelocity_min_use_yui" type="checkbox" id="fastvelocity_min_use_yui" class="jsprocessor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_use_yui'), true, false); ?> >
584
- Minify with YUI Compressor <span class="note-info">[ If selected, it will try to use the YUI Compressor to minify JS files ]</span></label>
585
- <br />
586
- <?php } ?>
587
-
588
  <label for="fastvelocity_min_disable_js_minification">
589
  <input name="fastvelocity_min_disable_js_minification" type="checkbox" id="fastvelocity_min_disable_js_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_minification'), true, false); ?> >
590
  Disable minification on JS files <span class="note-info">[ If selected, JS files will be merged but not minified ]</span></label>
591
  <br />
592
  </fieldset></td>
593
  </tr>
594
- </tbody></table>
595
-
596
-
597
- <div style="height: 20px;"></div>
598
- <h2 class="title">JS Advanced Options</h2>
599
- <p class="fvm-bold-green">It's highly recommended that you only select the options below if you're an advanced user or developer and understand what these options mean.</p>
600
 
601
- <table class="form-table fvm-settings">
602
- <tbody>
603
  <tr>
604
  <th scope="row">Render-blocking JS</th>
605
  <td>
@@ -610,19 +664,10 @@ Disable minification on JS files <span class="note-info">[ If selected, JS files
610
  <input name="fastvelocity_min_enable_defer_js" type="checkbox" id="fastvelocity_min_enable_defer_js" value="1" <?php echo checked(1 == get_option('fastvelocity_min_enable_defer_js'), true, false); ?>>
611
  Enable defer parsing of JS files globally <span class="note-info">[ Not all browsers, themes or plugins support this. Beware of broken functionality and design ]</span></label>
612
  <br />
613
- <label for="fastvelocity_min_defer_for_pagespeed">
614
- <input name="fastvelocity_min_defer_for_pagespeed" type="checkbox" id="fastvelocity_min_defer_for_pagespeed" value="1" <?php echo checked(1 == get_option('fastvelocity_min_defer_for_pagespeed'), true, false); ?>>
615
- Enable defer of JS for Pagespeed Insights <span class="note-info">[ Defer JS files for Pagespeed Insights only ]</span></label>
616
- <br />
617
-
618
- <label for="fastvelocity_min_defer_for_pagespeed_optimize">
619
- <input name="fastvelocity_min_defer_for_pagespeed_optimize" type="checkbox" id="fastvelocity_min_defer_for_pagespeed_optimize" value="1" <?php echo checked(1 == get_option('fastvelocity_min_defer_for_pagespeed_optimize'), true, false); ?>>
620
- Exclude JS files in the "ignore list" from Pagespeed Insights <span class="note-info">[ This only works with the option to defer for Pagespeed Insights ]</span></label>
621
- <br />
622
 
623
  <label for="fastvelocity_min_exclude_defer_jquery">
624
  <input name="fastvelocity_min_exclude_defer_jquery" type="checkbox" id="fastvelocity_min_exclude_defer_jquery" value="1" <?php echo checked(1 == get_option('fastvelocity_min_exclude_defer_jquery'), true, false); ?> >
625
- Skip deferring the jQuery library <span class="note-info">[ Will fix "undefined jQuery" errors on the Google Chrome console log ]</span></label>
626
  <br />
627
  <label for="fastvelocity_min_exclude_defer_login">
628
  <input name="fastvelocity_min_exclude_defer_login" type="checkbox" id="fastvelocity_min_exclude_defer_login" value="1" <?php echo checked(1 == get_option('fastvelocity_min_exclude_defer_login'), true, false); ?> >
@@ -632,26 +677,27 @@ Skip deferring completely on the login page <span class="note-info">[ If selecte
632
 
633
  </fieldset></td>
634
  </tr>
635
- </tbody></table>
636
-
637
 
 
 
 
 
 
 
 
 
638
 
639
- <div style="height: 20px;"></div>
640
- <h2 class="title">JS and CSS Exceptions</h2>
641
- <p class="fvm-bold-green">You can use this section to exclude certain CSS or JS files from being processed in case of conflicts while merging.<br />Read the HELP section for information on why you may need to use this.</p>
 
642
 
643
- <table class="form-table fvm-settings">
644
- <tbody>
645
- <tr>
646
- <th scope="row">Ignore List</th>
647
- <td><fieldset>
648
- <label for="blacklist_keys"><span class="fvm-label-pad">Ignore the following CSS and JS paths below:</span></label>
649
- <p>
650
- <textarea name="fastvelocity_min_ignore" rows="10" cols="50" id="fastvelocity_min_ignore" class="large-text code" placeholder="ex: /wp-includes/js/jquery/jquery.js"><?php echo get_option('fastvelocity_min_ignore'); ?></textarea>
651
- </p>
652
- <p class="description">[ Your own list of js /css files to ignore with wildcard support (read the faqs) ]</p>
653
  </fieldset></td>
654
  </tr>
 
 
 
 
655
  </tbody></table>
656
 
657
 
@@ -680,103 +726,168 @@ I know what I'm doing... <span class="note-info">[ Load my JS files from the CDN
680
  </tr>
681
  </tbody></table>
682
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
683
 
684
  <div style="height: 20px;"></div>
685
- <h2 class="title">Preconnect Optimization</h2>
686
- <p class="fvm-bold-green">Please make sure you understand these options before using them.</p>
687
 
 
688
  <table class="form-table fvm-settings">
689
  <tbody>
690
  <tr>
691
- <th scope="row">Preconnect Headers</th>
692
- <td><fieldset><legend class="screen-reader-text"><span>Preconnect</span></legend>
693
- <label for="fastvelocity_min_preconnect"><span class="fvm-label-pad">Insert one domain name url per line:</span></label>
694
  <p>
695
- <textarea name="fastvelocity_min_preconnect" rows="10" cols="50" id="fastvelocity_min_preconnect" class="large-text code" placeholder="ex: //fonts.gstatic.com"><?php echo get_option('fastvelocity_min_preconnect'); ?></textarea>
696
  </p>
697
- <p class="description">[ Use only the necessary domain names, such as remote font domain names, ex: //fonts.gstatic.com ]</p>
698
  </fieldset></td>
699
  </tr>
700
-
701
  </tbody></table>
702
 
703
 
704
  <div style="height: 20px;"></div>
705
- <h2 class="title">Homepage Optimization</h2>
706
- <p class="fvm-bold-green">Use this only for images above the fold that exist in all pages, such as your logo.</p>
707
-
708
  <table class="form-table fvm-settings">
709
  <tbody>
710
  <tr>
711
- <th scope="row">Preload Images</th>
712
- <td><fieldset><legend class="screen-reader-text"><span>Preload Images</span></legend>
713
- <label for="fastvelocity_min_preload"><span class="fvm-label-pad">Insert one image url per line:</span></label>
714
  <p>
715
- <textarea name="fastvelocity_min_preload" rows="10" cols="50" id="fastvelocity_min_preload" class="large-text code" placeholder="ex: //yoursite.com/wp-content/plugins/some-slider/large.img"><?php echo get_option('fastvelocity_min_preload'); ?></textarea>
716
  </p>
717
- <p class="description">[ Use only for large images that first load above the fold. Read the Help section for more details. ]</p>
718
  </fieldset></td>
719
  </tr>
720
  </tbody></table>
721
 
722
 
723
- <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
724
- </form>
725
- <?php } ?>
 
 
 
 
 
 
 
726
 
 
 
 
727
 
728
- <?php if( $active_tab == 'pro' ) { ?>
729
 
730
- <form method="post" action="options.php">
731
- <?php settings_fields('fvm-group-pro'); do_settings_sections('fvm-group-pro'); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
732
 
733
 
734
- <div style="height: 20px;"></div>
735
- <h2 class="title">Pro Optimization</h2>
736
- <p class="fvm-bold-green">Do NOT touch these settings, unless you're a developer that understands exactly what this does.<br />This section is experimental and may or may not be removed or restructured in the future.</p>
737
 
738
 
 
739
  <table class="form-table fvm-settings">
740
  <tbody>
741
-
742
-
743
  <tr>
744
- <th scope="row">Critical Path CSS</th>
745
  <td>
746
- <fieldset>
747
- <label for="blacklist_keys"><span class="fvm-label-pad">The CSS code here, will show up inside "style" tags in the header globally:</span></label>
748
  <p>
749
- <textarea name="fastvelocity_min_critical_path_css" rows="10" cols="50" id="fastvelocity_min_critical_path_css" class="large-text code" placeholder="your css code here"><?php echo get_option('fastvelocity_min_critical_path_css'); ?></textarea>
750
  </p>
751
- <p class="description">[ Use this if you're familiar with <a target="_blank" href="https://github.com/giakki/uncss">UnCSS</a> or have the correct critical path css. ]</p>
752
- </fieldset>
753
- </td>
754
  </tr>
 
755
 
756
-
 
 
757
  <tr>
758
- <th scope="row">Extra CSS Options</th>
759
- <td><fieldset>
760
- <label for="fastvelocity_min_fvm_removecss">
761
- <input name="fastvelocity_min_fvm_removecss" type="checkbox" id="fastvelocity_min_fvm_removecss" value="1" <?php echo checked(1 == get_option('fastvelocity_min_fvm_removecss'), true, false); ?>>
762
- Dequeue all CSS files <span class="note-info">[ Use this if you have your uncss code, your own css file or want to test how the critical path css looks like ]</span></label>
763
- </td>
 
764
  </tr>
765
  </tbody></table>
766
 
767
 
 
 
 
 
 
 
 
 
 
 
 
 
768
  <div style="height: 20px;"></div>
769
- <h2 class="title">Async CSS</h2>
770
- <p class="fvm-bold-green">If you have multiple css files per media type, they may load out of order and break your design.<br />Pagespeed will still complain about render blocking, until you have the correct critical path CSS code.</p>
771
 
772
  <table class="form-table fvm-settings">
773
  <tbody>
774
  <tr>
775
- <th scope="row">Enable Async CSS</th>
776
  <td><fieldset>
777
- <label for="fastvelocity_min_loadcss">
778
- <input name="fastvelocity_min_loadcss" type="checkbox" id="fastvelocity_min_loadcss" value="1" <?php echo checked(1 == get_option('fastvelocity_min_loadcss'), true, false); ?>>
779
- Async CSS with LoadCSS<span class="note-info">[ Only works if "Inline all header / footer CSS files" is disabled ]</span></label>
 
780
  </fieldset>
781
  </td>
782
  </tr>
@@ -785,109 +896,175 @@ Async CSS with LoadCSS<span class="note-info">[ Only works if "Inline all header
785
 
786
 
787
 
788
-
789
-
790
  <div style="height: 20px;"></div>
791
- <h2 class="title">Special JS and CSS Exceptions</h2>
792
- <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>
 
 
793
 
794
- <div style="height: 20px;"></div>
795
  <table class="form-table fvm-settings">
796
  <tbody>
797
  <tr>
798
- <th scope="row">External URLs to Merge</th>
799
- <td><fieldset><label for="blacklist_keys"><span class="fvm-label-pad">List of external domains that can be fetched and merged together:</span></label>
 
800
  <p>
801
- <textarea name="fastvelocity_min_merge_allowed_urls" rows="10" cols="50" id="fastvelocity_min_merge_allowed_urls" class="large-text code" placeholder="ex: example.com"><?php echo get_option('fastvelocity_min_merge_allowed_urls'); ?></textarea>
802
  </p>
803
- <p class="description">[ Add any external "domains" for JS or CSS files than can be merged fetched and merged together by FVM, ie: example.com ]</p>
 
 
 
804
  </fieldset></td>
805
  </tr>
 
806
  </tbody></table>
807
 
808
- <div style="height: 20px;"></div>
809
  <table class="form-table fvm-settings">
810
  <tbody>
811
  <tr>
812
- <th scope="row">Default Ignore List</th>
813
- <td>
814
- <fieldset><label for="blacklist_keys"><span class="fvm-label-pad">Do not edit, if you're not sure what this is:</span></label>
815
  <p>
816
- <textarea name="fastvelocity_min_ignorelist" rows="10" cols="50" id="fastvelocity_min_ignorelist" class="large-text code" placeholder="ex: /wp-includes/js/jquery/jquery.js"><?php echo get_option('fastvelocity_min_ignorelist'); ?></textarea>
817
  </p>
818
- <p class="description">[ Files that have been reported by other users to cause trouble when merged and that should always be ignored ]</p>
 
 
819
  </fieldset></td>
820
  </tr>
821
  </tbody></table>
822
 
 
823
  <div style="height: 20px;"></div>
 
 
 
824
  <table class="form-table fvm-settings">
825
  <tbody>
826
  <tr>
827
- <th scope="row">Default Blacklist</th>
828
- <td><fieldset><label for="blacklist_keys"><span class="fvm-label-pad">Do not edit, if you're not sure what this is:</span></label>
829
- <p>
830
- <textarea name="fastvelocity_min_blacklist" rows="10" cols="50" id="fastvelocity_min_blacklist" class="large-text code" placeholder="ex: /wp-includes/js/jquery/jquery.js"><?php echo get_option('fastvelocity_min_blacklist'); ?></textarea>
831
- </p>
832
- <p class="description">[ Usually, any IE css /js files that should always be ignored without incrementing the groups ]</p>
833
- </fieldset></td>
 
 
 
 
 
 
834
  </tr>
 
835
  </tbody></table>
836
 
837
 
838
  <div style="height: 20px;"></div>
839
- <h2 class="title">Cache Location</h2>
840
- <p class="fvm-bold-green">If your server blocks JavaScript on the uploads directory, you can change "wp-content/uploads" with "wp-content/cache" or other allowed public directory.</p>
 
 
 
841
  <table class="form-table fvm-settings">
842
  <tbody>
 
843
  <tr>
844
- <th scope="row"><span class="fvm-label-special">Cache Path</span></th>
845
- <td><fieldset>
846
- <label for="fastvelocity_min_change_cache_path">
847
- <p><input type="text" name="fastvelocity_min_change_cache_path" id="fastvelocity_min_change_cache_path" value="<?php echo get_option('fastvelocity_min_change_cache_path', ''); ?>" size="80" /></p>
848
- <p class="description">[ Default cache path is: <?php echo rtrim(wp_upload_dir()['basedir'], '/'); ?> ]</p>
849
- </label>
850
- </fieldset></td>
 
 
851
  </tr>
 
852
  <tr>
853
- <th scope="row"><span class="fvm-label-special">Cache Base URL</span></th>
854
- <td><fieldset>
855
- <label for="fastvelocity_min_change_cache_base_url">
856
- <p><input type="text" name="fastvelocity_min_change_cache_base_url" id="fastvelocity_min_change_cache_base_url" value="<?php echo get_option('fastvelocity_min_change_cache_base_url', ''); ?>" size="80" /></p>
857
- <p class="description">[ Default cache base url is: <?php echo rtrim(fvm_get_protocol(wp_upload_dir()['baseurl']), '/'); ?> ]</p>
858
- </label>
859
- </fieldset></td>
 
 
860
  </tr>
 
861
  </tbody></table>
862
 
863
 
 
864
  <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
865
  </form>
866
 
867
  <?php
868
  }
869
 
 
 
870
  if( $active_tab == 'server' ) {
871
  fvm_get_generalinfo();
872
  }
873
- ?>
874
 
875
- <?php if( $active_tab == 'help' ) { ?>
 
 
876
 
877
  <div class="wrap" id="fastvelocity-min">
878
  <div id="poststuff">
879
  <div id="fastvelocity_min_processed" class="postbox-container">
880
  <div class="meta-box-sortables ui-sortable">
 
 
 
 
 
 
 
 
881
 
882
  <div class="postbox" id="tab-info">
883
  <h3 class="hndle"><span>Frequently Asked Questions</span></h3>
884
- <div class="inside"><? echo fastvelocity_min_readme($plugindir.'readme.txt'); ?></div>
 
 
885
  </div>
886
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
887
  </div>
888
  </div>
889
  </div>
890
  </div>
 
891
  <?php } ?>
892
 
893
 
@@ -904,7 +1081,7 @@ fvm_get_generalinfo();
904
  # process header javascript ###############
905
  ###########################################
906
  function fastvelocity_min_merge_header_scripts() {
907
- 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;
908
  if(!is_object($wp_scripts)) { return false; }
909
  $scripts = wp_clone($wp_scripts);
910
  $scripts->all_deps($scripts->queue);
@@ -985,32 +1162,39 @@ for($i=0,$l=count($header);$i<$l;$i++) {
985
  $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
986
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
987
 
988
- # get css from hurl, if available and valid
989
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
990
- $newcode = false; $newcode = fvm_get_transient($tkey);
991
- if ( $newcode === false) {
992
- $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
993
- if(is_array($res)) {
994
- $newcode = $res['code'];
995
- $newlog = $res['log'];
996
- }
997
- } else {
998
- $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
999
  }
1000
-
1001
- # append
1002
- if($newcode !== false) {
1003
- $code.= $newcode;
1004
- $log.= $newlog;
1005
- }
 
 
 
 
 
 
 
1006
 
1007
  # Add extra data from wp_add_inline_script before
1008
- if ( ! empty( $wp_scripts->registered[$handle]->extra ) ) {
1009
- if ( ! empty( $wp_scripts->registered[$handle]->extra['before'] ) ) {
1010
- $code.= "\n".implode("\n", $wp_scripts->registered[$handle]->extra['before']);
1011
  }
1012
  }
1013
 
 
 
 
 
1014
  # consider dependencies on handles with an empty src
1015
  } else {
1016
  wp_dequeue_script($handle); wp_enqueue_script($handle);
@@ -1018,7 +1202,7 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1018
  endforeach;
1019
 
1020
  # prepare log
1021
- $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1022
 
1023
  # generate cache, write log
1024
  file_put_contents($file.'.txt', $log);
@@ -1034,7 +1218,7 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1034
  foreach($header[$i]['handles'] as $handle) {
1035
  if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1036
  }
1037
- if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode("\n", $data); }
1038
 
1039
  # enqueue file, if not empty
1040
  $check = ''; $check = trim(file_get_contents($file));
@@ -1060,7 +1244,7 @@ $wp_scripts->done = $done;
1060
  # process js in the footer ################
1061
  ###########################################
1062
  function fastvelocity_min_merge_footer_scripts() {
1063
- 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;
1064
  if(!is_object($wp_scripts)) { return false; }
1065
  $ctime = get_option('fvm-last-cache-update', '0');
1066
  $scripts = wp_clone($wp_scripts);
@@ -1129,29 +1313,33 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1129
  $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1130
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1131
 
1132
- # get css from hurl, if available and valid
1133
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1134
- $newcode = false; $newcode = fvm_get_transient($tkey);
1135
- if ( $newcode === false) {
1136
- $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
1137
- if(is_array($res)) {
1138
- $newcode = $res['code'];
1139
- $newlog = $res['log'];
1140
- }
1141
- } else {
1142
- $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1143
  }
1144
-
1145
- # append
1146
- if($newcode !== false) {
1147
- $code.= $newcode;
1148
- $log.= $newlog;
 
 
 
1149
  }
1150
 
 
 
 
 
1151
  # Add extra data from wp_add_inline_script before
1152
- if ( ! empty( $wp_scripts->registered[$handle]->extra ) ) {
1153
- if ( ! empty( $wp_scripts->registered[$handle]->extra['before'] ) ) {
1154
- $code.= "\n".implode("\n", $wp_scripts->registered[$handle]->extra['before']);
1155
  }
1156
  }
1157
 
@@ -1163,7 +1351,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1163
  endforeach;
1164
 
1165
  # prepare log
1166
- $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1167
 
1168
  # generate cache, write log
1169
  file_put_contents($file.'.txt', $log);
@@ -1179,7 +1367,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1179
  foreach($footer[$i]['handles'] as $handle) {
1180
  if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1181
  }
1182
- if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode("\n", $data); }
1183
 
1184
  # enqueue file, if not empty
1185
  $check = ''; $check = trim(file_get_contents($file));
@@ -1204,7 +1392,7 @@ $wp_scripts->done = $done;
1204
  # enable defer for JavaScript (WP 4.1 and above) and remove query strings for ignored files
1205
  ###########################################
1206
  function fastvelocity_min_defer_js($tag, $handle, $src) {
1207
- global $ignore, $blacklist, $ignorelist, $enable_defer_js, $defer_for_pagespeed, $wp_domain, $exclude_defer_login, $fvm_fix_editor;
1208
 
1209
  # no query strings
1210
  $tag = trim($tag); # must cleanup
@@ -1250,11 +1438,11 @@ if ($defer_for_pagespeed != true) { return $tag; } else {
1250
  if (fvm_is_local_domain($src) !== true) { return $tag; }
1251
 
1252
  # return if there are linebreaks (will break document.write)
1253
- if (stripos($tag, "\n") !== false) { return $tag; }
1254
 
1255
  # print code if there are no linebreaks, or return
1256
  if(!empty($tagdefer)) {
1257
- $deferinsights = '<script type="text/javascript">if(navigator.userAgent.match(/speed|Lighthouse|gtmetrix|Linux.*Moto\sG|x11.*firefox\/54|x11.*chrome\/39/i)){document.write('.json_encode($tagdefer).');}else{document.write('.json_encode($tag).');}</script>';
1258
  return preg_replace('#<script(.*?)>(.*?)</script>#is', $deferinsights, $tag);
1259
  }
1260
 
@@ -1271,7 +1459,7 @@ return $tag;
1271
  # process header css ######################
1272
  ###########################################
1273
  function fastvelocity_min_merge_header_css() {
1274
- global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_css, $force_inline_googlefonts, $remove_googlefonts, $loadcss, $critical_path_css, $fvm_remove_css;
1275
  if(!is_object($wp_styles)) { return false; }
1276
  $ctime = get_option('fvm-last-cache-update', '0');
1277
  $styles = wp_clone($wp_styles);
@@ -1296,7 +1484,6 @@ if($fvm_remove_css != false) {
1296
  # add defaults to ignore list
1297
  $ignore = fastvelocity_default_ignore($ignore);
1298
 
1299
-
1300
  # get list of handles to process, dequeue duplicate css urls and keep empty source handles (for dependencies)
1301
  $uniq = array(); $gfonts = array();
1302
  foreach( $styles->to_do as $handle):
@@ -1311,7 +1498,7 @@ foreach( $styles->to_do as $handle):
1311
  if ($mediatype == 'screen' || $mediatype == 'screen, print') { $mediatype = 'all'; }
1312
 
1313
  # full url or empty
1314
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1315
 
1316
  # mark duplicates as done and remove from the queue
1317
  if(!empty($hurl)) {
@@ -1325,7 +1512,10 @@ foreach( $styles->to_do as $handle):
1325
  # google fonts to the top (collect and skip process array)
1326
  if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1327
  if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
1328
- if(!$skip_google_fonts) { $google_fonts[$handle] = $hurl; } else {
 
 
 
1329
  wp_enqueue_style($handle); # skip google fonts optimization?
1330
  }
1331
  continue;
@@ -1338,27 +1528,70 @@ endforeach;
1338
 
1339
 
1340
  # concat google fonts, if enabled
1341
- if(!$skip_google_fonts && count($google_fonts) > 0) {
1342
- $concat_google_fonts = fastvelocity_min_concatenate_google_fonts($google_fonts);
1343
  foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1344
- if($force_inline_googlefonts == false) {
1345
- wp_enqueue_style('header-fvm-fonts', fvm_get_protocol($concat_google_fonts), array(), null, 'all');
 
 
 
1346
  } else {
1347
-
1348
- # google fonts download and inlining, ignore logs
1349
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1350
- $newcode = false; $newcode = fvm_get_transient($tkey);
1351
- if ( $newcode === false) {
1352
- $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
1353
- if(is_array($res)) { $newcode = $res['code']; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1354
  }
1355
-
1356
- # inline css or fail
1357
- if($newcode !== false) {
1358
- echo '<style type="text/css" media="all">'.$newcode.'</style>'."\n";
1359
- } else {
1360
- echo "<!-- GOOGLE FONTS REQUEST FAILED for $concat_google_fonts -->\n"; # log if failed
1361
- }
1362
  }
1363
  }
1364
 
@@ -1434,12 +1667,6 @@ if(!$skip_cssorder) {
1434
  }
1435
  }
1436
 
1437
- # critical path
1438
- if(!empty($critical_path_css) && $critical_path_css != false) {
1439
- echo '<style id="critical-path-global" type="text/css" media="all">'.$critical_path_css.'</style>'."\n";
1440
- }
1441
-
1442
-
1443
  # loop through header css and merge
1444
  for($i=0,$l=count($header);$i<$l;$i++) {
1445
  if(!isset($header[$i]['handle'])) {
@@ -1473,26 +1700,33 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1473
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1474
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1475
 
1476
- # get css from hurl, if available and valid
1477
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1478
- $newcode = false; $newcode = fvm_get_transient($tkey);
1479
- if ( $newcode === false) {
1480
- $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
1481
- if(is_array($res)) {
1482
- $newcode = $res['code'];
1483
- $newlog = $res['log'];
1484
- }
1485
- } else {
1486
- $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1487
  }
1488
-
1489
- # append
1490
- if($newcode !== false) {
1491
- $code.= $newcode;
1492
- if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) { $code.= $inline_css[$handle]; } # add inline css on the fly
1493
- $log.= $newlog;
1494
- }
1495
-
 
 
 
 
 
 
 
 
 
 
 
1496
  # consider dependencies on handles with an empty src
1497
  } else {
1498
  wp_dequeue_script($handle);
@@ -1501,7 +1735,7 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1501
  endforeach;
1502
 
1503
  # prepare log
1504
- $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1505
 
1506
  # generate cache, write log
1507
  file_put_contents($file.'.txt', $log);
@@ -1511,42 +1745,23 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1511
  }
1512
 
1513
  # register and enqueue minified file, consider excluding of mediatype "print" and inline css
1514
- if ($remove_print_mediatypes != 1 || ($remove_print_mediatypes == 1 && $header[$i]['media'] != 'print')) {
1515
- if($force_inline_css != false) {
1516
-
1517
- # print file, if not empty
1518
- $check = ''; $check = trim(file_get_contents($file));
1519
- if(file_exists($file) && !empty($check)) {
1520
- echo '<style type="text/css" media="'.$header[$i]['media'].'">'.$check.'</style>';
1521
- }
1522
 
 
 
 
 
 
 
 
 
 
 
1523
  } else {
1524
-
1525
- # move CSS to footer with loadCSS ?
1526
- if($loadcss != false) {
1527
- if($fvm_remove_css != true) {
1528
-
1529
- # save to some sort of global and show it on the footer
1530
- $mt = $header[$i]['media'];
1531
- echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$mt.'" onload="this.onload=null;this.rel=\'stylesheet\'">';
1532
- echo '<noscript><link rel="stylesheet" type="text/css" media="'.$mt.'" href="'.$file_url.'"></noscript>';
1533
- echo '<!--[if IE]><link rel="stylesheet" type="text/css" media="'.$mt.'" href="'.$file_url.'"><![endif]-->';
1534
-
1535
- /*
1536
- # alternative way
1537
- echo <<<EOF
1538
- <script type="text/javascript">var ldfvm$i=document.createElement("link");ldfvm$i.rel="stylesheet",ldfvm$i.type="text/css",ldfvm$i.media="bogus",ldfvm$i.href="$file_url",ldfvm$i.onload=function(){ldfvm$i.media="$mt"},document.getElementsByTagName("head")[0].appendChild(ldfvm$i);</script>
1539
- EOF;
1540
- */
1541
-
1542
- }
1543
- } else {
1544
- # enqueue file, if not empty
1545
- $check = ''; $check = trim(file_get_contents($file));
1546
- if(file_exists($file) && !empty($check)) {
1547
- wp_register_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
1548
- wp_enqueue_style("fvm-header-$i");
1549
- }
1550
  }
1551
  }
1552
  }
@@ -1569,7 +1784,8 @@ $wp_styles->done = $done;
1569
  # process css in the footer ###############
1570
  ###########################################
1571
  function fastvelocity_min_merge_footer_css() {
1572
- global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_css_footer, $force_inline_googlefonts, $remove_googlefonts, $loadcss, $fvm_remove_css;
 
1573
  if(!is_object($wp_styles)) { return false; }
1574
  $ctime = get_option('fvm-last-cache-update', '0');
1575
  $styles = wp_clone($wp_styles);
@@ -1601,9 +1817,11 @@ foreach( $styles->to_do as $handle ) :
1601
  if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1602
  wp_dequeue_style($handle);
1603
  if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
1604
- if(!$skip_google_fonts) { $google_fonts[$handle] = $hurl; } else {
1605
- wp_enqueue_style($handle); # skip google fonts optimization?
1606
- }
 
 
1607
  } else {
1608
  wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
1609
  }
@@ -1611,27 +1829,74 @@ endforeach;
1611
 
1612
 
1613
  # concat google fonts, if enabled
1614
- if(!$skip_google_fonts && count($google_fonts) > 0) {
1615
- $concat_google_fonts = fastvelocity_min_concatenate_google_fonts($google_fonts);
1616
  foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1617
- if($force_inline_googlefonts == false) {
1618
- wp_enqueue_style('footer-fvm-fonts', fvm_get_protocol($concat_google_fonts), array(), null, 'all');
 
 
 
1619
  } else {
1620
-
1621
- # google fonts download and inlining, ignore logs
1622
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1623
- $newcode = false; $newcode = fvm_get_transient($tkey);
1624
- if ( $newcode === false) {
1625
- $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
1626
- if(is_array($res)) { $newcode = $res['code']; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1627
  }
1628
-
1629
- # inline css or fail
1630
- if($newcode !== false) {
1631
- echo '<style type="text/css" media="all">'.$newcode.'</style>';
1632
- } else {
1633
- echo "<!-- GOOGLE FONTS REQUEST FAILED for $concat_google_fonts -->\n"; # log if failed
1634
- }
1635
  }
1636
  }
1637
 
@@ -1743,26 +2008,33 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1743
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1744
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1745
 
1746
- # get css from hurl, if available and valid
1747
- $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1748
- $newcode = false; $newcode = fvm_get_transient($tkey);
1749
- if ( $newcode === false) {
1750
- $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
1751
- if(is_array($res)) {
1752
- $newcode = $res['code'];
1753
- $newlog = $res['log'];
1754
- }
1755
- } else {
1756
- $newlog = "$printurl --- Debug: Fetched from transients cache with key $tkey ---\n";
1757
  }
1758
-
1759
- # append
1760
- if($newcode !== false) {
1761
- $code.= $newcode;
1762
- if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) { $code.= $inline_css[$handle]; } # add inline css on the fly
1763
- $log.= $newlog;
1764
- }
1765
-
 
 
 
 
 
 
 
 
 
 
 
1766
  # consider dependencies on handles with an empty src
1767
  } else {
1768
  wp_dequeue_script($handle);
@@ -1771,7 +2043,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1771
  endforeach;
1772
 
1773
  # prepare log
1774
- $log = "PROCESSED on ".date('r')."\n".$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL ))."\n";
1775
 
1776
  # generate cache, add inline css, write log
1777
  file_put_contents($file.'.txt', $log);
@@ -1781,23 +2053,23 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1781
  }
1782
 
1783
  # register and enqueue minified file, consider excluding of mediatype "print" and inline css
1784
- if ($remove_print_mediatypes != 1 || ($remove_print_mediatypes == 1 && $footer[$i]['media'] != 'print')) {
1785
- if($force_inline_css_footer != false) {
1786
- echo '<style type="text/css" media="'.$footer[$i]['media'].'">'.file_get_contents($file).'</style>';
 
 
 
 
 
 
 
 
 
1787
  } else {
1788
-
1789
- # footer css
1790
- if($loadcss != false) {
1791
- if($fvm_remove_css != true) {
1792
- echo '<link rel="stylesheet" type="text/css" media="'.$footer[$i]['media'].'" href="'.$file_url.'">';
1793
- }
1794
- } else {
1795
- # enqueue file, if not empty
1796
- $check = ''; $check = trim(file_get_contents($file));
1797
- if(file_exists($file) && !empty($check)) {
1798
- wp_register_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
1799
- wp_enqueue_style("fvm-footer-$i");
1800
- }
1801
  }
1802
  }
1803
  }
@@ -1821,51 +2093,69 @@ $wp_styles->done = $done;
1821
  # dev: https://www.filamentgroup.com/lab/async-css.html
1822
  ###########################################
1823
  function fvm_add_loadcss() {
1824
- global $force_inline_css, $loadcss, $fvm_remove_css;
1825
- if($force_inline_css == true && $loadcss != false && $fvm_remove_css != true) {
1826
-
1827
- # echo LoadCSS scripts
1828
- echo '<script>
1829
- /*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
1830
- !function(n){"use strict";n.loadCSS||(n.loadCSS=function(){});var o=loadCSS.relpreload={};if(o.support=function(){var e;try{e=n.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),o.bindMediaToggle=function(t){var e=t.media||"all";function a(){t.media=e}t.addEventListener?t.addEventListener("load",a):t.attachEvent&&t.attachEvent("onload",a),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(a,3e3)},o.poly=function(){if(!o.support())for(var t=n.document.getElementsByTagName("link"),e=0;e<t.length;e++){var a=t[e];"preload"!==a.rel||"style"!==a.getAttribute("as")||a.getAttribute("data-loadcss")||(a.setAttribute("data-loadcss",!0),o.bindMediaToggle(a))}},!o.support()){o.poly();var t=n.setInterval(o.poly,500);n.addEventListener?n.addEventListener("load",function(){o.poly(),n.clearInterval(t)}):n.attachEvent&&n.attachEvent("onload",function(){o.poly(),n.clearInterval(t)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:n.loadCSS=loadCSS}("undefined"!=typeof global?global:this);
1831
- </script>';
1832
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1833
  }
1834
 
1835
 
1836
 
1837
 
 
1838
  ###########################################
1839
  # add preconnect and preload headers
1840
  ###########################################
1841
- function fvm_buffer_placeholder_top() {
1842
- global $preload, $preconnect;
1843
-
1844
- # defaults
1845
- $meta = array();
1846
-
1847
- # preconnect resources
1848
- # https://css-tricks.com/prefetching-preloading-prebrowsing/
1849
- if(count($preconnect) > 0) {
1850
- $a = array(); foreach ($preconnect as $b) {
1851
- if(!empty($b)) { $a[] = '<link href="'.str_ireplace(array('http://', 'https://'), '//', $b).'" rel="preconnect">'; }
 
 
1852
  }
1853
- if(count($a) > 0) { $meta[] = implode('', $a); }
1854
  }
1855
 
1856
- # preload resources (beta: homepage only)
1857
- # https://css-tricks.com/prefetching-preloading-prebrowsing/
1858
- if((is_home() || is_front_page()) && count($preload) > 0) {
1859
- $a = array();
1860
- foreach ($preload as $b) {
1861
- if(!empty($b)) {
1862
- $meta[] = '<link rel="preload" as="image" href="'.str_ireplace(array('http://', 'https://'), '//', $b).'">';
1863
- }
1864
  }
1865
  }
1866
 
1867
- # output on top
1868
- echo implode('', $meta);
1869
  }
1870
 
1871
 
@@ -1873,39 +2163,30 @@ echo implode('', $meta);
1873
  ###########################################
1874
  # optimize the ignore list for pagespeed insights
1875
  ###########################################
1876
- function fastvelocity_min_defer_js_optimize($tag, $handle, $src) {
1877
- global $defer_for_pagespeed, $defer_for_pagespeed_optimize, $fvm_fix_editor;
1878
 
1879
  # return if there are linebreaks (will break document.write)
1880
- if (stripos($tag, "\n") !== false) { return $tag; }
1881
 
1882
  # fix page editors
1883
  if($fvm_fix_editor == true && is_user_logged_in()) { return $tag; }
1884
 
1885
- # return if external script url https://www.chromestatus.com/feature/5718547946799104
1886
- if (fvm_is_local_domain($src) !== true) { return $tag; }
1887
-
1888
- # exclude ignored scripts
1889
- if(substr($handle, 0, 4) != "fvm-" && $defer_for_pagespeed == true && $defer_for_pagespeed_optimize == true) {
1890
-
1891
- # get available nodes and add create with defer tag (if not async)
1892
- $dom = new DOMDocument();
1893
- libxml_use_internal_errors(true);
1894
- @$dom->loadHTML($tag);
1895
- $nodes = $dom->getElementsByTagName('script');
1896
- $tagdefer = '';
1897
- if ($nodes->length != 0) {
1898
- $node = $dom->getElementsByTagName('script')->item(0);
1899
- if (!$node->hasAttribute('async')) { $node->setAttribute('defer','defer'); };
1900
- $tagdefer = $dom->saveHTML($node);
1901
- }
1902
 
1903
- # print code if there are no linebreaks, or return
1904
- if(!empty($tagdefer)) {
1905
- $deferinsights = '<script type="text/javascript">if(!navigator.userAgent.match(/speed|Lighthouse|gtmetrix|Linux.*Moto\sG|x11.*firefox\/54|x11.*chrome\/39/i)){document.write('.json_encode($tag).');}</script>';
1906
- return preg_replace('#<script(.*?)>(.*?)</script>#is', $deferinsights, $tag);
 
 
 
 
 
1907
  }
1908
-
1909
  }
1910
 
1911
  # fallback
@@ -1914,3 +2195,230 @@ return $tag;
1914
 
1915
 
1916
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  Plugin Name: Fast Velocity Minify
4
  Plugin URI: http://fastvelocity.com
5
  Description: Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS and JavaScript files into groups, compressing HTML and other speed optimizations.
6
+ Author: fvm Peixoto
7
  Author URI: http://fastvelocity.com
8
+ Version: 2.4.0
9
  License: GPL2
10
 
11
  ------------------------------------------------------------------------
60
  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
68
 
69
  # reusable functions
70
  include($plugindir.'inc/functions.php');
71
  include($plugindir.'inc/functions-serverinfo.php');
72
+ include($plugindir.'inc/functions-upgrade.php');
73
 
74
  # wp-cli support
75
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
95
 
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
  ###########################################
102
  # build control panel pages ###############
103
  ###########################################
104
 
105
  # options from the database, false if not set
106
+ $ignore = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_ignore', '')));
107
+ $blacklist = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_blacklist', '')));
108
+ $ignorelist = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_ignorelist', '')));
109
+ $fvm_min_excludecsslist = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_excludecsslist', '')));
110
+ $fvm_min_excludejslist = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_excludejslist', '')));
111
  $fvm_enable_purgemenu = get_option('fastvelocity_min_enable_purgemenu');
112
  $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
113
  $disable_js_merge = get_option('fastvelocity_min_disable_js_merge');
114
  $disable_css_merge = get_option('fastvelocity_min_disable_css_merge');
115
  $disable_js_minification = get_option('fastvelocity_min_disable_js_minification');
116
  $disable_css_minification = get_option('fastvelocity_min_disable_css_minification');
 
117
  $remove_print_mediatypes = get_option('fastvelocity_min_remove_print_mediatypes');
118
  $skip_html_minification = get_option('fastvelocity_min_skip_html_minification');
119
  $strip_htmlcomments = get_option('fastvelocity_min_strip_htmlcomments');
120
  $skip_cssorder = get_option('fastvelocity_min_skip_cssorder');
121
  $skip_google_fonts = get_option('fastvelocity_min_skip_google_fonts');
122
  $skip_emoji_removal = get_option('fastvelocity_min_skip_emoji_removal');
123
+ $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');
130
  $exclude_defer_login = get_option('fastvelocity_min_exclude_defer_login');
 
 
131
  $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();
138
+ $force_inline_googlefonts = true;
139
+ $min_async_googlefonts = false;
140
+ $css_hide_googlefonts = false;
141
+
142
+
143
+ # define google fonts options based on a radio form
144
+ $fvm_gfonts_method = get_option("fastvelocity_gfonts_method");
145
+ if($fvm_gfonts_method != false) {
146
+ if($fvm_gfonts_method == 2) { # load Async
147
+ $force_inline_googlefonts = false;
148
+ $min_async_googlefonts = true;
149
+ $css_hide_googlefonts = false;
150
+ }
151
+ if($fvm_gfonts_method == 3) { # hide from PSI
152
+ $force_inline_googlefonts = false;
153
+ $min_async_googlefonts = false;
154
+ $css_hide_googlefonts = true;
155
+ }
156
+ }
157
 
 
 
 
 
 
 
 
158
 
159
+ # default ua list
160
+ $fvmualist = array('nux.*oto\sG', 'x11.*fox\/54', 'x11.*ome\/39', 'x11.*ome\/62', 'oid\s6.*1.*xus\s5.*MRA58N.*ome', 'JWR66Y.*ome\/62', 'woobot', 'wget', 'speed', 'ighth', 'tmetr');
161
 
162
 
163
  # add admin page and rewrite defaults
166
  add_action('admin_enqueue_scripts', 'fastvelocity_min_load_admin_jscss');
167
  add_action('wp_ajax_fastvelocity_min_files', 'fastvelocity_min_files_callback');
168
  add_action('admin_init', 'fastvelocity_min_register_settings');
169
+
170
+ # This function runs when WordPress updates or installs/remove something
171
+ add_action('upgrader_process_complete', 'fvm_purge_all');
172
+ add_action('after_switch_theme', 'fvm_purge_all');
173
+ add_action('activated_plugin', 'fvm_purge_all');
174
+ add_action('deactivated_plugin', 'fvm_purge_all');
175
+
176
+ # activation, deactivation
177
+ register_activation_hook( __FILE__, 'fastvelocity_plugin_activate' );
178
+ register_deactivation_hook( __FILE__, 'fastvelocity_plugin_deactivate');
179
+
180
  } else {
181
 
182
  # skip on certain post_types or if there are specific keys on the url or if editor or admin
183
+ if(!fastvelocity_exclude_contents()) {
184
 
185
  # actions for frontend only
186
  if(!$disable_js_merge) {
187
  add_action( 'wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
188
  add_action( 'wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
189
  }
190
+ if(!$disable_css_merge) {
191
+ add_action('wp_head', 'fvm_add_criticial_path', 2);
192
+
193
+ # merge, if inline is not selected
194
+ if($force_inline_css != true) {
195
+ add_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
196
+ add_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
197
+ } else {
198
+ add_filter('style_loader_tag', 'fastvelocity_optimizecss', PHP_INT_MAX, 4 );
199
+ add_action('wp_print_styles','fastvelocity_add_google_fonts_merged', PHP_INT_MAX);
200
+ add_action('wp_print_footer_scripts','fastvelocity_add_google_fonts_merged', PHP_INT_MAX );
201
+ }
202
+
203
  }
204
  if(!$skip_emoji_removal) {
205
  add_action( 'init', 'fastvelocity_min_disable_wp_emojicons' );
206
+ add_filter( 'tiny_mce_plugins', 'fastvelocity_disable_emojis_tinymce' );
207
+ }
208
+
209
+ if($fvm_clean_header_one) {
210
+ # no resource hints, generator tag, shortlinks, manifest link, etc
211
+ remove_action('wp_head', 'wp_resource_hints', 2 );
212
+ remove_action('wp_head', 'wp_generator');
213
+ remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0);
214
+ remove_action('wp_head', 'wlwmanifest_link');
215
+ remove_action('wp_head', 'rsd_link');
216
+ remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);
217
+ remove_action('wp_head','feed_links', 2);
218
+ remove_action('wp_head','feed_links_extra', 3);
219
  }
220
 
221
  # enable html minification
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
  }
244
  if($fvm_fix_editor == true && is_user_logged_in()) {
245
  remove_action('wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
246
  remove_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
 
247
  remove_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
248
  remove_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
249
  remove_action('init', 'fastvelocity_min_disable_wp_emojicons');
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
 
 
 
 
 
 
 
 
257
  # create admin menu
258
  function fastvelocity_min_admin_menu() {
259
  add_options_page('Fast Velocity Minify Settings', 'Fast Velocity Minify', 'manage_options', 'fastvelocity-min', 'fastvelocity_min_settings');
330
 
331
  # register plugin settings
332
  function fastvelocity_min_register_settings() {
333
+ register_setting('fvm-group', 'fastvelocity_min_enable_purgemenu');
334
+ register_setting('fvm-group', 'fastvelocity_min_preserve_oldcache');
335
  register_setting('fvm-group', 'fastvelocity_min_default_protocol');
336
  register_setting('fvm-group', 'fastvelocity_min_disable_js_merge');
337
  register_setting('fvm-group', 'fastvelocity_min_disable_css_merge');
338
  register_setting('fvm-group', 'fastvelocity_min_disable_js_minification');
339
  register_setting('fvm-group', 'fastvelocity_min_disable_css_minification');
 
340
  register_setting('fvm-group', 'fastvelocity_min_remove_print_mediatypes');
341
  register_setting('fvm-group', 'fastvelocity_min_skip_html_minification');
342
  register_setting('fvm-group', 'fastvelocity_min_strip_htmlcomments');
344
  register_setting('fvm-group', 'fastvelocity_min_skip_google_fonts');
345
  register_setting('fvm-group', 'fastvelocity_min_skip_fontawesome_fonts');
346
  register_setting('fvm-group', 'fastvelocity_min_skip_emoji_removal');
347
+ register_setting('fvm-group', 'fastvelocity_fvm_clean_header_one');
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');
 
 
356
  register_setting('fvm-group', 'fastvelocity_min_fvm_fix_editor');
357
  register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_url');
358
  register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_force');
359
+ register_setting('fvm-group', 'fastvelocity_min_change_cache_base_url');
360
+ register_setting('fvm-group', 'fastvelocity_min_change_cache_path');
361
 
362
+ # pro tab
363
+ register_setting('fvm-group-pro', 'fastvelocity_min_ignore');
 
 
364
  register_setting('fvm-group-pro', 'fastvelocity_min_ignorelist');
365
+ register_setting('fvm-group-pro', 'fastvelocity_min_excludecsslist');
366
+ register_setting('fvm-group-pro', 'fastvelocity_min_excludejslist');
367
  register_setting('fvm-group-pro', 'fastvelocity_min_blacklist');
368
  register_setting('fvm-group-pro', 'fastvelocity_min_merge_allowed_urls');
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');
375
+ register_setting('fvm-group-dev', 'fastvelocity_min_fvm_removecss');
376
+ register_setting('fvm-group-dev', 'fastvelocity_min_critical_path_css');
377
+ register_setting('fvm-group-dev', 'fastvelocity_min_critical_path_css_is_front_page');
378
+
379
+
380
+
381
  }
382
 
383
 
385
  # add settings link on plugin page
386
  function fastvelocity_min_settings_link($links) {
387
  if (is_plugin_active(plugin_basename( __FILE__ ))) {
388
+ $settings_link = '<a href="options-general.php?page=fastvelocity-min&tab=set">Settings</a>';
389
  array_unshift($links, $settings_link);
390
  }
391
  return $links;
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>
427
  <a href="?page=fastvelocity-min&tab=pro" class="nav-tab <?php echo $active_tab == 'pro' ? 'nav-tab-active' : ''; ?>">Pro</a>
428
+ <a href="?page=fastvelocity-min&tab=dev" class="nav-tab <?php echo $active_tab == 'dev' ? 'nav-tab-active' : ''; ?>">Developers</a>
429
  <a href="?page=fastvelocity-min&tab=server" class="nav-tab <?php echo $active_tab == 'server' ? 'nav-tab-active' : ''; ?>">Server Info</a>
430
  <a href="?page=fastvelocity-min&tab=help" class="nav-tab <?php echo $active_tab == 'help' ? 'nav-tab-active' : ''; ?>">Help</a>
431
  </h2>
443
  <div class="inside" id="fastvelocity_min_topbtns">
444
  <ul class="processed">
445
  <li id="purgeall-row">
446
+ <span class="filename">Purge FVM cache (<span id="fvm_cache_size"><?php echo fastvelocity_get_cachestats(); ?></span>)</span>
447
  <span class="actions">
448
  <form method="post" id="fastvelocity_min_clearall" action="<?php echo admin_url('options-general.php?page=fastvelocity-min&tab=status'); ?>">
449
  <input type="hidden" name="purgeall" value="1" />
464
  <div class="postbox" id="tab-css">
465
  <h3 class="hndle"><span>List of processed CSS files</span></h3>
466
  <div class="inside" id="fastvelocity_min_cssprocessed">
467
+ <?php
468
+ $force_inline_css = get_option('fastvelocity_min_force_inline_css');
469
+ if($force_inline_css != false) {
470
+ echo '<p>There are no merged CSS files listed here, because you are inlining all CSS directly.</p>';
471
+ } else {
472
+ echo '<ul class="processed"></ul>';
473
+ }
474
+ ?>
475
+
476
  </div>
477
  </div>
478
 
482
  </div>
483
  <?php } ?>
484
 
485
+ <?php if( $active_tab == 'set' ) { ?>
486
  <form method="post" action="options.php">
487
  <?php settings_fields('fvm-group'); do_settings_sections('fvm-group'); ?>
488
 
489
 
490
  <div style="height: 20px;"></div>
491
+ <h2 class="title">Basic Settings</h2>
492
  <p class="fvm-bold-green">These options are generaly safe to edit as needed. If you use a cache plugin, kindly purge all your caches once you're done with the changes.</p>
493
 
494
  <table class="form-table fvm-settings">
495
  <tbody>
496
 
497
+
498
  <tr>
499
+ <th scope="row">Functionality</th>
500
  <td>
501
+ <p class="fvm-bold-green fvm-rowintro">The HTML minification is ON by default, but you can:</p>
502
+
503
  <fieldset>
504
  <label for="fastvelocity_min_enable_purgemenu">
505
  <input name="fastvelocity_min_enable_purgemenu" type="checkbox" id="fastvelocity_min_enable_purgemenu" value="1" <?php echo checked(1 == get_option('fastvelocity_min_enable_purgemenu'), true, false); ?>>
506
+ Admin Bar Purge <span class="note-info">[ If selected, a new option to purge FVM cache from the admin bar will show up ]</span></label>
507
+ <br />
508
+
509
+ <label for="fastvelocity_min_preserve_oldcache">
510
+ <input name="fastvelocity_min_preserve_oldcache" type="checkbox" id="fastvelocity_min_preserve_oldcache" value="1" <?php echo checked(1 == get_option('fastvelocity_min_preserve_oldcache'), true, false); ?>>
511
+ Preserve Cache Files <span class="note-info">[ This will reload your cache files when you purge, but preserve the old files ]</span></label>
512
+ <br />
513
 
 
 
 
 
 
514
  <label for="fastvelocity_min_fvm_fix_editor">
515
  <input name="fastvelocity_min_fvm_fix_editor" type="checkbox" id="fastvelocity_min_fvm_fix_editor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_fvm_fix_editor'), true, false); ?>>
516
+ Fix Page Editors <span class="note-info">[ Will disable merging of JS and CSS for logged in users, to improve compatibility with visual editors ]</span></label>
517
+ <br />
518
+
519
  </fieldset></td>
520
  </tr>
521
 
532
  ?>
533
  <p class="fvm-bold-green fvm-rowintro">You may need to force http or https, for some CDN plugins to work:</p>
534
  <fieldset>
535
+ <label><input type="radio" name="fastvelocity_min_default_protocol" value="dynamic" <?php echo $a; ?>> Auto Detect </label><br>
536
+ <label><input type="radio" name="fastvelocity_min_default_protocol" value="http"<?php echo $b; ?>> Force HTTP urls (if you don't have SSL)</label><br>
537
+ <label><input type="radio" name="fastvelocity_min_default_protocol" value="https"<?php echo $c; ?>> Force HTTPS urls (recommended if you have SSL)</span></label><br>
538
  </fieldset>
539
  </td>
540
  </tr>
555
  Strip HTML comments <span class="note-info">[ Only works with the default HTML minification, but note that some plugins need HTML comments to work properly ]</span></label>
556
  <br />
557
 
558
+ <label for="fastvelocity_fvm_clean_header_one">
559
+ <input name="fastvelocity_fvm_clean_header_one" type="checkbox" id="fastvelocity_fvm_clean_header_one" value="1" <?php echo checked(1 == get_option('fastvelocity_fvm_clean_header_one'), true, false); ?>>
560
+ Cleanup Header <span class="note-info">[ Remove resource hints, generator tag, shortlinks, manifest link, etc ]</span></label>
561
+ <br />
562
+
563
  </fieldset></td>
564
  </tr>
565
 
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>
572
  <label for="fastvelocity_min_skip_emoji_removal">
573
  <input name="fastvelocity_min_skip_emoji_removal" type="checkbox" id="fastvelocity_min_skip_emoji_removal" class="jsprocessor" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_emoji_removal'), true, false); ?> >
579
  Disable Google Fonts merging <span class="note-info">[ If selected, Google Fonts will no longer be merged into one request ]</span></label>
580
  <br />
581
 
 
 
 
 
 
582
  <label for="fastvelocity_min_remove_googlefonts">
583
  <input name="fastvelocity_min_remove_googlefonts" type="checkbox" id="fastvelocity_min_remove_googlefonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_remove_googlefonts'), true, false); ?> >
584
+ Remove Google Fonts completely <span class="note-info">[ If selected, all enqueued Google Fonts will be removed from the site ]</span></label>
585
  <br />
586
 
587
  </fieldset></td>
588
  </tr>
589
 
590
 
591
+ <tr>
592
+ <th scope="row">Google Fonts</th>
593
+ <td>
594
+ <?php
595
+ # what to select
596
+ $sel = get_option('fastvelocity_gfonts_method');
597
+ $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>
623
  <br />
624
  <label for="fastvelocity_min_skip_cssorder">
625
  <input name="fastvelocity_min_skip_cssorder" type="checkbox" id="fastvelocity_min_skip_cssorder" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_cssorder'), true, false); ?> >
626
+ Preserve the order of CSS files <span class="note-info">[ If selected, you will have better CSS compatibility when merging but possibly more CSS files ]</span></label>
627
  <br />
628
  <label for="fastvelocity_min_remove_print_mediatypes">
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); ?> >
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>
647
  Disable JavaScript processing <span class="note-info">[ If selected, this plugin will ignore JS files completely ]</span></label>
648
  <br />
649
 
 
 
 
 
 
 
 
 
 
 
650
  <label for="fastvelocity_min_disable_js_minification">
651
  <input name="fastvelocity_min_disable_js_minification" type="checkbox" id="fastvelocity_min_disable_js_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_minification'), true, false); ?> >
652
  Disable minification on JS files <span class="note-info">[ If selected, JS files will be merged but not minified ]</span></label>
653
  <br />
654
  </fieldset></td>
655
  </tr>
 
 
 
 
 
 
656
 
 
 
657
  <tr>
658
  <th scope="row">Render-blocking JS</th>
659
  <td>
664
  <input name="fastvelocity_min_enable_defer_js" type="checkbox" id="fastvelocity_min_enable_defer_js" value="1" <?php echo checked(1 == get_option('fastvelocity_min_enable_defer_js'), true, false); ?>>
665
  Enable defer parsing of JS files globally <span class="note-info">[ Not all browsers, themes or plugins support this. Beware of broken functionality and design ]</span></label>
666
  <br />
 
 
 
 
 
 
 
 
 
667
 
668
  <label for="fastvelocity_min_exclude_defer_jquery">
669
  <input name="fastvelocity_min_exclude_defer_jquery" type="checkbox" id="fastvelocity_min_exclude_defer_jquery" value="1" <?php echo checked(1 == get_option('fastvelocity_min_exclude_defer_jquery'), true, false); ?> >
670
+ Skip deferring the jQuery library <span class="note-info">[ Will probably fix "undefined jQuery" errors on the Google Chrome console log ]</span></label>
671
  <br />
672
  <label for="fastvelocity_min_exclude_defer_login">
673
  <input name="fastvelocity_min_exclude_defer_login" type="checkbox" id="fastvelocity_min_exclude_defer_login" value="1" <?php echo checked(1 == get_option('fastvelocity_min_exclude_defer_login'), true, false); ?> >
677
 
678
  </fieldset></td>
679
  </tr>
 
 
680
 
681
+ <tr>
682
+ <th scope="row">PageSpeed Settings</th>
683
+ <td>
684
+ <p class="fvm-bold-green fvm-rowintro">Note that this will overwrite any other behaviour defined above and "may" cause errors.</p>
685
+ <fieldset>
686
+ <label for="fastvelocity_min_defer_for_pagespeed">
687
+ <input name="fastvelocity_min_defer_for_pagespeed" type="checkbox" id="fastvelocity_min_defer_for_pagespeed" value="1" <?php echo checked(1 == get_option('fastvelocity_min_defer_for_pagespeed'), true, false); ?>>
688
+ Enable defer of JS for PSI <span class="note-info">[ Will use JavaScript to defer the files conditionally ]</span></label>
689
 
690
+ <br />
691
+ <label for="fastvelocity_min_defer_for_pagespeed_optimize">
692
+ <input name="fastvelocity_min_defer_for_pagespeed_optimize" type="checkbox" id="fastvelocity_min_defer_for_pagespeed_optimize" value="1" <?php echo checked(1 == get_option('fastvelocity_min_defer_for_pagespeed_optimize'), true, false); ?>>
693
+ Exclude JS files in the "ignore list" from PSI <span class="note-info">[ This only works with "Enable defer of JS for PSI" enabled ]</span></label>
694
 
 
 
 
 
 
 
 
 
 
 
695
  </fieldset></td>
696
  </tr>
697
+
698
+
699
+
700
+
701
  </tbody></table>
702
 
703
 
726
  </tr>
727
  </tbody></table>
728
 
729
+ <div style="height: 20px;"></div>
730
+ <h2 class="title">Cache Location</h2>
731
+ <p class="fvm-bold-green">If your server blocks JavaScript on the uploads directory, you can change "wp-content/uploads" with "wp-content/cache" or other allowed public directory.</p>
732
+ <table class="form-table fvm-settings">
733
+ <tbody>
734
+ <tr>
735
+ <th scope="row"><span class="fvm-label-special">Cache Path</span></th>
736
+ <td><fieldset>
737
+ <label for="fastvelocity_min_change_cache_path">
738
+ <p><input type="text" name="fastvelocity_min_change_cache_path" id="fastvelocity_min_change_cache_path" value="<?php echo get_option('fastvelocity_min_change_cache_path', ''); ?>" size="80" /></p>
739
+ <p class="description">[ Default cache path is: <?php echo rtrim(wp_upload_dir()['basedir'], '/'); ?> ]</p>
740
+ </label>
741
+ </fieldset></td>
742
+ </tr>
743
+ <tr>
744
+ <th scope="row"><span class="fvm-label-special">Cache Base URL</span></th>
745
+ <td><fieldset>
746
+ <label for="fastvelocity_min_change_cache_base_url">
747
+ <p><input type="text" name="fastvelocity_min_change_cache_base_url" id="fastvelocity_min_change_cache_base_url" value="<?php echo get_option('fastvelocity_min_change_cache_base_url', ''); ?>" size="80" /></p>
748
+ <p class="description">[ Default cache base url is: <?php echo rtrim(fvm_get_protocol(wp_upload_dir()['baseurl']), '/'); ?> ]</p>
749
+ </label>
750
+ </fieldset></td>
751
+ </tr>
752
+ </tbody></table>
753
+
754
+
755
+ <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
756
+ </form>
757
+ <?php } ?>
758
+
759
+
760
+ <?php if( $active_tab == 'pro' ) { ?>
761
+
762
+ <form method="post" action="options.php">
763
+ <?php settings_fields('fvm-group-pro'); do_settings_sections('fvm-group-pro'); ?>
764
+
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">
772
  <tbody>
773
  <tr>
774
+ <th scope="row">Ignore List</th>
775
+ <td><fieldset>
776
+ <label for="blacklist_keys"><span class="fvm-label-pad">Ignore the following CSS and JS paths below:</span></label>
777
  <p>
778
+ <textarea name="fastvelocity_min_ignore" rows="7" cols="50" id="fastvelocity_min_ignore" class="large-text code" placeholder="ex: /wp-includes/js/jquery/jquery.js"><?php echo get_option('fastvelocity_min_ignore'); ?></textarea>
779
  </p>
780
+ <p class="description">[ Your own list of js /css files to ignore with wildcard support (read the faqs) ]</p>
781
  </fieldset></td>
782
  </tr>
 
783
  </tbody></table>
784
 
785
 
786
  <div style="height: 20px;"></div>
 
 
 
787
  <table class="form-table fvm-settings">
788
  <tbody>
789
  <tr>
790
+ <th scope="row">External URLs to Merge</th>
791
+ <td><fieldset><label for="blacklist_keys"><span class="fvm-label-pad">List of external domains that can be fetched and merged together:</span></label>
 
792
  <p>
793
+ <textarea name="fastvelocity_min_merge_allowed_urls" rows="7" cols="50" id="fastvelocity_min_merge_allowed_urls" class="large-text code" placeholder="ex: example.com"><?php echo get_option('fastvelocity_min_merge_allowed_urls'); ?></textarea>
794
  </p>
795
+ <p class="description">[ Add any external "domains" for JS or CSS files than can be merged fetched and merged together by FVM, ie: example.com ]</p>
796
  </fieldset></td>
797
  </tr>
798
  </tbody></table>
799
 
800
 
801
+ <div style="height: 20px;"></div>
802
+ <table class="form-table fvm-settings">
803
+ <tbody>
804
+ <tr>
805
+ <th scope="row">Exclude JS files from PSI</th>
806
+ <td><fieldset><label for="fastvelocity_min_excludejslist"><span class="fvm-label-pad">Files will be loaded Async and excluded from PSI:</span></label>
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>
814
+ </tbody></table>
815
 
 
816
 
817
+ <div style="height: 20px;"></div>
818
+ <table class="form-table fvm-settings">
819
+ <tbody>
820
+ <tr>
821
+ <th scope="row">Exclude CSS files from PSI</th>
822
+ <td><fieldset><label for="fastvelocity_min_excludecsslist"><span class="fvm-label-pad">Files will be loaded Async and excluded from PSI:</span></label>
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>
831
+ </tbody></table>
832
 
833
 
 
 
 
834
 
835
 
836
+ <div style="height: 20px;"></div>
837
  <table class="form-table fvm-settings">
838
  <tbody>
 
 
839
  <tr>
840
+ <th scope="row">Default Ignore List</th>
841
  <td>
842
+ <fieldset><label for="blacklist_keys"><span class="fvm-label-pad">Do not edit, if you're not sure what this is:</span></label>
 
843
  <p>
844
+ <textarea name="fastvelocity_min_ignorelist" rows="7" cols="50" id="fastvelocity_min_ignorelist" class="large-text code" placeholder="ex: /wp-includes/js/jquery/jquery.js"><?php echo get_option('fastvelocity_min_ignorelist'); ?></textarea>
845
  </p>
846
+ <p class="description">[ Files that have been consistently reported by other users to cause trouble when merged ]</p>
847
+ </fieldset></td>
 
848
  </tr>
849
+ </tbody></table>
850
 
851
+ <div style="height: 20px;"></div>
852
+ <table class="form-table fvm-settings">
853
+ <tbody>
854
  <tr>
855
+ <th scope="row">Default Blacklist</th>
856
+ <td><fieldset><label for="blacklist_keys"><span class="fvm-label-pad">Do not edit, if you're not sure what this is:</span></label>
857
+ <p>
858
+ <textarea name="fastvelocity_min_blacklist" rows="7" cols="50" id="fastvelocity_min_blacklist" class="large-text code" placeholder="ex: /wp-includes/js/jquery/jquery.js"><?php echo get_option('fastvelocity_min_blacklist'); ?></textarea>
859
+ </p>
860
+ <p class="description">[ Usually, any IE css /js files that should always be ignored without incrementing the groups ]</p>
861
+ </fieldset></td>
862
  </tr>
863
  </tbody></table>
864
 
865
 
866
+ <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
867
+ </form>
868
+
869
+ <?php
870
+ }
871
+
872
+ # start developers tab
873
+ if( $active_tab == 'dev' ) { ?>
874
+
875
+ <form method="post" action="options.php">
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>
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>
902
+ <p class="fvm-bold-green">Preload Headers: Use this for preloading specific, high priority resources that exist across all of your pages.</p>
903
+ <p class="fvm-bold-green">Note: Some servers do not support http push or headers. If you get a server error: a) rename the plugin directory via SFTP or your hosting control panel, b) go to your plugins page (plugin will be disabled on access), c) rename it back and d) activate it back (reset to default settings).</p>
904
 
 
905
  <table class="form-table fvm-settings">
906
  <tbody>
907
  <tr>
908
+ <th scope="row">Preconnect Headers</th>
909
+ <td><fieldset><legend class="screen-reader-text"><span>Preconnect</span></legend>
910
+ <label for="fastvelocity_min_hpreconnect"><span class="fvm-label-pad">Use only the strictly minimum necessary domain names, (cdn or frequent embeds):</span></label>
911
  <p>
912
+ <textarea name="fastvelocity_min_hpreconnect" rows="7" cols="50" id="fastvelocity_min_hpreconnect" class="large-text code" placeholder="https://cdn.example.com"><?php echo get_option('fastvelocity_min_hpreconnect'); ?></textarea>
913
  </p>
914
+ <p class="description">[ Use the complete scheme (http:// or https://) followed by the domain name only (no file paths). ]</p>
915
+ <p class="description">[ Examples: ]</p>
916
+ <p class="description">https://fonts.googleapis.com</p>
917
+ <p class="description">https://fonts.gstatic.com</p>
918
  </fieldset></td>
919
  </tr>
920
+
921
  </tbody></table>
922
 
 
923
  <table class="form-table fvm-settings">
924
  <tbody>
925
  <tr>
926
+ <th scope="row">Preload Headers</th>
927
+ <td><fieldset><legend class="screen-reader-text"><span>Preload Headers</span></legend>
928
+ <label for="fastvelocity_min_hpreload"><span class="fvm-label-pad">Insert your "complete php header code" here:</span></label>
929
  <p>
930
+ <textarea name="fastvelocity_min_hpreload" rows="7" cols="50" id="fastvelocity_min_hpreload" class="large-text code" placeholder="Link: &lt;https://cdn.example.com/s/font/v15/somefile.woff&gt;; rel=preload; as=font; crossorigin"><?php echo get_option('fastvelocity_min_hpreload'); ?></textarea>
931
  </p>
932
+ <p class="description">[ Example of a "complete php header code" to paste above ]</p>
933
+ <p class="description">Link: &lt;https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVZ0d.woff&gt;; rel=preload; as=font; crossorigin</p>
934
+ <p class="description">Link: &lt;https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/fontawesome-webfont.woff2&gt;; rel=preload; as=font; crossorigin</p>
935
  </fieldset></td>
936
  </tr>
937
  </tbody></table>
938
 
939
+
940
  <div style="height: 20px;"></div>
941
+ <h2 class="title">Async CSS</h2>
942
+ <p class="fvm-bold-green">If you have multiple css files per media type, they may load out of order and break your design.<br />These options won't work, if you select "Disable CSS Processing" on the settings page.</p>
943
+
944
  <table class="form-table fvm-settings">
945
  <tbody>
946
  <tr>
947
+ <th scope="row">Enable Async CSS</th>
948
+ <td><fieldset>
949
+ <label for="fastvelocity_min_loadcss">
950
+ <input name="fastvelocity_min_loadcss" type="checkbox" id="fastvelocity_min_loadcss" value="1" <?php echo checked(1 == get_option('fastvelocity_min_loadcss'), true, false); ?>>
951
+ Async CSS with LoadCSS<span class="note-info">[ Only works if "Inline all header / footer CSS files" is disabled ]</span></label>
952
+
953
+ <br />
954
+ <label for="fastvelocity_min_fvm_removecss">
955
+ <input name="fastvelocity_min_fvm_removecss" type="checkbox" id="fastvelocity_min_fvm_removecss" value="1" <?php echo checked(1 == get_option('fastvelocity_min_fvm_removecss'), true, false); ?>>
956
+ Dequeue all CSS files <span class="note-info">[ Use this if you want to test how your Critical Path CSS looks like ]</span></label>
957
+
958
+ </fieldset>
959
+ </td>
960
  </tr>
961
+
962
  </tbody></table>
963
 
964
 
965
  <div style="height: 20px;"></div>
966
+ <h2 class="title">Critical Path CSS</h2>
967
+ <p class="fvm-bold-green">Files that are inlined, or end up loading later (note: async css files load out of order) will overwritte existing styles, which can cause your design to break.</p>
968
+ <p class="fvm-bold-green">It's probably better to (uncss) remove all unused CSS on your site, select the "Dequeue all CSS files" and paste your code on the "Fallback CSS" section.</p>
969
+ <p class="fvm-bold-green">All code posted here will be inline early in the header, regardless of the "Async CSS with LoadCSS" being active or not (so you can use this to inline your extra css code without other plugins).</p>
970
+
971
  <table class="form-table fvm-settings">
972
  <tbody>
973
+
974
  <tr>
975
+ <th scope="row">Fallback CSS</th>
976
+ <td>
977
+ <fieldset>
978
+ <p>
979
+ <textarea name="fastvelocity_min_critical_path_css" rows="7" cols="50" id="fastvelocity_min_critical_path_css" class="large-text code" placeholder="your css code here"><?php echo get_option('fastvelocity_min_critical_path_css'); ?></textarea>
980
+ </p>
981
+ <p class="description">[ It will be overwritten, if some other more specific critical path code exists below ]</p>
982
+ </fieldset>
983
+ </td>
984
  </tr>
985
+
986
  <tr>
987
+ <th scope="row">is_front_page (conditional)</th>
988
+ <td>
989
+ <fieldset>
990
+ <p>
991
+ <textarea name="fastvelocity_min_critical_path_css_is_front_page" rows="7" cols="50" id="fastvelocity_min_critical_path_css_is_front_page" class="large-text code" placeholder="your css code here"><?php echo get_option('fastvelocity_min_critical_path_css_is_front_page'); ?></textarea>
992
+ </p>
993
+ <p class="description">[ Will show up if your page matches the WP conditional, is_front_page() ]</p>
994
+ </fieldset>
995
+ </td>
996
  </tr>
997
+
998
  </tbody></table>
999
 
1000
 
1001
+
1002
  <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
1003
  </form>
1004
 
1005
  <?php
1006
  }
1007
 
1008
+
1009
+ # start server info tab
1010
  if( $active_tab == 'server' ) {
1011
  fvm_get_generalinfo();
1012
  }
 
1013
 
1014
+
1015
+ # start help tab
1016
+ if( $active_tab == 'help' ) { ?>
1017
 
1018
  <div class="wrap" id="fastvelocity-min">
1019
  <div id="poststuff">
1020
  <div id="fastvelocity_min_processed" class="postbox-container">
1021
  <div class="meta-box-sortables ui-sortable">
1022
+
1023
+ <div class="postbox" id="tab-info">
1024
+ <h3 class="hndle"><span>Paid Clients / Custom Requests</span></h3>
1025
+ <div class="inside">
1026
+ <p>Please Visit: <a href="https://www.upwork.com/fl/fvmpeixoto">https://www.upwork.com/fl/fvmpeixoto</a></p>
1027
+ <p>Alternatively: <a href="https://fastvelocity.com/">https://fastvelocity.com/</a></p>
1028
+ </div>
1029
+ </div>
1030
 
1031
  <div class="postbox" id="tab-info">
1032
  <h3 class="hndle"><span>Frequently Asked Questions</span></h3>
1033
+ <div class="inside">
1034
+ <p>Please Visit: <a href="https://wordpress.org/plugins/fast-velocity-minify/#faq">https://wordpress.org/plugins/fast-velocity-minify/#faq</a></p>
1035
+ </div>
1036
  </div>
1037
+
1038
+ <div class="postbox" id="tab-info">
1039
+ <h3 class="hndle"><span>Open Source Support / Bug Report</span></h3>
1040
+ <div class="inside">
1041
+ <p>Please Visit: <a href="https://wordpress.org/support/plugin/fast-velocity-minify">https://wordpress.org/support/plugin/fast-velocity-minify</a></p>
1042
+ </div>
1043
+ </div>
1044
+
1045
+ <div class="postbox" id="tab-info">
1046
+ <h3 class="hndle"><span>Need faster hosting?</span></h3>
1047
+ <div class="inside">
1048
+ <p>Digital Ocean: (aff) <a href="https://m.do.co/c/039860472caf">https://www.digitalocean.com/</a></p>
1049
+ <p>Vultr: (aff) <a href="https://www.vultr.com/?ref=6879450">https://www.vultr.com/</a></p>
1050
+ <p>Linode: (aff) <a href="https://www.linode.com/?r=4b0ae524a0e54b1c11abb8014be4068f5a5d607a">https://www.linode.com/</a></p>
1051
+ <p>Amazon Lightsail: <a href="https://aws.amazon.com/lightsail/">https://aws.amazon.com/lightsail/</a></p>
1052
+ <p>Google Cloud: <a href="https://cloud.google.com/">https://cloud.google.com/</a></p>
1053
+ </div>
1054
+ </div>
1055
+
1056
+ <div class="postbox" id="tab-info">
1057
+ <h3 class="hndle"><span>Donations (Thank You)</span></h3>
1058
+ <div class="inside">
1059
+ <p>PayPal: <a href="https://goo.gl/vpLrSV">https://goo.gl/vpLrSV</a><br /></p>
1060
+ </div>
1061
+ </div>
1062
+
1063
  </div>
1064
  </div>
1065
  </div>
1066
  </div>
1067
+
1068
  <?php } ?>
1069
 
1070
 
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);
1162
  $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1163
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1164
 
1165
+ # download, minify, cache
1166
+ $tkey = 'js-'.$ctime.'-'.hash('adler32', $handle.$hurl).'.js';
1167
+ $json = false; $json = fvm_get_transient($tkey);
1168
+ if ( $json === false) {
1169
+ $json = fvm_download_and_minify($hurl, null, $disable_js_minification, 'js', $handle);
1170
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
1171
+ fvm_set_transient($tkey, $json);
 
 
 
 
1172
  }
1173
+
1174
+ # decode
1175
+ $res = json_decode($json, true);
1176
+
1177
+ # response has failed
1178
+ if($res['status'] != true) {
1179
+ $log.= $res['log'];
1180
+ continue;
1181
+ }
1182
+
1183
+ # append code to merged file
1184
+ $code.= $res['code'];
1185
+ $log.= $res['log'];
1186
 
1187
  # Add extra data from wp_add_inline_script before
1188
+ if (!empty( $wp_scripts->registered[$handle]->extra)) {
1189
+ if (!empty( $wp_scripts->registered[$handle]->extra['before'])){
1190
+ $code.= PHP_EOL.implode(PHP_EOL, $wp_scripts->registered[$handle]->extra['before']);
1191
  }
1192
  }
1193
 
1194
+
1195
+
1196
+
1197
+
1198
  # consider dependencies on handles with an empty src
1199
  } else {
1200
  wp_dequeue_script($handle); wp_enqueue_script($handle);
1202
  endforeach;
1203
 
1204
  # prepare log
1205
+ $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
1206
 
1207
  # generate cache, write log
1208
  file_put_contents($file.'.txt', $log);
1218
  foreach($header[$i]['handles'] as $handle) {
1219
  if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1220
  }
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));
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);
1313
  $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1314
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1315
 
1316
+
1317
+ # download, minify, cache
1318
+ $tkey = 'js-'.$ctime.'-'.hash('adler32', $handle.$hurl).'.js';
1319
+ $json = false; $json = fvm_get_transient($tkey);
1320
+ if ( $json === false) {
1321
+ $json = fvm_download_and_minify($hurl, null, $disable_js_minification, 'js', $handle);
1322
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
1323
+ fvm_set_transient($tkey, $json);
 
 
 
1324
  }
1325
+
1326
+ # decode
1327
+ $res = json_decode($json, true);
1328
+
1329
+ # response has failed
1330
+ if($res['status'] != true) {
1331
+ $log.= $res['log'];
1332
+ continue;
1333
  }
1334
 
1335
+ # append code to merged file
1336
+ $code.= $res['code'];
1337
+ $log.= $res['log'];
1338
+
1339
  # Add extra data from wp_add_inline_script before
1340
+ if (!empty($wp_scripts->registered[$handle]->extra)){
1341
+ if (!empty($wp_scripts->registered[$handle]->extra['before'])){
1342
+ $code.= PHP_EOL.implode(PHP_EOL, $wp_scripts->registered[$handle]->extra['before']);
1343
  }
1344
  }
1345
 
1351
  endforeach;
1352
 
1353
  # prepare log
1354
+ $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
1355
 
1356
  # generate cache, write log
1357
  file_put_contents($file.'.txt', $log);
1367
  foreach($footer[$i]['handles'] as $handle) {
1368
  if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1369
  }
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));
1392
  # enable defer for JavaScript (WP 4.1 and above) and remove query strings for ignored files
1393
  ###########################################
1394
  function fastvelocity_min_defer_js($tag, $handle, $src) {
1395
+ global $ignore, $blacklist, $ignorelist, $enable_defer_js, $defer_for_pagespeed, $wp_domain, $exclude_defer_login, $fvm_fix_editor, $fvmualist, $fvm_debug;
1396
 
1397
  # no query strings
1398
  $tag = trim($tag); # must cleanup
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)) {
1445
+ $deferinsights = '<script type="text/javascript">if(navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){document.write('.json_encode($tagdefer).');}else{document.write('.json_encode($tag).');}</script>';
1446
  return preg_replace('#<script(.*?)>(.*?)</script>#is', $deferinsights, $tag);
1447
  }
1448
 
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);
1484
  # add defaults to ignore list
1485
  $ignore = fastvelocity_default_ignore($ignore);
1486
 
 
1487
  # get list of handles to process, dequeue duplicate css urls and keep empty source handles (for dependencies)
1488
  $uniq = array(); $gfonts = array();
1489
  foreach( $styles->to_do as $handle):
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);
1502
 
1503
  # mark duplicates as done and remove from the queue
1504
  if(!empty($hurl)) {
1512
  # google fonts to the top (collect and skip process array)
1513
  if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1514
  if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
1515
+ if($skip_google_fonts != true || $force_inline_googlefonts != false) {
1516
+ $google_fonts[$handle] = $hurl;
1517
+
1518
+ } else {
1519
  wp_enqueue_style($handle); # skip google fonts optimization?
1520
  }
1521
  continue;
1528
 
1529
 
1530
  # concat google fonts, if enabled
1531
+ if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts != false && count($google_fonts) > 0)) {
 
1532
  foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1533
+
1534
+ # merge google fonts if force inlining is enabled?
1535
+ $nfonts = array();
1536
+ if($skip_google_fonts != true) {
1537
+ $nfonts[] = fvm_get_protocol(fastvelocity_min_concatenate_google_fonts($google_fonts));
1538
  } else {
1539
+ foreach ($google_fonts as $a) { if(!empty($a)) { $nfonts[] = $a; } }
1540
+ }
1541
+
1542
+ # foreach google font (will be one if merged is not disabled)
1543
+ if(count($nfonts) > 0) {
1544
+ foreach($nfonts as $gfurl) {
1545
+
1546
+ # hide from PSI, async, inline, or default
1547
+ if($css_hide_googlefonts == true) {
1548
+
1549
+ # make a stylesheet, hide from PSI
1550
+ $cssguid = 'fvm'.hash('adler32', $gfurl);
1551
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1552
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$gfurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="all"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1553
+ echo '}</script>';
1554
+
1555
+ # async CSS
1556
+ } elseif ($min_async_googlefonts == true) {
1557
+ echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1558
+ echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
1559
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
1560
+
1561
+ # inline css
1562
+ } elseif($force_inline_googlefonts == true) {
1563
+
1564
+ # download, minify, cache
1565
+ $tkey = 'css-'.$ctime.'-'.hash('adler32', $gfurl).'.css';
1566
+ $json = false; $json = fvm_get_transient($tkey);
1567
+ if ( $json === false) {
1568
+ $json = fvm_download_and_minify($gfurl, null, $disable_css_minification, 'css', null);
1569
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $gfurl -->" . PHP_EOL; }
1570
+ fvm_set_transient($tkey, $json);
1571
+ }
1572
+
1573
+ # decode
1574
+ $res = json_decode($json, true);
1575
+
1576
+ # response has failed
1577
+ if($res['status'] != true) {
1578
+ $log.= $res['log'];
1579
+ continue;
1580
+ }
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";
1587
+ }
1588
+
1589
+ # fallback, enqueue google fonts
1590
+ } else {
1591
+ wp_enqueue_style('header-fvm-fonts', $gfurl, array(), null, 'all');
1592
+ }
1593
+
1594
  }
 
 
 
 
 
 
 
1595
  }
1596
  }
1597
 
1667
  }
1668
  }
1669
 
 
 
 
 
 
 
1670
  # loop through header css and merge
1671
  for($i=0,$l=count($header);$i<$l;$i++) {
1672
  if(!isset($header[$i]['handle'])) {
1700
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1701
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1702
 
1703
+ # download, minify, cache
1704
+ $tkey = 'css-'.$ctime.'-'.hash('adler32', $handle.$hurl).'.css';
1705
+ $json = false; $json = fvm_get_transient($tkey);
1706
+ if ( $json === false) {
1707
+ $json = fvm_download_and_minify($hurl, null, $disable_css_minification, 'css', $handle);
1708
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
1709
+ fvm_set_transient($tkey, $json);
 
 
 
 
1710
  }
1711
+
1712
+ # decode
1713
+ $res = json_decode($json, true);
1714
+
1715
+ # response has failed
1716
+ if($res['status'] != true) {
1717
+ $log.= $res['log'];
1718
+ continue;
1719
+ }
1720
+
1721
+ # append code to merged file
1722
+ $code.= $res['code'];
1723
+ $log.= $res['log'];
1724
+
1725
+ # append inlined styles
1726
+ if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) {
1727
+ $code.= $inline_css[$handle];
1728
+ }
1729
+
1730
  # consider dependencies on handles with an empty src
1731
  } else {
1732
  wp_dequeue_script($handle);
1735
  endforeach;
1736
 
1737
  # prepare log
1738
+ $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
1739
 
1740
  # generate cache, write log
1741
  file_put_contents($file.'.txt', $log);
1745
  }
1746
 
1747
  # register and enqueue minified file, consider excluding of mediatype "print" and inline css
1748
+ if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $header[$i]['media'] != 'print')) {
 
 
 
 
 
 
 
1749
 
1750
+ # the developers tab, takes precedence
1751
+
1752
+ # Async CSS with loadCSS ?
1753
+ if($fvmloadcss != false && $fvm_remove_css != true) {
1754
+ $mt = $header[$i]['media'];
1755
+ echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$mt.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1756
+ echo '<noscript><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /></noscript>';
1757
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /><![endif]-->';
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
  # 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');
1791
  $styles = wp_clone($wp_styles);
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
1820
+ if($skip_google_fonts != true || $force_inline_googlefonts != false) {
1821
+ $google_fonts[$handle] = $hurl;
1822
+ } else {
1823
+ wp_enqueue_style($handle); # skip google fonts optimization?
1824
+ }
1825
  } else {
1826
  wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
1827
  }
1829
 
1830
 
1831
  # concat google fonts, if enabled
1832
+ if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts != false && count($google_fonts) > 0)) {
 
1833
  foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1834
+
1835
+ # merge google fonts if force inlining is enabled?
1836
+ $nfonts = array();
1837
+ if($skip_google_fonts != true) {
1838
+ $nfonts[] = fvm_get_protocol(fastvelocity_min_concatenate_google_fonts($google_fonts));
1839
  } else {
1840
+ foreach ($google_fonts as $a) { if(!empty($a)) { $nfonts[] = $a; } }
1841
+ }
1842
+
1843
+ # foreach google font (will be one if merged is not disabled)
1844
+ if(count($nfonts) > 0) {
1845
+ foreach($nfonts as $gfurl) {
1846
+
1847
+ # hide from PSI, async, inline, or default
1848
+ if($css_hide_googlefonts == true) {
1849
+
1850
+ # make a stylesheet, hide from PSI
1851
+ $cssguid = 'fvm'.hash('adler32', $gfurl);
1852
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1853
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$gfurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="all"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1854
+ echo '}</script>';
1855
+
1856
+ # async CSS
1857
+ } elseif ($min_async_googlefonts == true) {
1858
+ echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1859
+ echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
1860
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
1861
+
1862
+ # inline css
1863
+ } elseif($force_inline_googlefonts == true) {
1864
+
1865
+ # download, minify, cache
1866
+ $tkey = 'css-'.$ctime.'-'.hash('adler32', $gfurl).'.css';
1867
+ $json = false; $json = fvm_get_transient($tkey);
1868
+ if ( $json === false) {
1869
+ $json = fvm_download_and_minify($gfurl, null, $disable_css_minification, 'css', null);
1870
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $gfurl -->" . PHP_EOL; }
1871
+ fvm_set_transient($tkey, $json);
1872
+ }
1873
+
1874
+ # decode
1875
+ $res = json_decode($json, true);
1876
+
1877
+ # response has failed
1878
+ if($res['status'] != true) {
1879
+ $log.= $res['log'];
1880
+ continue;
1881
+ }
1882
+
1883
+ # append code to merged file
1884
+ $code.= $res['code'];
1885
+ $log.= $res['log'];
1886
+
1887
+ # inline css or fail
1888
+ if($res['code'] !== false) {
1889
+ echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
1890
+ } else {
1891
+ echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
1892
+ }
1893
+
1894
+ # fallback, enqueue google fonts
1895
+ } else {
1896
+ wp_enqueue_style('footer-fvm-fonts', $gfurl, array(), null, 'all');
1897
+ }
1898
+
1899
  }
 
 
 
 
 
 
 
1900
  }
1901
  }
1902
 
2008
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2009
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
2010
 
2011
+ # download, minify, cache
2012
+ $tkey = 'css-'.$ctime.'-'.hash('adler32', $handle.$hurl).'.css';
2013
+ $json = false; $json = fvm_get_transient($tkey);
2014
+ if ( $json === false) {
2015
+ $json = fvm_download_and_minify($hurl, null, $disable_css_minification, 'css', $handle);
2016
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
2017
+ fvm_set_transient($tkey, $json);
 
 
 
 
2018
  }
2019
+
2020
+ # decode
2021
+ $res = json_decode($json, true);
2022
+
2023
+ # response has failed
2024
+ if($res['status'] != true) {
2025
+ $log.= $res['log'];
2026
+ continue;
2027
+ }
2028
+
2029
+ # append code to merged file
2030
+ $code.= $res['code'];
2031
+ $log.= $res['log'];
2032
+
2033
+ # append inlined styles
2034
+ if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) {
2035
+ $code.= $inline_css[$handle];
2036
+ }
2037
+
2038
  # consider dependencies on handles with an empty src
2039
  } else {
2040
  wp_dequeue_script($handle);
2043
  endforeach;
2044
 
2045
  # prepare log
2046
+ $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
2047
 
2048
  # generate cache, add inline css, write log
2049
  file_put_contents($file.'.txt', $log);
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
+
2060
+ # Async CSS with loadCSS ?
2061
+ if($fvmloadcss != false && $fvm_remove_css != true) {
2062
+ $mt = $footer[$i]['media'];
2063
+ echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$mt.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2064
+ echo '<noscript><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /></noscript>';
2065
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /><![endif]-->';
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
  }
2093
  # dev: https://www.filamentgroup.com/lab/async-css.html
2094
  ###########################################
2095
  function fvm_add_loadcss() {
2096
+
2097
+ echo <<<EOF
2098
+ <script>
2099
+ /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
2100
+ !function(n){"use strict";n.loadCSS||(n.loadCSS=function(){});var o=loadCSS.relpreload={};if(o.support=function(){var e;try{e=n.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),o.bindMediaToggle=function(t){var e=t.media||"all";function a(){t.media=e}t.addEventListener?t.addEventListener("load",a):t.attachEvent&&t.attachEvent("onload",a),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(a,3e3)},o.poly=function(){if(!o.support())for(var t=n.document.getElementsByTagName("link"),e=0;e<t.length;e++){var a=t[e];"preload"!==a.rel||"style"!==a.getAttribute("as")||a.getAttribute("data-loadcss")||(a.setAttribute("data-loadcss",!0),o.bindMediaToggle(a))}},!o.support()){o.poly();var t=n.setInterval(o.poly,500);n.addEventListener?n.addEventListener("load",function(){o.poly(),n.clearInterval(t)}):n.attachEvent&&n.attachEvent("onload",function(){o.poly(),n.clearInterval(t)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:n.loadCSS=loadCSS}("undefined"!=typeof global?global:this);
2101
+ </script>
2102
+ EOF;
2103
+
2104
  }
2105
+
2106
+
2107
+
2108
+
2109
+ # add inline CSS code / Critical Path
2110
+ function fvm_add_criticial_path() {
2111
+ $no_global_critical_path_css = false;
2112
+ $critical_path_css = get_option('fastvelocity_min_critical_path_css');
2113
+ $critical_path_css_is_front_page = get_option('fastvelocity_min_critical_path_css_is_front_page');
2114
+
2115
+ # critical path (is_front_page only)
2116
+ if(!empty($critical_path_css_is_front_page) && $critical_path_css_is_front_page !== false) {
2117
+ echo '<style id="critical-path-is-front-page" type="text/css" media="all">'.$critical_path_css_is_front_page.'</style>'.PHP_EOL;
2118
+ $no_global_critical_path_css = 1;
2119
+ }
2120
+
2121
+ # global path, except if there's something else more specific
2122
+ if(!empty($critical_path_css) && $critical_path_css !== false && $no_global_critical_path_css === false) {
2123
+ echo '<style id="critical-path-global" type="text/css" media="all">'.$critical_path_css.'</style>'.PHP_EOL;
2124
+ }
2125
  }
2126
 
2127
 
2128
 
2129
 
2130
+
2131
  ###########################################
2132
  # add preconnect and preload headers
2133
  ###########################################
2134
+ add_action( 'send_headers', 'fvm_extra_preload_headers' );
2135
+ function fvm_extra_preload_headers() {
2136
+
2137
+ # fetch headers
2138
+ $preload = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_hpreload')));
2139
+ $preconnect = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_hpreconnect')));
2140
+
2141
+ # preconnect
2142
+ if(is_array($preload) && count($preload) > 0) {
2143
+ foreach ($preload as $h) {
2144
+ if(!empty($h)) {
2145
+ header($h, false);
2146
+ }
2147
  }
 
2148
  }
2149
 
2150
+ # preload
2151
+ if(is_array($preconnect) && count($preconnect) > 0) {
2152
+ foreach ($preconnect as $url) {
2153
+ if(!empty($url) && filter_var($url, FILTER_VALIDATE_URL)) {
2154
+ header("Link: <$url>; rel=preconnect", false);
2155
+ }
 
 
2156
  }
2157
  }
2158
 
 
 
2159
  }
2160
 
2161
 
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; }
2171
 
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
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');
2211
+
2212
+ # make sure href is complete
2213
+ $href = fastvelocity_min_get_hurl($href, $wp_domain, $wp_home);
2214
+
2215
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Inline CSS processing start $handle / $href -->" . PHP_EOL; }
2216
+
2217
+ # prevent optimization for these locations
2218
+ if (is_admin() || is_preview() || is_customize_preview() || ($fvm_fix_editor == true && is_user_logged_in())) {
2219
+ return $html;
2220
+ }
2221
+
2222
+ # skip all this, if the async css option is enabled
2223
+ if($fvmloadcss != false) {
2224
+ return $html;
2225
+ }
2226
+
2227
+ # remove all css?
2228
+ if($fvm_remove_css != false) {
2229
+ return false;
2230
+ }
2231
+
2232
+ # leave conditionals alone
2233
+ $conditional = wp_styles()->get_data($handle, 'conditional');
2234
+ if($conditional != false) {
2235
+ return $html;
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
+ }
2243
+
2244
+ # Exclude specific CSS files from PSI?
2245
+ if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($href, $fvm_min_excludecsslist)) {
2246
+ $cssguid = 'fvm'.hash('adler32', $href);
2247
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2248
+ 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.');';
2249
+ echo '}</script>';
2250
+ return false;
2251
+ }
2252
+
2253
+ # return if in any ignore or black list
2254
+ $nignore = array(); if(is_array($ignore)) { foreach ($ignore as $i) { if($i != '/fvm/cache/') { $nignore[] = $i; } } }
2255
+ if (count($nignore) > 0 && fastvelocity_min_in_arrayi($href, $nignore) || count($blacklist) > 0 && fastvelocity_min_in_arrayi($href, $blacklist) || count($ignorelist) > 0 && fastvelocity_min_in_arrayi($href, $ignorelist)) {
2256
+ return $html;
2257
+ }
2258
+
2259
+ # remove google fonts completely?
2260
+ if($remove_googlefonts != false && stripos($href, 'fonts.googleapis.com') !== false) {
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
+
2268
+ # hide google fonts from PSI
2269
+ if($css_hide_googlefonts == true) {
2270
+ $cssguid = 'fvm'.hash('adler32', $href);
2271
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2272
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$href.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="all"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2273
+ echo '}</script>';
2274
+ return false;
2275
+ }
2276
+
2277
+ # load google fonts async
2278
+ if($min_async_googlefonts != false) {
2279
+ echo '<link rel="preload" href="'.$href.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2280
+ echo '<noscript><link rel="stylesheet" href="'.$href.'" media="all" /></noscript>';
2281
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$href.'" media="all" /><![endif]-->';
2282
+ return false;
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
+
2289
+ # download, minify, cache
2290
+ $tkey = 'css-'.$ctime.'-'.hash('adler32', $handle.$href).'.css';
2291
+ $json = false; $json = fvm_get_transient($tkey);
2292
+ if ( $json === false) {
2293
+ $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2294
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2295
+ fvm_set_transient($tkey, $json);
2296
+ }
2297
+
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;
2304
+ return false;
2305
+ } else {
2306
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Google fonts request failed for $href -->" . PHP_EOL; }
2307
+ return $html;
2308
+ }
2309
+ }
2310
+
2311
+ # collect and remove google fonts for merging
2312
+ if(stripos($href, 'fonts.googleapis.com') !== false){
2313
+ $fvm_collect_google_fonts[$handle] = $href;
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; }
2321
+ return $html;
2322
+ }
2323
+
2324
+ # download, minify, cache
2325
+ $tkey = 'css-'.$ctime.'-'.hash('adler32', $handle.$href).'.css';
2326
+ $json = false; $json = fvm_get_transient($tkey);
2327
+ if ( $json === false) {
2328
+ $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2329
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2330
+ fvm_set_transient($tkey, $json);
2331
+ }
2332
+
2333
+ # decode
2334
+ $res = json_decode($json, true);
2335
+
2336
+ # inline it + other inlined children styles
2337
+ if($res['status'] != false) {
2338
+ echo '<style type="text/css" media="'.$media.'">'.$res['code'].'</style>';
2339
+
2340
+ # get inline_styles for this handle, minify and print
2341
+ $inline_styles = array();
2342
+ $inline_styles = wp_styles()->get_data( $handle, 'after' );
2343
+ if($inline_styles != false) {
2344
+
2345
+ # string type
2346
+ if(is_string($inline_styles)) {
2347
+ $code = fastvelocity_min_get_css($href, $inline_styles, $disable_css_minification);
2348
+ if(!empty($code) && $code != false) {
2349
+ echo '<style type="text/css" media="'.$media.'">'.$code.'</style>';
2350
+ }
2351
+ }
2352
+
2353
+ # array type
2354
+ if(is_array($inline_styles)) {
2355
+ foreach ($inline_styles as $st) {
2356
+ $code = fastvelocity_min_get_css($href, $st, $disable_css_minification);
2357
+ if(!empty($code) && $code != false) {
2358
+ echo '<style type="text/css" media="'.$media.'">'.$code.'</style>';
2359
+ }
2360
+ }
2361
+ }
2362
+ }
2363
+
2364
+ # prevent default
2365
+ return false;
2366
+
2367
+ } else {
2368
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: $handle / $href returned an empty from minification -->" . PHP_EOL; }
2369
+ return $html;
2370
+ }
2371
+
2372
+ # fallback, for whatever reason
2373
+ echo "<!-- ERROR: FVM couldn't catch the CSS file below. Please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
2374
+ return $html;
2375
+ }
2376
+
2377
+
2378
+ # critical css for the page
2379
+ function fastvelocity_add_google_fonts_merged() {
2380
+ global $fvm_collect_google_fonts, $fvmualist, $css_hide_googlefonts, $skip_google_fonts, $min_async_googlefonts, $fvm_debug;
2381
+
2382
+ # prevent optimization for logged in users
2383
+ if (is_admin() || is_preview() || is_customize_preview()) {
2384
+ return false;
2385
+ }
2386
+
2387
+ # must have something to do
2388
+ if(!is_array($fvm_collect_google_fonts) || count($fvm_collect_google_fonts) == 0) {
2389
+ return false;
2390
+ }
2391
+
2392
+ # merge google fonts
2393
+ $gfurl = fastvelocity_min_concatenate_google_fonts($fvm_collect_google_fonts);
2394
+ if(empty($gfurl)) {
2395
+ return false;
2396
+ }
2397
+
2398
+ # hide google fonts from PSI
2399
+ if($css_hide_googlefonts == true) {
2400
+
2401
+ # make a stylesheet, hide from PSI
2402
+ $cssguid = 'fvm'.hash('adler32', $gfurl);
2403
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2404
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$gfurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="all"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2405
+ echo '}</script>';
2406
+
2407
+ # load google fonts async
2408
+ } elseif($min_async_googlefonts != false) {
2409
+ echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2410
+ echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
2411
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
2412
+
2413
+ # fallback to normal inline
2414
+ } else {
2415
+ echo '<link rel="stylesheet" href="'.$gfurl.'" media="all" />';
2416
+ }
2417
+
2418
+ # unset per hook
2419
+ foreach($fvm_collect_google_fonts as $k=>$v) {
2420
+ unset($fvm_collect_google_fonts[$k]);
2421
+ }
2422
+
2423
+ }
2424
+
inc/functions-upgrade.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function fastvelocity_version_check() {
4
+ global $fastvelocity_plugin_version;
5
+
6
+ # current FVM install date, create if it doesn't exist
7
+ $ver = get_option("fastvelocity_plugin_version");
8
+ if ($ver == false) {
9
+ update_option( "fastvelocity_plugin_version", $fastvelocity_plugin_version);
10
+ $ver = '0.0.0';
11
+ }
12
+
13
+ # compare versions (0.1.2)
14
+ $dots = explode('.', $fastvelocity_plugin_version);
15
+ if(!is_array($dots) || count($dots) != 3) { return false; }
16
+
17
+
18
+ # changed options in 2.4.0
19
+ if($dots[0] < 2 || ($dots[0] == 2 && $dots[1] < 4)) {
20
+
21
+ # delete some old fields and define them on a radio option, by this priority
22
+ if(get_option("fastvelocity_css_hide_googlefonts") != false) {
23
+ update_option( "fastvelocity_gfonts_method", 3);
24
+ delete_option('fastvelocity_min_force_inline_googlefonts');
25
+ delete_option('fastvelocity_min_async_googlefonts');
26
+ delete_option('fastvelocity_css_hide_googlefonts');
27
+ }
28
+
29
+ if(get_option("fastvelocity_min_async_googlefonts") != false) {
30
+ update_option( "fastvelocity_gfonts_method", 2);
31
+ delete_option('fastvelocity_min_force_inline_googlefonts');
32
+ delete_option('fastvelocity_min_async_googlefonts');
33
+ delete_option('fastvelocity_css_hide_googlefonts');
34
+ }
35
+
36
+ if(get_option("fastvelocity_min_force_inline_googlefonts") != false) {
37
+ update_option( "fastvelocity_gfonts_method", 1);
38
+ delete_option('fastvelocity_min_force_inline_googlefonts');
39
+ delete_option('fastvelocity_min_async_googlefonts');
40
+ delete_option('fastvelocity_css_hide_googlefonts');
41
+ }
42
+
43
+ }
44
+
45
+ }
46
+ add_action( 'plugins_loaded', 'fastvelocity_version_check' );
inc/functions.php CHANGED
@@ -51,6 +51,44 @@ return array('cachebase'=>$cachebase,'tmpdir'=>$tmpdir, 'cachedir'=>$cachedir, '
51
  }
52
 
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  # detect external or internal scripts
55
  function fvm_is_local_domain($src) {
56
  $locations = array(home_url(), site_url(), network_home_url(), network_site_url());
@@ -93,8 +131,12 @@ $hurl = trim($src); if(empty($hurl)) { return $hurl; }
93
  # some fixes
94
  $hurl = str_ireplace(array('&#038;', '&amp;'), '&', $hurl);
95
 
96
- # get current protocol scheme with cloudflare support
97
- if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { $protocol = 'https://'; } else { $protocol = 'http://'; }
 
 
 
 
98
 
99
  #make sure wp_home doesn't have a forward slash
100
  $wp_home = rtrim($wp_home, '/');
@@ -118,12 +160,15 @@ if (substr($hurl, 0, 12) === "/wp-includes" || substr($hurl, 0, 9) === "/wp-admi
118
  $hurl = $wp_home.'/'.ltrim($hurl, "/"); }
119
 
120
  # make sure there is a protocol prefix as required
121
- $hurl = $protocol.str_ireplace(array('http://', 'https://'), '', $hurl); # enforce protocol
122
 
123
  # no query strings
124
  if (stripos($hurl, '.js?v') !== false) { $hurl = stristr($hurl, '.js?v', true).'.js'; } # no query strings
125
  if (stripos($hurl, '.css?v') !== false) { $hurl = stristr($hurl, '.css?v', true).'.css'; } # no query strings
126
 
 
 
 
127
  return $hurl;
128
  }
129
 
@@ -138,7 +183,7 @@ if (isset($_SERVER['SERVER_ADDR']) && stripos($hurl, preg_replace('/:\d+$/', '',
138
 
139
  # allow specific external urls to be merged
140
  if($noxtra === NULL) {
141
- $merge_allowed_urls = array_map('trim', explode("\n", get_option('fastvelocity_min_merge_allowed_urls', '')));
142
  if(is_array($merge_allowed_urls) && strlen(implode($merge_allowed_urls)) > 0) {
143
  foreach ($merge_allowed_urls as $e) {
144
  if (stripos($hurl, $e) !== false && !empty($e)) { return true; }
@@ -157,21 +202,21 @@ function fastvelocity_min_in_arrayi($hurl, $ignore){
157
 
158
  if (!empty($hurl) && is_array($ignore)) {
159
  foreach ($ignore as $i) {
160
- $i = str_ireplace(array('http://', 'https://'), '//', $i); # better compatibility
161
- $i = strtok(urldecode(rawurldecode($i)), '?'); # no query string, decode entities
162
- $i = trim(trim(trim(rtrim($i, '/')), '*')); # wildcard char removal
163
- if (stripos($hurl, $i) !== false) { return true; }
164
  }
165
  }
166
  return false;
167
  }
168
 
169
 
170
- # better compatibility urls, fix bootstrap 4 svg images https://www.w3.org/TR/SVG/intro.html#NamespaceAndDTDIdentifiers
171
  function fvm_compat_urls($code) {
172
  $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
173
  if($default_protocol == 'dynamic' || empty($default_protocol)) {
174
- $default_protocol = '//';
175
  } else {
176
  $default_protocol = $default_protocol.'://';
177
  }
@@ -212,8 +257,8 @@ function fvm_server_is_windows() {
212
  function fastvelocity_min_get_js($url, $js, $disable_js_minification) {
213
 
214
  # exclude minification on already minified files + jquery (because minification might break those)
215
- $excl = array('jquery.js', '.min.js', '-min.js', '/uploads/fusion-scripts/', '/min/');
216
- foreach($excl as $e) { if (stripos(basename($url), $e) !== false) { $disable_js_minification = true; break; } }
217
 
218
  # remove BOM
219
  $js = fastvelocity_min_remove_utf8_bom($js);
@@ -226,7 +271,9 @@ if(!$disable_js_minification) {
226
  }
227
 
228
  # needed when merging js files
229
- $js = $js."\r\n;";
 
 
230
 
231
  # return html
232
  return $js;
@@ -237,28 +284,6 @@ return $js;
237
  function fastvelocity_min_minify_js_string($js) {
238
  global $tmpdir, $plugindir;
239
 
240
- # check for exec + a supported java version
241
- $use_yui = get_option('fastvelocity_min_use_yui');
242
- if($use_yui == true && function_exists('exec') && exec('command -v java >/dev/null && echo "yes" || echo "no"') == 'yes') {
243
-
244
- # create temp files
245
- $tmpname = hash('adler32', $js);
246
- $tmpin = $tmpdir.'/'.$tmpname.'.js';
247
- file_put_contents($tmpin, $js);
248
- $tmpout = $tmpdir.'/'.$tmpname.'.min.js';
249
-
250
- # define jar path and command
251
- $cmd = 'java -jar '.$plugindir.'libs/jar/yuicompressor-2.4.8.jar'.' --preserve-semi --nomunge '.$tmpin.' -o '.$tmpout;
252
-
253
- # run local compiler
254
- exec($cmd . ' 2>&1', $output);
255
- if(count($output) == 0 && file_exists($tmpout)) {
256
- $min = file_get_contents($tmpout);
257
- if($min !== false) { return fvm_compat_urls($min); }
258
- exit();
259
- }
260
- }
261
-
262
  # PHP Minify [2016.08.01] from https://github.com/matthiasmullie/minify
263
  $minifier = new Minify\JS($js);
264
  $min = $minifier->minify();
@@ -283,15 +308,21 @@ function fastvelocity_min_html_compression_start() {
283
 
284
 
285
  # remove all cache files
286
- function fastvelocity_rrmdir($path) {
287
- clearstatcache();
288
- if(is_dir($path)) {
289
- $i = new DirectoryIterator($path);
290
- foreach($i as $f){
291
- if($f->isFile()){ unlink($f->getRealPath());
292
- } else if(!$f->isDot() && $f->isDir()){
293
- fastvelocity_rrmdir($f->getRealPath());
294
- rmdir($f->getRealPath());
 
 
 
 
 
 
295
  }
296
  }
297
  }
@@ -352,6 +383,9 @@ if(!empty($fvm_cdn_url)) {
352
  $css = str_ireplace($wp_domain, $fvm_cdn_url, $css);
353
  }
354
 
 
 
 
355
  # return html
356
  return $css;
357
  }
@@ -378,95 +412,152 @@ function fvm_file_get_contents_curl($url, $uagent=NULL) {
378
 
379
 
380
  # download and cache css and js files
381
- function fvm_download_and_cache($hurl, $tkey, $inline=null, $disable_minification=false, $type=null, $handle=null){
382
- global $cachedir, $cachedirurl, $wp_domain, $wp_home, $wp_home_path;
 
 
 
 
 
 
 
 
 
 
 
 
383
 
384
  # filters and defaults
385
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
386
- $printhandle = ''; if($handle !== null) { $printhandle = "[$handle]"; }
387
 
388
- # try to open locally first, but skip if we are on windows
389
- if(fvm_server_is_windows() === false) {
390
- if (stripos($hurl, $wp_domain) !== false) {
391
- # default
392
- $f = str_ireplace(rtrim($wp_home, '/'), rtrim($wp_home_path, '/'), $hurl);
393
- clearstatcache();
394
- if (file_exists($f)) {
395
- if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
396
- else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
397
-
398
- $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
399
- return array('log'=>$log, 'code'=>$code);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
400
  }
401
-
402
- # failover when home_url != site_url
403
- $nhurl = str_ireplace(site_url(), home_url(), $hurl);
404
- $f = str_ireplace(rtrim($wp_home, '/'), rtrim($wp_home_path, '/'), $nhurl);
405
- clearstatcache();
406
- if (file_exists($f)) {
407
- if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
408
- else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
409
- $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
410
- return array('log'=>$log, 'code'=>$code);
411
  }
412
- }
413
- }
414
 
415
 
416
- # else, fallback to remote urls (or windows)
417
- $ttl = 3600 * 24 * 7; # 7 days
418
- $code = fastvelocity_download($hurl, $tkey, $ttl);
419
- if($code !== false) {
420
- if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
421
- else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
422
- fvm_set_transient($tkey, $code, 604800);
423
- $log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
424
- return array('log'=>$log, 'code'=>$code);
425
- }
426
-
427
-
428
- # fallback when home_url != site_url
429
- if(stripos($hurl, $wp_domain) !== false && home_url() != site_url()) {
430
- $nhurl = str_ireplace(site_url(), home_url(), $hurl);
431
- $code = fastvelocity_download($nhurl, $tkey, $ttl);
432
  if($code !== false) {
433
- if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
434
- else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
435
- $log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
436
- return array('log'=>$log, 'code'=>$code);
 
 
 
 
 
 
 
 
437
  }
438
- }
439
 
440
 
441
- # if remote urls failed... try to open locally again, regardless of OS in use
442
- if (stripos($hurl, $wp_domain) !== false) {
443
- # default
444
- $f = str_ireplace(rtrim($wp_home, '/'), rtrim($wp_home_path, '/'), $hurl);
445
- clearstatcache();
446
- if (file_exists($f)) {
447
- if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
448
- else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
449
- $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
450
- return array('log'=>$log, 'code'=>$code);
 
 
 
 
 
 
 
 
451
  }
452
-
453
- # failover when home_url != site_url
454
- $nhurl = str_ireplace(site_url(), home_url(), $hurl);
455
- $f = str_ireplace(rtrim($wp_home, '/'), rtrim($wp_home_path, '/'), $nhurl);
456
- clearstatcache();
457
- if (file_exists($f)) {
458
- if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
459
- else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
460
- $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
461
- return array('log'=>$log, 'code'=>$code);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  }
463
- }
464
 
465
 
466
- # else fail
467
- $code = false;
468
- $log = " - FAILED --- Debug: $printhandle Tried to fetch via wp_remote_get, curl and also to open it locally. URL: $hurl ---\n";
469
- return array('log'=>$log, 'code'=>$code);
 
470
  }
471
 
472
 
@@ -547,83 +638,27 @@ return false;
547
  }
548
 
549
 
 
 
 
 
 
 
 
 
 
 
550
 
551
- # readme parser
552
- function fastvelocity_min_readme($url) {
553
-
554
- # read file
555
- $file = @file_get_contents( $url );
556
- if (empty($file)) { return '<strong>Readme Parser: readme.txt not found!</strong>'; }
557
-
558
- // line end to \n
559
- $file = preg_replace("/(\n\r|\r\n|\r|\n)/", "\n", $file);
560
-
561
- // headlines
562
- $s = array('===','==','=' );
563
- $r = array('h2' ,'h3','h4');
564
- for ( $x = 0; $x < sizeof($s); $x++ ) {
565
- $file = preg_replace('/(.*?)'.$s[$x].'(?!\")(.*?)'.$s[$x].'(.*?)/', '$1<'.$r[$x].'>$2</'.$r[$x].'>$3', $file);
566
- }
567
-
568
- // inline
569
- $s = array('\*\*','\`');
570
- $r = array('b' ,'code');
571
- for ( $x = 0; $x < sizeof($s); $x++ ) {
572
- $file = preg_replace('/(.*?)'.$s[$x].'(?!\s)(.*?)(?!\s)'.$s[$x].'(.*?)/', '$1<'.$r[$x].'>$2</'.$r[$x].'>$3', $file);
573
- }
574
-
575
- // ' _italic_ '
576
- $file = preg_replace('/(\s)_(\S.*?\S)_(\s|$)/', ' <em>$2</em> ', $file);
577
-
578
- // ul lists
579
- $s = array('\*','\+','\-');
580
- for ( $x = 0; $x < sizeof($s); $x++ )
581
- $file = preg_replace('/^['.$s[$x].'](\s)(.*?)(\n|$)/m', '<li>$2</li>', $file);
582
- $file = preg_replace('/\n<li>(.*?)/', '<ul><li>$1', $file);
583
- $file = preg_replace('/(<\/li>)(?!<li>)/', '$1</ul>', $file);
584
-
585
- // ol lists
586
- $file = preg_replace('/(\d{1,2}\.)\s(.*?)(\n|$)/', '<li>$2</li>', $file);
587
- $file = preg_replace('/\n<li>(.*?)/', '<ol><li>$1', $file);
588
- $file = preg_replace('/(<\/li>)(?!(\<li\>|\<\/ul\>))/', '$1</ol>', $file);
589
-
590
- // ol screenshots style
591
- $file = preg_replace('/(?=Screenshots)(.*?)<ol>/', '$1<ol class="readme-parser-screenshots">', $file);
592
-
593
- // line breaks
594
- $file = preg_replace('/(.*?)(\n)/', "<p>$1</p>", $file);
595
- $file = preg_replace('/(1|2|3|4)(><br\/>)/', '$1>', $file);
596
- $file = str_ireplace('</ul><br/>', '</ul>', $file);
597
-
598
- # cleanup
599
- $file = str_ireplace('<p></p>', '', $file);
600
- $file = str_ireplace('<p><h4>', '<h4>', $file);
601
- $file = str_ireplace('</h4></p>', '</h4>', $file);
602
-
603
- // urls
604
- $file = str_replace('http://www.', 'www.', $file);
605
- $file = str_replace('www.', 'http://www.', $file);
606
- $file = preg_replace('#(^|[^\"=]{1})(http://|ftp://|mailto:|https://)([^\s<>]+)([\s\n<>]|$)#', '$1<a target="_blank" href="$2$3">$2$3</a>$4', $file);
607
-
608
- # extra linebreaks
609
- $file = str_replace('<p>...</p>', "", $file);
610
-
611
- # extract faqs
612
- $prefix = "Frequently Asked Questions";
613
- $faq = substr($file, strpos($file, $prefix) + strlen($prefix));
614
- $faq = substr($faq, 0, strpos($faq, '<p><h3>'));
615
-
616
- return trim($faq);
617
  }
618
 
619
 
620
- # remove emoji support
621
- function fastvelocity_min_disable_wp_emojicons() {
622
- remove_action('wp_head', 'print_emoji_detection_script', 7);
623
- remove_action('wp_print_styles', 'print_emoji_styles');
624
- remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
625
- remove_action( 'admin_print_styles', 'print_emoji_styles' );
626
- }
627
 
628
  # escape double quotes
629
  function fastvelocity_escape_double($string) {
@@ -674,30 +709,21 @@ function fvm_get_protocol($url) {
674
  }
675
 
676
  # enforce protocol if needed
677
- $fp = get_option('fastvelocity_min_default_protocol', 'dynamic');
678
- if($fp == 'http') { $url = 'http://'.$url; } elseif($fp == 'https') { $url = 'https://'.$url; } else { $url = '//'.$url; }
 
 
 
 
679
 
680
  # return
681
- return $url;
682
  }
683
 
684
 
685
- # keep track of transients, dump our plugin transients as needed
686
- function fvm_transients_purge() {
687
-
688
- # last cache update to now
689
  update_option('fvm-last-cache-update', time());
690
-
691
- # delete legacy transients
692
- $tk = get_option( 'fvm_transient_keys' );
693
- if($tk !== false) {
694
- delete_option('fvm_transient_keys');
695
- if(is_array($tk)) {
696
- foreach( $tk as $t ) {
697
- delete_transient($t);
698
- }
699
- }
700
- }
701
  }
702
 
703
  # purge all caches
@@ -712,9 +738,8 @@ function fvm_purge_all() {
712
  return false;
713
  }
714
 
715
- # remove cache files, set last update and clean legacy transients
716
  fastvelocity_rrmdir($cachebase);
717
- fvm_transients_purge();
718
  do_action('fvm_after_purge_all');
719
  return true;
720
  }
@@ -726,69 +751,61 @@ function fvm_get_transient($key) {
726
  $tmpdir = $cachepath['tmpdir'];
727
  $f = $tmpdir.'/'.$key.'.transient';
728
  clearstatcache();
729
- if(file_exists($tmpdir.'/'.$key)) {
730
  return file_get_contents($f);
731
  } else {
732
  return false;
733
  }
734
  }
735
 
736
- # set transients on the disk
737
- function fvm_set_transient($key, $code, $ttl) {
738
  if(is_null($code) || empty($code)) { return false; }
739
  $cachepath = fvm_cachepath();
740
  $tmpdir = $cachepath['tmpdir'];
741
  $f = $tmpdir.'/'.$key.'.transient';
742
- $e = $tmpdir.'/'.$key.'.exp';
743
- clearstatcache();
744
-
745
- # update or not?
746
- if(!file_exists($f)) {
747
- $write = 1;
748
- } else {
749
- if(file_exists($e)) {
750
- $t = file_get_contents($e);
751
- if(is_numeric($t) && $t < time()) {
752
- $write = 1;
753
- }
754
- }
755
  }
756
 
757
- # proceed
758
- if(isset($write) && $write == 1) {
759
- file_put_contents($f, $code);
760
- file_put_contents($e, time()+$ttl);
761
- return true;
762
  }
763
 
764
  # fallback
765
- return false;
766
  }
767
 
768
 
769
  # exclude processing from some pages / posts / contents
770
  function fastvelocity_exclude_contents() {
 
 
 
 
 
 
 
 
 
 
771
 
772
- # ajax requests
773
- if (
774
- (defined('DOING_AJAX') && DOING_AJAX) || (function_exists('wp_doing_ajax') && wp_doing_ajax()) ||
775
- (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') ||
776
- (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
777
- ) { return true; }
778
-
779
- # robots.txt and xml dynamically generated sitemaps
780
- if(isset($_SERVER['REQUEST_URI']) && (substr($_SERVER['REQUEST_URI'], -4) == '.txt' || substr($_SERVER['REQUEST_URI'], -4) == '.xml')) { return true; }
781
-
782
- # customizer preview, visual composer
783
- $arr = array('customize_theme', 'preview_id', 'preview');
784
- foreach ($arr as $a) { if(isset($_GET[$a])) { return true; } }
785
-
786
- # Thrive plugins and other post_types
787
- $arr = array('tve_form_type', 'tve_lead_shortcode', 'tqb_splash');
788
- foreach ($arr as $a) { if(isset($_GET['post_type']) && $_GET['post_type'] == $a) { return true; } }
789
-
790
- # default
791
- return false;
792
  }
793
 
794
  # Know files that should always be ignored
@@ -796,7 +813,7 @@ function fastvelocity_default_ignore($ignore) {
796
  if(is_array($ignore)) {
797
 
798
  # from the database
799
- $exc = array_map('trim', explode("\n", get_option('fastvelocity_min_ignorelist', '')));
800
 
801
  # should we exclude jquery when defer is enabled?
802
  $exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
@@ -821,7 +838,7 @@ if(is_array($ignore)) {
821
  function fastvelocity_ie_blacklist($url) {
822
 
823
  # from the database
824
- $exc = array_map('trim', explode("\n", get_option('fastvelocity_min_blacklist', '')));
825
 
826
  # must have
827
  $exc[] = '/fvm/cache/';
@@ -833,44 +850,31 @@ function fastvelocity_ie_blacklist($url) {
833
 
834
 
835
  # download function with cache support and fallback
836
- function fastvelocity_download($url, $tkey, $ttl) {
837
-
838
- # rate limit requests, prevent slowdowns
839
- $rtlim = false; $rtlim = fvm_get_transient($tkey.'_access');
840
- if ( $rtlim !== false) { return false; }
841
 
842
- # info (needed for google fonts woff files + hinted fonts)
843
  $uagent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';
844
- $data = false; $data = fvm_get_transient($tkey);
845
- if ( $data === false) {
846
-
847
- # get updated list from our api and cache it for 24 hours
848
- $response = wp_remote_get($url, array('user-agent'=>$uagent, 'timeout' => 7, 'httpversion' => '1.1', 'sslverify'=>false));
849
- $res_code = wp_remote_retrieve_response_code($response);
850
- if($res_code == '200') {
851
- $data = wp_remote_retrieve_body($response);
852
- if(strlen($data) > 1 && $ttl > 0) {
853
- fvm_set_transient($tkey, $data, $ttl);
854
- return $data;
855
- }
856
- }
857
-
858
- # fallback, let's try curl if available
859
- if(function_exists('curl_version')) {
860
- $curl = fvm_file_get_contents_curl($url, $uagent);
861
- if(!empty($curl) && strlen($curl) > 1 && $ttl > 0) {
862
- fvm_set_transient($tkey, $data, $ttl);
863
- return $data;
864
- }
865
  }
866
-
867
- # error
868
- fvm_set_transient($tkey.'_access', "Failed to fetch: $url on ".current_time('timestamp'), $ttl);
869
- return false;
870
- }
871
 
872
- # return transient
873
- return $data;
 
 
 
 
 
 
 
 
874
  }
875
 
876
 
@@ -890,81 +894,93 @@ function fastvelocity_purge_others(){
890
 
891
  # wordpress default cache
892
  if (function_exists('wp_cache_flush')) {
893
- wp_cache_flush();
894
  }
895
 
896
  # Purge all W3 Total Cache
897
  if (function_exists('w3tc_pgcache_flush')) {
898
- w3tc_pgcache_flush();
899
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>W3 Total Cache</strong> have also been purged.</p></div>');
900
  }
901
 
902
  # Purge WP Super Cache
903
  if (function_exists('wp_cache_clear_cache')) {
904
- wp_cache_clear_cache();
905
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>WP Super Cache</strong> have also been purged.</p></div>');
906
  }
907
 
908
  # Purge WP Rocket
909
  if (function_exists('rocket_clean_domain')) {
910
- rocket_clean_domain();
911
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>WP Rocket</strong> have also been purged.</p></div>');
912
  }
913
 
914
  # Purge Wp Fastest Cache
915
  if(isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache')){
916
- $GLOBALS['wp_fastest_cache']->deleteCache();
917
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>Wp Fastest Cache</strong> have also been purged.</p></div>');
918
  }
919
 
920
  # Purge Cachify
921
  if (function_exists('cachify_flush_cache')) {
922
- cachify_flush_cache();
923
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>Cachify</strong> have also been purged.</p></div>');
924
  }
925
 
926
  # Purge Comet Cache
927
  if ( class_exists("comet_cache") ) {
928
- comet_cache::clear();
929
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>Comet Cache</strong> have also been purged.</p></div>');
930
  }
931
 
932
  # Purge Zen Cache
933
  if ( class_exists("zencache") ) {
934
- zencache::clear();
935
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>Comet Cache</strong> have also been purged.</p></div>');
936
  }
937
 
938
  # Purge LiteSpeed Cache
939
  if (class_exists('LiteSpeed_Cache_Tags')) {
940
- LiteSpeed_Cache_Tags::add_purge_tag('*');
941
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>LiteSpeed Cache</strong> have also been purged.</p></div>');
942
  }
943
 
944
  # Purge SG Optimizer
945
  if (function_exists('sg_cachepress_purge_cache')) {
946
- sg_cachepress_purge_cache();
947
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>SG Optimizer</strong> have also been purged.</p></div>');
948
  }
949
 
950
  # Purge Hyper Cache
951
  if (class_exists( 'HyperCache' )) {
952
- do_action( 'autoptimize_action_cachepurged' );
953
- return __( '<div class="notice notice-info is-dismissible"><p>All caches from <strong>HyperCache</strong> have also been purged.</p></div>');
954
  }
955
 
956
  # Purge Godaddy Managed WordPress Hosting (Varnish + APC)
957
  if (class_exists('WPaaS\Plugin')) {
958
- fastvelocity_godaddy_request('BAN');
959
- return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>WP Engine</strong> have also been purged.</p></div>');
 
 
 
 
 
 
960
  }
961
 
 
962
  # Purge WP Engine
963
  if (class_exists("WpeCommon")) {
964
- if (method_exists('WpeCommon', 'purge_memcached')) { WpeCommon::purge_memcached(); }
965
- if (method_exists('WpeCommon', 'clear_maxcdn_cache')) { WpeCommon::clear_maxcdn_cache(); }
966
- if (method_exists('WpeCommon', 'purge_varnish_cache')) { WpeCommon::purge_varnish_cache(); }
967
- }
968
 
 
 
 
 
969
 
970
  }
 
 
51
  }
52
 
53
 
54
+ # run during activation
55
+ function fastvelocity_plugin_activate() {
56
+
57
+ # default options to enable
58
+ $options_enable_default = array('fastvelocity_min_fvm_fix_editor', 'fastvelocity_min_remove_print_mediatypes', 'fastvelocity_min_force_inline_css', 'fastvelocity_min_defer_for_pagespeed', 'fastvelocity_min_defer_for_pagespeed_optimize', 'fastvelocity_fvm_clean_header_one', 'fastvelocity_gfonts_method');
59
+ foreach($options_enable_default as $option) {
60
+ update_option($option, 1, 'yes');
61
+ }
62
+
63
+ # increment time
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
71
+ $exc = array('/Avada/assets/js/main.min.js', '/woocommerce-product-search/js/product-search.js', '/includes/builder/scripts/frontend-builder-scripts.js', '/assets/js/jquery.themepunch.tools.min.js', '/js/TweenMax.min.js', '/jupiter/assets/js/min/full-scripts', '/wp-content/themes/Divi/core/admin/js/react-dom.production.min.js');
72
+ update_option('fastvelocity_min_ignorelist', implode(PHP_EOL, $exc));
73
+
74
+ }
75
+
76
+ # run during deactivation
77
+ function fastvelocity_plugin_deactivate() {
78
+ global $wpdb;
79
+
80
+ # delete all fvm options
81
+ $plugin_options = $wpdb->get_results( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE 'fastvelocity_%' OR option_name LIKE 'fvm-%'" );
82
+ if(is_array($plugin_options) && count($plugin_options) > 0) {
83
+ foreach( $plugin_options as $option ) { delete_option( $option->option_name ); }
84
+ }
85
+
86
+ # purge cache
87
+ fvm_purge_all();
88
+ }
89
+
90
+
91
+
92
  # detect external or internal scripts
93
  function fvm_is_local_domain($src) {
94
  $locations = array(home_url(), site_url(), network_home_url(), network_site_url());
131
  # some fixes
132
  $hurl = str_ireplace(array('&#038;', '&amp;'), '&', $hurl);
133
 
134
+ $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
135
+ if($default_protocol == 'dynamic' || empty($default_protocol)) {
136
+ if ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1)) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) { $default_protocol = 'https://'; } else { $default_protocol = 'http://'; }
137
+ } else {
138
+ $default_protocol = $default_protocol.'://';
139
+ }
140
 
141
  #make sure wp_home doesn't have a forward slash
142
  $wp_home = rtrim($wp_home, '/');
160
  $hurl = $wp_home.'/'.ltrim($hurl, "/"); }
161
 
162
  # make sure there is a protocol prefix as required
163
+ $hurl = $default_protocol.str_ireplace(array('http://', 'https://'), '', $hurl); # enforce protocol
164
 
165
  # no query strings
166
  if (stripos($hurl, '.js?v') !== false) { $hurl = stristr($hurl, '.js?v', true).'.js'; } # no query strings
167
  if (stripos($hurl, '.css?v') !== false) { $hurl = stristr($hurl, '.css?v', true).'.css'; } # no query strings
168
 
169
+ # make sure there is a protocol prefix as required
170
+ $hurl = fvm_compat_urls($hurl); # enforce protocol
171
+
172
  return $hurl;
173
  }
174
 
183
 
184
  # allow specific external urls to be merged
185
  if($noxtra === NULL) {
186
+ $merge_allowed_urls = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_merge_allowed_urls', '')));
187
  if(is_array($merge_allowed_urls) && strlen(implode($merge_allowed_urls)) > 0) {
188
  foreach ($merge_allowed_urls as $e) {
189
  if (stripos($hurl, $e) !== false && !empty($e)) { return true; }
202
 
203
  if (!empty($hurl) && is_array($ignore)) {
204
  foreach ($ignore as $i) {
205
+ $i = str_ireplace(array('http://', 'https://'), '//', $i); # better compatibility
206
+ $i = strtok(urldecode(rawurldecode($i)), '?'); # no query string, decode entities
207
+ $i = trim(trim(trim(rtrim($i, '/')), '*')); # wildcard char removal
208
+ if (stripos($hurl, $i) !== false) { return true; }
209
  }
210
  }
211
  return false;
212
  }
213
 
214
 
215
+ # better compatibility urls + fix bootstrap 4 svg images https://www.w3.org/TR/SVG/intro.html#NamespaceAndDTDIdentifiers
216
  function fvm_compat_urls($code) {
217
  $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
218
  if($default_protocol == 'dynamic' || empty($default_protocol)) {
219
+ if ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1)) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) { $default_protocol = 'https://'; } else { $default_protocol = 'http://'; }
220
  } else {
221
  $default_protocol = $default_protocol.'://';
222
  }
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');
261
+ foreach($excl as $e) { if (stripos(basename($url), $e) !== false) { $disable_js_minification = true; break; } }
262
 
263
  # remove BOM
264
  $js = fastvelocity_min_remove_utf8_bom($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;
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();
308
 
309
 
310
  # remove all cache files
311
+ function fastvelocity_rrmdir($path) {
312
+
313
+ # remove cache files, set last update and clean legacy transients
314
+ if(!get_option('fastvelocity_min_preserve_oldcache')) {
315
+
316
+ # purge
317
+ clearstatcache();
318
+ if(is_dir($path)) {
319
+ $i = new DirectoryIterator($path);
320
+ foreach($i as $f){
321
+ if($f->isFile()){ unlink($f->getRealPath());
322
+ } else if(!$f->isDot() && $f->isDir()){
323
+ fastvelocity_rrmdir($f->getRealPath());
324
+ rmdir($f->getRealPath());
325
+ }
326
  }
327
  }
328
  }
383
  $css = str_ireplace($wp_domain, $fvm_cdn_url, $css);
384
  }
385
 
386
+ # add css comment
387
+ $css = '/* info: ' . $url . ' */' . PHP_EOL . trim($css) . PHP_EOL;
388
+
389
  # return html
390
  return $css;
391
  }
412
 
413
 
414
  # download and cache css and js files
415
+ function fvm_download_and_minify($hurl, $inline, $disable_minification, $type, $handle){
416
+ global $cachedir, $cachedirurl, $wp_domain, $wp_home, $wp_home_path, $fvm_debug;
417
+
418
+ # must have
419
+ if(is_null($hurl) || empty($hurl)) { return false; }
420
+ if(!in_array($type, array('js', 'css'))) { return false; }
421
+
422
+ # defaults
423
+ if($disable_minification != true) { $disable_minification = false; }
424
+ if(is_null($inline) || empty($inline)) { $inline = ''; }
425
+ $printhandle = ''; if(is_null($handle) || empty($handle)) { $handle = ''; } else { $printhandle = "[$handle]"; }
426
+
427
+ # debug request
428
+ $dreq = array('hurl'=>$hurl, 'inline'=>$inline, 'disable_minification'=>$disable_minification, 'type'=>$type, 'handle'=>$handle);
429
 
430
  # filters and defaults
431
  $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
 
432
 
433
+ # linux servers
434
+ if(fvm_server_is_windows() === false) {
435
+ if (stripos($hurl, $wp_domain) !== false) {
436
+ # default
437
+ $f = str_ireplace(rtrim($wp_home, '/'), rtrim($wp_home_path, '/'), $hurl);
438
+ clearstatcache();
439
+ if (file_exists($f)) {
440
+ if($type == 'js') {
441
+ $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification);
442
+ } else {
443
+ $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification);
444
+ }
445
+
446
+ # log, save and return
447
+ $log = $printurl;
448
+ if($fvm_debug == true) { $log.= " --- Debug: $printhandle was opened from $f ---"; }
449
+ $log.= PHP_EOL;
450
+ $return = array('request'=>$dreq, 'log'=>$log, 'code'=>$code, 'status'=>true);
451
+ return json_encode($return);
452
+ }
453
+
454
+ # failover when home_url != site_url
455
+ $nhurl = str_ireplace(site_url(), home_url(), $hurl);
456
+ $f = str_ireplace(rtrim($wp_home, '/'), rtrim($wp_home_path, '/'), $nhurl);
457
+ clearstatcache();
458
+ if (file_exists($f)) {
459
+ if($type == 'js') {
460
+ $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification);
461
+ } else {
462
+ $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification);
463
+ }
464
+
465
+ # log, save and return
466
+ $log = $printurl;
467
+ if($fvm_debug == true) { $log.= " --- Debug: $printhandle was opened from $f ---"; }
468
+ $log.= PHP_EOL;
469
+ $return = array('request'=>$dreq, 'log'=>$log, 'code'=>$code, 'status'=>true);
470
+ return json_encode($return);
471
+ }
472
  }
 
 
 
 
 
 
 
 
 
 
473
  }
 
 
474
 
475
 
476
+ # else, fallback to remote urls (or windows)
477
+ $code = fastvelocity_download($hurl);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  if($code !== false) {
479
+ if($type == 'js') {
480
+ $code = fastvelocity_min_get_js($hurl, $code, $disable_minification);
481
+ } else {
482
+ $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification);
483
+ }
484
+
485
+ # log, save and return
486
+ $log = $printurl;
487
+ if($fvm_debug == true) { $log.= " --- Debug: $printhandle was fetched from $hurl ---"; }
488
+ $log.= PHP_EOL;
489
+ $return = array('request'=>$dreq, 'log'=>$log, 'code'=>$code, 'status'=>true);
490
+ return json_encode($return);
491
  }
 
492
 
493
 
494
+ # fallback when home_url != site_url
495
+ if(stripos($hurl, $wp_domain) !== false && home_url() != site_url()) {
496
+ $nhurl = str_ireplace(site_url(), home_url(), $hurl);
497
+ $code = fastvelocity_download($nhurl);
498
+ if($code !== false) {
499
+ if($type == 'js') {
500
+ $code = fastvelocity_min_get_js($hurl, $code, $disable_minification);
501
+ } else {
502
+ $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification);
503
+ }
504
+
505
+ # log, save and return
506
+ $log = $printurl;
507
+ if($fvm_debug == true) { $log.= " --- Debug: $printhandle was fetched from $hurl ---"; }
508
+ $log.= PHP_EOL;
509
+ $return = array('request'=>$dreq, 'log'=>$log, 'code'=>$code, 'status'=>true);
510
+ return json_encode($return);
511
+ }
512
  }
513
+
514
+
515
+ # if remote urls failed... try to open locally again, regardless of OS in use
516
+ if (stripos($hurl, $wp_domain) !== false) {
517
+ # default
518
+ $f = str_ireplace(rtrim($wp_home, '/'), rtrim($wp_home_path, '/'), $hurl);
519
+ clearstatcache();
520
+ if (file_exists($f)) {
521
+ if($type == 'js') {
522
+ $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification);
523
+ } else {
524
+ $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification);
525
+ }
526
+
527
+ # log, save and return
528
+ $log = $printurl;
529
+ if($fvm_debug == true) { $log.= " --- Debug: $printhandle was opened from $f ---"; }
530
+ $log.= PHP_EOL;
531
+ $return = array('request'=>$dreq, 'log'=>$log, 'code'=>$code, 'status'=>true);
532
+ return json_encode($return);
533
+ }
534
+
535
+ # failover when home_url != site_url
536
+ $nhurl = str_ireplace(site_url(), home_url(), $hurl);
537
+ $f = str_ireplace(rtrim($wp_home, '/'), rtrim($wp_home_path, '/'), $nhurl);
538
+ clearstatcache();
539
+ if (file_exists($f)) {
540
+ if($type == 'js') {
541
+ $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification);
542
+ } else {
543
+ $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification);
544
+ }
545
+
546
+ # log, save and return
547
+ $log = $printurl;
548
+ if($fvm_debug == true) { $log.= " --- Debug: $printhandle was opened from $f ---"; }
549
+ $log.= PHP_EOL;
550
+ $return = array('request'=>$dreq, 'log'=>$log, 'code'=>$code, 'status'=>true);
551
+ return json_encode($return);
552
+ }
553
  }
 
554
 
555
 
556
+ # else fail
557
+ $log = $printurl;
558
+ if($fvm_debug == true) { $log.= " --- Debug: $printhandle failed. Tried wp_remote_get, curl and local file_get_contents. ---"; }
559
+ $return = array('request'=>$dreq, 'log'=>$log, 'code'=>'', 'status'=>false);
560
+ return json_encode($return);
561
  }
562
 
563
 
638
  }
639
 
640
 
641
+ # remove emoji support
642
+ function fastvelocity_min_disable_wp_emojicons() {
643
+ remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
644
+ remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
645
+ remove_action( 'wp_print_styles', 'print_emoji_styles' );
646
+ remove_action( 'admin_print_styles', 'print_emoji_styles' );
647
+ remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
648
+ remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
649
+ remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
650
+ }
651
 
652
+ # remove from tinymce
653
+ function fastvelocity_disable_emojis_tinymce( $plugins ) {
654
+ if ( is_array( $plugins ) ) {
655
+ return array_diff( $plugins, array( 'wpemoji' ) );
656
+ } else {
657
+ return array();
658
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
659
  }
660
 
661
 
 
 
 
 
 
 
 
662
 
663
  # escape double quotes
664
  function fastvelocity_escape_double($string) {
709
  }
710
 
711
  # enforce protocol if needed
712
+ $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
713
+ if($default_protocol == 'dynamic' || empty($default_protocol)) {
714
+ if ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1)) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) { $default_protocol = 'https://'; } else { $default_protocol = 'http://'; }
715
+ } else {
716
+ $default_protocol = $default_protocol.'://';
717
+ }
718
 
719
  # return
720
+ return $default_protocol.$url;
721
  }
722
 
723
 
724
+ # increment file names
725
+ function fvm_cache_increment() {
 
 
726
  update_option('fvm-last-cache-update', time());
 
 
 
 
 
 
 
 
 
 
 
727
  }
728
 
729
  # purge all caches
738
  return false;
739
  }
740
 
 
741
  fastvelocity_rrmdir($cachebase);
742
+ fvm_cache_increment();
743
  do_action('fvm_after_purge_all');
744
  return true;
745
  }
751
  $tmpdir = $cachepath['tmpdir'];
752
  $f = $tmpdir.'/'.$key.'.transient';
753
  clearstatcache();
754
+ if(file_exists($f)) {
755
  return file_get_contents($f);
756
  } else {
757
  return false;
758
  }
759
  }
760
 
761
+ # set cache on disk
762
+ function fvm_set_transient($key, $code) {
763
  if(is_null($code) || empty($code)) { return false; }
764
  $cachepath = fvm_cachepath();
765
  $tmpdir = $cachepath['tmpdir'];
766
  $f = $tmpdir.'/'.$key.'.transient';
767
+ file_put_contents($f, $code);
768
+ return true;
769
+ }
770
+
771
+
772
+ # generate ascii slug
773
+ function fvm_safename($str, $noname=NULL) {
774
+ $nstr = preg_replace("/[^a-zA-Z0-9]+/", "-", $str);
775
+ $nstr = trim(trim($nstr, '-'));
776
+ if(strlen($nstr) > 1) {
777
+ return $nstr;
 
 
778
  }
779
 
780
+ # return false if no empty name rewrite requested
781
+ if($noname !== NULL) {
782
+ return false;
 
 
783
  }
784
 
785
  # fallback
786
+ return 'noname-'.hash('adler32', $str);
787
  }
788
 
789
 
790
  # exclude processing from some pages / posts / contents
791
  function fastvelocity_exclude_contents() {
792
+
793
+ # exclude processing here
794
+ if (is_admin() || (defined('DOING_AJAX') && DOING_AJAX) || (function_exists('wp_doing_ajax') && wp_doing_ajax()) || (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || (defined('WP_BLOG_ADMIN') && WP_BLOG_ADMIN) || (defined('WP_NETWORK_ADMIN') && WP_NETWORK_ADMIN) || (defined('WP_INSTALLING') && WP_INSTALLING) || (defined('WP_IMPORTING') && WP_IMPORTING) || (defined('WP_REPAIRING') && WP_REPAIRING) || (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) || (defined('SHORTINIT') && SHORTINIT) || (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') ||
795
+ (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') || (isset($_SERVER['REQUEST_URI']) && (substr($_SERVER['REQUEST_URI'], -4) == '.txt' || substr($_SERVER['REQUEST_URI'], -4) == '.xml'))) {
796
+ return true;
797
+ }
798
+
799
+ # customizer preview, visual composer
800
+ $arr = array('customize_theme', 'preview_id', 'preview');
801
+ foreach ($arr as $a) { if(isset($_GET[$a])) { return true; } }
802
 
803
+ # Thrive plugins and other post_types
804
+ $arr = array('tve_form_type', 'tve_lead_shortcode', 'tqb_splash');
805
+ foreach ($arr as $a) { if(isset($_GET['post_type']) && $_GET['post_type'] == $a) { return true; } }
806
+
807
+ # default
808
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
809
  }
810
 
811
  # Know files that should always be ignored
813
  if(is_array($ignore)) {
814
 
815
  # from the database
816
+ $exc = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_ignorelist', '')));
817
 
818
  # should we exclude jquery when defer is enabled?
819
  $exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
838
  function fastvelocity_ie_blacklist($url) {
839
 
840
  # from the database
841
+ $exc = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_blacklist', '')));
842
 
843
  # must have
844
  $exc[] = '/fvm/cache/';
850
 
851
 
852
  # download function with cache support and fallback
853
+ function fastvelocity_download($url) {
 
 
 
 
854
 
855
+ # info (needed for google fonts woff files + hinted fonts) as well as to bypass some security filters
856
  $uagent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';
857
+
858
+ # fetch via wordpress functions
859
+ $response = wp_remote_get($url, array('user-agent'=>$uagent, 'timeout' => 7, 'httpversion' => '1.1', 'sslverify'=>false));
860
+ $res_code = wp_remote_retrieve_response_code($response);
861
+ if($res_code == '200') {
862
+ $data = wp_remote_retrieve_body($response);
863
+ if(strlen($data) > 1) {
864
+ return $data;
 
 
 
 
 
 
 
 
 
 
 
 
 
865
  }
866
+ }
 
 
 
 
867
 
868
+ # fallback, let's try curl if available
869
+ if(function_exists('curl_version')) {
870
+ $curl = fvm_file_get_contents_curl($url, $uagent);
871
+ if(!empty($curl) && strlen($curl) > 1) {
872
+ return $data;
873
+ }
874
+ }
875
+
876
+ # fallback fail
877
+ return false;
878
  }
879
 
880
 
894
 
895
  # wordpress default cache
896
  if (function_exists('wp_cache_flush')) {
897
+ wp_cache_flush();
898
  }
899
 
900
  # Purge all W3 Total Cache
901
  if (function_exists('w3tc_pgcache_flush')) {
902
+ w3tc_pgcache_flush();
903
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>W3 Total Cache</strong> have also been purged.</p></div>');
904
  }
905
 
906
  # Purge WP Super Cache
907
  if (function_exists('wp_cache_clear_cache')) {
908
+ wp_cache_clear_cache();
909
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>WP Super Cache</strong> have also been purged.</p></div>');
910
  }
911
 
912
  # Purge WP Rocket
913
  if (function_exists('rocket_clean_domain')) {
914
+ rocket_clean_domain();
915
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>WP Rocket</strong> have also been purged.</p></div>');
916
  }
917
 
918
  # Purge Wp Fastest Cache
919
  if(isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache')){
920
+ $GLOBALS['wp_fastest_cache']->deleteCache();
921
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>Wp Fastest Cache</strong> have also been purged.</p></div>');
922
  }
923
 
924
  # Purge Cachify
925
  if (function_exists('cachify_flush_cache')) {
926
+ cachify_flush_cache();
927
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>Cachify</strong> have also been purged.</p></div>');
928
  }
929
 
930
  # Purge Comet Cache
931
  if ( class_exists("comet_cache") ) {
932
+ comet_cache::clear();
933
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>Comet Cache</strong> have also been purged.</p></div>');
934
  }
935
 
936
  # Purge Zen Cache
937
  if ( class_exists("zencache") ) {
938
+ zencache::clear();
939
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>Comet Cache</strong> have also been purged.</p></div>');
940
  }
941
 
942
  # Purge LiteSpeed Cache
943
  if (class_exists('LiteSpeed_Cache_Tags')) {
944
+ LiteSpeed_Cache_Tags::add_purge_tag('*');
945
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>LiteSpeed Cache</strong> have also been purged.</p></div>');
946
  }
947
 
948
  # Purge SG Optimizer
949
  if (function_exists('sg_cachepress_purge_cache')) {
950
+ sg_cachepress_purge_cache();
951
+ return __('<div class="notice notice-info is-dismissible"><p>All caches from <strong>SG Optimizer</strong> have also been purged.</p></div>');
952
  }
953
 
954
  # Purge Hyper Cache
955
  if (class_exists( 'HyperCache' )) {
956
+ do_action( 'autoptimize_action_cachepurged' );
957
+ return __( '<div class="notice notice-info is-dismissible"><p>All caches from <strong>HyperCache</strong> have also been purged.</p></div>');
958
  }
959
 
960
  # Purge Godaddy Managed WordPress Hosting (Varnish + APC)
961
  if (class_exists('WPaaS\Plugin')) {
962
+ fastvelocity_godaddy_request('BAN');
963
+ return __('<div class="notice notice-info is-dismissible"><p>A cache purge request has been sent to <strong>Go Daddy Varnish</strong></p></div><div class="notice notice-info is-dismissible"><p>Please note that it may not work 100% of the time, due to cache rate limiting by your host!</p></div>');
964
+ }
965
+
966
+ # purge cache enabler
967
+ if ( has_action('ce_clear_cache') ) {
968
+ do_action('ce_clear_cache');
969
+ return __( '<div class="notice notice-info is-dismissible"><p>All caches from <strong>Cache Enabler</strong> have also been purged.</p></div>');
970
  }
971
 
972
+
973
  # Purge WP Engine
974
  if (class_exists("WpeCommon")) {
975
+ if (method_exists('WpeCommon', 'purge_memcached')) { WpeCommon::purge_memcached(); }
976
+ if (method_exists('WpeCommon', 'clear_maxcdn_cache')) { WpeCommon::clear_maxcdn_cache(); }
977
+ if (method_exists('WpeCommon', 'purge_varnish_cache')) { WpeCommon::purge_varnish_cache(); }
 
978
 
979
+ if (method_exists('WpeCommon', 'purge_memcached') || method_exists('WpeCommon', 'clear_maxcdn_cache') || method_exists('WpeCommon', 'purge_varnish_cache')) {
980
+ return __('<div class="notice notice-info is-dismissible"><p>A cache purge request has been sent to <strong>WP Engine</strong></p></div><div class="notice notice-info is-dismissible"><p>Please note that it may not work 100% of the time, due to cache rate limiting by your host!</p></div>');
981
+ }
982
+ }
983
 
984
  }
985
+
986
+
libs/jar/index.html DELETED
File without changes
libs/jar/yuicompressor-2.4.8.jar DELETED
Binary file
readme.txt CHANGED
@@ -2,19 +2,21 @@
2
  Contributors: Alignak
3
  Tags: PHP Minify, YUI Compressor, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance
4
  Requires at least: 4.5
5
- Stable tag: 2.3.5
6
- Tested up to: 4.9.8
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
10
- Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS, JavaScript and HTML.
11
 
12
 
13
  == Description ==
14
 
15
  This plugin reduces HTTP requests by merging CSS & Javascript files into groups of files, while attempting to use the least amount of files as possible. It minifies CSS and JS files with PHP Minify (no extra requirements).
16
 
17
- Minification is done in real time and done on the frontend only during the first uncached request. Once the first request is processed, any other pages that require the same set of CSS and JavaScript will be served that same static cache file.
 
 
18
 
19
  This plugin includes options for developers and advanced users, however the default settings should work just fine for most sites.
20
 
@@ -26,26 +28,26 @@ I can offer you aditional `custom made` optimization on top of this plugin. If y
26
  = Features =
27
 
28
  * Merge JS and CSS files into groups to reduce the number of HTTP requests
29
- * Google Fonts merging and optimization
30
  * Handles scripts loaded both in the header & footer separately
31
  * Keeps the order of the scripts even if you exclude some files from minification
32
  * Supports localized scripts (https://codex.wordpress.org/Function_Reference/wp_localize_script)
33
  * Minifies CSS and JS with PHP Minify only, no third party software or libraries needed.
34
- * Option to use YUI Compressor rather than PHP Minify (you you have "exec" and "java" available on your system).
35
- * Option to defer JavaScript and CSS files.
36
- * Stores the cache files in the uploads directory.
37
- * View the status and logs on the WordPress admin page.
38
- * Option to Minify HTML for further improvements.
39
- * Ability to turn off minification
40
- * Ability to turn off CSS or JS optimization seperatly (by disabling either css or js processing)
41
- * Ability to manually ignore scripts or css
42
- * Support for conditional scripts and styles
43
- * Support for multisite installations
44
  * Support for gzip_static on Nginx
45
- * Support for the CDN Enabler plugin
46
- * Auto purging of cache files on W3 Total Cache, WP Supercache, WP Rocket, Wp Fastest Cache, Cachify, Comet Cache, Zen Cache, LiteSpeed Cache, Nginx Cache (by Till Krüss ), SG Optimizer, HyperCache, Godaddy Managed WordPress Hosting and WP Engine (read the FAQs)
47
- * WP CLI support
48
  * Support for preconnect and preload headers
 
 
 
49
  * and some more...
50
 
51
 
@@ -74,197 +76,160 @@ I can offer you aditional `custom made` optimization on top of this plugin. If y
74
 
75
  == Screenshots ==
76
 
77
- 1. The status and logs page.
78
- 2. The settings page.
79
- 3. The Advanced settings.
80
-
81
 
82
  == Frequently Asked Questions ==
83
 
84
- = Why is Sucuri saying that there is a "potential" backdoor, or malware on the Server Info page ? =
85
- It’s a false positive, but for a more indepth explanation: https://wordpress.org/support/topic/malware-alert-3/ In addition, note that I have reached out to Sucuri, which confirmed that they are aware of the false positive and are updating their signatures to remove that notice.
86
 
87
- ...
88
 
89
- = How can I exclude certain assets by wildcard? =
90
 
91
- Each line on the ignore list will try to match a substring against all CSS or JS files, for example `//yoursite.com/wp-content/plugins/some-plugin/js/` will ignore all files inside that directory. You can also shorten the URL like `/some-plugin/js/` and then it will match any css or js URL that has `/some-plugin/js/` on the path. Obviously, doing `/js/` would match any files inside any "/js/" directory and in any location, so to avoid unexpected situations please always use the longest, most specific path you can use.
92
 
93
- ...
94
 
95
- = Why is the ignore list not working? =
96
 
97
- The ignore list may be working, just try to use partial paths (see wildcard help above) and use relative urls only without any query vars.
98
 
99
- ...
100
 
 
101
 
102
- = Why are there several or lots of JS and CSS files listed on the status page, or why the cache directory takes so much space? =
103
-
104
- Well, some sites and themes have a combined CSS size above 1+ MB, so when you have 200 files, that's 200+ MB.
105
- Different pages may need different JS and CSS files per page, post, category, tag, homepage or even custom post types, but if the requirements never change and you always load the exact same files on every page, you will not see as many files. Likewise, if you have some dynamic URL for CSS or JS that always changes in each page view (the query var for example), you must add it to the ignore list (else it will generate a new cache file every page view).
106
 
107
- ...
108
 
109
- = Can I update plugins and themes? =
110
 
111
- Yes, but it's recommended that you purge the cache (from the plugin status page) in order for the merging and minification cache files to be regenerated and for you to be sure the updates went smoothly. The plugin will also try to automatically purge some popular cache plugins, however we still recommend that you purge all caches on your cache plugin / server (whatever you use) "after" purging Fast Velocity Minify cache.
112
 
113
- ...
114
 
115
  = Is it compatible with other caching plugins? =
116
 
117
- You must disable any features on your theme or cache plugins, which perform minification of css, html and js.
118
- The plugin will try to automatically purge several popular cache plugins, however we still recommend you to purge all caches (on whatever you use) if you also manually purge the cache on the plugin settings for some reason.
119
- 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, SG Optimizer, Godaddy Managed WordPress Hosting and WP Engine
120
 
121
- ...
122
 
123
  = Is it resource intensive, or will it use too much CPU on my shared hosting plan? =
124
 
125
- No, it's not. On the first run, each single file is minified into an intermediate cache. When a new group of files is found, it reuses those files and merges them into a new static cache file. All pages that request the same group of CSS or JS files will also make use of that file.
126
 
127
- ...
128
 
129
  = Is it compatible with multisites? =
130
 
131
- Yes, it generates a new cache file for every different set of JS and CSS requirements it finds.
132
 
133
- ...
134
-
135
- = Is it compatible with AdSense and other ad networks? =
136
-
137
- The plugin is compatible with any add network but also depends on how you are loading the ads into the site. We only merge and minify css and JavaScript files enqueued in the header and footer that match your own domain name... which would exclude any external ads. If you're using a plugin that uses JS to insert the ads on the page, there could be issues. Please report on the support forum if you found such case.
138
-
139
- ...
140
-
141
- = After installing, why did my site feels slow to load? =
142
-
143
- The cache regeneration happens once per URL or if the included CSS + JS files change. If you need the same set of CSS and JS files in every page, the cache file will only be generated once and reused for all other pages, however if you have a CSS or JS that is generated dynamically and uses a time based query string, (url changes on every page view), you must add it to the ignore list by wildcard.
144
-
145
- ...
146
 
147
  = How do I use the pre-compressed files with gzip_static on Nginx? =
148
 
149
  When we merge and minify the css and js files, we also create a `.gz` file to be used with `gzip_static` on Nginx. You need to enable this feature on your Nginx configuration file if you want to make use of it.
150
 
151
- ...
152
 
153
- = Where is the YUI Compressor option gone? =
154
 
155
- This functionality depends on whether you have exec and java available on your system and PHP can detect it or not. It will be visible on the basic Settings page under the JavaScript Options section and it is available for JS files only.
156
 
157
- ...
158
 
159
  = After installing, why are some images and sliders not working? =
160
 
161
- a) You cannot do double minification, as it will break things, so make sure you have disabled any features on your theme or other plugins, which perform minification of css, html and js files.
162
 
163
- b) Are you trying to use the defer JS or CSS options, without understanding exactly how it works? Be advised that most themes do not work properly with those options on.
164
 
165
- c) The plugin relies on PHP Minify to minify JavaScript and css files, however it is not a perfect library and there are plugins that are already minified and do not output a min.js or min.css name and end up being minified again. Try to disable minification on JS and CSS files and purge the cache.
166
 
167
- d) Sometimes a plugin conflicts with another when merged. Try to disable CSS processing first and see if it works. Try to disable JS processing second and see if it works. Try to disable HTML minification last and see if it works. If one of those work, you know there is a conflict.
168
 
169
- e) If you have a conflict, try to add each CSS and each JS to the ignore list, one by one until you find the one that causes the conflict. If you have no idea of which files to add, check the log file on the status page for a list of files.
170
 
171
- ...
172
 
173
  = Why are some of the CSS and JS files not being merged? =
174
 
175
- The plugin only processes (same domain) JS and CSS files enqueued using the official method outlined here: https://developer.wordpress.org/themes/basics/including-css-javascript/
176
-
177
- Some developers enqueue all files properly but might still "print" conditional tags directly in the header, while they should be following the example as explained on the codex: https://developer.wordpress.org/reference/functions/wp_script_add_data/
178
-
179
- Because "printing CSS and JS tags on the header and footer is evil" (seriously), we cannot capture those files and merge them together.
180
 
181
- There are also specific ways to enqueue files meant to be loaded for IE users only, mobile users, desktop users, printers, etc., else those may be merged together and break things. There is a blacklist and default ignore list on the PRO tab because of this.
182
-
183
- ...
184
-
185
- = How can I load CSS async, get the critical path or why is there a flash of unstyled content when I enable this? =
186
-
187
- This is an advanced option for highly skilled developers. Do not try to fiddle with these settings if you are not one, as it will almost certainly break your site layout and functionality.
188
-
189
- Loading CSS async only works properly and consistently, when you have one single CSS file being generated and your critical path is generic enough to be common on all pages.
190
-
191
- ...
192
 
193
  = How to undo all changes done by the plugin? =
194
 
195
- The plugin itself does not do any "changes" to your site and all original files are untouched. It intercepts the enqueued CSS and JS files, processes and hides them, while enqueuing the newly optimized cached version of those files. As with any plugin, simply disable or uninstall the plugin, purge all caches you may have in use (plugins, server, cloudflare, etc.) and the site will go back to what it was before installing it. The plugin does not delete anything from the database or modify any of your files.
196
 
197
- ...
198
 
199
- = Why is it that even though I have disabled or deleted the plugin, the design is still broken? =
200
 
201
- Some "cheap" or so called "optimized" hosting providers, implement a misconfigured and aggressive cache on their servers, and then are "smart" enough to ignore your multiple cache purge requests if those are too frequent.
202
 
203
- Some providers use a "deploy system", where you upload / replace / delete the files via sftp, but those are not reflected on the live site immediately. This means that in some cases, you can delete your whole WordPress installation via sftp, and the site still works perfectly fine even after purging the cache.
204
-
205
- You may have deleted the physical files from the disk, but that's either just some random storage they gave you and that they sync to the main server every few hours, or it may be the actual live server but with a file cache layer on top of it (so the old code keeps running even though you have deleted the files).
206
-
207
- The only solution is to contact your hosting company and ask them why you have deleted the plugin and purged your cache, but the live site does not reflect the changes.
208
-
209
- Providers well known to have this issue are hostgator and iPage (please report others if you find them).
210
-
211
- ...
212
 
213
  = Why is my Visual Composer or Page Editor not working? =
214
 
215
- Some plugins and themes need to edit the layout and styles on the frontend. When they need to do that, they enqueue several extra js and css files that are caught by this plugin and are merged, when in fact those need to load separately. If you encounter such issue of your page editor not working on the frontend, kindly enable the "Fix Page Editors" and purge your caches.
216
-
217
- This option hides all optimization from logged in users, so it is as if the plugin has been disabled. Not logged in users and search engines, still see the optimized version.
218
-
219
- ...
220
-
221
- = How should I use the "Preload Images" and what is it for? =
222
-
223
- Certain themes and plugins, either load large images or sliders on the homepage. Most of them will also load "above the fold" causing the "Prioritize visible content" or the "Eliminate render-blocking JavaScript and CSS in above-the-fold content" message on pagespeed insights.
224
-
225
- While this may not work when the images are large, you can use the "Preload Images" for the first relevant images that load above the fold, such as the logo or the first image of a slider. Please note however, this is for images that show up in all pages, not just the homepage.
226
-
227
- Do not put too many images here as those are downloaded in high priority and it will slow down the rest of the page load.
228
-
229
- ...
230
 
231
  = What are the recommended cloudflare settings for this plugin? =
232
 
233
- On the "Speed" tab, deselect the Auto Minify for JavaScript, CSS and HTML as well as the Rocket Loader option as there is no benefit of using them with our plugin (we already minify things).
234
 
235
- Those options can also break the design due to double minification or the fact that the Rocket Loader is still experimental (you can read about that on the "Help" link under each selected option on cloudflare).
236
 
237
- ...
238
 
239
- = I have a complaint or I need support right now. Why haven't you replied to my topic on the support forum yet? =
240
 
241
- Before getting angry because you have no answer within a few hours (even with paid plugins, sometimes it takes weeks...), please be informed about how wordpress.org and the plugins directory work.
242
 
243
- The plugins directory is an open source, free service where developers and programmers contribute (on their free time) with plugins that can be downloaded and installed by anyone "at their own risk" and are all released under the GPL license.
244
 
245
- While all plugins have to be approved and reviewed by the WordPress team before being published (for dangerous code, spam, etc.) this does not change the license or add any warranty. All plugins are provided as they are, free of charge and should be used at your own risk (so you should make backups before installing any plugin or performing updates) and it is your sole responsibility if you break your site after installing a plugin from the plugins directory.
246
 
247
- Support is provided by plugin authors on their free time and without warranty of a reply, so you can experience different levels of support level from plugin to plugin. As the author of this plugin I strive to provide support on a daily basis and I can take a look and help you with some issues related with my plugin, but please note that this is done out of my goodwill and in no way I have any legal or moral obligation for doing this. I am also available for hiring if you need custom-made speed optimizations (check my profile links).
248
 
249
- For a full version of the license, please read: https://wordpress.org/about/gpl/
250
 
251
- ...
 
252
 
253
- = Where can I get support or report bugs? =
254
 
255
- You can get support on the official WordPress plugin page at https://wordpress.org/support/plugin/fast-velocity-minify
256
- You can also see my profile and check my links if you wish to hire me for custom speed optimization on WordPress or extra features.
257
 
258
- ...
 
259
 
260
  = How can I donate to the plugin author? =
261
 
262
  If you would like to donate any amount to the plugin author (thank you in advance), you can do it via PayPal at https://goo.gl/vpLrSV
263
 
264
- ...
265
 
266
  == Changelog ==
267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  = 2.3.5 [2018.08.27] =
269
  * added thinkwithgoogle support for the defer for insights option
270
  * added HyperCache support, thanks to @erich_k4wp
2
  Contributors: Alignak
3
  Tags: PHP Minify, YUI Compressor, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance
4
  Requires at least: 4.5
5
+ Stable tag: 2.3.8
6
+ Tested up to: 5.0
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
10
+ Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS, JavaScript and HTML, setting up HTTP preload and preconnect headers, loading CSS async and a few more options.
11
 
12
 
13
  == Description ==
14
 
15
  This plugin reduces HTTP requests by merging CSS & Javascript files into groups of files, while attempting to use the least amount of files as possible. It minifies CSS and JS files with PHP Minify (no extra requirements).
16
 
17
+ There are also options to apply critical CSS and load CSS async, as well as to define HTTP preload and preconnect headers (server push).
18
+
19
+ Minification is done on the frontend during the first uncached request. Once the first request is processed, any other pages that require the same set of CSS and JavaScript files, will be served that same (static) cache file.
20
 
21
  This plugin includes options for developers and advanced users, however the default settings should work just fine for most sites.
22
 
28
  = Features =
29
 
30
  * Merge JS and CSS files into groups to reduce the number of HTTP requests
31
+ * Google Fonts merging, inlining and optimization
32
  * Handles scripts loaded both in the header & footer separately
33
  * Keeps the order of the scripts even if you exclude some files from minification
34
  * Supports localized scripts (https://codex.wordpress.org/Function_Reference/wp_localize_script)
35
  * Minifies CSS and JS with PHP Minify only, no third party software or libraries needed.
36
+ * Option to defer JavaScript and CSS files, either globally or pagespeed insights only.
37
+ * Creates static cache files in the uploads directory.
38
+ * Preserves your original files, by duplicating and copying those files to the uploads directory
39
+ * View the status and detailed logs on the WordPress admin page.
40
+ * Option to Minify HTML, remove extra info from the header and other optimizations.
41
+ * Ability to turn off minification for JS, CSS or HTML (purge the cache to see it)
42
+ * Ability to turn off CSS or JS merging completely (so you can debug which section causes conflicts and exclude the offending files)
43
+ * Ability to manually ignore JavaScript or CSS files that conflict when merged together (please report if you find some)
44
+ * Support for conditional scripts and styles, as well as inlined code that depends on the handles
45
+ * Support for multisite installations (each site has its own settings)
46
  * Support for gzip_static on Nginx
 
 
 
47
  * Support for preconnect and preload headers
48
+ * CDN option, to rewrite all static assets inside the JS or CSS files
49
+ * WP CLI support to check stats and purge the cache
50
+ * Auto purging of cache files for W3 Total Cache, WP Supercache, WP Rocket, Wp Fastest Cache, Cachify, Comet Cache, Zen Cache, LiteSpeed Cache, Nginx Cache (by Till Krüss ), SG Optimizer, HyperCache, Cache Enabler, Godaddy Managed WordPress Hosting and WP Engine (read the FAQs)
51
  * and some more...
52
 
53
 
76
 
77
  == Screenshots ==
78
 
79
+ 1. The Status and Logs page.
80
+ 2. The Settings page.
81
+ 3. The Pro settings.
82
+ 4. The Developers settings.
83
 
84
  == Frequently Asked Questions ==
85
 
86
+ = Can I update plugins and themes after installing FVM? =
 
87
 
88
+ Yes. FVM doesn't touch your original files, it merely copies them to the uploads directory and merges them together with minification. If you install new plugins, update or change themes, FVM will purge its cache as well as some of the most popular cache plugins. It's recommended that you purge your page cache on the server "after" purging Fast Velocity Minify, if you have some cache on the server side.
89
 
90
+ = After installing, why did my site feels slow to load? =
91
 
92
+ Please see the question below.
93
 
 
94
 
95
+ = Why are there lots of JS and CSS files listed on the status page and why is the cache directory taking so much space? =
96
 
97
+ Beware! Some themes combine CSS using PHP with a query string that changes on every pageload... (this is bad practice). When FVM sees a different url being enqueued, it will consider that as a new file and try to create a new set of files on every pageview too. You must exclude that dynamic url via the Ignore List on FVM for your cache to be efficient and stop growing. Also note, if your pages enqueue different styles and javascript in different pages, that is "one set" of files to be merged.
98
 
 
99
 
100
+ = How can I exclude certain assets by wildcard? =
101
 
102
+ Each line on the ignore list will try to match a substring against all CSS or JS files, for example `//yoursite.com/wp-content/plugins/some-plugin/js/` will ignore all files inside that directory. You can also shorten the URL like `/some-plugin/js/` and then it will match any css or js URL that has `/some-plugin/js/` on the path. Obviously, doing `/js/` would match any files inside any "/js/" directory and in any location, so to avoid unexpected situations please always use the longest, most specific path you can use.
 
 
 
103
 
 
104
 
105
+ = Why is the ignore list not working? =
106
 
107
+ The ignore list "is" working, just try to use partial paths (see wildcard help above) and use relative urls only without any query vars.
108
 
 
109
 
110
  = Is it compatible with other caching plugins? =
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
 
117
+ Unless you are not excluding dynamic CSS files that change the url in every pageload, no it is not heavy at all. On the first run, each single file is minified into an intermediate cache. When a new group of CSS/JS files is found on a new page, it reuses those files and merges them into a new static cache file. All pages that request the same group of CSS or JS files will also make use of that file, thus regeneration only happens once ina while.
118
 
 
119
 
120
  = Is it compatible with multisites? =
121
 
122
+ Yes, it generates a new cache file for every different set of JS and CSS requirements it finds, but you must enable and configure FVM settings for each site in your network separatly (no global settings for all sites).
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
  = How do I use the pre-compressed files with gzip_static on Nginx? =
126
 
127
  When we merge and minify the css and js files, we also create a `.gz` file to be used with `gzip_static` on Nginx. You need to enable this feature on your Nginx configuration file if you want to make use of it.
128
 
 
129
 
130
+ = Is it compatible with AdSense and other ad networks? =
131
 
132
+ If you are just insertigng ads on your pages, yes. If you are using a custom script to inject those ads, please double check if it works.
133
 
 
134
 
135
  = After installing, why are some images and sliders not working? =
136
 
137
+ a) You cannot do double minification, so make sure you have disabled any features on your theme or other plugins that perform minification of css, html and js files.
138
 
139
+ b) If you enabled the option to defer JS or CSS, please note that some themes and plugins need jQuery and other libraries to be render blocking, so they are not "undefined" during page load.
140
 
141
+ c) The plugin relies on PHP Minify to minify JavaScript and css files, however it is not a perfect library and there are plugins that are already minified and do not output a "min.js" or "min.css" filename (and end up being minified again). Try to disable minification on JS and CSS files and purge the cache, then either dequeue it and enqueue an alternative file or add it to the ignore list.
142
 
143
+ d) Sometimes a plugin conflicts with another when merged (look at google chrome console log for hints). Try to disable CSS processing first and see if it works. Disable JS processing second and see if it works. Try to disable HTML minification last and see if it works. If one of those work, you know there is a conflict when merging/minifying.
144
 
145
+ e) If you have a conflict, try to add each CSS and each JS file to the ignore list one by one, until you find the one that causes the conflict. If you have no idea of which files to add, check the log file on the "status page" for a list of files being merged into each generated file.
146
 
 
147
 
148
  = Why are some of the CSS and JS files not being merged? =
149
 
150
+ The plugin only processes JS and CSS files enqueued using the official WordPress api method - https://developer.wordpress.org/themes/basics/including-css-javascript/ -as well as files from the same domain (unless specified on the settings).
 
 
 
 
151
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
  = How to undo all changes done by the plugin? =
154
 
155
+ The plugin itself does not do any "changes" to your site and all original files are untouched. It intercepts the enqueued CSS and JS files just before printing your HTML, copies them and enqueues the newly optimized cached version of those files to the frontend. As with any plugin... simply disable or uninstall the plugin, purge all caches you may have in use (plugins, server, cloudflare, etc.) and the site will go back to what it was before installing it. The plugin does not delete anything from the database or modify any of your files.
156
 
 
157
 
158
+ = I have disabled or deleted the plugin but my design is still broken! =
159
 
160
+ Some "cheap" (or sometimes expensive) "optimized" hosting providers, implement a (misconfigured) aggressive cache on their servers that caches PHP code execution and PHP files. I've seen people completely deleting all WordPress files from their host via SFTP/FTP and the website kept working fine for hours. Furthermore, very often they rate limit your cache purge requests... so if you delete FVM and are still seeing references to FVM files on the "view-source:https://example.com" please be patient and contact your web hosting to purge all caches. Providers known to have this issue are some plans on hostgator and iPage (please report others if you find them).
161
 
 
 
 
 
 
 
 
 
 
162
 
163
  = Why is my Visual Composer or Page Editor not working? =
164
 
165
+ Some plugins and themes need to edit the layout and styles on the frontend. If you have trouble with page editors, please enable the "Fix Page Editors" option on FVM and purge your caches. Note: You will only see the FVM minification working when you're logged out or using another browser after this setting.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
  = What are the recommended cloudflare settings for this plugin? =
168
 
169
+ On the "Speed" tab, deselect the Auto Minify for JavaScript, CSS and HTML as well as the Rocket Loader option as there is no benefit of using them with our plugin (we already minify things). Those options can also break the design due to double minification or the fact that the Rocket Loader is still experimental (you can read about that on the "Help" link under each selected option on cloudflare).
170
 
 
171
 
172
+ = How can I load CSS async? =
173
 
174
+ You are probably a developer if you are trying this. The answer is: make sure FVM is only generating 1 CSS file, because "async" means multiple files will load out of order (but CSS needs order most of the times). If FVM is generating more than 1 CSS file, try to manually dequeue some of the CSS files that are breaking the series on FVM (such as external enqueued files), or add their domain to the settings to be merged together. Please note... this is an advanced option for highly skilled developers. Do not try to fiddle with these settings if you are not one, as it will almost certainly break your site layout and functionality.
175
 
 
176
 
177
+ = I have a complaint or I need support right now. =
178
 
179
+ Before getting angry because you have no answer within a few hours (even with paid plugins, sometimes it takes weeks...), please be informed about how wordpress.org and the plugins directory work. The plugins directory is an open source, free service where developers and programmers contribute (on their free time) with plugins that can be downloaded and installed by anyone "at their own risk" and are all released under the GPL license. While all plugins have to be approved and reviewed by the WordPress team before being published (for dangerous code, spam, etc.) this does not change the license or add any warranty. All plugins are provided as they are, free of charge and should be used at your own risk (so you should make backups before installing any plugin or performing updates) and it is your sole responsibility if you break your site after installing a plugin from the plugins directory. For a full version of the license, please read: https://wordpress.org/about/gpl/
180
 
181
+ = Why haven't you replied to my topic on the support forum yet? =
182
 
183
+ Support is provided by plugin authors on their free time and without warranty of a reply, so you can experience different levels of support level from plugin to plugin. As the author of this plugin I strive to provide support on a daily basis and I can take a look and help you with some issues related with my plugin, but please note that this is done out of my goodwill and in no way I have any legal or moral obligation for doing this. Sometimes I am extremely busy and may take a few days to reply, but I will always reply.
184
 
185
+ = But I really need fast support right now, is there any other way? =
186
+ I am also available for hiring if you need custom-made speed optimizations. After you have isntalled the plugin, check the "Help" tab for contact information, or check my profile links here on WordPress.
187
 
 
188
 
189
+ = Where can I report bugs? =
 
190
 
191
+ You can get support on the official WordPress plugin page at https://wordpress.org/support/plugin/fast-velocity-minify
192
+ Alternatively, you can reach me via info (at) fastvelocity.com for security or other vulnerabilities.
193
 
194
  = How can I donate to the plugin author? =
195
 
196
  If you would like to donate any amount to the plugin author (thank you in advance), you can do it via PayPal at https://goo.gl/vpLrSV
197
 
198
+
199
 
200
  == Changelog ==
201
 
202
+ = 2.4.0 [2018.11.26] =
203
+ * bug fixes related to the inline css option
204
+ * changed a few options and added better descriptions to the admin options
205
+
206
+ = 2.3.9 [2018.11.24] =
207
+ * there was an error on my end while pushing 2.3.8... this is a version bump
208
+
209
+ = 2.3.8 [2018.11.24] =
210
+ * removed the dynamic protocol in favour of auto detecting HTTP(s)
211
+ * fixed a bug where some CSS files were being removed with the latest CSS inline method
212
+ * fixed a bug where the wrong file path was being generated for fonts and some static assets (when the plugin or theme, uses relative paths and the Inline CSS option is enabled)
213
+
214
+ = 2.3.7 [2018.11.24] =
215
+ * bug fixes and performance improvements
216
+ * changed a few "options" location to other tabs
217
+ * changed the "Inline CSS" method to inline each file right separatly, instead of merging it and then inline it (also improves compatibility)
218
+ * added option to exclude JS and CSS files from PSI separatly (will load them Async, so make sure to read the instructions for each)
219
+ * added a dedicated Critical Path CSS for "is_front_page" (more conditionals on the roadmap)
220
+ * renamed some labels to be more explicit regardless of what they do
221
+
222
+ = 2.3.6 [2018.11.20] =
223
+ * added better header preloader and preconnect headers for css and js files
224
+ * added support to automatically purge the cache enabler plugin
225
+ * added option to reload the cache, while preserving the old static files
226
+ * added better default options after first install
227
+ * added and reorganized some options
228
+ * added a new developers tab
229
+ * removed the YUI compressor option (defaults to PHP Minify)
230
+ * readme and screenshots update
231
+ * tested up to WP 5.0 tag
232
+
233
  = 2.3.5 [2018.08.27] =
234
  * added thinkwithgoogle support for the defer for insights option
235
  * added HyperCache support, thanks to @erich_k4wp