Fast Velocity Minify - Version 2.8.5

Version Description

[2020.04.30] = * bug fixes and some more minification default exclusions

Download this release

Release Info

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

Code changes from version 2.8.4 to 2.8.5

Files changed (5) hide show
  1. fvm.php +3052 -3023
  2. inc/functions-cache.php +3 -2
  3. inc/functions-upgrade.php +5 -13
  4. inc/functions.php +4 -4
  5. readme.txt +4 -1
fvm.php CHANGED
@@ -1,3023 +1,3052 @@
1
- <?php
2
- /*
3
- Plugin Name: Fast Velocity Minify
4
- Plugin URI: http://fastvelocity.com
5
- Description: Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS and JavaScript files into groups, compressing HTML and other speed optimizations.
6
- Author: Raul Peixoto
7
- Author URI: http://fastvelocity.com
8
- Version: 2.8.4
9
- License: GPL2
10
-
11
- ------------------------------------------------------------------------
12
- This program is free software; you can redistribute it and/or modify
13
- it under the terms of the GNU General Public License as published by
14
- the Free Software Foundation; either version 2 of the License, or
15
- (at your option) any later version.
16
-
17
- This program is distributed in the hope that it will be useful,
18
- but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
- GNU General Public License for more details.
21
-
22
- You should have received a copy of the GNU General Public License
23
- along with this program; if not, write to the Free Software
24
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
- */
26
-
27
- # check for minimum requirements and prevent activation or disable if not fully compatible
28
- function fvm_compat_checker() {
29
- global $wp_version;
30
-
31
- # defaults
32
- $error = '';
33
-
34
- # php version requirements
35
- if (version_compare( PHP_VERSION, '5.5', '<' )) {
36
- $error = 'Fast Velocity Minify requires PHP 5.5 or higher. You’re still on '. PHP_VERSION;
37
- }
38
-
39
- # php extension requirements
40
- if (!extension_loaded('mbstring')) {
41
- $error = 'Fast Velocity Minify requires the PHP mbstring module to be installed on the server.';
42
- }
43
-
44
- # wp version requirements
45
- if ( version_compare( $GLOBALS['wp_version'], '4.5', '<' ) ) {
46
- $error = 'Fast Velocity Minify requires WP 4.5 or higher. You’re still on ' . $GLOBALS['wp_version'];
47
- }
48
-
49
- if ((is_plugin_active(plugin_basename( __FILE__ )) && !empty($error)) || !empty($error)) {
50
- if (isset($_GET['activate'])) { unset($_GET['activate']); }
51
- deactivate_plugins( plugin_basename( __FILE__ ));
52
- add_action('admin_notices', function() use ($error){
53
- echo '<div class="notice notice-error is-dismissible"><p><strong>'.$error.'</strong></p></div>';
54
- });
55
- }
56
- }
57
- add_action('admin_init', 'fvm_compat_checker');
58
-
59
-
60
- # get plugin version
61
- $fastvelocity_plugin_version_get_data = get_file_data(__FILE__, array('Version' => 'Version'), false);
62
- $fastvelocity_plugin_version = $fastvelocity_plugin_version_get_data['Version'];
63
-
64
- # get the plugin directory
65
- $plugindir = plugin_dir_path( __FILE__ ); # prints with trailing slash
66
-
67
- # reusable functions
68
- include($plugindir.'inc/functions.php');
69
- include($plugindir.'inc/functions-serverinfo.php');
70
- include($plugindir.'inc/functions-upgrade.php');
71
- include($plugindir.'inc/functions-cache.php');
72
-
73
- # wp-cli support
74
- if ( defined( 'WP_CLI' ) && WP_CLI ) {
75
- include($plugindir.'inc/functions-cli.php');
76
- }
77
-
78
-
79
- # get cache directories and urls
80
- $cachepath = fvm_cachepath();
81
- $tmpdir = $cachepath['tmpdir'];
82
- $cachedir = $cachepath['cachedir'];
83
- $cachedirurl = $cachepath['cachedirurl'];
84
-
85
- $wp_home = site_url(); # get the current wordpress installation url
86
- $wp_domain = trim(str_ireplace(array('http://', 'https://'), '', trim($wp_home, '/')));
87
- $wp_home_path = ABSPATH;
88
-
89
- # default globals
90
- $fastvelocity_min_global_js_done = array();
91
- $fvm_collect_google_fonts = array();
92
- $collect_preload_css = array();
93
- $collect_preload_js = array();
94
- $fvm_debug = get_option('fastvelocity_fvm_debug');
95
-
96
- ###########################################
97
- # build control panel pages ###############
98
- ###########################################
99
-
100
- # options from the database, false if not set
101
- $ignore = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_ignore', ''))));
102
- $blacklist = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_blacklist', ''))));
103
- $ignorelist = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_ignorelist', ''))));
104
- $fvm_min_excludecsslist = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_excludecsslist', ''))));
105
- $fvm_min_excludejslist = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_excludejslist', ''))));
106
-
107
- $fvm_enable_purgemenu = get_option('fastvelocity_min_enable_purgemenu');
108
- $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
109
- $disable_js_merge = get_option('fastvelocity_min_disable_js_merge');
110
- $disable_css_merge = get_option('fastvelocity_min_disable_css_merge');
111
- $disable_js_minification = get_option('fastvelocity_min_disable_js_minification');
112
- $disable_css_minification = get_option('fastvelocity_min_disable_css_minification');
113
- $remove_print_mediatypes = get_option('fastvelocity_min_remove_print_mediatypes');
114
- $skip_html_minification = get_option('fastvelocity_min_skip_html_minification');
115
- $strip_htmlcomments = get_option('fastvelocity_min_strip_htmlcomments');
116
- $skip_cssorder = get_option('fastvelocity_min_skip_cssorder');
117
- $skip_google_fonts = get_option('fastvelocity_min_skip_google_fonts');
118
- $skip_emoji_removal = get_option('fastvelocity_min_skip_emoji_removal');
119
- $fvm_clean_header_one = get_option('fastvelocity_fvm_clean_header_one');
120
- $enable_defer_js = get_option('fastvelocity_min_enable_defer_js');
121
- $exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
122
- $force_inline_css = get_option('fastvelocity_min_force_inline_css');
123
- $force_inline_css_footer = get_option('fastvelocity_min_force_inline_css_footer');
124
- $remove_googlefonts = get_option('fastvelocity_min_remove_googlefonts');
125
- $defer_for_pagespeed = get_option('fastvelocity_min_defer_for_pagespeed');
126
- $defer_for_pagespeed_optimize = get_option('fastvelocity_min_defer_for_pagespeed_optimize');
127
- $exclude_defer_login = get_option('fastvelocity_min_exclude_defer_login');
128
- $skip_defer_lists = get_option('fastvelocity_min_skip_defer_lists');
129
- $fvm_fix_editor = get_option('fastvelocity_min_fvm_fix_editor');
130
- $fvmloadcss = get_option('fastvelocity_min_loadcss');
131
- $fvm_remove_css = get_option('fastvelocity_min_fvm_removecss');
132
- $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
133
- $fvm_enabled_css_preload = get_option('fastvelocity_enabled_css_preload');
134
- $fvm_enabled_js_preload = get_option('fastvelocity_enabled_css_preload');
135
- $fvm_fawesome_method = get_option("fastvelocity_fontawesome_method");
136
-
137
- # default options
138
- $used_css_files = array();
139
- $force_inline_googlefonts = true;
140
- $min_async_googlefonts = false;
141
- $css_hide_googlefonts = false;
142
-
143
-
144
- # define google fonts options based on a radio form
145
- $fvm_gfonts_method = get_option("fastvelocity_gfonts_method");
146
- if($fvm_gfonts_method != false) {
147
- if($fvm_gfonts_method == 2) { # load Async
148
- $force_inline_googlefonts = false;
149
- $min_async_googlefonts = true;
150
- $css_hide_googlefonts = false;
151
- }
152
- if($fvm_gfonts_method == 3) { # hide from PSI
153
- $force_inline_googlefonts = false;
154
- $min_async_googlefonts = false;
155
- $css_hide_googlefonts = true;
156
- }
157
- }
158
-
159
-
160
- # default ua list
161
- $fvmualist = array('x11.*fox\/54', 'oid\s4.*xus.*ome\/62', 'oobot', 'ighth', 'tmetr', 'eadles', 'ingdo');
162
-
163
- # header and footer markers
164
- add_action('wp_head','fastvelocity_add_fvmuag', -PHP_INT_MAX);
165
- function fastvelocity_add_fvmuag() {
166
- global $fvmualist;
167
- if(!fastvelocity_exclude_contents() || fastvelocity_load_fvuag()) {
168
- echo '<script>'.fastvelocity_get_fvmuag($fvmualist).'</script>';
169
- }
170
- }
171
-
172
- # generate fvmuag js function
173
- function fastvelocity_get_fvmuag($fvmualist) {
174
- return 'function fvmuag(){if(navigator.userAgent.match(/'.implode('|', $fvmualist).'/i))return!1;if(navigator.userAgent.match(/x11.*ome\/75\.0\.3770\.100/i)){var e=screen.width,t=screen.height;if("number"==typeof e&&"number"==typeof t&&862==t&&1367==e)return!1}return!0}';
175
- }
176
-
177
-
178
-
179
- # add admin page and rewrite defaults
180
- if(is_admin()) {
181
- add_action('admin_menu', 'fastvelocity_min_admin_menu');
182
- add_action('admin_enqueue_scripts', 'fastvelocity_min_load_admin_jscss');
183
- add_action('wp_ajax_fastvelocity_min_files', 'fastvelocity_min_files_callback');
184
- add_action('admin_init', 'fastvelocity_min_register_settings');
185
-
186
- # This function runs when WordPress updates or installs/remove something
187
- add_action('upgrader_process_complete', 'fastvelocity_purge_all_global');
188
- add_action('after_switch_theme', 'fastvelocity_purge_all_global');
189
- add_action('admin_init', 'fastvelocity_purge_onsave', 1);
190
-
191
- # activation, deactivation
192
- register_activation_hook( __FILE__, 'fastvelocity_plugin_activate' );
193
- register_deactivation_hook( __FILE__, 'fastvelocity_plugin_deactivate');
194
- register_uninstall_hook( __FILE__, 'fastvelocity_plugin_uninstall');
195
-
196
- } else {
197
- add_action('setup_theme', 'fastvelocity_process_frontend' );
198
- }
199
-
200
- function fastvelocity_process_frontend() {
201
- global $disable_js_merge, $disable_css_merge, $force_inline_css, $skip_emoji_removal, $fvm_clean_header_one, $skip_html_minification, $fvmloadcss, $fvm_fawesome_method, $fvm_gfonts_method;
202
-
203
- # skip on certain post_types or if there are specific keys on the url or if editor or admin
204
- if(!fastvelocity_exclude_contents()) {
205
-
206
- # actions for frontend only
207
- if(!$disable_js_merge) {
208
- add_action( 'wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
209
- add_action( 'wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
210
- }
211
- if(!$disable_css_merge) {
212
- add_action('wp_head', 'fvm_add_criticial_path', 2);
213
-
214
- # merge, if inline is not selected
215
- if($force_inline_css != true) {
216
- add_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
217
- add_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
218
- } else {
219
- add_filter('style_loader_tag', 'fastvelocity_optimizecss', PHP_INT_MAX, 4 );
220
- add_action('wp_print_styles','fastvelocity_add_google_fonts_merged', PHP_INT_MAX);
221
- add_action('wp_print_footer_scripts','fastvelocity_add_google_fonts_merged', PHP_INT_MAX );
222
- }
223
-
224
- }
225
- if(!$skip_emoji_removal) {
226
- add_action( 'init', 'fastvelocity_min_disable_wp_emojicons' );
227
- add_filter( 'tiny_mce_plugins', 'fastvelocity_disable_emojis_tinymce' );
228
- }
229
-
230
- if($fvm_clean_header_one) {
231
- # no resource hints, generator tag, shortlinks, manifest link, etc
232
- remove_action('wp_head', 'wp_resource_hints', 2);
233
- remove_action('wp_head', 'wp_generator');
234
- remove_action('template_redirect', 'wp_shortlink_header', 11);
235
- remove_action('wp_head', 'wlwmanifest_link');
236
- remove_action('wp_head', 'rsd_link');
237
- remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);
238
- remove_action('wp_head','feed_links', 2);
239
- remove_action('wp_head','feed_links_extra', 3);
240
- add_filter('after_setup_theme', 'fastvelocity_remove_redundant_shortlink');
241
- }
242
-
243
- # enable html minification
244
- if(!$skip_html_minification && !is_admin()) {
245
- add_action('template_redirect', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
246
- }
247
-
248
- # add the LoadCSS polyfil
249
- if($fvmloadcss || $fvm_fawesome_method == 2 || $fvm_gfonts_method == 2) {
250
- add_action('wp_footer', 'fvm_add_loadcss', PHP_INT_MAX);
251
- }
252
-
253
- # add the LoadAsync JavaScript function
254
- add_action('wp_head', 'fvm_add_loadasync', 0);
255
-
256
- # remove query from static assets and process defering (if enabled)
257
- add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
258
- add_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
259
-
260
- # headers
261
- add_action( 'send_headers', 'fvm_extra_preload_headers' );
262
- add_action( 'wp_footer', 'fastvelocity_generate_preload_headers', PHP_INT_MAX);
263
- add_filter( 'script_loader_tag', 'fastvelocity_collect_js_preload_headers', PHP_INT_MAX, 3 );
264
-
265
- }
266
- }
267
-
268
- # exclude processing for editors and administrators (fix editors)
269
- add_action( 'plugins_loaded', 'fastvelocity_fix_editor' );
270
- function fastvelocity_fix_editor() {
271
- global $fvm_fix_editor;
272
- if($fvm_fix_editor == true && is_user_logged_in()) {
273
- remove_action('setup_theme', 'fastvelocity_process_frontend' );
274
- }
275
- }
276
-
277
- # create admin menu
278
- function fastvelocity_min_admin_menu() {
279
- add_options_page('Fast Velocity Minify Settings', 'Fast Velocity Minify', 'manage_options', 'fastvelocity-min', 'fastvelocity_min_settings');
280
- }
281
-
282
-
283
- # add admin toolbar
284
- if($fvm_enable_purgemenu == true) {
285
- add_action( 'admin_bar_menu', 'fastvelocity_admintoolbar', 100 );
286
- }
287
-
288
- # admin toolbar processing
289
- function fastvelocity_admintoolbar() {
290
- if(current_user_can('manage_options')) {
291
- global $wp_admin_bar;
292
-
293
- # Create or add new items into the Admin Toolbar.
294
- $wp_admin_bar->add_node(array(
295
- 'id' => 'fvm',
296
- 'title' => '<span class="ab-icon"></span><span class="ab-label">' . __("FVM Purge",'fvm') . '</span>',
297
- 'href' => wp_nonce_url( add_query_arg('_fvmcache', 'clear'), 'fvm_clear_nonce')
298
- ));
299
-
300
- }
301
- }
302
-
303
-
304
- # function to list all cache files
305
- function fastvelocity_min_files_callback() {
306
-
307
- # must be able to cleanup cache
308
- if (!current_user_can('manage_options')) {
309
- wp_die( __('You do not have sufficient permissions to access this page.'));
310
- }
311
-
312
- global $cachedir;
313
-
314
- # default
315
- $size = fastvelocity_get_cachestats();
316
- $return = array('js' => array(), 'css' => array(), 'cachesize'=> $size);
317
-
318
- # inspect directory with opendir, since glob might not be available in some systems
319
- clearstatcache();
320
- if ($handle = opendir($cachedir.fastvelocity_get_os_slash())) {
321
- while (false !== ($file = readdir($handle))) {
322
- $file = $cachedir.fastvelocity_get_os_slash().$file;
323
- $ext = pathinfo($file, PATHINFO_EXTENSION);
324
- if (in_array($ext, array('js', 'css'))) {
325
- $log = ''; if (file_exists($file.'.txt')) { $log = file_get_contents($file.'.txt'); }
326
- $mincss = substr($file, 0, -4).'.min.css';
327
- $minjs = substr($file, 0, -3).'.min.js';
328
- $filename = basename($file);
329
- if ($ext == 'css' && file_exists($mincss)) { $filename = basename($mincss); }
330
- if ($ext == 'js' && file_exists($minjs)) { $filename = basename($minjs); }
331
- $fsize = fastvelocity_format_filesize(filesize($file));
332
- $uid = hash('sha1', $filename);
333
- array_push($return[$ext], array('uid'=>$uid, 'filename' => $filename, 'log' => $log, 'fsize' => $fsize));
334
- }
335
- }
336
- closedir($handle);
337
- }
338
-
339
- header('Content-Type: application/json');
340
- echo json_encode($return);
341
- wp_die();
342
- }
343
-
344
-
345
- # load wp-admin css and js files
346
- function fastvelocity_min_load_admin_jscss($hook) {
347
- if ('settings_page_fastvelocity-min' != $hook) { return; }
348
- wp_enqueue_script('postbox');
349
- wp_enqueue_style('fastvelocity-min', plugins_url('fvm.css', __FILE__), array(), filemtime(plugin_dir_path( __FILE__).'fvm.css'));
350
- wp_enqueue_script('fastvelocity-min', plugins_url('fvm.js', __FILE__), array('jquery'), filemtime(plugin_dir_path( __FILE__).'fvm.js'), true);
351
- }
352
-
353
-
354
- # register plugin settings
355
- function fastvelocity_min_register_settings() {
356
- register_setting('fvm-group', 'fastvelocity_min_enable_purgemenu');
357
- register_setting('fvm-group', 'fastvelocity_preserve_settings_on_uninstall');
358
- register_setting('fvm-group', 'fastvelocity_min_default_protocol');
359
- register_setting('fvm-group', 'fastvelocity_min_disable_js_merge');
360
- register_setting('fvm-group', 'fastvelocity_min_disable_css_merge');
361
- register_setting('fvm-group', 'fastvelocity_min_disable_js_minification');
362
- register_setting('fvm-group', 'fastvelocity_min_disable_css_minification');
363
- register_setting('fvm-group', 'fastvelocity_min_remove_print_mediatypes');
364
- register_setting('fvm-group', 'fastvelocity_min_skip_html_minification');
365
- register_setting('fvm-group', 'fastvelocity_min_strip_htmlcomments');
366
- register_setting('fvm-group', 'fastvelocity_min_skip_cssorder');
367
- register_setting('fvm-group', 'fastvelocity_min_skip_google_fonts');
368
- register_setting('fvm-group', 'fastvelocity_min_skip_fontawesome_fonts');
369
- register_setting('fvm-group', 'fastvelocity_min_skip_emoji_removal');
370
- register_setting('fvm-group', 'fastvelocity_fvm_clean_header_one');
371
- register_setting('fvm-group', 'fastvelocity_min_enable_defer_js');
372
- register_setting('fvm-group', 'fastvelocity_min_exclude_defer_jquery');
373
- register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
374
- register_setting('fvm-group', 'fastvelocity_min_force_inline_css_footer');
375
- register_setting('fvm-group', 'fastvelocity_min_remove_googlefonts');
376
- register_setting('fvm-group', 'fastvelocity_gfonts_method');
377
- register_setting('fvm-group', 'fastvelocity_fontawesome_method');
378
- register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
379
- register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed_optimize');
380
- register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
381
- register_setting('fvm-group', 'fastvelocity_min_skip_defer_lists');
382
- register_setting('fvm-group', 'fastvelocity_min_fvm_fix_editor');
383
- register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_url');
384
- register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_force');
385
- register_setting('fvm-group', 'fastvelocity_min_change_cache_base_url');
386
- register_setting('fvm-group', 'fastvelocity_min_change_cache_path');
387
-
388
- # pro tab
389
- register_setting('fvm-group-pro', 'fastvelocity_min_ignore');
390
- register_setting('fvm-group-pro', 'fastvelocity_min_ignorelist');
391
- register_setting('fvm-group-pro', 'fastvelocity_min_excludecsslist');
392
- register_setting('fvm-group-pro', 'fastvelocity_min_excludejslist');
393
- register_setting('fvm-group-pro', 'fastvelocity_min_blacklist');
394
- register_setting('fvm-group-pro', 'fastvelocity_min_merge_allowed_urls');
395
-
396
- # dev tab
397
- register_setting('fvm-group-dev', 'fastvelocity_fvm_debug');
398
- register_setting('fvm-group-dev', 'fastvelocity_enabled_css_preload');
399
- register_setting('fvm-group-dev', 'fastvelocity_enabled_js_preload');
400
- register_setting('fvm-group-dev', 'fastvelocity_min_hpreload');
401
- register_setting('fvm-group-dev', 'fastvelocity_min_hpreconnect');
402
- register_setting('fvm-group-dev', 'fastvelocity_min_loadcss');
403
- register_setting('fvm-group-dev', 'fastvelocity_min_fvm_removecss');
404
- register_setting('fvm-group-dev', 'fastvelocity_min_critical_path_css');
405
- register_setting('fvm-group-dev', 'fastvelocity_min_critical_path_css_is_front_page');
406
-
407
-
408
-
409
- }
410
-
411
-
412
-
413
- # add settings link on plugin page
414
- function fastvelocity_min_settings_link($links) {
415
- if (is_plugin_active(plugin_basename( __FILE__ ))) {
416
- $settings_link = '<a href="options-general.php?page=fastvelocity-min&tab=set">Settings</a>';
417
- array_unshift($links, $settings_link);
418
- }
419
- return $links;
420
- }
421
- add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
422
-
423
-
424
- # purge all caches by request
425
- add_action('init','fastvelocity_process_cache_purge_request');
426
- function fastvelocity_process_cache_purge_request(){
427
- if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['_fvmcache'])) {
428
-
429
- # must be able to cleanup cache
430
- if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
431
-
432
- # validate nonce
433
- if(empty($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'fvm_clear_nonce')) {
434
- wp_die( __('Invalid or expired request... please go back and refresh before trying again!'));
435
- }
436
-
437
- if(is_admin()) {
438
- fvm_purge_all(); # purge all
439
- $others = fvm_purge_others(); # purge third party caches
440
- $notice = array('All caches from <strong>FVM</strong> have been purged!', strip_tags($others, '<strong>'));
441
- $notice = array_filter($notice);
442
- $notice = json_encode($notice); # encode
443
- set_transient( 'wordpress_fvmcache', $notice, 10);
444
- wp_safe_redirect(remove_query_arg('_wpnonce', remove_query_arg('_fvmcache', wp_get_referer())));
445
- } else {
446
- fvm_purge_all(); # purge all
447
- fvm_purge_others(); # purge third party caches
448
- wp_safe_redirect(remove_query_arg('_wpnonce', remove_query_arg('_fvmcache', wp_get_referer())));
449
- }
450
- }
451
- }
452
-
453
- # print admin notices after purging caches, if on wp-admin
454
- add_action( 'admin_notices', 'fastvelocity_cachepurge_admin_notices' );
455
- function fastvelocity_cachepurge_admin_notices() {
456
-
457
- # skip on submit
458
- if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['_fvmcache'])) {
459
- return true;
460
- }
461
-
462
- # cache purge notices
463
- $inf = get_transient('wordpress_fvmcache');
464
- if($inf != false && !empty($inf)) {
465
-
466
- # decode to array or null
467
- $jsonarr = json_decode($inf, true);
468
- if(!is_null($jsonarr) && is_array($jsonarr)){
469
-
470
- # print notices
471
- foreach ($jsonarr as $notice) {
472
- echo __('<div class="notice notice-success is-dismissible"><p>'.$notice.'</p></div>');
473
- }
474
- }
475
-
476
- # remove
477
- delete_transient('wordpress_fvmcache');
478
- }
479
- }
480
-
481
-
482
- # print admin notices if we don't have enough file permissions to write
483
- add_action( 'admin_notices', 'fastvelocity_check_permissions_admin_notices' );
484
- function fastvelocity_check_permissions_admin_notices() {
485
-
486
- # get cache path
487
- $cachepath = fvm_cachepath();
488
- $cachebase = $cachepath['cachebase'];
489
- if(is_dir($cachebase) && !is_writable($cachebase)) {
490
- $chmod = substr(sprintf('%o', fileperms($cachebase)), -4);
491
- echo __('<div class="notice notice-error is-dismissible"><p>FVM needs writting permissions on '.$cachebase.'</p></div>');
492
- echo __('<div class="notice notice-error is-dismissible"><p>The current permissions for FVM are chmod '.$chmod.'</p></div>');
493
- echo __('<div class="notice notice-error is-dismissible"><p>If you need something higher than 755 for it to work, your server is probaly misconfigured. Please contact your hosting provider or check the help section for other providers.</p></div>');
494
- }
495
-
496
- }
497
-
498
-
499
- # manage settings page
500
- function fastvelocity_min_settings() {
501
- if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
502
-
503
- # tmp folder
504
- global $tmpdir, $cachedir, $plugindir;
505
-
506
- # get active tab, set default
507
- $active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'status';
508
-
509
- ?>
510
- <div class="wrap">
511
- <h1>Fast Velocity Minify</h1>
512
-
513
- <h2 class="nav-tab-wrapper wp-clearfix">
514
- <a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
515
- <a href="?page=fastvelocity-min&tab=set" class="nav-tab <?php echo $active_tab == 'set' ? 'nav-tab-active' : ''; ?>">Settings</a>
516
- <a href="?page=fastvelocity-min&tab=pro" class="nav-tab <?php echo $active_tab == 'pro' ? 'nav-tab-active' : ''; ?>">Pro</a>
517
- <a href="?page=fastvelocity-min&tab=dev" class="nav-tab <?php echo $active_tab == 'dev' ? 'nav-tab-active' : ''; ?>">Developers</a>
518
- <a href="?page=fastvelocity-min&tab=server" class="nav-tab <?php echo $active_tab == 'server' ? 'nav-tab-active' : ''; ?>">Server Info</a>
519
- <a href="?page=fastvelocity-min&tab=help" class="nav-tab <?php echo $active_tab == 'help' ? 'nav-tab-active' : ''; ?>">Help</a>
520
- </h2>
521
-
522
-
523
- <?php if( $active_tab == 'status' ) { ?>
524
-
525
- <div id="fastvelocity-min">
526
- <div id="poststuff">
527
- <div id="fastvelocity_min_processed" class="postbox-container">
528
- <div class="meta-box">
529
-
530
- <div class="postbox" id="tab-purge">
531
- <h3 class="hndle"><span>Purge the cache files </span></h3>
532
- <div class="inside" id="fastvelocity_min_topbtns">
533
- <ul class="processed">
534
- <li id="purgeall-row">
535
- <span class="filename">Purge FVM cache (<span id="fvm_cache_size"><?php echo fastvelocity_get_cachestats(); ?></span>)</span>
536
- <span class="actions">
537
- <form method="post" id="fastvelocity_min_clearall" action="<?php echo wp_nonce_url( add_query_arg('_fvmcache', 'clear'), 'fvm_clear_nonce'); ?>">
538
- <input type="hidden" name="purgeall" value="1" />
539
- <?php submit_button('Delete', 'button-secondary', 'submit', false); ?>
540
- </form>
541
- </li>
542
- </ul>
543
- </div>
544
- </div>
545
-
546
- <div class="postbox" id="tab-js">
547
- <h3 class="hndle"><span>List of processed JS files</span></h3>
548
- <div class="inside" id="fastvelocity_min_jsprocessed">
549
- <ul class="processed"></ul>
550
- </div>
551
- </div>
552
-
553
- <div class="postbox" id="tab-css">
554
- <h3 class="hndle"><span>List of processed CSS files</span></h3>
555
- <div class="inside" id="fastvelocity_min_cssprocessed">
556
- <?php
557
- $force_inline_css = get_option('fastvelocity_min_force_inline_css');
558
- if($force_inline_css != false) {
559
- echo '<p>There are no merged CSS files listed here, because you are inlining all CSS directly.</p>';
560
- } else {
561
- echo '<ul class="processed"></ul>';
562
- }
563
- ?>
564
-
565
- </div>
566
- </div>
567
-
568
- </div>
569
- </div>
570
- </div>
571
- </div>
572
- <?php } ?>
573
-
574
- <?php if( $active_tab == 'set' ) { ?>
575
- <form method="post" action="options.php">
576
- <?php settings_fields('fvm-group'); do_settings_sections('fvm-group'); ?>
577
-
578
-
579
- <div style="height: 20px;"></div>
580
- <h2 class="title">Basic Settings</h2>
581
- <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>
582
-
583
- <table class="form-table fvm-settings">
584
- <tbody>
585
-
586
-
587
- <tr>
588
- <th scope="row">Functionality</th>
589
- <td>
590
- <p class="fvm-bold-green fvm-rowintro">The HTML minification is ON by default, but you can:</p>
591
-
592
- <fieldset>
593
- <label for="fastvelocity_min_enable_purgemenu">
594
- <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); ?>>
595
- 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>
596
- <br />
597
-
598
- <label for="fastvelocity_preserve_settings_on_uninstall">
599
- <input name="fastvelocity_preserve_settings_on_uninstall" type="checkbox" id="fastvelocity_preserve_settings_on_uninstall" value="1" <?php echo checked(1 == get_option('fastvelocity_preserve_settings_on_uninstall'), true, false); ?>>
600
- Preserve Settings<span class="note-info">[ If selected, all FVM settings will be preserved, even if you uninstall the plugin ]</span></label>
601
- <br />
602
-
603
- <label for="fastvelocity_min_fvm_fix_editor">
604
- <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); ?>>
605
- 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>
606
- <br />
607
-
608
- </fieldset></td>
609
- </tr>
610
-
611
-
612
- <tr>
613
- <th scope="row">URL Options</th>
614
- <td>
615
- <?php
616
- # what to select
617
- $sel = get_option('fastvelocity_min_default_protocol');
618
- $a = ''; if($sel == 'dynamic' || empty($sel)) { $a = ' checked="checked"'; }
619
- $b = ''; if($sel == 'http') { $b = ' checked="checked"'; }
620
- $c = ''; if($sel == 'https') { $c = ' checked="checked"'; }
621
- ?>
622
- <p class="fvm-bold-green fvm-rowintro">You may need to force http or https, for some CDN plugins to work:</p>
623
- <fieldset>
624
- <label><input type="radio" name="fastvelocity_min_default_protocol" value="dynamic" <?php echo $a; ?>> Auto Detect </label><br>
625
- <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>
626
- <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>
627
- </fieldset>
628
- </td>
629
- </tr>
630
-
631
- <tr>
632
- <th scope="row">HTML Options</th>
633
- <td>
634
- <p class="fvm-bold-green fvm-rowintro">The HTML minification is ON by default, but you can:</p>
635
-
636
- <fieldset>
637
- <label for="fastvelocity_min_skip_html_minification">
638
- <input name="fastvelocity_min_skip_html_minification" type="checkbox" id="fastvelocity_min_skip_html_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_html_minification'), true, false); ?>>
639
- Disable HTML Minification <span class="note-info">[ This will disable HTML minification ]</span></label>
640
- <br />
641
-
642
- <label for="fastvelocity_min_strip_htmlcomments">
643
- <input name="fastvelocity_min_strip_htmlcomments" type="checkbox" id="fastvelocity_min_strip_htmlcomments" value="1" <?php echo checked(1 == get_option('fastvelocity_min_strip_htmlcomments'), true, false); ?>>
644
- 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>
645
- <br />
646
-
647
- <label for="fastvelocity_fvm_clean_header_one">
648
- <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); ?>>
649
- Cleanup Header <span class="note-info">[ Remove resource hints, generator tag, shortlinks, manifest link, etc ]</span></label>
650
- <br />
651
-
652
- </fieldset></td>
653
- </tr>
654
-
655
-
656
- <tr>
657
- <th scope="row">Font Options</th>
658
- <td>
659
- <p class="fvm-bold-green fvm-rowintro">The default options are usually good for performance.</p>
660
- <fieldset>
661
- <label for="fastvelocity_min_skip_emoji_removal">
662
- <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); ?> >
663
- Stop removing Emojis and smileys <span class="note-info">[ If selected, Emojis will be left alone and won't be removed from wordpress ]</span></label>
664
- <br />
665
-
666
- <label for="fastvelocity_min_skip_google_fonts">
667
- <input name="fastvelocity_min_skip_google_fonts" type="checkbox" id="fastvelocity_min_skip_google_fonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_google_fonts'), true, false); ?> >
668
- Disable Google Fonts merging <span class="note-info">[ If selected, Google Fonts will no longer be merged into one request ]</span></label>
669
- <br />
670
-
671
- <label for="fastvelocity_min_remove_googlefonts">
672
- <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); ?> >
673
- Remove Google Fonts completely <span class="note-info">[ If selected, all enqueued Google Fonts will be removed from the site ]</span></label>
674
- <br />
675
-
676
- </fieldset></td>
677
- </tr>
678
-
679
-
680
- <tr>
681
- <th scope="row">Google Fonts</th>
682
- <td>
683
- <?php
684
- # what to select
685
- $sel = get_option('fastvelocity_gfonts_method');
686
- $a = ''; if($sel == 1 || empty($sel)) { $a = ' checked="checked"'; }
687
- $b = ''; if($sel == 2) { $b = ' checked="checked"'; }
688
- $c = ''; if($sel == 3) { $c = ' checked="checked"'; }
689
- ?>
690
- <p class="fvm-bold-green fvm-rowintro">Choose how to include Google Fonts on your pages, when available:</p>
691
- <fieldset>
692
- <label><input type="radio" name="fastvelocity_gfonts_method" value="1" <?php echo $a; ?>> Inline Google Fonts CSS</label> <span class="note-info">[ Will inline the <a target="_blank" href="https://caniuse.com/#feat=woff">woof</a> format only (with font hinting) ]</span><br>
693
- <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>
694
- <label><input type="radio" name="fastvelocity_gfonts_method" value="3"<?php echo $c; ?>> Async and exclude Google Fonts CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
695
- </fieldset>
696
- </td>
697
- </tr>
698
-
699
- <tr>
700
- <th scope="row">Font Awesome</th>
701
- <td>
702
- <?php
703
- # what to select
704
- $sel = get_option('fastvelocity_fontawesome_method');
705
- $a = ''; if($sel == 1 || empty($sel)) { $a = ' checked="checked"'; }
706
- $b = ''; if($sel == 2) { $b = ' checked="checked"'; }
707
- $c = ''; if($sel == 3) { $c = ' checked="checked"'; }
708
- ?>
709
- <p class="fvm-bold-green fvm-rowintro">Only if available and if it has "font-awesome" in the url:</p>
710
- <fieldset>
711
- <label><input type="radio" name="fastvelocity_fontawesome_method" value="1" <?php echo $a; ?>> Merge or Inline Font Awesome CSS</label> <span class="note-info">[ Depends on if you have the Inline CSS option enabled or not ]</span><br>
712
- <label><input type="radio" name="fastvelocity_fontawesome_method" value="2"<?php echo $b; ?>> Async Font Awesome CSS file</label> <span class="note-info">[ Will use <a target="_blank" href="https://caniuse.com/#feat=link-rel-preload">preload</a> with <a href="https://github.com/filamentgroup/loadCSS">LoadCSS</a> polyfill ]</span><br>
713
- <label><input type="radio" name="fastvelocity_fontawesome_method" value="3"<?php echo $c; ?>> Async and exclude Font Awesome CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
714
- </fieldset>
715
- </td>
716
- </tr>
717
-
718
-
719
- <tr>
720
- <th scope="row">CSS Options</th>
721
- <td>
722
- <p class="fvm-bold-green fvm-rowintro">It's recommended that you Inline all CSS files, if they are small enough.</p>
723
-
724
- <fieldset>
725
- <label for="fastvelocity_min_disable_css_merge">
726
- <input name="fastvelocity_min_disable_css_merge" type="checkbox" id="fastvelocity_min_disable_css_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_css_merge'), true, false); ?>>
727
- Disable CSS processing<span class="note-info">[ If selected, this plugin will ignore CSS files completely ]</span></label>
728
- <br />
729
- <label for="fastvelocity_min_disable_css_minification">
730
- <input name="fastvelocity_min_disable_css_minification" type="checkbox" id="fastvelocity_min_disable_css_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_css_minification'), true, false); ?>>
731
- Disable minification on CSS files <span class="note-info">[ If selected, CSS files will be merged but not minified ]</span></label>
732
- <br />
733
- <label for="fastvelocity_min_skip_cssorder">
734
- <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); ?> >
735
- 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>
736
- <br />
737
- <label for="fastvelocity_min_remove_print_mediatypes">
738
- <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); ?> >
739
- Disable the "Print" related stylesheets <span class="note-info">[ If selected, CSS files of mediatype "print" will be removed from the site ]</span></label>
740
- <br />
741
- <label for="fastvelocity_min_force_inline_css_footer">
742
- <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); ?>>
743
- Inline CSS in the footer <span class="note-info">[ If selected, any FVM generated CSS files in the footer, will be inlined ]</span></label>
744
- <br />
745
- <label for="fastvelocity_min_force_inline_css">
746
- <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); ?>>
747
- Inline CSS both in the header and footer <span class="note-info">[ If selected, any FVM generated CSS files (header + footer) will be inlined ]</span></label>
748
- <br />
749
- </fieldset></td>
750
- </tr>
751
-
752
-
753
- <tr>
754
- <th scope="row">JavaScript Options</th>
755
- <td>
756
- <p class="fvm-bold-green fvm-rowintro">Try to disable minification (and purge the cache) first, if you have trouble with JavaScript in the frontend.</p>
757
- <fieldset>
758
- <label for="fastvelocity_min_disable_js_merge">
759
- <input name="fastvelocity_min_disable_js_merge" type="checkbox" id="fastvelocity_min_disable_js_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_merge'), true, false); ?> >
760
- Disable JavaScript processing <span class="note-info">[ If selected, this plugin will ignore JS files completely ]</span></label>
761
- <br />
762
-
763
- <label for="fastvelocity_min_disable_js_minification">
764
- <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); ?> >
765
- Disable minification on JS files <span class="note-info">[ If selected, JS files will be merged but not minified ]</span></label>
766
- <br />
767
- </fieldset></td>
768
- </tr>
769
-
770
- <tr>
771
- <th scope="row">Render-blocking JS</th>
772
- <td>
773
- <fieldset><legend class="screen-reader-text"><span>Render-blocking</span></legend>
774
-
775
- <p class="fvm-bold-green fvm-rowintro">Some themes and plugins "need" render blocking scripts to work, so please take a look at the dev console for errors.</p>
776
- <label for="fastvelocity_min_enable_defer_js">
777
- <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); ?>>
778
- Enable defer parsing of FVM JS files globally <span class="note-info">[ Not all browsers, themes or plugins support this. Beware of broken functionality and design ]</span></label>
779
- <br />
780
-
781
- <label for="fastvelocity_min_exclude_defer_jquery">
782
- <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); ?> >
783
- Skip deferring the jQuery library <span class="note-info">[ Will probably fix "undefined jQuery" errors on the Google Chrome console log ]</span></label>
784
- <br />
785
- <label for="fastvelocity_min_exclude_defer_login">
786
- <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); ?> >
787
- Skip deferring JS on the login page <span class="note-info">[ If selected, will disable JS deferring on your login page ]</span></label>
788
- <br />
789
- <label for="fastvelocity_min_skip_defer_lists">
790
- <input name="fastvelocity_min_skip_defer_lists" type="checkbox" id="fastvelocity_min_skip_defer_lists" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_defer_lists'), true, false); ?> >
791
- Skip deferring the ignore list <span class="note-info">[ If selected, files on the blacklist, ignore list, etc, won't be deferred ]</span></label>
792
- <br />
793
-
794
- </fieldset></td>
795
- </tr>
796
-
797
- <tr>
798
- <th scope="row">PageSpeed Settings</th>
799
- <td>
800
- <p class="fvm-bold-green fvm-rowintro">Note that this will overwrite any other behaviour defined above and "may" cause errors.</p>
801
- <fieldset>
802
- <label for="fastvelocity_min_defer_for_pagespeed">
803
- <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); ?>>
804
- Enable defer of all JS files for PSI only <span class="note-info">[ Will use JavaScript to defer all JS files for PSI ]</span></label>
805
-
806
- <br />
807
- <label for="fastvelocity_min_defer_for_pagespeed_optimize">
808
- <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); ?>>
809
- Exclude JS files in the "ignore list" from PSI <span class="note-info">[ This will hide the "ignored files" from PSI instead of simply deferring ]</span></label>
810
-
811
- </fieldset></td>
812
- </tr>
813
-
814
- </tbody></table>
815
-
816
-
817
- <div style="height: 20px;"></div>
818
- <h2 class="title">CDN Options</h2>
819
- <p class="fvm-bold-green">When the "Enable defer of JS for Pagespeed Insights" option is enabled, JS and CSS files will not be loaded from the CDN due to <a target="_blank" href="https://www.chromestatus.com/feature/5718547946799104">compatibility</a> reasons.<br />However, you can define a CDN Domain below, in order to use it for all of the static assets "inside" your CSS and JS files.</p>
820
-
821
- <table class="form-table fvm-settings">
822
- <tbody>
823
- <tr>
824
- <th scope="row"><span class="fvm-label-special">Your CDN domain</span></th>
825
- <td><fieldset>
826
- <label for="fastvelocity_min_fvm_cdn_url">
827
- <p><input type="text" name="fastvelocity_min_fvm_cdn_url" id="fastvelocity_min_fvm_cdn_url" value="<?php echo get_option('fastvelocity_min_fvm_cdn_url', ''); ?>" size="80" /></p>
828
- <p class="description">[ Will rewrite the static assets urls inside FVM merged files to your cdn domain. Usage: cdn.example.com ]</p></label>
829
- </fieldset>
830
- </td>
831
- </tr>
832
-
833
- <tr>
834
- <th scope="row">Force the CDN Usage</th>
835
- <td>
836
- <p class="fvm-bold-green fvm-rowintro">If you force this, your JS files may not load for certain slow internet users on Google Chrome.</p>
837
- <fieldset>
838
- <label for="fastvelocity_min_fvm_cdn_force">
839
- <input name="fastvelocity_min_fvm_cdn_force" type="checkbox" id="fastvelocity_min_fvm_cdn_force" value="1" <?php echo checked(1 == get_option('fastvelocity_min_fvm_cdn_force'), true, false); ?>>
840
- I know what I'm doing... <span class="note-info">[ Load my JS files from the CDN, even when "defer for Pagespeed Insights" is enabled ]</span></label>
841
- </fieldset></td>
842
- </tr>
843
-
844
- </tbody></table>
845
-
846
- <div style="height: 20px;"></div>
847
- <h2 class="title">Cache Location</h2>
848
- <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>
849
- <table class="form-table fvm-settings">
850
- <tbody>
851
- <tr>
852
- <th scope="row"><span class="fvm-label-special">Cache Path</span></th>
853
- <td><fieldset>
854
- <label for="fastvelocity_min_change_cache_path">
855
- <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>
856
- <p class="description">[ Default cache path is: <?php echo rtrim(wp_upload_dir()['basedir'], '/'); ?> ]</p>
857
- </label>
858
- <br />
859
- <label for="fastvelocity_min_change_cache_base_url">
860
- <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>
861
- <p class="description">[ Default cache base url is: <?php echo rtrim(fvm_get_protocol(wp_upload_dir()['baseurl']), '/'); ?> ]</p>
862
- </label>
863
- </fieldset></td>
864
- </tr>
865
- </tbody></table>
866
-
867
-
868
- <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
869
- </form>
870
- <?php } ?>
871
-
872
-
873
- <?php if( $active_tab == 'pro' ) { ?>
874
-
875
- <form method="post" action="options.php">
876
- <?php settings_fields('fvm-group-pro'); do_settings_sections('fvm-group-pro'); ?>
877
-
878
-
879
- <div style="height: 20px;"></div>
880
- <h2 class="title">Special JS and CSS Exceptions</h2>
881
- <p class="fvm-bold-green">You can use this section to edit or change our default exclusions, as well as to add your own.<br />Make sure you understand the difference between Defer and Async.</p>
882
- <p class="fvm-bold-green">When you use an option here that uses "Async", styles and scripts load "out of order" and completely independent from the others. That means, the files that end up loading later, will overwrite any previously loaded code. On the other hand, when you use the "ignore list" or when you select an option to "defer", the order of scripts and styles is preserved and should not overwrite previously loaded code, unless there is an higher specificy somewhere else.</p>
883
-
884
- <div style="height: 20px;"></div>
885
- <table class="form-table fvm-settings">
886
- <tbody>
887
- <tr>
888
- <th scope="row">Ignore List</th>
889
- <td><fieldset>
890
- <label for="blacklist_keys"><span class="fvm-label-pad">Ignore the following CSS and JS paths below:</span></label>
891
- <p>
892
- <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>
893
- </p>
894
- <p class="description">[ Your own list of js /css files to ignore with wildcard support (read the faqs) ]</p>
895
- </fieldset></td>
896
- </tr>
897
- </tbody></table>
898
-
899
-
900
- <div style="height: 20px;"></div>
901
- <table class="form-table fvm-settings">
902
- <tbody>
903
- <tr>
904
- <th scope="row">External URLs to Merge</th>
905
- <td><fieldset><label for="blacklist_keys"><span class="fvm-label-pad">List of external domains that can be fetched and merged together:</span></label>
906
- <p>
907
- <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>
908
- </p>
909
- <p class="description">[ Add any external "domains" for JS or CSS files than can be merged fetched and merged together by FVM, ie: cdnjs.cloudflare.com ]</p>
910
- </fieldset></td>
911
- </tr>
912
- </tbody></table>
913
-
914
-
915
- <div style="height: 20px;"></div>
916
- <table class="form-table fvm-settings">
917
- <tbody>
918
- <tr>
919
- <th scope="row">Exclude JS files from PSI</th>
920
- <td><fieldset><label for="fastvelocity_min_excludejslist"><span class="fvm-label-pad">Files will be loaded Async and excluded from PSI:</span></label>
921
- <p>
922
- <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>
923
- </p>
924
- <p class="description">[ Any JS file that can load Async and completely independent, such as analytics or pixel scripts ]</p>
925
-
926
- </fieldset></td>
927
- </tr>
928
- </tbody></table>
929
-
930
-
931
- <div style="height: 20px;"></div>
932
- <table class="form-table fvm-settings">
933
- <tbody>
934
- <tr>
935
- <th scope="row">Exclude CSS files from PSI</th>
936
- <td><fieldset><label for="fastvelocity_min_excludecsslist"><span class="fvm-label-pad">Files will be loaded Async and excluded from PSI:</span></label>
937
- <p>
938
- <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/some-other-font.min.css"><?php echo get_option('fastvelocity_min_excludecsslist'); ?></textarea>
939
- </p>
940
- <p class="description">[ Any CSS file that can load completely independent, such as fontawesome or other icons ]</p>
941
-
942
- </fieldset></td>
943
- </tr>
944
- </tbody></table>
945
-
946
-
947
-
948
-
949
- <div style="height: 20px;"></div>
950
- <table class="form-table fvm-settings">
951
- <tbody>
952
- <tr>
953
- <th scope="row">Default Ignore List</th>
954
- <td>
955
- <fieldset><label for="blacklist_keys"><span class="fvm-label-pad">Do not edit, if you're not sure what this is:</span></label>
956
- <p>
957
- <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>
958
- </p>
959
- <p class="description">[ Files that have been consistently reported by other users to cause trouble when merged ]</p>
960
- </fieldset></td>
961
- </tr>
962
- </tbody></table>
963
-
964
- <div style="height: 20px;"></div>
965
- <table class="form-table fvm-settings">
966
- <tbody>
967
- <tr>
968
- <th scope="row">Default Blacklist</th>
969
- <td><fieldset><label for="blacklist_keys"><span class="fvm-label-pad">Do not edit, if you're not sure what this is:</span></label>
970
- <p>
971
- <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>
972
- </p>
973
- <p class="description">[ Usually, any IE css /js files that should always be ignored without incrementing the groups ]</p>
974
- </fieldset></td>
975
- </tr>
976
- </tbody></table>
977
-
978
-
979
- <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
980
- </form>
981
-
982
- <?php
983
- }
984
-
985
- # start developers tab
986
- if( $active_tab == 'dev' ) { ?>
987
-
988
- <form method="post" action="options.php">
989
- <?php settings_fields('fvm-group-dev'); do_settings_sections('fvm-group-dev'); ?>
990
-
991
- <div style="height: 20px;"></div>
992
- <h2 class="title">Development</h2>
993
- <p class="fvm-bold-green">This are handy things for the plugin author, but may be of use to you if you are looking to debug some issue.</p>
994
- <p class="fvm-bold-green">Please note that the automatic headers, are only available after the first, uncached pageview (you may need to purge your cache to see them, or your server may not support this at all).</p>
995
-
996
- <table class="form-table fvm-settings">
997
- <tbody>
998
- <tr>
999
- <th scope="row">Dev Options</th>
1000
- <td><fieldset>
1001
- <label for="fastvelocity_fvm_debug">
1002
- <input name="fastvelocity_fvm_debug" type="checkbox" id="fastvelocity_fvm_debug" value="1" <?php echo checked(1 == get_option('fastvelocity_fvm_debug'), true, false); ?>>
1003
- Enable FVM Debug Mode<span class="note-info">[ Add extra info to the "status page" logs as well as some comments on the HTML frontend (beta) ]</span></label>
1004
-
1005
- <br />
1006
- <label for="fastvelocity_enabled_css_preload">
1007
- <input name="fastvelocity_enabled_css_preload" type="checkbox" id="fastvelocity_enabled_css_preload" value="1" <?php echo checked(1 == get_option('fastvelocity_enabled_css_preload'), true, false); ?>>
1008
- Enable FVM CSS files Preload<span class="note-info">[ Automatically create http headers for FVM generated CSS files (when not inlined) ]</span></label>
1009
-
1010
- <br />
1011
- <label for="fastvelocity_enabled_js_preload">
1012
- <input name="fastvelocity_enabled_js_preload" type="checkbox" id="fastvelocity_enabled_js_preload" value="1" <?php echo checked(1 == get_option('fastvelocity_enabled_js_preload'), true, false); ?>>
1013
- Enable FVM JS files Preload<span class="note-info">[ Automatically create http headers for FVM generated JS files ]</span></label>
1014
-
1015
-
1016
- </fieldset>
1017
- </td>
1018
- </tr>
1019
- </tbody></table>
1020
-
1021
-
1022
-
1023
-
1024
-
1025
-
1026
- <div style="height: 20px;"></div>
1027
- <h2 class="title">HTTP Headers</h2>
1028
- <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>
1029
- <p class="fvm-bold-green">Preload Headers: Use this for preloading specific, high priority resources that exist across all of your pages.</p>
1030
- <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>
1031
-
1032
- <table class="form-table fvm-settings">
1033
- <tbody>
1034
- <tr>
1035
- <th scope="row">Preconnect Headers</th>
1036
- <td><fieldset><legend class="screen-reader-text"><span>Preconnect</span></legend>
1037
- <label for="fastvelocity_min_hpreconnect"><span class="fvm-label-pad">Use only the strictly minimum necessary domain names, (cdn or frequent embeds):</span></label>
1038
- <p>
1039
- <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>
1040
- </p>
1041
- <p class="description">[ Use the complete scheme (http:// or https://) followed by the domain name only (no file paths). ]</p>
1042
- <p class="description">[ Examples: ]</p>
1043
- <p class="description">https://fonts.googleapis.com</p>
1044
- <p class="description">https://fonts.gstatic.com</p>
1045
- </fieldset></td>
1046
- </tr>
1047
-
1048
- </tbody></table>
1049
-
1050
- <table class="form-table fvm-settings">
1051
- <tbody>
1052
- <tr>
1053
- <th scope="row">Preload Headers</th>
1054
- <td><fieldset><legend class="screen-reader-text"><span>Preload Headers</span></legend>
1055
- <label for="fastvelocity_min_hpreload"><span class="fvm-label-pad">Insert your "complete php header code" here:</span></label>
1056
- <p>
1057
- <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>
1058
- </p>
1059
- <p class="description">[ Example of a "complete php header code" to paste above ]</p>
1060
- <p class="description">Link: &lt;https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVZ0d.woff&gt;; rel=preload; as=font; crossorigin</p>
1061
- <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>
1062
- </fieldset></td>
1063
- </tr>
1064
- </tbody></table>
1065
-
1066
-
1067
- <div style="height: 20px;"></div>
1068
- <h2 class="title">Async CSS</h2>
1069
- <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>
1070
-
1071
- <table class="form-table fvm-settings">
1072
- <tbody>
1073
- <tr>
1074
- <th scope="row">Enable Async CSS</th>
1075
- <td><fieldset>
1076
- <label for="fastvelocity_min_loadcss">
1077
- <input name="fastvelocity_min_loadcss" type="checkbox" id="fastvelocity_min_loadcss" value="1" <?php echo checked(1 == get_option('fastvelocity_min_loadcss'), true, false); ?>>
1078
- Async CSS with LoadCSS <span class="note-info">[ Note that inline CSS won't work if this is active ]</span></label>
1079
-
1080
- <br />
1081
- <label for="fastvelocity_min_fvm_removecss">
1082
- <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); ?>>
1083
- Dequeue all CSS files <span class="note-info">[ Use this if you want to test how your Critical Path CSS looks like ]</span></label>
1084
-
1085
- </fieldset>
1086
- </td>
1087
- </tr>
1088
-
1089
- </tbody></table>
1090
-
1091
-
1092
- <div style="height: 20px;"></div>
1093
- <h2 class="title">Critical Path CSS</h2>
1094
- <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>
1095
- <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>
1096
- <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>
1097
-
1098
- <table class="form-table fvm-settings">
1099
- <tbody>
1100
-
1101
- <tr>
1102
- <th scope="row">Fallback CSS</th>
1103
- <td>
1104
- <fieldset>
1105
- <p>
1106
- <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>
1107
- </p>
1108
- <p class="description">[ It will be overwritten, if some other more specific critical path code exists below ]</p>
1109
- </fieldset>
1110
- </td>
1111
- </tr>
1112
-
1113
- <tr>
1114
- <th scope="row">is_front_page (conditional)</th>
1115
- <td>
1116
- <fieldset>
1117
- <p>
1118
- <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>
1119
- </p>
1120
- <p class="description">[ Will show up if your page matches the WP conditional, is_front_page() ]</p>
1121
- </fieldset>
1122
- </td>
1123
- </tr>
1124
-
1125
- </tbody></table>
1126
-
1127
-
1128
-
1129
- <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
1130
- </form>
1131
-
1132
- <?php
1133
- }
1134
-
1135
-
1136
- # start server info tab
1137
- if( $active_tab == 'server' ) {
1138
- fvm_get_generalinfo();
1139
- }
1140
-
1141
-
1142
- # start help tab
1143
- if( $active_tab == 'help' ) { ?>
1144
-
1145
- <div class="wrap" id="fastvelocity-min">
1146
- <div id="poststuff">
1147
- <div id="fastvelocity_min_processed" class="postbox-container">
1148
- <div class="meta-box-sortables ui-sortable">
1149
-
1150
- <div class="postbox" id="tab-info">
1151
- <h3 class="hndle"><span>Paid Clients / Custom Requests</span></h3>
1152
- <div class="inside">
1153
- <p>Please Visit: <a href="https://www.upwork.com/fl/fvmpeixoto">https://www.upwork.com/fl/fvmpeixoto</a></p>
1154
- <p>Alternatively: <a href="https://fastvelocity.com/">https://fastvelocity.com/</a></p>
1155
- </div>
1156
- </div>
1157
-
1158
- <div class="postbox" id="tab-info">
1159
- <h3 class="hndle"><span>Frequently Asked Questions</span></h3>
1160
- <div class="inside">
1161
- <p>Please Visit: <a href="https://wordpress.org/plugins/fast-velocity-minify/#faq">https://wordpress.org/plugins/fast-velocity-minify/#faq</a></p>
1162
- </div>
1163
- </div>
1164
-
1165
- <div class="postbox" id="tab-info">
1166
- <h3 class="hndle"><span>Open Source Support / Bug Report</span></h3>
1167
- <div class="inside">
1168
- <p>Please Visit: <a href="https://wordpress.org/support/plugin/fast-velocity-minify">https://wordpress.org/support/plugin/fast-velocity-minify</a></p>
1169
- </div>
1170
- </div>
1171
-
1172
- <div class="postbox" id="tab-info">
1173
- <h3 class="hndle"><span>Need faster hosting?</span></h3>
1174
- <div class="inside">
1175
- <p>Digital Ocean: (aff) <a href="https://m.do.co/c/039860472caf">https://www.digitalocean.com/</a></p>
1176
- <p>Vultr: (aff) <a href="https://www.vultr.com/?ref=6879450">https://www.vultr.com/</a></p>
1177
- <p>Linode: (aff) <a href="https://www.linode.com/?r=4b0ae524a0e54b1c11abb8014be4068f5a5d607a">https://www.linode.com/</a></p>
1178
- <p>Amazon Lightsail: <a href="https://aws.amazon.com/lightsail/">https://aws.amazon.com/lightsail/</a></p>
1179
- <p>Google Cloud: <a href="https://cloud.google.com/">https://cloud.google.com/</a></p>
1180
- </div>
1181
- </div>
1182
-
1183
- <div class="postbox" id="tab-info">
1184
- <h3 class="hndle"><span>Donations (Thank You)</span></h3>
1185
- <div class="inside">
1186
- <p>PayPal: <a href="https://goo.gl/vpLrSV">https://goo.gl/vpLrSV</a><br /></p>
1187
- </div>
1188
- </div>
1189
-
1190
- </div>
1191
- </div>
1192
- </div>
1193
- </div>
1194
-
1195
- <?php } ?>
1196
-
1197
-
1198
-
1199
- </div>
1200
-
1201
- <div class="clear"></div>
1202
-
1203
- <?php
1204
- }
1205
-
1206
-
1207
- ###########################################
1208
- # process header javascript ###############
1209
- ###########################################
1210
- function fastvelocity_min_merge_header_scripts() {
1211
- global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery, $fvm_debug, $fvm_min_excludejslist, $fvmualist;
1212
- if(!is_object($wp_scripts)) { return false; }
1213
- $scripts = wp_clone($wp_scripts);
1214
- $scripts->all_deps($scripts->queue);
1215
- $ctime = get_option('fvm-last-cache-update', '0');
1216
- $header = array();
1217
-
1218
- # mark as done (as we go)
1219
- $done = $scripts->done;
1220
-
1221
- # add defaults to ignore list
1222
- $ignore = fastvelocity_default_ignore($ignore);
1223
-
1224
- # get groups of handles
1225
- foreach( $scripts->to_do as $handle ) :
1226
-
1227
- # is it a footer script?
1228
- $is_footer = 0;
1229
- if (isset($wp_scripts->registered[$handle]->extra["group"]) || isset($wp_scripts->registered[$handle]->args)) {
1230
- $is_footer = 1;
1231
- }
1232
-
1233
- # skip footer scripts for now
1234
- if($is_footer != 1) {
1235
-
1236
- # get full url
1237
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1238
-
1239
- # inlined scripts without file
1240
- if( empty($hurl)) {
1241
- continue;
1242
- }
1243
-
1244
- # Exclude JS files from PSI (Async) takes priority over the ignore list
1245
- if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
1246
-
1247
- # check for string match
1248
- $skipjs = false;
1249
- foreach($fvm_min_excludejslist as $l) {
1250
- if (stripos($hurl, $l) !== false) {
1251
- # print code if there are no linebreaks, or return
1252
- echo '<script type="text/javascript">if(fvmuag()){';
1253
- echo "loadAsync('$hurl', null);";
1254
- echo '}</script>';
1255
- $skipjs = true;
1256
- break;
1257
- }
1258
- }
1259
- if($skipjs != false) { continue; }
1260
- }
1261
-
1262
-
1263
- # IE only files don't increment things
1264
- $ieonly = fastvelocity_ie_blacklist($hurl);
1265
- if($ieonly == true) { continue; }
1266
-
1267
- # skip ignore list, scripts with conditionals, external scripts
1268
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1269
-
1270
- # process
1271
- if(isset($header[count($header)-1]['handle']) || count($header) == 0) {
1272
- array_push($header, array('handles'=>array()));
1273
- }
1274
-
1275
- # push it to the array
1276
- array_push($header[count($header)-1]['handles'], $handle);
1277
-
1278
- # external and ignored scripts
1279
- } else {
1280
- array_push($header, array('handle'=>$handle));
1281
- }
1282
-
1283
- # make sure that the scripts skipped here, show up in the footer
1284
- } else {
1285
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1286
-
1287
- # inlined scripts without file
1288
- if( empty($hurl)) {
1289
- wp_enqueue_script($handle, false);
1290
- } else {
1291
- wp_enqueue_script($handle, $hurl, array(), null, true);
1292
- }
1293
- }
1294
- endforeach;
1295
-
1296
- # loop through header scripts and merge
1297
- for($i=0,$l=count($header);$i<$l;$i++) {
1298
- if(!isset($header[$i]['handle'])) {
1299
-
1300
- # static cache file info + done
1301
- $done = array_merge($done, $header[$i]['handles']);
1302
- $hash = 'header-'.hash('sha1',implode('',$header[$i]['handles']));
1303
-
1304
- # create cache files and urls
1305
- $file = $cachedir.fastvelocity_get_os_slash().$hash.'.min.js';
1306
- $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'.min.js');
1307
-
1308
- # generate a new cache file
1309
- clearstatcache();
1310
- if (!file_exists($file)) {
1311
-
1312
- # code and log initialization
1313
- $log = '';
1314
- $code = '';
1315
-
1316
- # minify and write to file
1317
- foreach($header[$i]['handles'] as $handle) :
1318
- if(!empty($wp_scripts->registered[$handle]->src)) {
1319
-
1320
- # get hurl per handle
1321
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1322
-
1323
- # inlined scripts without file
1324
- if( empty($hurl)) {
1325
- continue;
1326
- }
1327
-
1328
- # print url
1329
- $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1330
-
1331
- # download, minify, cache
1332
- $tkey = 'js-'.hash('sha1', $handle.$hurl).'.js';
1333
- $json = false; $json = fvm_get_transient($tkey);
1334
- if ( $json === false) {
1335
- $json = fvm_download_and_minify($hurl, null, $disable_js_minification, 'js', $handle);
1336
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
1337
- fvm_set_transient($tkey, $json);
1338
- }
1339
-
1340
- # decode
1341
- $res = json_decode($json, true);
1342
-
1343
- # response has failed
1344
- if($res['status'] != true) {
1345
- $log.= $res['log'];
1346
- continue;
1347
- }
1348
-
1349
- # Add extra data from wp_add_inline_script before
1350
- if (!empty( $wp_scripts->registered[$handle]->extra)) {
1351
- if (!empty( $wp_scripts->registered[$handle]->extra['before'])){
1352
- $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $wp_scripts->registered[$handle]->extra['before']));
1353
- }
1354
- }
1355
-
1356
- # append code to merged file
1357
- $code.= "/* $hurl */". PHP_EOL . fastvelocity_try_catch_wrap($res['code']);
1358
- $log.= $res['log'];
1359
-
1360
- # Add extra data from wp_add_inline_script after
1361
- if (!empty( $wp_scripts->registered[$handle]->extra)) {
1362
- if (!empty( $wp_scripts->registered[$handle]->extra['after'])){
1363
- $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $wp_scripts->registered[$handle]->extra['after']));
1364
- }
1365
- }
1366
-
1367
- # consider dependencies on handles with an empty src
1368
- } else {
1369
- wp_dequeue_script($handle); wp_enqueue_script($handle);
1370
- }
1371
- endforeach;
1372
-
1373
- # prepare log
1374
- $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
1375
-
1376
- # generate cache, write log
1377
- if(!empty($code)) {
1378
- file_put_contents($file.'.txt', $log);
1379
- file_put_contents($file, $code);
1380
- file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1381
-
1382
- # permissions
1383
- fastvelocity_fix_permission_bits($file.'.txt');
1384
- fastvelocity_fix_permission_bits($file);
1385
- fastvelocity_fix_permission_bits($file.'.gz');
1386
-
1387
- # brotli static support
1388
- if(function_exists('brotli_compress')) {
1389
- file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
1390
- fastvelocity_fix_permission_bits($file.'.br');
1391
- }
1392
- }
1393
- }
1394
-
1395
- # register minified file
1396
- wp_register_script("fvm-header-$i", $file_url, array(), null, false);
1397
-
1398
- # add all extra data from wp_localize_script
1399
- $data = array();
1400
- foreach($header[$i]['handles'] as $handle) {
1401
- if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1402
- }
1403
- if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1404
-
1405
- # enqueue file, if not empty
1406
- if(file_exists($file) && (filesize($file) > 0 || count($data) > 0)) {
1407
- wp_enqueue_script("fvm-header-$i");
1408
- } else {
1409
- # file could not be generated, output something meaningful
1410
- echo "<!-- ERROR: FVM was not allowed to save it's cache on - $file -->";
1411
- echo "<!-- Please check if the path above is correct and ensure your server has writting permission there! -->";
1412
- echo "<!-- If you found a bug, please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
1413
- }
1414
-
1415
- # other scripts need to be requeued for the order of files to be kept
1416
- } else {
1417
- wp_dequeue_script($header[$i]['handle']);
1418
- wp_enqueue_script($header[$i]['handle']);
1419
- }
1420
- }
1421
-
1422
- # remove from queue
1423
- $wp_scripts->done = $done;
1424
- }
1425
- ###########################################
1426
-
1427
-
1428
-
1429
- ###########################################
1430
- # process js in the footer ################
1431
- ###########################################
1432
- function fastvelocity_min_merge_footer_scripts() {
1433
- global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery, $fvm_debug, $fvm_min_excludejslist, $fvmualist;
1434
- if(!is_object($wp_scripts)) { return false; }
1435
- $ctime = get_option('fvm-last-cache-update', '0');
1436
- $scripts = wp_clone($wp_scripts);
1437
- $scripts->all_deps($scripts->queue);
1438
- $footer = array();
1439
-
1440
- # mark as done (as we go)
1441
- $done = $scripts->done;
1442
-
1443
- # add defaults to ignore list
1444
- $ignore = fastvelocity_default_ignore($ignore);
1445
-
1446
-
1447
- # get groups of handles
1448
- foreach( $scripts->to_do as $handle ) :
1449
-
1450
- # get full url
1451
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1452
-
1453
- # inlined scripts without file
1454
- if( empty($hurl)) {
1455
- continue;
1456
- }
1457
-
1458
- # Exclude JS files from PSI (Async) takes priority over the ignore list
1459
- if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
1460
-
1461
- # check for string match
1462
- $skipjs = false;
1463
- foreach($fvm_min_excludejslist as $l) {
1464
- if (stripos($hurl, $l) !== false) {
1465
- # print code if there are no linebreaks, or return
1466
- echo '<script type="text/javascript">if(fvmuag()){';
1467
- echo "loadAsync('$hurl', null);";
1468
- echo '}</script>';
1469
- $skipjs = true;
1470
- break;
1471
- }
1472
- }
1473
- if($skipjs != false) { continue; }
1474
- }
1475
-
1476
- # IE only files don't increment things
1477
- $ieonly = fastvelocity_ie_blacklist($hurl);
1478
- if($ieonly == true) { continue; }
1479
-
1480
- # skip ignore list, scripts with conditionals, external scripts
1481
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1482
-
1483
- # process
1484
- if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0) {
1485
- array_push($footer, array('handles'=>array()));
1486
- }
1487
-
1488
- # push it to the array
1489
- array_push($footer[count($footer)-1]['handles'], $handle);
1490
-
1491
- # external and ignored scripts
1492
- } else {
1493
- array_push($footer, array('handle'=>$handle));
1494
- }
1495
- endforeach;
1496
-
1497
- # loop through footer scripts and merge
1498
- for($i=0,$l=count($footer);$i<$l;$i++) {
1499
- if(!isset($footer[$i]['handle'])) {
1500
-
1501
- # static cache file info + done
1502
- $done = array_merge($done, $footer[$i]['handles']);
1503
- $hash = 'footer-'.hash('sha1',implode('',$footer[$i]['handles']));
1504
-
1505
- # create cache files and urls
1506
- $file = $cachedir.fastvelocity_get_os_slash().$hash.'.min.js';
1507
- $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'.min.js');
1508
-
1509
- # generate a new cache file
1510
- clearstatcache();
1511
- if (!file_exists($file)) {
1512
-
1513
- # code and log initialization
1514
- $log = '';
1515
- $code = '';
1516
-
1517
- # minify and write to file
1518
- foreach($footer[$i]['handles'] as $handle) :
1519
- if(!empty($wp_scripts->registered[$handle]->src)) {
1520
-
1521
- # get hurl per handle
1522
- $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1523
-
1524
- # inlined scripts without file
1525
- if( empty($hurl)) {
1526
- continue;
1527
- }
1528
-
1529
- # print url
1530
- $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1531
-
1532
-
1533
- # download, minify, cache
1534
- $tkey = 'js-'.hash('sha1', $handle.$hurl).'.js';
1535
- $json = false; $json = fvm_get_transient($tkey);
1536
- if ( $json === false) {
1537
- $json = fvm_download_and_minify($hurl, null, $disable_js_minification, 'js', $handle);
1538
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
1539
- fvm_set_transient($tkey, $json);
1540
- }
1541
-
1542
- # decode
1543
- $res = json_decode($json, true);
1544
-
1545
- # response has failed
1546
- if($res['status'] != true) {
1547
- $log.= $res['log'];
1548
- continue;
1549
- }
1550
-
1551
- # Add extra data from wp_add_inline_script before
1552
- if (!empty($wp_scripts->registered[$handle]->extra)){
1553
- if (!empty($wp_scripts->registered[$handle]->extra['before'])){
1554
- $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $wp_scripts->registered[$handle]->extra['before']));
1555
- }
1556
- }
1557
-
1558
- # append code to merged file
1559
- $code.= "/* $hurl */". PHP_EOL . fastvelocity_try_catch_wrap($res['code']);
1560
- $log.= $res['log'];
1561
-
1562
- # Add extra data from wp_add_inline_script after
1563
- if (!empty($wp_scripts->registered[$handle]->extra)){
1564
- if (!empty($wp_scripts->registered[$handle]->extra['after'])){
1565
- $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $wp_scripts->registered[$handle]->extra['after']));
1566
- }
1567
- }
1568
-
1569
- # consider dependencies on handles with an empty src
1570
- } else {
1571
- wp_dequeue_script($handle);
1572
- wp_enqueue_script($handle);
1573
- }
1574
- endforeach;
1575
-
1576
- # prepare log
1577
- $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
1578
-
1579
- # generate cache, write log
1580
- if(!empty($code)) {
1581
- file_put_contents($file.'.txt', $log);
1582
- file_put_contents($file, $code);
1583
- file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1584
-
1585
- # permissions
1586
- fastvelocity_fix_permission_bits($file.'.txt');
1587
- fastvelocity_fix_permission_bits($file);
1588
- fastvelocity_fix_permission_bits($file.'.gz');
1589
-
1590
- # brotli static support
1591
- if(function_exists('brotli_compress')) {
1592
- file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
1593
- fastvelocity_fix_permission_bits($file.'.br');
1594
- }
1595
- }
1596
- }
1597
-
1598
- # register minified file
1599
- wp_register_script("fvm-footer-$i", $file_url, array(), null, false);
1600
-
1601
- # add all extra data from wp_localize_script
1602
- $data = array();
1603
- foreach($footer[$i]['handles'] as $handle) {
1604
- if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1605
- }
1606
- if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1607
-
1608
- # enqueue file, if not empty
1609
- if(file_exists($file) && (filesize($file) > 0 || count($data) > 0)) {
1610
- wp_enqueue_script("fvm-footer-$i");
1611
- } else {
1612
- # file could not be generated, output something meaningful
1613
- echo "<!-- ERROR: FVM was not allowed to save it's cache on - $file -->";
1614
- echo "<!-- Please check if the path above is correct and ensure your server has writting permission there! -->";
1615
- echo "<!-- If you found a bug, please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
1616
- }
1617
-
1618
- # other scripts need to be requeued for the order of files to be kept
1619
- } else {
1620
- wp_dequeue_script($footer[$i]['handle']); wp_enqueue_script($footer[$i]['handle']);
1621
- }
1622
- }
1623
-
1624
- # remove from queue
1625
- $wp_scripts->done = $done;
1626
- }
1627
- ##############################
1628
-
1629
-
1630
-
1631
- ###########################################
1632
- # enable defer for JavaScript (WP 4.1 and above) and remove query strings for ignored files
1633
- ###########################################
1634
- function fastvelocity_min_defer_js($tag, $handle, $src) {
1635
- global $ignore, $blacklist, $ignorelist, $enable_defer_js, $defer_for_pagespeed, $wp_domain, $exclude_defer_login, $fvm_fix_editor, $fvmualist, $defer_for_pagespeed_optimize, $exclude_defer_jquery, $skip_defer_lists;
1636
-
1637
- # no query strings
1638
- $tag = trim($tag); # must cleanup
1639
- if (stripos($src, '?ver') !== false) {
1640
- $srcf = stristr($src, '?ver', true);
1641
- $tag = str_ireplace($src, $srcf, $tag);
1642
- $src = $srcf;
1643
- }
1644
-
1645
-
1646
- # fix page editors, admin, amp, etc
1647
- if(fastvelocity_exclude_contents()) { return $tag; }
1648
-
1649
- # return if defer option is not selected
1650
- if ($defer_for_pagespeed != true && $enable_defer_js != true) { return $tag; }
1651
-
1652
- # Skip deferring the jQuery library option
1653
- if($exclude_defer_jquery != false && (stripos($tag, '/jquery.js') !== false || stripos($tag, '/jquery.min.js') !== false || (stripos($tag, '/jquery-') !== false && stripos($tag, '.js') !== false))) {
1654
- return $tag;
1655
- }
1656
-
1657
- # return if external script url https://www.chromestatus.com/feature/5718547946799104
1658
- if (fvm_is_local_domain($src) !== true) { return $tag; }
1659
-
1660
- # bypass if there are linebreaks (will break document.write) or already being optimized
1661
- if (stripos($tag, PHP_EOL) !== false || stripos($tag, 'navigator.userAgent.match') !== false) {
1662
- return $tag;
1663
- }
1664
-
1665
- # should we exclude defer on the login page?
1666
- if($exclude_defer_login == true && stripos($_SERVER["SCRIPT_NAME"], strrchr(wp_login_url(), '/')) !== false){
1667
- return $tag;
1668
- }
1669
-
1670
- # add defer attribute, but only if not having async or defer already
1671
- if (stripos($tag, 'defer') === false && stripos($tag, 'async') === false) {
1672
-
1673
- # defer tag globally
1674
- $jsdefer = str_ireplace('<script ', '<script defer ', $tag);
1675
- $jsdeferpsi = $jsdefer;
1676
-
1677
- # add cdn for PSI
1678
- $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
1679
- if(!empty($fvm_cdn_url)) {
1680
- $fvm_cdn_url = trim(trim(str_ireplace(array('http://', 'https://'), '', trim($fvm_cdn_url, '/'))), '/');
1681
- $jsdeferpsi = str_ireplace($src, $fvm_cdn_url, $jsdefer);
1682
- }
1683
-
1684
-
1685
- # defer tag for PSI only
1686
- $jsdeferpsionly = '<script type="text/javascript">if(navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){document.write('.fastvelocity_escape_url_js($jsdeferpsi).');}else{document.write('.fastvelocity_escape_url_js($tag).');}</script>';
1687
-
1688
- # hide tag from PSI
1689
- $jsdeferhidepsi = '<script type="text/javascript">if(fvmuag()){document.write('.fastvelocity_escape_url_js($tag).');}</script>';
1690
-
1691
- # must return by this order...
1692
-
1693
- # remove FVM from the ignore list
1694
- array_filter($ignore, function ($var) { return (stripos($var, '/fvm/') === false); });
1695
-
1696
- # Exclude JS files in the "ignore list" from PSI
1697
- if($defer_for_pagespeed_optimize != false) {
1698
- if((count($ignore) > 0 && fastvelocity_min_in_arrayi($src, $ignore)) || (count($blacklist) > 0 && fastvelocity_min_in_arrayi($src, $blacklist)) || (count($ignorelist) > 0 && fastvelocity_min_in_arrayi($src, $ignorelist))) {
1699
- return $jsdeferhidepsi;
1700
- }
1701
- }
1702
-
1703
- # Enable defer of JS files for PSI
1704
- if($defer_for_pagespeed != false) {
1705
- return $jsdeferpsionly;
1706
- }
1707
-
1708
- # Enable defer parsing of FVM JS files globally
1709
- if($enable_defer_js == true) {
1710
-
1711
- # consider "Skip deferring the ignore list"
1712
- if($skip_defer_lists != false && ((count($ignore) > 0 && fastvelocity_min_in_arrayi($src, $ignore)) || (count($blacklist) > 0 && fastvelocity_min_in_arrayi($src, $blacklist)) || (count($ignorelist) > 0 && fastvelocity_min_in_arrayi($src, $ignorelist)))) {
1713
- return $tag;
1714
- } else {
1715
- return $jsdefer;
1716
- }
1717
- }
1718
-
1719
- }
1720
-
1721
- # fallback
1722
- return $tag;
1723
- }
1724
- ###########################################
1725
-
1726
-
1727
- ###########################################
1728
- # process header css ######################
1729
- ###########################################
1730
- function fastvelocity_min_merge_header_css() {
1731
- global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_min_excludecsslist, $fvm_debug, $fvm_min_excludecsslist, $fvm_fawesome_method;
1732
- if(!is_object($wp_styles)) { return false; }
1733
- $ctime = get_option('fvm-last-cache-update', '0');
1734
- $styles = wp_clone($wp_styles);
1735
- $styles->all_deps($styles->queue);
1736
- $done = $styles->done;
1737
- $header = array();
1738
- $google_fonts = array();
1739
- $process = array();
1740
- $inline_css = array();
1741
- $log = '';
1742
-
1743
- # dequeue all styles
1744
- if($fvm_remove_css != false) {
1745
- foreach( $styles->to_do as $handle ) :
1746
- $done = array_merge($done, array($handle));
1747
- endforeach;
1748
-
1749
- # remove from queue
1750
- $wp_styles->done = $done;
1751
- return false;
1752
- }
1753
-
1754
- # add defaults to ignore list
1755
- $ignore = fastvelocity_default_ignore($ignore);
1756
-
1757
- # get list of handles to process, dequeue duplicate css urls and keep empty source handles (for dependencies)
1758
- $uniq = array(); $gfonts = array();
1759
- foreach( $styles->to_do as $handle):
1760
-
1761
- # conditionals
1762
- $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
1763
- $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
1764
- }
1765
-
1766
- # mediatype
1767
- $mt = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
1768
- if ($mt == 'screen' || $mt == 'screen, print' || empty($mt) || is_null($mt) || $mt == false) { $mt = 'all'; }
1769
- $mediatype = $mt;
1770
-
1771
- # full url or empty
1772
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1773
-
1774
- # inlined scripts without file
1775
- if( empty($hurl)) {
1776
- continue;
1777
- }
1778
-
1779
- # mark duplicates as done and remove from the queue
1780
- if(!empty($hurl)) {
1781
- $key = hash('sha1', $hurl);
1782
- if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
1783
- }
1784
-
1785
- # Exclude specific CSS files from PSI?
1786
- if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($hurl, $fvm_min_excludecsslist)) {
1787
- $cssguid = 'fvm'.hash('sha1', $hurl);
1788
- echo '<script type="text/javascript">if(fvmuag()){';
1789
- echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1790
- echo '}</script>';
1791
- $done = array_merge($done, array($handle)); continue;
1792
- }
1793
-
1794
- # font awesome processing, async css
1795
- if($fvm_fawesome_method == 2 && stripos($hurl, 'font-awesome') !== false) {
1796
- echo '<link rel="preload" href="'.$hurl.'" as="style" media="'.$mediatype.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1797
- echo '<noscript><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /></noscript>';
1798
- echo '<!--[if IE]><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /><![endif]-->';
1799
- $done = array_merge($done, array($handle)); continue;
1800
- }
1801
-
1802
- # font awesome processing, async and exclude from PSI
1803
- if($fvm_fawesome_method == 3 && stripos($hurl, 'font-awesome') !== false) {
1804
- $cssguid = 'fvm'.hash('sha1', $hurl);
1805
- echo '<script type="text/javascript">if(fvmuag()){';
1806
- echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1807
- echo '}</script>';
1808
- $done = array_merge($done, array($handle)); continue;
1809
- }
1810
-
1811
- # array of info to save
1812
- $arr = array('handle'=>$handle, 'url'=>$hurl, 'conditional'=>$conditional, 'mediatype'=>$mediatype);
1813
-
1814
- # google fonts to the top (collect and skip process array)
1815
- if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1816
- if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
1817
- if($skip_google_fonts != true || $force_inline_googlefonts != false) {
1818
- $google_fonts[$handle] = $hurl;
1819
-
1820
- } else {
1821
- wp_enqueue_style($handle); # skip google fonts optimization?
1822
- }
1823
- continue;
1824
- }
1825
-
1826
- # all else
1827
- $process[$handle] = $arr;
1828
-
1829
- endforeach;
1830
-
1831
-
1832
- # concat google fonts, if enabled
1833
- if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts != false && count($google_fonts) > 0)) {
1834
- foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1835
-
1836
- # merge google fonts if force inlining is enabled?
1837
- $nfonts = array();
1838
- if($skip_google_fonts != true) {
1839
- $nfonts[] = fvm_get_protocol(fastvelocity_min_concatenate_google_fonts($google_fonts));
1840
- } else {
1841
- foreach ($google_fonts as $a) { if(!empty($a)) { $nfonts[] = $a; } }
1842
- }
1843
-
1844
- # foreach google font (will be one if merged is not disabled)
1845
- if(count($nfonts) > 0) {
1846
- foreach($nfonts as $gfurl) {
1847
-
1848
- # hide from PSI, async, inline, or default
1849
- if($css_hide_googlefonts == true) {
1850
-
1851
- # make a stylesheet, hide from PSI
1852
- $cssguid = 'fvm'.hash('sha1', $gfurl);
1853
- echo '<script type="text/javascript">if(fvmuag()){';
1854
- 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.');';
1855
- echo '}</script>';
1856
-
1857
- # async CSS
1858
- } elseif ($min_async_googlefonts == true) {
1859
- echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1860
- echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
1861
- echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
1862
-
1863
- # inline css
1864
- } elseif($force_inline_googlefonts == true) {
1865
-
1866
- # download, minify, cache
1867
- $tkey = 'css-'.hash('sha1', $gfurl).'.css';
1868
- $json = false; $json = fvm_get_transient($tkey);
1869
- if ( $json === false) {
1870
- $json = fvm_download_and_minify($gfurl, null, $disable_css_minification, 'css', null);
1871
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $gfurl -->" . PHP_EOL; }
1872
- fvm_set_transient($tkey, $json);
1873
- }
1874
-
1875
- # decode
1876
- $res = json_decode($json, true);
1877
-
1878
- # response has failed
1879
- if($res['status'] != true) {
1880
- $log.= $res['log'];
1881
- continue;
1882
- }
1883
-
1884
- # inline css or fail
1885
- if($res['code'] !== false) {
1886
-
1887
- # add font-display
1888
- # https://developers.google.com/web/updates/2016/02/font-display
1889
- $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
1890
-
1891
- # inline
1892
- echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
1893
- } else {
1894
- echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
1895
- }
1896
-
1897
- # fallback, enqueue google fonts
1898
- } else {
1899
- wp_enqueue_style('header-fvm-fonts', $gfurl, array(), null, 'all');
1900
- }
1901
-
1902
- }
1903
- }
1904
- }
1905
-
1906
-
1907
- # get groups of handles
1908
- foreach( $styles->to_do as $handle ) :
1909
-
1910
- # skip already processed google fonts and empty dependencies
1911
- if(isset($google_fonts[$handle])) { continue; } # skip google fonts
1912
- if(empty($wp_styles->registered[$handle]->src)) { continue; } # skip empty src
1913
- if (fastvelocity_min_in_arrayi($handle, $done)) { continue; } # skip if marked as done before
1914
- if (!isset($process[$handle])) { continue; } # skip if not on our unique process list
1915
-
1916
- # get full url
1917
- $hurl = $process[$handle]['url'];
1918
- $conditional = $process[$handle]['conditional'];
1919
- $mediatype = $process[$handle]['mediatype'];
1920
-
1921
- # IE only files don't increment things
1922
- $ieonly = fastvelocity_ie_blacklist($hurl);
1923
- if($ieonly == true) { continue; }
1924
-
1925
- # skip ignore list, conditional css, external css, font-awesome merge
1926
- if ( (!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home))
1927
- || empty($hurl)
1928
- || ($fvm_fawesome_method == 1 && stripos($hurl, 'font-awesome') !== false)) {
1929
-
1930
- # colect inline css for this handle
1931
- if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
1932
- $inline_css[$handle] = fastvelocity_min_minify_css_string(implode('', $wp_styles->registered[$handle]->extra['after'])); # save
1933
- $wp_styles->registered[$handle]->extra['after'] = null; # dequeue
1934
- }
1935
-
1936
- # process
1937
- if(isset($header[count($header)-1]['handle']) || count($header) == 0 || $header[count($header)-1]['media'] != $mediatype) {
1938
- array_push($header, array('handles'=>array(), 'media'=>$mediatype));
1939
- }
1940
-
1941
- # push it to the array
1942
- array_push($header[count($header)-1]['handles'], $handle);
1943
-
1944
- # external and ignored css
1945
- } else {
1946
-
1947
- # normal enqueuing
1948
- array_push($header, array('handle'=>$handle));
1949
- }
1950
- endforeach;
1951
-
1952
- # reorder CSS by mediatypes
1953
- if(!$skip_cssorder) {
1954
- if(count($header) > 0) {
1955
-
1956
- # get unique mediatypes
1957
- $allmedia = array();
1958
- foreach($header as $array) {
1959
- if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1960
- }
1961
-
1962
- # extract handles by mediatype
1963
- $grouphandles = array();
1964
- foreach ($allmedia as $md=>$var) {
1965
- foreach($header as $array) {
1966
- if (isset($array['media']) && $array['media'] === $md) {
1967
- foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1968
- }
1969
- }
1970
- }
1971
-
1972
- # reset and reorder header by mediatypes
1973
- $newheader = array();
1974
- foreach ($allmedia as $md=>$var) { $newheader[] = array('handles' => $grouphandles[$md], 'media'=>$md); }
1975
- if(count($newheader) > 0) { $header = $newheader; }
1976
- }
1977
- }
1978
-
1979
- # loop through header css and merge
1980
- for($i=0,$l=count($header);$i<$l;$i++) {
1981
- if(!isset($header[$i]['handle'])) {
1982
-
1983
- # get has for the inline css in this group
1984
- $inline_css_group = array();
1985
- foreach($header[$i]['handles'] as $h) { if(isset($inline_css[$h]) && !empty($inline_css[$h])) { $inline_css_group[] = $inline_css[$h]; } }
1986
- $inline_css_hash = md5(implode('',$inline_css_group));
1987
-
1988
- # static cache file info + done
1989
- $done = array_merge($done, $header[$i]['handles']);
1990
- $hash = 'header-'.hash('sha1',implode('',$header[$i]['handles']).$inline_css_hash);
1991
-
1992
- # create cache files and urls
1993
- $file = $cachedir.fastvelocity_get_os_slash().$hash.'.min.css';
1994
- $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'.min.css');
1995
-
1996
- # generate a new cache file
1997
- clearstatcache();
1998
- if (!file_exists($file)) {
1999
-
2000
- # code and log initialization
2001
- $log = '';
2002
- $code = '';
2003
-
2004
- # minify and write to file
2005
- foreach($header[$i]['handles'] as $handle) :
2006
- if(!empty($wp_styles->registered[$handle]->src)) {
2007
-
2008
- # get hurl per handle
2009
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2010
-
2011
- # inlined scripts without file
2012
- if( empty($hurl)) {
2013
- continue;
2014
- }
2015
-
2016
- # print url
2017
- $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
2018
-
2019
- # download, minify, cache
2020
- $tkey = 'css-'.hash('sha1', $handle.$hurl).'.css';
2021
- $json = false; $json = fvm_get_transient($tkey);
2022
- if ( $json === false) {
2023
- $json = fvm_download_and_minify($hurl, null, $disable_css_minification, 'css', $handle);
2024
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
2025
- fvm_set_transient($tkey, $json);
2026
- }
2027
-
2028
- # decode
2029
- $res = json_decode($json, true);
2030
-
2031
- # response has failed
2032
- if($res['status'] != true) {
2033
- $log.= $res['log'];
2034
- continue;
2035
- }
2036
-
2037
- # append code to merged file
2038
- $code.= $res['code'];
2039
- $log.= $res['log'];
2040
-
2041
- # append inlined styles
2042
- if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) {
2043
- $code.= $inline_css[$handle];
2044
- }
2045
-
2046
- # consider dependencies on handles with an empty src
2047
- } else {
2048
- wp_dequeue_script($handle);
2049
- wp_enqueue_script($handle);
2050
- }
2051
- endforeach;
2052
-
2053
- # prepare log
2054
- $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
2055
-
2056
- # generate cache, write log
2057
- if(!empty($code)) {
2058
- file_put_contents($file.'.txt', $log);
2059
- file_put_contents($file, $code);
2060
- file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
2061
-
2062
- # permissions
2063
- fastvelocity_fix_permission_bits($file.'.txt');
2064
- fastvelocity_fix_permission_bits($file);
2065
- fastvelocity_fix_permission_bits($file.'.gz');
2066
-
2067
- # brotli static support
2068
- if(function_exists('brotli_compress')) {
2069
- file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
2070
- fastvelocity_fix_permission_bits($file.'.br');
2071
- }
2072
- }
2073
- }
2074
-
2075
- # register and enqueue minified file, consider excluding of mediatype "print" and inline css
2076
- if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $header[$i]['media'] != 'print')) {
2077
-
2078
- # the developers tab, takes precedence
2079
-
2080
- # Async CSS with loadCSS ?
2081
- if($fvmloadcss != false && $fvm_remove_css != true) {
2082
- $mt = $header[$i]['media'];
2083
- echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$mt.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2084
- echo '<noscript><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /></noscript>';
2085
- echo '<!--[if IE]><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /><![endif]-->';
2086
-
2087
- # enqueue file, if not empty
2088
- } else {
2089
- if(file_exists($file) && filesize($file) > 0) {
2090
-
2091
- # inline CSS if mediatype is not of type "all" (such as mobile only), if the file is smaller than 20KB
2092
- if(filesize($file) < 20000 && $header[$i]['media'] != 'all') {
2093
- echo '<style id="fvm-header-'.$i.'" media="'.$header[$i]['media'].'">'.file_get_contents($file).'</style>';
2094
- } else {
2095
- # enqueue it
2096
- wp_enqueue_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
2097
- }
2098
- } else {
2099
- # file could not be generated, output something meaningful
2100
- echo "<!-- ERROR: FVM was not allowed to save it's cache on - $file -->";
2101
- echo "<!-- Please check if the path above is correct and ensure your server has writting permission there! -->";
2102
- echo "<!-- If you found a bug, please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
2103
- }
2104
- }
2105
- }
2106
-
2107
- # other css need to be requeued for the order of files to be kept
2108
- } else {
2109
- wp_dequeue_style($header[$i]['handle']);
2110
- wp_enqueue_style($header[$i]['handle']);
2111
- }
2112
- }
2113
-
2114
- # remove from queue
2115
- $wp_styles->done = $done;
2116
-
2117
- }
2118
- ###########################################
2119
-
2120
-
2121
- ###########################################
2122
- # process css in the footer ###############
2123
- ###########################################
2124
- function fastvelocity_min_merge_footer_css() {
2125
- global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_debug, $fvm_fawesome_method, $fvm_min_excludecsslist, $force_inline_css_footer;
2126
-
2127
- if(!is_object($wp_styles)) { return false; }
2128
- $ctime = get_option('fvm-last-cache-update', '0');
2129
- $styles = wp_clone($wp_styles);
2130
- $styles->all_deps($styles->queue);
2131
- $done = $styles->done;
2132
- $footer = array();
2133
- $google_fonts = array();
2134
- $inline_css = array();
2135
- $code = '';
2136
- $log = '';
2137
-
2138
- # dequeue all styles
2139
- if($fvm_remove_css != false) {
2140
- foreach( $styles->to_do as $handle ) :
2141
- $done = array_merge($done, array($handle));
2142
- endforeach;
2143
-
2144
- # remove from queue
2145
- $wp_styles->done = $done;
2146
- return false;
2147
- }
2148
-
2149
-
2150
- # add defaults to ignore list
2151
- $ignore = fastvelocity_default_ignore($ignore);
2152
-
2153
- # google fonts to the top
2154
- foreach( $styles->to_do as $handle ) :
2155
-
2156
- # dequeue and get a list of google fonts, or requeue external
2157
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2158
-
2159
- # inlined scripts without file
2160
- if( empty($hurl)) {
2161
- continue;
2162
- }
2163
-
2164
- if (stripos($hurl, 'fonts.googleapis.com') !== false) {
2165
- wp_dequeue_style($handle);
2166
- if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
2167
- if($skip_google_fonts != true || $force_inline_googlefonts != false) {
2168
- $google_fonts[$handle] = $hurl;
2169
- } else {
2170
- wp_enqueue_style($handle); # skip google fonts optimization?
2171
- }
2172
- } else {
2173
- wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
2174
- }
2175
-
2176
- endforeach;
2177
-
2178
-
2179
- # concat google fonts, if enabled
2180
- if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts != false && count($google_fonts) > 0)) {
2181
- foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
2182
-
2183
- # merge google fonts if force inlining is enabled?
2184
- $nfonts = array();
2185
- if($skip_google_fonts != true) {
2186
- $nfonts[] = fvm_get_protocol(fastvelocity_min_concatenate_google_fonts($google_fonts));
2187
- } else {
2188
- foreach ($google_fonts as $a) { if(!empty($a)) { $nfonts[] = $a; } }
2189
- }
2190
-
2191
- # foreach google font (will be one if merged is not disabled)
2192
- if(count($nfonts) > 0) {
2193
- foreach($nfonts as $gfurl) {
2194
-
2195
- # hide from PSI, async, inline, or default
2196
- if($css_hide_googlefonts == true) {
2197
-
2198
- # make a stylesheet, hide from PSI
2199
- $cssguid = 'fvm'.hash('sha1', $gfurl);
2200
- echo '<script type="text/javascript">if(fvmuag()){';
2201
- 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.');';
2202
- echo '}</script>';
2203
-
2204
- # async CSS
2205
- } elseif ($min_async_googlefonts == true) {
2206
- echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2207
- echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
2208
- echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
2209
-
2210
- # inline css
2211
- } elseif($force_inline_googlefonts == true) {
2212
-
2213
- # download, minify, cache
2214
- $tkey = 'css-'.hash('sha1', $gfurl).'.css';
2215
- $json = false; $json = fvm_get_transient($tkey);
2216
- if ( $json === false) {
2217
- $json = fvm_download_and_minify($gfurl, null, $disable_css_minification, 'css', null);
2218
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $gfurl -->" . PHP_EOL; }
2219
- fvm_set_transient($tkey, $json);
2220
- }
2221
-
2222
- # decode
2223
- $res = json_decode($json, true);
2224
-
2225
- # response has failed
2226
- if($res['status'] != true) {
2227
- $log.= $res['log'];
2228
- continue;
2229
- }
2230
-
2231
- # append code to merged file
2232
- $code.= $res['code'];
2233
- $log.= $res['log'];
2234
-
2235
- # inline css or fail
2236
- if($res['code'] !== false) {
2237
- echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2238
- } else {
2239
- echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
2240
- }
2241
-
2242
- # fallback, enqueue google fonts
2243
- } else {
2244
- wp_enqueue_style('footer-fvm-fonts', $gfurl, array(), null, 'all');
2245
- }
2246
-
2247
- }
2248
- }
2249
- }
2250
-
2251
-
2252
- # get groups of handles
2253
- $uniq = array();
2254
- foreach( $styles->to_do as $handle ) :
2255
-
2256
- # skip already processed google fonts
2257
- if(isset($google_fonts[$handle])) { continue; }
2258
-
2259
- # conditionals
2260
- $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
2261
- $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
2262
- }
2263
-
2264
- # mediatype
2265
- $mt = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
2266
- if ($mt == 'screen' || $mt == 'screen, print' || empty($mt) || is_null($mt) || $mt == false) { $mt = 'all'; }
2267
- $mediatype = $mt;
2268
-
2269
- # get full url
2270
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2271
-
2272
- # inlined scripts without file
2273
- if( empty($hurl)) {
2274
- continue;
2275
- }
2276
-
2277
- # mark duplicates as done and remove from the queue
2278
- if(!empty($hurl)) {
2279
- $key = hash('sha1', $hurl);
2280
- if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
2281
- }
2282
-
2283
- # IE only files don't increment things
2284
- $ieonly = fastvelocity_ie_blacklist($hurl);
2285
- if($ieonly == true) { continue; }
2286
-
2287
-
2288
- # Exclude specific CSS files from PSI?
2289
- if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($hurl, $fvm_min_excludecsslist)) {
2290
- $cssguid = 'fvm'.hash('sha1', $hurl);
2291
- echo '<script type="text/javascript">if(fvmuag()){';
2292
- echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2293
- echo '}</script>';
2294
- $done = array_merge($done, array($handle)); continue;
2295
- }
2296
-
2297
- # font awesome processing, async css
2298
- if($fvm_fawesome_method == 2 && stripos($hurl, 'font-awesome') !== false) {
2299
- echo '<link rel="preload" href="'.$hurl.'" as="style" media="'.$mediatype.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2300
- echo '<noscript><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /></noscript>';
2301
- echo '<!--[if IE]><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /><![endif]-->';
2302
- $done = array_merge($done, array($handle)); continue;
2303
- }
2304
-
2305
- # font awesome processing, async and exclude from PSI
2306
- if($fvm_fawesome_method == 3 && stripos($hurl, 'font-awesome') !== false) {
2307
- $cssguid = 'fvm'.hash('sha1', $hurl);
2308
- echo '<script type="text/javascript">if(fvmuag()){';
2309
- echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2310
- echo '}</script>';
2311
- $done = array_merge($done, array($handle)); continue;
2312
- }
2313
-
2314
- # skip ignore list, conditional css, external css, font-awesome merge
2315
- if ( (!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home))
2316
- || empty($hurl)
2317
- || ($fvm_fawesome_method == 1 && stripos($hurl, 'font-awesome') !== false)) {
2318
-
2319
- # colect inline css for this handle
2320
- if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
2321
- $inline_css[$handle] = fastvelocity_min_minify_css_string(implode('', $wp_styles->registered[$handle]->extra['after'])); # save
2322
- $wp_styles->registered[$handle]->extra['after'] = null; # dequeue
2323
- }
2324
-
2325
- # process
2326
- if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0 || $footer[count($footer)-1]['media'] != $wp_styles->registered[$handle]->args) {
2327
- array_push($footer, array('handles'=>array(),'media'=>$mediatype));
2328
- }
2329
-
2330
- # push it to the array get latest modified time
2331
- array_push($footer[count($footer)-1]['handles'], $handle);
2332
-
2333
- # external and ignored css
2334
- } else {
2335
-
2336
- # normal enqueueing
2337
- array_push($footer, array('handle'=>$handle));
2338
- }
2339
- endforeach;
2340
-
2341
-
2342
- # reorder CSS by mediatypes
2343
- if(!$skip_cssorder) {
2344
- if(count($footer) > 0) {
2345
-
2346
- # get unique mediatypes
2347
- $allmedia = array();
2348
- foreach($footer as $key=>$array) {
2349
- if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
2350
- }
2351
-
2352
- # extract handles by mediatype
2353
- $grouphandles = array();
2354
- foreach ($allmedia as $md=>$var) {
2355
- foreach($footer as $array) {
2356
- if (isset($array['media']) && $array['media'] === $md) {
2357
- foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
2358
- }
2359
- }
2360
- }
2361
-
2362
- # reset and reorder footer by mediatypes
2363
- $newfooter = array();
2364
- foreach ($allmedia as $md=>$var) { $newfooter[] = array('handles' => $grouphandles[$md], 'media'=>$md); }
2365
- if(count($newfooter) > 0) { $footer = $newfooter; }
2366
- }
2367
- }
2368
-
2369
- # loop through footer css and merge
2370
- for($i=0,$l=count($footer);$i<$l;$i++) {
2371
- if(!isset($footer[$i]['handle'])) {
2372
-
2373
- # get has for the inline css in this group
2374
- $inline_css_group = array();
2375
- foreach($footer[$i]['handles'] as $h) { if(isset($inline_css[$h]) && !empty($inline_css[$h])) { $inline_css_group[] = $inline_css[$h]; } }
2376
- $inline_css_hash = md5(implode('',$inline_css_group));
2377
-
2378
- # static cache file info + done
2379
- $done = array_merge($done, $footer[$i]['handles']);
2380
- $hash = 'footer-'.hash('sha1',implode('',$footer[$i]['handles']).$inline_css_hash);
2381
-
2382
- # create cache files and urls
2383
- $file = $cachedir.fastvelocity_get_os_slash().$hash.'.min.css';
2384
- $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'.min.css');
2385
-
2386
- # generate a new cache file
2387
- clearstatcache();
2388
- if (!file_exists($file)) {
2389
-
2390
- # code and log initialization
2391
- $log = '';
2392
- $code = '';
2393
-
2394
- # minify and write to file
2395
- foreach($footer[$i]['handles'] as $handle) :
2396
- if(!empty($wp_styles->registered[$handle]->src)) {
2397
-
2398
- # get hurl per handle
2399
- $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2400
-
2401
- # inlined scripts without file
2402
- if( empty($hurl)) {
2403
- continue;
2404
- }
2405
-
2406
- # print url
2407
- $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
2408
-
2409
- # download, minify, cache
2410
- $tkey = 'css-'.hash('sha1', $handle.$hurl).'.css';
2411
- $json = false; $json = fvm_get_transient($tkey);
2412
- if ( $json === false) {
2413
- $json = fvm_download_and_minify($hurl, null, $disable_css_minification, 'css', $handle);
2414
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
2415
- fvm_set_transient($tkey, $json);
2416
- }
2417
-
2418
- # decode
2419
- $res = json_decode($json, true);
2420
-
2421
- # response has failed
2422
- if($res['status'] != true) {
2423
- $log.= $res['log'];
2424
- continue;
2425
- }
2426
-
2427
- # append code to merged file
2428
- $code.= $res['code'];
2429
- $log.= $res['log'];
2430
-
2431
- # append inlined styles
2432
- if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) {
2433
- $code.= $inline_css[$handle];
2434
- }
2435
-
2436
- # consider dependencies on handles with an empty src
2437
- } else {
2438
- wp_dequeue_script($handle);
2439
- wp_enqueue_script($handle);
2440
- }
2441
- endforeach;
2442
-
2443
- # prepare log
2444
- $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
2445
-
2446
- # generate cache, add inline css, write log
2447
- if(!empty($code)) {
2448
- file_put_contents($file.'.txt', $log);
2449
- file_put_contents($file, $code); # preserve style tags
2450
- file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
2451
-
2452
- # permissions
2453
- fastvelocity_fix_permission_bits($file.'.txt');
2454
- fastvelocity_fix_permission_bits($file);
2455
- fastvelocity_fix_permission_bits($file.'.gz');
2456
-
2457
- # brotli static support
2458
- if(function_exists('brotli_compress')) {
2459
- file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
2460
- fastvelocity_fix_permission_bits($file.'.br');
2461
- }
2462
- }
2463
- }
2464
-
2465
- # register and enqueue minified file, consider excluding of mediatype "print" and inline css
2466
- if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $footer[$i]['media'] != 'print')) {
2467
-
2468
- # the developers tab, takes precedence
2469
-
2470
- # Async CSS with loadCSS ?
2471
- if($fvmloadcss != false && $fvm_remove_css != true) {
2472
- $mt = $footer[$i]['media'];
2473
- echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$mt.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2474
- echo '<noscript><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /></noscript>';
2475
- echo '<!--[if IE]><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /><![endif]-->';
2476
-
2477
- # enqueue file, if not empty
2478
- } else {
2479
- if(file_exists($file) && filesize($file) > 0) {
2480
-
2481
- # inline if the file is smaller than 20KB or option has been enabled
2482
- if(filesize($file) < 20000 || $force_inline_css_footer != false) {
2483
- echo '<style id="fvm-footer-'.$i.'" media="'.$footer[$i]['media'].'">'.file_get_contents($file).'</style>';
2484
- } else {
2485
- # enqueue it
2486
- wp_enqueue_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
2487
- }
2488
- } else {
2489
- # file could not be generated, output something meaningful
2490
- echo "<!-- ERROR: FVM was not allowed to save it's cache on - $file -->";
2491
- echo "<!-- Please check if the path above is correct and ensure your server has writting permission there! -->";
2492
- echo "<!-- If you found a bug, please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
2493
- }
2494
- }
2495
- }
2496
-
2497
- # other css need to be requeued for the order of files to be kept
2498
- } else {
2499
- wp_dequeue_style($footer[$i]['handle']);
2500
- wp_enqueue_style($footer[$i]['handle']);
2501
- }
2502
- }
2503
-
2504
- # remove from queue
2505
- $wp_styles->done = $done;
2506
- }
2507
- ###########################################
2508
-
2509
-
2510
-
2511
-
2512
- ###########################################
2513
- # defer CSS globally from the header (order matters)
2514
- # dev: https://www.filamentgroup.com/lab/async-css.html
2515
- ###########################################
2516
- function fvm_add_loadcss() {
2517
-
2518
- echo <<<EOF
2519
- <script>
2520
- /* loadCSS. [c]2017 Filament Group, Inc. MIT License */
2521
- (function(w){if(!w.loadCSS)w.loadCSS=function(){};var rp=loadCSS.relpreload={};rp.support=function(){var ret;try{ret=w.document.createElement("link").relList.supports("preload")}catch(e){ret=false}return function(){return ret}}();rp.bindMediaToggle=function(link){var finalMedia=link.media||"all";function enableStylesheet(){if(link.addEventListener)link.removeEventListener("load",enableStylesheet);else if(link.attachEvent)link.detachEvent("onload",enableStylesheet);link.setAttribute("onload",null);link.media=finalMedia}if(link.addEventListener)link.addEventListener("load",enableStylesheet);else if(link.attachEvent)link.attachEvent("onload",enableStylesheet);setTimeout(function(){link.rel="stylesheet";link.media="only x"});setTimeout(enableStylesheet,3E3)};rp.poly=function(){if(rp.support())return;var links=w.document.getElementsByTagName("link");for(var i=0;i<links.length;i++){var link=links[i];if(link.rel==="preload"&&link.getAttribute("as")==="style"&&!link.getAttribute("data-loadcss")){link.setAttribute("data-loadcss", true);rp.bindMediaToggle(link)}}};if(!rp.support()){rp.poly();var run=w.setInterval(rp.poly,500);if(w.addEventListener)w.addEventListener("load",function(){rp.poly();w.clearInterval(run)});else if(w.attachEvent)w.attachEvent("onload",function(){rp.poly();w.clearInterval(run)})}if(typeof exports!=="undefined")exports.loadCSS=loadCSS;else w.loadCSS=loadCSS})(typeof global!=="undefined"?global:this);
2522
- </script>
2523
- EOF;
2524
-
2525
- }
2526
-
2527
- # fvm load async scripts with callback
2528
- function fvm_add_loadasync() {
2529
- global $fvm_min_excludejslist;
2530
- if($fvm_min_excludejslist != false && is_array($fvm_min_excludejslist) && count($fvm_min_excludejslist) > 0) {
2531
-
2532
- echo <<<EOF
2533
- <script>function loadAsync(e,a){var t=document.createElement("script");t.src=e,null!==a&&(t.readyState?t.onreadystatechange=function(){"loaded"!=t.readyState&&"complete"!=t.readyState||(t.onreadystatechange=null,a())}:t.onload=function(){a()}),document.getElementsByTagName("head")[0].appendChild(t)}</script>
2534
- EOF;
2535
-
2536
- }
2537
- }
2538
-
2539
-
2540
-
2541
- # add inline CSS code / Critical Path
2542
- function fvm_add_criticial_path() {
2543
- $no_global_critical_path_css = false;
2544
- $critical_path_css = get_option('fastvelocity_min_critical_path_css');
2545
- $critical_path_css_is_front_page = get_option('fastvelocity_min_critical_path_css_is_front_page');
2546
-
2547
- # critical path (is_front_page only)
2548
- if(!empty($critical_path_css_is_front_page) && $critical_path_css_is_front_page !== false) {
2549
- echo '<style id="critical-path-is-front-page" type="text/css" media="all">'.$critical_path_css_is_front_page.'</style>'.PHP_EOL;
2550
- $no_global_critical_path_css = 1;
2551
- }
2552
-
2553
- # global path, except if there's something else more specific
2554
- if(!empty($critical_path_css) && $critical_path_css !== false && $no_global_critical_path_css === false) {
2555
- echo '<style id="critical-path-global" type="text/css" media="all">'.$critical_path_css.'</style>'.PHP_EOL;
2556
- }
2557
- }
2558
-
2559
-
2560
-
2561
-
2562
-
2563
- ###########################################
2564
- # add preconnect and preload headers
2565
- ###########################################
2566
- function fvm_extra_preload_headers() {
2567
-
2568
- # fetch headers
2569
- $preload = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_hpreload')));
2570
- $preconnect = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_hpreconnect')));
2571
-
2572
- # preconnect
2573
- if(is_array($preload) && count($preload) > 0) {
2574
- foreach ($preload as $h) {
2575
- if(!empty($h)) {
2576
- header($h, false);
2577
- }
2578
- }
2579
- }
2580
-
2581
- # preload
2582
- if(is_array($preconnect) && count($preconnect) > 0) {
2583
- foreach ($preconnect as $url) {
2584
- if(!empty($url) && filter_var($url, FILTER_VALIDATE_URL)) {
2585
- header("Link: <$url>; rel=preconnect", false);
2586
- }
2587
- }
2588
- }
2589
-
2590
- # fvm css and js generated files
2591
- $fvm_headers = fastvelocity_get_preload_headers();
2592
- if($fvm_headers != false) {
2593
- $nh = array_map('trim', explode(PHP_EOL, $fvm_headers));
2594
- foreach ($nh as $h) {
2595
- if(!empty($h)) {
2596
- header($h, false);
2597
- }
2598
- }
2599
- }
2600
-
2601
- }
2602
-
2603
-
2604
-
2605
- # inline css in place, instead of inlining the large file
2606
- function fastvelocity_optimizecss($html, $handle, $href, $media){
2607
- global $fvm_debug, $wp_domain, $wp_home, $force_inline_css, $fvmualist, $fvm_collect_google_fonts, $force_inline_googlefonts, $min_async_googlefonts, $remove_googlefonts, $skip_google_fonts, $css_hide_googlefonts, $remove_print_mediatypes, $ignore, $blacklist, $ignorelist, $wp_home, $fvmloadcss, $fvm_remove_css, $fvm_cdn_url, $disable_minification, $fvm_min_excludecsslist, $disable_css_minification, $fvm_fix_editor, $fvm_fawesome_method;
2608
-
2609
- # current timestamp
2610
- $ctime = get_option('fvm-last-cache-update', '0');
2611
-
2612
- # make sure href is complete
2613
- $href = fastvelocity_min_get_hurl($href, $wp_domain, $wp_home);
2614
-
2615
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Inline CSS processing start $handle / $href -->" . PHP_EOL; }
2616
-
2617
- # prevent optimization for these locations
2618
- if(fastvelocity_exclude_contents()) {
2619
- return $html;
2620
- }
2621
-
2622
- # skip all this, if the async css option is enabled
2623
- if($fvmloadcss != false) {
2624
- return $html;
2625
- }
2626
-
2627
- # remove all css?
2628
- if($fvm_remove_css != false) {
2629
- return false;
2630
- }
2631
-
2632
- # leave conditionals alone
2633
- $conditional = wp_styles()->get_data($handle, 'conditional');
2634
- if($conditional != false) {
2635
- return $html;
2636
- }
2637
-
2638
- # mediatype fix for some plugins + remove print mediatypes
2639
- if ($media == 'screen' || $media == 'screen, print' || empty($media) || is_null($media) || $media == false) { $media = 'all'; }
2640
- if($remove_print_mediatypes != false && $media == 'print') {
2641
- return false;
2642
- }
2643
-
2644
- # Exclude specific CSS files from PSI?
2645
- if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($href, $fvm_min_excludecsslist)) {
2646
- $cssguid = 'fvm'.hash('sha1', $href);
2647
- echo '<script type="text/javascript">if(fvmuag()){';
2648
- 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.');';
2649
- echo '}</script>';
2650
- return false;
2651
- }
2652
-
2653
- # remove FVM from the ignore list
2654
- array_filter($ignore, function ($var) { return (stripos($var, '/fvm/') === false); });
2655
-
2656
- # return if in any ignore or black list
2657
- if (count($ignore) > 0 && fastvelocity_min_in_arrayi($href, $ignore) || count($blacklist) > 0 && fastvelocity_min_in_arrayi($href, $blacklist) || count($ignorelist) > 0 && fastvelocity_min_in_arrayi($href, $ignorelist)) {
2658
- return $html;
2659
- }
2660
-
2661
- # remove google fonts completely?
2662
- if($remove_googlefonts != false && stripos($href, 'fonts.googleapis.com') !== false) {
2663
- return false;
2664
- }
2665
-
2666
- # handle google fonts here, when merging is disabled
2667
- if(stripos($href, 'fonts.googleapis.com') !== false && $skip_google_fonts != false) {
2668
-
2669
- # hide google fonts from PSI
2670
- if($css_hide_googlefonts == true) {
2671
- $cssguid = 'fvm'.hash('sha1', $href);
2672
- echo '<script type="text/javascript">if(fvmuag()){';
2673
- 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.');';
2674
- echo '}</script>';
2675
- return false;
2676
- }
2677
-
2678
- # load google fonts async
2679
- if($min_async_googlefonts != false) {
2680
- echo '<link rel="preload" href="'.$href.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2681
- echo '<noscript><link rel="stylesheet" href="'.$href.'" media="all" /></noscript>';
2682
- echo '<!--[if IE]><link rel="stylesheet" href="'.$href.'" media="all" /><![endif]-->';
2683
- return false;
2684
- }
2685
- }
2686
-
2687
- # font awesome processing, async css
2688
- if($fvm_fawesome_method == 2 && stripos($href, 'font-awesome') !== false) {
2689
- echo '<link rel="preload" href="'.$href.'" as="style" media="'.$media.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2690
- echo '<noscript><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /></noscript>';
2691
- echo '<!--[if IE]><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /><![endif]-->';
2692
- return false;
2693
- }
2694
-
2695
- # font awesome processing, async and exclude from PSI
2696
- if($fvm_fawesome_method == 3 && stripos($href, 'font-awesome') !== false) {
2697
- $cssguid = 'fvm'.hash('sha1', $href);
2698
- echo '<script type="text/javascript">if(fvmuag()){';
2699
- 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.');';
2700
- echo '}</script>';
2701
- return false;
2702
- }
2703
-
2704
- # font awesome processing, inline
2705
- if($fvm_fawesome_method == 1 && stripos($href, 'font-awesome') !== false) {
2706
-
2707
- # download, minify, cache
2708
- $tkey = 'css-'.hash('sha1', $handle.$href).'.css';
2709
- $json = false; $json = fvm_get_transient($tkey);
2710
- if ( $json === false) {
2711
- $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2712
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2713
- fvm_set_transient($tkey, $json);
2714
- }
2715
-
2716
- # decode
2717
- $res = json_decode($json, true);
2718
-
2719
- # add font-display
2720
- # https://developers.google.com/web/updates/2016/02/font-display
2721
- $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
2722
-
2723
- # inline css or fail
2724
- if($res['status'] != false) {
2725
- echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2726
- return false;
2727
- } else {
2728
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Font Awesome request failed for $href -->" . PHP_EOL; }
2729
- return $html;
2730
- }
2731
- }
2732
-
2733
- # inline google fonts, do not collect
2734
- if(stripos($href, 'fonts.googleapis.com') !== false && $force_inline_googlefonts != false && $css_hide_googlefonts != true && $min_async_googlefonts != true) {
2735
-
2736
- # download, minify, cache
2737
- $tkey = 'css-'.hash('sha1', $handle.$href).'.css';
2738
- $json = false; $json = fvm_get_transient($tkey);
2739
- if ( $json === false) {
2740
- $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2741
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2742
- fvm_set_transient($tkey, $json);
2743
- }
2744
-
2745
- # decode
2746
- $res = json_decode($json, true);
2747
-
2748
- # add font-display
2749
- # https://developers.google.com/web/updates/2016/02/font-display
2750
- $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
2751
-
2752
- # inline css or fail
2753
- if($res['status'] != false) {
2754
- echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2755
- return false;
2756
- } else {
2757
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Google fonts request failed for $href -->" . PHP_EOL; }
2758
- return $html;
2759
- }
2760
- }
2761
-
2762
- # collect and remove google fonts for merging
2763
- if(stripos($href, 'fonts.googleapis.com') !== false){
2764
- $fvm_collect_google_fonts[$handle] = $href;
2765
- return false;
2766
- }
2767
-
2768
- # skip external scripts that are not specifically allowed
2769
- if (fvm_internal_url($href, $wp_home) === false || empty($href)) {
2770
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Skipped the next external enqueued CSS -->" . PHP_EOL; }
2771
- return $html;
2772
- }
2773
-
2774
- # download, minify, cache
2775
- $tkey = 'css-'.hash('sha1', $handle.$href).'.css';
2776
- $json = false; $json = fvm_get_transient($tkey);
2777
- if ( $json === false) {
2778
- $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2779
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2780
- fvm_set_transient($tkey, $json);
2781
- }
2782
-
2783
- # decode
2784
- $res = json_decode($json, true);
2785
-
2786
- # inline it + other inlined children styles
2787
- if($res['status'] != false) {
2788
- echo '<style type="text/css" media="'.$media.'">'.$res['code'].'</style>';
2789
-
2790
- # get inline_styles for this handle, minify and print
2791
- $inline_styles = array();
2792
- $inline_styles = wp_styles()->get_data( $handle, 'after' );
2793
- if($inline_styles != false) {
2794
-
2795
- # string type
2796
- if(is_string($inline_styles)) {
2797
- $code = fastvelocity_min_get_css($href, $inline_styles, $disable_css_minification);
2798
- if(!empty($code) && $code != false) {
2799
- echo '<style type="text/css" media="'.$media.'">'.$code.'</style>';
2800
- }
2801
- }
2802
-
2803
- # array type
2804
- if(is_array($inline_styles)) {
2805
- foreach ($inline_styles as $st) {
2806
- $code = fastvelocity_min_get_css($href, $st, $disable_css_minification);
2807
- if(!empty($code) && $code != false) {
2808
- echo '<style type="text/css" media="'.$media.'">'.$code.'</style>';
2809
- }
2810
- }
2811
- }
2812
- }
2813
-
2814
- # prevent default
2815
- return false;
2816
-
2817
- } else {
2818
- if($fvm_debug == true) { echo "<!-- FVM DEBUG: $handle / $href returned an empty from minification -->" . PHP_EOL; }
2819
- return $html;
2820
- }
2821
-
2822
- # fallback, for whatever reason
2823
- echo "<!-- ERROR: FVM couldn't catch the CSS file below. Please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
2824
- return $html;
2825
- }
2826
-
2827
-
2828
- # critical css for the page
2829
- function fastvelocity_add_google_fonts_merged() {
2830
- global $fvm_collect_google_fonts, $fvmualist, $css_hide_googlefonts, $skip_google_fonts, $min_async_googlefonts, $fvm_debug;
2831
-
2832
- # prevent optimization for logged in users
2833
- if (is_admin() || is_preview() || is_customize_preview()) {
2834
- return false;
2835
- }
2836
-
2837
- # must have something to do
2838
- if(!is_array($fvm_collect_google_fonts) || count($fvm_collect_google_fonts) == 0) {
2839
- return false;
2840
- }
2841
-
2842
- # merge google fonts
2843
- $gfurl = fastvelocity_min_concatenate_google_fonts($fvm_collect_google_fonts);
2844
- if(empty($gfurl)) {
2845
- return false;
2846
- }
2847
-
2848
- # hide google fonts from PSI
2849
- if($css_hide_googlefonts == true) {
2850
-
2851
- # make a stylesheet, hide from PSI
2852
- $cssguid = 'fvm'.hash('sha1', $gfurl);
2853
- echo '<script type="text/javascript">if(fvmuag()){';
2854
- 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.');';
2855
- echo '}</script>';
2856
-
2857
- # load google fonts async
2858
- } elseif($min_async_googlefonts != false) {
2859
- echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2860
- echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
2861
- echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
2862
-
2863
- # fallback to normal inline
2864
- } else {
2865
- echo '<link rel="stylesheet" href="'.$gfurl.'" media="all" />';
2866
- }
2867
-
2868
- # unset per hook
2869
- foreach($fvm_collect_google_fonts as $k=>$v) {
2870
- unset($fvm_collect_google_fonts[$k]);
2871
- }
2872
-
2873
- }
2874
-
2875
-
2876
-
2877
- # collect all fvm JS files and save them to an headers file
2878
- function fastvelocity_collect_js_preload_headers($html, $handle, $src){
2879
- global $cachedirurl, $collect_preload_js, $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2880
-
2881
- # return if disabled
2882
- if ($fvm_enabled_js_preload != true) {
2883
- return $html;
2884
- }
2885
-
2886
- # collect
2887
- if (stripos($src, $cachedirurl) !== false) {
2888
- $collect_preload_js[] = $src;
2889
- }
2890
- return $html;
2891
- }
2892
-
2893
- # generate preload headers file
2894
- function fastvelocity_generate_preload_headers(){
2895
- global $cachedirurl, $collect_preload_css, $collect_preload_js, $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2896
-
2897
- # return if disabled
2898
- if ($fvm_enabled_css_preload != true && $fvm_enabled_js_preload != true) {
2899
- return false;
2900
- }
2901
-
2902
- # get host with multisite support and query strings
2903
- $host = htmlentities($_SERVER['SERVER_NAME']);
2904
- if(empty($hosts)) { $host = htmlentities($_SERVER['HTTP_HOST']); }
2905
- $request_query = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY);
2906
- $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
2907
- $is_admin = strpos( $request_uri, '/wp-admin/' );
2908
-
2909
- # always false for admin pages
2910
- if( false !== $is_admin){
2911
- return false;
2912
- }
2913
-
2914
- # initialize headers
2915
- $headers = array();
2916
-
2917
- # css headers
2918
- if ($fvm_enabled_css_preload != false && is_array($collect_preload_css) && count($collect_preload_css) > 0) {
2919
- foreach($collect_preload_css as $u) {
2920
-
2921
- # filter out footer footer files, because they are not in the critical path
2922
- if(stripos($u, $cachedirurl . '/footer-') !== false) { continue; }
2923
-
2924
- # add headers
2925
- $headers[] = "Link: <$u>; rel=preload; as=style";
2926
- }
2927
- }
2928
-
2929
- # js headers
2930
- if ($fvm_enabled_js_preload != false && is_array($collect_preload_js) && count($collect_preload_js) > 0) {
2931
- foreach($collect_preload_js as $u) {
2932
-
2933
- # filter out footer footer files, because they are not in the critical path
2934
- if(stripos($u, $cachedirurl . '/footer-') !== false) { continue; }
2935
-
2936
- # add headers
2937
- $headers[] = "Link: <$u>; rel=preload; as=script";
2938
- }
2939
- }
2940
-
2941
- # must have something
2942
- if(count($headers) == 0) {
2943
- return false;
2944
- } else {
2945
- $headers = implode(PHP_EOL, $headers);
2946
- }
2947
-
2948
- # get cache path
2949
- $cachepath = fvm_cachepath();
2950
- $headerdir = $cachepath['headerdir'];
2951
- $cachefilebase = $headerdir.'/';
2952
-
2953
- # possible cache file locations
2954
- $b = $cachefilebase . md5($host.'-'.$request_uri).'.header';
2955
- $a = $cachefilebase . md5($host.'-'.$request_uri.$request_query).'.header';
2956
-
2957
- # reset file cache
2958
- clearstatcache();
2959
-
2960
- # if there are no query strings
2961
- if($b == $a) {
2962
- if(!file_exists($a)) {
2963
- file_put_contents($a, $headers);
2964
- fastvelocity_fix_permission_bits($a);
2965
- }
2966
- return false;
2967
- }
2968
-
2969
- # b fallback
2970
- if($b != $a && !file_exists($b)) {
2971
- file_put_contents($b, $headers);
2972
- fastvelocity_fix_permission_bits($b);
2973
- }
2974
-
2975
- return false;
2976
- }
2977
-
2978
-
2979
- # get current headers file for the url
2980
- function fastvelocity_get_preload_headers(){
2981
- global $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2982
-
2983
- # return if disabled
2984
- if ($fvm_enabled_css_preload != true && $fvm_enabled_js_preload != true) {
2985
- return false;
2986
- }
2987
-
2988
- # get host with multisite support and query strings
2989
- $host = htmlentities($_SERVER['SERVER_NAME']);
2990
- if(empty($hosts)) { $host = htmlentities($_SERVER['HTTP_HOST']); }
2991
- $request_query = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY);
2992
- $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
2993
- $is_admin = strpos( $request_uri, '/wp-admin/' );
2994
-
2995
- # always false for admin pages
2996
- if( false !== $is_admin){
2997
- return false;
2998
- }
2999
-
3000
- # get cache path
3001
- $cachepath = fvm_cachepath();
3002
- $headerdir = $cachepath['headerdir'];
3003
- $cachefilebase = $headerdir.'/';
3004
-
3005
- # possible cache file locations
3006
- $b = $cachefilebase . md5($host.'-'.$request_uri).'.header';
3007
- $a = $cachefilebase . md5($host.'-'.$request_uri.$request_query).'.header';
3008
-
3009
- # reset file cache
3010
- clearstatcache();
3011
-
3012
- # return header files or fallback
3013
- if($b == $a && file_exists($a)) { return file_get_contents($a); }
3014
- if($b != $a && file_exists($b)) { return file_get_contents($b); }
3015
-
3016
- return false;
3017
- }
3018
-
3019
-
3020
-
3021
- # cron job to delete old FVM cache
3022
- add_action('fastvelocity_purge_old_cron_event', 'fvm_purge_old');
3023
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Fast Velocity Minify
4
+ Plugin URI: http://fastvelocity.com
5
+ Description: Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS and JavaScript files into groups, compressing HTML and other speed optimizations.
6
+ Author: Raul Peixoto
7
+ Author URI: http://fastvelocity.com
8
+ Version: 2.8.5
9
+ License: GPL2
10
+
11
+ ------------------------------------------------------------------------
12
+ This program is free software; you can redistribute it and/or modify
13
+ it under the terms of the GNU General Public License as published by
14
+ the Free Software Foundation; either version 2 of the License, or
15
+ (at your option) any later version.
16
+
17
+ This program is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ GNU General Public License for more details.
21
+
22
+ You should have received a copy of the GNU General Public License
23
+ along with this program; if not, write to the Free Software
24
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
+ */
26
+
27
+ # check for minimum requirements and prevent activation or disable if not fully compatible
28
+ function fvm_compat_checker() {
29
+ global $wp_version;
30
+
31
+ # defaults
32
+ $error = '';
33
+
34
+ # php version requirements
35
+ if (version_compare( PHP_VERSION, '5.5', '<' )) {
36
+ $error = 'Fast Velocity Minify requires PHP 5.5 or higher. You’re still on '. PHP_VERSION;
37
+ }
38
+
39
+ # php extension requirements
40
+ if (!extension_loaded('mbstring')) {
41
+ $error = 'Fast Velocity Minify requires the PHP mbstring module to be installed on the server.';
42
+ }
43
+
44
+ # wp version requirements
45
+ if ( version_compare( $GLOBALS['wp_version'], '4.5', '<' ) ) {
46
+ $error = 'Fast Velocity Minify requires WP 4.5 or higher. You’re still on ' . $GLOBALS['wp_version'];
47
+ }
48
+
49
+ if ((is_plugin_active(plugin_basename( __FILE__ )) && !empty($error)) || !empty($error)) {
50
+ if (isset($_GET['activate'])) { unset($_GET['activate']); }
51
+ deactivate_plugins( plugin_basename( __FILE__ ));
52
+ add_action('admin_notices', function() use ($error){
53
+ echo '<div class="notice notice-error is-dismissible"><p><strong>'.$error.'</strong></p></div>';
54
+ });
55
+ }
56
+ }
57
+ add_action('admin_init', 'fvm_compat_checker');
58
+
59
+
60
+ # get plugin version
61
+ $fastvelocity_plugin_version_get_data = get_file_data(__FILE__, array('Version' => 'Version'), false);
62
+ $fastvelocity_plugin_version = $fastvelocity_plugin_version_get_data['Version'];
63
+
64
+ # get the plugin directory
65
+ $plugindir = plugin_dir_path( __FILE__ ); # prints with trailing slash
66
+
67
+ # reusable functions
68
+ include($plugindir.'inc/functions.php');
69
+ include($plugindir.'inc/functions-serverinfo.php');
70
+ include($plugindir.'inc/functions-upgrade.php');
71
+ include($plugindir.'inc/functions-cache.php');
72
+
73
+ # wp-cli support
74
+ if ( defined( 'WP_CLI' ) && WP_CLI ) {
75
+ include($plugindir.'inc/functions-cli.php');
76
+ }
77
+
78
+
79
+ # get cache directories and urls
80
+ $cachepath = fvm_cachepath();
81
+ $tmpdir = $cachepath['tmpdir'];
82
+ $cachedir = $cachepath['cachedir'];
83
+ $cachedirurl = $cachepath['cachedirurl'];
84
+
85
+ $wp_home = site_url(); # get the current wordpress installation url
86
+ $wp_domain = trim(str_ireplace(array('http://', 'https://'), '', trim($wp_home, '/')));
87
+ $wp_home_path = ABSPATH;
88
+
89
+ # default globals
90
+ $fastvelocity_min_global_js_done = array();
91
+ $fvm_collect_google_fonts = array();
92
+ $collect_preload_css = array();
93
+ $collect_preload_js = array();
94
+ $fvm_debug = get_option('fastvelocity_fvm_debug');
95
+
96
+ ###########################################
97
+ # build control panel pages ###############
98
+ ###########################################
99
+
100
+ # options from the database, false if not set
101
+ $ignore = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_ignore', ''))));
102
+ $blacklist = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_blacklist', ''))));
103
+ $ignorelist = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_ignorelist', ''))));
104
+ $fvm_min_excludecsslist = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_excludecsslist', ''))));
105
+ $fvm_min_excludejslist = array_filter(array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_excludejslist', ''))));
106
+
107
+ $fvm_enable_purgemenu = get_option('fastvelocity_min_enable_purgemenu');
108
+ $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
109
+ $disable_js_merge = get_option('fastvelocity_min_disable_js_merge');
110
+ $disable_css_merge = get_option('fastvelocity_min_disable_css_merge');
111
+ $disable_js_minification = get_option('fastvelocity_min_disable_js_minification');
112
+ $disable_css_minification = get_option('fastvelocity_min_disable_css_minification');
113
+ $remove_print_mediatypes = get_option('fastvelocity_min_remove_print_mediatypes');
114
+ $skip_html_minification = get_option('fastvelocity_min_skip_html_minification');
115
+ $strip_htmlcomments = get_option('fastvelocity_min_strip_htmlcomments');
116
+ $skip_cssorder = get_option('fastvelocity_min_skip_cssorder');
117
+ $skip_google_fonts = get_option('fastvelocity_min_skip_google_fonts');
118
+ $skip_emoji_removal = get_option('fastvelocity_min_skip_emoji_removal');
119
+ $fvm_clean_header_one = get_option('fastvelocity_fvm_clean_header_one');
120
+ $enable_defer_js = get_option('fastvelocity_min_enable_defer_js');
121
+ $exclude_defer_jquery = get_option('fastvelocity_min_exclude_defer_jquery');
122
+ $force_inline_css = get_option('fastvelocity_min_force_inline_css');
123
+ $force_inline_css_footer = get_option('fastvelocity_min_force_inline_css_footer');
124
+ $remove_googlefonts = get_option('fastvelocity_min_remove_googlefonts');
125
+ $defer_for_pagespeed = get_option('fastvelocity_min_defer_for_pagespeed');
126
+ $defer_for_pagespeed_optimize = get_option('fastvelocity_min_defer_for_pagespeed_optimize');
127
+ $exclude_defer_login = get_option('fastvelocity_min_exclude_defer_login');
128
+ $skip_defer_lists = get_option('fastvelocity_min_skip_defer_lists');
129
+ $fvm_fix_editor = get_option('fastvelocity_min_fvm_fix_editor');
130
+ $fvmloadcss = get_option('fastvelocity_min_loadcss');
131
+ $fvm_remove_css = get_option('fastvelocity_min_fvm_removecss');
132
+ $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
133
+ $fvm_enabled_css_preload = get_option('fastvelocity_enabled_css_preload');
134
+ $fvm_enabled_js_preload = get_option('fastvelocity_enabled_css_preload');
135
+ $fvm_fawesome_method = get_option("fastvelocity_fontawesome_method");
136
+
137
+ # default options
138
+ $used_css_files = array();
139
+ $force_inline_googlefonts = true;
140
+ $min_async_googlefonts = false;
141
+ $css_hide_googlefonts = false;
142
+
143
+
144
+ # define google fonts options based on a radio form
145
+ $fvm_gfonts_method = get_option("fastvelocity_gfonts_method");
146
+ if($fvm_gfonts_method != false) {
147
+ if($fvm_gfonts_method == 2) { # load Async
148
+ $force_inline_googlefonts = false;
149
+ $min_async_googlefonts = true;
150
+ $css_hide_googlefonts = false;
151
+ }
152
+ if($fvm_gfonts_method == 3) { # hide from PSI
153
+ $force_inline_googlefonts = false;
154
+ $min_async_googlefonts = false;
155
+ $css_hide_googlefonts = true;
156
+ }
157
+ }
158
+
159
+
160
+ # default ua list
161
+ $fvmualist = array('x11.*fox\/54', 'oid\s4.*xus.*ome\/62', 'oobot', 'ighth', 'tmetr', 'eadles', 'ingdo');
162
+
163
+ # header and footer markers
164
+ add_action('wp_head','fastvelocity_add_fvmuag', -PHP_INT_MAX);
165
+ function fastvelocity_add_fvmuag() {
166
+ global $fvmualist;
167
+ if(!fastvelocity_exclude_contents() || fastvelocity_load_fvuag()) {
168
+ echo '<script>'.fastvelocity_get_fvmuag($fvmualist).'</script>';
169
+ }
170
+ }
171
+
172
+ # generate fvmuag js function
173
+ function fastvelocity_get_fvmuag($fvmualist) {
174
+ return 'function fvmuag(){if(navigator.userAgent.match(/'.implode('|', $fvmualist).'/i))return!1;if(navigator.userAgent.match(/x11.*ome\/75\.0\.3770\.100/i)){var e=screen.width,t=screen.height;if("number"==typeof e&&"number"==typeof t&&862==t&&1367==e)return!1}return!0}';
175
+ }
176
+
177
+
178
+
179
+ # add admin page and rewrite defaults
180
+ if(is_admin()) {
181
+ add_action('admin_menu', 'fastvelocity_min_admin_menu');
182
+ add_action('admin_enqueue_scripts', 'fastvelocity_min_load_admin_jscss');
183
+ add_action('wp_ajax_fastvelocity_min_files', 'fastvelocity_min_files_callback');
184
+ add_action('admin_init', 'fastvelocity_min_register_settings');
185
+
186
+ # This function runs when WordPress updates or installs/remove something
187
+ add_action('upgrader_process_complete', 'fastvelocity_purge_all_global');
188
+ add_action('after_switch_theme', 'fastvelocity_purge_all_global');
189
+ add_action('admin_init', 'fastvelocity_purge_onsave', 1);
190
+
191
+ # activation, deactivation
192
+ register_activation_hook( __FILE__, 'fastvelocity_plugin_activate' );
193
+ register_deactivation_hook( __FILE__, 'fastvelocity_plugin_deactivate');
194
+ register_uninstall_hook( __FILE__, 'fastvelocity_plugin_uninstall');
195
+
196
+ } else {
197
+ add_action('setup_theme', 'fastvelocity_process_frontend' );
198
+ }
199
+
200
+ function fastvelocity_process_frontend() {
201
+ global $disable_js_merge, $disable_css_merge, $force_inline_css, $skip_emoji_removal, $fvm_clean_header_one, $skip_html_minification, $fvmloadcss, $fvm_fawesome_method, $fvm_gfonts_method;
202
+
203
+ # skip on certain post_types or if there are specific keys on the url or if editor or admin
204
+ if(!fastvelocity_exclude_contents()) {
205
+
206
+ # actions for frontend only
207
+ if(!$disable_js_merge) {
208
+ add_action( 'wp_print_scripts', 'fastvelocity_min_merge_header_scripts', PHP_INT_MAX );
209
+ add_action( 'wp_print_footer_scripts', 'fastvelocity_min_merge_footer_scripts', 9.999999 );
210
+ }
211
+ if(!$disable_css_merge) {
212
+ add_action('wp_head', 'fvm_add_criticial_path', 2);
213
+
214
+ # merge, if inline is not selected
215
+ if($force_inline_css != true) {
216
+ add_action('wp_print_styles', 'fastvelocity_min_merge_header_css', PHP_INT_MAX );
217
+ add_action('wp_print_footer_scripts', 'fastvelocity_min_merge_footer_css', 9.999999 );
218
+ } else {
219
+ add_filter('style_loader_tag', 'fastvelocity_optimizecss', PHP_INT_MAX, 4 );
220
+ add_action('wp_print_styles','fastvelocity_add_google_fonts_merged', PHP_INT_MAX);
221
+ add_action('wp_print_footer_scripts','fastvelocity_add_google_fonts_merged', PHP_INT_MAX );
222
+ }
223
+
224
+ }
225
+ if(!$skip_emoji_removal) {
226
+ add_action( 'init', 'fastvelocity_min_disable_wp_emojicons' );
227
+ add_filter( 'tiny_mce_plugins', 'fastvelocity_disable_emojis_tinymce' );
228
+ }
229
+
230
+ if($fvm_clean_header_one) {
231
+ # no resource hints, generator tag, shortlinks, manifest link, etc
232
+ remove_action('wp_head', 'wp_resource_hints', 2);
233
+ remove_action('wp_head', 'wp_generator');
234
+ remove_action('template_redirect', 'wp_shortlink_header', 11);
235
+ remove_action('wp_head', 'wlwmanifest_link');
236
+ remove_action('wp_head', 'rsd_link');
237
+ remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);
238
+ remove_action('wp_head','feed_links', 2);
239
+ remove_action('wp_head','feed_links_extra', 3);
240
+ add_filter('after_setup_theme', 'fastvelocity_remove_redundant_shortlink');
241
+ }
242
+
243
+ # enable html minification
244
+ if(!$skip_html_minification && !is_admin()) {
245
+ add_action('template_redirect', 'fastvelocity_min_html_compression_start', PHP_INT_MAX);
246
+ }
247
+
248
+ # add the LoadCSS polyfil
249
+ if($fvmloadcss || $fvm_fawesome_method == 2 || $fvm_gfonts_method == 2) {
250
+ add_action('wp_footer', 'fvm_add_loadcss', PHP_INT_MAX);
251
+ }
252
+
253
+ # add the LoadAsync JavaScript function
254
+ add_action('wp_head', 'fvm_add_loadasync', 0);
255
+
256
+ # remove query from static assets and process defering (if enabled)
257
+ add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
258
+ add_filter('script_loader_tag', 'fastvelocity_min_defer_js', 10, 3);
259
+
260
+ # headers
261
+ add_action( 'send_headers', 'fvm_extra_preload_headers' );
262
+ add_action( 'wp_footer', 'fastvelocity_generate_preload_headers', PHP_INT_MAX);
263
+ add_filter( 'script_loader_tag', 'fastvelocity_collect_js_preload_headers', PHP_INT_MAX, 3 );
264
+
265
+ }
266
+ }
267
+
268
+ # exclude processing for editors and administrators (fix editors)
269
+ add_action( 'plugins_loaded', 'fastvelocity_fix_editor' );
270
+ function fastvelocity_fix_editor() {
271
+ global $fvm_fix_editor;
272
+ if($fvm_fix_editor == true && is_user_logged_in()) {
273
+ remove_action('setup_theme', 'fastvelocity_process_frontend' );
274
+ }
275
+ }
276
+
277
+ # create admin menu
278
+ function fastvelocity_min_admin_menu() {
279
+ add_options_page('Fast Velocity Minify Settings', 'Fast Velocity Minify', 'manage_options', 'fastvelocity-min', 'fastvelocity_min_settings');
280
+ }
281
+
282
+
283
+ # add admin toolbar
284
+ if($fvm_enable_purgemenu == true) {
285
+ add_action( 'admin_bar_menu', 'fastvelocity_admintoolbar', 100 );
286
+ }
287
+
288
+ # admin toolbar processing
289
+ function fastvelocity_admintoolbar() {
290
+ if(current_user_can('manage_options')) {
291
+ global $wp_admin_bar;
292
+
293
+ # Create or add new items into the Admin Toolbar.
294
+ $wp_admin_bar->add_node(array(
295
+ 'id' => 'fvm',
296
+ 'title' => '<span class="ab-icon"></span><span class="ab-label">' . __("FVM Purge",'fvm') . '</span>',
297
+ 'href' => wp_nonce_url( add_query_arg('_fvmcache', 'clear'), 'fvm_clear_nonce')
298
+ ));
299
+
300
+ }
301
+ }
302
+
303
+
304
+ # function to list all cache files
305
+ function fastvelocity_min_files_callback() {
306
+
307
+ # must be able to cleanup cache
308
+ if (!current_user_can('manage_options')) {
309
+ wp_die( __('You do not have sufficient permissions to access this page.'));
310
+ }
311
+
312
+ global $cachedir;
313
+
314
+ # default
315
+ $size = fastvelocity_get_cachestats();
316
+ $return = array('js' => array(), 'css' => array(), 'cachesize'=> $size);
317
+
318
+ # inspect directory with opendir, since glob might not be available in some systems
319
+ clearstatcache();
320
+ if ($handle = opendir($cachedir.fastvelocity_get_os_slash())) {
321
+ while (false !== ($file = readdir($handle))) {
322
+ $file = $cachedir.fastvelocity_get_os_slash().$file;
323
+ $ext = pathinfo($file, PATHINFO_EXTENSION);
324
+ if (in_array($ext, array('js', 'css'))) {
325
+ $log = ''; if (file_exists($file.'.txt')) { $log = file_get_contents($file.'.txt'); }
326
+ $mincss = substr($file, 0, -4).'.min.css';
327
+ $minjs = substr($file, 0, -3).'.min.js';
328
+ $filename = basename($file);
329
+ if ($ext == 'css' && file_exists($mincss)) { $filename = basename($mincss); }
330
+ if ($ext == 'js' && file_exists($minjs)) { $filename = basename($minjs); }
331
+ $fsize = fastvelocity_format_filesize(filesize($file));
332
+ $uid = hash('sha1', $filename);
333
+ array_push($return[$ext], array('uid'=>$uid, 'filename' => $filename, 'log' => $log, 'fsize' => $fsize));
334
+ }
335
+ }
336
+ closedir($handle);
337
+ }
338
+
339
+ header('Content-Type: application/json');
340
+ echo json_encode($return);
341
+ wp_die();
342
+ }
343
+
344
+
345
+ # load wp-admin css and js files
346
+ function fastvelocity_min_load_admin_jscss($hook) {
347
+ if ('settings_page_fastvelocity-min' != $hook) { return; }
348
+ wp_enqueue_script('postbox');
349
+ wp_enqueue_style('fastvelocity-min', plugins_url('fvm.css', __FILE__), array(), filemtime(plugin_dir_path( __FILE__).'fvm.css'));
350
+ wp_enqueue_script('fastvelocity-min', plugins_url('fvm.js', __FILE__), array('jquery'), filemtime(plugin_dir_path( __FILE__).'fvm.js'), true);
351
+ }
352
+
353
+
354
+ # register plugin settings
355
+ function fastvelocity_min_register_settings() {
356
+ register_setting('fvm-group', 'fastvelocity_min_enable_purgemenu');
357
+ register_setting('fvm-group', 'fastvelocity_preserve_settings_on_uninstall');
358
+ register_setting('fvm-group', 'fastvelocity_min_default_protocol');
359
+ register_setting('fvm-group', 'fastvelocity_min_disable_js_merge');
360
+ register_setting('fvm-group', 'fastvelocity_min_disable_css_merge');
361
+ register_setting('fvm-group', 'fastvelocity_min_disable_js_minification');
362
+ register_setting('fvm-group', 'fastvelocity_min_disable_css_minification');
363
+ register_setting('fvm-group', 'fastvelocity_min_remove_print_mediatypes');
364
+ register_setting('fvm-group', 'fastvelocity_min_skip_html_minification');
365
+ register_setting('fvm-group', 'fastvelocity_min_strip_htmlcomments');
366
+ register_setting('fvm-group', 'fastvelocity_min_skip_cssorder');
367
+ register_setting('fvm-group', 'fastvelocity_min_skip_google_fonts');
368
+ register_setting('fvm-group', 'fastvelocity_min_skip_fontawesome_fonts');
369
+ register_setting('fvm-group', 'fastvelocity_min_skip_emoji_removal');
370
+ register_setting('fvm-group', 'fastvelocity_fvm_clean_header_one');
371
+ register_setting('fvm-group', 'fastvelocity_min_enable_defer_js');
372
+ register_setting('fvm-group', 'fastvelocity_min_exclude_defer_jquery');
373
+ register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
374
+ register_setting('fvm-group', 'fastvelocity_min_force_inline_css_footer');
375
+ register_setting('fvm-group', 'fastvelocity_min_remove_googlefonts');
376
+ register_setting('fvm-group', 'fastvelocity_gfonts_method');
377
+ register_setting('fvm-group', 'fastvelocity_fontawesome_method');
378
+ register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
379
+ register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed_optimize');
380
+ register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
381
+ register_setting('fvm-group', 'fastvelocity_min_skip_defer_lists');
382
+ register_setting('fvm-group', 'fastvelocity_min_fvm_fix_editor');
383
+ register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_url');
384
+ register_setting('fvm-group', 'fastvelocity_min_fvm_cdn_force');
385
+ register_setting('fvm-group', 'fastvelocity_min_change_cache_base_url');
386
+ register_setting('fvm-group', 'fastvelocity_min_change_cache_path');
387
+
388
+ # pro tab
389
+ register_setting('fvm-group-pro', 'fastvelocity_min_ignore');
390
+ register_setting('fvm-group-pro', 'fastvelocity_min_ignorelist');
391
+ register_setting('fvm-group-pro', 'fastvelocity_min_excludecsslist');
392
+ register_setting('fvm-group-pro', 'fastvelocity_min_excludejslist');
393
+ register_setting('fvm-group-pro', 'fastvelocity_min_blacklist');
394
+ register_setting('fvm-group-pro', 'fastvelocity_min_merge_allowed_urls');
395
+
396
+ # dev tab
397
+ register_setting('fvm-group-dev', 'fastvelocity_fvm_debug');
398
+ register_setting('fvm-group-dev', 'fastvelocity_enabled_css_preload');
399
+ register_setting('fvm-group-dev', 'fastvelocity_enabled_js_preload');
400
+ register_setting('fvm-group-dev', 'fastvelocity_min_hpreload');
401
+ register_setting('fvm-group-dev', 'fastvelocity_min_hpreconnect');
402
+ register_setting('fvm-group-dev', 'fastvelocity_min_loadcss');
403
+ register_setting('fvm-group-dev', 'fastvelocity_min_fvm_removecss');
404
+ register_setting('fvm-group-dev', 'fastvelocity_min_critical_path_css');
405
+ register_setting('fvm-group-dev', 'fastvelocity_min_critical_path_css_is_front_page');
406
+
407
+
408
+
409
+ }
410
+
411
+
412
+
413
+ # add settings link on plugin page
414
+ function fastvelocity_min_settings_link($links) {
415
+ if (is_plugin_active(plugin_basename( __FILE__ ))) {
416
+ $settings_link = '<a href="options-general.php?page=fastvelocity-min&tab=set">Settings</a>';
417
+ array_unshift($links, $settings_link);
418
+ }
419
+ return $links;
420
+ }
421
+ add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
422
+
423
+
424
+ # purge all caches by request
425
+ add_action('init','fastvelocity_process_cache_purge_request');
426
+ function fastvelocity_process_cache_purge_request(){
427
+ if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['_fvmcache'])) {
428
+
429
+ # must be able to cleanup cache
430
+ if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
431
+
432
+ # validate nonce
433
+ if(empty($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'fvm_clear_nonce')) {
434
+ wp_die( __('Invalid or expired request... please go back and refresh before trying again!'));
435
+ }
436
+
437
+ if(is_admin()) {
438
+ fvm_purge_all(); # purge all
439
+ $others = fvm_purge_others(); # purge third party caches
440
+ $notice = array('All caches from <strong>FVM</strong> have been purged!', strip_tags($others, '<strong>'));
441
+ $notice = array_filter($notice);
442
+ $notice = json_encode($notice); # encode
443
+ set_transient( 'wordpress_fvmcache', $notice, 10);
444
+ wp_safe_redirect(remove_query_arg('_wpnonce', remove_query_arg('_fvmcache', wp_get_referer())));
445
+ } else {
446
+ fvm_purge_all(); # purge all
447
+ fvm_purge_others(); # purge third party caches
448
+ wp_safe_redirect(remove_query_arg('_wpnonce', remove_query_arg('_fvmcache', wp_get_referer())));
449
+ }
450
+ }
451
+ }
452
+
453
+ # print admin notices after purging caches, if on wp-admin
454
+ add_action( 'admin_notices', 'fastvelocity_cachepurge_admin_notices' );
455
+ function fastvelocity_cachepurge_admin_notices() {
456
+
457
+ # skip on submit
458
+ if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['_fvmcache'])) {
459
+ return true;
460
+ }
461
+
462
+ # cache purge notices
463
+ $inf = get_transient('wordpress_fvmcache');
464
+ if($inf != false && !empty($inf)) {
465
+
466
+ # decode to array or null
467
+ $jsonarr = json_decode($inf, true);
468
+ if(!is_null($jsonarr) && is_array($jsonarr)){
469
+
470
+ # print notices
471
+ foreach ($jsonarr as $notice) {
472
+ echo __('<div class="notice notice-success is-dismissible"><p>'.$notice.'</p></div>');
473
+ }
474
+ }
475
+
476
+ # remove
477
+ delete_transient('wordpress_fvmcache');
478
+ }
479
+ }
480
+
481
+
482
+ # print admin notices if we don't have enough file permissions to write
483
+ add_action( 'admin_notices', 'fastvelocity_check_permissions_admin_notices' );
484
+ function fastvelocity_check_permissions_admin_notices() {
485
+
486
+ # get cache path
487
+ $cachepath = fvm_cachepath();
488
+ $cachebase = $cachepath['cachebase'];
489
+ if(is_dir($cachebase) && !is_writable($cachebase)) {
490
+ $chmod = substr(sprintf('%o', fileperms($cachebase)), -4);
491
+ echo __('<div class="notice notice-error is-dismissible"><p>FVM needs writting permissions on '.$cachebase.'</p></div>');
492
+ echo __('<div class="notice notice-error is-dismissible"><p>The current permissions for FVM are chmod '.$chmod.'</p></div>');
493
+ echo __('<div class="notice notice-error is-dismissible"><p>If you need something higher than 755 for it to work, your server is probaly misconfigured. Please contact your hosting provider or check the help section for other providers.</p></div>');
494
+ }
495
+
496
+ }
497
+
498
+
499
+ # manage settings page
500
+ function fastvelocity_min_settings() {
501
+ if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
502
+
503
+ # tmp folder
504
+ global $tmpdir, $cachedir, $plugindir;
505
+
506
+ # get active tab, set default
507
+ $active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'status';
508
+
509
+ ?>
510
+ <div class="wrap">
511
+ <h1>Fast Velocity Minify</h1>
512
+
513
+ <h2 class="nav-tab-wrapper wp-clearfix">
514
+ <a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
515
+ <a href="?page=fastvelocity-min&tab=set" class="nav-tab <?php echo $active_tab == 'set' ? 'nav-tab-active' : ''; ?>">Settings</a>
516
+ <a href="?page=fastvelocity-min&tab=pro" class="nav-tab <?php echo $active_tab == 'pro' ? 'nav-tab-active' : ''; ?>">Pro</a>
517
+ <a href="?page=fastvelocity-min&tab=dev" class="nav-tab <?php echo $active_tab == 'dev' ? 'nav-tab-active' : ''; ?>">Developers</a>
518
+ <a href="?page=fastvelocity-min&tab=server" class="nav-tab <?php echo $active_tab == 'server' ? 'nav-tab-active' : ''; ?>">Server Info</a>
519
+ <a href="?page=fastvelocity-min&tab=help" class="nav-tab <?php echo $active_tab == 'help' ? 'nav-tab-active' : ''; ?>">Help</a>
520
+ </h2>
521
+
522
+
523
+ <?php if( $active_tab == 'status' ) { ?>
524
+
525
+ <div id="fastvelocity-min">
526
+ <div id="poststuff">
527
+ <div id="fastvelocity_min_processed" class="postbox-container">
528
+ <div class="meta-box">
529
+
530
+ <div class="postbox" id="tab-purge">
531
+ <h3 class="hndle"><span>Purge the cache files </span></h3>
532
+ <div class="inside" id="fastvelocity_min_topbtns">
533
+ <ul class="processed">
534
+ <li id="purgeall-row">
535
+ <span class="filename">Purge FVM cache (<span id="fvm_cache_size"><?php echo fastvelocity_get_cachestats(); ?></span>)</span>
536
+ <span class="actions">
537
+ <form method="post" id="fastvelocity_min_clearall" action="<?php echo wp_nonce_url( add_query_arg('_fvmcache', 'clear'), 'fvm_clear_nonce'); ?>">
538
+ <input type="hidden" name="purgeall" value="1" />
539
+ <?php submit_button('Delete', 'button-secondary', 'submit', false); ?>
540
+ </form>
541
+ </li>
542
+ </ul>
543
+ </div>
544
+ </div>
545
+
546
+ <div class="postbox" id="tab-js">
547
+ <h3 class="hndle"><span>List of processed JS files</span></h3>
548
+ <div class="inside" id="fastvelocity_min_jsprocessed">
549
+ <ul class="processed"></ul>
550
+ </div>
551
+ </div>
552
+
553
+ <div class="postbox" id="tab-css">
554
+ <h3 class="hndle"><span>List of processed CSS files</span></h3>
555
+ <div class="inside" id="fastvelocity_min_cssprocessed">
556
+ <?php
557
+ $force_inline_css = get_option('fastvelocity_min_force_inline_css');
558
+ if($force_inline_css != false) {
559
+ echo '<p>There are no merged CSS files listed here, because you are inlining all CSS directly.</p>';
560
+ } else {
561
+ echo '<ul class="processed"></ul>';
562
+ }
563
+ ?>
564
+
565
+ </div>
566
+ </div>
567
+
568
+ </div>
569
+ </div>
570
+ </div>
571
+ </div>
572
+ <?php } ?>
573
+
574
+ <?php if( $active_tab == 'set' ) { ?>
575
+ <form method="post" action="options.php">
576
+ <?php settings_fields('fvm-group'); do_settings_sections('fvm-group'); ?>
577
+
578
+
579
+ <div style="height: 20px;"></div>
580
+ <h2 class="title">Basic Settings</h2>
581
+ <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>
582
+
583
+ <table class="form-table fvm-settings">
584
+ <tbody>
585
+
586
+
587
+ <tr>
588
+ <th scope="row">Functionality</th>
589
+ <td>
590
+ <p class="fvm-bold-green fvm-rowintro">The HTML minification is ON by default, but you can:</p>
591
+
592
+ <fieldset>
593
+ <label for="fastvelocity_min_enable_purgemenu">
594
+ <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); ?>>
595
+ 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>
596
+ <br />
597
+
598
+ <label for="fastvelocity_preserve_settings_on_uninstall">
599
+ <input name="fastvelocity_preserve_settings_on_uninstall" type="checkbox" id="fastvelocity_preserve_settings_on_uninstall" value="1" <?php echo checked(1 == get_option('fastvelocity_preserve_settings_on_uninstall'), true, false); ?>>
600
+ Preserve Settings<span class="note-info">[ If selected, all FVM settings will be preserved, even if you uninstall the plugin ]</span></label>
601
+ <br />
602
+
603
+ <label for="fastvelocity_min_fvm_fix_editor">
604
+ <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); ?>>
605
+ 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>
606
+ <br />
607
+
608
+ </fieldset></td>
609
+ </tr>
610
+
611
+
612
+ <tr>
613
+ <th scope="row">URL Options</th>
614
+ <td>
615
+ <?php
616
+ # what to select
617
+ $sel = get_option('fastvelocity_min_default_protocol');
618
+ $a = ''; if($sel == 'dynamic' || empty($sel)) { $a = ' checked="checked"'; }
619
+ $b = ''; if($sel == 'http') { $b = ' checked="checked"'; }
620
+ $c = ''; if($sel == 'https') { $c = ' checked="checked"'; }
621
+ ?>
622
+ <p class="fvm-bold-green fvm-rowintro">You may need to force http or https, for some CDN plugins to work:</p>
623
+ <fieldset>
624
+ <label><input type="radio" name="fastvelocity_min_default_protocol" value="dynamic" <?php echo $a; ?>> Auto Detect </label><br>
625
+ <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>
626
+ <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>
627
+ </fieldset>
628
+ </td>
629
+ </tr>
630
+
631
+ <tr>
632
+ <th scope="row">HTML Options</th>
633
+ <td>
634
+ <p class="fvm-bold-green fvm-rowintro">The HTML minification is ON by default, but you can:</p>
635
+
636
+ <fieldset>
637
+ <label for="fastvelocity_min_skip_html_minification">
638
+ <input name="fastvelocity_min_skip_html_minification" type="checkbox" id="fastvelocity_min_skip_html_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_html_minification'), true, false); ?>>
639
+ Disable HTML Minification <span class="note-info">[ This will disable HTML minification ]</span></label>
640
+ <br />
641
+
642
+ <label for="fastvelocity_min_strip_htmlcomments">
643
+ <input name="fastvelocity_min_strip_htmlcomments" type="checkbox" id="fastvelocity_min_strip_htmlcomments" value="1" <?php echo checked(1 == get_option('fastvelocity_min_strip_htmlcomments'), true, false); ?>>
644
+ 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>
645
+ <br />
646
+
647
+ <label for="fastvelocity_fvm_clean_header_one">
648
+ <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); ?>>
649
+ Cleanup Header <span class="note-info">[ Remove resource hints, generator tag, shortlinks, manifest link, etc ]</span></label>
650
+ <br />
651
+
652
+ </fieldset></td>
653
+ </tr>
654
+
655
+
656
+ <tr>
657
+ <th scope="row">Font Options</th>
658
+ <td>
659
+ <p class="fvm-bold-green fvm-rowintro">The default options are usually good for performance.</p>
660
+ <fieldset>
661
+ <label for="fastvelocity_min_skip_emoji_removal">
662
+ <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); ?> >
663
+ Stop removing Emojis and smileys <span class="note-info">[ If selected, Emojis will be left alone and won't be removed from wordpress ]</span></label>
664
+ <br />
665
+
666
+ <label for="fastvelocity_min_skip_google_fonts">
667
+ <input name="fastvelocity_min_skip_google_fonts" type="checkbox" id="fastvelocity_min_skip_google_fonts" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_google_fonts'), true, false); ?> >
668
+ Disable Google Fonts merging <span class="note-info">[ If selected, Google Fonts will no longer be merged into one request ]</span></label>
669
+ <br />
670
+
671
+ <label for="fastvelocity_min_remove_googlefonts">
672
+ <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); ?> >
673
+ Remove Google Fonts completely <span class="note-info">[ If selected, all enqueued Google Fonts will be removed from the site ]</span></label>
674
+ <br />
675
+
676
+ </fieldset></td>
677
+ </tr>
678
+
679
+
680
+ <tr>
681
+ <th scope="row">Google Fonts</th>
682
+ <td>
683
+ <?php
684
+ # what to select
685
+ $sel = get_option('fastvelocity_gfonts_method');
686
+ $a = ''; if($sel == 1 || empty($sel)) { $a = ' checked="checked"'; }
687
+ $b = ''; if($sel == 2) { $b = ' checked="checked"'; }
688
+ $c = ''; if($sel == 3) { $c = ' checked="checked"'; }
689
+ ?>
690
+ <p class="fvm-bold-green fvm-rowintro">Choose how to include Google Fonts on your pages, when available:</p>
691
+ <fieldset>
692
+ <label><input type="radio" name="fastvelocity_gfonts_method" value="1" <?php echo $a; ?>> Inline Google Fonts CSS</label> <span class="note-info">[ Will inline the <a target="_blank" href="https://caniuse.com/#feat=woff">woof</a> format only (with font hinting) ]</span><br>
693
+ <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>
694
+ <label><input type="radio" name="fastvelocity_gfonts_method" value="3"<?php echo $c; ?>> Async and exclude Google Fonts CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
695
+ </fieldset>
696
+ </td>
697
+ </tr>
698
+
699
+ <tr>
700
+ <th scope="row">Font Awesome</th>
701
+ <td>
702
+ <?php
703
+ # what to select
704
+ $sel = get_option('fastvelocity_fontawesome_method');
705
+ $a = ''; if($sel == 1 || empty($sel)) { $a = ' checked="checked"'; }
706
+ $b = ''; if($sel == 2) { $b = ' checked="checked"'; }
707
+ $c = ''; if($sel == 3) { $c = ' checked="checked"'; }
708
+ ?>
709
+ <p class="fvm-bold-green fvm-rowintro">Only if available and if it has "font-awesome" in the url:</p>
710
+ <fieldset>
711
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="1" <?php echo $a; ?>> Merge or Inline Font Awesome CSS</label> <span class="note-info">[ Depends on if you have the Inline CSS option enabled or not ]</span><br>
712
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="2"<?php echo $b; ?>> Async Font Awesome CSS file</label> <span class="note-info">[ Will use <a target="_blank" href="https://caniuse.com/#feat=link-rel-preload">preload</a> with <a href="https://github.com/filamentgroup/loadCSS">LoadCSS</a> polyfill ]</span><br>
713
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="3"<?php echo $c; ?>> Async and exclude Font Awesome CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
714
+ </fieldset>
715
+ </td>
716
+ </tr>
717
+
718
+
719
+ <tr>
720
+ <th scope="row">CSS Options</th>
721
+ <td>
722
+ <p class="fvm-bold-green fvm-rowintro">It's recommended that you Inline all CSS files, if they are small enough.</p>
723
+
724
+ <fieldset>
725
+ <label for="fastvelocity_min_disable_css_merge">
726
+ <input name="fastvelocity_min_disable_css_merge" type="checkbox" id="fastvelocity_min_disable_css_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_css_merge'), true, false); ?>>
727
+ Disable CSS processing<span class="note-info">[ If selected, this plugin will ignore CSS files completely ]</span></label>
728
+ <br />
729
+ <label for="fastvelocity_min_disable_css_minification">
730
+ <input name="fastvelocity_min_disable_css_minification" type="checkbox" id="fastvelocity_min_disable_css_minification" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_css_minification'), true, false); ?>>
731
+ Disable minification on CSS files <span class="note-info">[ If selected, CSS files will be merged but not minified ]</span></label>
732
+ <br />
733
+ <label for="fastvelocity_min_skip_cssorder">
734
+ <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); ?> >
735
+ 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>
736
+ <br />
737
+ <label for="fastvelocity_min_remove_print_mediatypes">
738
+ <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); ?> >
739
+ Disable the "Print" related stylesheets <span class="note-info">[ If selected, CSS files of mediatype "print" will be removed from the site ]</span></label>
740
+ <br />
741
+ <label for="fastvelocity_min_force_inline_css_footer">
742
+ <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); ?>>
743
+ Inline CSS in the footer <span class="note-info">[ If selected, any FVM generated CSS files in the footer, will be inlined ]</span></label>
744
+ <br />
745
+ <label for="fastvelocity_min_force_inline_css">
746
+ <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); ?>>
747
+ Inline CSS both in the header and footer <span class="note-info">[ If selected, any FVM generated CSS files (header + footer) will be inlined ]</span></label>
748
+ <br />
749
+ </fieldset></td>
750
+ </tr>
751
+
752
+
753
+ <tr>
754
+ <th scope="row">JavaScript Options</th>
755
+ <td>
756
+ <p class="fvm-bold-green fvm-rowintro">Try to disable minification (and purge the cache) first, if you have trouble with JavaScript in the frontend.</p>
757
+ <fieldset>
758
+ <label for="fastvelocity_min_disable_js_merge">
759
+ <input name="fastvelocity_min_disable_js_merge" type="checkbox" id="fastvelocity_min_disable_js_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_merge'), true, false); ?> >
760
+ Disable JavaScript processing <span class="note-info">[ If selected, this plugin will ignore JS files completely ]</span></label>
761
+ <br />
762
+
763
+ <label for="fastvelocity_min_disable_js_minification">
764
+ <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); ?> >
765
+ Disable minification on JS files <span class="note-info">[ If selected, JS files will be merged but not minified ]</span></label>
766
+ <br />
767
+ </fieldset></td>
768
+ </tr>
769
+
770
+ <tr>
771
+ <th scope="row">Render-blocking JS</th>
772
+ <td>
773
+ <fieldset><legend class="screen-reader-text"><span>Render-blocking</span></legend>
774
+
775
+ <p class="fvm-bold-green fvm-rowintro">Some themes and plugins "need" render blocking scripts to work, so please take a look at the dev console for errors.</p>
776
+ <label for="fastvelocity_min_enable_defer_js">
777
+ <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); ?>>
778
+ Enable defer parsing of FVM JS files globally <span class="note-info">[ Not all browsers, themes or plugins support this. Beware of broken functionality and design ]</span></label>
779
+ <br />
780
+
781
+ <label for="fastvelocity_min_exclude_defer_jquery">
782
+ <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); ?> >
783
+ Skip deferring the jQuery library <span class="note-info">[ Will probably fix "undefined jQuery" errors on the Google Chrome console log ]</span></label>
784
+ <br />
785
+ <label for="fastvelocity_min_exclude_defer_login">
786
+ <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); ?> >
787
+ Skip deferring JS on the login page <span class="note-info">[ If selected, will disable JS deferring on your login page ]</span></label>
788
+ <br />
789
+ <label for="fastvelocity_min_skip_defer_lists">
790
+ <input name="fastvelocity_min_skip_defer_lists" type="checkbox" id="fastvelocity_min_skip_defer_lists" value="1" <?php echo checked(1 == get_option('fastvelocity_min_skip_defer_lists'), true, false); ?> >
791
+ Skip deferring the ignore list <span class="note-info">[ If selected, files on the blacklist, ignore list, etc, won't be deferred ]</span></label>
792
+ <br />
793
+
794
+ </fieldset></td>
795
+ </tr>
796
+
797
+ <tr>
798
+ <th scope="row">PageSpeed Settings</th>
799
+ <td>
800
+ <p class="fvm-bold-green fvm-rowintro">Note that this will overwrite any other behaviour defined above and "may" cause errors.</p>
801
+ <fieldset>
802
+ <label for="fastvelocity_min_defer_for_pagespeed">
803
+ <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); ?>>
804
+ Enable defer of all JS files for PSI only <span class="note-info">[ Will use JavaScript to defer all JS files for PSI ]</span></label>
805
+
806
+ <br />
807
+ <label for="fastvelocity_min_defer_for_pagespeed_optimize">
808
+ <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); ?>>
809
+ Exclude JS files in the "ignore list" from PSI <span class="note-info">[ This will hide the "ignored files" from PSI instead of simply deferring ]</span></label>
810
+
811
+ </fieldset></td>
812
+ </tr>
813
+
814
+ </tbody></table>
815
+
816
+
817
+ <div style="height: 20px;"></div>
818
+ <h2 class="title">CDN Options</h2>
819
+ <p class="fvm-bold-green">When the "Enable defer of JS for Pagespeed Insights" option is enabled, JS and CSS files will not be loaded from the CDN due to <a target="_blank" href="https://www.chromestatus.com/feature/5718547946799104">compatibility</a> reasons.<br />However, you can define a CDN Domain below, in order to use it for all of the static assets "inside" your CSS and JS files.</p>
820
+
821
+ <table class="form-table fvm-settings">
822
+ <tbody>
823
+ <tr>
824
+ <th scope="row"><span class="fvm-label-special">Your CDN domain</span></th>
825
+ <td><fieldset>
826
+ <label for="fastvelocity_min_fvm_cdn_url">
827
+ <p><input type="text" name="fastvelocity_min_fvm_cdn_url" id="fastvelocity_min_fvm_cdn_url" value="<?php echo get_option('fastvelocity_min_fvm_cdn_url', ''); ?>" size="80" /></p>
828
+ <p class="description">[ Will rewrite the static assets urls inside FVM merged files to your cdn domain. Usage: cdn.example.com ]</p></label>
829
+ </fieldset>
830
+ </td>
831
+ </tr>
832
+
833
+ <tr>
834
+ <th scope="row">Force the CDN Usage</th>
835
+ <td>
836
+ <p class="fvm-bold-green fvm-rowintro">If you force this, your JS files may not load for certain slow internet users on Google Chrome.</p>
837
+ <fieldset>
838
+ <label for="fastvelocity_min_fvm_cdn_force">
839
+ <input name="fastvelocity_min_fvm_cdn_force" type="checkbox" id="fastvelocity_min_fvm_cdn_force" value="1" <?php echo checked(1 == get_option('fastvelocity_min_fvm_cdn_force'), true, false); ?>>
840
+ I know what I'm doing... <span class="note-info">[ Load my JS files from the CDN, even when "defer for Pagespeed Insights" is enabled ]</span></label>
841
+ </fieldset></td>
842
+ </tr>
843
+
844
+ </tbody></table>
845
+
846
+ <div style="height: 20px;"></div>
847
+ <h2 class="title">Cache Location</h2>
848
+ <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>
849
+ <table class="form-table fvm-settings">
850
+ <tbody>
851
+ <tr>
852
+ <th scope="row"><span class="fvm-label-special">Cache Path</span></th>
853
+ <td><fieldset>
854
+ <label for="fastvelocity_min_change_cache_path">
855
+ <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>
856
+ <p class="description">[ Default cache path is: <?php echo rtrim(wp_upload_dir()['basedir'], '/'); ?> ]</p>
857
+ </label>
858
+ <br />
859
+ <label for="fastvelocity_min_change_cache_base_url">
860
+ <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>
861
+ <p class="description">[ Default cache base url is: <?php echo rtrim(fvm_get_protocol(wp_upload_dir()['baseurl']), '/'); ?> ]</p>
862
+ </label>
863
+ </fieldset></td>
864
+ </tr>
865
+ </tbody></table>
866
+
867
+
868
+ <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
869
+ </form>
870
+ <?php } ?>
871
+
872
+
873
+ <?php if( $active_tab == 'pro' ) { ?>
874
+
875
+ <form method="post" action="options.php">
876
+ <?php settings_fields('fvm-group-pro'); do_settings_sections('fvm-group-pro'); ?>
877
+
878
+
879
+ <div style="height: 20px;"></div>
880
+ <h2 class="title">Special JS and CSS Exceptions</h2>
881
+ <p class="fvm-bold-green">You can use this section to edit or change our default exclusions, as well as to add your own.<br />Make sure you understand the difference between Defer and Async.</p>
882
+ <p class="fvm-bold-green">When you use an option here that uses "Async", styles and scripts load "out of order" and completely independent from the others. That means, the files that end up loading later, will overwrite any previously loaded code. On the other hand, when you use the "ignore list" or when you select an option to "defer", the order of scripts and styles is preserved and should not overwrite previously loaded code, unless there is an higher specificy somewhere else.</p>
883
+
884
+ <div style="height: 20px;"></div>
885
+ <table class="form-table fvm-settings">
886
+ <tbody>
887
+ <tr>
888
+ <th scope="row">Ignore List</th>
889
+ <td><fieldset>
890
+ <label for="blacklist_keys"><span class="fvm-label-pad">Ignore the following CSS and JS paths below:</span></label>
891
+ <p>
892
+ <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>
893
+ </p>
894
+ <p class="description">[ Your own list of js /css files to ignore with wildcard support (read the faqs) ]</p>
895
+ </fieldset></td>
896
+ </tr>
897
+ </tbody></table>
898
+
899
+
900
+ <div style="height: 20px;"></div>
901
+ <table class="form-table fvm-settings">
902
+ <tbody>
903
+ <tr>
904
+ <th scope="row">External URLs to Merge</th>
905
+ <td><fieldset><label for="blacklist_keys"><span class="fvm-label-pad">List of external domains that can be fetched and merged together:</span></label>
906
+ <p>
907
+ <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>
908
+ </p>
909
+ <p class="description">[ Add any external "domains" for JS or CSS files than can be merged fetched and merged together by FVM, ie: cdnjs.cloudflare.com ]</p>
910
+ </fieldset></td>
911
+ </tr>
912
+ </tbody></table>
913
+
914
+
915
+ <div style="height: 20px;"></div>
916
+ <table class="form-table fvm-settings">
917
+ <tbody>
918
+ <tr>
919
+ <th scope="row">Exclude JS files from PSI</th>
920
+ <td><fieldset><label for="fastvelocity_min_excludejslist"><span class="fvm-label-pad">Files will be loaded Async and excluded from PSI:</span></label>
921
+ <p>
922
+ <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>
923
+ </p>
924
+ <p class="description">[ Any JS file that can load Async and completely independent, such as analytics or pixel scripts ]</p>
925
+
926
+ </fieldset></td>
927
+ </tr>
928
+ </tbody></table>
929
+
930
+
931
+ <div style="height: 20px;"></div>
932
+ <table class="form-table fvm-settings">
933
+ <tbody>
934
+ <tr>
935
+ <th scope="row">Exclude CSS files from PSI</th>
936
+ <td><fieldset><label for="fastvelocity_min_excludecsslist"><span class="fvm-label-pad">Files will be loaded Async and excluded from PSI:</span></label>
937
+ <p>
938
+ <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/some-other-font.min.css"><?php echo get_option('fastvelocity_min_excludecsslist'); ?></textarea>
939
+ </p>
940
+ <p class="description">[ Any CSS file that can load completely independent, such as fontawesome or other icons ]</p>
941
+
942
+ </fieldset></td>
943
+ </tr>
944
+ </tbody></table>
945
+
946
+
947
+
948
+
949
+ <div style="height: 20px;"></div>
950
+ <table class="form-table fvm-settings">
951
+ <tbody>
952
+ <tr>
953
+ <th scope="row">Default Ignore List</th>
954
+ <td>
955
+ <fieldset><label for="blacklist_keys"><span class="fvm-label-pad">Do not edit, if you're not sure what this is:</span></label>
956
+ <p>
957
+ <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>
958
+ </p>
959
+ <p class="description">[ Files that have been consistently reported by other users to cause trouble when merged ]</p>
960
+ </fieldset></td>
961
+ </tr>
962
+ </tbody></table>
963
+
964
+ <div style="height: 20px;"></div>
965
+ <table class="form-table fvm-settings">
966
+ <tbody>
967
+ <tr>
968
+ <th scope="row">Default Blacklist</th>
969
+ <td><fieldset><label for="blacklist_keys"><span class="fvm-label-pad">Do not edit, if you're not sure what this is:</span></label>
970
+ <p>
971
+ <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>
972
+ </p>
973
+ <p class="description">[ Usually, any IE css /js files that should always be ignored without incrementing the groups ]</p>
974
+ </fieldset></td>
975
+ </tr>
976
+ </tbody></table>
977
+
978
+
979
+ <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
980
+ </form>
981
+
982
+ <?php
983
+ }
984
+
985
+ # start developers tab
986
+ if( $active_tab == 'dev' ) { ?>
987
+
988
+ <form method="post" action="options.php">
989
+ <?php settings_fields('fvm-group-dev'); do_settings_sections('fvm-group-dev'); ?>
990
+
991
+ <div style="height: 20px;"></div>
992
+ <h2 class="title">Development</h2>
993
+ <p class="fvm-bold-green">This are handy things for the plugin author, but may be of use to you if you are looking to debug some issue.</p>
994
+ <p class="fvm-bold-green">Please note that the automatic headers, are only available after the first, uncached pageview (you may need to purge your cache to see them, or your server may not support this at all).</p>
995
+
996
+ <table class="form-table fvm-settings">
997
+ <tbody>
998
+ <tr>
999
+ <th scope="row">Dev Options</th>
1000
+ <td><fieldset>
1001
+ <label for="fastvelocity_fvm_debug">
1002
+ <input name="fastvelocity_fvm_debug" type="checkbox" id="fastvelocity_fvm_debug" value="1" <?php echo checked(1 == get_option('fastvelocity_fvm_debug'), true, false); ?>>
1003
+ Enable FVM Debug Mode<span class="note-info">[ Add extra info to the "status page" logs as well as some comments on the HTML frontend (beta) ]</span></label>
1004
+
1005
+ <br />
1006
+ <label for="fastvelocity_enabled_css_preload">
1007
+ <input name="fastvelocity_enabled_css_preload" type="checkbox" id="fastvelocity_enabled_css_preload" value="1" <?php echo checked(1 == get_option('fastvelocity_enabled_css_preload'), true, false); ?>>
1008
+ Enable FVM CSS files Preload<span class="note-info">[ Automatically create http headers for FVM generated CSS files (when not inlined) ]</span></label>
1009
+
1010
+ <br />
1011
+ <label for="fastvelocity_enabled_js_preload">
1012
+ <input name="fastvelocity_enabled_js_preload" type="checkbox" id="fastvelocity_enabled_js_preload" value="1" <?php echo checked(1 == get_option('fastvelocity_enabled_js_preload'), true, false); ?>>
1013
+ Enable FVM JS files Preload<span class="note-info">[ Automatically create http headers for FVM generated JS files ]</span></label>
1014
+
1015
+
1016
+ </fieldset>
1017
+ </td>
1018
+ </tr>
1019
+ </tbody></table>
1020
+
1021
+
1022
+
1023
+
1024
+
1025
+
1026
+ <div style="height: 20px;"></div>
1027
+ <h2 class="title">HTTP Headers</h2>
1028
+ <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>
1029
+ <p class="fvm-bold-green">Preload Headers: Use this for preloading specific, high priority resources that exist across all of your pages.</p>
1030
+ <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>
1031
+
1032
+ <table class="form-table fvm-settings">
1033
+ <tbody>
1034
+ <tr>
1035
+ <th scope="row">Preconnect Headers</th>
1036
+ <td><fieldset><legend class="screen-reader-text"><span>Preconnect</span></legend>
1037
+ <label for="fastvelocity_min_hpreconnect"><span class="fvm-label-pad">Use only the strictly minimum necessary domain names, (cdn or frequent embeds):</span></label>
1038
+ <p>
1039
+ <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>
1040
+ </p>
1041
+ <p class="description">[ Use the complete scheme (http:// or https://) followed by the domain name only (no file paths). ]</p>
1042
+ <p class="description">[ Examples: ]</p>
1043
+ <p class="description">https://fonts.googleapis.com</p>
1044
+ <p class="description">https://fonts.gstatic.com</p>
1045
+ </fieldset></td>
1046
+ </tr>
1047
+
1048
+ </tbody></table>
1049
+
1050
+ <table class="form-table fvm-settings">
1051
+ <tbody>
1052
+ <tr>
1053
+ <th scope="row">Preload Headers</th>
1054
+ <td><fieldset><legend class="screen-reader-text"><span>Preload Headers</span></legend>
1055
+ <label for="fastvelocity_min_hpreload"><span class="fvm-label-pad">Insert your "complete php header code" here:</span></label>
1056
+ <p>
1057
+ <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>
1058
+ </p>
1059
+ <p class="description">[ Example of a "complete php header code" to paste above ]</p>
1060
+ <p class="description">Link: &lt;https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVZ0d.woff&gt;; rel=preload; as=font; crossorigin</p>
1061
+ <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>
1062
+ </fieldset></td>
1063
+ </tr>
1064
+ </tbody></table>
1065
+
1066
+
1067
+ <div style="height: 20px;"></div>
1068
+ <h2 class="title">Async CSS</h2>
1069
+ <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>
1070
+
1071
+ <table class="form-table fvm-settings">
1072
+ <tbody>
1073
+ <tr>
1074
+ <th scope="row">Enable Async CSS</th>
1075
+ <td><fieldset>
1076
+ <label for="fastvelocity_min_loadcss">
1077
+ <input name="fastvelocity_min_loadcss" type="checkbox" id="fastvelocity_min_loadcss" value="1" <?php echo checked(1 == get_option('fastvelocity_min_loadcss'), true, false); ?>>
1078
+ Async CSS with LoadCSS <span class="note-info">[ Note that inline CSS won't work if this is active ]</span></label>
1079
+
1080
+ <br />
1081
+ <label for="fastvelocity_min_fvm_removecss">
1082
+ <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); ?>>
1083
+ Dequeue all CSS files <span class="note-info">[ Use this if you want to test how your Critical Path CSS looks like ]</span></label>
1084
+
1085
+ </fieldset>
1086
+ </td>
1087
+ </tr>
1088
+
1089
+ </tbody></table>
1090
+
1091
+
1092
+ <div style="height: 20px;"></div>
1093
+ <h2 class="title">Critical Path CSS</h2>
1094
+ <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>
1095
+ <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>
1096
+ <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>
1097
+
1098
+ <table class="form-table fvm-settings">
1099
+ <tbody>
1100
+
1101
+ <tr>
1102
+ <th scope="row">Fallback CSS</th>
1103
+ <td>
1104
+ <fieldset>
1105
+ <p>
1106
+ <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>
1107
+ </p>
1108
+ <p class="description">[ It will be overwritten, if some other more specific critical path code exists below ]</p>
1109
+ </fieldset>
1110
+ </td>
1111
+ </tr>
1112
+
1113
+ <tr>
1114
+ <th scope="row">is_front_page (conditional)</th>
1115
+ <td>
1116
+ <fieldset>
1117
+ <p>
1118
+ <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>
1119
+ </p>
1120
+ <p class="description">[ Will show up if your page matches the WP conditional, is_front_page() ]</p>
1121
+ </fieldset>
1122
+ </td>
1123
+ </tr>
1124
+
1125
+ </tbody></table>
1126
+
1127
+
1128
+
1129
+ <p class="submit"><input type="submit" name="fastvelocity_min_save_options" id="fastvelocity_min_save_options" class="button button-primary" value="Save Changes"></p>
1130
+ </form>
1131
+
1132
+ <?php
1133
+ }
1134
+
1135
+
1136
+ # start server info tab
1137
+ if( $active_tab == 'server' ) {
1138
+ fvm_get_generalinfo();
1139
+ }
1140
+
1141
+
1142
+ # start help tab
1143
+ if( $active_tab == 'help' ) { ?>
1144
+
1145
+ <div class="wrap" id="fastvelocity-min">
1146
+ <div id="poststuff">
1147
+ <div id="fastvelocity_min_processed" class="postbox-container">
1148
+ <div class="meta-box-sortables ui-sortable">
1149
+
1150
+ <div class="postbox" id="tab-info">
1151
+ <h3 class="hndle"><span>Paid Clients / Custom Requests</span></h3>
1152
+ <div class="inside">
1153
+ <p>Please Visit: <a href="https://www.upwork.com/fl/fvmpeixoto">https://www.upwork.com/fl/fvmpeixoto</a></p>
1154
+ <p>Alternatively: <a href="https://fastvelocity.com/">https://fastvelocity.com/</a></p>
1155
+ </div>
1156
+ </div>
1157
+
1158
+ <div class="postbox" id="tab-info">
1159
+ <h3 class="hndle"><span>Frequently Asked Questions</span></h3>
1160
+ <div class="inside">
1161
+ <p>Please Visit: <a href="https://wordpress.org/plugins/fast-velocity-minify/#faq">https://wordpress.org/plugins/fast-velocity-minify/#faq</a></p>
1162
+ </div>
1163
+ </div>
1164
+
1165
+ <div class="postbox" id="tab-info">
1166
+ <h3 class="hndle"><span>Open Source Support / Bug Report</span></h3>
1167
+ <div class="inside">
1168
+ <p>Please Visit: <a href="https://wordpress.org/support/plugin/fast-velocity-minify">https://wordpress.org/support/plugin/fast-velocity-minify</a></p>
1169
+ </div>
1170
+ </div>
1171
+
1172
+ <div class="postbox" id="tab-info">
1173
+ <h3 class="hndle"><span>Need faster hosting?</span></h3>
1174
+ <div class="inside">
1175
+ <p>Digital Ocean: (aff) <a href="https://m.do.co/c/039860472caf">https://www.digitalocean.com/</a></p>
1176
+ <p>Vultr: (aff) <a href="https://www.vultr.com/?ref=6879450">https://www.vultr.com/</a></p>
1177
+ <p>Linode: (aff) <a href="https://www.linode.com/?r=4b0ae524a0e54b1c11abb8014be4068f5a5d607a">https://www.linode.com/</a></p>
1178
+ <p>Amazon Lightsail: <a href="https://aws.amazon.com/lightsail/">https://aws.amazon.com/lightsail/</a></p>
1179
+ <p>Google Cloud: <a href="https://cloud.google.com/">https://cloud.google.com/</a></p>
1180
+ </div>
1181
+ </div>
1182
+
1183
+ <div class="postbox" id="tab-info">
1184
+ <h3 class="hndle"><span>Donations (Thank You)</span></h3>
1185
+ <div class="inside">
1186
+ <p>PayPal: <a href="https://goo.gl/vpLrSV">https://goo.gl/vpLrSV</a><br /></p>
1187
+ </div>
1188
+ </div>
1189
+
1190
+ </div>
1191
+ </div>
1192
+ </div>
1193
+ </div>
1194
+
1195
+ <?php } ?>
1196
+
1197
+
1198
+
1199
+ </div>
1200
+
1201
+ <div class="clear"></div>
1202
+
1203
+ <?php
1204
+ }
1205
+
1206
+
1207
+ ###########################################
1208
+ # process header javascript ###############
1209
+ ###########################################
1210
+ function fastvelocity_min_merge_header_scripts() {
1211
+ global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery, $fvm_debug, $fvm_min_excludejslist, $fvmualist;
1212
+ if(!is_object($wp_scripts)) { return false; }
1213
+ $scripts = wp_clone($wp_scripts);
1214
+ $scripts->all_deps($scripts->queue);
1215
+ $ctime = get_option('fvm-last-cache-update', '0');
1216
+ $header = array();
1217
+
1218
+ # mark as done (as we go)
1219
+ $done = $scripts->done;
1220
+
1221
+ # add defaults to ignore list
1222
+ $ignore = fastvelocity_default_ignore($ignore);
1223
+
1224
+ # get groups of handles
1225
+ foreach( $scripts->to_do as $handle ) :
1226
+
1227
+ # is it a footer script?
1228
+ $is_footer = 0;
1229
+ if (isset($wp_scripts->registered[$handle]->extra["group"]) || isset($wp_scripts->registered[$handle]->args)) {
1230
+ $is_footer = 1;
1231
+ }
1232
+
1233
+ # skip footer scripts for now
1234
+ if($is_footer != 1) {
1235
+
1236
+ # get full url
1237
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1238
+
1239
+ # inlined scripts without file
1240
+ if( empty($hurl)) {
1241
+ continue;
1242
+ }
1243
+
1244
+ # Exclude JS files from PSI (Async) takes priority over the ignore list
1245
+ if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
1246
+
1247
+ # check for string match
1248
+ $skipjs = false;
1249
+ foreach($fvm_min_excludejslist as $l) {
1250
+ if (stripos($hurl, $l) !== false) {
1251
+ # print code if there are no linebreaks, or return
1252
+ echo '<script type="text/javascript">if(fvmuag()){';
1253
+ echo "loadAsync('$hurl', null);";
1254
+ echo '}</script>';
1255
+ $skipjs = true;
1256
+ break;
1257
+ }
1258
+ }
1259
+ if($skipjs != false) { continue; }
1260
+ }
1261
+
1262
+
1263
+ # IE only files don't increment things
1264
+ $ieonly = fastvelocity_ie_blacklist($hurl);
1265
+ if($ieonly == true) { continue; }
1266
+
1267
+ # skip ignore list, scripts with conditionals, external scripts
1268
+ if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1269
+
1270
+ # process
1271
+ if(isset($header[count($header)-1]['handle']) || count($header) == 0) {
1272
+ array_push($header, array('handles'=>array()));
1273
+ }
1274
+
1275
+ # push it to the array
1276
+ array_push($header[count($header)-1]['handles'], $handle);
1277
+
1278
+ # external and ignored scripts
1279
+ } else {
1280
+ array_push($header, array('handle'=>$handle));
1281
+ }
1282
+
1283
+ # make sure that the scripts skipped here, show up in the footer
1284
+ } else {
1285
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1286
+
1287
+ # inlined scripts without file
1288
+ if( empty($hurl)) {
1289
+ wp_enqueue_script($handle, false);
1290
+ } else {
1291
+ wp_enqueue_script($handle, $hurl, array(), null, true);
1292
+ }
1293
+ }
1294
+ endforeach;
1295
+
1296
+ # loop through header scripts and merge
1297
+ for($i=0,$l=count($header);$i<$l;$i++) {
1298
+ if(!isset($header[$i]['handle'])) {
1299
+
1300
+ # static cache file info + done
1301
+ $done = array_merge($done, $header[$i]['handles']);
1302
+ $hash = 'header-'.hash('sha1',implode('',$header[$i]['handles']));
1303
+
1304
+ # create cache files and urls
1305
+ $file = $cachedir.fastvelocity_get_os_slash().$hash.'.min.js';
1306
+ $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'.min.js');
1307
+
1308
+ # generate a new cache file
1309
+ clearstatcache();
1310
+ if (!file_exists($file)) {
1311
+
1312
+ # code and log initialization
1313
+ $log = '';
1314
+ $code = '';
1315
+
1316
+ # minify and write to file
1317
+ foreach($header[$i]['handles'] as $handle) :
1318
+ if(!empty($wp_scripts->registered[$handle]->src)) {
1319
+
1320
+ # get hurl per handle
1321
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1322
+
1323
+ # inlined scripts without file
1324
+ if( empty($hurl)) {
1325
+ continue;
1326
+ }
1327
+
1328
+ # print url
1329
+ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1330
+
1331
+ # download, minify, cache
1332
+ $tkey = 'js-'.hash('sha1', $handle.$hurl).'.js';
1333
+ $json = false; $json = fvm_get_transient($tkey);
1334
+ if ( $json === false) {
1335
+ $json = fvm_download_and_minify($hurl, null, $disable_js_minification, 'js', $handle);
1336
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
1337
+ fvm_set_transient($tkey, $json);
1338
+ }
1339
+
1340
+ # decode
1341
+ $res = json_decode($json, true);
1342
+
1343
+ # response has failed
1344
+ if($res['status'] != true) {
1345
+ $log.= $res['log'];
1346
+ continue;
1347
+ }
1348
+
1349
+ # Add child data before anything else
1350
+ if (!empty($wp_scripts->registered[$handle]->extra)){
1351
+ if (!empty($wp_scripts->registered[$handle]->extra['data'])){
1352
+ $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $wp_scripts->registered[$handle]->extra['data']));
1353
+ }
1354
+ }
1355
+
1356
+
1357
+ # Add extra data from wp_add_inline_script before
1358
+ if (!empty($wp_scripts->registered[$handle]->extra)){
1359
+ if (isset($wp_scripts->registered[$handle]->extra['before'])){
1360
+ if(is_array($wp_scripts->registered[$handle]->extra['before'])) {
1361
+ $arr = array_filter($wp_scripts->registered[$handle]->extra['before']);
1362
+ $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $arr));
1363
+ }
1364
+ }
1365
+ }
1366
+
1367
+ # append code to merged file
1368
+ $code.= "/* $hurl */". PHP_EOL . fastvelocity_try_catch_wrap($res['code']);
1369
+ $log.= $res['log'];
1370
+
1371
+ # Add extra data from wp_add_inline_script after
1372
+ if (!empty($wp_scripts->registered[$handle]->extra)){
1373
+ if (isset($wp_scripts->registered[$handle]->extra['after'])){
1374
+ if(is_array($wp_scripts->registered[$handle]->extra['after'])) {
1375
+ $arr = array_filter($wp_scripts->registered[$handle]->extra['after']);
1376
+ $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $arr));
1377
+ }
1378
+ }
1379
+ }
1380
+
1381
+ # consider dependencies on handles with an empty src
1382
+ } else {
1383
+ wp_dequeue_script($handle); wp_enqueue_script($handle);
1384
+ }
1385
+ endforeach;
1386
+
1387
+ # prepare log
1388
+ $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
1389
+
1390
+ # generate cache, write log
1391
+ if(!empty($code)) {
1392
+ file_put_contents($file.'.txt', $log);
1393
+ file_put_contents($file, $code);
1394
+ file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1395
+
1396
+ # permissions
1397
+ fastvelocity_fix_permission_bits($file.'.txt');
1398
+ fastvelocity_fix_permission_bits($file);
1399
+ fastvelocity_fix_permission_bits($file.'.gz');
1400
+
1401
+ # brotli static support
1402
+ if(function_exists('brotli_compress')) {
1403
+ file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
1404
+ fastvelocity_fix_permission_bits($file.'.br');
1405
+ }
1406
+ }
1407
+ }
1408
+
1409
+ # register minified file
1410
+ wp_register_script("fvm-header-$i", $file_url, array(), null, false);
1411
+
1412
+ # add all extra data from wp_localize_script
1413
+ $data = array();
1414
+ foreach($header[$i]['handles'] as $handle) {
1415
+ if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1416
+ }
1417
+ if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1418
+
1419
+ # enqueue file, if not empty
1420
+ if(file_exists($file) && (filesize($file) > 0 || count($data) > 0)) {
1421
+ wp_enqueue_script("fvm-header-$i");
1422
+ } else {
1423
+ # file could not be generated, output something meaningful
1424
+ echo "<!-- ERROR: FVM was not allowed to save it's cache on - $file -->";
1425
+ echo "<!-- Please check if the path above is correct and ensure your server has writting permission there! -->";
1426
+ echo "<!-- If you found a bug, please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
1427
+ }
1428
+
1429
+ # other scripts need to be requeued for the order of files to be kept
1430
+ } else {
1431
+ wp_dequeue_script($header[$i]['handle']);
1432
+ wp_enqueue_script($header[$i]['handle']);
1433
+ }
1434
+ }
1435
+
1436
+ # remove from queue
1437
+ $wp_scripts->done = $done;
1438
+ }
1439
+ ###########################################
1440
+
1441
+
1442
+
1443
+ ###########################################
1444
+ # process js in the footer ################
1445
+ ###########################################
1446
+ function fastvelocity_min_merge_footer_scripts() {
1447
+ global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery, $fvm_debug, $fvm_min_excludejslist, $fvmualist;
1448
+ if(!is_object($wp_scripts)) { return false; }
1449
+ $ctime = get_option('fvm-last-cache-update', '0');
1450
+ $scripts = wp_clone($wp_scripts);
1451
+ $scripts->all_deps($scripts->queue);
1452
+ $footer = array();
1453
+
1454
+ # mark as done (as we go)
1455
+ $done = $scripts->done;
1456
+
1457
+ # add defaults to ignore list
1458
+ $ignore = fastvelocity_default_ignore($ignore);
1459
+
1460
+
1461
+ # get groups of handles
1462
+ foreach( $scripts->to_do as $handle ) :
1463
+
1464
+ # get full url
1465
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1466
+
1467
+ # inlined scripts without file
1468
+ if( empty($hurl)) {
1469
+ continue;
1470
+ }
1471
+
1472
+ # Exclude JS files from PSI (Async) takes priority over the ignore list
1473
+ if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
1474
+
1475
+ # check for string match
1476
+ $skipjs = false;
1477
+ foreach($fvm_min_excludejslist as $l) {
1478
+ if (stripos($hurl, $l) !== false) {
1479
+ # print code if there are no linebreaks, or return
1480
+ echo '<script type="text/javascript">if(fvmuag()){';
1481
+ echo "loadAsync('$hurl', null);";
1482
+ echo '}</script>';
1483
+ $skipjs = true;
1484
+ break;
1485
+ }
1486
+ }
1487
+ if($skipjs != false) { continue; }
1488
+ }
1489
+
1490
+ # IE only files don't increment things
1491
+ $ieonly = fastvelocity_ie_blacklist($hurl);
1492
+ if($ieonly == true) { continue; }
1493
+
1494
+ # skip ignore list, scripts with conditionals, external scripts
1495
+ if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
1496
+
1497
+ # process
1498
+ if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0) {
1499
+ array_push($footer, array('handles'=>array()));
1500
+ }
1501
+
1502
+ # push it to the array
1503
+ array_push($footer[count($footer)-1]['handles'], $handle);
1504
+
1505
+ # external and ignored scripts
1506
+ } else {
1507
+ array_push($footer, array('handle'=>$handle));
1508
+ }
1509
+ endforeach;
1510
+
1511
+ # loop through footer scripts and merge
1512
+ for($i=0,$l=count($footer);$i<$l;$i++) {
1513
+ if(!isset($footer[$i]['handle'])) {
1514
+
1515
+ # static cache file info + done
1516
+ $done = array_merge($done, $footer[$i]['handles']);
1517
+ $hash = 'footer-'.hash('sha1',implode('',$footer[$i]['handles']));
1518
+
1519
+ # create cache files and urls
1520
+ $file = $cachedir.fastvelocity_get_os_slash().$hash.'.min.js';
1521
+ $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'.min.js');
1522
+
1523
+ # generate a new cache file
1524
+ clearstatcache();
1525
+ if (!file_exists($file)) {
1526
+
1527
+ # code and log initialization
1528
+ $log = '';
1529
+ $code = '';
1530
+
1531
+ # minify and write to file
1532
+ foreach($footer[$i]['handles'] as $handle) :
1533
+ if(!empty($wp_scripts->registered[$handle]->src)) {
1534
+
1535
+ # get hurl per handle
1536
+ $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1537
+
1538
+ # inlined scripts without file
1539
+ if( empty($hurl)) {
1540
+ continue;
1541
+ }
1542
+
1543
+ # print url
1544
+ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
1545
+
1546
+
1547
+ # download, minify, cache
1548
+ $tkey = 'js-'.hash('sha1', $handle.$hurl).'.js';
1549
+ $json = false; $json = fvm_get_transient($tkey);
1550
+ if ( $json === false) {
1551
+ $json = fvm_download_and_minify($hurl, null, $disable_js_minification, 'js', $handle);
1552
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
1553
+ fvm_set_transient($tkey, $json);
1554
+ }
1555
+
1556
+ # decode
1557
+ $res = json_decode($json, true);
1558
+
1559
+ # response has failed
1560
+ if($res['status'] != true) {
1561
+ $log.= $res['log'];
1562
+ continue;
1563
+ }
1564
+
1565
+
1566
+ # Add child data before anything else
1567
+ if (!empty($wp_scripts->registered[$handle]->extra)){
1568
+ if (!empty($wp_scripts->registered[$handle]->extra['data'])){
1569
+ $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $wp_scripts->registered[$handle]->extra['data']));
1570
+ }
1571
+ }
1572
+
1573
+
1574
+ # Add extra data from wp_add_inline_script before
1575
+ if (!empty($wp_scripts->registered[$handle]->extra)){
1576
+ if (isset($wp_scripts->registered[$handle]->extra['before'])){
1577
+ if(is_array($wp_scripts->registered[$handle]->extra['before'])) {
1578
+ $arr = array_filter($wp_scripts->registered[$handle]->extra['before']);
1579
+ $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $arr));
1580
+ }
1581
+ }
1582
+ }
1583
+
1584
+ # append code to merged file
1585
+ $code.= "/* $hurl */". PHP_EOL . fastvelocity_try_catch_wrap($res['code']);
1586
+ $log.= $res['log'];
1587
+
1588
+ # Add extra data from wp_add_inline_script after
1589
+ if (!empty($wp_scripts->registered[$handle]->extra)){
1590
+ if (isset($wp_scripts->registered[$handle]->extra['after'])){
1591
+ if(is_array($wp_scripts->registered[$handle]->extra['after'])) {
1592
+ $arr = array_filter($wp_scripts->registered[$handle]->extra['after']);
1593
+ $code.= PHP_EOL . fastvelocity_try_catch_wrap(implode(PHP_EOL, $arr));
1594
+ }
1595
+ }
1596
+ }
1597
+
1598
+ # consider dependencies on handles with an empty src
1599
+ } else {
1600
+ wp_dequeue_script($handle);
1601
+ wp_enqueue_script($handle);
1602
+ }
1603
+ endforeach;
1604
+
1605
+ # prepare log
1606
+ $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
1607
+
1608
+ # generate cache, write log
1609
+ if(!empty($code)) {
1610
+ file_put_contents($file.'.txt', $log);
1611
+ file_put_contents($file, $code);
1612
+ file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
1613
+
1614
+ # permissions
1615
+ fastvelocity_fix_permission_bits($file.'.txt');
1616
+ fastvelocity_fix_permission_bits($file);
1617
+ fastvelocity_fix_permission_bits($file.'.gz');
1618
+
1619
+ # brotli static support
1620
+ if(function_exists('brotli_compress')) {
1621
+ file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
1622
+ fastvelocity_fix_permission_bits($file.'.br');
1623
+ }
1624
+ }
1625
+ }
1626
+
1627
+ # register minified file
1628
+ wp_register_script("fvm-footer-$i", $file_url, array(), null, false);
1629
+
1630
+ # add all extra data from wp_localize_script
1631
+ $data = array();
1632
+ foreach($footer[$i]['handles'] as $handle) {
1633
+ if(isset($wp_scripts->registered[$handle]->extra['data'])) { $data[] = $wp_scripts->registered[$handle]->extra['data']; }
1634
+ }
1635
+ if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1636
+
1637
+ # enqueue file, if not empty
1638
+ if(file_exists($file) && (filesize($file) > 0 || count($data) > 0)) {
1639
+ wp_enqueue_script("fvm-footer-$i");
1640
+ } else {
1641
+ # file could not be generated, output something meaningful
1642
+ echo "<!-- ERROR: FVM was not allowed to save it's cache on - $file -->";
1643
+ echo "<!-- Please check if the path above is correct and ensure your server has writting permission there! -->";
1644
+ echo "<!-- If you found a bug, please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
1645
+ }
1646
+
1647
+ # other scripts need to be requeued for the order of files to be kept
1648
+ } else {
1649
+ wp_dequeue_script($footer[$i]['handle']); wp_enqueue_script($footer[$i]['handle']);
1650
+ }
1651
+ }
1652
+
1653
+ # remove from queue
1654
+ $wp_scripts->done = $done;
1655
+ }
1656
+ ##############################
1657
+
1658
+
1659
+
1660
+ ###########################################
1661
+ # enable defer for JavaScript (WP 4.1 and above) and remove query strings for ignored files
1662
+ ###########################################
1663
+ function fastvelocity_min_defer_js($tag, $handle, $src) {
1664
+ global $ignore, $blacklist, $ignorelist, $enable_defer_js, $defer_for_pagespeed, $wp_domain, $exclude_defer_login, $fvm_fix_editor, $fvmualist, $defer_for_pagespeed_optimize, $exclude_defer_jquery, $skip_defer_lists;
1665
+
1666
+ # no query strings
1667
+ $tag = trim($tag); # must cleanup
1668
+ if (stripos($src, '?ver') !== false) {
1669
+ $srcf = stristr($src, '?ver', true);
1670
+ $tag = str_ireplace($src, $srcf, $tag);
1671
+ $src = $srcf;
1672
+ }
1673
+
1674
+
1675
+ # fix page editors, admin, amp, etc
1676
+ if(fastvelocity_exclude_contents()) { return $tag; }
1677
+
1678
+ # return if defer option is not selected
1679
+ if ($defer_for_pagespeed != true && $enable_defer_js != true) { return $tag; }
1680
+
1681
+ # Skip deferring the jQuery library option
1682
+ if($exclude_defer_jquery != false && (stripos($tag, '/jquery.js') !== false || stripos($tag, '/jquery.min.js') !== false || (stripos($tag, '/jquery-') !== false && stripos($tag, '.js') !== false))) {
1683
+ return $tag;
1684
+ }
1685
+
1686
+ # return if external script url https://www.chromestatus.com/feature/5718547946799104
1687
+ if (fvm_is_local_domain($src) !== true) { return $tag; }
1688
+
1689
+ # bypass if there are linebreaks (will break document.write) or already being optimized
1690
+ if (stripos($tag, PHP_EOL) !== false || stripos($tag, 'navigator.userAgent.match') !== false) {
1691
+ return $tag;
1692
+ }
1693
+
1694
+ # should we exclude defer on the login page?
1695
+ if($exclude_defer_login == true && stripos($_SERVER["SCRIPT_NAME"], strrchr(wp_login_url(), '/')) !== false){
1696
+ return $tag;
1697
+ }
1698
+
1699
+ # add defer attribute, but only if not having async or defer already
1700
+ if (stripos($tag, 'defer') === false && stripos($tag, 'async') === false) {
1701
+
1702
+ # defer tag globally
1703
+ $jsdefer = str_ireplace('<script ', '<script defer ', $tag);
1704
+ $jsdeferpsi = $jsdefer;
1705
+
1706
+ # add cdn for PSI
1707
+ $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
1708
+ if(!empty($fvm_cdn_url)) {
1709
+ $fvm_cdn_url = trim(trim(str_ireplace(array('http://', 'https://'), '', trim($fvm_cdn_url, '/'))), '/');
1710
+ $jsdeferpsi = str_ireplace($src, $fvm_cdn_url, $jsdefer);
1711
+ }
1712
+
1713
+
1714
+ # defer tag for PSI only
1715
+ $jsdeferpsionly = '<script type="text/javascript">if(navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){document.write('.fastvelocity_escape_url_js($jsdeferpsi).');}else{document.write('.fastvelocity_escape_url_js($tag).');}</script>';
1716
+
1717
+ # hide tag from PSI
1718
+ $jsdeferhidepsi = '<script type="text/javascript">if(fvmuag()){document.write('.fastvelocity_escape_url_js($tag).');}</script>';
1719
+
1720
+ # must return by this order...
1721
+
1722
+ # remove FVM from the ignore list
1723
+ array_filter($ignore, function ($var) { return (stripos($var, '/fvm/') === false); });
1724
+
1725
+ # Exclude JS files in the "ignore list" from PSI
1726
+ if($defer_for_pagespeed_optimize != false) {
1727
+ if((count($ignore) > 0 && fastvelocity_min_in_arrayi($src, $ignore)) || (count($blacklist) > 0 && fastvelocity_min_in_arrayi($src, $blacklist)) || (count($ignorelist) > 0 && fastvelocity_min_in_arrayi($src, $ignorelist))) {
1728
+ return $jsdeferhidepsi;
1729
+ }
1730
+ }
1731
+
1732
+ # Enable defer of JS files for PSI
1733
+ if($defer_for_pagespeed != false) {
1734
+ return $jsdeferpsionly;
1735
+ }
1736
+
1737
+ # Enable defer parsing of FVM JS files globally
1738
+ if($enable_defer_js == true) {
1739
+
1740
+ # consider "Skip deferring the ignore list"
1741
+ if($skip_defer_lists != false && ((count($ignore) > 0 && fastvelocity_min_in_arrayi($src, $ignore)) || (count($blacklist) > 0 && fastvelocity_min_in_arrayi($src, $blacklist)) || (count($ignorelist) > 0 && fastvelocity_min_in_arrayi($src, $ignorelist)))) {
1742
+ return $tag;
1743
+ } else {
1744
+ return $jsdefer;
1745
+ }
1746
+ }
1747
+
1748
+ }
1749
+
1750
+ # fallback
1751
+ return $tag;
1752
+ }
1753
+ ###########################################
1754
+
1755
+
1756
+ ###########################################
1757
+ # process header css ######################
1758
+ ###########################################
1759
+ function fastvelocity_min_merge_header_css() {
1760
+ global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_min_excludecsslist, $fvm_debug, $fvm_min_excludecsslist, $fvm_fawesome_method;
1761
+ if(!is_object($wp_styles)) { return false; }
1762
+ $ctime = get_option('fvm-last-cache-update', '0');
1763
+ $styles = wp_clone($wp_styles);
1764
+ $styles->all_deps($styles->queue);
1765
+ $done = $styles->done;
1766
+ $header = array();
1767
+ $google_fonts = array();
1768
+ $process = array();
1769
+ $inline_css = array();
1770
+ $log = '';
1771
+
1772
+ # dequeue all styles
1773
+ if($fvm_remove_css != false) {
1774
+ foreach( $styles->to_do as $handle ) :
1775
+ $done = array_merge($done, array($handle));
1776
+ endforeach;
1777
+
1778
+ # remove from queue
1779
+ $wp_styles->done = $done;
1780
+ return false;
1781
+ }
1782
+
1783
+ # add defaults to ignore list
1784
+ $ignore = fastvelocity_default_ignore($ignore);
1785
+
1786
+ # get list of handles to process, dequeue duplicate css urls and keep empty source handles (for dependencies)
1787
+ $uniq = array(); $gfonts = array();
1788
+ foreach( $styles->to_do as $handle):
1789
+
1790
+ # conditionals
1791
+ $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
1792
+ $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
1793
+ }
1794
+
1795
+ # mediatype
1796
+ $mt = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
1797
+ if ($mt == 'screen' || $mt == 'screen, print' || empty($mt) || is_null($mt) || $mt == false) { $mt = 'all'; }
1798
+ $mediatype = $mt;
1799
+
1800
+ # full url or empty
1801
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1802
+
1803
+ # inlined scripts without file
1804
+ if( empty($hurl)) {
1805
+ continue;
1806
+ }
1807
+
1808
+ # mark duplicates as done and remove from the queue
1809
+ if(!empty($hurl)) {
1810
+ $key = hash('sha1', $hurl);
1811
+ if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
1812
+ }
1813
+
1814
+ # Exclude specific CSS files from PSI?
1815
+ if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($hurl, $fvm_min_excludecsslist)) {
1816
+ $cssguid = 'fvm'.hash('sha1', $hurl);
1817
+ echo '<script type="text/javascript">if(fvmuag()){';
1818
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1819
+ echo '}</script>';
1820
+ $done = array_merge($done, array($handle)); continue;
1821
+ }
1822
+
1823
+ # font awesome processing, async css
1824
+ if($fvm_fawesome_method == 2 && stripos($hurl, 'font-awesome') !== false) {
1825
+ echo '<link rel="preload" href="'.$hurl.'" as="style" media="'.$mediatype.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1826
+ echo '<noscript><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /></noscript>';
1827
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /><![endif]-->';
1828
+ $done = array_merge($done, array($handle)); continue;
1829
+ }
1830
+
1831
+ # font awesome processing, async and exclude from PSI
1832
+ if($fvm_fawesome_method == 3 && stripos($hurl, 'font-awesome') !== false) {
1833
+ $cssguid = 'fvm'.hash('sha1', $hurl);
1834
+ echo '<script type="text/javascript">if(fvmuag()){';
1835
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1836
+ echo '}</script>';
1837
+ $done = array_merge($done, array($handle)); continue;
1838
+ }
1839
+
1840
+ # array of info to save
1841
+ $arr = array('handle'=>$handle, 'url'=>$hurl, 'conditional'=>$conditional, 'mediatype'=>$mediatype);
1842
+
1843
+ # google fonts to the top (collect and skip process array)
1844
+ if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1845
+ if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
1846
+ if($skip_google_fonts != true || $force_inline_googlefonts != false) {
1847
+ $google_fonts[$handle] = $hurl;
1848
+
1849
+ } else {
1850
+ wp_enqueue_style($handle); # skip google fonts optimization?
1851
+ }
1852
+ continue;
1853
+ }
1854
+
1855
+ # all else
1856
+ $process[$handle] = $arr;
1857
+
1858
+ endforeach;
1859
+
1860
+
1861
+ # concat google fonts, if enabled
1862
+ if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts != false && count($google_fonts) > 0)) {
1863
+ foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
1864
+
1865
+ # merge google fonts if force inlining is enabled?
1866
+ $nfonts = array();
1867
+ if($skip_google_fonts != true) {
1868
+ $nfonts[] = fvm_get_protocol(fastvelocity_min_concatenate_google_fonts($google_fonts));
1869
+ } else {
1870
+ foreach ($google_fonts as $a) { if(!empty($a)) { $nfonts[] = $a; } }
1871
+ }
1872
+
1873
+ # foreach google font (will be one if merged is not disabled)
1874
+ if(count($nfonts) > 0) {
1875
+ foreach($nfonts as $gfurl) {
1876
+
1877
+ # hide from PSI, async, inline, or default
1878
+ if($css_hide_googlefonts == true) {
1879
+
1880
+ # make a stylesheet, hide from PSI
1881
+ $cssguid = 'fvm'.hash('sha1', $gfurl);
1882
+ echo '<script type="text/javascript">if(fvmuag()){';
1883
+ 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.');';
1884
+ echo '}</script>';
1885
+
1886
+ # async CSS
1887
+ } elseif ($min_async_googlefonts == true) {
1888
+ echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1889
+ echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
1890
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
1891
+
1892
+ # inline css
1893
+ } elseif($force_inline_googlefonts == true) {
1894
+
1895
+ # download, minify, cache
1896
+ $tkey = 'css-'.hash('sha1', $gfurl).'.css';
1897
+ $json = false; $json = fvm_get_transient($tkey);
1898
+ if ( $json === false) {
1899
+ $json = fvm_download_and_minify($gfurl, null, $disable_css_minification, 'css', null);
1900
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $gfurl -->" . PHP_EOL; }
1901
+ fvm_set_transient($tkey, $json);
1902
+ }
1903
+
1904
+ # decode
1905
+ $res = json_decode($json, true);
1906
+
1907
+ # response has failed
1908
+ if($res['status'] != true) {
1909
+ $log.= $res['log'];
1910
+ continue;
1911
+ }
1912
+
1913
+ # inline css or fail
1914
+ if($res['code'] !== false) {
1915
+
1916
+ # add font-display
1917
+ # https://developers.google.com/web/updates/2016/02/font-display
1918
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
1919
+
1920
+ # inline
1921
+ echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
1922
+ } else {
1923
+ echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
1924
+ }
1925
+
1926
+ # fallback, enqueue google fonts
1927
+ } else {
1928
+ wp_enqueue_style('header-fvm-fonts', $gfurl, array(), null, 'all');
1929
+ }
1930
+
1931
+ }
1932
+ }
1933
+ }
1934
+
1935
+
1936
+ # get groups of handles
1937
+ foreach( $styles->to_do as $handle ) :
1938
+
1939
+ # skip already processed google fonts and empty dependencies
1940
+ if(isset($google_fonts[$handle])) { continue; } # skip google fonts
1941
+ if(empty($wp_styles->registered[$handle]->src)) { continue; } # skip empty src
1942
+ if (fastvelocity_min_in_arrayi($handle, $done)) { continue; } # skip if marked as done before
1943
+ if (!isset($process[$handle])) { continue; } # skip if not on our unique process list
1944
+
1945
+ # get full url
1946
+ $hurl = $process[$handle]['url'];
1947
+ $conditional = $process[$handle]['conditional'];
1948
+ $mediatype = $process[$handle]['mediatype'];
1949
+
1950
+ # IE only files don't increment things
1951
+ $ieonly = fastvelocity_ie_blacklist($hurl);
1952
+ if($ieonly == true) { continue; }
1953
+
1954
+ # skip ignore list, conditional css, external css, font-awesome merge
1955
+ if ( (!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home))
1956
+ || empty($hurl)
1957
+ || ($fvm_fawesome_method == 1 && stripos($hurl, 'font-awesome') !== false)) {
1958
+
1959
+ # colect inline css for this handle
1960
+ if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
1961
+ $inline_css[$handle] = fastvelocity_min_minify_css_string(implode('', $wp_styles->registered[$handle]->extra['after'])); # save
1962
+ $wp_styles->registered[$handle]->extra['after'] = null; # dequeue
1963
+ }
1964
+
1965
+ # process
1966
+ if(isset($header[count($header)-1]['handle']) || count($header) == 0 || $header[count($header)-1]['media'] != $mediatype) {
1967
+ array_push($header, array('handles'=>array(), 'media'=>$mediatype));
1968
+ }
1969
+
1970
+ # push it to the array
1971
+ array_push($header[count($header)-1]['handles'], $handle);
1972
+
1973
+ # external and ignored css
1974
+ } else {
1975
+
1976
+ # normal enqueuing
1977
+ array_push($header, array('handle'=>$handle));
1978
+ }
1979
+ endforeach;
1980
+
1981
+ # reorder CSS by mediatypes
1982
+ if(!$skip_cssorder) {
1983
+ if(count($header) > 0) {
1984
+
1985
+ # get unique mediatypes
1986
+ $allmedia = array();
1987
+ foreach($header as $array) {
1988
+ if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1989
+ }
1990
+
1991
+ # extract handles by mediatype
1992
+ $grouphandles = array();
1993
+ foreach ($allmedia as $md=>$var) {
1994
+ foreach($header as $array) {
1995
+ if (isset($array['media']) && $array['media'] === $md) {
1996
+ foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1997
+ }
1998
+ }
1999
+ }
2000
+
2001
+ # reset and reorder header by mediatypes
2002
+ $newheader = array();
2003
+ foreach ($allmedia as $md=>$var) { $newheader[] = array('handles' => $grouphandles[$md], 'media'=>$md); }
2004
+ if(count($newheader) > 0) { $header = $newheader; }
2005
+ }
2006
+ }
2007
+
2008
+ # loop through header css and merge
2009
+ for($i=0,$l=count($header);$i<$l;$i++) {
2010
+ if(!isset($header[$i]['handle'])) {
2011
+
2012
+ # get has for the inline css in this group
2013
+ $inline_css_group = array();
2014
+ foreach($header[$i]['handles'] as $h) { if(isset($inline_css[$h]) && !empty($inline_css[$h])) { $inline_css_group[] = $inline_css[$h]; } }
2015
+ $inline_css_hash = md5(implode('',$inline_css_group));
2016
+
2017
+ # static cache file info + done
2018
+ $done = array_merge($done, $header[$i]['handles']);
2019
+ $hash = 'header-'.hash('sha1',implode('',$header[$i]['handles']).$inline_css_hash);
2020
+
2021
+ # create cache files and urls
2022
+ $file = $cachedir.fastvelocity_get_os_slash().$hash.'.min.css';
2023
+ $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'.min.css');
2024
+
2025
+ # generate a new cache file
2026
+ clearstatcache();
2027
+ if (!file_exists($file)) {
2028
+
2029
+ # code and log initialization
2030
+ $log = '';
2031
+ $code = '';
2032
+
2033
+ # minify and write to file
2034
+ foreach($header[$i]['handles'] as $handle) :
2035
+ if(!empty($wp_styles->registered[$handle]->src)) {
2036
+
2037
+ # get hurl per handle
2038
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2039
+
2040
+ # inlined scripts without file
2041
+ if( empty($hurl)) {
2042
+ continue;
2043
+ }
2044
+
2045
+ # print url
2046
+ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
2047
+
2048
+ # download, minify, cache
2049
+ $tkey = 'css-'.hash('sha1', $handle.$hurl).'.css';
2050
+ $json = false; $json = fvm_get_transient($tkey);
2051
+ if ( $json === false) {
2052
+ $json = fvm_download_and_minify($hurl, null, $disable_css_minification, 'css', $handle);
2053
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
2054
+ fvm_set_transient($tkey, $json);
2055
+ }
2056
+
2057
+ # decode
2058
+ $res = json_decode($json, true);
2059
+
2060
+ # response has failed
2061
+ if($res['status'] != true) {
2062
+ $log.= $res['log'];
2063
+ continue;
2064
+ }
2065
+
2066
+ # append code to merged file
2067
+ $code.= $res['code'];
2068
+ $log.= $res['log'];
2069
+
2070
+ # append inlined styles
2071
+ if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) {
2072
+ $code.= $inline_css[$handle];
2073
+ }
2074
+
2075
+ # consider dependencies on handles with an empty src
2076
+ } else {
2077
+ wp_dequeue_script($handle);
2078
+ wp_enqueue_script($handle);
2079
+ }
2080
+ endforeach;
2081
+
2082
+ # prepare log
2083
+ $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
2084
+
2085
+ # generate cache, write log
2086
+ if(!empty($code)) {
2087
+ file_put_contents($file.'.txt', $log);
2088
+ file_put_contents($file, $code);
2089
+ file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
2090
+
2091
+ # permissions
2092
+ fastvelocity_fix_permission_bits($file.'.txt');
2093
+ fastvelocity_fix_permission_bits($file);
2094
+ fastvelocity_fix_permission_bits($file.'.gz');
2095
+
2096
+ # brotli static support
2097
+ if(function_exists('brotli_compress')) {
2098
+ file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
2099
+ fastvelocity_fix_permission_bits($file.'.br');
2100
+ }
2101
+ }
2102
+ }
2103
+
2104
+ # register and enqueue minified file, consider excluding of mediatype "print" and inline css
2105
+ if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $header[$i]['media'] != 'print')) {
2106
+
2107
+ # the developers tab, takes precedence
2108
+
2109
+ # Async CSS with loadCSS ?
2110
+ if($fvmloadcss != false && $fvm_remove_css != true) {
2111
+ $mt = $header[$i]['media'];
2112
+ echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$mt.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2113
+ echo '<noscript><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /></noscript>';
2114
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /><![endif]-->';
2115
+
2116
+ # enqueue file, if not empty
2117
+ } else {
2118
+ if(file_exists($file) && filesize($file) > 0) {
2119
+
2120
+ # inline CSS if mediatype is not of type "all" (such as mobile only), if the file is smaller than 20KB
2121
+ if(filesize($file) < 20000 && $header[$i]['media'] != 'all') {
2122
+ echo '<style id="fvm-header-'.$i.'" media="'.$header[$i]['media'].'">'.file_get_contents($file).'</style>';
2123
+ } else {
2124
+ # enqueue it
2125
+ wp_enqueue_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
2126
+ }
2127
+ } else {
2128
+ # file could not be generated, output something meaningful
2129
+ echo "<!-- ERROR: FVM was not allowed to save it's cache on - $file -->";
2130
+ echo "<!-- Please check if the path above is correct and ensure your server has writting permission there! -->";
2131
+ echo "<!-- If you found a bug, please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
2132
+ }
2133
+ }
2134
+ }
2135
+
2136
+ # other css need to be requeued for the order of files to be kept
2137
+ } else {
2138
+ wp_dequeue_style($header[$i]['handle']);
2139
+ wp_enqueue_style($header[$i]['handle']);
2140
+ }
2141
+ }
2142
+
2143
+ # remove from queue
2144
+ $wp_styles->done = $done;
2145
+
2146
+ }
2147
+ ###########################################
2148
+
2149
+
2150
+ ###########################################
2151
+ # process css in the footer ###############
2152
+ ###########################################
2153
+ function fastvelocity_min_merge_footer_css() {
2154
+ global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_debug, $fvm_fawesome_method, $fvm_min_excludecsslist, $force_inline_css_footer;
2155
+
2156
+ if(!is_object($wp_styles)) { return false; }
2157
+ $ctime = get_option('fvm-last-cache-update', '0');
2158
+ $styles = wp_clone($wp_styles);
2159
+ $styles->all_deps($styles->queue);
2160
+ $done = $styles->done;
2161
+ $footer = array();
2162
+ $google_fonts = array();
2163
+ $inline_css = array();
2164
+ $code = '';
2165
+ $log = '';
2166
+
2167
+ # dequeue all styles
2168
+ if($fvm_remove_css != false) {
2169
+ foreach( $styles->to_do as $handle ) :
2170
+ $done = array_merge($done, array($handle));
2171
+ endforeach;
2172
+
2173
+ # remove from queue
2174
+ $wp_styles->done = $done;
2175
+ return false;
2176
+ }
2177
+
2178
+
2179
+ # add defaults to ignore list
2180
+ $ignore = fastvelocity_default_ignore($ignore);
2181
+
2182
+ # google fonts to the top
2183
+ foreach( $styles->to_do as $handle ) :
2184
+
2185
+ # dequeue and get a list of google fonts, or requeue external
2186
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2187
+
2188
+ # inlined scripts without file
2189
+ if( empty($hurl)) {
2190
+ continue;
2191
+ }
2192
+
2193
+ if (stripos($hurl, 'fonts.googleapis.com') !== false) {
2194
+ wp_dequeue_style($handle);
2195
+ if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
2196
+ if($skip_google_fonts != true || $force_inline_googlefonts != false) {
2197
+ $google_fonts[$handle] = $hurl;
2198
+ } else {
2199
+ wp_enqueue_style($handle); # skip google fonts optimization?
2200
+ }
2201
+ } else {
2202
+ wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
2203
+ }
2204
+
2205
+ endforeach;
2206
+
2207
+
2208
+ # concat google fonts, if enabled
2209
+ if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts != false && count($google_fonts) > 0)) {
2210
+ foreach ($google_fonts as $h=>$a) { $done = array_merge($done, array($h)); } # mark as done
2211
+
2212
+ # merge google fonts if force inlining is enabled?
2213
+ $nfonts = array();
2214
+ if($skip_google_fonts != true) {
2215
+ $nfonts[] = fvm_get_protocol(fastvelocity_min_concatenate_google_fonts($google_fonts));
2216
+ } else {
2217
+ foreach ($google_fonts as $a) { if(!empty($a)) { $nfonts[] = $a; } }
2218
+ }
2219
+
2220
+ # foreach google font (will be one if merged is not disabled)
2221
+ if(count($nfonts) > 0) {
2222
+ foreach($nfonts as $gfurl) {
2223
+
2224
+ # hide from PSI, async, inline, or default
2225
+ if($css_hide_googlefonts == true) {
2226
+
2227
+ # make a stylesheet, hide from PSI
2228
+ $cssguid = 'fvm'.hash('sha1', $gfurl);
2229
+ echo '<script type="text/javascript">if(fvmuag()){';
2230
+ 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.');';
2231
+ echo '}</script>';
2232
+
2233
+ # async CSS
2234
+ } elseif ($min_async_googlefonts == true) {
2235
+ echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2236
+ echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
2237
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
2238
+
2239
+ # inline css
2240
+ } elseif($force_inline_googlefonts == true) {
2241
+
2242
+ # download, minify, cache
2243
+ $tkey = 'css-'.hash('sha1', $gfurl).'.css';
2244
+ $json = false; $json = fvm_get_transient($tkey);
2245
+ if ( $json === false) {
2246
+ $json = fvm_download_and_minify($gfurl, null, $disable_css_minification, 'css', null);
2247
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $gfurl -->" . PHP_EOL; }
2248
+ fvm_set_transient($tkey, $json);
2249
+ }
2250
+
2251
+ # decode
2252
+ $res = json_decode($json, true);
2253
+
2254
+ # response has failed
2255
+ if($res['status'] != true) {
2256
+ $log.= $res['log'];
2257
+ continue;
2258
+ }
2259
+
2260
+ # append code to merged file
2261
+ $code.= $res['code'];
2262
+ $log.= $res['log'];
2263
+
2264
+ # inline css or fail
2265
+ if($res['code'] !== false) {
2266
+ echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2267
+ } else {
2268
+ echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
2269
+ }
2270
+
2271
+ # fallback, enqueue google fonts
2272
+ } else {
2273
+ wp_enqueue_style('footer-fvm-fonts', $gfurl, array(), null, 'all');
2274
+ }
2275
+
2276
+ }
2277
+ }
2278
+ }
2279
+
2280
+
2281
+ # get groups of handles
2282
+ $uniq = array();
2283
+ foreach( $styles->to_do as $handle ) :
2284
+
2285
+ # skip already processed google fonts
2286
+ if(isset($google_fonts[$handle])) { continue; }
2287
+
2288
+ # conditionals
2289
+ $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
2290
+ $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
2291
+ }
2292
+
2293
+ # mediatype
2294
+ $mt = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
2295
+ if ($mt == 'screen' || $mt == 'screen, print' || empty($mt) || is_null($mt) || $mt == false) { $mt = 'all'; }
2296
+ $mediatype = $mt;
2297
+
2298
+ # get full url
2299
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2300
+
2301
+ # inlined scripts without file
2302
+ if( empty($hurl)) {
2303
+ continue;
2304
+ }
2305
+
2306
+ # mark duplicates as done and remove from the queue
2307
+ if(!empty($hurl)) {
2308
+ $key = hash('sha1', $hurl);
2309
+ if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
2310
+ }
2311
+
2312
+ # IE only files don't increment things
2313
+ $ieonly = fastvelocity_ie_blacklist($hurl);
2314
+ if($ieonly == true) { continue; }
2315
+
2316
+
2317
+ # Exclude specific CSS files from PSI?
2318
+ if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($hurl, $fvm_min_excludecsslist)) {
2319
+ $cssguid = 'fvm'.hash('sha1', $hurl);
2320
+ echo '<script type="text/javascript">if(fvmuag()){';
2321
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2322
+ echo '}</script>';
2323
+ $done = array_merge($done, array($handle)); continue;
2324
+ }
2325
+
2326
+ # font awesome processing, async css
2327
+ if($fvm_fawesome_method == 2 && stripos($hurl, 'font-awesome') !== false) {
2328
+ echo '<link rel="preload" href="'.$hurl.'" as="style" media="'.$mediatype.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2329
+ echo '<noscript><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /></noscript>';
2330
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /><![endif]-->';
2331
+ $done = array_merge($done, array($handle)); continue;
2332
+ }
2333
+
2334
+ # font awesome processing, async and exclude from PSI
2335
+ if($fvm_fawesome_method == 3 && stripos($hurl, 'font-awesome') !== false) {
2336
+ $cssguid = 'fvm'.hash('sha1', $hurl);
2337
+ echo '<script type="text/javascript">if(fvmuag()){';
2338
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2339
+ echo '}</script>';
2340
+ $done = array_merge($done, array($handle)); continue;
2341
+ }
2342
+
2343
+ # skip ignore list, conditional css, external css, font-awesome merge
2344
+ if ( (!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home))
2345
+ || empty($hurl)
2346
+ || ($fvm_fawesome_method == 1 && stripos($hurl, 'font-awesome') !== false)) {
2347
+
2348
+ # colect inline css for this handle
2349
+ if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
2350
+ $inline_css[$handle] = fastvelocity_min_minify_css_string(implode('', $wp_styles->registered[$handle]->extra['after'])); # save
2351
+ $wp_styles->registered[$handle]->extra['after'] = null; # dequeue
2352
+ }
2353
+
2354
+ # process
2355
+ if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0 || $footer[count($footer)-1]['media'] != $wp_styles->registered[$handle]->args) {
2356
+ array_push($footer, array('handles'=>array(),'media'=>$mediatype));
2357
+ }
2358
+
2359
+ # push it to the array get latest modified time
2360
+ array_push($footer[count($footer)-1]['handles'], $handle);
2361
+
2362
+ # external and ignored css
2363
+ } else {
2364
+
2365
+ # normal enqueueing
2366
+ array_push($footer, array('handle'=>$handle));
2367
+ }
2368
+ endforeach;
2369
+
2370
+
2371
+ # reorder CSS by mediatypes
2372
+ if(!$skip_cssorder) {
2373
+ if(count($footer) > 0) {
2374
+
2375
+ # get unique mediatypes
2376
+ $allmedia = array();
2377
+ foreach($footer as $key=>$array) {
2378
+ if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
2379
+ }
2380
+
2381
+ # extract handles by mediatype
2382
+ $grouphandles = array();
2383
+ foreach ($allmedia as $md=>$var) {
2384
+ foreach($footer as $array) {
2385
+ if (isset($array['media']) && $array['media'] === $md) {
2386
+ foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
2387
+ }
2388
+ }
2389
+ }
2390
+
2391
+ # reset and reorder footer by mediatypes
2392
+ $newfooter = array();
2393
+ foreach ($allmedia as $md=>$var) { $newfooter[] = array('handles' => $grouphandles[$md], 'media'=>$md); }
2394
+ if(count($newfooter) > 0) { $footer = $newfooter; }
2395
+ }
2396
+ }
2397
+
2398
+ # loop through footer css and merge
2399
+ for($i=0,$l=count($footer);$i<$l;$i++) {
2400
+ if(!isset($footer[$i]['handle'])) {
2401
+
2402
+ # get has for the inline css in this group
2403
+ $inline_css_group = array();
2404
+ foreach($footer[$i]['handles'] as $h) { if(isset($inline_css[$h]) && !empty($inline_css[$h])) { $inline_css_group[] = $inline_css[$h]; } }
2405
+ $inline_css_hash = md5(implode('',$inline_css_group));
2406
+
2407
+ # static cache file info + done
2408
+ $done = array_merge($done, $footer[$i]['handles']);
2409
+ $hash = 'footer-'.hash('sha1',implode('',$footer[$i]['handles']).$inline_css_hash);
2410
+
2411
+ # create cache files and urls
2412
+ $file = $cachedir.fastvelocity_get_os_slash().$hash.'.min.css';
2413
+ $file_url = fvm_get_protocol($cachedirurl.'/'.$hash.'.min.css');
2414
+
2415
+ # generate a new cache file
2416
+ clearstatcache();
2417
+ if (!file_exists($file)) {
2418
+
2419
+ # code and log initialization
2420
+ $log = '';
2421
+ $code = '';
2422
+
2423
+ # minify and write to file
2424
+ foreach($footer[$i]['handles'] as $handle) :
2425
+ if(!empty($wp_styles->registered[$handle]->src)) {
2426
+
2427
+ # get hurl per handle
2428
+ $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2429
+
2430
+ # inlined scripts without file
2431
+ if( empty($hurl)) {
2432
+ continue;
2433
+ }
2434
+
2435
+ # print url
2436
+ $printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
2437
+
2438
+ # download, minify, cache
2439
+ $tkey = 'css-'.hash('sha1', $handle.$hurl).'.css';
2440
+ $json = false; $json = fvm_get_transient($tkey);
2441
+ if ( $json === false) {
2442
+ $json = fvm_download_and_minify($hurl, null, $disable_css_minification, 'css', $handle);
2443
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $hurl -->" . PHP_EOL; }
2444
+ fvm_set_transient($tkey, $json);
2445
+ }
2446
+
2447
+ # decode
2448
+ $res = json_decode($json, true);
2449
+
2450
+ # response has failed
2451
+ if($res['status'] != true) {
2452
+ $log.= $res['log'];
2453
+ continue;
2454
+ }
2455
+
2456
+ # append code to merged file
2457
+ $code.= $res['code'];
2458
+ $log.= $res['log'];
2459
+
2460
+ # append inlined styles
2461
+ if(isset($inline_css[$handle]) && !empty($inline_css[$handle])) {
2462
+ $code.= $inline_css[$handle];
2463
+ }
2464
+
2465
+ # consider dependencies on handles with an empty src
2466
+ } else {
2467
+ wp_dequeue_script($handle);
2468
+ wp_enqueue_script($handle);
2469
+ }
2470
+ endforeach;
2471
+
2472
+ # prepare log
2473
+ $log = "PROCESSED on ".date('r').PHP_EOL.$log."PROCESSED from ".home_url(add_query_arg( NULL, NULL )).PHP_EOL;
2474
+
2475
+ # generate cache, add inline css, write log
2476
+ if(!empty($code)) {
2477
+ file_put_contents($file.'.txt', $log);
2478
+ file_put_contents($file, $code); # preserve style tags
2479
+ file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
2480
+
2481
+ # permissions
2482
+ fastvelocity_fix_permission_bits($file.'.txt');
2483
+ fastvelocity_fix_permission_bits($file);
2484
+ fastvelocity_fix_permission_bits($file.'.gz');
2485
+
2486
+ # brotli static support
2487
+ if(function_exists('brotli_compress')) {
2488
+ file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
2489
+ fastvelocity_fix_permission_bits($file.'.br');
2490
+ }
2491
+ }
2492
+ }
2493
+
2494
+ # register and enqueue minified file, consider excluding of mediatype "print" and inline css
2495
+ if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $footer[$i]['media'] != 'print')) {
2496
+
2497
+ # the developers tab, takes precedence
2498
+
2499
+ # Async CSS with loadCSS ?
2500
+ if($fvmloadcss != false && $fvm_remove_css != true) {
2501
+ $mt = $footer[$i]['media'];
2502
+ echo '<link rel="preload" href="'.$file_url.'" as="style" media="'.$mt.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2503
+ echo '<noscript><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /></noscript>';
2504
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$file_url.'" media="'.$mt.'" /><![endif]-->';
2505
+
2506
+ # enqueue file, if not empty
2507
+ } else {
2508
+ if(file_exists($file) && filesize($file) > 0) {
2509
+
2510
+ # inline if the file is smaller than 20KB or option has been enabled
2511
+ if(filesize($file) < 20000 || $force_inline_css_footer != false) {
2512
+ echo '<style id="fvm-footer-'.$i.'" media="'.$footer[$i]['media'].'">'.file_get_contents($file).'</style>';
2513
+ } else {
2514
+ # enqueue it
2515
+ wp_enqueue_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
2516
+ }
2517
+ } else {
2518
+ # file could not be generated, output something meaningful
2519
+ echo "<!-- ERROR: FVM was not allowed to save it's cache on - $file -->";
2520
+ echo "<!-- Please check if the path above is correct and ensure your server has writting permission there! -->";
2521
+ echo "<!-- If you found a bug, please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
2522
+ }
2523
+ }
2524
+ }
2525
+
2526
+ # other css need to be requeued for the order of files to be kept
2527
+ } else {
2528
+ wp_dequeue_style($footer[$i]['handle']);
2529
+ wp_enqueue_style($footer[$i]['handle']);
2530
+ }
2531
+ }
2532
+
2533
+ # remove from queue
2534
+ $wp_styles->done = $done;
2535
+ }
2536
+ ###########################################
2537
+
2538
+
2539
+
2540
+
2541
+ ###########################################
2542
+ # defer CSS globally from the header (order matters)
2543
+ # dev: https://www.filamentgroup.com/lab/async-css.html
2544
+ ###########################################
2545
+ function fvm_add_loadcss() {
2546
+
2547
+ echo <<<EOF
2548
+ <script>
2549
+ /* loadCSS. [c]2017 Filament Group, Inc. MIT License */
2550
+ (function(w){if(!w.loadCSS)w.loadCSS=function(){};var rp=loadCSS.relpreload={};rp.support=function(){var ret;try{ret=w.document.createElement("link").relList.supports("preload")}catch(e){ret=false}return function(){return ret}}();rp.bindMediaToggle=function(link){var finalMedia=link.media||"all";function enableStylesheet(){if(link.addEventListener)link.removeEventListener("load",enableStylesheet);else if(link.attachEvent)link.detachEvent("onload",enableStylesheet);link.setAttribute("onload",null);link.media=finalMedia}if(link.addEventListener)link.addEventListener("load",enableStylesheet);else if(link.attachEvent)link.attachEvent("onload",enableStylesheet);setTimeout(function(){link.rel="stylesheet";link.media="only x"});setTimeout(enableStylesheet,3E3)};rp.poly=function(){if(rp.support())return;var links=w.document.getElementsByTagName("link");for(var i=0;i<links.length;i++){var link=links[i];if(link.rel==="preload"&&link.getAttribute("as")==="style"&&!link.getAttribute("data-loadcss")){link.setAttribute("data-loadcss", true);rp.bindMediaToggle(link)}}};if(!rp.support()){rp.poly();var run=w.setInterval(rp.poly,500);if(w.addEventListener)w.addEventListener("load",function(){rp.poly();w.clearInterval(run)});else if(w.attachEvent)w.attachEvent("onload",function(){rp.poly();w.clearInterval(run)})}if(typeof exports!=="undefined")exports.loadCSS=loadCSS;else w.loadCSS=loadCSS})(typeof global!=="undefined"?global:this);
2551
+ </script>
2552
+ EOF;
2553
+
2554
+ }
2555
+
2556
+ # fvm load async scripts with callback
2557
+ function fvm_add_loadasync() {
2558
+ global $fvm_min_excludejslist;
2559
+ if($fvm_min_excludejslist != false && is_array($fvm_min_excludejslist) && count($fvm_min_excludejslist) > 0) {
2560
+
2561
+ echo <<<EOF
2562
+ <script>function loadAsync(e,a){var t=document.createElement("script");t.src=e,null!==a&&(t.readyState?t.onreadystatechange=function(){"loaded"!=t.readyState&&"complete"!=t.readyState||(t.onreadystatechange=null,a())}:t.onload=function(){a()}),document.getElementsByTagName("head")[0].appendChild(t)}</script>
2563
+ EOF;
2564
+
2565
+ }
2566
+ }
2567
+
2568
+
2569
+
2570
+ # add inline CSS code / Critical Path
2571
+ function fvm_add_criticial_path() {
2572
+ $no_global_critical_path_css = false;
2573
+ $critical_path_css = get_option('fastvelocity_min_critical_path_css');
2574
+ $critical_path_css_is_front_page = get_option('fastvelocity_min_critical_path_css_is_front_page');
2575
+
2576
+ # critical path (is_front_page only)
2577
+ if(!empty($critical_path_css_is_front_page) && $critical_path_css_is_front_page !== false) {
2578
+ echo '<style id="critical-path-is-front-page" type="text/css" media="all">'.$critical_path_css_is_front_page.'</style>'.PHP_EOL;
2579
+ $no_global_critical_path_css = 1;
2580
+ }
2581
+
2582
+ # global path, except if there's something else more specific
2583
+ if(!empty($critical_path_css) && $critical_path_css !== false && $no_global_critical_path_css === false) {
2584
+ echo '<style id="critical-path-global" type="text/css" media="all">'.$critical_path_css.'</style>'.PHP_EOL;
2585
+ }
2586
+ }
2587
+
2588
+
2589
+
2590
+
2591
+
2592
+ ###########################################
2593
+ # add preconnect and preload headers
2594
+ ###########################################
2595
+ function fvm_extra_preload_headers() {
2596
+
2597
+ # fetch headers
2598
+ $preload = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_hpreload')));
2599
+ $preconnect = array_map('trim', explode(PHP_EOL, get_option('fastvelocity_min_hpreconnect')));
2600
+
2601
+ # preconnect
2602
+ if(is_array($preload) && count($preload) > 0) {
2603
+ foreach ($preload as $h) {
2604
+ if(!empty($h)) {
2605
+ header($h, false);
2606
+ }
2607
+ }
2608
+ }
2609
+
2610
+ # preload
2611
+ if(is_array($preconnect) && count($preconnect) > 0) {
2612
+ foreach ($preconnect as $url) {
2613
+ if(!empty($url) && filter_var($url, FILTER_VALIDATE_URL)) {
2614
+ header("Link: <$url>; rel=preconnect", false);
2615
+ }
2616
+ }
2617
+ }
2618
+
2619
+ # fvm css and js generated files
2620
+ $fvm_headers = fastvelocity_get_preload_headers();
2621
+ if($fvm_headers != false) {
2622
+ $nh = array_map('trim', explode(PHP_EOL, $fvm_headers));
2623
+ foreach ($nh as $h) {
2624
+ if(!empty($h)) {
2625
+ header($h, false);
2626
+ }
2627
+ }
2628
+ }
2629
+
2630
+ }
2631
+
2632
+
2633
+
2634
+ # inline css in place, instead of inlining the large file
2635
+ function fastvelocity_optimizecss($html, $handle, $href, $media){
2636
+ global $fvm_debug, $wp_domain, $wp_home, $force_inline_css, $fvmualist, $fvm_collect_google_fonts, $force_inline_googlefonts, $min_async_googlefonts, $remove_googlefonts, $skip_google_fonts, $css_hide_googlefonts, $remove_print_mediatypes, $ignore, $blacklist, $ignorelist, $wp_home, $fvmloadcss, $fvm_remove_css, $fvm_cdn_url, $disable_minification, $fvm_min_excludecsslist, $disable_css_minification, $fvm_fix_editor, $fvm_fawesome_method;
2637
+
2638
+ # current timestamp
2639
+ $ctime = get_option('fvm-last-cache-update', '0');
2640
+
2641
+ # make sure href is complete
2642
+ $href = fastvelocity_min_get_hurl($href, $wp_domain, $wp_home);
2643
+
2644
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Inline CSS processing start $handle / $href -->" . PHP_EOL; }
2645
+
2646
+ # prevent optimization for these locations
2647
+ if(fastvelocity_exclude_contents()) {
2648
+ return $html;
2649
+ }
2650
+
2651
+ # skip all this, if the async css option is enabled
2652
+ if($fvmloadcss != false) {
2653
+ return $html;
2654
+ }
2655
+
2656
+ # remove all css?
2657
+ if($fvm_remove_css != false) {
2658
+ return false;
2659
+ }
2660
+
2661
+ # leave conditionals alone
2662
+ $conditional = wp_styles()->get_data($handle, 'conditional');
2663
+ if($conditional != false) {
2664
+ return $html;
2665
+ }
2666
+
2667
+ # mediatype fix for some plugins + remove print mediatypes
2668
+ if ($media == 'screen' || $media == 'screen, print' || empty($media) || is_null($media) || $media == false) { $media = 'all'; }
2669
+ if($remove_print_mediatypes != false && $media == 'print') {
2670
+ return false;
2671
+ }
2672
+
2673
+ # Exclude specific CSS files from PSI?
2674
+ if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($href, $fvm_min_excludecsslist)) {
2675
+ $cssguid = 'fvm'.hash('sha1', $href);
2676
+ echo '<script type="text/javascript">if(fvmuag()){';
2677
+ 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.');';
2678
+ echo '}</script>';
2679
+ return false;
2680
+ }
2681
+
2682
+ # remove FVM from the ignore list
2683
+ array_filter($ignore, function ($var) { return (stripos($var, '/fvm/') === false); });
2684
+
2685
+ # return if in any ignore or black list
2686
+ if (count($ignore) > 0 && fastvelocity_min_in_arrayi($href, $ignore) || count($blacklist) > 0 && fastvelocity_min_in_arrayi($href, $blacklist) || count($ignorelist) > 0 && fastvelocity_min_in_arrayi($href, $ignorelist)) {
2687
+ return $html;
2688
+ }
2689
+
2690
+ # remove google fonts completely?
2691
+ if($remove_googlefonts != false && stripos($href, 'fonts.googleapis.com') !== false) {
2692
+ return false;
2693
+ }
2694
+
2695
+ # handle google fonts here, when merging is disabled
2696
+ if(stripos($href, 'fonts.googleapis.com') !== false && $skip_google_fonts != false) {
2697
+
2698
+ # hide google fonts from PSI
2699
+ if($css_hide_googlefonts == true) {
2700
+ $cssguid = 'fvm'.hash('sha1', $href);
2701
+ echo '<script type="text/javascript">if(fvmuag()){';
2702
+ 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.');';
2703
+ echo '}</script>';
2704
+ return false;
2705
+ }
2706
+
2707
+ # load google fonts async
2708
+ if($min_async_googlefonts != false) {
2709
+ echo '<link rel="preload" href="'.$href.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2710
+ echo '<noscript><link rel="stylesheet" href="'.$href.'" media="all" /></noscript>';
2711
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$href.'" media="all" /><![endif]-->';
2712
+ return false;
2713
+ }
2714
+ }
2715
+
2716
+ # font awesome processing, async css
2717
+ if($fvm_fawesome_method == 2 && stripos($href, 'font-awesome') !== false) {
2718
+ echo '<link rel="preload" href="'.$href.'" as="style" media="'.$media.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2719
+ echo '<noscript><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /></noscript>';
2720
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /><![endif]-->';
2721
+ return false;
2722
+ }
2723
+
2724
+ # font awesome processing, async and exclude from PSI
2725
+ if($fvm_fawesome_method == 3 && stripos($href, 'font-awesome') !== false) {
2726
+ $cssguid = 'fvm'.hash('sha1', $href);
2727
+ echo '<script type="text/javascript">if(fvmuag()){';
2728
+ 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.');';
2729
+ echo '}</script>';
2730
+ return false;
2731
+ }
2732
+
2733
+ # font awesome processing, inline
2734
+ if($fvm_fawesome_method == 1 && stripos($href, 'font-awesome') !== false) {
2735
+
2736
+ # download, minify, cache
2737
+ $tkey = 'css-'.hash('sha1', $handle.$href).'.css';
2738
+ $json = false; $json = fvm_get_transient($tkey);
2739
+ if ( $json === false) {
2740
+ $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2741
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2742
+ fvm_set_transient($tkey, $json);
2743
+ }
2744
+
2745
+ # decode
2746
+ $res = json_decode($json, true);
2747
+
2748
+ # add font-display
2749
+ # https://developers.google.com/web/updates/2016/02/font-display
2750
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
2751
+
2752
+ # inline css or fail
2753
+ if($res['status'] != false) {
2754
+ echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2755
+ return false;
2756
+ } else {
2757
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Font Awesome request failed for $href -->" . PHP_EOL; }
2758
+ return $html;
2759
+ }
2760
+ }
2761
+
2762
+ # inline google fonts, do not collect
2763
+ if(stripos($href, 'fonts.googleapis.com') !== false && $force_inline_googlefonts != false && $css_hide_googlefonts != true && $min_async_googlefonts != true) {
2764
+
2765
+ # download, minify, cache
2766
+ $tkey = 'css-'.hash('sha1', $handle.$href).'.css';
2767
+ $json = false; $json = fvm_get_transient($tkey);
2768
+ if ( $json === false) {
2769
+ $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2770
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2771
+ fvm_set_transient($tkey, $json);
2772
+ }
2773
+
2774
+ # decode
2775
+ $res = json_decode($json, true);
2776
+
2777
+ # add font-display
2778
+ # https://developers.google.com/web/updates/2016/02/font-display
2779
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
2780
+
2781
+ # inline css or fail
2782
+ if($res['status'] != false) {
2783
+ echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2784
+ return false;
2785
+ } else {
2786
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Google fonts request failed for $href -->" . PHP_EOL; }
2787
+ return $html;
2788
+ }
2789
+ }
2790
+
2791
+ # collect and remove google fonts for merging
2792
+ if(stripos($href, 'fonts.googleapis.com') !== false){
2793
+ $fvm_collect_google_fonts[$handle] = $href;
2794
+ return false;
2795
+ }
2796
+
2797
+ # skip external scripts that are not specifically allowed
2798
+ if (fvm_internal_url($href, $wp_home) === false || empty($href)) {
2799
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Skipped the next external enqueued CSS -->" . PHP_EOL; }
2800
+ return $html;
2801
+ }
2802
+
2803
+ # download, minify, cache
2804
+ $tkey = 'css-'.hash('sha1', $handle.$href).'.css';
2805
+ $json = false; $json = fvm_get_transient($tkey);
2806
+ if ( $json === false) {
2807
+ $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2808
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2809
+ fvm_set_transient($tkey, $json);
2810
+ }
2811
+
2812
+ # decode
2813
+ $res = json_decode($json, true);
2814
+
2815
+ # inline it + other inlined children styles
2816
+ if($res['status'] != false) {
2817
+ echo '<style type="text/css" media="'.$media.'">'.$res['code'].'</style>';
2818
+
2819
+ # get inline_styles for this handle, minify and print
2820
+ $inline_styles = array();
2821
+ $inline_styles = wp_styles()->get_data( $handle, 'after' );
2822
+ if($inline_styles != false) {
2823
+
2824
+ # string type
2825
+ if(is_string($inline_styles)) {
2826
+ $code = fastvelocity_min_get_css($href, $inline_styles, $disable_css_minification);
2827
+ if(!empty($code) && $code != false) {
2828
+ echo '<style type="text/css" media="'.$media.'">'.$code.'</style>';
2829
+ }
2830
+ }
2831
+
2832
+ # array type
2833
+ if(is_array($inline_styles)) {
2834
+ foreach ($inline_styles as $st) {
2835
+ $code = fastvelocity_min_get_css($href, $st, $disable_css_minification);
2836
+ if(!empty($code) && $code != false) {
2837
+ echo '<style type="text/css" media="'.$media.'">'.$code.'</style>';
2838
+ }
2839
+ }
2840
+ }
2841
+ }
2842
+
2843
+ # prevent default
2844
+ return false;
2845
+
2846
+ } else {
2847
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: $handle / $href returned an empty from minification -->" . PHP_EOL; }
2848
+ return $html;
2849
+ }
2850
+
2851
+ # fallback, for whatever reason
2852
+ echo "<!-- ERROR: FVM couldn't catch the CSS file below. Please report this on https://wordpress.org/support/plugin/fast-velocity-minify/ -->";
2853
+ return $html;
2854
+ }
2855
+
2856
+
2857
+ # critical css for the page
2858
+ function fastvelocity_add_google_fonts_merged() {
2859
+ global $fvm_collect_google_fonts, $fvmualist, $css_hide_googlefonts, $skip_google_fonts, $min_async_googlefonts, $fvm_debug;
2860
+
2861
+ # prevent optimization for logged in users
2862
+ if (is_admin() || is_preview() || is_customize_preview()) {
2863
+ return false;
2864
+ }
2865
+
2866
+ # must have something to do
2867
+ if(!is_array($fvm_collect_google_fonts) || count($fvm_collect_google_fonts) == 0) {
2868
+ return false;
2869
+ }
2870
+
2871
+ # merge google fonts
2872
+ $gfurl = fastvelocity_min_concatenate_google_fonts($fvm_collect_google_fonts);
2873
+ if(empty($gfurl)) {
2874
+ return false;
2875
+ }
2876
+
2877
+ # hide google fonts from PSI
2878
+ if($css_hide_googlefonts == true) {
2879
+
2880
+ # make a stylesheet, hide from PSI
2881
+ $cssguid = 'fvm'.hash('sha1', $gfurl);
2882
+ echo '<script type="text/javascript">if(fvmuag()){';
2883
+ 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.');';
2884
+ echo '}</script>';
2885
+
2886
+ # load google fonts async
2887
+ } elseif($min_async_googlefonts != false) {
2888
+ echo '<link rel="preload" href="'.$gfurl.'" as="style" media="all" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2889
+ echo '<noscript><link rel="stylesheet" href="'.$gfurl.'" media="all" /></noscript>';
2890
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$gfurl.'" media="all" /><![endif]-->';
2891
+
2892
+ # fallback to normal inline
2893
+ } else {
2894
+ echo '<link rel="stylesheet" href="'.$gfurl.'" media="all" />';
2895
+ }
2896
+
2897
+ # unset per hook
2898
+ foreach($fvm_collect_google_fonts as $k=>$v) {
2899
+ unset($fvm_collect_google_fonts[$k]);
2900
+ }
2901
+
2902
+ }
2903
+
2904
+
2905
+
2906
+ # collect all fvm JS files and save them to an headers file
2907
+ function fastvelocity_collect_js_preload_headers($html, $handle, $src){
2908
+ global $cachedirurl, $collect_preload_js, $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2909
+
2910
+ # return if disabled
2911
+ if ($fvm_enabled_js_preload != true) {
2912
+ return $html;
2913
+ }
2914
+
2915
+ # collect
2916
+ if (stripos($src, $cachedirurl) !== false) {
2917
+ $collect_preload_js[] = $src;
2918
+ }
2919
+ return $html;
2920
+ }
2921
+
2922
+ # generate preload headers file
2923
+ function fastvelocity_generate_preload_headers(){
2924
+ global $cachedirurl, $collect_preload_css, $collect_preload_js, $fvm_enabled_css_preload, $fvm_enabled_js_preload;
2925
+
2926
+ # return if disabled
2927
+ if ($fvm_enabled_css_preload != true && $fvm_enabled_js_preload != true) {
2928
+ return false;
2929
+ }
2930
+
2931
+ # get host with multisite support and query strings
2932
+ $host = htmlentities($_SERVER['SERVER_NAME']);
2933
+ if(empty($hosts)) { $host = htmlentities($_SERVER['HTTP_HOST']); }
2934
+ $request_query = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY);
2935
+ $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
2936
+ $is_admin = strpos( $request_uri, '/wp-admin/' );
2937
+
2938
+ # always false for admin pages
2939
+ if( false !== $is_admin){
2940
+ return false;
2941
+ }
2942
+
2943
+ # initialize headers
2944
+ $headers = array();
2945
+
2946
+ # css headers
2947
+ if ($fvm_enabled_css_preload != false && is_array($collect_preload_css) && count($collect_preload_css) > 0) {
2948
+ foreach($collect_preload_css as $u) {
2949
+
2950
+ # filter out footer footer files, because they are not in the critical path
2951
+ if(stripos($u, $cachedirurl . '/footer-') !== false) { continue; }
2952
+
2953
+ # add headers
2954
+ $headers[] = "Link: <$u>; rel=preload; as=style";
2955
+ }
2956
+ }
2957
+
2958
+ # js headers
2959
+ if ($fvm_enabled_js_preload != false && is_array($collect_preload_js) && count($collect_preload_js) > 0) {
2960
+ foreach($collect_preload_js as $u) {
2961
+
2962
+ # filter out footer footer files, because they are not in the critical path
2963
+ if(stripos($u, $cachedirurl . '/footer-') !== false) { continue; }
2964
+
2965
+ # add headers
2966
+ $headers[] = "Link: <$u>; rel=preload; as=script";
2967
+ }
2968
+ }
2969
+
2970
+ # must have something
2971
+ if(count($headers) == 0) {
2972
+ return false;
2973
+ } else {
2974
+ $headers = implode(PHP_EOL, $headers);
2975
+ }
2976
+
2977
+ # get cache path
2978
+ $cachepath = fvm_cachepath();
2979
+ $headerdir = $cachepath['headerdir'];
2980
+ $cachefilebase = $headerdir.'/';
2981
+
2982
+ # possible cache file locations
2983
+ $b = $cachefilebase . md5($host.'-'.$request_uri).'.header';
2984
+ $a = $cachefilebase . md5($host.'-'.$request_uri.$request_query).'.header';
2985
+
2986
+ # reset file cache
2987
+ clearstatcache();
2988
+
2989
+ # if there are no query strings
2990
+ if($b == $a) {
2991
+ if(!file_exists($a)) {
2992
+ file_put_contents($a, $headers);
2993
+ fastvelocity_fix_permission_bits($a);
2994
+ }
2995
+ return false;
2996
+ }
2997
+
2998
+ # b fallback
2999
+ if($b != $a && !file_exists($b)) {
3000
+ file_put_contents($b, $headers);
3001
+ fastvelocity_fix_permission_bits($b);
3002
+ }
3003
+
3004
+ return false;
3005
+ }
3006
+
3007
+
3008
+ # get current headers file for the url
3009
+ function fastvelocity_get_preload_headers(){
3010
+ global $fvm_enabled_css_preload, $fvm_enabled_js_preload;
3011
+
3012
+ # return if disabled
3013
+ if ($fvm_enabled_css_preload != true && $fvm_enabled_js_preload != true) {
3014
+ return false;
3015
+ }
3016
+
3017
+ # get host with multisite support and query strings
3018
+ $host = htmlentities($_SERVER['SERVER_NAME']);
3019
+ if(empty($hosts)) { $host = htmlentities($_SERVER['HTTP_HOST']); }
3020
+ $request_query = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY);
3021
+ $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
3022
+ $is_admin = strpos( $request_uri, '/wp-admin/' );
3023
+
3024
+ # always false for admin pages
3025
+ if( false !== $is_admin){
3026
+ return false;
3027
+ }
3028
+
3029
+ # get cache path
3030
+ $cachepath = fvm_cachepath();
3031
+ $headerdir = $cachepath['headerdir'];
3032
+ $cachefilebase = $headerdir.'/';
3033
+
3034
+ # possible cache file locations
3035
+ $b = $cachefilebase . md5($host.'-'.$request_uri).'.header';
3036
+ $a = $cachefilebase . md5($host.'-'.$request_uri.$request_query).'.header';
3037
+
3038
+ # reset file cache
3039
+ clearstatcache();
3040
+
3041
+ # return header files or fallback
3042
+ if($b == $a && file_exists($a)) { return file_get_contents($a); }
3043
+ if($b != $a && file_exists($b)) { return file_get_contents($b); }
3044
+
3045
+ return false;
3046
+ }
3047
+
3048
+
3049
+
3050
+ # cron job to delete old FVM cache
3051
+ add_action('fastvelocity_purge_old_cron_event', 'fvm_purge_old');
3052
+
inc/functions-cache.php CHANGED
@@ -323,7 +323,7 @@ if ( class_exists("comet_cache") ) {
323
  # Purge Zen Cache
324
  if ( class_exists("zencache") ) {
325
  zencache::clear();
326
- return __('<div class="notice notice-info is-dismissible"><p>All caches on <strong>Comet Cache</strong> have been purged.</p></div>');
327
  }
328
 
329
  # Purge LiteSpeed Cache
@@ -335,7 +335,7 @@ if (class_exists('LiteSpeed_Cache_Tags')) {
335
  # Purge Hyper Cache
336
  if (class_exists( 'HyperCache' )) {
337
  do_action( 'autoptimize_action_cachepurged' );
338
- return __( '<div class="notice notice-info is-dismissible"><p>All caches on <strong>HyperCache</strong> have been purged.</p></div>');
339
  }
340
 
341
  # purge cache enabler
@@ -347,6 +347,7 @@ if ( has_action('ce_clear_cache') ) {
347
  # purge wpfc
348
  if (function_exists('wpfc_clear_all_cache')) {
349
  wpfc_clear_all_cache(true);
 
350
  }
351
 
352
  # add breeze cache purge support
323
  # Purge Zen Cache
324
  if ( class_exists("zencache") ) {
325
  zencache::clear();
326
+ return __('<div class="notice notice-info is-dismissible"><p>All caches on <strong>Zen Cache</strong> have been purged.</p></div>');
327
  }
328
 
329
  # Purge LiteSpeed Cache
335
  # Purge Hyper Cache
336
  if (class_exists( 'HyperCache' )) {
337
  do_action( 'autoptimize_action_cachepurged' );
338
+ return __( '<div class="notice notice-info is-dismissible"><p>All caches on <strong>Hyper Cache</strong> have been purged.</p></div>');
339
  }
340
 
341
  # purge cache enabler
347
  # purge wpfc
348
  if (function_exists('wpfc_clear_all_cache')) {
349
  wpfc_clear_all_cache(true);
350
+ return __( '<div class="notice notice-info is-dismissible"><p>All caches on <strong>WPFC</strong> have been purged.</p></div>');
351
  }
352
 
353
  # add breeze cache purge support
inc/functions-upgrade.php CHANGED
@@ -16,21 +16,13 @@ function fastvelocity_plugin_upgrade_completed($upgrader_object, $options) {
16
  update_option( "fastvelocity_plugin_version", $fastvelocity_plugin_version, 'no');
17
  }
18
 
19
- if( $options['action'] == 'update' && $options['type'] == 'plugin' && isset( $options['plugins'] ) ) {
20
- # Iterate through the plugins being updated and check if ours is there
21
- foreach( $options['plugins'] as $plugin ) {
22
- if( $plugin == plugin_basename( __FILE__ )) {
23
-
24
- # run for any update lower than 2.8.0
25
- if (version_compare($ver, '2.8.0', '<')) {
26
 
27
- # default ignore list
28
- $exc = array('/themes/Avada/assets/js/main.min.js', '/plugins/woocommerce-product-search/js/product-search.js', '/plugins/revslider/public/assets/js/jquery.themepunch.tools.min.js', '/js/TweenMax.min.js', '/themes/jupiter/assets/js/min/full-scripts', '/plugins/LayerSlider/static/layerslider/js/greensock.js', '/themes/kalium/assets/js/main.min.js', '/js/mediaelement/', '/plugins/elementor/assets/js/common.min.js', '/plugins/elementor/assets/js/frontend.min.js', '/plugins/elementor-pro/assets/js/frontend.min.js', '/themes/kalium/assets/js/main.min.js');
29
- update_option('fastvelocity_min_ignorelist', implode(PHP_EOL, $exc), 'no');
30
 
31
- }
32
- }
33
- }
34
  }
35
  }
36
 
16
  update_option( "fastvelocity_plugin_version", $fastvelocity_plugin_version, 'no');
17
  }
18
 
19
+ # run for any update lower than 2.8.4
20
+ if (version_compare($ver, '2.8.4', '<')) {
 
 
 
 
 
21
 
22
+ # default ignore list update
23
+ $exc = array('/themes/Avada/assets/js/main.min.js', '/plugins/woocommerce-product-search/js/product-search.js', '/plugins/revslider/public/assets/js/jquery.themepunch.tools.min.js', '/js/TweenMax.min.js', '/themes/jupiter/assets/js/min/full-scripts', '/plugins/LayerSlider/static/layerslider/js/greensock.js', '/themes/kalium/assets/js/main.min.js', '/js/mediaelement/', '/plugins/elementor/assets/js/common.min.js', '/plugins/elementor/assets/js/frontend.min.js', '/plugins/elementor-pro/assets/js/frontend.min.js', '/themes/kalium/assets/js/main.min.js', '/wp-includes/js/mediaelement/wp-mediaelement.min.js');
24
+ update_option('fastvelocity_min_ignorelist', implode(PHP_EOL, $exc), 'no');
25
 
 
 
 
26
  }
27
  }
