PluginProbe
Featherweight / 2.2.0
Featherweight v2.2.0
2.2.3 2.2.2 2.2.0 2.2.1 2.0.2 trunk 1.4.5 1.5.0 1.5.19 1.5.20 1.5.21 1.5.22 1.6.0 1.6.1 2.0.0 2.0.1
wp-disable / lib / class-wpperformance.php

class-wpperformance.php in Featherweight 2.2.0, at lib/class-wpperformance.php

963 lines 29.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) || exit; // Prevent direct access.
3 class WpPerformance {
4
5 private static $instance = false;
6
7 const MIN_PHP_VERSION = '7.4';
8 const MIN_WP_VERSION = '6.4';
9 const TEXT_DOMAIN = 'wp-disable';
10 const OPTION_KEY = 'wpperformance_rev3a';
11
12 // Internal schema version, bumped when a one-time data migration is needed.
13 // v2: removed the obsolete Universal Analytics "local GA" offload feature.
14 const DB_VERSION = 2;
15 const DB_VERSION_KEY = 'wpperformance_db_version';
16
17 private $plugin_settings = null;
18
19 private static $enabled_woocommerce = null;
20
21 /**
22 * Constructor.
23 * Initializes the plugin by setting localization, filters, and
24 * administration functions.
25 */
26 private function __construct() {
27
28 if ( ! $this->test_host() ) { return; }
29
30 $this->maybe_upgrade();
31
32 if( ! class_exists('Optimisationio_Dashboard') ){
33 require_once 'class-optimisationio-dashboard.php';
34 }
35
36 Optimisationio_Dashboard::init();
37
38 new WpPerformance_Admin;
39
40 add_action( 'init', array( $this, 'text_domain' ) );
41
42 $this->apply_settings();
43 }
44
45 /**
46 * Singleton class instance.
47 */
48 public static function get_instance() {
49 if ( ! self::$instance ) {
50 self::$instance = new self();
51 }
52 return self::$instance;
53 }
54
55 /**
56 * Loads the plugin text domain for translation
57 */
58 public function text_domain() {
59 load_plugin_textdomain(
60 self::TEXT_DOMAIN,
61 false,
62 dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR
63 );
64 }
65
66 /**
67 * Delete plugin's transient values.
68 */
69 public static function delete_transients() {
70 delete_transient( self::OPTION_KEY . '_referalls_spam_blacklist' );
71 }
72
73 /**
74 * Delete plugin's options values.
75 */
76 public static function delete_options() {
77 delete_option( self::OPTION_KEY . '_settings' );
78 delete_option( self::OPTION_KEY . '_combined_google_fonts_requests_number' );
79 delete_option( self::OPTION_KEY . '_combined_font_awesome_requests_number' );
80 delete_option( self::DB_VERSION_KEY );
81 }
82
83 /**
84 * One-time data migrations, keyed off DB_VERSION_KEY.
85 */
86 private function maybe_upgrade() {
87
88 $installed = (int) get_option( self::DB_VERSION_KEY, 1 );
89
90 if ( $installed >= self::DB_VERSION ) {
91 return;
92 }
93
94 // v2: tear down the removed Universal Analytics "local GA" offload.
95 wp_clear_scheduled_hook( 'update_local_ga' );
96 delete_transient( 'wpperformance_ds_tracking_id' );
97
98 $settings = get_option( self::OPTION_KEY . '_settings', array() );
99 if ( is_array( $settings ) ) {
100 $ga_keys = array(
101 'ds_tracking_id', 'ds_adjusted_bounce_rate', 'ds_enqueue_order',
102 'ds_anonymize_ip', 'ds_script_position', 'ds_track_admin',
103 'caos_disable_display_features', 'caos_remove_wp_cron',
104 );
105 foreach ( $ga_keys as $ga_key ) {
106 unset( $settings[ $ga_key ] );
107 }
108 update_option( self::OPTION_KEY . '_settings', $settings );
109 }
110
111 $local_ga = dirname( dirname( __FILE__ ) ) . '/cache/local-ga.js';
112 if ( file_exists( $local_ga ) ) {
113 @unlink( $local_ga );
114 }
115
116 update_option( self::DB_VERSION_KEY, self::DB_VERSION );
117 }
118
119 public static function delete_spam_comments() {
120 global $wpdb;
121
122 $spam_comments_id_arr = $wpdb->get_col( "SELECT comment_id FROM {$wpdb->comments} WHERE comment_approved = 'spam'" );
123 if ( ! empty( $spam_comments_id_arr ) ) {
124 $spam_comments_id_arr = array_map( 'intval', $spam_comments_id_arr );
125
126 // Build one %d placeholder per id. Using IN ( %s ) with an imploded
127 // string (the old code) made $wpdb->prepare quote the whole list as a
128 // single value, so nothing was ever deleted.
129 $placeholders = implode( ', ', array_fill( 0, count( $spam_comments_id_arr ), '%d' ) );
130
131 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->comments} WHERE comment_id IN ( $placeholders )", $spam_comments_id_arr ) );
132 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->commentmeta} WHERE comment_id IN ( $placeholders )", $spam_comments_id_arr ) );
133
134 $wpdb->query( "OPTIMIZE TABLE $wpdb->comments" );
135 $wpdb->query( "OPTIMIZE TABLE $wpdb->commentmeta" );
136 }
137 }
138
139 public static function schedule_spam_comments_delete( $schedule, $reschedule = false ) {
140
141 $pre_schedule = wp_get_schedule( 'delete_spam_comments' );
142
143 if ( $reschedule || ( $pre_schedule && $pre_schedule !== $schedule ) || ! wp_next_scheduled( 'delete_spam_comments' ) ) {
144 self::unschedule_spam_comments_delete();
145 wp_schedule_event( time(), $schedule, 'delete_spam_comments' );
146 }
147 }
148
149 public static function unschedule_spam_comments_delete() {
150 wp_clear_scheduled_hook( 'delete_spam_comments' );
151 }
152
153 // -------------------------------------------------------------------------
154 // Environment Checks
155 // -------------------------------------------------------------------------
156
157 /**
158 * Checks PHP and WordPress versions.
159 */
160 private function test_host() {
161 // Check if PHP is too old.
162 if ( version_compare( PHP_VERSION, self::MIN_PHP_VERSION, '<' ) ) {
163 // Display notice.
164 add_action( 'admin_notices', array( &$this, 'php_version_error' ) );
165 return false;
166 }
167
168 // Check if WordPress is too old.
169 global $wp_version;
170 if ( version_compare( $wp_version, self::MIN_WP_VERSION, '<' ) ) {
171 add_action( 'admin_notices', array( &$this, 'wp_version_error' ) );
172 return false;
173 }
174 return true;
175 }
176
177 /**
178 * Displays a warning when installed on an old PHP version.
179 */
180 public function php_version_error() {
181 echo '<div class="error"><p><strong>';
182 printf(
183 'Error: %3$s requires PHP version %1$s or greater.<br/>' .
184 'Your installed PHP version: %2$s',
185 self::MIN_PHP_VERSION,
186 PHP_VERSION,
187 $this->get_plugin_name()
188 );
189 echo '</strong></p></div>';
190 }
191
192 /**
193 * Displays a warning when installed in an old WordPress version.
194 */
195 public function wp_version_error() {
196 echo '<div class="error"><p><strong>';
197 printf(
198 'Error: %2$s requires WordPress version %1$s or greater.',
199 self::MIN_WP_VERSION,
200 $this->get_plugin_name()
201 );
202 echo '</strong></p></div>';
203 }
204
205 /**
206 * Get the name of this plugin.
207 *
208 * @return string The plugin name.
209 */
210 private function get_plugin_name() {
211 // get_plugin_data() lives in wp-admin and must be pointed at the MAIN
212 // plugin file (this is the class file). Guard both so the version-error
213 // notices never fatal.
214 if ( ! function_exists( 'get_plugin_data' ) ) {
215 require_once ABSPATH . 'wp-admin/includes/plugin.php';
216 }
217 $main_file = dirname( __FILE__, 2 ) . '/wpperformance.php';
218 $data = get_plugin_data( $main_file, false, false );
219 return ! empty( $data['Name'] ) ? $data['Name'] : 'Featherweight';
220 }
221
222 // -------------------------------------------------------------------------
223 // Apply settings values
224 // -------------------------------------------------------------------------
225
226 private function apply_settings() {
227
228 $this->check_referral_spam_disable();
229
230 if ( ! is_admin() ) {
231 $this->check_pages_disable();
232 $this->check_dns_prefetch();
233 }
234 else{
235 $this->check_admin_notices_display();
236 }
237
238 $this->check_comments_disable();
239 $this->check_feeds_disable();
240
241 add_action( 'wp_print_styles', array( $this, 'enqueue_scripts' ), -1 );
242 add_action( 'wp_print_styles', array( $this, 'dequeue_styles'), -1 );
243 add_action( 'wp_print_scripts', array( $this, 'dequeue_scripts' ), 100 );
244
245 }
246
247 private function get_settings_values() {
248 $this->plugin_settings = null === $this->plugin_settings ? get_option( WpPerformance::OPTION_KEY . '_settings', array() ) : $this->plugin_settings;
249 return $this->plugin_settings;
250 }
251
252 public function enqueue_scripts() {
253 $async_links = $this->check_googlefonts_fontawesome_styles();
254 if ( ! empty( $async_links ) ) {
255 wp_enqueue_script( 'wp-disable-css-lazy-load', plugin_dir_url( dirname( __FILE__ ) ) . 'js/css-lazy-load.js' );
256 wp_localize_script( 'wp-disable-css-lazy-load', 'WpDisableAsyncLinks', $async_links );
257 }
258 }
259
260 public function dequeue_styles(){
261
262 $settings = $this->get_settings_values();
263
264 if( ! is_admin() &&
265 ! is_admin_bar_showing() &&
266 ! is_customize_preview() &&
267 isset( $settings['disable_front_dashicons_when_disabled_toolbar'] ) &&
268 $settings['disable_front_dashicons_when_disabled_toolbar'] ){
269 wp_deregister_style('dashicons');
270 }
271 }
272
273 public function dequeue_scripts() {
274
275 $settings = $this->get_settings_values();
276
277 $invalid_disable = is_page('lost_password');
278
279 $wc_invalid_disable = ! WpPerformance::is_woocommerce_enabled() || $invalid_disable || is_account_page() || is_checkout();
280
281 if ( ! $wc_invalid_disable && isset( $settings['disable_woocommerce_password_meter'] ) && $settings['disable_woocommerce_password_meter'] ) {
282
283 if ( wp_script_is( 'zxcvbn-async', 'enqueued' ) ) {
284 wp_dequeue_script( 'zxcvbn-async' );
285 }
286
287 if ( wp_script_is( 'password-strength-meter', 'enqueued' ) ) {
288 wp_dequeue_script( 'password-strength-meter' );
289 }
290
291 if ( wp_script_is( 'wc-password-strength-meter', 'enqueued' ) ) {
292 wp_dequeue_script( 'wc-password-strength-meter' );
293 }
294 }
295
296 if ( ! $invalid_disable && isset( $settings['disable_wordpress_password_meter'] ) && $settings['disable_wordpress_password_meter'] ) {
297
298 if ( wp_script_is( 'zxcvbn-async', 'enqueued' ) ) {
299 wp_dequeue_script( 'zxcvbn-async' );
300 }
301
302 if ( wp_script_is( 'password-strength-meter', 'enqueued' ) ) {
303 wp_dequeue_script( 'password-strength-meter' );
304 }
305 }
306 }
307
308 private function check_googlefonts_fontawesome_styles() {
309 global $wp_styles;
310 $ret = array();
311 if ( isset( $wp_styles ) && ! empty( $wp_styles ) ) {
312
313 $settings = $this->get_settings_values();
314
315 $load_google_fonts = isset( $settings['lazy_load_google_fonts'] ) && $settings['lazy_load_google_fonts'];
316 $load_font_awesome = isset( $settings['lazy_load_font_awesome'] ) && $settings['lazy_load_font_awesome'];
317
318 if ( $load_google_fonts || $load_font_awesome ) {
319
320 $gfonts_base_url = 'fonts.googleapis.com/css';
321 $gfonts_links = array();
322
323 $font_awesome_slug = 'font-awesome';
324 $font_awesome_slug_alt = 'fontawesome';
325 $font_awesome_links = array(
326 'external' => array(),
327 'internal' => array(),
328 );
329
330 foreach ( $wp_styles->queue as $handle ) {
331 if ( $load_google_fonts && false !== strpos( $wp_styles->registered[ $handle ]->src, $gfonts_base_url ) ) {
332 $gfonts_links[] = urldecode( str_replace( array( '&amp;' ), array( '&' ), $wp_styles->registered[ $handle ]->src ) );
333 wp_dequeue_style( $handle );
334 } elseif ( $load_font_awesome && false !== strpos( $wp_styles->registered[ $handle ]->src, $font_awesome_slug ) || false !== strpos( $wp_styles->registered[ $handle ]->src, $font_awesome_slug_alt ) ) {
335
336 wp_dequeue_style( $handle );
337
338 $font_awesome_links[ false !== strpos( $wp_styles->registered[ $handle ]->src, site_url() ) ? 'internal' : 'external' ][] = array(
339 'ver' => $wp_styles->registered[ $handle ]->ver ? $wp_styles->registered[ $handle ]->ver : false,
340 'link' => $wp_styles->registered[ $handle ]->src,
341 );
342 }
343 }
344
345 $saved_font_awesome_requests = 0;
346 $saved_google_fonts_requests = 0;
347
348 if ( $load_font_awesome && ( ! empty( $font_awesome_links['internal'] ) || ! empty( $font_awesome_links['external'] ) ) ) {
349
350 // @note: Prioritize external links.
351 $fa_links = ! empty( $font_awesome_links['external'] ) ? $font_awesome_links['external'] : $font_awesome_links['internal'];
352
353 $selected_fa_link = $fa_links[0];
354
355 $links_count = count( $fa_links );
356 if ( 1 < $links_count ) {
357 for ( $i = 1; $i < $links_count; $i++ ) {
358 if ( false !== $fa_links[ $i ]['ver'] &&
359 ( false === $selected_fa_link['ver'] || version_compare( $selected_fa_link['ver'], $fa_links[ $i ]['ver'], '<' ) )
360 ) {
361 $selected_fa_link = $fa_links[ $i ];
362 }
363 }
364 }
365
366 $ret['wp-disable-font-awesome'] = esc_url( $selected_fa_link['link'] );
367
368 $this->update_saved_font_awesome_requests( count( $font_awesome_links['internal'] ) + count( $font_awesome_links['external'] ) );
369 }
370 else{
371 $this->update_saved_font_awesome_requests(0);
372 }
373
374 if ( $load_google_fonts && ! empty( $gfonts_links ) ) {
375
376 $ret['wp-disable-google-fonts'] = esc_url( $this->combine_google_fonts_links( $gfonts_links ) );
377
378 $this->update_saved_google_fonts_request( count( $gfonts_links ) );
379 }
380 else{
381 $this->update_saved_google_fonts_request(0);
382 }
383 }
384 else{
385 $this->update_saved_font_awesome_requests(0);
386 $this->update_saved_google_fonts_request(0);
387 }
388 }// End if().
389
390 return $ret;
391 }
392
393 private function update_saved_google_fonts_request( $count ) {
394 $count = ! isset( $count ) ? 0 : (int) $count;
395 $old_val = get_option( self::OPTION_KEY . '_combined_google_fonts_requests_number' );
396 if( false === $old_val || ( false !== $old_val && $count > (int) $old_val ) ){
397 update_option( self::OPTION_KEY . '_combined_google_fonts_requests_number', $count );
398 }
399 }
400
401 private function update_saved_font_awesome_requests( $count ) {
402 $count = ! isset( $count ) ? 0 : (int) $count;
403 $old_val = get_option( self::OPTION_KEY . '_combined_font_awesome_requests_number' );
404 if( false === $old_val || ( false !== $old_val && $count > (int) $old_val ) ){
405 update_option( self::OPTION_KEY . '_combined_font_awesome_requests_number', $count );
406 }
407 }
408
409 public static function saved_external_requests(){
410 $google_fonts = (int) get_option( self::OPTION_KEY . '_combined_google_fonts_requests_number' );
411 $font_awesome = (int) get_option( self::OPTION_KEY . '_combined_font_awesome_requests_number' );
412 $google_fonts_saved = 1 < $google_fonts ? $google_fonts - 1 : 0;
413 $font_awesome_saved = 1 < $font_awesome ? $font_awesome - 1 : 0;
414 return $google_fonts_saved + $font_awesome_saved;
415 }
416
417 /**
418 * Combine multiple Google Fonts links into one.
419 *
420 * @param array $links An array of the different Google Fonts links. Default array().
421 * @return string The compined Google Fonts link.
422 */
423 private function combine_google_fonts_links( $links = array() ) {
424
425 if ( ! is_array( $links ) ) {
426 return $links;
427 }
428
429 $links = array_unique( $links );
430
431 if ( 1 === count( $links ) ) {
432 return $links[0];
433 }
434
435 $protocol = 'https';
436 $base_url = '//fonts.googleapis.com/css';
437 $family_arg = 'family';
438 $subset_arg = 'subset';
439
440 $base_url_len = strlen( $base_url );
441 $family_arg_len = strlen( $family_arg );
442
443 $fonts = array();
444 $cnt = 0;
445
446 $clean_links = array();
447 foreach ( $links as $k => $v ) {
448
449 $base_url_pos = strrpos( $v, $base_url );
450
451 $args_str = trim( substr( $v, ($base_url_len + $base_url_pos), strlen( $v ) ) );
452
453 if ( substr( $args_str, 0, $family_arg_len + 2 ) === '?' . $family_arg . '=' ) {
454 $args_str = substr( $args_str, $family_arg_len + 2, strlen( $args_str ) );
455 }
456
457 $tmp = explode( '|', $args_str );
458 $tmp_count = count( $tmp );
459 for ( $i = 0; $i < $tmp_count; $i++ ) {
460 $clean_links[] = $tmp[ $i ];
461 }
462 }
463
464 foreach ( $clean_links as $k => $v ) {
465
466 $expl = explode( '&' . $subset_arg, $v );
467
468 if ( isset( $expl[0] ) && ! empty( $expl[0] ) ) {
469
470 $tmp = explode( ':', $expl[0] );
471
472 if ( isset( $tmp[0] ) && ! empty( $tmp[0] ) ) {
473
474 // Has font family name.
475 $font_name = str_replace( ' ', '+', $tmp[0] );
476
477 if ( ! isset( $fonts[ $font_name ] ) ) {
478 $fonts[ $font_name ] = array(
479 'sizes' => array(),
480 'subsets' => array(),
481 );
482 }
483
484 if ( isset( $tmp[1] ) && ! empty( $tmp[1] ) ) {
485
486 // Has font sizes.
487 $x = explode( ',', $tmp[1] );
488 $xc = count( $x );
489
490 foreach ( $x as $xk => $xv ) {
491 if ( ! in_array( $xv, $fonts[ $font_name ]['sizes'], true ) && ( 400 !== (int) $xv || $xc > 1) ) {
492 $fonts[ $font_name ]['sizes'][] = $xv;
493 }
494 }
495 }
496
497 if ( isset( $expl[1] ) && ! empty( $expl[1] ) ) {
498
499 // Has subsets.
500 $y = explode( ',', $expl[1] );
501 $yc = count( $y );
502
503 foreach ( $y as $yk => $yv ) {
504
505 if ( '=' === substr( $yv, 0, 1 ) ) {
506 $yv = substr( $yv, 1, strlen( $yv ) );
507 }
508
509 if ( ! in_array( $yv, $fonts[ $font_name ]['subsets'], true ) && ('latin' !== $yv || $yc > 1) ) {
510 $fonts[ $font_name ]['subsets'][] = $yv;
511 }
512 }
513 }
514 }// End if().
515 }// End if().
516 }// End foreach().
517
518 $ret = '';
519
520 if ( ! empty( $fonts ) ) {
521
522 $ret .= $protocol . ':' . $base_url;
523 $i = 0;
524 $subsets = array();
525
526 foreach ( $fonts as $key => $val ) {
527
528 if ( 0 === $i ) {
529 $ret .= '?' . $family_arg . '=';
530 } else {
531 $ret .= '|';
532 }
533
534 $ret .= $key;
535
536 if ( ! empty( $val['sizes'] ) ) {
537 $ret .= ':' . implode( ',', $val['sizes'] );
538 }
539
540 if ( ! empty( $val['subsets'] ) ) {
541 $subsets = array_merge( $subsets, $val['subsets'] );
542 }
543
544 $i++;
545 }
546
547 if ( ! empty( $subsets ) ) {
548 $ret .= '&' . $subset_arg . '=' . implode( ',', $subsets );
549 }
550 }
551
552 return $ret;
553 }
554
555 public static function check_spam_comments_delete( $reschedule = false ) {
556
557 // This method is static; $this is never available here (the old
558 // isset( $this ) branch was dead code that also errored on PHP 8).
559 $settings = get_option( self::OPTION_KEY . '_settings', array() );
560
561 if ( isset( $settings['spam_comments_cleaner'] ) && 1 === (int) $settings['spam_comments_cleaner'] && isset( $settings['delete_spam_comments'] ) && $settings['delete_spam_comments'] ) {
562 self::schedule_spam_comments_delete( $settings['delete_spam_comments'], $reschedule );
563 } else {
564 self::unschedule_spam_comments_delete();
565 }
566 }
567
568 public static function synchronize_discussion_data($settings){
569 if ( isset( $settings['disable_gravatars'] ) && 1 === (int) $settings['disable_gravatars'] ) {
570 update_option( 'show_avatars', false );
571 } else {
572 update_option( 'show_avatars', true );
573 }
574
575 if ( isset( $settings['default_ping_status'] ) && 1 === (int) $settings['default_ping_status'] ) {
576 update_option( 'default_ping_status', 'close' );
577 } else {
578 update_option( 'default_ping_status', 'open' );
579 }
580
581 if ( isset( $settings['close_comments'] ) && 1 === (int) $settings['close_comments'] ) {
582 update_option( 'close_comments_for_old_posts', true );
583 update_option( 'close_comments_days_old', 28 );
584 } else {
585 update_option( 'close_comments_for_old_posts', false );
586 update_option( 'close_comments_days_old', 14 );
587 }
588
589 if ( isset( $settings['paginate_comments'] ) && 1 === (int) $settings['paginate_comments'] ) {
590 update_option( 'page_comments', true );
591 update_option( 'comments_per_page', 20 );
592 } else {
593 update_option( 'page_comments', false );
594 update_option( 'comments_per_page', 50 );
595 }
596 }
597
598 private function check_admin_notices_display(){
599 $settings = $this->get_settings_values();
600 if ( isset( $settings['disable_admin_notices'] ) && $settings['disable_admin_notices'] ) {
601 add_action('admin_print_scripts', array($this, 'disable_admin_notices') );
602 }
603 }
604
605 public function disable_admin_notices(){
606 global $wp_filter;
607 if (is_user_admin()) {
608 if (isset($wp_filter['user_admin_notices'])) {
609 unset($wp_filter['user_admin_notices']);
610 }
611 } elseif (isset($wp_filter['admin_notices'])) {
612 unset($wp_filter['admin_notices']);
613 }
614 if (isset($wp_filter['all_admin_notices'])) {
615 unset($wp_filter['all_admin_notices']);
616 }
617 }
618
619 private function check_pages_disable(){
620 $settings = $this->get_settings_values();
621 if ( isset( $settings['disable_author_pages'] ) && $settings['disable_author_pages'] ) {
622 add_action( 'template_redirect', array( $this, 'redirect_author_pages' ) );
623 }
624 }
625
626 public function redirect_author_pages(){
627 if( get_query_var( 'author' ) || get_query_var( 'author_name' ) ){
628 wp_safe_redirect( home_url(), 307 );
629 exit;
630 }
631 }
632
633 public function comment_admin_menu_remove(){
634 remove_menu_page('edit-comments.php');
635 }
636
637 private function check_dns_prefetch(){
638
639 $settings = $this->get_settings_values();
640
641 if( ! isset( $settings['dns_prefetch'] ) || ! $settings['dns_prefetch'] ) {
642 return;
643 }
644
645 $list = array();
646 $host_list = $settings['dns_prefetch_host_list'];
647 $host_list = '' !== $host_list ? explode("\n", $host_list) : array();
648
649 if( ! empty( $host_list ) ){
650 foreach ($host_list as $key => $val) {
651 $val = str_replace( 'http:', '', str_replace( 'https:', '', esc_url( $val ) ) );
652 if( $val && ! in_array($val, $list, true) ){
653 $list[] = $val;
654 }
655 }
656 }
657
658 if( ! empty( $list ) ){
659 foreach ($list as $key => $val) {
660 echo '<link rel="dns-prefetch" href="' . esc_url( $val ) . '" />' . "\n";
661 }
662 }
663 }
664
665 private function check_comments_disable() {
666 $settings = $this->get_settings_values();
667 $disable_all_comments = isset( $settings['disable_all_comments'] ) && 1 === $settings['disable_all_comments'];
668 if( $disable_all_comments ){
669 if( ! is_admin() ){
670 add_filter( 'feed_links_show_comments_feed', '__return_false' );
671 add_action( 'wp_footer', array( $this, 'hide_meta_widget_link' ), 100 );
672 add_action( 'template_redirect', array( $this, 'check_comments_template' ) );
673 }
674 else{
675 add_action('admin_menu', array( $this, 'comment_admin_menu_remove' ) );
676 }
677 }
678 }
679
680 public function check_comments_template() {
681
682 $settings = $this->get_settings_values();
683
684 $disable_settings = false;
685
686 if ( isset( $settings['disable_all_comments'] ) && 1 === $settings['disable_all_comments'] ) {
687 $disable_settings = true;
688 } elseif ( isset( $settings['disable_comments_on_certain_post_types'] ) && 1 === $settings['disable_comments_on_certain_post_types'] ) {
689
690 $current_post_type = get_post_type();
691
692 if ( $current_post_type &&
693 isset( $settings['disable_comments_on_post_types'] ) &&
694 is_array( $settings['disable_comments_on_post_types'] ) &&
695 isset( $settings['disable_comments_on_post_types'][ $current_post_type ] ) &&
696 1 === (int) $settings['disable_comments_on_post_types'][ $current_post_type ] ) {
697 $disable_settings = true;
698 }
699 }
700
701 if ( $disable_settings ) {
702
703 // Replace comments template with empty file.
704 add_action( 'comments_template', array( $this, 'empty_comments_template' ) );
705
706 // Remove comment-reply script for themes that include it indiscriminately.
707 wp_deregister_script( 'comment-reply' );
708 } else {
709 $this->check_comments_authors_links();
710 }
711 }
712
713 public function hide_meta_widget_link() {
714 if ( is_active_widget( false, false, 'meta', true ) && wp_script_is( 'jquery', 'enqueued' ) ) {
715 echo '<script> jQuery(function($){ $(".widget_meta a[href=\'' . esc_url( get_bloginfo( 'comments_rss2_url' ) ) . '\']").parent().remove(); }); </script>';
716 }
717 }
718
719 public function empty_comments_template() {
720 return dirname( dirname( __FILE__ ) ) . '/includes/empty-comments-template.php';
721 }
722
723 private function check_comments_authors_links() {
724 $settings = $this->get_settings_values();
725 if ( isset( $settings['remove_comments_links'] ) && 1 === $settings['remove_comments_links'] ) {
726 add_filter( 'comment_form_default_fields', array( $this, 'filter_comments_fields' ), 10 );
727 add_filter( 'get_comment_author_link', array( $this, 'disable_comments_authors_links' ), 10 );
728 add_filter( 'comment_text', array( $this, 'disable_comments_content_links' ), 10 );
729 }
730 }
731
732 public function filter_comments_fields( $fields ) {
733 if ( isset( $fields['url'] ) ) {
734 unset( $fields['url'] );
735 }
736 return $fields;
737 }
738
739 public function disable_comments_content_links( $content = '' ) {
740 // This is a 'comment_text' filter: it must RETURN the value. The old
741 // echo printed the stripped content and returned null, blanking comments.
742 return preg_replace( '/<a[^>]*href=[^>]*>|<\/[^a]*a[^>]*>/i', '', $content );
743 }
744
745 public function disable_comments_authors_links( $author_link ) {
746 return strip_tags( $author_link );
747 }
748
749 public function check_feeds_disable() {
750
751 $settings = $this->get_settings_values();
752
753 if ( isset( $settings['disable_rss'] ) && 1 === $settings['disable_rss'] ) {
754 add_action( 'wp_loaded', array( $this, 'remove_feed_links' ) );
755 add_action( 'template_redirect', array( $this, 'filter_feeds' ), 1 );
756 add_filter( 'bbp_request', array( $this, 'filter_bbp_feeds' ), 9 );
757 }
758 }
759
760 public function remove_feed_links() {
761 remove_action( 'wp_head', 'feed_links', 2 );
762 remove_action( 'wp_head', 'feed_links_extra', 3 );
763 }
764
765 public function filter_feeds() {
766
767 if ( ! is_feed() || is_404() ) {
768 return;
769 }
770
771 $settings = $this->get_settings_values();
772
773 if ( isset( $settings['not_disable_global_feeds'] ) && 1 === $settings['not_disable_global_feeds'] ) {
774 if ( ! ( is_singular() || is_archive() || is_date() || is_author() || is_category() || is_tag() || is_tax() || is_search() ) ) {
775 return;
776 }
777 }
778
779 $this->disabled_feed_behaviour();
780 }
781
782 public function disabled_feed_behaviour() {
783
784 global $wp_rewrite, $wp_query;
785
786 $settings = $this->get_settings_values();
787
788 if ( isset( $settings['disabled_feed_behaviour'] ) && '404_error' === $settings['disabled_feed_behaviour'] ) {
789 $wp_query->is_feed = false;
790 $wp_query->set_404();
791 status_header( 404 );
792 // Override the xml+rss header set by WP in send_headers
793 header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) );
794 } else {
795 if ( isset( $_GET['feed'] ) ) {
796 wp_safe_redirect( esc_url_raw( remove_query_arg( 'feed' ) ), 301 );
797 exit;
798 }
799
800 if ( 'old' !== get_query_var( 'feed' ) ) { // WP redirects these anyway, and removing the query var will confuse it thoroughly
801 set_query_var( 'feed', '' );
802 }
803
804 redirect_canonical(); // Let WP figure out the appropriate redirect URL.
805
806 // Still here? redirect_canonical failed to redirect, probably because of a filter. Try the hard way.
807 $struct = ( ! is_singular() && is_comment_feed() ) ? $wp_rewrite->get_comment_feed_permastruct() : $wp_rewrite->get_feed_permastruct();
808 $struct = preg_quote( $struct, '#' );
809 $struct = str_replace( '%feed%', '(\w+)?', $struct );
810 $struct = preg_replace( '#/+#', '/', $struct );
811 $host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '';
812 $uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
813 $requested_url = ( is_ssl() ? 'https://' : 'http://' ) . $host . $uri;
814 $new_url = preg_replace( '#' . $struct . '/?$#', '', $requested_url );
815
816 if ( $new_url !== $requested_url ) {
817 wp_safe_redirect( $new_url, 301 );
818 exit;
819 }
820 }
821 }
822
823 /**
824 * BBPress feed detection sourced from bbp_request_feed_trap() in BBPress Core.
825 *
826 * @param [type] $query_vars [description].
827 * @return [type] [description]
828 */
829 public function filter_bbp_feeds( $query_vars ) {
830 // Looking at a feed
831 if ( isset( $query_vars['feed'] ) ) {
832
833 // Forum/Topic/Reply Feed
834 if ( isset( $query_vars['post_type'] ) ) {
835
836 // Matched post type
837 $post_type = false;
838
839 // Post types to check
840 $post_types = array(
841 bbp_get_forum_post_type(),
842 bbp_get_topic_post_type(),
843 bbp_get_reply_post_type(),
844 );
845
846 // Cast query vars as array outside of foreach loop
847 $qv_array = (array) $query_vars['post_type'];
848
849 // Check if this query is for a bbPress post type
850 foreach ( $post_types as $bbp_pt ) {
851 if ( in_array( $bbp_pt, $qv_array, true ) ) {
852 $post_type = $bbp_pt;
853 break;
854 }
855 }
856
857 // Looking at a bbPress post type
858 if ( ! empty( $post_type ) ) {
859 $this->disabled_feed_behaviour();
860 }
861 }
862 }
863
864 // No feed so continue on
865 return $query_vars;
866 }
867
868 public function check_referral_spam_disable(){
869 $settings = $this->get_settings_values();
870 if ( isset( $settings['disable_referral_spam'] ) && 1 === $settings['disable_referral_spam'] ) {
871
872 add_filter('request', array($this, 'filter_referral_spam_requests'), 0);
873 }
874 }
875
876 public function filter_referral_spam_requests($request){
877 global $wp_query;
878
879 $referrer = wp_get_referer() !== false ? wp_get_referer() : ( isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '' );
880
881 if ( empty( $referrer ) ) {
882 return $request;
883 }
884
885 $referrer = wp_parse_url($referrer, PHP_URL_HOST);
886
887 $referrers_blacklist = $this->referrals_blacklist();
888
889 if( empty( $referrers_blacklist ) ){
890 return $request;
891 }
892
893 $is_blacklisted = false;
894
895 foreach ($referrers_blacklist as $blist_ref) {
896 if (false !== stripos($referrer, $blist_ref)) {
897 $is_blacklisted = true;
898 break;
899 }
900 }
901
902 if( $is_blacklisted ){
903 status_header(404);
904 $wp_query->set_404();
905 get_template_part('404');
906 exit();
907 }
908
909 return $request;
910 }
911
912 private function referrals_blacklist(){
913
914 $ret = get_transient( self::OPTION_KEY . '_referalls_spam_blacklist' );
915
916 if( false === $ret ){
917
918 $response = wp_remote_get( 'https://wielo.co/referrer-spam.php', array( 'timeout' => 5 ) );
919
920 if ($response instanceof WP_Error) {
921 error_log('Unable to get referrals spam blacklist: ' . $response->get_error_message());
922 return;
923 }
924
925 $ret = $response['body'];
926
927 if (empty($ret)) {
928 error_log('Invalid referrals spam blacklist response');
929 return;
930 }
931
932 $ret = json_decode($ret, true);
933
934 if (null === $ret) {
935 error_log('Invalid referrals spam blacklist data');
936 return;
937 }
938
939 set_transient( self::OPTION_KEY . '_referalls_spam_blacklist', $ret, DAY_IN_SECONDS ); // Refresh daily.
940 }
941
942 return $ret;
943 }
944
945 public static function is_woocommerce_enabled(){
946 if( null === WpPerformance::$enabled_woocommerce ){
947 WpPerformance::$enabled_woocommerce = in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) );
948 }
949 return WpPerformance::$enabled_woocommerce;
950 }
951
952 /**
953 * Whether to show the SEO settings tab.
954 *
955 * True only when a supported SEO plugin is active (currently Yoast SEO);
956 * the SEO options are no-ops otherwise. Kept abstracted so other SEO
957 * plugins can be added here later. Props @JeroenSormani.
958 */
959 public static function should_show_seo_tab(){
960 return defined( 'WPSEO_VERSION' );
961 }
962 }
963