09b52d43 by Jeff Balicki

ddd

1 parent 4c19e6fe
...@@ -6,7 +6,7 @@ Description: Improve your speed score on GTmetrix, Pingdom Tools and Google Page ...@@ -6,7 +6,7 @@ Description: Improve your speed score on GTmetrix, Pingdom Tools and Google Page
6 Author: Raul Peixoto 6 Author: Raul Peixoto
7 Author URI: http://fastvelocity.com 7 Author URI: http://fastvelocity.com
8 Text Domain: fast-velocity-minify 8 Text Domain: fast-velocity-minify
9 Version: 3.2.2 9 Version: 3.2.6
10 License: GPL2 10 License: GPL2
11 11
12 ------------------------------------------------------------------------ 12 ------------------------------------------------------------------------
......
...@@ -83,6 +83,49 @@ function fvm_check_misconfiguration() { ...@@ -83,6 +83,49 @@ function fvm_check_misconfiguration() {
83 } 83 }
84 84
85 } 85 }
86
87 # check if our tables exist, and do maintenance once a day
88 $fvm_table_checker = get_transient('fvm_table_checker');
89 $fvm_table_checker = false;
90 if ($fvm_table_checker === false) {
91
92 # test if at least one table exists
93 global $wpdb;
94 if(!is_null($wpdb)) {
95 $sqla_table_name = $wpdb->prefix . 'fvm_cache';
96 if (!$wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $sqla_table_name)) === $sqla_table_name) {
97 fvm_plugin_activate();
98 }
99 }
100
101 # daily maintenance
102 try {
103
104 if(!is_null($wpdb)) {
105
106 # limit cache table to 20k records
107 $lim = 20000;
108 $res = $wpdb->get_row("SELECT MAX(id) as maxid FROM ".$wpdb->prefix."fvm_cache");
109 if(isset($res->maxid) && intval($res->maxid) > $lim) {
110 $wpdb->query($wpdb->prepare("DELETE FROM ".$wpdb->prefix."fvm_cache WHERE id < %d LIMIT 1", (intval($res->maxid) - $lim)));
111 }
112
113 # limit logs table to 500 records
114 $lim = 500;
115 $res = $wpdb->get_row("SELECT MAX(id) as maxid FROM ".$wpdb->prefix."fvm_logs");
116 if(isset($res->maxid) && intval($res->maxid) > $lim) {
117 $wpdb->query($wpdb->prepare("DELETE FROM ".$wpdb->prefix."fvm_logs WHERE id < %d LIMIT 1", (intval($res->maxid) - $lim)));
118 }
119
120 }
121
122 } catch (Exception $e) {
123 error_log('Error: '.$e->getMessage(), 0);
124 }
125
126
127 }
128
86 129
87 } catch (Exception $e) { 130 } catch (Exception $e) {
88 error_log('Caught exception (fvm_initialize_database): '.$e->getMessage(), 0); 131 error_log('Caught exception (fvm_initialize_database): '.$e->getMessage(), 0);
...@@ -207,25 +250,30 @@ function fvm_add_admin_menu() { ...@@ -207,25 +250,30 @@ function fvm_add_admin_menu() {
207 # print admin notices when needed (json) 250 # print admin notices when needed (json)
208 function fvm_show_admin_notice_from_transient() { 251 function fvm_show_admin_notice_from_transient() {
209 if(current_user_can('manage_options')) { 252 if(current_user_can('manage_options')) {
210 $inf = get_transient('fvm_admin_notice'); 253 $inf = get_transient('fvm_admin_notice_'.get_current_user_id());
254
255 # show transient after the redirect
211 if($inf != false && !empty($inf)) { 256 if($inf != false && !empty($inf)) {
212 $jsonarr = json_decode($inf, true); 257 $notices = json_decode($inf, true);
213 if(!is_null($jsonarr) && is_array($jsonarr)){ 258 if(!is_null($notices) && is_array($notices)){
214
215 # add all
216 $jsonarr = array_unique($jsonarr);
217 foreach ($jsonarr as $notice) {
218 add_settings_error( 'fvm_admin_notice', 'fvm_admin_notice', 'FVM: '.$notice, 'info' );
219 }
220 259
221 # output on other pages 260 # consolidate messages
222 if(!isset($_GET['page']) || (isset($_GET['page']) && $_GET['page'] != 'fvm')) { 261 $notices = array_unique($notices);
223 settings_errors( 'fvm_admin_notice' ); 262 if(count($notices) > 1) {
263 $msg = '<div class="fvm-info-list"><h3>FVM</h3><ul>';
264 foreach ($notices as $notice) { $msg.= "<li>$notice</li>"; }
265 $msg.= '</ul></div>';
266 add_settings_error( 'fvm_admin_notice', 'fvm_admin_notice', $msg, 'info' );
267 } else {
268 $msg = 'FVM: '.implode(PHP_EOL, $notices);
269 add_settings_error( 'fvm_admin_notice', 'fvm_admin_notice', $msg, 'info' );
224 } 270 }
271
225 } 272 }
226 273
227 # remove 274 # delete
228 delete_transient('fvm_admin_notice'); 275 delete_transient('fvm_admin_notice_'.get_current_user_id());
276
229 } 277 }
230 } 278 }
231 } 279 }
...@@ -301,47 +349,66 @@ function fvm_get_logs_callback() { ...@@ -301,47 +349,66 @@ function fvm_get_logs_callback() {
301 register_activation_hook($fvm_var_file, 'fvm_plugin_activate'); 349 register_activation_hook($fvm_var_file, 'fvm_plugin_activate');
302 function fvm_plugin_activate() { 350 function fvm_plugin_activate() {
303 351
352 # defauls
304 global $wpdb; 353 global $wpdb;
305 if(is_null($wpdb)) { return false; } 354 if(is_null($wpdb)) { return false; }
306 355 $charset_collate = $wpdb->get_charset_collate();
307 # defauls
308 $sql = array();
309 $wpdb_collate = $wpdb->collate;
310
311 # create cache table
312 $sqla_table_name = $wpdb->prefix . 'fvm_cache'; 356 $sqla_table_name = $wpdb->prefix . 'fvm_cache';
313 $sqla = "CREATE TABLE IF NOT EXISTS {$sqla_table_name} (
314 `id` bigint(20) unsigned NOT NULL auto_increment ,
315 `uid` varchar(64) NOT NULL,
316 `date` bigint(10) unsigned NOT NULL,
317 `type` varchar(3) NOT NULL,
318 `content` mediumtext NOT NULL,
319 `meta` mediumtext NOT NULL,
320 PRIMARY KEY (id),
321 UNIQUE KEY uid (uid),
322 KEY date (date), KEY type (type)
323 )
324 COLLATE {$wpdb_collate}";
325
326 # create logs table
327 $sqlb_table_name = $wpdb->prefix . 'fvm_logs'; 357 $sqlb_table_name = $wpdb->prefix . 'fvm_logs';
328 $sqlb = "CREATE TABLE IF NOT EXISTS {$sqlb_table_name} ( 358
329 `id` bigint(20) unsigned NOT NULL auto_increment, 359 # create cache table
330 `uid` varchar(64) NOT NULL, 360 $sqla = "CREATE TABLE {$sqla_table_name} (
331 `date` bigint(10) unsigned NOT NULL, 361 id bigint(20) unsigned NOT NULL auto_increment ,
332 `type` varchar(10) NOT NULL, 362 uid varchar(64) NOT NULL,
333 `msg` mediumtext NOT NULL, 363 date bigint(10) unsigned NOT NULL,
334 `meta` mediumtext NOT NULL, 364 type varchar(3) NOT NULL,
335 PRIMARY KEY (id), 365 content mediumtext NOT NULL,
336 UNIQUE KEY uid (uid), 366 meta mediumtext NOT NULL,
337 KEY date (date), 367 PRIMARY KEY (id),
338 KEY type (type) 368 UNIQUE KEY uid (uid),
339 ) 369 KEY date (date), KEY type (type)
340 COLLATE {$wpdb_collate}"; 370 ) $charset_collate;";
371
372 # create logs table
373 $sqlb = "CREATE TABLE {$sqlb_table_name} (
374 id bigint(20) unsigned NOT NULL auto_increment,
375 uid varchar(64) NOT NULL,
376 date bigint(10) unsigned NOT NULL,
377 type varchar(10) NOT NULL,
378 msg mediumtext NOT NULL,
379 meta mediumtext NOT NULL,
380 PRIMARY KEY (id),
381 UNIQUE KEY uid (uid),
382 KEY date (date),
383 KEY type (type)
384 ) $charset_collate;";
341 385
342 # run sql 386 # run sql
343 $wpdb->query($sqla); 387 # https://developer.wordpress.org/reference/functions/dbdelta/
344 $wpdb->query($sqlb); 388 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
389 dbDelta( $sqla );
390 dbDelta( $sqlb );
391
392 # test if at least one table exists
393 if (!$wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $sqla_table_name)) === $sqla_table_name) {
394
395 # log
396 $err = 'An error occurred when trying to create the database tables';
397 error_log($err);
398
399 # alert
400 if(is_admin()) {
401 $notices = array($err);
402 set_transient('fvm_admin_notice_'.get_current_user_id(), json_encode($notices), 10);
403 }
404
405 # try again in 1 hour
406 set_transient('fvm_table_checker', true, HOUR_IN_SECONDS);
407
408 } else {
409 # success, but check again tomorrow
410 set_transient('fvm_table_checker', true, DAY_IN_SECONDS);
411 }
345 412
346 } 413 }
347 414
...@@ -349,6 +416,9 @@ function fvm_plugin_activate() { ...@@ -349,6 +416,9 @@ function fvm_plugin_activate() {
349 # run during deactivation 416 # run during deactivation
350 register_deactivation_hook($fvm_var_file, 'fvm_plugin_deactivate'); 417 register_deactivation_hook($fvm_var_file, 'fvm_plugin_deactivate');
351 function fvm_plugin_deactivate() { 418 function fvm_plugin_deactivate() {
419
420 # process cache settings
421 fvm_purge_static_files();
352 422
353 global $wpdb; 423 global $wpdb;
354 if(is_null($wpdb)) { return false; } 424 if(is_null($wpdb)) { return false; }
...@@ -356,16 +426,17 @@ function fvm_plugin_deactivate() { ...@@ -356,16 +426,17 @@ function fvm_plugin_deactivate() {
356 # remove options and tables 426 # remove options and tables
357 $wpdb->query("DELETE FROM {$wpdb->prefix}options WHERE option_name = 'fvm_last_cache_update'"); 427 $wpdb->query("DELETE FROM {$wpdb->prefix}options WHERE option_name = 'fvm_last_cache_update'");
358 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}fvm_cache"); 428 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}fvm_cache");
359 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}fvm_logs"); 429 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}fvm_logs");
360
361 # process cache settings
362 fvm_purge_static_files();
363 430
364 } 431 }
365 432
366 # run during uninstall 433 # run during uninstall
367 register_uninstall_hook($fvm_var_file, 'fvm_plugin_uninstall'); 434 register_uninstall_hook($fvm_var_file, 'fvm_plugin_uninstall');
368 function fvm_plugin_uninstall() { 435 function fvm_plugin_uninstall() {
436
437 # process cache settings
438 fvm_purge_static_files();
439
369 global $wpdb; 440 global $wpdb;
370 if(is_null($wpdb)) { return false; } 441 if(is_null($wpdb)) { return false; }
371 442
...@@ -375,9 +446,6 @@ function fvm_plugin_uninstall() { ...@@ -375,9 +446,6 @@ function fvm_plugin_uninstall() {
375 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}fvm_cache"); 446 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}fvm_cache");
376 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}fvm_logs"); 447 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}fvm_logs");
377 448
378 # process cache settings
379 fvm_purge_static_files();
380
381 } 449 }
382 450
383 451
......
...@@ -214,7 +214,7 @@ function fvm_purge_others(){ ...@@ -214,7 +214,7 @@ function fvm_purge_others(){
214 do_action("swcfpc_purge_everything"); 214 do_action("swcfpc_purge_everything");
215 return __( 'All caches on <strong>WP Cloudflare Super Page Cache</strong> have been purged.', 'fast-velocity-minify' ); 215 return __( 'All caches on <strong>WP Cloudflare Super Page Cache</strong> have been purged.', 'fast-velocity-minify' );
216 } 216 }
217 217
218 # Purge Hyper Cache 218 # Purge Hyper Cache
219 if (class_exists( 'HyperCache' )) { 219 if (class_exists( 'HyperCache' )) {
220 do_action( 'autoptimize_action_cachepurged' ); 220 do_action( 'autoptimize_action_cachepurged' );
...@@ -255,6 +255,30 @@ function fvm_purge_others(){ ...@@ -255,6 +255,30 @@ function fvm_purge_others(){
255 do_action('wpo_cache_flush'); 255 do_action('wpo_cache_flush');
256 return __( 'All caches on <strong>WP-Optimize</strong> have been purged.', 'fast-velocity-minify' ); 256 return __( 'All caches on <strong>WP-Optimize</strong> have been purged.', 'fast-velocity-minify' );
257 } 257 }
258
259 # nginx helper
260 if(has_action('rt_nginx_helper_purge_all')) {
261 do_action('rt_nginx_helper_purge_all');
262 $ret[] = __( 'Nginx Helper' );
263 }
264
265
266 # Object Cache
267
268 # WordPress OPCache
269 if (function_exists('wp_cache_flush')) {
270 wp_cache_flush();
271 }
272
273 # Purge Redis Object Cache plugin
274 if(class_exists('Redis') && defined('WP_REDIS_PATH')) {
275 $r = new Redis();
276 if ($r->connect( WP_REDIS_PATH, 0 )) {
277 if( false !== $r->flushdb() ) {
278 $ret[] = __('Redis Object Cache');
279 }
280 }
281 }
258 282
259 # hosting companies 283 # hosting companies
260 284
...@@ -316,15 +340,59 @@ function fvm_purge_others(){ ...@@ -316,15 +340,59 @@ function fvm_purge_others(){
316 if(function_exists('pantheon_wp_clear_edge_all')) { 340 if(function_exists('pantheon_wp_clear_edge_all')) {
317 pantheon_wp_clear_edge_all(); 341 pantheon_wp_clear_edge_all();
318 } 342 }
343
344 # cloudways varnish
345 if(fvm_purge_varnish_cloudways()) {
346 $ret[] = __('Cloudways (Varnish)');
347 }
319 348
320 # wordpress default cache 349 # bigscoots.com
321 if (function_exists('wp_cache_flush')) { 350 if(has_action('bs_cache_purge_cache')) {
322 wp_cache_flush(); 351 do_action('bs_cache_purge_cache');
352 $ret[] = __( 'BigScoots' );
353 }
354
355 # godaddy.com managed WordPress
356 if (class_exists('WPass') && method_exists('WPass\Cache', 'do_ban')){
357 WPaaS\Cache::do_ban();
358 $ret[] = __( 'GoDaddy' );
323 } 359 }
324 360
325 } 361 }
326 362
327 363
364 # purge varnish on cloudways
365 function fvm_purge_varnish_cloudways() {
366
367 # cloudways detection
368 if (!isset($_SERVER['cw_allowed_ip'])){ return false; }
369
370 # must have
371 if (!isset($_SERVER['HTTP_X_VARNISH']) || !isset($_SERVER['HTTP_X_APPLICATION'])){ return false; }
372 if (is_null($_SERVER['HTTP_X_VARNISH']) || is_null($_SERVER['HTTP_X_APPLICATION'])){ return false; }
373 if ('varnishpass' === trim($_SERVER['HTTP_X_APPLICATION'])){ return false; }
374 if ('bypass' === trim($_SERVER['HTTP_X_APPLICATION'])){ return false; }
375
376 # host and uri path
377 $host = wpraiser_get_domain();
378
379 # request arguments
380 $request_args = array('method' => 'PURGE', 'redirection' => 0, 'timeout' => 10, 'blocking' => false, 'headers' => array('Host' => $host, 'X-Purge-Method' => 'regex') );
381
382 # default host and port
383 $varnish_ip = '127.0.0.1';
384 $varnish_port = '8080';
385
386 # overwrite by constant
387 if(defined('FVM_VARNISH_IP') && !empty(FVM_VARNISH_IP)) { $varnish_ip = trim(FVM_VARNISH_IP); }
388 if(defined('FVM_VARNISH_PORT') && !empty(FVM_VARNISH_PORT)) { $varnish_port = trim(FVM_VARNISH_PORT); }
389
390 # purge async
391 $response = wp_remote_request('http://'.$varnish_ip.':'.$varnish_port.'/.*', $request_args);
392 return true;
393 }
394
395
328 # Purge Godaddy Managed WordPress Hosting (Varnish) 396 # Purge Godaddy Managed WordPress Hosting (Varnish)
329 function fvm_godaddy_request( $method) { 397 function fvm_godaddy_request( $method) {
330 $url = home_url(); 398 $url = home_url();
...@@ -460,34 +528,20 @@ function fvm_generate_min_url($url, $tkey, $type, $code) { ...@@ -460,34 +528,20 @@ function fvm_generate_min_url($url, $tkey, $type, $code) {
460 $file = $ch_info['ch_dir'] . DIRECTORY_SEPARATOR . $filename; 528 $file = $ch_info['ch_dir'] . DIRECTORY_SEPARATOR . $filename;
461 $public = $ch_info['ch_url'] . '/' .$filename; 529 $public = $ch_info['ch_url'] . '/' .$filename;
462 530
463 # wordpress functions 531 # php
464 require_once (ABSPATH . DIRECTORY_SEPARATOR . 'wp-admin'. DIRECTORY_SEPARATOR .'includes'. DIRECTORY_SEPARATOR .'class-wp-filesystem-base.php'); 532 if(!file_exists($file) || (file_exists($file) && filemtime($file) < $tvers)) { file_put_contents($file, $code); }
465 require_once (ABSPATH . DIRECTORY_SEPARATOR .'wp-admin'. DIRECTORY_SEPARATOR .'includes'. DIRECTORY_SEPARATOR .'class-wp-filesystem-direct.php'); 533 if(file_exists($file)) { return $public; }
466
467 # initialize
468 $fileSystemDirect = new WP_Filesystem_Direct(false);
469
470 # create if doesn't exist
471 if(!$fileSystemDirect->exists($file) || ($fileSystemDirect->exists($file) && $fileSystemDirect->mtime($file) < $tvers)) {
472 $fileSystemDirect->put_contents($file, $code);
473 }
474
475 # return url
476 return $public;
477 534
478 } 535 }
479 } 536 }
480 537
481 # default 538 # default, fail and log
482 return $url; 539 return false;
483 } 540 }
484 541
485 542
486 543
487 544
488
489
490
491 # check if PHP has some functions disabled 545 # check if PHP has some functions disabled
492 function fvm_function_available($func) { 546 function fvm_function_available($func) {
493 if (ini_get('safe_mode')) return false; 547 if (ini_get('safe_mode')) return false;
...@@ -535,51 +589,80 @@ function fvm_purge_static_files() { ...@@ -535,51 +589,80 @@ function fvm_purge_static_files() {
535 global $wpdb; 589 global $wpdb;
536 if(is_null($wpdb)) { return false; } 590 if(is_null($wpdb)) { return false; }
537 try { 591 try {
538 $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}fvm_cache"); 592
539 $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}fvm_logs"); 593 # table names
594 $sqla_table_name = $wpdb->prefix . 'fvm_cache';
595 $sqlb_table_name = $wpdb->prefix . 'fvm_logs';
596
597 # test if at least one table exists and empty them
598 if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $sqla_table_name)) === $sqla_table_name) {
599 $wpdb->query("TRUNCATE TABLE {$sqla_table_name}");
600 $wpdb->query("TRUNCATE TABLE {$sqlb_table_name}");
601 }
602
540 } catch (Exception $e) { 603 } catch (Exception $e) {
541 error_log('Error: '.$e->getMessage(), 0); 604 error_log('Error: '.$e->getMessage(), 0);
542 } 605 }
543 606
544 # increment 607 # increment
545 update_option('fvm_last_cache_update', time()); 608 $tver = time();
609 update_option('fvm_last_cache_update', $tver);
546 610
547 # check cache directory 611 # check cache directory
548 $ch_info = fvm_get_cache_location(); 612 $ch_info = fvm_get_cache_location();
549 if(isset($ch_info['ch_url']) && !empty($ch_info['ch_url']) && isset($ch_info['ch_dir']) && !empty($ch_info['ch_dir'])) { 613 if(isset($ch_info['ch_url']) && !empty($ch_info['ch_url']) && isset($ch_info['ch_dir']) && !empty($ch_info['ch_dir'])) {
550 if(is_dir($ch_info['ch_dir']) && is_writable($ch_info['ch_dir'])) { 614 if(is_dir($ch_info['ch_dir']) && is_writable($ch_info['ch_dir'])) {
551 615
552 # wordpress functions
553 require_once (ABSPATH . DIRECTORY_SEPARATOR . 'wp-admin'. DIRECTORY_SEPARATOR .'includes'. DIRECTORY_SEPARATOR .'class-wp-filesystem-base.php');
554 require_once (ABSPATH . DIRECTORY_SEPARATOR .'wp-admin'. DIRECTORY_SEPARATOR .'includes'. DIRECTORY_SEPARATOR .'class-wp-filesystem-direct.php');
555 616
556 # start
557 $fileSystemDirect = new WP_Filesystem_Direct(false);
558
559 # instant purge 617 # instant purge
560 global $fvm_settings;
561 if(isset($fvm_settings['cache']['min_instant_purge']) && $fvm_settings['cache']['min_instant_purge'] == true) { 618 if(isset($fvm_settings['cache']['min_instant_purge']) && $fvm_settings['cache']['min_instant_purge'] == true) {
562 $fileSystemDirect->rmdir($ch_info['ch_dir'], true); 619 fvm_rrmdir($ch_info['ch_dir']);
563 return true; 620 } else {
564 } else { 621 fvm_rrmdir($ch_info['ch_dir'], $tver); # 7 days
622 }
623
624 }
625 }
626
627 }
628
629
630 # remove all cache files
631 function fvm_rrmdir($path, $tver=null) {
632 clearstatcache();
633 if(is_dir($path)) {
634 try {
635
636 $i = new DirectoryIterator($path);
637 foreach($i as $f){
565 638
566 # older than 24h and not matching current timestamp 639 # 7 days older than timestamp
567 $list = $fileSystemDirect->dirlist($ch_info['ch_dir'], false, true); 640 if(isset($tver) && !is_null($tver)) {
568 if(is_array($list) && count($list) > 0) { 641
569 foreach($list as $k=>$arr) { 642 if($f->isFile() && $f->getMTime() <= intval($tver) - 86400 * 7) { @unlink($f->getRealPath()); }
570 if(isset($arr['lastmodunix']) && $arr['type'] == 'f' && intval($arr['lastmodunix']) <= time()-86400) { 643 if($f->isDir() && !$f->isDot()){
571 if(substr($arr['name'], 0, 10) !== time()) { 644 fvm_rrmdir($f->getRealPath(), $tver);
572 $fileSystemDirect->delete($ch_info['ch_dir'] . DIRECTORY_SEPARATOR . $arr['name'], false, 'f'); 645 @rmdir($f->getRealPath());
573 } 646 }
574 } 647
648 } else {
649 # immediate
650 if($f->isFile()){ @unlink($f->getRealPath()); }
651 if($f->isDir() && !$f->isDot()){
652 fvm_rrmdir($f->getRealPath());
653 @rmdir($f->getRealPath());
575 } 654 }
576 } 655 }
577
578 }
579 656
580 } 657 }
658
659 } catch (Exception $e) {
660 return get_class($e) . ": " . $e->getMessage();
661 }
662
663 # self
664 if(is_dir($path)) { @rmdir($path); }
581 } 665 }
582
583 } 666 }
584 667
585 668
...@@ -950,20 +1033,13 @@ function fvm_replace_css_imports($css, $rq=null) { ...@@ -950,20 +1033,13 @@ function fvm_replace_css_imports($css, $rq=null) {
950 1033
951 1034
952 # remove fonts and icons from final css 1035 # remove fonts and icons from final css
953 function fvm_extract_fonts($css_code) { 1036 function fvm_extract_fonts($css_code, $url=null) {
954 1037
955 global $fvm_settings, $fvm_urls; 1038 global $fvm_settings, $fvm_urls;
956 $critical_fonts = array();
957 $mff = array(); 1039 $mff = array();
958 $css_preload = array(); 1040 $css_preload = array();
959 $css_code_ff = ''; 1041 $css_code_ff = '';
960 1042
961 # get list of fonts that are on the critical path and are to be left alone
962 if( isset($fvm_settings['css']['css_optimize_critical_fonts']) &&
963 !empty($fvm_settings['css']['css_optimize_critical_fonts'])) {
964 $critical_fonts = fvm_string_toarray($fvm_settings['css']['css_optimize_critical_fonts']);
965 }
966
967 # extract font faces 1043 # extract font faces
968 preg_match_all('/\@\s*font-face\s*\{([^}]+)\}/iUu', $css_code, $mff); 1044 preg_match_all('/\@\s*font-face\s*\{([^}]+)\}/iUu', $css_code, $mff);
969 if(isset($mff[0]) && is_array($mff[0])) { 1045 if(isset($mff[0]) && is_array($mff[0])) {
...@@ -976,6 +1052,50 @@ function fvm_extract_fonts($css_code) { ...@@ -976,6 +1052,50 @@ function fvm_extract_fonts($css_code) {
976 } 1052 }
977 } 1053 }
978 1054
1055 # add font-display swap for all font faces
1056 # https://developers.google.com/web/updates/2016/02/font-display
1057 $css_code_ff = preg_replace_callback('/(?:@font-face)\s*{(?<value>[^}]+)}/i',
1058 function ($matches) {
1059 if(stripos($matches['value'], 'font-display') !== false) {
1060 return $matches[0];
1061 } else {
1062 return str_replace($matches['value'], 'font-display:swap;'.$matches['value'], $matches[0] );
1063 }
1064 },
1065 $css_code_ff
1066 );
1067
1068 # add font-display swap for all font faces
1069 # https://developers.google.com/web/updates/2016/02/font-display
1070 $css_code = preg_replace_callback('/(?:@font-face)\s*{(?<value>[^}]+)}/i',
1071 function ($matches) {
1072 if(stripos($matches['value'], 'font-display') !== false) {
1073 return $matches[0];
1074 } else {
1075 return str_replace($matches['value'], 'font-display:swap;'.$matches['value'], $matches[0] );
1076 }
1077 },
1078 $css_code
1079 );
1080
1081 # remove query strings from fonts
1082 $css_code_ff = preg_replace('/(.eot|.woff2|.woff|.ttf)+[?+](.+?)(\)|\'|\")/ui', "$1"."$3", $css_code_ff);
1083 $css_code = preg_replace('/(.eot|.woff2|.woff|.ttf)+[?+](.+?)(\)|\'|\")/ui', "$1"."$3", $css_code);
1084
1085 # fix url paths css_code_ff
1086 if(!empty($url)) {
1087 $matches = array(); preg_match_all("/url\(\s*['\"]?(?!data:)(?!http)(?![\/'\"])(.+?)['\"]?\s*\)/ui", $css_code_ff, $matches);
1088 foreach($matches[1] as $a) { $b = trim($a); if($b != $a) { $css_code_ff = str_replace($a, $b, $css_code_ff); } }
1089 $css_code_ff = preg_replace("/url\(\s*['\"]?(?!data:)(?!http)(?![\/'\"#])(.+?)['\"]?\s*\)/ui", "url(".dirname($url)."/$1)", $css_code_ff);
1090 }
1091
1092 # fix url paths css_code
1093 if(!empty($url)) {
1094 $matches = array(); preg_match_all("/url\(\s*['\"]?(?!data:)(?!http)(?![\/'\"])(.+?)['\"]?\s*\)/ui", $css_code, $matches);
1095 foreach($matches[1] as $a) { $b = trim($a); if($b != $a) { $css_code = str_replace($a, $b, $css_code); } }
1096 $css_code = preg_replace("/url\(\s*['\"]?(?!data:)(?!http)(?![\/'\"#])(.+?)['\"]?\s*\)/ui", "url(".dirname($url)."/$1)", $css_code);
1097 }
1098
979 # relative paths 1099 # relative paths
980 $css_code_ff = str_replace('https://'.$fvm_urls['wp_domain'], '', $css_code_ff); 1100 $css_code_ff = str_replace('https://'.$fvm_urls['wp_domain'], '', $css_code_ff);
981 $css_code_ff = str_replace('http://'.$fvm_urls['wp_domain'], '', $css_code_ff); 1101 $css_code_ff = str_replace('http://'.$fvm_urls['wp_domain'], '', $css_code_ff);
...@@ -999,7 +1119,7 @@ function fvm_process_cdn($html) { ...@@ -999,7 +1119,7 @@ function fvm_process_cdn($html) {
999 # html must be an object 1119 # html must be an object
1000 if (!is_object($html)) { 1120 if (!is_object($html)) {
1001 $nobj = 1; 1121 $nobj = 1;
1002 $html = str_get_html($html, true, true, 'UTF-8', false, PHP_EOL, ' '); 1122 $html = fvm_str_get_html($html, true, true, 'UTF-8', false, PHP_EOL, ' ');
1003 } 1123 }
1004 1124
1005 # default integration 1125 # default integration
...@@ -1653,32 +1773,9 @@ function fvm_can_process_common() { ...@@ -1653,32 +1773,9 @@ function fvm_can_process_common() {
1653 return true; 1773 return true;
1654 } 1774 }
1655 1775
1656 # check if the user is logged in, and if the user role allows optimization
1657 function fvm_user_role_processing_allowed($group) {
1658 if(function_exists('is_user_logged_in') && function_exists('wp_get_current_user')) {
1659 if(is_user_logged_in()) {
1660
1661 # get user roles
1662 global $fvm_settings;
1663 $user = wp_get_current_user();
1664 $roles = (array) $user->roles;
1665 foreach($roles as $role) {
1666 if(isset($fvm_settings['minify'][$role]) && $fvm_settings['minify'][$role] == true) {
1667 return true;
1668 }
1669 }
1670
1671 # disable for other logged in users by default
1672 return false;
1673 }
1674 }
1675
1676 # allow by default
1677 return true;
1678 }
1679 1776
1680 # check if we can process the page, minimum filters 1777 # check if we can process the page, minimum filters
1681 function fvm_can_process_query_string($loc) { 1778 function fvm_can_process_query_string() {
1682 1779
1683 # host and uri path 1780 # host and uri path
1684 $host = fvm_get_domain(); 1781 $host = fvm_get_domain();
...@@ -1693,11 +1790,17 @@ function fvm_can_process_query_string($loc) { ...@@ -1693,11 +1790,17 @@ function fvm_can_process_query_string($loc) {
1693 # check 1790 # check
1694 $qsarr = array(); parse_str($parse["query"], $qsarr); 1791 $qsarr = array(); parse_str($parse["query"], $qsarr);
1695 1792
1696 # allowed queries by default 1793 # remove allowed query strings from the list of detected queries
1697 if(isset($qsarr['s'])) { unset($qsarr['s']); } # search 1794 if(isset($fvm_settings['settings']['qs']) && !empty($fvm_settings['settings']['qs'])) {
1698 if(isset($qsarr['lang'])) { unset($qsarr['lang']); } # wpml 1795 $arr = fvm_string_toarray($fvm_settings['settings']['qs']);
1699 1796 if(is_array($arr) && count($arr) > 0) {
1700 # if there are other queries left, bypass cache 1797 foreach ($arr as $a) {
1798 if(isset($qsarr[$e])) { unset($qsarr[$e]); }
1799 }
1800 }
1801 }
1802
1803 # if there are other queries left, bypass processing
1701 if(count($qsarr) > 0) { 1804 if(count($qsarr) > 0) {
1702 return false; 1805 return false;
1703 } 1806 }
...@@ -1707,6 +1810,29 @@ function fvm_can_process_query_string($loc) { ...@@ -1707,6 +1810,29 @@ function fvm_can_process_query_string($loc) {
1707 return true; 1810 return true;
1708 } 1811 }
1709 1812
1813 # check if the user is logged in, and if the user role allows optimization
1814 function fvm_user_role_processing_allowed($group) {
1815 if(function_exists('is_user_logged_in') && function_exists('wp_get_current_user')) {
1816 if(is_user_logged_in()) {
1817
1818 # get user roles
1819 global $fvm_settings;
1820 $user = wp_get_current_user();
1821 $roles = (array) $user->roles;
1822 foreach($roles as $role) {
1823 if(isset($fvm_settings['minify'][$role]) && $fvm_settings['minify'][$role] == true) {
1824 return true;
1825 }
1826 }
1827
1828 # disable for other logged in users by default
1829 return false;
1830 }
1831 }
1832
1833 # allow by default
1834 return true;
1835 }
1710 1836
1711 1837
1712 # check if page is amp 1838 # check if page is amp
......
...@@ -47,12 +47,13 @@ function fvm_process_page($html) { ...@@ -47,12 +47,13 @@ function fvm_process_page($html) {
47 47
48 # get html into an object 48 # get html into an object
49 # https://simplehtmldom.sourceforge.io/manual.htm 49 # https://simplehtmldom.sourceforge.io/manual.htm
50 $html_object = str_get_html($html, false, true, 'UTF-8', false, PHP_EOL, ' '); 50 $html_object = fvm_str_get_html($html, false, true, 'UTF-8', false, PHP_EOL, ' ');
51 51
52 # return early if html is not an object, or overwrite html into an object for processing 52 # return early if html is not an object, or overwrite html into an object for processing
53 if (!is_object($html_object)) { 53 if (!is_object($html_object)) {
54 return $html . '<!-- simplehtmldom failed to process the html -->'; 54 return $html . '<!-- simplehtmldom failed to process the html -->';
55 } else { 55 } else {
56 $html_src = $html;
56 $html = $html_object; 57 $html = $html_object;
57 } 58 }
58 59
...@@ -66,13 +67,16 @@ function fvm_process_page($html) { ...@@ -66,13 +67,16 @@ function fvm_process_page($html) {
66 $htmljsheader = array(); 67 $htmljsheader = array();
67 $htmljsdefer = array(); 68 $htmljsdefer = array();
68 69
70 # only error possible for now
71 $fvm_error = PHP_EOL . '<!-- ['.date('r').'] FVM has no write access for CSS / JS cache files under '. fvm_get_cache_location()['ch_url'] . ' -->'. PHP_EOL;
72
69 73
70 # collect all link preload headers, skip amp 74 # collect all link preload headers, skip amp
71 if(fvm_is_amp_page() !== true) { 75 if(fvm_is_amp_page() !== true) {
72 76
73 # skip on web stories 77 # skip on web stories
74 if(count($html->find('script[src*=cdn.ampproject.org]')) > 0) { 78 if(count($html->find('script[src*=cdn.ampproject.org]')) > 0) {
75 return $html . '<!-- FVM does not support AMP -->'; 79 return $html_src . DIRECTORY_SEPARATOR . '<!-- FVM ['.date('r').'] does not support AMP -->';
76 } 80 }
77 81
78 # add other preloads 82 # add other preloads
...@@ -188,7 +192,7 @@ function fvm_process_page($html) { ...@@ -188,7 +192,7 @@ function fvm_process_page($html) {
188 192
189 # extract fonts and icons 193 # extract fonts and icons
190 if(isset($fvm_settings['css']['fonts']) && $fvm_settings['css']['fonts'] == true) { 194 if(isset($fvm_settings['css']['fonts']) && $fvm_settings['css']['fonts'] == true) {
191 $extract_fonts_arr = fvm_extract_fonts($css['code']); 195 $extract_fonts_arr = fvm_extract_fonts($css['code'], $href);
192 $css_lowpriority_code.= '/* '.$href.' */'. PHP_EOL . $extract_fonts_arr['fonts']; 196 $css_lowpriority_code.= '/* '.$href.' */'. PHP_EOL . $extract_fonts_arr['fonts'];
193 $css_code = $extract_fonts_arr['code']; 197 $css_code = $extract_fonts_arr['code'];
194 } else { 198 } else {
...@@ -259,7 +263,7 @@ function fvm_process_page($html) { ...@@ -259,7 +263,7 @@ function fvm_process_page($html) {
259 263
260 # extract fonts and icons 264 # extract fonts and icons
261 if(isset($fvm_settings['css']['fonts']) && $fvm_settings['css']['fonts'] == true) { 265 if(isset($fvm_settings['css']['fonts']) && $fvm_settings['css']['fonts'] == true) {
262 $extract_fonts_arr = fvm_extract_fonts($css['code']); 266 $extract_fonts_arr = fvm_extract_fonts($css['code'], $href);
263 $css_lowpriority_code.= '/* '.$href.' */'. PHP_EOL . $extract_fonts_arr['fonts']; 267 $css_lowpriority_code.= '/* '.$href.' */'. PHP_EOL . $extract_fonts_arr['fonts'];
264 $css_code = $extract_fonts_arr['code']; 268 $css_code = $extract_fonts_arr['code'];
265 } else { 269 } else {
...@@ -277,6 +281,9 @@ function fvm_process_page($html) { ...@@ -277,6 +281,9 @@ function fvm_process_page($html) {
277 281
278 # generate url 282 # generate url
279 $ind_css_url = fvm_generate_min_url($href, $css['tkey'], 'css', $css_code); 283 $ind_css_url = fvm_generate_min_url($href, $css['tkey'], 'css', $css_code);
284 if($ind_css_url === false) {
285 return $html_src . $fvm_error;
286 }
280 287
281 # cdn 288 # cdn
282 if(isset($fvm_settings['cdn']['cssok']) && $fvm_settings['cdn']['cssok'] == true) { 289 if(isset($fvm_settings['cdn']['cssok']) && $fvm_settings['cdn']['cssok'] == true) {
...@@ -402,14 +409,17 @@ function fvm_process_page($html) { ...@@ -402,14 +409,17 @@ function fvm_process_page($html) {
402 409
403 # generate url 410 # generate url
404 $css_fonts_url = fvm_generate_min_url('fonts', $tkey, 'css', $css_lowpriority_code); 411 $css_fonts_url = fvm_generate_min_url('fonts', $tkey, 'css', $css_lowpriority_code);
405 412 if($css_fonts_url === false) {
406 # cdn 413 return $html_src . $fvm_error;
407 if(isset($fvm_settings['cdn']['cssok']) && $fvm_settings['cdn']['cssok'] == true) {
408 $css_fonts_url = fvm_rewrite_cdn_url($css_fonts_url);
409 } 414 }
410 415
411 # preload 416 # cdn
412 $htmlcssheader[0] = '<link id="fvm-fonts" rel="stylesheet" href="'.$css_fonts_url.'" media="fonts" onload="if(fvmuag()){this.media=\'all\'}" />'; 417 if(isset($fvm_settings['cdn']['cssok']) && $fvm_settings['cdn']['cssok'] == true) {
418 $css_fonts_url = fvm_rewrite_cdn_url($css_fonts_url);
419 }
420
421 # preload
422 $htmlcssheader[0] = '<link id="fvm-fonts" rel="stylesheet" href="'.$css_fonts_url.'" media="fonts" onload="if(fvmuag()){this.media=\'all\'}" />';
413 423
414 } 424 }
415 # END OPTIMIZED FONT DELIVERY 425 # END OPTIMIZED FONT DELIVERY
...@@ -435,29 +445,32 @@ function fvm_process_page($html) { ...@@ -435,29 +445,32 @@ function fvm_process_page($html) {
435 445
436 # url, preload, add 446 # url, preload, add
437 $merged_css_url = fvm_generate_min_url('combined', $tkey, 'css', $merged_css); 447 $merged_css_url = fvm_generate_min_url('combined', $tkey, 'css', $merged_css);
438 448 if($merged_css_url === false) {
439 # cdn 449 return $html_src . $fvm_error;
440 if(isset($fvm_settings['cdn']['cssok']) && $fvm_settings['cdn']['cssok'] == true) {
441 $merged_css_url = fvm_rewrite_cdn_url($merged_css_url);
442 } 450 }
443
444 # http, html preload + header
445 if($css_method == 'block') {
446 451
447 # add to header 452 # cdn
448 $htmlcssheader[] = '<link rel="stylesheet" href="'.$merged_css_url.'" media="'.$mediatype.'" />'; 453 if(isset($fvm_settings['cdn']['cssok']) && $fvm_settings['cdn']['cssok'] == true) {
449 454 $merged_css_url = fvm_rewrite_cdn_url($merged_css_url);
450 # http and html preload for render blocking css
451 if(!isset($fvm_settings['css']['nopreload']) || (isset($fvm_settings['css']['nopreload']) && $fvm_settings['css']['nopreload'] != true)) {
452 $htmlpreloads[] = '<link rel="preload" href="'.$merged_css_url.'" as="style" media="'.$mediatype.'" />';
453 } 455 }
454 456
455 } else { 457 # http, html preload + header
458 if($css_method == 'block') {
459
460 # add to header
461 $htmlcssheader[] = '<link rel="stylesheet" href="'.$merged_css_url.'" media="'.$mediatype.'" />';
462
463 # http and html preload for render blocking css
464 if(!isset($fvm_settings['css']['nopreload']) || (isset($fvm_settings['css']['nopreload']) && $fvm_settings['css']['nopreload'] != true)) {
465 $htmlpreloads[] = '<link rel="preload" href="'.$merged_css_url.'" as="style" media="'.$mediatype.'" />';
466 }
467
468 } else {
469
470 # async
471 $htmlcssheader[] = '<link rel="preload" as="style" href="'.$merged_css_url.'" media="'.$mediatype.'" onload="this.rel=\'stylesheet\'" />';
456 472
457 # async 473 }
458 $htmlcssheader[] = '<link rel="preload" as="style" href="'.$merged_css_url.'" media="'.$mediatype.'" onload="this.rel=\'stylesheet\'" />';
459
460 }
461 474
462 } 475 }
463 } 476 }
...@@ -708,6 +721,9 @@ function fvm_process_page($html) { ...@@ -708,6 +721,9 @@ function fvm_process_page($html) {
708 721
709 # generate url 722 # generate url
710 $ind_js_url = fvm_generate_min_url($tag->src, $js['tkey'], 'js', $js['code']); 723 $ind_js_url = fvm_generate_min_url($tag->src, $js['tkey'], 'js', $js['code']);
724 if($ind_js_url === false) {
725 return $html_src . $fvm_error;
726 }
711 727
712 # cdn 728 # cdn
713 if(isset($fvm_settings['cdn']['jsok']) && $fvm_settings['cdn']['jsok'] == true) { 729 if(isset($fvm_settings['cdn']['jsok']) && $fvm_settings['cdn']['jsok'] == true) {
...@@ -759,6 +775,9 @@ function fvm_process_page($html) { ...@@ -759,6 +775,9 @@ function fvm_process_page($html) {
759 775
760 # generate url 776 # generate url
761 $ind_js_url = fvm_generate_min_url($tag->src, $js['tkey'], 'js', $js['code']); 777 $ind_js_url = fvm_generate_min_url($tag->src, $js['tkey'], 'js', $js['code']);
778 if($ind_js_url === false) {
779 return $html_src . $fvm_error;
780 }
762 781
763 # cdn 782 # cdn
764 if(isset($fvm_settings['cdn']['jsok']) && $fvm_settings['cdn']['jsok'] == true) { 783 if(isset($fvm_settings['cdn']['jsok']) && $fvm_settings['cdn']['jsok'] == true) {
...@@ -885,20 +904,23 @@ function fvm_process_page($html) { ...@@ -885,20 +904,23 @@ function fvm_process_page($html) {
885 904
886 # generate url 905 # generate url
887 $merged_js_url = fvm_generate_min_url('combined', $tkey, 'js', $merged_js); 906 $merged_js_url = fvm_generate_min_url('combined', $tkey, 'js', $merged_js);
888 907 if($merged_js_url === false) {
889 # cdn 908 return $html_src . $fvm_error;
890 if(isset($fvm_settings['cdn']['jsok']) && $fvm_settings['cdn']['jsok'] == true) {
891 $merged_js_url = fvm_rewrite_cdn_url($merged_js_url);
892 }
893
894 # http and html preload for render blocking scripts
895 if(!isset($fvm_settings['js']['nopreload']) || (isset($fvm_settings['js']['nopreload']) && $fvm_settings['js']['nopreload'] != true)) {
896 $htmlpreloads[] = '<link rel="preload" href="'.$merged_js_url.'" as="script" />';
897 } 909 }
898 910
899 # add to header 911 # cdn
900 $htmljsheader[] = "<script data-cfasync='false' src='".$merged_js_url."'></script>"; 912 if(isset($fvm_settings['cdn']['jsok']) && $fvm_settings['cdn']['jsok'] == true) {
901 913 $merged_js_url = fvm_rewrite_cdn_url($merged_js_url);
914 }
915
916 # http and html preload for render blocking scripts
917 if(!isset($fvm_settings['js']['nopreload']) || (isset($fvm_settings['js']['nopreload']) && $fvm_settings['js']['nopreload'] != true)) {
918 $htmlpreloads[] = '<link rel="preload" href="'.$merged_js_url.'" as="script" />';
919 }
920
921 # add to header
922 $htmljsheader[] = "<script data-cfasync='false' src='".$merged_js_url."'></script>";
923
902 } 924 }
903 925
904 # deferred scripts 926 # deferred scripts
...@@ -910,15 +932,18 @@ function fvm_process_page($html) { ...@@ -910,15 +932,18 @@ function fvm_process_page($html) {
910 932
911 # generate url 933 # generate url
912 $merged_js_url = fvm_generate_min_url('combined', $tkey, 'js', $merged_js); 934 $merged_js_url = fvm_generate_min_url('combined', $tkey, 'js', $merged_js);
913 935 if($merged_js_url === false) {
914 # cdn 936 return $html_src . $fvm_error;
915 if(isset($fvm_settings['cdn']['jsok']) && $fvm_settings['cdn']['jsok'] == true) {
916 $merged_js_url = fvm_rewrite_cdn_url($merged_js_url);
917 } 937 }
918 938
919 # header, no preload for deferred files 939 # cdn
920 $htmljsheader[] = "<script defer='defer' src='".$merged_js_url."'></script>"; 940 if(isset($fvm_settings['cdn']['jsok']) && $fvm_settings['cdn']['jsok'] == true) {
921 941 $merged_js_url = fvm_rewrite_cdn_url($merged_js_url);
942 }
943
944 # header, no preload for deferred files
945 $htmljsheader[] = "<script defer='defer' src='".$merged_js_url."'></script>";
946
922 } 947 }
923 948
924 } 949 }
......
...@@ -286,6 +286,21 @@ ...@@ -286,6 +286,21 @@
286 </div> 286 </div>
287 287
288 <div style="height: 20px;"></div> 288 <div style="height: 20px;"></div>
289 <h2 class="title">Query String Settings</h2>
290
291 <div class="accordion">
292 <h3>Allowed Query Strings</h3>
293 <div>
294 <p><strong>Notes:</strong></p>
295 <p>This allows processing of CSS, HTML and JS when the url contains certain query strings, but note that if there are other query strings found on the same url not on the list of allowed query strings, it will still not process the url.</p>
296 <p><strong>Example Settings:</strong></p>
297 <p class="fvm-code-full">
298 utm_source<br />utm_campaign<br />utm_medium<br />utm_expid<br />utm_term<br />utm_content<br />fb_action_ids<br />fb_action_types<br />fb_source<br />fbclid<br />_ga<br />gclid<br />age-verified<br />usqp<br />cn-reloaded<br />lang<br />s<br />permalink_name<br />lp-variation-id<br />author<br />author_name<br />cat<br />category_name<br />order<br />orderby<br />p<br />page_id<br />page<br />paged<br />post_type<br />posts<br />s<br />search<br />taxonomy<br />tag<br />tag_id<br />term
299 </p>
300 </div>
301 </div>
302
303 <div style="height: 20px;"></div>
289 <h2 class="title">User Settings</h2> 304 <h2 class="title">User Settings</h2>
290 305
291 <div class="accordion"> 306 <div class="accordion">
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
22 <fieldset> 22 <fieldset>
23 <label for="fvm_settings_cache_min_instant_purge"> 23 <label for="fvm_settings_cache_min_instant_purge">
24 <input name="fvm_settings[cache][min_instant_purge]" type="checkbox" id="fvm_settings_cache_min_instant_purge" value="1" <?php echo fvm_get_settings_checkbox(fvm_get_settings_value($fvm_settings, 'cache', 'min_instant_purge')); ?>> 24 <input name="fvm_settings[cache][min_instant_purge]" type="checkbox" id="fvm_settings_cache_min_instant_purge" value="1" <?php echo fvm_get_settings_checkbox(fvm_get_settings_value($fvm_settings, 'cache', 'min_instant_purge')); ?>>
25 <?php _e( 'Purge Minified CSS/JS files instantly', 'fast-velocity-minify' ); ?> <span class="note-info">[ <?php _e( 'Cache files are only deleted if older than 24h by default, for compatibility with certain hosting providers.', 'fast-velocity-minify' ); ?> ]</span></label> 25 <?php _e( 'Purge Minified CSS/JS files instantly', 'fast-velocity-minify' ); ?> <span class="note-info">[ <?php _e( 'CSS & JS cache files are preserved for 7 days by default, for better compatibility with certain hosting providers.', 'fast-velocity-minify' ); ?> ]</span></label>
26 <br /> 26 <br />
27 27
28 </fieldset></td> 28 </fieldset></td>
...@@ -160,7 +160,7 @@ ...@@ -160,7 +160,7 @@
160 <td><fieldset> 160 <td><fieldset>
161 <label for="fvm_settings_css_remove"><span class="fvm-bold-green fvm-rowintro"><?php _e( 'Remove the following CSS files', 'fast-velocity-minify' ); ?></span></label> 161 <label for="fvm_settings_css_remove"><span class="fvm-bold-green fvm-rowintro"><?php _e( 'Remove the following CSS files', 'fast-velocity-minify' ); ?></span></label>
162 <p><textarea name="fvm_settings[css][remove]" rows="7" cols="50" id="fvm_settings_css_remove" class="large-text code" placeholder="ex: fonts.googleapis.com"><?php echo fvm_get_settings_value($fvm_settings, 'css', 'remove'); ?></textarea></p> 162 <p><textarea name="fvm_settings[css][remove]" rows="7" cols="50" id="fvm_settings_css_remove" class="large-text code" placeholder="ex: fonts.googleapis.com"><?php echo fvm_get_settings_value($fvm_settings, 'css', 'remove'); ?></textarea></p>
163 <p class="description">[ <?php _e( 'This will allow you to remove unwanted CSS files by URL path from the frontend', 'fast-velocity-minify' ); ?> ]</p> 163 <p class="description">[ <?php _e( 'This will allow you to remove unwanted CSS files by URI path from the frontend', 'fast-velocity-minify' ); ?> ]</p>
164 <p class="description">[ <?php _e( 'Will match using <code>PHP stripos</code> against the <code>href attribute</code> on the <code>link tag</code>', 'fast-velocity-minify' ); ?> ]</p> 164 <p class="description">[ <?php _e( 'Will match using <code>PHP stripos</code> against the <code>href attribute</code> on the <code>link tag</code>', 'fast-velocity-minify' ); ?> ]</p>
165 </fieldset></td> 165 </fieldset></td>
166 </tr> 166 </tr>
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
170 <td><fieldset> 170 <td><fieldset>
171 <label for="fvm_settings_css_async"><span class="fvm-bold-green fvm-rowintro"><?php _e( 'Async the following CSS files', 'fast-velocity-minify' ); ?></span></label> 171 <label for="fvm_settings_css_async"><span class="fvm-bold-green fvm-rowintro"><?php _e( 'Async the following CSS files', 'fast-velocity-minify' ); ?></span></label>
172 <p><textarea name="fvm_settings[css][async]" rows="7" cols="50" id="fvm_settings_css_async" class="large-text code" placeholder="ex: /plugins/something/assets/low-priority.css"><?php echo fvm_get_settings_value($fvm_settings, 'css', 'async'); ?></textarea></p> 172 <p><textarea name="fvm_settings[css][async]" rows="7" cols="50" id="fvm_settings_css_async" class="large-text code" placeholder="ex: /plugins/something/assets/low-priority.css"><?php echo fvm_get_settings_value($fvm_settings, 'css', 'async'); ?></textarea></p>
173 <p class="description">[ <?php _e( 'This will allow you to remove unwanted CSS files by URL path from the frontend', 'fast-velocity-minify' ); ?> ]</p> 173 <p class="description">[ <?php _e( 'This will allow you to Async CSS files by URI path from the frontend', 'fast-velocity-minify' ); ?> ]</p>
174 <p class="description">[ <?php _e( 'Will match using <code>PHP stripos</code> against the <code>href attribute</code> on the <code>link tag</code>', 'fast-velocity-minify' ); ?> ]</p> 174 <p class="description">[ <?php _e( 'Will match using <code>PHP stripos</code> against the <code>href attribute</code> on the <code>link tag</code>', 'fast-velocity-minify' ); ?> ]</p>
175 </fieldset></td> 175 </fieldset></td>
176 </tr> 176 </tr>
...@@ -364,6 +364,22 @@ www.googletagmanager.com/gtm.js"><?php echo fvm_get_settings_value($fvm_settings ...@@ -364,6 +364,22 @@ www.googletagmanager.com/gtm.js"><?php echo fvm_get_settings_value($fvm_settings
364 364
365 365
366 <div style="height: 60px;"></div> 366 <div style="height: 60px;"></div>
367 <h2 class="title"><?php _e( 'Query Strings', 'fast-velocity-minify' ); ?></h2>
368 <h3 class="fvm-bold-green"><?php _e( 'Allow processing of CSS, JS & HTML on specific query strings', 'fast-velocity-minify' ); ?></h3>
369 <table class="form-table fvm-settings">
370 <tbody>
371 <tr>
372 <th scope="row"><?php _e( 'Allowed Query Strings', 'fast-velocity-minify' ); ?></th>
373 <td><fieldset>
374 <label for="fvm_settings_settings_qs"><span class="fvm-bold-green fvm-rowintro"><?php _e( 'One query string key per line', 'fast-velocity-minify' ); ?></span></label>
375 <p><textarea name="fvm_settings[settings][qs]" rows="7" cols="50" id="fvm_settings_settings_qs" class="large-text code" placeholder="--- check the help section for suggestions ---"><?php echo fvm_get_settings_value($fvm_settings, 'settings', 'qs'); ?></textarea></p>
376 <p class="description">[ <?php _e( 'Additional query strings, keys only', 'fast-velocity-minify' ); ?> ]</p>
377 </fieldset></td>
378 </tr>
379 </tbody></table>
380
381
382 <div style="height: 60px;"></div>
367 <h2 class="title"><?php _e( 'User Settings', 'fast-velocity-minify' ); ?></h2> 383 <h2 class="title"><?php _e( 'User Settings', 'fast-velocity-minify' ); ?></h2>
368 <h3 class="fvm-bold-green"><?php _e( 'For compatibility reasons, only anonymous users should be optimized by default.', 'fast-velocity-minify' ); ?></h3> 384 <h3 class="fvm-bold-green"><?php _e( 'For compatibility reasons, only anonymous users should be optimized by default.', 'fast-velocity-minify' ); ?></h3>
369 <table class="form-table fvm-settings"> 385 <table class="form-table fvm-settings">
......
...@@ -563,47 +563,7 @@ class CSS extends Minify ...@@ -563,47 +563,7 @@ class CSS extends Minify
563 */ 563 */
564 protected function shortenZeroes($content) 564 protected function shortenZeroes($content)
565 { 565 {
566 // we don't want to strip units in `calc()` expressions: 566 // removed
567 // `5px - 0px` is valid, but `5px - 0` is not
568 // `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
569 // `10 * 0` is invalid
570 // we've extracted calcs earlier, so we don't need to worry about this
571
572 // reusable bits of code throughout these regexes:
573 // before & after are used to make sure we don't match lose unintended
574 // 0-like values (e.g. in #000, or in http://url/1.0)
575 // units can be stripped from 0 values, or used to recognize non 0
576 // values (where wa may be able to strip a .0 suffix)
577 $before = '(?<=[:(, ])';
578 $after = '(?=[ ,);}])';
579 $units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)';
580
581 // strip units after zeroes (0px -> 0)
582 // NOTE: it should be safe to remove all units for a 0 value, but in
583 // practice, Webkit (especially Safari) seems to stumble over at least
584 // 0%, potentially other units as well. Only stripping 'px' for now.
585 // @see https://github.com/matthiasmullie/minify/issues/60
586 $content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);
587
588 // strip 0-digits (.0 -> 0)
589 $content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);
590 // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
591 $content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);
592 // strip trailing 0: 50.00 -> 50, 50.00px -> 50px
593 $content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);
594 // strip leading 0: 0.1 -> .1, 01.1 -> 1.1
595 $content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);
596
597 // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
598 $content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
599
600 // IE doesn't seem to understand a unitless flex-basis value (correct -
601 // it goes against the spec), so let's add it in again (make it `%`,
602 // which is only 1 char: 0%, 0px, 0 anything, it's all just the same)
603 // @see https://developer.mozilla.org/nl/docs/Web/CSS/flex
604 $content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content);
605 $content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
606
607 return $content; 567 return $content;
608 } 568 }
609 569
......
...@@ -26,32 +26,32 @@ if (!defined('ABSPATH')){ exit(); } ...@@ -26,32 +26,32 @@ if (!defined('ABSPATH')){ exit(); }
26 26
27 # mod 27 # mod
28 defined('FVM_MAX_FILE_SIZE') || define('FVM_MAX_FILE_SIZE', 2000000); # Process HTML up to 2 Mb 28 defined('FVM_MAX_FILE_SIZE') || define('FVM_MAX_FILE_SIZE', 2000000); # Process HTML up to 2 Mb
29 defined('DEFAULT_TARGET_CHARSET') || define('DEFAULT_TARGET_CHARSET', 'UTF-8'); 29 defined('FVMDEFAULT_TARGET_CHARSET') || define('FVMDEFAULT_TARGET_CHARSET', 'UTF-8');
30 defined('DEFAULT_BR_TEXT') || define('DEFAULT_BR_TEXT', "\r\n"); 30 defined('FVMDEFAULT_BR_TEXT') || define('FVMDEFAULT_BR_TEXT', "\r\n");
31 defined('DEFAULT_SPAN_TEXT') || define('DEFAULT_SPAN_TEXT', ' '); 31 defined('FVMDEFAULT_SPAN_TEXT') || define('FVMDEFAULT_SPAN_TEXT', ' ');
32 32
33 # other 33 # other
34 define('HDOM_TYPE_ELEMENT', 1); 34 define('FVMHDOM_TYPE_ELEMENT', 1);
35 define('HDOM_TYPE_COMMENT', 2); 35 define('FVMHDOM_TYPE_COMMENT', 2);
36 define('HDOM_TYPE_TEXT', 3); 36 define('FVMHDOM_TYPE_TEXT', 3);
37 define('HDOM_TYPE_ENDTAG', 4); 37 define('FVMHDOM_TYPE_ENDTAG', 4);
38 define('HDOM_TYPE_ROOT', 5); 38 define('FVMHDOM_TYPE_ROOT', 5);
39 define('HDOM_TYPE_UNKNOWN', 6); 39 define('FVMHDOM_TYPE_UNKNOWN', 6);
40 define('HDOM_QUOTE_DOUBLE', 0); 40 define('FVMHDOM_QUOTE_DOUBLE', 0);
41 define('HDOM_QUOTE_SINGLE', 1); 41 define('FVMHDOM_QUOTE_SINGLE', 1);
42 define('HDOM_QUOTE_NO', 3); 42 define('FVMHDOM_QUOTE_NO', 3);
43 define('HDOM_INFO_BEGIN', 0); 43 define('FVMHDOM_INFO_BEGIN', 0);
44 define('HDOM_INFO_END', 1); 44 define('FVMHDOM_INFO_END', 1);
45 define('HDOM_INFO_QUOTE', 2); 45 define('FVMHDOM_INFO_QUOTE', 2);
46 define('HDOM_INFO_SPACE', 3); 46 define('FVMHDOM_INFO_SPACE', 3);
47 define('HDOM_INFO_TEXT', 4); 47 define('FVMHDOM_INFO_TEXT', 4);
48 define('HDOM_INFO_INNER', 5); 48 define('FVMHDOM_INFO_INNER', 5);
49 define('HDOM_INFO_OUTER', 6); 49 define('FVMHDOM_INFO_OUTER', 6);
50 define('HDOM_INFO_ENDSPACE', 7); 50 define('FVMHDOM_INFO_ENDSPACE', 7);
51 define('HDOM_SMARTY_AS_TEXT', 1); 51 define('FVMHDOM_SMARTY_AS_TEXT', 1);
52 52
53 # functions 53 # functions
54 function file_get_html( 54 function fvm_file_get_html(
55 $url, 55 $url,
56 $use_include_path = false, 56 $use_include_path = false,
57 $context = null, 57 $context = null,
...@@ -59,14 +59,14 @@ function file_get_html( ...@@ -59,14 +59,14 @@ function file_get_html(
59 $maxLen = -1, 59 $maxLen = -1,
60 $lowercase = true, 60 $lowercase = true,
61 $forceTagsClosed = true, 61 $forceTagsClosed = true,
62 $target_charset = DEFAULT_TARGET_CHARSET, 62 $target_charset = FVMDEFAULT_TARGET_CHARSET,
63 $stripRN = true, 63 $stripRN = true,
64 $defaultBRText = DEFAULT_BR_TEXT, 64 $defaultBRText = FVMDEFAULT_BR_TEXT,
65 $defaultSpanText = DEFAULT_SPAN_TEXT) 65 $defaultSpanText = FVMDEFAULT_SPAN_TEXT)
66 { 66 {
67 if($maxLen <= 0) { $maxLen = FVM_MAX_FILE_SIZE; } 67 if($maxLen <= 0) { $maxLen = FVM_MAX_FILE_SIZE; }
68 68
69 $dom = new simple_html_dom( 69 $dom = new fvm_simple_html_dom(
70 null, 70 null,
71 $lowercase, 71 $lowercase,
72 $forceTagsClosed, 72 $forceTagsClosed,
...@@ -97,16 +97,16 @@ function file_get_html( ...@@ -97,16 +97,16 @@ function file_get_html(
97 return $dom->load($contents, $lowercase, $stripRN); 97 return $dom->load($contents, $lowercase, $stripRN);
98 } 98 }
99 99
100 function str_get_html( 100 function fvm_str_get_html(
101 $str, 101 $str,
102 $lowercase = true, 102 $lowercase = true,
103 $forceTagsClosed = true, 103 $forceTagsClosed = true,
104 $target_charset = DEFAULT_TARGET_CHARSET, 104 $target_charset = FVMDEFAULT_TARGET_CHARSET,
105 $stripRN = true, 105 $stripRN = true,
106 $defaultBRText = DEFAULT_BR_TEXT, 106 $defaultBRText = FVMDEFAULT_BR_TEXT,
107 $defaultSpanText = DEFAULT_SPAN_TEXT) 107 $defaultSpanText = FVMDEFAULT_SPAN_TEXT)
108 { 108 {
109 $dom = new simple_html_dom( 109 $dom = new fvm_simple_html_dom(
110 null, 110 null,
111 $lowercase, 111 $lowercase,
112 $forceTagsClosed, 112 $forceTagsClosed,
...@@ -124,14 +124,14 @@ function str_get_html( ...@@ -124,14 +124,14 @@ function str_get_html(
124 return $dom->load($str, $lowercase, $stripRN); 124 return $dom->load($str, $lowercase, $stripRN);
125 } 125 }
126 126
127 function dump_html_tree($node, $show_attr = true, $deep = 0) 127 function fvm_dump_html_tree($node, $show_attr = true, $deep = 0)
128 { 128 {
129 $node->dump($node); 129 $node->dump($node);
130 } 130 }
131 131
132 class simple_html_dom_node 132 class fvm_simple_html_dom_node
133 { 133 {
134 public $nodetype = HDOM_TYPE_TEXT; 134 public $nodetype = FVMHDOM_TYPE_TEXT;
135 public $tag = 'text'; 135 public $tag = 'text';
136 public $attr = array(); 136 public $attr = array();
137 public $children = array(); 137 public $children = array();
...@@ -218,10 +218,10 @@ class simple_html_dom_node ...@@ -218,10 +218,10 @@ class simple_html_dom_node
218 $string .= " text: ({$this->text})"; 218 $string .= " text: ({$this->text})";
219 } 219 }
220 220
221 $string .= ' HDOM_INNER_INFO: '; 221 $string .= ' FVMHDOM_INNER_INFO: ';
222 222
223 if (isset($node->_[HDOM_INFO_INNER])) { 223 if (isset($node->_[FVMHDOM_INFO_INNER])) {
224 $string .= "'" . $node->_[HDOM_INFO_INNER] . "'"; 224 $string .= "'" . $node->_[FVMHDOM_INFO_INNER] . "'";
225 } else { 225 } else {
226 $string .= ' NULL '; 226 $string .= ' NULL ';
227 } 227 }
...@@ -345,12 +345,12 @@ class simple_html_dom_node ...@@ -345,12 +345,12 @@ class simple_html_dom_node
345 345
346 function innertext() 346 function innertext()
347 { 347 {
348 if (isset($this->_[HDOM_INFO_INNER])) { 348 if (isset($this->_[FVMHDOM_INFO_INNER])) {
349 return $this->_[HDOM_INFO_INNER]; 349 return $this->_[FVMHDOM_INFO_INNER];
350 } 350 }
351 351
352 if (isset($this->_[HDOM_INFO_TEXT])) { 352 if (isset($this->_[FVMHDOM_INFO_TEXT])) {
353 return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); 353 return $this->dom->restore_noise($this->_[FVMHDOM_INFO_TEXT]);
354 } 354 }
355 355
356 $ret = ''; 356 $ret = '';
...@@ -387,24 +387,24 @@ class simple_html_dom_node ...@@ -387,24 +387,24 @@ class simple_html_dom_node
387 call_user_func_array($this->dom->callback, array($this)); 387 call_user_func_array($this->dom->callback, array($this));
388 } 388 }
389 389
390 if (isset($this->_[HDOM_INFO_OUTER])) { 390 if (isset($this->_[FVMHDOM_INFO_OUTER])) {
391 return $this->_[HDOM_INFO_OUTER]; 391 return $this->_[FVMHDOM_INFO_OUTER];
392 } 392 }
393 393
394 if (isset($this->_[HDOM_INFO_TEXT])) { 394 if (isset($this->_[FVMHDOM_INFO_TEXT])) {
395 return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); 395 return $this->dom->restore_noise($this->_[FVMHDOM_INFO_TEXT]);
396 } 396 }
397 397
398 $ret = ''; 398 $ret = '';
399 399
400 if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) { 400 if ($this->dom && $this->dom->nodes[$this->_[FVMHDOM_INFO_BEGIN]]) {
401 $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup(); 401 $ret = $this->dom->nodes[$this->_[FVMHDOM_INFO_BEGIN]]->makeup();
402 } 402 }
403 403
404 if (isset($this->_[HDOM_INFO_INNER])) { 404 if (isset($this->_[FVMHDOM_INFO_INNER])) {
405 // todo: <br> should either never have HDOM_INFO_INNER or always 405 // todo: <br> should either never have FVMHDOM_INFO_INNER or always
406 if ($this->tag !== 'br') { 406 if ($this->tag !== 'br') {
407 $ret .= $this->_[HDOM_INFO_INNER]; 407 $ret .= $this->_[FVMHDOM_INFO_INNER];
408 } 408 }
409 } elseif ($this->nodes) { 409 } elseif ($this->nodes) {
410 foreach ($this->nodes as $n) { 410 foreach ($this->nodes as $n) {
...@@ -412,7 +412,7 @@ class simple_html_dom_node ...@@ -412,7 +412,7 @@ class simple_html_dom_node
412 } 412 }
413 } 413 }
414 414
415 if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END] != 0) { 415 if (isset($this->_[FVMHDOM_INFO_END]) && $this->_[FVMHDOM_INFO_END] != 0) {
416 $ret .= '</' . $this->tag . '>'; 416 $ret .= '</' . $this->tag . '>';
417 } 417 }
418 418
...@@ -421,14 +421,14 @@ class simple_html_dom_node ...@@ -421,14 +421,14 @@ class simple_html_dom_node
421 421
422 function text() 422 function text()
423 { 423 {
424 if (isset($this->_[HDOM_INFO_INNER])) { 424 if (isset($this->_[FVMHDOM_INFO_INNER])) {
425 return $this->_[HDOM_INFO_INNER]; 425 return $this->_[FVMHDOM_INFO_INNER];
426 } 426 }
427 427
428 switch ($this->nodetype) { 428 switch ($this->nodetype) {
429 case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); 429 case FVMHDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[FVMHDOM_INFO_TEXT]);
430 case HDOM_TYPE_COMMENT: return ''; 430 case FVMHDOM_TYPE_COMMENT: return '';
431 case HDOM_TYPE_UNKNOWN: return ''; 431 case FVMHDOM_TYPE_UNKNOWN: return '';
432 } 432 }
433 433
434 if (strcasecmp($this->tag, 'script') === 0) { return ''; } 434 if (strcasecmp($this->tag, 'script') === 0) { return ''; }
...@@ -436,7 +436,7 @@ class simple_html_dom_node ...@@ -436,7 +436,7 @@ class simple_html_dom_node
436 436
437 $ret = ''; 437 $ret = '';
438 438
439 // In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed 439 // In rare cases, (always node type 1 or FVMHDOM_TYPE_ELEMENT - observed
440 // for some span tags, and some p tags) $this->nodes is set to NULL. 440 // for some span tags, and some p tags) $this->nodes is set to NULL.
441 // NOTE: This indicates that there is a problem where it's set to NULL 441 // NOTE: This indicates that there is a problem where it's set to NULL
442 // without a clear happening. 442 // without a clear happening.
...@@ -472,8 +472,8 @@ class simple_html_dom_node ...@@ -472,8 +472,8 @@ class simple_html_dom_node
472 function makeup() 472 function makeup()
473 { 473 {
474 // text, comment, unknown 474 // text, comment, unknown
475 if (isset($this->_[HDOM_INFO_TEXT])) { 475 if (isset($this->_[FVMHDOM_INFO_TEXT])) {
476 return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); 476 return $this->dom->restore_noise($this->_[FVMHDOM_INFO_TEXT]);
477 } 477 }
478 478
479 $ret = '<' . $this->tag; 479 $ret = '<' . $this->tag;
...@@ -485,23 +485,23 @@ class simple_html_dom_node ...@@ -485,23 +485,23 @@ class simple_html_dom_node
485 // skip removed attribute 485 // skip removed attribute
486 if ($val === null || $val === false) { continue; } 486 if ($val === null || $val === false) { continue; }
487 487
488 $ret .= $this->_[HDOM_INFO_SPACE][$i][0]; 488 $ret .= $this->_[FVMHDOM_INFO_SPACE][$i][0];
489 489
490 //no value attr: nowrap, checked selected... 490 //no value attr: nowrap, checked selected...
491 if ($val === true) { 491 if ($val === true) {
492 $ret .= $key; 492 $ret .= $key;
493 } else { 493 } else {
494 switch ($this->_[HDOM_INFO_QUOTE][$i]) 494 switch ($this->_[FVMHDOM_INFO_QUOTE][$i])
495 { 495 {
496 case HDOM_QUOTE_DOUBLE: $quote = '"'; break; 496 case FVMHDOM_QUOTE_DOUBLE: $quote = '"'; break;
497 case HDOM_QUOTE_SINGLE: $quote = '\''; break; 497 case FVMHDOM_QUOTE_SINGLE: $quote = '\''; break;
498 default: $quote = ''; 498 default: $quote = '';
499 } 499 }
500 500
501 $ret .= $key 501 $ret .= $key
502 . $this->_[HDOM_INFO_SPACE][$i][1] 502 . $this->_[FVMHDOM_INFO_SPACE][$i][1]
503 . '=' 503 . '='
504 . $this->_[HDOM_INFO_SPACE][$i][2] 504 . $this->_[FVMHDOM_INFO_SPACE][$i][2]
505 . $quote 505 . $quote
506 . $val 506 . $val
507 . $quote; 507 . $quote;
...@@ -509,7 +509,7 @@ class simple_html_dom_node ...@@ -509,7 +509,7 @@ class simple_html_dom_node
509 } 509 }
510 510
511 $ret = $this->dom->restore_noise($ret); 511 $ret = $this->dom->restore_noise($ret);
512 return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; 512 return $ret . $this->_[FVMHDOM_INFO_ENDSPACE] . '>';
513 } 513 }
514 514
515 function find($selector, $idx = null, $lowercase = false) 515 function find($selector, $idx = null, $lowercase = false)
...@@ -524,9 +524,9 @@ class simple_html_dom_node ...@@ -524,9 +524,9 @@ class simple_html_dom_node
524 // code tracker id 2788009 524 // code tracker id 2788009
525 // used to be: if (($levle=count($selectors[0]))===0) return array(); 525 // used to be: if (($levle=count($selectors[0]))===0) return array();
526 if (($levle = count($selectors[$c])) === 0) { return array(); } 526 if (($levle = count($selectors[$c])) === 0) { return array(); }
527 if (!isset($this->_[HDOM_INFO_BEGIN])) { return array(); } 527 if (!isset($this->_[FVMHDOM_INFO_BEGIN])) { return array(); }
528 528
529 $head = array($this->_[HDOM_INFO_BEGIN] => 1); 529 $head = array($this->_[FVMHDOM_INFO_BEGIN] => 1);
530 $cmd = ' '; // Combinator 530 $cmd = ' '; // Combinator
531 531
532 // handle descendant selectors, no recursive! 532 // handle descendant selectors, no recursive!
...@@ -575,18 +575,18 @@ class simple_html_dom_node ...@@ -575,18 +575,18 @@ class simple_html_dom_node
575 if ($parent_cmd === ' ') { // Descendant Combinator 575 if ($parent_cmd === ' ') { // Descendant Combinator
576 // Find parent closing tag if the current element doesn't have a closing 576 // Find parent closing tag if the current element doesn't have a closing
577 // tag (i.e. void element) 577 // tag (i.e. void element)
578 $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0; 578 $end = (!empty($this->_[FVMHDOM_INFO_END])) ? $this->_[FVMHDOM_INFO_END] : 0;
579 if ($end == 0) { 579 if ($end == 0) {
580 $parent = $this->parent; 580 $parent = $this->parent;
581 while (!isset($parent->_[HDOM_INFO_END]) && $parent !== null) { 581 while (!isset($parent->_[FVMHDOM_INFO_END]) && $parent !== null) {
582 $end -= 1; 582 $end -= 1;
583 $parent = $parent->parent; 583 $parent = $parent->parent;
584 } 584 }
585 $end += $parent->_[HDOM_INFO_END]; 585 $end += $parent->_[FVMHDOM_INFO_END];
586 } 586 }
587 587
588 // Get list of target nodes 588 // Get list of target nodes
589 $nodes_start = $this->_[HDOM_INFO_BEGIN] + 1; 589 $nodes_start = $this->_[FVMHDOM_INFO_BEGIN] + 1;
590 $nodes_count = $end - $nodes_start; 590 $nodes_count = $end - $nodes_start;
591 $nodes = array_slice($this->dom->nodes, $nodes_start, $nodes_count, true); 591 $nodes = array_slice($this->dom->nodes, $nodes_start, $nodes_count, true);
592 } elseif ($parent_cmd === '>') { // Child Combinator 592 } elseif ($parent_cmd === '>') { // Child Combinator
...@@ -777,7 +777,7 @@ class simple_html_dom_node ...@@ -777,7 +777,7 @@ class simple_html_dom_node
777 } 777 }
778 778
779 // Found a match. Add to list and clear node 779 // Found a match. Add to list and clear node
780 if ($pass) $ret[$node->_[HDOM_INFO_BEGIN]] = 1; 780 if ($pass) $ret[$node->_[FVMHDOM_INFO_BEGIN]] = 1;
781 unset($node); 781 unset($node);
782 } 782 }
783 // It's passed by reference so this is actually what this function returns. 783 // It's passed by reference so this is actually what this function returns.
...@@ -990,17 +990,17 @@ class simple_html_dom_node ...@@ -990,17 +990,17 @@ class simple_html_dom_node
990 if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } 990 if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
991 991
992 switch ($name) { 992 switch ($name) {
993 case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; 993 case 'outertext': return $this->_[FVMHDOM_INFO_OUTER] = $value;
994 case 'innertext': 994 case 'innertext':
995 if (isset($this->_[HDOM_INFO_TEXT])) { 995 if (isset($this->_[FVMHDOM_INFO_TEXT])) {
996 return $this->_[HDOM_INFO_TEXT] = $value; 996 return $this->_[FVMHDOM_INFO_TEXT] = $value;
997 } 997 }
998 return $this->_[HDOM_INFO_INNER] = $value; 998 return $this->_[FVMHDOM_INFO_INNER] = $value;
999 } 999 }
1000 1000
1001 if (!isset($this->attr[$name])) { 1001 if (!isset($this->attr[$name])) {
1002 $this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); 1002 $this->_[FVMHDOM_INFO_SPACE][] = array(' ', '', '');
1003 $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; 1003 $this->_[FVMHDOM_INFO_QUOTE][] = FVMHDOM_QUOTE_DOUBLE;
1004 } 1004 }
1005 1005
1006 $this->attr[$name] = $value; 1006 $this->attr[$name] = $value;
...@@ -1391,7 +1391,7 @@ class simple_html_dom_node ...@@ -1391,7 +1391,7 @@ class simple_html_dom_node
1391 1391
1392 } 1392 }
1393 1393
1394 class simple_html_dom 1394 class fvm_simple_html_dom
1395 { 1395 {
1396 public $root = null; 1396 public $root = null;
1397 public $nodes = array(); 1397 public $nodes = array();
...@@ -1467,10 +1467,10 @@ class simple_html_dom ...@@ -1467,10 +1467,10 @@ class simple_html_dom
1467 $str = null, 1467 $str = null,
1468 $lowercase = true, 1468 $lowercase = true,
1469 $forceTagsClosed = true, 1469 $forceTagsClosed = true,
1470 $target_charset = DEFAULT_TARGET_CHARSET, 1470 $target_charset = FVMDEFAULT_TARGET_CHARSET,
1471 $stripRN = true, 1471 $stripRN = true,
1472 $defaultBRText = DEFAULT_BR_TEXT, 1472 $defaultBRText = FVMDEFAULT_BR_TEXT,
1473 $defaultSpanText = DEFAULT_SPAN_TEXT, 1473 $defaultSpanText = FVMDEFAULT_SPAN_TEXT,
1474 $options = 0) 1474 $options = 0)
1475 { 1475 {
1476 if ($str) { 1476 if ($str) {
...@@ -1505,8 +1505,8 @@ class simple_html_dom ...@@ -1505,8 +1505,8 @@ class simple_html_dom
1505 $str, 1505 $str,
1506 $lowercase = true, 1506 $lowercase = true,
1507 $stripRN = true, 1507 $stripRN = true,
1508 $defaultBRText = DEFAULT_BR_TEXT, 1508 $defaultBRText = FVMDEFAULT_BR_TEXT,
1509 $defaultSpanText = DEFAULT_SPAN_TEXT, 1509 $defaultSpanText = FVMDEFAULT_SPAN_TEXT,
1510 $options = 0) 1510 $options = 0)
1511 { 1511 {
1512 global $debug_object; 1512 global $debug_object;
...@@ -1541,14 +1541,14 @@ class simple_html_dom ...@@ -1541,14 +1541,14 @@ class simple_html_dom
1541 // strip out server side scripts 1541 // strip out server side scripts
1542 $this->remove_noise("'(<\?)(.*?)(\?>)'s", true); 1542 $this->remove_noise("'(<\?)(.*?)(\?>)'s", true);
1543 1543
1544 if($options & HDOM_SMARTY_AS_TEXT) { // Strip Smarty scripts 1544 if($options & FVMHDOM_SMARTY_AS_TEXT) { // Strip Smarty scripts
1545 $this->remove_noise("'(\{\w)(.*?)(\})'s", true); 1545 $this->remove_noise("'(\{\w)(.*?)(\})'s", true);
1546 } 1546 }
1547 1547
1548 // parsing 1548 // parsing
1549 $this->parse(); 1549 $this->parse();
1550 // end 1550 // end
1551 $this->root->_[HDOM_INFO_END] = $this->cursor; 1551 $this->root->_[FVMHDOM_INFO_END] = $this->cursor;
1552 $this->parse_charset(); 1552 $this->parse_charset();
1553 1553
1554 // make load function chainable 1554 // make load function chainable
...@@ -1628,8 +1628,8 @@ class simple_html_dom ...@@ -1628,8 +1628,8 @@ class simple_html_dom
1628 1628
1629 protected function prepare( 1629 protected function prepare(
1630 $str, $lowercase = true, 1630 $str, $lowercase = true,
1631 $defaultBRText = DEFAULT_BR_TEXT, 1631 $defaultBRText = FVMDEFAULT_BR_TEXT,
1632 $defaultSpanText = DEFAULT_SPAN_TEXT) 1632 $defaultSpanText = FVMDEFAULT_SPAN_TEXT)
1633 { 1633 {
1634 $this->clear(); 1634 $this->clear();
1635 1635
...@@ -1643,10 +1643,10 @@ class simple_html_dom ...@@ -1643,10 +1643,10 @@ class simple_html_dom
1643 $this->lowercase = $lowercase; 1643 $this->lowercase = $lowercase;
1644 $this->default_br_text = $defaultBRText; 1644 $this->default_br_text = $defaultBRText;
1645 $this->default_span_text = $defaultSpanText; 1645 $this->default_span_text = $defaultSpanText;
1646 $this->root = new simple_html_dom_node($this); 1646 $this->root = new fvm_simple_html_dom_node($this);
1647 $this->root->tag = 'root'; 1647 $this->root->tag = 'root';
1648 $this->root->_[HDOM_INFO_BEGIN] = -1; 1648 $this->root->_[FVMHDOM_INFO_BEGIN] = -1;
1649 $this->root->nodetype = HDOM_TYPE_ROOT; 1649 $this->root->nodetype = FVMHDOM_TYPE_ROOT;
1650 $this->parent = $this->root; 1650 $this->parent = $this->root;
1651 if ($this->size > 0) { $this->char = $this->doc[0]; } 1651 if ($this->size > 0) { $this->char = $this->doc[0]; }
1652 } 1652 }
...@@ -1665,9 +1665,9 @@ class simple_html_dom ...@@ -1665,9 +1665,9 @@ class simple_html_dom
1665 } 1665 }
1666 1666
1667 // Add a text node for text between tags 1667 // Add a text node for text between tags
1668 $node = new simple_html_dom_node($this); 1668 $node = new fvm_simple_html_dom_node($this);
1669 ++$this->cursor; 1669 ++$this->cursor;
1670 $node->_[HDOM_INFO_TEXT] = $s; 1670 $node->_[FVMHDOM_INFO_TEXT] = $s;
1671 $this->link_nodes($node, false); 1671 $this->link_nodes($node, false);
1672 } 1672 }
1673 } 1673 }
...@@ -1814,7 +1814,7 @@ class simple_html_dom ...@@ -1814,7 +1814,7 @@ class simple_html_dom
1814 { 1814 {
1815 // Set end position if no further tags found 1815 // Set end position if no further tags found
1816 if ($this->char !== '<') { 1816 if ($this->char !== '<') {
1817 $this->root->_[HDOM_INFO_END] = $this->cursor; 1817 $this->root->_[FVMHDOM_INFO_END] = $this->cursor;
1818 return false; 1818 return false;
1819 } 1819 }
1820 1820
...@@ -1845,7 +1845,7 @@ class simple_html_dom ...@@ -1845,7 +1845,7 @@ class simple_html_dom
1845 if (isset($this->optional_closing_tags[$parent_lower]) 1845 if (isset($this->optional_closing_tags[$parent_lower])
1846 && isset($this->block_tags[$tag_lower])) { 1846 && isset($this->block_tags[$tag_lower])) {
1847 1847
1848 $this->parent->_[HDOM_INFO_END] = 0; 1848 $this->parent->_[FVMHDOM_INFO_END] = 0;
1849 $org_parent = $this->parent; 1849 $org_parent = $this->parent;
1850 1850
1851 // Traverse ancestors to find a matching opening tag 1851 // Traverse ancestors to find a matching opening tag
...@@ -1864,7 +1864,7 @@ class simple_html_dom ...@@ -1864,7 +1864,7 @@ class simple_html_dom
1864 $this->parent = $this->parent->parent; 1864 $this->parent = $this->parent->parent;
1865 } 1865 }
1866 1866
1867 $this->parent->_[HDOM_INFO_END] = $this->cursor; 1867 $this->parent->_[FVMHDOM_INFO_END] = $this->cursor;
1868 return $this->as_text_node($tag); 1868 return $this->as_text_node($tag);
1869 } 1869 }
1870 } elseif (($this->parent->parent) 1870 } elseif (($this->parent->parent)
...@@ -1872,7 +1872,7 @@ class simple_html_dom ...@@ -1872,7 +1872,7 @@ class simple_html_dom
1872 ) { 1872 ) {
1873 // Grandparent exists and current tag is a block tag, so our 1873 // Grandparent exists and current tag is a block tag, so our
1874 // parent doesn't have an end tag 1874 // parent doesn't have an end tag
1875 $this->parent->_[HDOM_INFO_END] = 0; // No end tag 1875 $this->parent->_[FVMHDOM_INFO_END] = 0; // No end tag
1876 $org_parent = $this->parent; 1876 $org_parent = $this->parent;
1877 1877
1878 // Traverse ancestors to find a matching opening tag 1878 // Traverse ancestors to find a matching opening tag
...@@ -1886,13 +1886,13 @@ class simple_html_dom ...@@ -1886,13 +1886,13 @@ class simple_html_dom
1886 // If we don't have a match add current tag as text node 1886 // If we don't have a match add current tag as text node
1887 if (strtolower($this->parent->tag) !== $tag_lower) { 1887 if (strtolower($this->parent->tag) !== $tag_lower) {
1888 $this->parent = $org_parent; // restore origonal parent 1888 $this->parent = $org_parent; // restore origonal parent
1889 $this->parent->_[HDOM_INFO_END] = $this->cursor; 1889 $this->parent->_[FVMHDOM_INFO_END] = $this->cursor;
1890 return $this->as_text_node($tag); 1890 return $this->as_text_node($tag);
1891 } 1891 }
1892 } elseif (($this->parent->parent) 1892 } elseif (($this->parent->parent)
1893 && strtolower($this->parent->parent->tag) === $tag_lower 1893 && strtolower($this->parent->parent->tag) === $tag_lower
1894 ) { // Grandparent exists and current tag closes it 1894 ) { // Grandparent exists and current tag closes it
1895 $this->parent->_[HDOM_INFO_END] = 0; 1895 $this->parent->_[FVMHDOM_INFO_END] = 0;
1896 $this->parent = $this->parent->parent; 1896 $this->parent = $this->parent->parent;
1897 } else { // Random tag, add as text node 1897 } else { // Random tag, add as text node
1898 return $this->as_text_node($tag); 1898 return $this->as_text_node($tag);
...@@ -1900,7 +1900,7 @@ class simple_html_dom ...@@ -1900,7 +1900,7 @@ class simple_html_dom
1900 } 1900 }
1901 1901
1902 // Set end position of parent tag to current cursor position 1902 // Set end position of parent tag to current cursor position
1903 $this->parent->_[HDOM_INFO_END] = $this->cursor; 1903 $this->parent->_[FVMHDOM_INFO_END] = $this->cursor;
1904 1904
1905 if ($this->parent->parent) { 1905 if ($this->parent->parent) {
1906 $this->parent = $this->parent->parent; 1906 $this->parent = $this->parent->parent;
...@@ -1911,8 +1911,8 @@ class simple_html_dom ...@@ -1911,8 +1911,8 @@ class simple_html_dom
1911 } 1911 }
1912 1912
1913 // start tag 1913 // start tag
1914 $node = new simple_html_dom_node($this); 1914 $node = new fvm_simple_html_dom_node($this);
1915 $node->_[HDOM_INFO_BEGIN] = $this->cursor; 1915 $node->_[FVMHDOM_INFO_BEGIN] = $this->cursor;
1916 ++$this->cursor; 1916 ++$this->cursor;
1917 $tag = $this->copy_until($this->token_slash); // Get tag name 1917 $tag = $this->copy_until($this->token_slash); // Get tag name
1918 $node->tag_start = $begin_tag_pos; 1918 $node->tag_start = $begin_tag_pos;
...@@ -1922,17 +1922,17 @@ class simple_html_dom ...@@ -1922,17 +1922,17 @@ class simple_html_dom
1922 // <![CDATA[ ... ]]> 1922 // <![CDATA[ ... ]]>
1923 // <!-- Comment --> 1923 // <!-- Comment -->
1924 if (isset($tag[0]) && $tag[0] === '!') { 1924 if (isset($tag[0]) && $tag[0] === '!') {
1925 $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>'); 1925 $node->_[FVMHDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>');
1926 1926
1927 if (isset($tag[2]) && $tag[1] === '-' && $tag[2] === '-') { // Comment ("<!--") 1927 if (isset($tag[2]) && $tag[1] === '-' && $tag[2] === '-') { // Comment ("<!--")
1928 $node->nodetype = HDOM_TYPE_COMMENT; 1928 $node->nodetype = FVMHDOM_TYPE_COMMENT;
1929 $node->tag = 'comment'; 1929 $node->tag = 'comment';
1930 } else { // Could be doctype or CDATA but we don't care 1930 } else { // Could be doctype or CDATA but we don't care
1931 $node->nodetype = HDOM_TYPE_UNKNOWN; 1931 $node->nodetype = FVMHDOM_TYPE_UNKNOWN;
1932 $node->tag = 'unknown'; 1932 $node->tag = 'unknown';
1933 } 1933 }
1934 1934
1935 if ($this->char === '>') { $node->_[HDOM_INFO_TEXT] .= '>'; } 1935 if ($this->char === '>') { $node->_[FVMHDOM_INFO_TEXT] .= '>'; }
1936 1936
1937 $this->link_nodes($node, true); 1937 $this->link_nodes($node, true);
1938 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next 1938 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
...@@ -1943,7 +1943,7 @@ class simple_html_dom ...@@ -1943,7 +1943,7 @@ class simple_html_dom
1943 // i.e. "<<html>" 1943 // i.e. "<<html>"
1944 if ($pos = strpos($tag, '<') !== false) { 1944 if ($pos = strpos($tag, '<') !== false) {
1945 $tag = '<' . substr($tag, 0, -1); 1945 $tag = '<' . substr($tag, 0, -1);
1946 $node->_[HDOM_INFO_TEXT] = $tag; 1946 $node->_[FVMHDOM_INFO_TEXT] = $tag;
1947 $this->link_nodes($node, false); 1947 $this->link_nodes($node, false);
1948 $this->char = $this->doc[--$this->pos]; // prev 1948 $this->char = $this->doc[--$this->pos]; // prev
1949 return true; 1949 return true;
...@@ -1951,7 +1951,7 @@ class simple_html_dom ...@@ -1951,7 +1951,7 @@ class simple_html_dom
1951 1951
1952 // Handle invalid tag names (i.e. "<html#doc>") 1952 // Handle invalid tag names (i.e. "<html#doc>")
1953 if (!preg_match('/^\w[\w:-]*$/', $tag)) { 1953 if (!preg_match('/^\w[\w:-]*$/', $tag)) {
1954 $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>'); 1954 $node->_[FVMHDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>');
1955 1955
1956 // Next char is the beginning of a new tag, don't touch it. 1956 // Next char is the beginning of a new tag, don't touch it.
1957 if ($this->char === '<') { 1957 if ($this->char === '<') {
...@@ -1960,14 +1960,14 @@ class simple_html_dom ...@@ -1960,14 +1960,14 @@ class simple_html_dom
1960 } 1960 }
1961 1961
1962 // Next char closes current tag, add and be done with it. 1962 // Next char closes current tag, add and be done with it.
1963 if ($this->char === '>') { $node->_[HDOM_INFO_TEXT] .= '>'; } 1963 if ($this->char === '>') { $node->_[FVMHDOM_INFO_TEXT] .= '>'; }
1964 $this->link_nodes($node, false); 1964 $this->link_nodes($node, false);
1965 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next 1965 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
1966 return true; 1966 return true;
1967 } 1967 }
1968 1968
1969 // begin tag, add new node 1969 // begin tag, add new node
1970 $node->nodetype = HDOM_TYPE_ELEMENT; 1970 $node->nodetype = FVMHDOM_TYPE_ELEMENT;
1971 $tag_lower = strtolower($tag); 1971 $tag_lower = strtolower($tag);
1972 $node->tag = ($this->lowercase) ? $tag_lower : $tag; 1972 $node->tag = ($this->lowercase) ? $tag_lower : $tag;
1973 1973
...@@ -1975,7 +1975,7 @@ class simple_html_dom ...@@ -1975,7 +1975,7 @@ class simple_html_dom
1975 if (isset($this->optional_closing_tags[$tag_lower])) { 1975 if (isset($this->optional_closing_tags[$tag_lower])) {
1976 // Traverse ancestors to close all optional closing tags 1976 // Traverse ancestors to close all optional closing tags
1977 while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) { 1977 while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) {
1978 $this->parent->_[HDOM_INFO_END] = 0; 1978 $this->parent->_[FVMHDOM_INFO_END] = 0;
1979 $this->parent = $this->parent->parent; 1979 $this->parent = $this->parent->parent;
1980 } 1980 }
1981 $node->parent = $this->parent; 1981 $node->parent = $this->parent;
...@@ -2005,9 +2005,9 @@ class simple_html_dom ...@@ -2005,9 +2005,9 @@ class simple_html_dom
2005 // handle endless '<' 2005 // handle endless '<'
2006 // Out of bounds before the tag ended 2006 // Out of bounds before the tag ended
2007 if ($this->pos >= $this->size - 1 && $this->char !== '>') { 2007 if ($this->pos >= $this->size - 1 && $this->char !== '>') {
2008 $node->nodetype = HDOM_TYPE_TEXT; 2008 $node->nodetype = FVMHDOM_TYPE_TEXT;
2009 $node->_[HDOM_INFO_END] = 0; 2009 $node->_[FVMHDOM_INFO_END] = 0;
2010 $node->_[HDOM_INFO_TEXT] = '<' . $tag . $space[0] . $name; 2010 $node->_[FVMHDOM_INFO_TEXT] = '<' . $tag . $space[0] . $name;
2011 $node->tag = 'text'; 2011 $node->tag = 'text';
2012 $this->link_nodes($node, false); 2012 $this->link_nodes($node, false);
2013 return true; 2013 return true;
...@@ -2016,11 +2016,11 @@ class simple_html_dom ...@@ -2016,11 +2016,11 @@ class simple_html_dom
2016 // handle mismatch '<' 2016 // handle mismatch '<'
2017 // Attributes cannot start after opening tag 2017 // Attributes cannot start after opening tag
2018 if ($this->doc[$this->pos - 1] == '<') { 2018 if ($this->doc[$this->pos - 1] == '<') {
2019 $node->nodetype = HDOM_TYPE_TEXT; 2019 $node->nodetype = FVMHDOM_TYPE_TEXT;
2020 $node->tag = 'text'; 2020 $node->tag = 'text';
2021 $node->attr = array(); 2021 $node->attr = array();
2022 $node->_[HDOM_INFO_END] = 0; 2022 $node->_[FVMHDOM_INFO_END] = 0;
2023 $node->_[HDOM_INFO_TEXT] = substr( 2023 $node->_[FVMHDOM_INFO_TEXT] = substr(
2024 $this->doc, 2024 $this->doc,
2025 $begin_tag_pos, 2025 $begin_tag_pos,
2026 $this->pos - $begin_tag_pos - 1 2026 $this->pos - $begin_tag_pos - 1
...@@ -2044,12 +2044,12 @@ class simple_html_dom ...@@ -2044,12 +2044,12 @@ class simple_html_dom
2044 $this->parse_attr($node, $name, $space); // get attribute value 2044 $this->parse_attr($node, $name, $space); // get attribute value
2045 } else { 2045 } else {
2046 //no value attr: nowrap, checked selected... 2046 //no value attr: nowrap, checked selected...
2047 $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; 2047 $node->_[FVMHDOM_INFO_QUOTE][] = FVMHDOM_QUOTE_NO;
2048 $node->attr[$name] = true; 2048 $node->attr[$name] = true;
2049 if ($this->char != '>') { $this->char = $this->doc[--$this->pos]; } // prev 2049 if ($this->char != '>') { $this->char = $this->doc[--$this->pos]; } // prev
2050 } 2050 }
2051 2051
2052 $node->_[HDOM_INFO_SPACE][] = $space; 2052 $node->_[FVMHDOM_INFO_SPACE][] = $space;
2053 2053
2054 // prepare for next attribute 2054 // prepare for next attribute
2055 $space = array( 2055 $space = array(
...@@ -2063,12 +2063,12 @@ class simple_html_dom ...@@ -2063,12 +2063,12 @@ class simple_html_dom
2063 } while ($this->char !== '>' && $this->char !== '/'); // go until the tag ended 2063 } while ($this->char !== '>' && $this->char !== '/'); // go until the tag ended
2064 2064
2065 $this->link_nodes($node, true); 2065 $this->link_nodes($node, true);
2066 $node->_[HDOM_INFO_ENDSPACE] = $space[0]; 2066 $node->_[FVMHDOM_INFO_ENDSPACE] = $space[0];
2067 2067
2068 // handle empty tags (i.e. "<div/>") 2068 // handle empty tags (i.e. "<div/>")
2069 if ($this->copy_until_char('>') === '/') { 2069 if ($this->copy_until_char('>') === '/') {
2070 $node->_[HDOM_INFO_ENDSPACE] .= '/'; 2070 $node->_[FVMHDOM_INFO_ENDSPACE] .= '/';
2071 $node->_[HDOM_INFO_END] = 0; 2071 $node->_[FVMHDOM_INFO_END] = 0;
2072 } else { 2072 } else {
2073 // reset parent 2073 // reset parent
2074 if (!isset($this->self_closing_tags[strtolower($node->tag)])) { 2074 if (!isset($this->self_closing_tags[strtolower($node->tag)])) {
...@@ -2082,7 +2082,7 @@ class simple_html_dom ...@@ -2082,7 +2082,7 @@ class simple_html_dom
2082 // This way when we see it in plaintext, we can generate formatting that the user wants. 2082 // This way when we see it in plaintext, we can generate formatting that the user wants.
2083 // since a br tag never has sub nodes, this works well. 2083 // since a br tag never has sub nodes, this works well.
2084 if ($node->tag === 'br') { 2084 if ($node->tag === 'br') {
2085 $node->_[HDOM_INFO_INNER] = $this->default_br_text; 2085 $node->_[FVMHDOM_INFO_INNER] = $this->default_br_text;
2086 } 2086 }
2087 2087
2088 return true; 2088 return true;
...@@ -2097,19 +2097,19 @@ class simple_html_dom ...@@ -2097,19 +2097,19 @@ class simple_html_dom
2097 2097
2098 switch ($this->char) { 2098 switch ($this->char) {
2099 case '"': 2099 case '"':
2100 $quote_type = HDOM_QUOTE_DOUBLE; 2100 $quote_type = FVMHDOM_QUOTE_DOUBLE;
2101 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next 2101 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2102 $value = $this->copy_until_char('"'); 2102 $value = $this->copy_until_char('"');
2103 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next 2103 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2104 break; 2104 break;
2105 case '\'': 2105 case '\'':
2106 $quote_type = HDOM_QUOTE_SINGLE; 2106 $quote_type = FVMHDOM_QUOTE_SINGLE;
2107 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next 2107 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2108 $value = $this->copy_until_char('\''); 2108 $value = $this->copy_until_char('\'');
2109 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next 2109 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2110 break; 2110 break;
2111 default: 2111 default:
2112 $quote_type = HDOM_QUOTE_NO; 2112 $quote_type = FVMHDOM_QUOTE_NO;
2113 $value = $this->copy_until($this->token_attr); 2113 $value = $this->copy_until($this->token_attr);
2114 } 2114 }
2115 2115
...@@ -2127,7 +2127,7 @@ class simple_html_dom ...@@ -2127,7 +2127,7 @@ class simple_html_dom
2127 } 2127 }
2128 2128
2129 if (!$is_duplicate) { 2129 if (!$is_duplicate) {
2130 $node->_[HDOM_INFO_QUOTE][] = $quote_type; 2130 $node->_[FVMHDOM_INFO_QUOTE][] = $quote_type;
2131 $node->attr[$name] = $value; 2131 $node->attr[$name] = $value;
2132 } 2132 }
2133 } 2133 }
...@@ -2143,9 +2143,9 @@ class simple_html_dom ...@@ -2143,9 +2143,9 @@ class simple_html_dom
2143 2143
2144 protected function as_text_node($tag) 2144 protected function as_text_node($tag)
2145 { 2145 {
2146 $node = new simple_html_dom_node($this); 2146 $node = new fvm_simple_html_dom_node($this);
2147 ++$this->cursor; 2147 ++$this->cursor;
2148 $node->_[HDOM_INFO_TEXT] = '</' . $tag . '>'; 2148 $node->_[FVMHDOM_INFO_TEXT] = '</' . $tag . '>';
2149 $this->link_nodes($node, false); 2149 $this->link_nodes($node, false);
2150 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next 2150 $this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
2151 return true; 2151 return true;
...@@ -2323,12 +2323,12 @@ class simple_html_dom ...@@ -2323,12 +2323,12 @@ class simple_html_dom
2323 2323
2324 function createElement($name, $value = null) 2324 function createElement($name, $value = null)
2325 { 2325 {
2326 return @str_get_html("<$name>$value</$name>")->firstChild(); 2326 return @fvm_str_get_html("<$name>$value</$name>")->firstChild();
2327 } 2327 }
2328 2328
2329 function createTextNode($value) 2329 function createTextNode($value)
2330 { 2330 {
2331 return @end(str_get_html($value)->nodes); 2331 return @end(fvm_str_get_html($value)->nodes);
2332 } 2332 }
2333 2333
2334 function getElementById($id) 2334 function getElementById($id)
......
...@@ -3,13 +3,13 @@ Contributors: Alignak ...@@ -3,13 +3,13 @@ Contributors: Alignak
3 Tags: PHP Minify, Lighthouse, GTmetrix, Pingdom, Pagespeed, Merging, Minification, Optimization, Speed, Performance, FVM 3 Tags: PHP Minify, Lighthouse, GTmetrix, Pingdom, Pagespeed, Merging, Minification, Optimization, Speed, Performance, FVM
4 Requires at least: 4.9 4 Requires at least: 4.9
5 Requires PHP: 5.6 5 Requires PHP: 5.6
6 Stable tag: 3.2.2 6 Stable tag: 3.2.6
7 Tested up to: 5.7.1 7 Tested up to: 5.9.1
8 Text Domain: fast-velocity-minify 8 Text Domain: fast-velocity-minify
9 License: GPLv3 or later 9 License: GPLv3 or later
10 License URI: http://www.gnu.org/licenses/gpl-3.0.html 10 License URI: http://www.gnu.org/licenses/gpl-3.0.html
11 11
12 Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by adjusting your CSS and JS files (defer, async, minify, combine, etc), compressing HTML, simplifying fonts and a few more speed optimization options. 12 Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by adjusting CSS and JS files (defer, async, minify, combine, etc), compressing HTML, simplifying fonts and a few more speed optimization options.
13 13
14 14
15 == Description == 15 == Description ==
...@@ -49,8 +49,26 @@ You need a public directory to store and serve minified cache files. If you need ...@@ -49,8 +49,26 @@ You need a public directory to store and serve minified cache files. If you need
49 49
50 == Changelog == 50 == Changelog ==
51 51
52 = 3.2.2 [2021.05.09] = 52 = 3.2.6 [2022.02.06] =
53 * cache purging fixes
54
55 = 3.2.5 [2022.02.01] =
56 * changed writing the css/js files to WP_Filesystem_Direct with a secondary fallback method
57 * fixed a bug when merging css/js can break the site layout if the plugin failed to write the cache file (there will be an html comment on the footer if this happens)
58 * renamed a common name class to avoid conflicts with other plugins
59
60 = 3.2.4 [2022.01.31] =
61 * WP 5.9 / PHP 8 maintenance release
62 * changed deferred css/js cache clearing from 24h to 7 days
63 * added cache purging support for nginx helper plugin
64 * added option to allow processing on specific query strings
65 * other bug fixes
66
67 = 3.2.3 [2021.05.15] =
53 * added auto varnish cache purge for Cloudways 68 * added auto varnish cache purge for Cloudways
69 * switched from WP_Filesystem_Direct() to WP_Filesystem()
70
71 = 3.2.2 [2021.05.09] =
54 * fixed some JS files not being minified 72 * fixed some JS files not being minified
55 73
56 = 3.2.1 [2021.05.07] = 74 = 3.2.1 [2021.05.07] =
......