28
 
inc/functions.php CHANGED
@@ -68,7 +68,7 @@ function fastvelocity_plugin_activate() {
68
  update_option('fastvelocity_min_blacklist', implode(PHP_EOL, $exc), 'no');
69
 
70
  # default ignore list
71
- $exc = array('/themes/Avada/assets/js/main.min.js', '/plugins/woocommerce-product-search/js/product-search.js', '/plugins/revslider/public/assets/js/jquery.themepunch.tools.min.js', '/js/TweenMax.min.js', '/themes/jupiter/assets/js/min/full-scripts', '/plugins/LayerSlider/static/layerslider/js/greensock.js', '/themes/kalium/assets/js/main.min.js', '/js/mediaelement/', '/plugins/elementor/assets/js/common.min.js', '/plugins/elementor/assets/js/frontend.min.js', '/plugins/elementor-pro/assets/js/frontend.min.js', '/themes/kalium/assets/js/main.min.js');
72
  update_option('fastvelocity_min_ignorelist', implode(PHP_EOL, $exc), 'no');
73
 
74
  }
@@ -312,7 +312,7 @@ function fastvelocity_min_get_js($url, $js, $disable_js_minification) {
312
  global $fvm_debug;
313
 
314
  # exclude minification on already minified files + jquery (because minification might break those)
315
- $excl = array('jquery.js', '.min.js', '-min.js', '/uploads/fusion-scripts/', '/min/', '.packed.js', '/frontend-builder-global-functions.js');
316
  foreach($excl as $e) { if (stripos(basename($url), $e) !== false) { $disable_js_minification = true; break; } }
317
 
318
  # remove BOM
@@ -326,7 +326,7 @@ if(!$disable_js_minification) {
326
  }
327
 
328
  # remove sourcemaps
329
- $js = preg_replace('~//[#@]\s(source(?:Mapping)?URL)=\s*(\S+)~', '', $js);
330
 
331
  # needed when merging js files
332
  $js = trim($js);
@@ -395,7 +395,7 @@ $ctime = get_option('fvm-last-cache-update', '0'); # last update or zero
395
  $css = preg_replace('/(.eot|.woff2|.woff|.ttf)+[?+](.+?)(\)|\'|\")/ui', "$1"."#".$ctime."$3", $css); # fonts cache buster
396
 
397
  # remove sourcemaps
398
- $css = preg_replace('~//[#@]\s(source(?:Mapping)?URL)=\s*(\S+)~', '', $css);
399
 
400
  # minify CSS
401
  if(!$disable_css_minification) {
68
  update_option('fastvelocity_min_blacklist', implode(PHP_EOL, $exc), 'no');
69
 
70
  # default ignore list
71
+ $exc = array('/themes/Avada/assets/js/main.min.js', '/plugins/woocommerce-product-search/js/product-search.js', '/plugins/revslider/public/assets/js/jquery.themepunch.tools.min.js', '/js/TweenMax.min.js', '/themes/jupiter/assets/js/min/full-scripts', '/plugins/LayerSlider/static/layerslider/js/greensock.js', '/themes/kalium/assets/js/main.min.js', '/js/mediaelement/', '/plugins/elementor/assets/js/common.min.js', '/plugins/elementor/assets/js/frontend.min.js', '/plugins/elementor-pro/assets/js/frontend.min.js', '/themes/kalium/assets/js/main.min.js', '/wp-includes/js/mediaelement/wp-mediaelement.min.js');
72
  update_option('fastvelocity_min_ignorelist', implode(PHP_EOL, $exc), 'no');
73
 
74
  }
312
  global $fvm_debug;
313
 
314
  # exclude minification on already minified files + jquery (because minification might break those)
315
+ $excl = array('jquery.js', '.min.js', '-min.js', '/uploads/fusion-scripts/', '/min/', '.packed.js', '/includes/builder/scripts/');
316
  foreach($excl as $e) { if (stripos(basename($url), $e) !== false) { $disable_js_minification = true; break; } }
317
 
318
  # remove BOM
326
  }
327
 
328
  # remove sourcemaps
329
+ $js = preg_replace('~//[#@]\s(source(?:Mapping)?URL)=\s*(\S+)~us', '', $js);
330
 
331
  # needed when merging js files
332
  $js = trim($js);
395
  $css = preg_replace('/(.eot|.woff2|.woff|.ttf)+[?+](.+?)(\)|\'|\")/ui', "$1"."#".$ctime."$3", $css); # fonts cache buster
396
 
397
  # remove sourcemaps
398
+ $css = preg_replace('~//[#@]\s(source(?:Mapping)?URL)=\s*(\S+)~us', '', $css);
399
 
400
  # minify CSS
401
  if(!$disable_css_minification) {
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: Alignak
3
  Tags: PHP Minify, Lighthouse, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance, Optimization, FVM
4
  Requires at least: 4.7
5
  Requires PHP: 5.6
6
- Stable tag: 2.8.4
7
  Tested up to: 5.4
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -198,6 +198,9 @@ Please backup your site before updating. Version 3.0 will have a major code rewr
198
 
199
  == Changelog ==
200
 
 
 
 
201
  = 2.8.4 [2020.04.24] =
202
  * added frontend-builder-global-functions.js to the list of minification exclusions, but allowing merging (Divi Compatibility)
203
 
3
  Tags: PHP Minify, Lighthouse, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance, Optimization, FVM
4
  Requires at least: 4.7
5
  Requires PHP: 5.6
6
+ Stable tag: 2.8.5
7
  Tested up to: 5.4
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
198
 
199
  == Changelog ==
200
 
201
+ = 2.8.5 [2020.04.30] =
202
+ * bug fixes and some more minification default exclusions
203
+
204
  = 2.8.4 [2020.04.24] =
205
  * added frontend-builder-global-functions.js to the list of minification exclusions, but allowing merging (Divi Compatibility)
206